Tutoriales de VPS
Instalar Directus, el CMS headless, en un VPS (2026): Docker Compose, PostgreSQL, Redis y HTTPS automático con Caddy
Directus es una buena opción para desarrolladores que quieren autohospedar un backend de contenido, un sistema de gestión interno o un CMS headless. Este artículo abarca la elección de la configuración del VPS, Docker Compose, PostgreSQL, Redis, HTTPS automático con Caddy, copias de seguridad y comprobaciones de seguridad para ayudarte a desplegar Directus como un entorno de producción mantenible a largo plazo.
Instalar Directus, el CMS headless, en un VPS (2026): Docker Compose, PostgreSQL, Redis y HTTPS automático con Caddy
Si ya no quieres usar WordPress para todos tus backends de contenido y sientes que los costes y las limitaciones de Contentful, Strapi Cloud y diversos CMS SaaS no son del todo controlables, Directus autoalojado es una opción muy adecuada para usuarios de VPS.
Directus no se plantea como "otro sistema de blogs", sino como una forma de convertir bases de datos como PostgreSQL y MySQL en un panel de administración visual, una API REST, una API GraphQL y un sistema de permisos. Puedes usarlo para gestionar artículos, productos, directorios de herramientas, datos internos y formularios operativos, o tratarlo como un Backend-as-a-Service ligero.
Este artículo se centra en una solución mantenible en producción: Directus + PostgreSQL + Redis + Caddy + Docker Compose. Es más adecuada para el uso a largo plazo que "ejecutar solo un contenedor SQLite" y requiere menos esfuerzo que escribir a mano Nginx + Certbot, porque Caddy puede solicitar y renovar certificados HTTPS automáticamente.
Es adecuado para los siguientes tipos de usuarios:
- Quienes quieren autohospedar un CMS headless en un VPS en lugar de pagar una suscripción SaaS a largo plazo.
- Quienes quieren ofrecer una API de contenido para Next.js, Nuxt, Astro, Hugo o miniprogramas.
- Quienes quieren montar un panel de administración interno, un directorio de herramientas, una biblioteca de recursos o una base de datos de clientes.
- Quienes ya saben lo básico de SSH y Docker, pero no quieren mantener un Kubernetes complejo.
- Quienes quieren que los datos estén en su propio VPS y base de datos, para no quedar atados a una plataforma al migrar.
Si solo quieres montar un blog, la guía para montar un blog personal en un VPS de nuestro sitio es más directa. Si estás trabajando en flujos de trabajo automatizados, puedes consultar Montar flujos de automatización con n8n en un VPS. Directus encaja mejor en escenarios con "estructuras de contenido complejas, necesidad de permisos y necesidad de API".
Directus en sí no es pesado; lo que realmente consume recursos es la base de datos, la subida de imágenes, el volumen de solicitudes a la API y las extensiones que escribas.
| Escenario | Configuración recomendada | Descripción |
|---|---|---|
| Backend de contenido personal, proyectos de prueba | 1 núcleo, 2 GB de RAM | Puede funcionar, pero no cargues demasiadas extensiones |
| CMS para equipos pequeños, directorio de herramientas | 2 núcleos, 4 GB de RAM | Más estable, nivel de partida recomendado |
| API de contenido para varios sitios, sistemas internos | 4 núcleos, 8 GB de RAM | Más margen para base de datos, caché y copias de seguridad |
| Gran volumen de subidas de imágenes/archivos | Añadir almacenamiento de objetos aparte | No acumules archivos grandes en el disco del sistema |
Se recomienda empezar con al menos 40 GB de disco. Los datos principales de Directus están en la base de datos, los archivos subidos están en el directorio uploads y las extensiones en el directorio extensions. Al hacer copias de seguridad más adelante, hay que cubrir estas tres partes.
Necesitas:
- Un VPS con Ubuntu 22.04 / 24.04.
- Un dominio, por ejemplo
cms.example.com. - Un registro DNS A que apunte a la IP pública del VPS.
- Los puertos 22, 80 y 443 abiertos.
- Docker y el plugin Docker Compose.
Para instalar Docker puedes consultar los artículos sobre Docker de nuestro sitio; aquí tienes una comprobación mínima:
docker --version
docker compose version
Si el comando no existe, instala primero Docker Engine y el plugin Compose y luego continúa.
sudo mkdir -p /opt/directus/{uploads,extensions,database,caddy}
sudo chown -R $USER:$USER /opt/directus
cd /opt/directus
Se recomienda no colocar Directus bajo /root. Así las copias de seguridad, las migraciones y la gestión con systemd serán más claras.
Directus necesita un SECRET, y la base de datos también necesita una contraseña segura. No uses valores predeterminados como directus/directus en producción.
openssl rand -hex 32
openssl rand -base64 32
Guarda los resultados generados en un gestor de contraseñas. Los necesitarás al escribir .env más adelante.
Crea .env:
nano .env
Ejemplo:
DIRECTUS_DOMAIN=cms.example.com
DIRECTUS_PUBLIC_URL=https://cms.example.com
POSTGRES_DB=directus
POSTGRES_USER=directus
POSTGRES_PASSWORD=replace-with-strong-db-password
DIRECTUS_SECRET=replace-with-random-secret
[email protected]
DIRECTUS_ADMIN_PASSWORD=replace-with-strong-admin-password
Notas:
DIRECTUS_DOMAINno debe incluirhttps://.DIRECTUS_PUBLIC_URLdebe coincidir con la dirección de acceso final.- La contraseña del administrador se puede cambiar en el panel tras el primer arranque, pero el valor inicial no debe ser demasiado débil.
Crea docker-compose.yml:
nano docker-compose.yml
Rellena:
services:
database:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- ./database:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
cache:
image: redis:7-alpine
restart: unless-stopped
command: redis-server --appendonly yes
volumes:
- ./redis:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
directus:
image: directus/directus:11.17.0
restart: unless-stopped
depends_on:
database:
condition: service_healthy
cache:
condition: service_healthy
environment:
SECRET: ${DIRECTUS_SECRET}
PUBLIC_URL: ${DIRECTUS_PUBLIC_URL}
DB_CLIENT: pg
DB_HOST: database
DB_PORT: 5432
DB_DATABASE: ${POSTGRES_DB}
DB_USER: ${POSTGRES_USER}
DB_PASSWORD: ${POSTGRES_PASSWORD}
CACHE_ENABLED: "true"
CACHE_STORE: redis
CACHE_AUTO_PURGE: "true"
REDIS: redis://cache:6379
ADMIN_EMAIL: ${DIRECTUS_ADMIN_EMAIL}
ADMIN_PASSWORD: ${DIRECTUS_ADMIN_PASSWORD}
WEBSOCKETS_ENABLED: "true"
IP_TRUST_PROXY: "true"
volumes:
- ./uploads:/directus/uploads
- ./extensions:/directus/extensions
expose:
- "8055"
caddy:
image: caddy:2-alpine
restart: unless-stopped
depends_on:
- directus
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
volumes:
caddy_data:
caddy_config:
Aquí hay varios puntos clave:
- Directus no mapea
8055:8055directamente a la red pública; solo se expone a Caddy dentro de la red de Docker. - Los datos de PostgreSQL se montan en
./databasey los archivos subidos se montan en./uploads. - Caddy se encarga de los puertos públicos 80/443 y de HTTPS.
directus/directus:11.17.0es una versión de ejemplo; en producción real se recomienda fijar una versión que hayas probado y no usarlatesta largo plazo.
Crea el Caddyfile:
nano caddy/Caddyfile
Escribe:
{$DIRECTUS_DOMAIN} {
encode zstd gzip
reverse_proxy directus:8055
}
La lógica de Caddy es sencilla: si el dominio resuelve a este VPS y los puertos 80/443 son accesibles, Caddy solicitará y renovará los certificados automáticamente. En comparación con Nginx + Certbot, la configuración es más corta y es más difícil olvidar la renovación.
Si tu DNS aún no ha surtido efecto, no inicies Caddy todavía, o la solicitud del certificado podría fallar. Puedes usar:
dig +short cms.example.com
Confirma que devuelve la IP pública del VPS.
cd /opt/directus
docker compose pull
docker compose up -d
Ver el estado:
docker compose ps
docker compose logs -f directus
Accede a:
https://cms.example.com
Inicia sesión con el correo y la contraseña del administrador de .env.
La puesta en marcha no termina al ver la página de inicio de sesión. Como mínimo, comprueba esto:
-
https://cms.example.com/server/pingdevuelve una respuesta normal. - HTTP redirige automáticamente a HTTPS.
- Tras iniciar sesión en el panel, puedes crear una Collection de prueba.
- Puedes crear, leer y editar un registro de prueba.
- Puedes subir una imagen de prueba y sigue existiendo tras reiniciar.
- Directus se recupera tras
docker compose restart. -
docker compose logs directusno muestra errores repetidos de conexión a la base de datos.
Si la página devuelve 502, revisa primero:
docker compose ps
docker compose logs caddy
docker compose logs directus
Las causas habituales son que el DNS no apunta al VPS, que 80/443 no están abiertos, que el contenedor de Directus no se ha iniciado, que PUBLIC_URL está mal escrito o que el dominio del Caddyfile está mal escrito.
Un entorno de producción de Directus debe respaldar al menos tres tipos de datos:
- La base de datos PostgreSQL.
- El directorio de archivos
uploads. - El directorio de extensiones
extensionsy la configuracióndocker-compose.yml/.env.
Ejemplo de copia de seguridad de la base de datos:
cd /opt/directus
docker compose exec -T database pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" > directus-$(date +%F).sql
Pero este comando puede no leer .env al usar directamente las variables de entorno del host. Una forma más fiable es escribir un script de copia de seguridad que lea explícitamente .env o que especifique las variables dentro del contenedor. En nuestro sitio ya hay simulacros de copia de seguridad y restauración en VPS; se recomienda incluir Directus en el mismo simulacro de restauración, en lugar de limitarse a hacer archivos comprimidos que "parecen tener copia de seguridad".
Directus es un sistema de backend, así que no lo dejes expuesto:
- La contraseña del administrador debe ser suficientemente segura y hay que activar la jerarquía de permisos de cuentas dentro del equipo.
- No expongas PostgreSQL ni Redis a la red pública.
- No abras el puerto 8055 de Directus directamente a todo internet.
- Si pones Cloudflare delante de Caddy, confirma el modo SSL y la política de acceso al origen real.
- Actualiza periódicamente la imagen de Directus, pero haz copia de seguridad de la base de datos y de los archivos subidos antes de actualizar.
- Si solo lo usa el equipo interno, puedes considerar añadir Cloudflare Access o Tailscale.
Si no tienes claro cómo gestionar el acceso remoto a la base de datos, consulta primero No expongas las bases de datos del VPS directamente a la red pública. Si te preocupa la exposición de la IP de origen, puedes consultar Ocultar la IP de origen con Cloudflare Tunnel.
Depende del escenario.
| Escenario | Más adecuado |
|---|---|
| Blogs tradicionales, ecosistema de plugins, mercado de temas | WordPress |
| Sitios de contenido con frontend y backend separados | Directus |
| Directorios de herramientas, bibliotecas de recursos, backends internos | Directus |
| Necesidad de permisos y API complejos | Directus |
| No quieres escribir frontend, solo publicar artículos rápido | WordPress |
| El contenido debe sincronizarse con varios frontends | Directus |
Las ventajas de Directus son la libertad de estructura, las API directas y un modelo de permisos claro; la desventaja es que normalmente aún necesitas un sitio frontend, como Next.js, Nuxt, Astro o un generador de sitios estáticos. No es una herramienta tradicional de creación de sitios que "tras instalarla ya tiene un mercado de temas completo".
1. ¿Se puede usar SQLite?
Para pruebas sí; para producción no se recomienda. Los tutoriales oficiales incluyen escenarios con SQLite, pero para producción a largo plazo se recomienda más PostgreSQL o MySQL, sobre todo con backends multiusuario, escrituras frecuentes y muchas funciones de extensión.
2. ¿Caddy o Nginx?
Si ya estás familiarizado con Nginx, puedes seguir usando Nginx. Para proyectos nuevos se recomienda más Caddy, por el HTTPS automático, la configuración corta y la renovación sin complicaciones. Este artículo elige Caddy para reducir el coste de mantenimiento.
3. ¿Cuánta memoria necesita el VPS?
Para uso personal, 2 GB pueden servir de partida; para equipos pequeños se recomiendan 4 GB. Cuando Directus, PostgreSQL, Redis y Caddy se ejecutan en la misma máquina, una máquina de 1 GB estará bastante justa.
4. ¿Qué hago si las imágenes subidas aumentan cada vez más?
A medio y largo plazo se recomienda conectar almacenamiento de objetos compatible con S3, o al menos hacer una copia de seguridad separada de uploads. No esperes a que el disco del sistema se llene para migrar.
5. ¿Actualizar Directus puede dañar los datos?
Cualquier actualización de CMS tiene riesgos. No hagas directamente latest para traer la nueva versión; primero revisa el changelog, valida en un entorno de prueba y luego actualiza tras hacer copia de seguridad de la base de datos de producción y de los archivos subidos.
- El registro A del dominio apunta al VPS.
- El VPS tiene abiertos 80/443 y 8055 no está abierto a la red pública.
-
SECRET, la contraseña de la base de datos y la contraseña del administrador en.envson suficientemente seguras. - Docker Compose fija la versión de Directus.
- PostgreSQL, uploads y extensions tienen estrategia de copia de seguridad.
- El HTTPS automático de Caddy funciona correctamente.
- El inicio de sesión, la creación de datos, la subida de archivos y la recuperación tras reiniciar se han probado correctamente.
Directus encaja muy bien en usuarios de VPS que piensan: "quiero tener el contenido y los datos en mis propias manos, pero no quiero escribir un backend desde cero". Combinando Directus, PostgreSQL, Redis y Caddy con Docker Compose, puedes obtener un entorno de CMS headless mantenible en un VPS normal.
Lo que realmente importa no es "si puede arrancar", sino: si la base de datos es persistente, si los archivos subidos están respaldados, si HTTPS se renueva automáticamente, si el puerto del backend no está expuesto y si puedes revertir antes de actualizar. Si haces bien estas cosas, Directus puede pasar de ser un contenedor de pruebas a un backend de contenido realmente utilizable a largo plazo.