Skip to main content

Deploying a Second Seafile Instance on YunoHost (Docker Compose)

Context

I recently needed to deploy a second instance of Seafile on my new primary domain (obulou.org) while keeping my old instance (obulou.my) running on the same VPS.

Running two instances of the same service on one server can be tricky. You have to be careful with port conflicts, volume mapping, and ensuring YunoHost's Nginx reverse proxy knows exactly where to look.

During this process, I encountered a "boot loop" where the Seafile container kept restarting, and a "502 Bad Gateway" error. This guide documents the correct deployment path and the fixes for those specific errors.

Prerequisites

  • OS: Debian (YunoHost installed)
  • Docker: Installed via YunoHost or manually.
  • Domain: A sub-domain configured in YunoHost (e.g., seafile.obulou.org).

1. Preparation: Isolate the Environment

Since I already had a Seafile instance using /opt/seafile-data, I needed a fresh directory to prevent data corruption.

# Create a new directory for the second instance
mkdir -p /opt/seafile-data-org
cd /opt/seafile-data-org

2. The Docker Compose Configuration

The critical part here is changing the external port. My old Seafile uses port 8001. For this new one, I mapped it to 8002.

File: docker-compose.yml

services:
  db:
    image: mariadb:10.11
    container_name: seafile-mysql-org  # Unique name to avoid conflict
    environment:
      - MYSQL_ROOT_PASSWORD=your_secure_password
      - MYSQL_LOG_CONSOLE=true
    volumes:
      - /opt/seafile-data-org/db:/var/lib/mysql # Unique path
    networks:
      - seafile-net-org

  memcached:
    image: memcached:1.6.18
    container_name: seafile-memcached-org
    entrypoint: memcached -m 256
    networks:
      - seafile-net-org

  seafile:
    image: seafileltd/seafile-mc:11.0-latest
    container_name: seafile-org
    ports:
      - "8002:80"  # Mapped to 8002. Internal port must remain 80.
    volumes:
      - /opt/seafile-data-org/seafile:/shared # Unique path
    environment:
      - DB_HOST=db
      - DB_ROOT_PASSWD=your_secure_password # Must match MYSQL_ROOT_PASSWORD above
      - TIME_ZONE=Asia/Kuala_Lumpur
      - SEAFILE_ADMIN_EMAIL=me@obulou.org
      - SEAFILE_ADMIN_PASSWORD=your_admin_password
      - SEAFILE_SERVER_LETSENCRYPT=false   # YunoHost handles SSL
      - SEAFILE_SERVER_HOSTNAME=seafile.obulou.org
    depends_on:
      - db
      - memcached
    networks:
      - seafile-net-org

networks:
  seafile-net-org:

Deploy it:

docker compose up -d


3. The "Boot Loop" & Configuration Fixes

This is where I got stuck. After deployment, the container might start restarting endlessly, or Nginx might show 502 Bad Gateway.

This happens because Seafile's Python configuration file (seahub_settings.py) is extremely sensitive to syntax errors. A missing comma or quote will crash the server before it even logs an error.

A. The "Safe Append" Method

Instead of using nano to edit the settings (where typos are easy), use the cat command to append the necessary CSRF and Email settings safely.

Fixing "CSRF Verification Failed" and Adding SMTP:

Run this command block in your terminal (replace email details with your own):

cat <<EOF >> /opt/seafile-data-org/seafile/seafile/conf/seahub_settings.py

# --- Custom Settings ---
# Fix CSRF error behind reverse proxy
CSRF_TRUSTED_ORIGINS = ["https://seafile.obulou.org"]
SERVICE_URL = "https://seafile.obulou.org"
FILE_SERVER_ROOT = "https://seafile.obulou.org/seafhttp"

# SMTP / Email Configuration
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com' # Or your provider
EMAIL_HOST_USER = 'me@obulou.org'
EMAIL_HOST_PASSWORD = 'your_app_password'
EMAIL_PORT = 587
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
SERVER_EMAIL = EMAIL_HOST_USER
EOF

Apply the fix:

docker restart seafile-org


4. Enabling "Infinite" Uploads

By default, Nginx limits uploads to 1MB, and Seafile has its own limits. To allow large file syncs:

A. Seafile Internal Config

Edit /opt/seafile-data-org/seafile/seafile/conf/seafile.conf:

[fileserver]
max_upload_size = 0

B. Nginx (YunoHost) Config

If you use the YunoHost Redirect App, the config is usually in /etc/nginx/conf.d/yourdomain.d/redirect.conf.

Add these lines inside the location / block:

location / {
    # ... existing proxy settings ...
    
    # Disable body size checking
    client_max_body_size 0;
    
    # Optimise for large uploads
    proxy_request_buffering off;
    proxy_read_timeout 3600s;
    proxy_send_timeout 3600s;
}

Reload Nginx: systemctl reload nginx.


5. Troubleshooting Cheat Sheet

Symptom Cause Fix
502 Bad Gateway Seahub container is crashing or restarting. Check docker ps. If it restarts every few seconds, you likely have a syntax error in seahub_settings.py.
CSRF Verification Failed Seafile doesn't trust the YunoHost reverse proxy domain. Add CSRF_TRUSTED_ORIGINS to seahub_settings.py.
"Failed to send email" SMTP settings missing or incorrect password. Use the "Safe Append" method above to add SMTP details. Note: Gmail requires an App Password.
Uploads fail instantly Nginx client_max_body_size is too low. Set client_max_body_size 0; in Nginx config.

Lessons Learnt

  • Check the Logs: If the container keeps restarting, docker logs might be generic. Check the internal logs at /opt/seafile-data-org/seafile/logs/seahub.log. If that file is missing, the crash is happening during config loading (syntax error).
  • Naming Matters: Always suffix containers (e.g., -org) when running multiple instances to prevent Docker naming conflicts.
  • Syntax Sensitivity: Python config files do not forgive missing commas!