Tutorial
Instalar Immich en Proxmox con acceso público, Nginx Proxy Manager y DDNS
Despliegue completo de Immich en Proxmox con SSD + HDD, acceso por dominio, proxy inverso con Nginx Proxy Manager, HTTPS y DNS dinámico con Cloudflare.
Objetivo
En este despliegue he montado un servidor de Immich dentro del homelab con:
- almacenamiento separado entre SSD y HDD
- acceso público mediante dominio
- proxy inverso con Nginx Proxy Manager
- HTTPS automático
- IP dinámica resuelta con DDNS sobre Cloudflare
Arquitectura final
Internet
↓
Cloudflare
↓
Router (80/443)
↓
VM Proxy (Nginx Proxy Manager)
↓
VM Immich (Docker)
↓
/srv/immich-library (HDD)
Crear la VM de Immich
La VM en Proxmox queda con esta base:
- Debian 13 minimal
- 2 vCPU
- 4 GB de RAM
- disco SSD para el sistema
- disco HDD adicional para los datos
Problema real: el usuario no tenía sudo
Después de instalar Debian, el usuario inicial no tenía permisos administrativos.
su -
usermod -aG sudo TU_USUARIO
reboot
Instalación de Docker
Problema típico
Docker no instalaba correctamente y docker-ce aparecía sin candidato. La causa era la ausencia del repositorio oficial.
Instalación correcta
sudo apt update
sudo apt install -y curl gnupg ca-certificates lsb-release
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Permitir usar Docker sin sudo
sudo usermod -aG docker TU_USUARIO
newgrp docker
Configuración del disco HDD
Problema detectado
El disco adicional no aparecía dentro de Debian porque no estaba realmente añadido desde Proxmox.
Solución
En Proxmox:
VM -> Hardware -> Add -> Hard Disk
Particionado
sudo fdisk /dev/sdb
Dentro de fdisk:
n
p
1
Enter
Enter
w
Formatear
sudo mkfs.ext4 /dev/sdb1
Montar
sudo mkdir -p /srv/immich-library
sudo mount /dev/sdb1 /srv/immich-library
Persistencia
Primero obtengo el UUID:
sudo blkid
Luego edito /etc/fstab:
sudo nano /etc/fstab
Añado una línea como esta:
UUID=TU_UUID /srv/immich-library ext4 defaults,nofail 0 2
Permisos
sudo chown -R 1000:1000 /srv/immich-library
sudo chmod -R 755 /srv/immich-library
Despliegue de Immich
mkdir /home/TU_USUARIO/immich-app
cd /home/TU_USUARIO/immich-app
wget https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
wget https://github.com/immich-app/immich/releases/latest/download/example.env -O .env
Configuración
Edito .env y ajusto al menos estas variables:
UPLOAD_LOCATION=/srv/immich-library
DB_DATA_LOCATION=./postgres
TZ=Europe/Madrid
Levantar contenedores
docker compose up -d
Acceso local
http://TU_IP_VM:2283
Exponer Immich con Nginx Proxy Manager
No cubro aquí la instalación completa de NPM, solo la parte necesaria para publicar Immich.
Proxy Host
- Dominio:
cloud.TU_DOMINIO.com - Forward IP:
TU_IP_VM_IMMICH - Puerto:
2283
Opciones recomendadas
Websockets: ONBlock exploits: ON
Configuración avanzada
client_max_body_size 50000M;
proxy_request_buffering off;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
SSL
- Let’s Encrypt
- Force HTTPS
- HTTP/2
DNS en Cloudflare
Creo el registro DNS inicial:
- Tipo:
A - Nombre:
cloud - IP:
TU_IP_PUBLICA - Proxy:
OFFal principio
DDNS con Cloudflare
Problema
La IP pública cambia y el dominio deja de resolver bien si no se actualiza automáticamente.
Script
sudo mkdir -p /opt/ddns
sudo nano /opt/ddns/ddns.sh
Script base:
#!/usr/bin/env bash
CF_TOKEN="TU_TOKEN"
ZONE_NAME="TU_DOMINIO.com"
RECORD_NAME="cloud.TU_DOMINIO.com"
IP=$(curl -s https://api.ipify.org)
ZONE_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$ZONE_NAME" \
-H "Authorization: Bearer $CF_TOKEN" | jq -r '.result[0].id')
RECORD_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?name=$RECORD_NAME" \
-H "Authorization: Bearer $CF_TOKEN" | jq -r '.result[0].id')
curl -X PATCH "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
-H "Authorization: Bearer $CF_TOKEN" \
-H "Content-Type: application/json" \
--data "{\"type\":\"A\",\"name\":\"$RECORD_NAME\",\"content\":\"$IP\",\"ttl\":120,\"proxied\":true}"
Seguridad
sudo chmod 700 /opt/ddns/ddns.sh
sudo chown root:root /opt/ddns/ddns.sh
Automatización
Servicio:
[Service]
ExecStart=/opt/ddns/ddns.sh
Type=oneshot
Timer:
[Timer]
OnBootSec=1min
OnUnitActiveSec=5min
Activación:
sudo systemctl daemon-reload
sudo systemctl enable --now ddns.timer
Seguridad básica
Problema detectado
Cualquiera podía registrarse en Immich.
Solución
En Immich:
Settings -> Authentication -> Disable sign-up
Problemas reales encontrados
- Docker no instalaba porque faltaba el repositorio oficial.
- El disco no aparecía porque no estaba añadido en Proxmox.
- Docker daba problemas de permisos porque el usuario no estaba en el grupo adecuado.
- Las subidas grandes fallaban sin
client_max_body_size. - El SSL fallaba mientras DNS y proxy no estaban alineados.
- El registro abierto suponía un riesgo claro de abuso.
Consideraciones
- Immich evita duplicados automáticamente.
- Si cambia la IP pública, el dominio no tiene por qué romperse si el DDNS funciona bien.
- Separar almacenamiento mejora orden y rendimiento.
- El proxy inverso permite escalar más servicios sin rehacer la arquitectura.
Resultado final
- servidor de fotos privado
- acceso desde cualquier lugar
- HTTPS válido
- IP dinámica resuelta
- arquitectura escalable
Mejoras futuras
- autenticación externa o SSO
- backups automáticos
- uso de GPU para ML
- monitorización
- VPN o Zero Trust
Comentarios
Conversación sobre Instalar Immich en Proxmox con acceso público, Nginx Proxy Manager y DDNS
Solo se muestran comentarios aprobados. Para publicar uno es necesario iniciar sesión.Cargando comentarios…