Seafile 12 (With Caddy) behind Nginx Proxy Manager

Have someone tried this? I can’t get to work SeaFile server 12 using manual. I was trying to turn off caddy and use only my Nginx Proxy Manager but i gave up. Now i’m struggling trying to use this Scenario
Internet > Nginx Proxy Manager > Caddy (Deployed with Seafile)

I have not done the reverse proxy in front of caddy, but I did put it behind the nginx reverse proxy I already have working without using caddy. So mine goes:

Internet > Nginx reverse proxy > Seafile and seahub in the seafile container.

There’s actually an nginx reverse proxy inside the seafile container, but I can’t figure out why, so I just bypassed it and talk directly to the seafile components. This was not just about cutting out that other nginx, but also let me keep the nginx config I had been using with my previous seafile version (without docker) with almost no changes.

When you tried without caddy what problem did you see?

I use traefik instead of caddy with docker compose:

Internet → Traefik → Seafile Container

which works great!

Please give us more details to allow us to help you.

Hi!
I’m currently having the same problem. For a few days I’ve been trying to get Seafile 12 (Community Edition) to work properly behind Nginx Proxy Manager. With no luck. I have reviewed the logs and found nothing that might be related to this problem. Without Nginx Proxy Manager everything works perfectly. Both http and https. If Seafile is behind NPM, the GUI in the browser starts, but I can’t download or upload any files through the browser. I can’t open the PDF preview. Seadoc also doesn’t work properly. Opening any document ends with the following message: “Load doc content error”. It’s similar with the Wiki function. You can’t open a previously created entry because it ends with an error: “AxiosError”. Desktop clients also do not work properly. Both Windows Drive Client and Windows Sync Client. There is simply no file synchronization even though the server appears connected. With the ios client it’s similar. I’m logged in, I can browse the server’s content but I can’t download or upload anything. I need Nginx Proxy Manager because I have other WWW services on this server. I managed to configure those without any problems.
Please help me figure out what is wrong with my configuration.
Damian

.env

COMPOSE_FILE='seafile-server.yml,caddy.yml,seadoc.yml,notification-server.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_CADDY_IMAGE=lucaslorentz/caddy-docker-proxy:2.9-alpine

SEAFILE_VOLUME=/opt/seafile-data
SEAFILE_MYSQL_VOLUME=/opt/seafile-mysql/db
SEAFILE_CADDY_VOLUME=/opt/seafile-caddy

SEAFILE_MYSQL_DB_HOST=db
INIT_SEAFILE_MYSQL_ROOT_PASSWORD=db_dev
SEAFILE_MYSQL_DB_USER=seafile
SEAFILE_MYSQL_DB_PASSWORD=###secret###

TIME_ZONE=Etc/UTC

JWT_PRIVATE_KEY=###secret###

SEAFILE_SERVER_HOSTNAME=seafile.example.com
SEAFILE_SERVER_PROTOCOL=http

INIT_SEAFILE_ADMIN_EMAIL=###secret###
INIT_SEAFILE_ADMIN_PASSWORD=###secret###


SEADOC_IMAGE=seafileltd/sdoc-server:1.0-latest
SEADOC_VOLUME=/opt/seadoc-data

ENABLE_SEADOC=true
SEADOC_SERVER_URL=http://seafile.example.com/sdoc-server


NOTIFICATION_SERVER_IMAGE=seafileltd/notification-server:12.0-latest
NOTIFICATION_SERVER_VOLUME=/opt/notification-data

seafile-server.yml

services:
  db:
    image: ${SEAFILE_DB_IMAGE:-mariadb:10.11}
    container_name: seafile-mysql
    restart: unless-stopped
    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
    restart: unless-stopped
    entrypoint: memcached -m 256
    networks:
      - seafile-net

  seafile:
    image: ${SEAFILE_IMAGE:-seafileltd/seafile-mc:12.0-latest}
    container_name: seafile
    restart: unless-stopped
    ports:
      - "8000:80"
    # - "443:443"
      - "8002:8080"
    volumes:
      - ${SEAFILE_VOLUME:-/opt/seafile-data}:/shared
      - /opt/seafile-fuse:/seafile-fuse
    privileged: true
    cap_add:
      - SYS_ADMIN
    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:-false}
      - SEADOC_SERVER_URL=${SEADOC_SERVER_URL:-http://seafile.example.com/sdoc-server}
    labels:
      caddy: ${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      caddy.reverse_proxy: "{{upstreams 80}}"
    depends_on:
      db:
        condition: service_healthy
      memcached:
        condition: service_started
    networks:
      - seafile-net

networks:
  seafile-net:
    name: seafile-net

caddy.yml

services:

  caddy:
    image: ${SEAFILE_CADDY_IMAGE:-lucaslorentz/caddy-docker-proxy:2.9-alpine}
    restart: unless-stopped
    container_name: seafile-caddy
    ports:
      - 80:80
      - 443:443
    environment:
      - CADDY_INGRESS_NETWORKS=seafile-net
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ${SEAFILE_CADDY_VOLUME:-/opt/seafile-caddy}:/data/caddy
    networks:
      - seafile-net
    healthcheck:
      test: ["CMD-SHELL", "curl --fail http://localhost:2019/metrics || exit 1"]
      start_period: 20s
      interval: 20s
      timeout: 5s
      retries: 3

networks:
  seafile-net:
    name: seafile-net

seadoc.yml

services:

  seadoc:
    image: ${SEADOC_IMAGE:-seafileltd/sdoc-server:1.0-latest}
    container_name: seadoc
    volumes:
      - ${SEADOC_VOLUME:-/opt/seadoc-data/}:/shared
    ports:
      - "8004:80"
    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:
      caddy: ${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      caddy.@ws.0_header: "Connection *Upgrade*"
      caddy.@ws.1_header: "Upgrade websocket"
      caddy.0_reverse_proxy: "@ws {{upstreams 80}}"
      caddy.1_handle_path: "/socket.io/*"
      caddy.1_handle_path.0_rewrite: "* /socket.io{uri}"
      caddy.1_handle_path.1_reverse_proxy: "{{upstreams 80}}"
      caddy.2_handle_path: "/sdoc-server/*"
      caddy.2_handle_path.0_rewrite: "* {uri}"
      caddy.2_handle_path.1_reverse_proxy: "{{upstreams 80}}"
    depends_on:
      db:
        condition: service_healthy
    networks:
      - seafile-net

networks:
  seafile-net:
    name: seafile-net

seafile.conf

[fileserver]
port = 8082

[database]
type = mysql
host = db
port = 3306
user = seafile
password = ###secret###
db_name = seafile_db
connection_charset = utf8

[notification]
enabled = true
host = notification-server
port = 8083
log_level = info
jwt_private_key = ###secret###


seahub_settings.py

# -*- coding: utf-8 -*-
SECRET_KEY = "###secret###"
SERVICE_URL = "http://docs.seafile.com/"

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'seahub_db',
        'USER': 'seafile',
        'PASSWORD': '###secret###',
        'HOST': 'db',
        'PORT': '3306',
        'OPTIONS': {'charset': 'utf8mb4'},
    }
}


CACHES = {
    'default': {
        'BACKEND': 'django_pylibmc.memcached.PyLibMCCache',
        'LOCATION': 'memcached:11211',
    },
    'locmem': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
    },
}
COMPRESS_CACHE_BACKEND = 'locmem'
TIME_ZONE = 'Etc/UTC'
FILE_SERVER_ROOT = "http://docs.seafile.com/seafhttp"

EMAIL_USE_TLS = True
EMAIL_HOST = '###secret###'
EMAIL_HOST_USER = '###secret###'
EMAIL_HOST_PASSWORD = '###secret###'
EMAIL_PORT = 587
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
SERVER_EMAIL = EMAIL_HOST_USER
CSRF_TRUSTED_ORIGINS = ["https://seafile.example.com"]

I am also having a similar problem. TBH I was struggling to get it to work in docker in the first place, and I’ve ended up installing it in a dedicated docker LXC in proxmox as it didn’t seem to like being in portainer or on the docker on my synology.

I have nginx proxy manager running for other services in my homelab and accepting internet connections, so it can do the HTTPS and the standard caddy with seafile won’t be able to as it’s not accepting internet traffic. so I’ve done my best to follow the documentation on the website for both installing and using other proxies. it’s working now, inthe sense that I put in the DNS name and I can log into seafile, but I can’t upload anything or do much more.

The older YT guides talk about setting the service URL but that’s no longer in GUI settings. I have edited seahub_settings.py file, restarted and set my URL in there and it’s not doing helping.

I’d like to use this as a way of saving files and being able to share them with friends and colleagues but I’m really strugglgin to know what to do next. What am I doing wrong?

I don’t know anything about Nginx Proxy Manager (I’ve never used it), but I would start with the suggestion that if you are going to use it, don’t also use Caddy. The more simple the setup, the easier it is going to be to troubleshoot and maintain (which is also why I wish seafile wasn’t joining the docker trend).

Here is a working nginx config from my old test setup. I made it more complicated for my production setup in a number of ways (authelia single sign on server, bypassed nginx in the container, added the notification server, etc.), but this setup was pretty simple. I don’t think it should matter, but I did switch to using the go fileserver so if you continue to have problems you might want to try doing that.

Also note that this config doesn’t have anything for seadoc. I could not find out what license seadoc is under, or any of the code, so I can’t run it in my environment.

server {
    listen       80;
    server_name  test-seafile.{{ primary_public_domain }};
    
    rewrite ^ https://$http_host$request_uri? permanent;    # Forced redirect from HTTP to HTTPS

    server_tokens off;      # Prevents the Nginx version from being displayed in the HTTP response header
}

server {
    listen 443 http2 ssl;

    include /etc/nginx/snippets/ssl.conf;

    server_name test-seafile.{{ primary_public_domain }};
    server_tokens off;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

# Replace robots.txt with my own
   include  /etc/nginx/snippets/override-robots-txt.conf;

    location / {
        proxy_pass         http://192.168.69.5:80 ;

	include /etc/nginx/snippets/proxy.conf;

        client_max_body_size 0;

	access_log      /var/log/nginx/seahub.access.log;
        error_log       /var/log/nginx/seahub.error.log;
    }

    location /seafhttp {
        rewrite ^/seafhttp(.*)$ $1 break;
        proxy_pass http://192.168.69.5:80;

	include /etc/nginx/snippets/proxy.conf;

        client_max_body_size 0;

	# supposed to fix large file uploads with web interface
	proxy_request_buffering off;

        access_log      /var/log/nginx/seafhttp.access.log;
        error_log       /var/log/nginx/seafhttp.error.log;
    }

}

If you still have trouble with uploading and downloading files, I would try switching to the go file server, and see if you get more useful error messages in the logs after that.
https://manual.seafile.com/12.0/config/seafile-conf/

Thanks for your reply. I’m not using caddy with this, having a reverse proxy feeding into a reverse proxy seemed silly and the seafile website has instructions on how to use your own reverse proxy, including settings to put in nginx which is great, except they don’t seem to actually work, or I’m having difficulty anyways.

Thanks for your examples, I’ll have a think about how they might fit in with the other instructions.

I think I’ve found a solution to my problems. I had custom local IP addresses set in my router. The problem was that in my local network I had IP addresses belonging to the public address pool. I changed the addressing of the home network to 192.168.0.1 and all my problems disappeared.

It sounds like you’re trying to set up a Seafile server using Nginx Proxy Manager in front of Caddy, but running into some challenges. To get this working, the key is to ensure that Nginx and Caddy aren’t conflicting. Since both can handle SSL termination, you should configure Nginx Proxy Manager to handle the external SSL and forward traffic to Caddy, which then routes it to the Seafile instance. Make sure that Nginx is set up correctly to forward HTTP or HTTPS traffic to Caddy’s internal server, and check that Caddy is configured to listen for requests on the correct port. Additionally, double-check your DNS and port forwarding settings to ensure that both Nginx and Caddy are accessible externally. If you’re still having trouble, simplifying the setup temporarily by testing each proxy server individually might help isolate the issue. Look through the logs for both Nginx and Caddy to identify where the problem might lie, as they can provide useful clues on misconfigurations. Hopefully, with a bit of tweaking, you’ll get everything running smoothly!