Tutorial

Stack homelab VPS 2026: cinco servicios self-hosted

Despliegue10 min de lectura8 pasos

Alojar una aplicación en un VPS se ha convertido en algo rutinario para los desarrolladores. Alojar cinco aplicaciones a la vez — un gestor de archivos, una bóveda de contraseñas, un servidor multimedia, una biblioteca de fotos y un archivador de documentos — en el mismo VPS, con un único archivo de composición y un único certificado SSL, es otra historia. Esta guía presenta la arquitectura completa del stack homelab 2026: cómo dimensionar el servidor, cómo estructurar el `docker-compose.yml`, cómo configurar Caddy para enrutar cada subdominio y cómo evitar los errores más habituales en el arranque.

Contenido· Por qué consolidar cinco servicios en un solo VPS1/8
  1. 01Por qué consolidar cinco servicios en un solo VPS
  2. 02Lo que este stack aporta en la práctica
  3. 03Requisitos previos: dimensionamiento y puertos
  4. 04Despliegue paso a paso
  5. 05Caddy, Nginx Proxy Manager o Traefik: qué reverse proxy para este stack
  6. 06Hardening mínimo antes de la exposición pública
  7. 07Resolución de problemas: errores comunes en el arranque
  8. 08Para ir más lejos

Por qué consolidar cinco servicios en un solo VPS

El enfoque «una app, un VPS» tiene su lógica: aislamiento total, despliegue independiente, sin riesgo de contención. También tiene un coste real — cinco servidores, cinco direcciones IP, cinco renovaciones, cinco configuraciones de nginx, cinco certificados TLS que vigilar. Para un stack personal o un equipo pequeño, ese coste solo se justifica si las aplicaciones tienen picos de carga muy distintos o requisitos de seguridad incompatibles.

Nextcloud, Vaultwarden, Jellyfin, Immich y Paperless-ngx comparten la característica de ser aplicaciones de tráfico moderado, utilizadas principalmente por uno o pocos usuarios. Vaultwarden consume menos de 50 MB de RAM en modo de espera. Paperless-ngx ronda los 200 MB. Immich, el más exigente en reposo fuera del transcodificado, se mantiene por debajo de 400 MB en inactividad. Estas mediciones están documentadas en los proyectos GitHub respectivos y en los comentarios de la comunidad self-hosting.

La consolidación en un VPS no elimina los riesgos — los concentra. La contrapartida es un único punto de entrada que endurecer, un único certificado que gestionar y un manifiesto Docker Compose versionado que constituye por sí solo la documentación completa de la infraestructura.

Lo que este stack aporta en la práctica

  • Soberanía sobre los datos — archivos, contraseñas, fotos y documentos permanecen en tu servidor, bajo tu clave de cifrado, sin dependencia de ningún proveedor cloud de terceros.
  • Un único certificado TLS wildcard — Caddy solicita y renueva automáticamente *.votre-domaine.com mediante el reto DNS-01, cubriendo todos los subdominios del stack con una sola configuración.
  • Red Docker interna aislada — ninguna aplicación expone un puerto público directamente; todo el tráfico entrante pasa por Caddy en los puertos 80 y 443, y los servicios se comunican a través de una red bridge privada.
  • Volúmenes nombrados y restauración predecible — cada servicio declara sus datos en un volumen Docker nombrado (nextcloud_data, vaultwarden_data…), lo que hace que las copias de seguridad y las migraciones sean reproducibles con un solo comando rsync.
  • Actualizaciones independientes — descargar una nueva imagen de Immich no reinicia ni Jellyfin ni Paperless-ngx; docker compose up -d --no-deps immich solo toca el servicio en cuestión.
  • Coste fijo y predecible — un VPS de recursos fijos elimina las sorpresas de facturación que generan los servicios en la nube cuando el transcodificado de Jellyfin se dispara o las tareas OCR de Paperless-ngx se acumulan.
  • Posible interconexión de servicios — Nextcloud puede usar Redis y MariaDB ya presentes en el Compose; Immich comparte la misma red que el reverse proxy sin configuración adicional.

Requisitos previos: dimensionamiento y puertos

El suelo realista para este stack en uso habitual es 4 vCPU / 8 GB de RAM / 100 GB de almacenamiento SSD. Este dimensionamiento cubre las huellas en reposo de cada servicio y deja margen para el transcodificado bajo demanda de Jellyfin y las tareas OCR de Paperless-ngx, que son los dos picos de carga más relevantes del stack.

Huellas medidas en modo de espera (sin sesión activa, sin tarea en segundo plano):

- Nextcloud (PHP-FPM + cron): ~300 MB según la carga de sincronización.
- Vaultwarden: < 50 MB, imagen Rust muy compacta.
- Jellyfin: ~250 MB sin transcodificado activo. En transcodificado software (x264, 1080p): entre 1 y 2 vCPU en punta.
- Immich (server + microservices): ~350-400 MB en reposo. Las tareas de aprendizaje automático (detección de caras, clasificación) pueden consumir hasta 2 GB de RAM según el volumen.
- Paperless-ngx (web + worker): ~200 MB. El OCR de Tesseract sobre un PDF de 50 páginas puede saturar temporalmente un vCPU.
- Caddy: < 30 MB.
- Bases de datos (MariaDB para Nextcloud + Paperless, Redis): ~200 MB combinados.

Total estimado en reposo: ~1,6 GB de los 8 GB disponibles. El margen absorbe los picos y permite añadir otro servicio sin redimensionar.

Puertos que abrir en el cortafuegos: 80/tcp y 443/tcp únicamente. El resto permanece cerrado — los servicios internos no se exponen directamente.

Despliegue paso a paso

  1. Preparar el VPS

    Conéctate por SSH a tu VPS y actualiza el sistema: apt update && apt upgrade -y. Instala Docker y el plugin Compose: curl -fsSL https://get.docker.com | sh. Verifica la instalación: docker compose version. Crea un usuario no root dedicado y agrégalo al grupo docker: adduser deploy && usermod -aG docker deploy. Activa UFW con las reglas mínimas: ufw allow 22/tcp && ufw allow 80/tcp && ufw allow 443/tcp && ufw enable.

  2. Configurar el DNS

    En tu zona DNS, crea un registro A para el dominio raíz apuntando a la IP de tu VPS, luego subdominios CNAME o A para cada servicio: nextcloud.votre-domaine.com, vault.votre-domaine.com, jellyfin.votre-domaine.com, photos.votre-domaine.com y docs.votre-domaine.com. Si usas el reto DNS-01 de Caddy para el certificado wildcard, asegúrate de que tu proveedor DNS tiene una API compatible con el módulo caddy-dns correspondiente. Espera la propagación del DNS (entre minutos y horas según el TTL configurado).

  3. Crear la estructura de directorios

    Crea el árbol del proyecto en el VPS: mkdir -p /opt/homelab/{caddy,nextcloud,vaultwarden,jellyfin,immich,paperless}. Este directorio contendrá el archivo docker-compose.yml, el Caddyfile y los archivos de entorno. Los datos persistentes se almacenarán en volúmenes Docker nombrados, no en bind-mounts, para simplificar las copias de seguridad y evitar problemas de permisos.

  4. Escribir el Caddyfile

    En /opt/homelab/caddy/Caddyfile, declara un bloque por subdominio. Ejemplo para Nextcloud: nextcloud.votre-domaine.com { reverse_proxy nextcloud:80 }. Repite el patrón para cada servicio apuntando al nombre del servicio Docker (vaultwarden, jellyfin, immich-server, paperless-webserver). Caddy obtiene y renueva los certificados Let's Encrypt automáticamente en el primer acceso. Para un certificado wildcard, sustituye los bloques individuales por *.votre-domaine.com con el módulo DNS de tu proveedor, configurado mediante las variables de entorno de la imagen Caddy personalizada.

  5. Escribir el docker-compose.yml

    Crea /opt/homelab/docker-compose.yml con una red proxy compartida y una red internal aislada. Declara el servicio Caddy con ports: ["80:80", "443:443"] y volumes: ["./caddy/Caddyfile:/etc/caddy/Caddyfile", "caddy_data:/data"]. Para cada aplicación, declara networks: [proxy, internal] y no expongas ningún ports: — solo Caddy expone puertos públicos. Usa depends_on con condition: service_healthy para que Nextcloud no intente conectarse a MariaDB antes de que esté lista. Las variables sensibles (contraseñas de bases de datos, claves secretas) van en un archivo .env referenciado por env_file: .env.

  6. Configurar las variables de entorno

    Crea /opt/homelab/.env con las variables requeridas por cada servicio: MYSQL_ROOT_PASSWORD, MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD para MariaDB; NEXTCLOUD_ADMIN_USER, NEXTCLOUD_ADMIN_PASSWORD, NEXTCLOUD_TRUSTED_DOMAINS para Nextcloud; VAULTWARDEN_ADMIN_TOKEN para Vaultwarden. Genera los secretos con openssl rand -hex 32. Para Immich, copia el archivo .env de ejemplo del repositorio oficial. Nunca hagas commit de este archivo en un repositorio público; añade .env a tu .gitignore.

  7. Lanzar el stack

    Desde /opt/homelab, ejecuta docker compose pull para descargar todas las imágenes y luego docker compose up -d para arrancar el conjunto. Sigue los logs de arranque con docker compose logs -f para asegurarte de que cada servicio inicia sin errores. La primera inicialización de Nextcloud y Paperless-ngx puede tardar unos minutos (migraciones de base de datos, generación de claves). Caddy obtiene los certificados TLS en el primer acceso a cada subdominio — verifica que los puertos 80 y 443 son accesibles desde el exterior antes de probar.

  8. Finalizar la configuración de cada servicio

    Accede a cada interfaz web para completar la configuración inicial: Nextcloud (nextcloud.votre-domaine.com) para activar las aplicaciones recomendadas (Contacts, Calendar, Talk); Immich (photos.votre-domaine.com) para configurar las bibliotecas y activar las tareas de aprendizaje automático en segundo plano; Paperless-ngx (docs.votre-domaine.com) para configurar el consumidor de documentos y el OCR; Jellyfin (jellyfin.votre-domaine.com) para apuntar a las carpetas de medios montadas como volúmenes. Vaultwarden (vault.votre-domaine.com) solo requiere crear una cuenta desde el cliente Bitwarden — no se necesita configuración inicial del servidor.

Caddy, Nginx Proxy Manager o Traefik: qué reverse proxy para este stack

Desplace la tabla

CriterioCaddyNginx Proxy ManagerTraefik
ConfiguraciónCaddyfile declarativo, recarga sin downtimeInterfaz web, sin archivos que editarLabels Docker, recarga automática
SSL automáticoIntegrado, DNS-01 y HTTP-01 nativosLet's Encrypt vía interfaz, DNS-01 posibleLet's Encrypt vía ACME resolver, DNS-01 vía providers
WildcardNativo vía módulo caddy-dnsPosible pero requiere configuración manualNativo vía certificateResolvers
Curva de aprendizajeBaja — Caddyfile legible en 10 minutosMuy baja — todo se hace con clicsMedia — documentación extensa
Adecuado para este stackSí — configuración versionada, recarga en calienteSí para empezar, menos ideal para versionarSí para stacks más complejos, sobrecarga de config aquí

Hardening mínimo antes de la exposición pública

Cuatro medidas a aplicar antes de hacer el stack accesible desde el exterior:

1. Desactiva la página de registro abierto de Vaultwarden poniendo SIGNUPS_ALLOWED=false en el .env una vez creada tu cuenta.
2. Añade una cabecera X-Robots-Tag: noindex en el Caddyfile para Vaultwarden y la interfaz de administración de Paperless-ngx — estas páginas no deben indexarse.
3. Activa la rotación de logs de Docker (log-opts en /etc/docker/daemon.json) para evitar que los logs de Jellyfin o Paperless-ngx llenen el disco.
4. Programa un docker compose pull && docker compose up -d semanal mediante cron para mantener las imágenes actualizadas — las aplicaciones self-hosted publican periódicamente parches de seguridad. Revisa los changelogs antes de actualizar Immich, que puede introducir migraciones de base de datos no reversibles.

Resolución de problemas: errores comunes en el arranque

Error response from daemon: network proxy declared as external, but could not be found — Este mensaje aparece cuando la red Docker externa declarada en docker-compose.yml no existe todavía. Créala manualmente antes del primer docker compose up: docker network create proxy. O convierte la red en interna en el Compose (elimina external: true) para que Compose la cree él mismo.

nextcloud.votre-domaine.com redirected you too many times — Nextcloud detecta la petición HTTPS como HTTP porque Caddy la reenvía en HTTP sobre la red interna. Añade NEXTCLOUD_TRUSTED_PROXIES con la subred Docker (por ejemplo 172.16.0.0/12) y OVERWRITEPROTOCOL=https en el .env. Sin estas variables, Nextcloud no confía en las cabeceras X-Forwarded-Proto transmitidas por Caddy e intenta redirigir a HTTPS indefinidamente.

Immich cannot connect to database: connection refused — Immich arranca antes de que PostgreSQL esté listo. Añade depends_on con condition: service_healthy en el servicio immich-server y verifica que el servicio database declara un healthcheck válido (por ejemplo pg_isready -U immich). Sin healthcheck, Docker Compose considera el servicio «arrancado» en cuanto se lanza el contenedor, no cuando acepta conexiones.

Paperless-ngx worker exited with error: celery worker unhealthy — La base de datos Redis no es accesible. Comprueba que el servicio Redis está en la misma red que Paperless y que la variable PAPERLESS_REDIS apunta al nombre del servicio Compose (redis://redis:6379), no a localhost — en Docker Compose, localhost dentro de un contenedor apunta al propio contenedor, no a otro servicio.

Caddy no renueva el certificado wildcard — Si usas el reto DNS-01, verifica que las variables de entorno de la API DNS (token, zone ID) se transmiten correctamente al servicio Caddy en el Compose. Un token caducado o un permiso DNS insuficiente hace que la renovación falle silenciosamente 30 días antes de la expiración — Caddy registra el error pero no bloquea el tráfico hasta la expiración real.

Para ir más lejos

Este stack cubre los cinco servicios más demandados en las configuraciones homelab de 2026. Cada uno tiene una guía dedicada en este blog si quieres profundizar en un aspecto concreto: backup de Nextcloud, gestión de álbumes en Immich, transcodificado hardware en Jellyfin, reglas de retención en Paperless-ngx o sincronización multidispositivo en Vaultwarden.

Para ir más allá de este stack, las próximas piezas habitualmente añadidas son Uptime Kuma (monitorización de servicios internos) y Ntfy o Apprise (notificaciones push). Estos servicios son suficientemente ligeros para añadirse al mismo Compose sin afectar al dimensionamiento.

Si la gestión manual de actualizaciones y copias de seguridad se convierte en una carga, Coolify y Dokploy ofrecen interfaces que automatizan estas tareas conservando la arquitectura Docker Compose subyacente.

Un VPS con acceso root para tu stack homelab

ServOrbit.com ofrece VPS cloud desde 99 DH/mes, con IPv4 dedicada, elección de OS (Ubuntu, Debian, AlmaLinux), red de alta disponibilidad y snapshots. Despliega todo este stack con un solo comando `docker compose up -d`.

¿Necesita ayuda?

Consulte nuestro centro de ayuda y nuestra FAQ, o contacte con nuestro equipo: llamada, WhatsApp o correo electrónico. Soporte en francés, inglés y árabe.

Escribir por WhatsAppse abre en una pestaña nueva