Dify en tu propio servidor: constructor de agentes de IA sin código
TL;DR
Dify es una plataforma self-hosted para crear aplicaciones de IA, chatbots, búsqueda RAG y agentes de IA sin escribir código backend completo. En esta guía desplegaremos Dify en Ubuntu 24.04 LTS mediante Docker Compose, conectaremos HTTPS, configuraremos la seguridad básica, las copias de seguridad y verificaremos el funcionamiento del servicio.
- Dify funciona en tu propio VPS y no requiere instalar Python ni Node.js en el host.
- Para un equipo de pruebas bastan 4 vCPU, 8 GB de RAM y un SSD de 80 GB o más.
- La configuración utiliza PostgreSQL, Redis, Weaviate y contenedores sandbox de Dify.
- El acceso al panel de administración se organiza mediante un dominio y un certificado TLS de Let’s Encrypt.
- Los secretos se almacenan en el archivo
.env, y los datos se copian regularmente a un almacenamiento externo.
1. TL;DR
Dify es un constructor visual de aplicaciones de IA. En su interfaz se puede crear un workflow, un chatbot, un agente con herramientas, una base de conocimientos y una API para tu propio sitio web. A diferencia de la versión SaaS, Dify self-hosted se ejecuta en tu servidor, por lo que controlas de forma independiente la configuración, el acceso de red, las copias de seguridad y los modelos de lenguaje conectados.
- Utilizamos Ubuntu Server 24.04 LTS.
- Instalamos Docker Engine 28.x y Docker Compose v2.
- Desplegamos Dify 1.x desde el repositorio oficial.
- Publicamos la aplicación mediante Caddy y HTTPS.
- Verificamos los contenedores, la API, el dominio y las copias de seguridad.
2. Contenido
La guía está dirigida a un administrador que sabe conectarse a un servidor Linux mediante SSH y dispone de un dominio registrado. Los comandos se ejecutan como un usuario normal con permisos sudo, salvo que se indique explícitamente lo contrario.
Antes de comenzar, prepare un nombre de dominio, por ejemplo dify.example.com. Cree un registro A en DNS que apunte a la dirección IPv4 del servidor. Si utiliza IPv6, agregue un registro AAAA solo después de comprobar que el firewall está correctamente configurado.
3. Qué configuramos y por qué
Qué es Dify
Dify es una plataforma open-source para desarrollar aplicaciones basadas en modelos de lenguaje de gran tamaño. Combina un editor visual de prompts, un motor de workflow, gestión de modelos, bases de conocimientos, búsqueda RAG, publicación de aplicaciones web y una REST API.
En un escenario típico, el usuario formula una pregunta en el chat. Dify recibe la solicitud, busca fragmentos relevantes en los documentos si es necesario, transmite el contexto al modelo de lenguaje, aplica reglas adicionales y devuelve una respuesta. Este proceso se puede configurar mediante bloques visuales sin desarrollar un servicio backend independiente.
Qué tareas resuelve Dify self-hosted
- Chat corporativo interno sobre documentos e instrucciones.
- Agente de IA para atención al cliente o primera línea de helpdesk.
- Generación de textos, clasificación de solicitudes y extracción de datos.
- Búsqueda RAG en PDF, DOCX, Markdown y otros materiales.
- Prototipado de funciones de IA antes de integrarlas en un producto SaaS.
- Pasarela API única para varios proveedores de modelos de lenguaje.
Qué estará listo al final
Tras completar la guía, en el servidor funcionarán Dify, la base de datos PostgreSQL, Redis para colas y caché, el almacenamiento vectorial y los servicios auxiliares. El panel administrativo estará disponible mediante HTTPS, y las aplicaciones de usuario podrán publicarse como interfaces web o conectarse mediante API.
Es importante entender los límites de esta instalación. Dify no convierte un VPS normal en un modelo de lenguaje autónomo. Para generar respuestas es necesario conectar una API externa de un proveedor o desplegar un modelo local mediante Ollama, vLLM u otro servidor compatible. Un modelo local requerirá adicionalmente una GPU o una gran cantidad de RAM.
Cloud-managed o self-hosted
| Criterio | Versión en la nube | Self-hosted en VPS |
|---|---|---|
| Inicio | No es necesario administrar el servidor | Es necesario instalar y actualizar el software |
| Control de datos | Depende de las condiciones del proveedor | El servicio y la base de datos están bajo tu control |
| Acceso de red | Normalmente lo determina el plan | Puede limitarse mediante VPN, firewall o allowlist |
| Escalabilidad | Se realiza mediante el panel del proveedor | Eres responsable de CPU, RAM, disco y tolerancia a fallos |
| Coste | Pago del plan y posibles límites | Pago del servidor más la API de modelos de lenguaje |
La opción self-hosted tiene sentido cuando se necesita controlar el perímetro de red, aplicar políticas propias de almacenamiento de datos, contar con recursos predecibles o poder modificar la infraestructura. También resulta cómoda para el desarrollo, pero requiere mantenimiento regular: actualizaciones, comprobación del disco, copias de seguridad y control de secretos.
4. Qué configuración de VPS se necesita para esta tarea
Configuración mínima
Dify se ejecuta como un conjunto de contenedores, por lo que consume considerablemente más recursos que un pequeño servicio web. La carga depende del número de workflow simultáneos, el tamaño de los índices RAG, la cantidad de documentos y los modelos seleccionados.
| Escenario | CPU | RAM | Disco | Red |
|---|---|---|---|---|
| Pruebas y un administrador | 2 vCPU | 4 GB | 50 GB SSD | 100 Mbit/s |
| Equipo pequeño | 4 vCPU | 8 GB | 80–120 GB NVMe | 100–500 Mbit/s |
| Carga de trabajo | 8 vCPU | 16 GB | 160–300 GB NVMe | 500 Mbit/s o más |
Una opción inicial práctica para un equipo de varias personas es 4 vCPU, 8 GB de RAM, un disco NVMe de 100 GB o más y copias de seguridad fuera del servidor. Puede elegir un VPS adecuado con estas características y aumentar los recursos más adelante sin cambiar la arquitectura.
Por qué es importante un disco rápido
En Dify funcionan simultáneamente PostgreSQL, Redis, el almacenamiento vectorial y tareas en segundo plano. Un HDD lento aumenta el tiempo de inicio de los contenedores, la indexación de documentos y la ejecución de workflows. Un SSD es la opción mínima razonable, mientras que NVMe es preferible para cargas frecuentes de archivos y varios usuarios.
Cuándo se necesita un servidor dedicado
Un servidor dedicado está justificado si se requiere un modelo de lenguaje local propio, un índice de documentos grande, decenas o cientos de solicitudes paralelas, aislamiento estricto de recursos o una GPU. Para Dify sin una LLM local, normalmente no se necesita un servidor dedicado: la aplicación puede acceder a una API externa y el VPS sigue siendo suficientemente económico.
Elección de ubicación
La región del servidor influye en la latencia para los usuarios, la disponibilidad de los proveedores de API y los requisitos legales sobre los datos. Para un chat interactivo, es recomendable elegir un centro de datos cercano a la audiencia principal. Si Dify accede a un modelo externo en otra región, mida la latencia hacia ambos endpoints, no solo hacia el servidor.
Para un servidor de producción también se necesitan una IPv4 pública, la posibilidad de abrir los puertos TCP 80 y 443, snapshots automáticos o almacenamiento externo para las copias de seguridad. No dependa de un snapshot como única copia: la pérdida de la cuenta o la eliminación del VPS puede destruir también el snapshot.
5. Preparación del servidor
Conexión y actualización del sistema
A continuación se asume un servidor Ubuntu Server 24.04 LTS limpio con el usuario root. Sustituya la dirección IP por la de su VPS.
ssh [email protected]
Primero actualizaremos el índice de paquetes y los componentes instalados.
apt update && apt full-upgrade -y
apt install -y ca-certificates curl gnupg git jq unzip vim ufw fail2ban unattended-upgrades
El primer comando instala actualizaciones de seguridad. El segundo añade utilidades para repositorios, diagnóstico, firewall e instalación automática de actualizaciones de seguridad.
Creación del administrador
No utilice acceso SSH permanente como root. Cree un usuario independiente y añádalo al grupo sudo.
adduser deploy
usermod -aG sudo deploy
install -d -m 700 -o deploy -g deploy /home/deploy/.ssh
En el ordenador local, genere una clave ED25519 si aún no la tiene.
ssh-keygen -t ed25519 -C "dify-admin"
Copie la clave pública al servidor. El comando solicitará la contraseña del usuario deploy.
ssh-copy-id [email protected]
ssh [email protected]
Asegúrese de que sudo funciona.
sudo -v
id
Configuración de SSH
Antes de desactivar el inicio de sesión por contraseña, compruebe que se abre una nueva sesión SSH con clave. A continuación, cree un archivo drop-in independiente.
sudo tee /etc/ssh/sshd_config.d/ hardening.conf >/dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
EOF
En el comando anterior no debe haber un espacio dentro de la ruta. La variante correcta, si el shell no procesó la línea con espacio:
sudo tee /etc/ssh/sshd_config.d/hardening.conf >/dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
EOF
sudo sshd -t
sudo systemctl reload ssh
La comprobación sshd -t es obligatoria: evita aplicar una configuración sintácticamente incorrecta. No cierre la sesión SSH anterior hasta verificar el nuevo acceso en una ventana independiente.
Firewall y fail2ban
Abriremos SSH, HTTP y HTTPS. Es mejor limitar el puerto SSH a su dirección IP si es fija.
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
Activaremos la protección de SSH contra ataques de fuerza bruta de contraseñas y claves.
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
En producción resulta útil limitar SSH con una regla como sudo ufw allow from 198.51.100.25 to any port 22 proto tcp. No la ejecute hasta conocer su dirección actual: una regla errónea puede bloquear el acceso.
Actualizaciones automáticas de seguridad
sudo dpkg-reconfigure -plow unattended-upgrades
sudo systemctl status unattended-upgrades --no-pager
Las actualizaciones automáticas son útiles para los paquetes del sistema operativo, pero no sustituyen una actualización planificada de las imágenes Docker de Dify. Cambie la versión de la aplicación por separado y solo después de realizar una copia de seguridad.
6. Instalación del software — paso a paso
Paso 1. Instalación de Docker Engine
Para Dify en 2026, utilice Docker Engine 27 o 28 y Docker Compose v2. No instale el paquete antiguo docker-compose desde un PPA aleatorio: el comando actual es docker compose.
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
Los comandos añaden la clave oficial de Docker y preparan el directorio para los repositorios firmados.
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(. /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
Comprobaremos las versiones y el contenedor de prueba.
sudo docker version
sudo docker compose version
sudo docker run --rm hello-world
Añada el usuario deploy al grupo Docker para no utilizar sudo en cada comando.
sudo usermod -aG docker "$USER"
newgrp docker
docker ps
La pertenencia al grupo Docker proporciona, en la práctica, privilegios de root. Por ello, el acceso al servidor debe estar protegido mediante claves SSH, firewall y un número limitado de administradores.
Paso 2. Descarga de Dify
El paquete oficial self-hosted de Dify se encuentra en el repositorio Git del proyecto. Para production, fije una versión verificada en lugar de dejar la aplicación en una rama de desarrollo arbitraria. A continuación se muestra un ejemplo para la línea Dify 1.x; antes de la instalación, compruebe el nombre de la última etiqueta estable en el repositorio oficial.
sudo mkdir -p /opt
sudo chown deploy:deploy /opt
cd /opt
git clone https://github.com/langgenius/dify.git
cd /opt/dify/docker
Si ha elegido una etiqueta estable concreta, cambie el repositorio a ella. El valor de la etiqueta debe existir en el momento de la instalación.
git fetch --tags
git tag --sort=-v:refname | head -n 10
git checkout 1.9.1
Si en el repositorio oficial ya se ha publicado una versión estable más reciente, sustituya 1.9.1 por ella. No mezcle archivos de distintas versiones ni copie el .env antiguo sin comprobar los nuevos parámetros.
Paso 3. Creación del archivo de entorno
Copie la plantilla de configuración. Dify utiliza variables de entorno para las contraseñas de la base de datos, las claves de firma, las direcciones de los servicios y la URL de publicación.
cd /opt/dify/docker
cp .env.example .env
chmod 600 .env
sed -n '1,80p' .env
Genere valores aleatorios para los secretos. No utilice contraseñas cortas, fechas de nacimiento, el nombre del proyecto ni la misma clave para todos los componentes.
python3 - <<'PY'
import secrets
for name in ("SECRET_KEY", "INIT_PASSWORD", "DB_PASSWORD", "REDIS_PASSWORD"):
print(f"{name}={secrets.token_urlsafe(32)}")
PY
Copie los valores obtenidos en las líneas correspondientes de .env. Para editarlo automáticamente, puede utilizar un editor:
nano /opt/dify/docker/.env
Paso 4. Inicio de los contenedores
Antes del primer inicio, compruebe qué archivos compose incluye la versión seleccionada.
cd /opt/dify/docker
docker compose config --quiet
Si el comando finaliza sin mostrar un mensaje de error, la configuración es sintácticamente correcta. Inicie el stack en segundo plano.
docker compose up -d
El primer inicio puede tardar varios minutos: Docker descargará las imágenes de PostgreSQL, Redis, el almacenamiento vectorial, API, worker y los componentes web.
Paso 5. Comprobación del estado
docker compose ps
docker compose logs --tail=100 api
docker compose logs --tail=100 worker
La mayoría de los contenedores deberían tener el estado Up o running. Un estado puntual health: starting después del inicio es normal, pero debería cambiar al cabo de unos minutos.
Paso 6. Comprobación HTTP local
Compruebe qué puerto está publicado por la configuración compose.
docker compose port nginx 80
curl -I http://127.0.0.1
Si en la versión seleccionada el contenedor proxy externo tiene otro nombre, utilice el nombre mostrado por docker compose ps. Una respuesta 200, 301 o 302 indica que la capa HTTP responde. Un error 502 requiere comprobar los contenedores backend.
7. Configuración
Parámetros principales de Dify
A continuación se indican los parámetros que normalmente deben comprobarse en /opt/dify/docker/.env. Los nombres de algunas variables pueden cambiar entre versiones, por lo que debe consultar los comentarios del .env.example actual.
cd /opt/dify/docker
grep -E '^(SECRET_KEY|INIT_PASSWORD|CONSOLE_API_URL|CONSOLE_WEB_URL|SERVICE_API_URL|FILES_URL|DB_|REDIS_|VECTOR|LOG_LEVEL)' .env
Para el dominio de Dify, normalmente se definen las URL de la consola, la API y el servicio de archivos. Ejemplo:
CONSOLE_API_URL=https://dify.example.com
CONSOLE_WEB_URL=https://dify.example.com
SERVICE_API_URL=https://dify.example.com
APP_WEB_URL=https://dify.example.com
FILES_URL=https://dify.example.com
Si su versión contiene otros nombres para las variables de URL, no los añada a ciegas: utilice los nombres de la plantilla de la versión concreta. No publique el contenido completo del archivo .env en tickets ni chats.
Conexión del proveedor del modelo de lenguaje
Después de iniciar sesión en la consola web, abra la configuración de proveedores de modelos y añada la clave de API del proveedor necesario. La clave se almacena en la configuración de Dify o en el almacenamiento protegido del propio proveedor, según el método seleccionado.
Para la primera prueba, configure un modelo económico con un contexto limitado y establezca límites de gasto en la API del proveedor. Después, cree una aplicación Chatflow sencilla con una instrucción del sistema y una pregunta de prueba. Compruebe no solo la calidad de la respuesta, sino también el número de tokens, la latencia y las llamadas erróneas a las herramientas.
Conexión de la base de conocimientos
- Cree un Dataset en el panel de Dify.
- Cargue un conjunto pequeño de documentos sin datos confidenciales.
- Seleccione el método de división del texto y el tamaño del fragmento.
- Espere a que finalice la indexación.
- Cree una aplicación con un bloque de búsqueda en el Dataset.
- Compruebe la respuesta a una pregunta que aparezca explícitamente en los documentos.
Si los documentos contienen tablas, escaneos o una maquetación compleja, compruebe por separado la calidad de la extracción del texto. RAG no corrige los errores de OCR ni garantiza una cita exacta cuando el archivo original se ha dividido incorrectamente.
Reverse proxy mediante Caddy
El proxy integrado de Dify resulta práctico para el inicio local, pero un Caddy independiente simplifica la obtención y renovación del certificado. En esta variante, Caddy escuchará en los puertos 80 y 443 del host, mientras que Dify solo estará disponible a través de un puerto local.
Primero detenga o reconfigure el componente de Dify que ya ocupa el puerto 80. Los nombres de los servicios varían según la versión, por lo que primero debe consultar la lista de publicaciones:
cd /opt/dify/docker
docker compose ps
docker compose port nginx 80 || true
sudo ss -ltnp | grep -E ':(80|443)\b'
Instale Caddy desde el repositorio apt oficial:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install -y caddy
Cree la configuración de Caddy. Si Dify publica HTTP en otro puerto local, sustituya 127.0.0.1:8080 por la dirección real.
dify.example.com {
reverse_proxy 127.0.0.1:8080
header {
X-Content-Type-Options "nosniff"
Referrer-Policy "strict-origin-when-cross-origin"
X-Frame-Options "SAMEORIGIN"
}
log {
output file /var/log/caddy/dify-access.log
format json
}
}
Guarde el archivo, compruébelo y reinicie Caddy:
sudo caddy fmt --overwrite /etc/caddy/Caddyfile
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl enable --now caddy
sudo systemctl reload caddy
sudo journalctl -u caddy -n 50 --no-pager
Caddy solicitará automáticamente un certificado de Let’s Encrypt si el DNS ya apunta al servidor y los puertos 80/443 están accesibles desde Internet. Para un dominio privado sin un registro DNS público, el certificado público automático no funcionará; en ese caso, utilice una CA corporativa o una VPN.
Comprobación del dominio y HTTPS
dig +short dify.example.com
curl -I https://dify.example.com
curl -sS -o /dev/null -w '%{http_code}\n' https://dify.example.com
Compruebe el período de validez del certificado:
echo | openssl s_client -connect dify.example.com:443 -servername dify.example.com 2>/dev/null | openssl x509 -noout -subject -issuer -dates
Comprobación de contenedores y recursos
cd /opt/dify/docker
docker compose ps
docker stats --no-stream
df -h
free -h
sudo journalctl -u docker --since "30 minutes ago" --no-pager
Deje como mínimo entre un 15 y un 20 por ciento de espacio libre en el disco. Las imágenes de Docker, los registros y los documentos cargados aumentan gradualmente el consumo. Cuando el disco se llena, PostgreSQL y Redis pueden finalizar con errores, incluso si hay CPU y RAM disponibles.
Creación de la primera aplicación
- Abra la URL de Dify y complete la configuración inicial del administrador.
- Añada un modelo en la sección Model Provider.
- Cree un Chatflow o Workflow.
- Defina una instrucción del sistema y limite el ámbito de la respuesta.
- Publique la aplicación y pruebe la interfaz web.
- Para la integración, copie la clave de API de la aplicación, no la contraseña del administrador.
Trate las claves de API como contraseñas: emita una clave independiente para cada servicio, guárdela en un almacén de secretos y revóquela cuando finalice el experimento. No incluya la clave en código JavaScript que se envíe al navegador del usuario.
8. Copias de seguridad y mantenimiento
Qué debe conservarse
- PostgreSQL: usuarios, aplicaciones, configuraciones y metadatos.
- Archivos de Dify: documentos cargados, imágenes y resultados del procesamiento.
- Almacenamiento vectorial: índices de Dataset o documentos fuente para la restauración.
.envy los archivos compose seleccionados.- La configuración de Caddy y firewall.
- La lista de versiones de imágenes Docker y la etiqueta Git de Dify.
El archivo .env contiene secretos, por lo que la copia de seguridad debe estar cifrada. No lo almacene en un repositorio Git público ni lo envíe a un almacenamiento de objetos común sin cifrado.
Volcado local de PostgreSQL
El comando exacto depende del nombre del contenedor y de la base de datos en la versión seleccionada. Puede obtener el nombre así:
cd /opt/dify/docker
docker compose ps --services
docker compose ps | grep -E 'postgres|db'
Si el servicio de base de datos se llama db, el ejemplo de volcado es el siguiente:
mkdir -p /opt/backups/dify
docker compose exec -T db pg_dump -U postgres dify | gzip > "/opt/backups/dify/postgres-$(date +%F-%H%M).sql.gz"
find /opt/backups/dify -type f -name '.sql.gz' -mtime +14 -delete
Compruebe el nombre de la base de datos y del usuario con las variables DB_DATABASE y DB_USERNAME en el .env actual. No introduzca la contraseña en la línea de comandos: podría acabar en el historial del shell o en la lista de procesos.
Script de copia de seguridad con restic
Para production es mejor utilizar un storage externo compatible con S3 o un servidor de backup independiente. Instale restic:
sudo apt install -y restic
sudo install -d -m 700 /etc/restic
sudo nano /etc/restic/dify.env
Ejemplo de archivo de entorno:
AWS_ACCESS_KEY_ID=replace-me
AWS_SECRET_ACCESS_KEY=replace-me
RESTIC_REPOSITORY=s3:https://s3.example.net/dify-backups
RESTIC_PASSWORD=replace-with-long-random-password
Restrinja el acceso a él:
sudo chmod 600 /etc/restic/dify.env
sudo restic --env-file /etc/restic/dify.env init
Cree el script. Detiene las operaciones en segundo plano durante un breve periodo, realiza un volcado de la base de datos, copia la configuración y envía los datos a restic.
sudo tee /usr/local/sbin/backup-dify >/dev/null <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
BASE=/opt/dify/docker
WORK=/var/backups/dify
STAMP=$(date +%F-%H%M)
mkdir -p "$WORK"
cd "$BASE"
docker compose exec -T db pg_dump -U postgres dify | gzip > "$WORK/postgres-$STAMP.sql.gz"
tar --exclude='.log' -czf "$WORK/config-$STAMP.tar.gz" \
"$BASE/.env" "$BASE/docker-compose.yaml" /etc/caddy/Caddyfile
restic --env-file /etc/restic/dify.env backup "$WORK" /opt/dify
restic --env-file /etc/restic/dify.env forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
find "$WORK" -type f -mtime +2 -delete
EOF
sudo chmod 700 /usr/local/sbin/backup-dify
sudo /usr/local/sbin/backup-dify
Compruebe que existe el snapshot:
sudo restic --env-file /etc/restic/dify.env snapshots
sudo restic --env-file /etc/restic/dify.env check
Ejecución programada
Cree una tarea cron como root. Elija la hora teniendo en cuenta la zona horaria y la carga.
sudo crontab -e
30 3 * /usr/local/sbin/backup-dify >> /var/log/backup-dify.log 2>&1
Al menos una vez al mes, realice una restauración de prueba en una máquina independiente o en un VPS temporal. Una copia de seguridad que nunca se ha restaurado es solo una suposición de que los datos existen.
Actualización de Dify
Antes de actualizar, guarde la etiqueta Git actual, la configuración, el volcado de PostgreSQL y la lista de imágenes.
cd /opt/dify
git rev-parse --short HEAD
cd docker
docker compose images
sudo /usr/local/sbin/backup-dify
Después obtenga la nueva versión y revise sus release notes. No actualice production directamente desde la rama main. Primero pruebe la nueva versión en una copia de la base de datos o en un servidor de staging.
cd /opt/dify
git fetch --tags
git checkout 1.9.1
cd docker
docker compose pull
docker compose config --quiet
docker compose up -d
docker compose ps
Después de la actualización, compruebe el acceso a la consola, la creación de una aplicación de prueba, la búsqueda en Dataset y la API. Para una instalación pequeña, normalmente es adecuada una maintenance window de 10–30 minutos. Un rolling update requiere varias instancias de API y worker, almacenamiento compartido y un esquema de migraciones independiente, por lo que no es necesario para el primer VPS.
Monitorización
Comience con comprobaciones simples: espacio libre, RAM, estado de los contenedores, errores de Docker y fecha de expiración del certificado TLS. Para una operación continua, añada Uptime Kuma, Prometheus u otra monitorización, pero no aloje la única monitorización en el mismo VPS.
df -h /
free -m
docker compose -f /opt/dify/docker/docker-compose.yaml ps
docker system df
sudo journalctl -p warning..alert --since today --no-pager
9. Troubleshooting y FAQ
Después del inicio, los contenedores se reinician constantemente. ¿Qué comprobar?
Primero ejecute docker compose ps y revise los logs del servicio específico: docker compose logs --tail=200 api, worker, db o redis. Las causas frecuentes son secretos incorrectos en .env, falta de RAM, un puerto ocupado o un archivo compose incompatible. Compruebe free -h, df -h y docker compose config. Después de corregirlo, reinicie únicamente el stack afectado con el comando docker compose up -d.
¿Qué configuración de VPS es mínimamente adecuada?
Para conocer Dify puede empezar con 2 vCPU, 4 GB de RAM y SSD de 50 GB o más, pero este es el límite inferior para un usuario y pruebas pequeñas. Para un equipo real, es mejor elegir 4 vCPU, 8 GB de RAM y NVMe de 80–100 GB o más. Si se planea una LLM local, estos requisitos ya no son adecuados: necesitará un servidor GPU independiente o un dedicated potente con mucha RAM.
¿Qué elegir para esta tarea: VPS o dedicated?
Un VPS es adecuado para la mayoría de los proyectos Dify que utilizan API de modelos externas: es más económico, más fácil de escalar y suficiente para un equipo pequeño o mediano. Un dedicated tiene sentido con una carga alta constante, inference local, un índice vectorial grande, GPU o un aislamiento estricto de recursos. Puede empezar con un VPS y trasladar Docker Compose a un dedicated más adelante, si las métricas muestran falta de CPU, RAM, disco o I/O.
Se abre 502 Bad Gateway a través del dominio. ¿Dónde buscar la causa?
Compruebe si el backend responde localmente: curl -I http://127.0.0.1:8080 o el puerto real de la configuración compose. Después revise sudo journalctl -u caddy -n 100 y docker compose logs --tail=100. A menudo Caddy está configurado con el puerto incorrecto, el contenedor de Dify no se ha iniciado o el puerto ya está ocupado por el proxy integrado. Compruebe también que Caddy y Docker utilicen la misma dirección loopback.
El certificado Let’s Encrypt no se emite. ¿Qué hacer?
Asegúrese de que el registro A del dominio devuelve la dirección pública del VPS: dig +short dify.example.com. Los puertos 80 y 443 deben estar permitidos tanto en UFW como en el firewall del proveedor. Compruebe que el registro AAAA no apunte a un IPv6 que no funciona: la autoridad de certificación puede elegir IPv6 y recibir un error. Los logs de Caddy mostrarán la causa exacta, por ejemplo DNS failure, timeout o rate limit.
Dify no detecta el modelo de lenguaje añadido. ¿Por qué?
Compruebe la clave API, el endpoint y el tipo de modelo seleccionado. Si el proveedor utiliza una API compatible con OpenAI, la URL debe apuntar al base path correcto, no solo al dominio. Realice una prueba de conexión desde el contenedor o desde el host mediante curl, teniendo en cuenta que el contenedor puede no tener acceso DNS o tener un firewall saliente. Compruebe los límites de la cuenta del proveedor y la hora del servidor mediante timedatectl.
La indexación de documentos se ha detenido en un porcentaje.
Revise los logs de worker y del almacenamiento vectorial: docker compose logs --tail=200 worker y los del servicio vectorial correspondiente. Compruebe el espacio libre, la RAM y la disponibilidad de Redis. Un PDF grande, un escaneo sin capa de texto o un archivo dañado puede bloquear el procesamiento. Para el diagnóstico, cargue un archivo de texto pequeño. Si el archivo pequeño se indexa, probablemente el problema está en el formato o el tamaño del documento fuente.
¿Cómo restringir el acceso al panel administrativo?
La opción más sencilla es cerrar 80/443 para todo Internet y permitir el acceso de los usuarios mediante WireGuard o VPN corporativa. Si se requiere acceso público, utilice contraseñas largas y únicas, MFA, claves API independientes, fail2ban y un WAF externo. No exponga públicamente los puertos Docker de PostgreSQL, Redis y el almacenamiento vectorial. En el firewall solo deben estar abiertos SSH, HTTP y HTTPS, y es recomendable restringir SSH a IP de confianza.
¿Se puede ejecutar Dify con un modelo local en el mismo VPS?
Técnicamente es posible conectar un servicio de inference compatible, pero un VPS normal sin GPU funcionará lentamente. Un modelo cuantizado pequeño requerirá mucha RAM y la velocidad de generación puede ser inaceptable. Es más práctico mantener Dify en un CPU-VPS y trasladar inference a un servidor GPU. Restrinja la comunicación entre ambos mediante una red privada, VPN o una allowlist de firewall, y active TLS para la API del modelo.
10. Conclusiones y siguientes pasos
Como resultado, ha obtenido Dify self-hosted en Ubuntu con Docker Compose, conexión a un modelo de lenguaje, dominio HTTPS y un esquema básico de copias de seguridad. Esta instalación es adecuada para prototipos, herramientas internas de AI, bases de conocimiento RAG y equipos pequeños de production.
La siguiente etapa práctica consiste en trasladar staging a un proyecto independiente, añadir monitorización de recursos y probar regularmente la restauración de copias de seguridad. A medida que aumente la carga, mida CPU, RAM, I/O, el tamaño de PostgreSQL y el tiempo de procesamiento de workflow, en lugar de aumentar el plan a ciegas. Para modelos locales y una carga alta constante, planifique con antelación una GPU independiente o un servidor dedicated.