What is Seafile

Seafile is an open-source, cross-platform file-hosting software system. Files are stored on a central server and can be synchronized with personal computers and mobile devices through apps. Files on the Seafile server can also be accessed directly via the server's web interface. Seafile's functionality is similar to other popular file hosting services such as Dropbox and Google Drive. The primary difference between Seafile and Dropbox/Google Drive is that Seafile is a self-hosted file sharing solution for private cloud applications. In private clouds, storage space and client connection limits are determined exclusively by the users' own infrastructure and settings rather than the terms and conditions of a cloud service provider. Additionally, organizations, whose data privacy policies bar them from using public cloud services can draw on Seafile to build a file sharing system of their own.

that's exactly what someone like me wants. Full control and self-hosted!

traefik configuration (Seafile Version 12)

Seafile has slightly modified the structure of its docker compose. The Documentation says nothing about traefik. Upgrade howto In version 12, the Docker Compose root looks like this:

RWill_2025-02-13%2008-42-22

I've already said that I'm a traefik fan. That's why I certainly don't need caddy. In order to be able to use Seafile without caddy, I rebuild the Compose files accordingly. First I throw the caddy.yml out of the .env

# .env for Seafile modified by ♞Raffael.Willems
COMPOSE_FILE='seafile-server.yml,seadoc.yml' 
COMPOSE_PATH_SEPARATOR=','

SEAFILE_IMAGE=seafileltd/seafile-mc:12.0-latest
SEAFILE_DB_IMAGE=mariadb:10.11
SEAFILE_MEMCACHED_IMAGE=memcached:1.6.29
SEAFILE_VOLUME=/srv/seafile/seafile-data
SEAFILE_MYSQL_VOLUME=/srv/seafile/seafile-mysql/db
SEAFILE_MYSQL_DB_HOST=db
INIT_SEAFILE_MYSQL_ROOT_PASSWORD=ROOT_PASSWORD
SEAFILE_MYSQL_DB_USER=seafile
SEAFILE_MYSQL_DB_PASSWORD=PASSWORD
TIME_ZONE=Etc/UTC
JWT_PRIVATE_KEY=
SEAFILE_SERVER_HOSTNAME=seafile.example.com
SEAFILE_SERVER_PROTOCOL=https
INIT_SEAFILE_ADMIN_EMAIL=me@example.com
INIT_SEAFILE_ADMIN_PASSWORD=asecret
SEADOC_IMAGE=seafileltd/sdoc-server:1.0-latest
SEADOC_VOLUME=/opt/seadoc-data
ENABLE_SEADOC=true
SEADOC_SERVER_URL=https://seafile.willifix.net/sdoc-server
NOTIFICATION_SERVER_IMAGE=seafileltd/notification-server:12.0-latest
NOTIFICATION_SERVER_VOLUME=/opt/notification-data

We then need to add a few labels to seafile-server.yml. We also need to remove the existing caddy configuration here.

# seafile-server compose modified by ♞Raffael.Willems
services:
  db:
    image: ${SEAFILE_DB_IMAGE:-mariadb:10.11}
    container_name: seafile-mysql
    environment:
      - MYSQL_ROOT_PASSWORD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:-}
      - MYSQL_LOG_CONSOLE=true
      - MARIADB_AUTO_UPGRADE=1
    volumes:
      - "${SEAFILE_MYSQL_VOLUME:-/opt/seafile-mysql/db}:/var/lib/mysql"
    networks:
      - seafile-net
    healthcheck:
      test:
        [
          "CMD",
          "/usr/local/bin/healthcheck.sh",
          "--connect",
          "--mariadbupgrade",
          "--innodb_initialized",
        ]
      interval: 20s
      start_period: 30s
      timeout: 5s
      retries: 10
  memcached:
    image: ${SEAFILE_MEMCACHED_IMAGE:-memcached:1.6.29}
    container_name: seafile-memcached
    entrypoint: memcached -m 256
    networks:
      - seafile-net
  seafile:
    image: ${SEAFILE_IMAGE:-seafileltd/seafile-mc:12.0-latest}
    container_name: seafile
    volumes:
      - ${SEAFILE_VOLUME:-/opt/seafile-data}:/shared
    environment:
      - DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
      - DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306}
      - DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
      - DB_ROOT_PASSWD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:-}
      - DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
      - SEAFILE_MYSQL_DB_CCNET_DB_NAME=${SEAFILE_MYSQL_DB_CCNET_DB_NAME:-ccnet_db}
      - SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=${SEAFILE_MYSQL_DB_SEAFILE_DB_NAME:-seafile_db}
      - SEAFILE_MYSQL_DB_SEAHUB_DB_NAME=${SEAFILE_MYSQL_DB_SEAHUB_DB_NAME:-seahub_db}
      - TIME_ZONE=${TIME_ZONE:-Etc/UTC}
      - INIT_SEAFILE_ADMIN_EMAIL=${INIT_SEAFILE_ADMIN_EMAIL:-me@example.com}
      - INIT_SEAFILE_ADMIN_PASSWORD=${INIT_SEAFILE_ADMIN_PASSWORD:-asecret}
      - SEAFILE_SERVER_HOSTNAME=${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      - SEAFILE_SERVER_PROTOCOL=${SEAFILE_SERVER_PROTOCOL:-http}
      - SITE_ROOT=${SITE_ROOT:-/}
      - NON_ROOT=${NON_ROOT:-false}
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - SEAFILE_LOG_TO_STDOUT=${SEAFILE_LOG_TO_STDOUT:-false}
      - ENABLE_SEADOC=${ENABLE_SEADOC:-true}
      - SEADOC_SERVER_URL=${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}/sdoc-server
    labels:
     - "traefik.enable=true"
     - "traefik.http.routers.seafile.tls.certresolver=LEwillifixnet"
     - "traefik.http.routers.seafile.tls=true"
     - "traefik.http.routers.seafile.rule=Host(`seafile.willifix.net`)"
     - "traefik.http.routers.seafile.entrypoints=websecure"
     - "traefik.http.routers.seafile.service=seafile"
     - "traefik.http.routers.seafile.middlewares=rafficontact@docker"
     - "traefik.http.services.seafile.loadbalancer.server.port=80"
    depends_on:
      db:
        condition: service_healthy
      memcached:
        condition: service_started
    networks:
      - seafile-net
      - public
networks:
  seafile-net:
    name: seafile-net
  public:
    external: true
    name: public

Finally, we have to convert the seadoc.yml to traefik:

# seadoc compose modified by ♞Raffael.Willems
services:
  seadoc:
    image: ${SEADOC_IMAGE:-seafileltd/sdoc-server:1.0-latest}
    container_name: seadoc
    volumes:
      - ${SEADOC_VOLUME:-/srv/seafile/seadoc-data/}:/shared
    environment:
      - DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
      - DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306}
      - DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
      - DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
      - DB_NAME=${SEADOC_MYSQL_DB_NAME:-seahub_db}
      - TIME_ZONE=${TIME_ZONE:-Etc/UTC}
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - NON_ROOT=${NON_ROOT:-false}
      - SEAHUB_SERVICE_URL=${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.seafhttp.tls.certresolver=LEwillifixnet"
      - "traefik.http.routers.seafhttp.tls=true"
      - "traefik.http.routers.seafhttp.rule=Host(`seafile.willifix.net`) && PathPrefix(`/sdoc-server`) || PathPrefix(`/socket.io`)"
      - "traefik.http.routers.seafhttp.entrypoints=websecure"
      - "traefik.http.services.seafhttp.loadbalancer.server.port=80"
      - "traefik.http.routers.seafhttp.service=seafhttp"
      - "traefik.http.routers.seafhttp.middlewares=sf-strippath"
      - "traefik.http.middlewares.sf-strippath.stripprefix.prefixes=/sdoc-server"
    depends_on:
      db:
        condition: service_healthy
    networks:
      - seafile-net
      - public
networks:
  seafile-net:
    name: seafile-net
  public:
    external: true
    name: public

Previous Post