Seafile es una plataforma de sincronización y compartición de archivos autoalojada, parecida a Dropbox o Google Drive, que destaca por su rendimiento con bibliotecas grandes, el historial de versiones y el cifrado de bibliotecas en el cliente. En esta guía desplegarás Seafile Community Edition 12 con Docker Compose en Ubuntu 24.04, lo publicarás detrás de Nginx con un certificado de Let's Encrypt y activarás el acceso por WebDAV.
Requisitos previos
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con al menos 2 GB de RAM (4 GB recomendados) y espacio en disco suficiente para los archivos de los usuarios.
- Un usuario no root con privilegios
sudo. - Docker Engine y el plugin Docker Compose instalados desde el repositorio oficial de Docker.
- Un dominio o subdominio, por ejemplo
seafile.tu_dominio.com, con un registro DNSAapuntando a la IP pública del servidor. - Los puertos 80 y 443 accesibles desde Internet.
A lo largo de la guía, sustituye seafile.tu_dominio.com por tu subdominio real.
Paso 1: Preparar el directorio y los secretos
Seafile guardará su configuración, la base de datos y los archivos en un único directorio del host. Créalo en /opt/seafile:
sudo mkdir -p /opt/seafile
cd /opt/seafile
Las contraseñas y la clave de firma de tokens irán en un archivo .env que Docker Compose lee automáticamente. Genera tres valores aleatorios para usarlos a continuación:
openssl rand -hex 24
openssl rand -hex 24
openssl rand -hex 32
Crea el archivo .env:
sudo nano /opt/seafile/.env
Pega el siguiente contenido y sustituye los valores de ejemplo por los que acabas de generar y por tus datos de administrador:
DB_ROOT_PASSWORD=primer_valor_generado
DB_PASSWORD=segundo_valor_generado
JWT_PRIVATE_KEY=tercer_valor_generado
SEAFILE_HOSTNAME=seafile.tu_dominio.com
ADMIN_EMAIL=admin@tu_dominio.com
ADMIN_PASSWORD=tu_contraseña_segura
TIME_ZONE=Europe/Madrid
Restringe los permisos del archivo, ya que contiene credenciales:
sudo chmod 600 /opt/seafile/.env
Paso 2: Crear el archivo de Docker Compose
El despliegue usa tres contenedores: MariaDB para los metadatos, Memcached como caché y la imagen oficial seafileltd/seafile-mc, que incluye el servidor de Seafile, la interfaz web Seahub y un Nginx interno. El puerto web del contenedor se publica solo en 127.0.0.1:8000, porque el acceso público lo gestionará el Nginx del host.
sudo nano /opt/seafile/docker-compose.yml
services:
db:
image: mariadb:10.11
container_name: seafile-mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_LOG_CONSOLE: "true"
MARIADB_AUTO_UPGRADE: "1"
volumes:
- ./mysql:/var/lib/mysql
healthcheck:
test: ["CMD", "/usr/local/bin/healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 20s
start_period: 30s
timeout: 5s
retries: 10
memcached:
image: memcached:1.6.29
container_name: seafile-memcached
restart: unless-stopped
entrypoint: memcached -m 256
seafile:
image: seafileltd/seafile-mc:12.0-latest
container_name: seafile
restart: unless-stopped
ports:
- "127.0.0.1:8000:80"
volumes:
- ./data:/shared
environment:
SEAFILE_MYSQL_DB_HOST: db
SEAFILE_MYSQL_DB_PORT: "3306"
SEAFILE_MYSQL_DB_USER: seafile
SEAFILE_MYSQL_DB_PASSWORD: ${DB_PASSWORD}
INIT_SEAFILE_MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
SEAFILE_MYSQL_DB_CCNET_DB_NAME: ccnet_db
SEAFILE_MYSQL_DB_SEAFILE_DB_NAME: seafile_db
SEAFILE_MYSQL_DB_SEAHUB_DB_NAME: seahub_db
TIME_ZONE: ${TIME_ZONE}
INIT_SEAFILE_ADMIN_EMAIL: ${ADMIN_EMAIL}
INIT_SEAFILE_ADMIN_PASSWORD: ${ADMIN_PASSWORD}
SEAFILE_SERVER_HOSTNAME: ${SEAFILE_HOSTNAME}
SEAFILE_SERVER_PROTOCOL: https
JWT_PRIVATE_KEY: ${JWT_PRIVATE_KEY}
ENABLE_SEADOC: "false"
depends_on:
db:
condition: service_healthy
memcached:
condition: service_started
Las variables que empiezan por INIT_ solo se usan en el primer arranque, cuando Seafile crea las bases de datos y la cuenta de administrador. Cambiarlas después no tiene efecto.
Notase publica el puerto en
127.0.0.1a propósito. Docker añade sus propias reglas de iptables y un puerto publicado en todas las interfaces quedaría expuesto aunque UFW lo bloquee.
Paso 3: Arrancar Seafile
Descarga las imágenes y levanta los contenedores:
cd /opt/seafile
sudo docker compose up -d
El primer arranque tarda uno o dos minutos porque Seafile inicializa las bases de datos. Sigue los logs hasta que el servidor indique que ha arrancado:
sudo docker compose logs -f seafile
seafile | Seafile server started
seafile | Seahub is started
seafile | Done.
Pulsa Ctrl+C para salir de los logs. Comprueba que los tres contenedores están en marcha y que la base de datos está sana:
sudo docker compose ps
NAME IMAGE STATUS
seafile seafileltd/seafile-mc:12.0-latest Up 2 minutes
seafile-memcached memcached:1.6.29 Up 2 minutes
seafile-mysql mariadb:10.11 Up 2 minutes (healthy)
Por último, confirma que Seahub responde en el puerto local:
curl -I http://127.0.0.1:8000
HTTP/1.1 302 Found
Location: /accounts/login/
La redirección a la página de inicio de sesión indica que la aplicación funciona.
Paso 4: Configurar Nginx como proxy inverso
Instala Nginx y Certbot con su plugin para Nginx:
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx
Crea el bloque de servidor para Seafile:
sudo nano /etc/nginx/sites-available/seafile
server {
listen 80;
listen [::]:80;
server_name seafile.tu_dominio.com;
# Sin límite de tamaño: Seafile trocea las subidas grandes
client_max_body_size 0;
proxy_request_buffering off;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 1200s;
proxy_send_timeout 1200s;
}
}
Activa el sitio, comprueba la sintaxis y recarga Nginx:
sudo ln -s /etc/nginx/sites-available/seafile /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Si usas UFW, permite SSH y el tráfico web:
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
Paso 5: Obtener el certificado TLS
Certbot obtiene el certificado de Let's Encrypt y modifica el bloque de servidor para servir HTTPS y redirigir HTTP:
sudo certbot --nginx -d seafile.tu_dominio.com
Cuando termine, verifica que el sitio responde por HTTPS:
curl -I https://seafile.tu_dominio.com
HTTP/2 302
location: /accounts/login/
El paquete de Certbot instala un temporizador de systemd que renueva el certificado automáticamente. Puedes probar la renovación con sudo certbot renew --dry-run.
Paso 6: Primer inicio de sesión y administración
Abre https://seafile.tu_dominio.com en el navegador e inicia sesión con el correo y la contraseña que pusiste en ADMIN_EMAIL y ADMIN_PASSWORD. Una vez dentro:
- Cambia la contraseña desde el menú de tu avatar si la definiste de forma provisional.
- Abre Administración del sistema (menú del avatar) para crear usuarios, grupos y cuotas de almacenamiento. La cuota por defecto se define en Configuración.
- En la página principal, crea una biblioteca y sube un archivo para comprobar que las subidas funcionan a través del proxy.
Al crear una biblioteca puedes marcarla como cifrada. Los archivos se cifran en el cliente con la contraseña de la biblioteca, por lo que el servidor no puede leer su contenido. Esa contraseña no se puede recuperar: si se pierde, los datos también. Las bibliotecas cifradas no admiten vista previa de archivos en el navegador ni acceso por WebDAV.
Desde la página de descargas de Seafile puedes instalar el cliente de escritorio (Windows, macOS y Linux) o las aplicaciones móviles. Al configurarlos, usa https://seafile.tu_dominio.com como dirección del servidor.
Paso 7: Activar WebDAV (opcional)
WebDAV permite montar tus bibliotecas no cifradas como una unidad de red desde clientes que no tienen app de Seafile. Viene desactivado. Edita su configuración, que se encuentra en el volumen de datos:
sudo nano /opt/seafile/data/seafile/conf/seafdav.conf
Deja la sección así:
[WEBDAV]
enabled = true
port = 8080
share_name = /seafdav
Reinicia el contenedor de Seafile para aplicar el cambio:
cd /opt/seafile
sudo docker compose restart seafile
El Nginx interno del contenedor ya enruta /seafdav al servicio WebDAV, así que no hace falta tocar el Nginx del host. Comprueba que responde con tus credenciales (debe devolver 207 Multi-Status):
curl -s -o /dev/null -w '%{http_code}\n' -X PROPFIND -H 'Depth: 1' -u 'admin@tu_dominio.com' https://seafile.tu_dominio.com/seafdav/
207
La URL para los clientes WebDAV es https://seafile.tu_dominio.com/seafdav/, con tu correo de Seafile como usuario.
Paso 8: Copias de seguridad
Todo el estado de Seafile está en /opt/seafile: las bases de datos de MariaDB y el directorio data, que contiene los bloques de los archivos. Para una copia coherente, vuelca primero las bases de datos:
cd /opt/seafile
source <(sudo grep DB_ROOT_PASSWORD .env)
for db in ccnet_db seafile_db seahub_db; do
sudo docker compose exec -T db mariadb-dump -uroot -p"$DB_ROOT_PASSWORD" --opt "$db" | sudo tee "/opt/seafile/$db.sql" > /dev/null
done
Después copia /opt/seafile/data y los tres archivos .sql a otro servidor o almacenamiento externo con la herramienta que uses habitualmente (por ejemplo rsync o restic). Comprueba que los volcados no están vacíos con ls -lh /opt/seafile/*.sql.
Solución de problemas
Error 403 "CSRF verification failed" al iniciar sesión. Suele ocurrir cuando la URL con la que accedes no coincide con la que Seafile conoce. Edita /opt/seafile/data/seafile/conf/seahub_settings.py, añade la línea CSRF_TRUSTED_ORIGINS = ['https://seafile.tu_dominio.com'] y reinicia con sudo docker compose restart seafile.
Las subidas o descargas fallan pero la web carga. Seafile construye las URL de subida a partir de SEAFILE_SERVER_HOSTNAME y SEAFILE_SERVER_PROTOCOL. Comprueba que en .env y en docker-compose.yml coinciden con el dominio y el esquema (https) reales y recrea el contenedor con sudo docker compose up -d. Si el navegador muestra un error de tamaño, revisa que client_max_body_size 0; sigue en el bloque que Certbot creó para el puerto 443.
El contenedor de Seafile no arranca. Consulta los logs de la aplicación y de la base de datos:
sudo docker compose logs --tail 50 seafile
sudo docker compose logs --tail 20 db
Un error de acceso a MariaDB en el primer arranque indica normalmente que DB_ROOT_PASSWORD no coincide con la contraseña con la que se inicializó ./mysql. En una instalación nueva sin datos, puedes parar los contenedores, borrar /opt/seafile/mysql y /opt/seafile/data y volver a arrancar.
Conclusión
Tienes Seafile Community Edition funcionando en Docker, publicado con HTTPS mediante Nginx y con WebDAV disponible para clientes genéricos. Como siguientes pasos, configura el envío de correo en seahub_settings.py para que funcionen las invitaciones y el restablecimiento de contraseñas, programa las copias de seguridad del Paso 8 con un temporizador de systemd y revisa las notas de versión antes de cambiar la etiqueta de la imagen a una versión mayor.
