• Dec. 2, 2025, 9:22 a.m.

    Context

    Running Seafile alongside YunoHost can be tricky because YunoHost's Nginx already claims ports 80 and 443. To avoid conflicts, we deploy Seafile in a Docker container mapped to a custom port (e.g., 8001) and use YunoHost/Nginx as a reverse proxy.

    1. Preparation

    Create a dedicated directory to keep the project organised.

    mkdir -p /opt/seafile-data
    cd /opt/seafile-data
    

    2. Docker Compose Configuration

    Create the docker-compose.yml file.

    Crucial Adjustments for YunoHost:

    • Port Mapping: Changed from 80:80 to 8001:80.
    • Database Passwords: Ensure MYSQL_ROOT_PASSWORD (in the db service) matches DB_ROOT_PASSWD (in the seafile service).
    services:
      db:
        image: mariadb:10.11
        container_name: seafile-mysql
        environment:
          - MYSQL_ROOT_PASSWORD=your_secure_password  # MUST match DB_ROOT_PASSWD below
          - MYSQL_LOG_CONSOLE=true
        volumes:
          - /opt/seafile-mysql/db:/var/lib/mysql
        networks:
          - seafile-net
    
      memcached:
        image: memcached:1.6.18
        container_name: seafile-memcached
        entrypoint: memcached -m 256
        networks:
          - seafile-net
    
      seafile:
        image: seafileltd/seafile-mc:11.0-latest
        container_name: seafile
        ports:
          - "8001:80"  # Mapped to 8001 to avoid YunoHost conflict
        volumes:
          - /opt/seafile-data/seafile:/shared
        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@example.com
          - SEAFILE_ADMIN_PASSWORD=asecret
          - SEAFILE_SERVER_LETSENCRYPT=false   # YunoHost handles SSL
          - SEAFILE_SERVER_HOSTNAME=seafile.yourdomain.com
        depends_on:
          - db
          - memcached
        networks:
          - seafile-net
    
    networks:
      seafile-net:
    

    3. Handling the "Access Denied" Database Error

    If you start the container, change the password in the YAML file, and restart it, you might see this error in the logs:

    (1045, "Access denied for user 'root'...")

    This happens because the MariaDB volume persists the old password. To fix this on a fresh install:

    1. Stop the containers: docker compose down
    2. Delete the database volume data: rm -rf /opt/seafile-mysql/db/*
    3. Start fresh: docker compose up -d

    4. Fixing the CSRF Verification Failed (403) Error

    Upon logging in, you might receive a Forbidden (403): CSRF verification failed error. This occurs because Seafile does not trust the origin domain when behind a reverse proxy.

    The Fix:

    1. Edit the Seahub settings file on the host:
      bash nano /opt/seafile-data/seafile/seafile/conf/seahub_settings.py
    2. Add your domain to the trusted list at the bottom of the file:
      python CSRF_TRUSTED_ORIGINS = ["https://seafile.yourdomain.com"]
    3. Ensure the service URLs are correct in the same file:
      python SERVICE_URL = "https://seafile.yourdomain.com" FILE_SERVER_ROOT = "https://seafile.yourdomain.com/seafhttp"
    4. Restart the container:
      bash docker compose restart seafile

    5. Final YunoHost Configuration

    To make the site accessible publicly via HTTPS:

    1. Create a "Redirect" app in YunoHost (or a custom Nginx conf).
    2. Point the domain (e.g., seafile.yourdomain.com) to the local Docker port: http://127.0.0.1:8001.
    3. Install a Let's Encrypt certificate via the YunoHost admin panel.

    Notes: Always remember to back up /opt/seafile-data and /opt/seafile-mysql when performing server maintenance.