Autoalojar Umami para las estadísticas de tu sitio
Sigue esto en tu propio servidor. Empieza gratis, sin tarjeta
Quieres saber cuántas personas visitaron tu sitio hoy y de dónde llegaron, sin enviar cada vista de página a una empresa de publicidad y sin un aviso de cookies. Umami hace justo eso: un panel de estadísticas de código abierto que corre en un solo contenedor con una sola base de datos Postgres. Esta guía te lleva de un servidor vacío a Umami en tu propio dominio con HTTPS, midiendo tu primer sitio, con un respaldo que sabes restaurar y un plan para las actualizaciones. La última parte muestra la versión de un clic en Railyard.
Esta guía usa Umami 3.4.1, la versión actual, con Postgres 16. Umami 3 solo es compatible con Postgres (versión 12.14 o posterior), así que aquí no hay opción de MySQL.
Lo que necesitas
- Un servidor. Umami y Postgres son livianos, así que un servidor pequeño alcanza. Un Hetzner CX23 (2 vCPU, 4 GB de RAM, 40 GB NVMe) cuesta 5,99 €/mes sin IVA y deja espacio para otras apps. Usa Ubuntu 24.04 u otra imagen reciente basada en Debian.
- Un dominio o subdominio que puedas apuntar al servidor. Esta guía usa
analytics.example.com. - Acceso SSH como root o con un usuario que tenga
sudo.
Paso 1: Apunta el DNS al servidor y actualízalo
Crea el servidor, anota su dirección IPv4 pública y agrega en tu proveedor de DNS un registro A para analytics.example.com que apunte a esa dirección. Hazlo primero: Caddy solo puede obtener un certificado cuando el nombre ya resuelve a tu servidor, y el DNS puede tardar unos minutos en actualizarse.
Luego entra y actualiza el sistema:
ssh root@203.0.113.10
apt update && apt upgrade -y
Revisa el registro desde tu computadora:
dig +short analytics.example.com
Deberías ver la IP de tu servidor. Si todavía no aparece nada, sigue adelante y vuelve a revisar antes del paso 5.
Paso 2: Instala Docker
Umami, Postgres y Caddy corren en contenedores, así que Docker Engine con el plugin de Compose es lo único que hay que instalar. El script de Docker configura su repositorio oficial y sus paquetes:
curl -fsSL https://get.docker.com | sh
systemctl enable --now docker
docker --version
docker compose version
Deberías ver una línea de versión para Docker y otra para Docker Compose.
Paso 3: Crea los secretos
Crea una carpeta para el stack y genera tres valores en un archivo .env:
mkdir -p /opt/umami/backups
cd /opt/umami
echo "DB_PASSWORD=$(openssl rand -hex 24)" >> .env
echo "APP_SECRET=$(openssl rand -hex 32)" >> .env
echo "TWO_FACTOR_ENCRYPTION_KEY=$(openssl rand -hex 32)" >> .env
chmod 600 .env
Para qué sirve cada uno, según la documentación de Umami:
DATABASE_URLes la única variable estrictamente obligatoria. La armarás a partir deDB_PASSWORDen el archivo de Compose.APP_SECRETprotege los tokens de autenticación. Cada instalación debería tener el suyo.TWO_FACTOR_ENCRYPTION_KEYes una cadena hexadecimal de 64 caracteres que cifra los secretos de la autenticación de dos factores.openssl rand -hex 32produce justo eso. El archivo de Compose de Umami la define, y la necesitas si piensas activar el inicio de sesión de dos factores.
Revisa el archivo:
cat /opt/umami/.env
Deberías ver tres líneas, cada una con un valor aleatorio largo.
Paso 4: Escribe el archivo de Compose y el Caddyfile
Guarda esto como /opt/umami/compose.yaml. Sigue la estructura del docker-compose.yml de Umami, con versiones fijas en lugar de latest y Caddy adelante:
services:
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
- caddy-config:/config
depends_on:
- umami
umami:
image: ghcr.io/umami-software/umami:3.4.1
restart: unless-stopped
init: true
environment:
DATABASE_URL: postgresql://umami:${DB_PASSWORD}@db:5432/umami
APP_SECRET: ${APP_SECRET}
TWO_FACTOR_ENCRYPTION_KEY: ${TWO_FACTOR_ENCRYPTION_KEY}
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:3000/api/heartbeat"]
interval: 5s
timeout: 5s
retries: 5
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: umami
POSTGRES_USER: umami
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- umami-db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U umami -d umami"]
interval: 5s
timeout: 5s
retries: 5
volumes:
umami-db-data:
caddy-data:
caddy-config:
Algunas cosas que conviene saber:
- Solo Caddy publica puertos. Umami escucha en el 3000 y Postgres en el 5432 dentro de la red de Compose, así que ninguno es accesible desde internet.
- Compose lee
${DB_PASSWORD}y los demás valores del archivo.enven la misma carpeta. - Umami espera a que Postgres esté saludable antes de arrancar, y crea sus tablas en el primer inicio.
- El volumen
caddy-dataguarda tus certificados, así que un reinicio no pide certificados nuevos.
Ahora guarda esto como /opt/umami/Caddyfile, con tu propio dominio:
analytics.example.com {
encode zstd gzip
reverse_proxy umami:3000
}
Caddy toma el dominio de la dirección del sitio, obtiene un certificado de Let’s Encrypt, redirige HTTP a HTTPS y pasa las solicitudes al contenedor umami. Revisa ambos archivos:
cd /opt/umami
docker compose config --quiet && echo "compose ok"
docker compose run --rm --no-deps caddy caddy validate --config /etc/caddy/Caddyfile
Deberías ver compose ok y luego Valid configuration al final de la salida de Caddy.
Paso 5: Arranca el stack
docker compose up -d
docker compose ps
Después de veinte o treinta segundos deberías ver db y umami marcados como (healthy), y caddy como Up. Revisa la app desde su contenedor:
docker compose exec umami curl -s http://localhost:3000/api/heartbeat
Deberías ver {"ok":true}. Luego observa cómo Caddy obtiene el certificado:
docker compose logs -f caddy
Deberías ver una línea que dice que se obtuvo el certificado para analytics.example.com. Presiona Ctrl+C y abre https://analytics.example.com en tu navegador. Deberías ver la página de inicio de sesión de Umami con un certificado válido.
Paso 6: Inicia sesión y cambia la contraseña por defecto
Cada instalación nueva de Umami crea la misma cuenta: usuario admin, contraseña umami. Entra con ella y cambia la contraseña de inmediato desde la configuración de tu perfil. Mientras no lo hagas, cualquiera que encuentre tu página de inicio de sesión puede entrar como administrador, así que no dejes una instalación nueva corriendo toda la noche con la contraseña por defecto.
Luego agrega tu sitio. Haz clic en Websites en la barra lateral, luego en Add website, escribe un nombre y el dominio de tu sitio, y guarda. Haz clic en Edit en el sitio nuevo y copia el código de la sección Tracking code en el <head> de tu sitio.
Carga tu sitio en otra pestaña. Deberías ver la visita en el panel de Umami en pocos segundos. Si no aparece, prueba con un navegador sin bloqueador de anuncios: la documentación de Umami advierte que los bloqueadores pueden impedir que el script de seguimiento se cargue.
Paso 7: Respalda la base de datos
Todo lo importante está en Postgres: tu cuenta, tus sitios y cada vista de página. Guarda esto como /opt/umami/backup.sh:
#!/usr/bin/env bash
set -euo pipefail
cd /opt/umami
docker compose exec -T db pg_dump -U umami umami | gzip > "backups/umami-$(date +%F).sql.gz"
find backups -name 'umami-*.sql.gz' -mtime +14 -delete
Hazlo ejecutable, córrelo una vez y prográmalo todos los días a las 03:00 con crontab -e:
chmod +x /opt/umami/backup.sh
/opt/umami/backup.sh
ls -lh /opt/umami/backups
0 3 * * * /opt/umami/backup.sh
Deberías ver un archivo .sql.gz de unos pocos kilobytes en una instalación nueva, que crece a medida que llegan datos. El script conserva catorce días. Copia también los archivos fuera del servidor (almacenamiento de objetos, u otra máquina con rsync), porque un respaldo en el mismo disco no sobrevive si pierdes el servidor.
Un respaldo solo cuenta cuando ya lo restauraste. Para restaurar en una instalación nueva, arranca solo la base de datos, carga el respaldo y luego arranca Umami:
docker compose up -d --wait db
gunzip -c backups/umami-2026-05-19.sql.gz | docker compose exec -T db psql -q -U umami umami
docker compose up -d
Cargar el respaldo en una base vacía antes de que arranque Umami evita conflictos con las tablas que Umami crea en su primer inicio. Deberías ver que Umami registra No pending migrations to apply, y recuperar tu cuenta y tus datos.
Paso 8: Actualiza
Umami aplica sus migraciones de base de datos al arrancar, así que actualizar es cambiar la etiqueta de la imagen y reiniciar. Lee primero las notas de la versión en GitHub, haz un respaldo, cambia la etiqueta en compose.yaml (por ejemplo de 3.4.1 a la siguiente versión) y corre:
/opt/umami/backup.sh
docker compose pull umami
docker compose up -d umami
docker compose logs -f umami
Deberías ver que se aplican las migraciones y luego que Next.js avisa que está listo. Si algo sale mal, vuelve a la etiqueta anterior y restaura el respaldo del paso 7. Mantén Caddy y Postgres al día de la misma forma: docker compose pull y docker compose up -d para Caddy, mientras que un cambio de versión mayor de Postgres (de 16 a 17) requiere exportar y restaurar, no solo una etiqueta nueva.
El atajo: hazlo con Railyard
Los pasos 2 a 5 son lo que la plantilla de Umami de Railyard hace por ti: despliega Umami en Railyard. Elige un servidor, y Railyard construye Umami, crea una base de datos Postgres para él, conecta ambos sin que tengas que configurar nada a mano y genera APP_SECRET. La app recibe una dirección HTTPS de inmediato, y puedes agregar tu propio dominio desde su pestaña Domains con los registros DNS que te muestra (Dominios y HTTPS).
El paso 6 sigue aplicando: entra con admin / umami y cambia la contraseña de inmediato. Los respaldos del paso 7 se convierten en respaldos programados de Postgres con restauración en un clic, descritos en Bases de datos y respaldos.
La plantilla corre en un servidor de tu propia cuenta en la nube o en uno que ya tienes, así que el costo sigue siendo el del servidor. El plan Free de Railyard incluye un servidor más un servidor de bases de datos y tres apps, sin tarjeta. Pro cuesta US$19/mes y Team US$49/mes, por equipo.
Solución de problemas
Caddy no obtiene el certificado. Casi siempre es el DNS. Corre dig +short analytics.example.com y confirma que devuelve la IP de tu servidor. Asegúrate también de que los puertos 80 y 443 estén abiertos en el firewall de tu proveedor, porque Let’s Encrypt se conecta al servidor para validarlo. Caddy reintenta solo, así que cuando el DNS esté bien, sigue docker compose logs -f caddy.
address already in use en el puerto 80 o 443. Otro programa ya escucha ahí, a menudo un Nginx o un Apache que venía con la imagen. Encuéntralo con ss -tlnp | grep -E ':(80|443)\s', detenlo y desactívalo, y vuelve a correr docker compose up -d.
Umami se reinicia una y otra vez. Corre docker compose logs umami. La causa habitual es un DATABASE_URL que no coincide con la base de datos. Si cambiaste DB_PASSWORD después del primer arranque, Postgres sigue con la anterior: la contraseña solo se aplica cuando se crea el volumen. Vuelve al valor anterior o cámbiala dentro de Postgres con ALTER USER.
El panel no muestra visitas. Revisa que el código de seguimiento esté en el <head> de la página que cargaste, que el dominio del sitio en Umami coincida con el tuyo, y prueba un navegador sin bloqueador de anuncios. La pestaña de red de tu navegador debería mostrar script.js cargando desde tu dominio de Umami.
El servidor se queda sin memoria. Umami y Postgres son pequeños, pero en un servidor compartido con otras apps el mecanismo del kernel que mata procesos por falta de memoria puede detener un contenedor. Revisa con dmesg | grep -i "out of memory" y docker stats, y luego mueve algo a otro servidor o agranda este.
Preguntas frecuentes
¿Umami usa cookies? Umami está hecho para recopilar estadísticas sin cookies, por eso muchos sitios lo usan sin aviso de consentimiento. Si necesitas uno depende de las reglas que te aplican, así que revísalas.
¿Una instalación de Umami puede medir varios sitios? Sí. Agrega cada uno en Websites y cada uno tiene su propio código de seguimiento y su propio panel.
¿Puedo correrlo sin Docker? Sí. La documentación de Umami describe una instalación desde el código fuente con Node.js 18.18 o posterior, pnpm y una base Postgres, bajo un gestor de procesos como PM2. Docker es más fácil de actualizar, por eso esta guía lo usa.
¿Cómo paso de Google Analytics a Umami? Umami empieza a contar en cuanto el código de seguimiento está en tu sitio. Deja ambos scripts en tus páginas un tiempo si quieres comparar los números antes de quitar el de Google.
Umami es de las apps autoalojadas más fáciles de mantener bien: un contenedor, una base de datos y una configuración de proxy pequeña. Sea cual sea el camino que elijas, los hábitos que importan son los mismos: cambiar la contraseña por defecto el primer día y restaurar un respaldo al menos una vez para saber que funciona.
Por qué eligen Railyard para esto
- Tu propia cuenta en la nube. Despliega en DigitalOcean, Hetzner, Vultr, AWS, OVHcloud, o cualquier servidor Linux por SSH, facturado directamente por tu proveedor, sin márgenes adicionales.
- Un precio fijo por equipo. El plan Free es gratis para siempre: un servidor más un servidor de base de datos, tres apps, sin tarjeta. Pro cuesta $19 al mes por hasta cinco servidores y apps ilimitadas. Team cuesta $49 al mes con servidores ilimitados. Sin cargos por app, por despliegue, por asiento ni por gigabyte.
- Plantillas de un clic. Despliega apps de código abierto, como bases de datos, analítica y herramientas de desarrollo, en tu propio servidor con un clic.
- Bases de datos administradas. Postgres, MySQL y Redis, con copias de seguridad programadas y verificadas por restauración, y recuperación a un punto en el tiempo.
- Despliegue con git push. Despliega desde GitHub, GitLab o la CLI, con HTTPS automático y lanzamientos sin tiempo de inactividad.