nginx reverse proxy and seafile both on separate docker containers reddit / selfhosted ---------------------------------------------------------------------- mhmert · 2023-11-06 21:44 I have two docker containers of which I'll show their docker-compose files below. I'm trying to setup an nginx reverse proxy to the seafile container. However, when accessing the domain name I'm not getting through to the seafile webadmin page. ​ Based on the default [mydomain.com](https://mydomain.com) I know that the certificates are operational. I got the ip address in "$ docker inspect seafile-arm-docker- seafile-1" and took the ip address corresponding to the "IPAddress" that I found in there ([192.168.16.3](https://192.168.16.3)). Unfortunately, I do get an 504 error. ​ I'm using, for seafile: [https://github.com/ChatDeBlofeld/seafile-arm-docker- base](https://github.com/ChatDeBlofeld/seafile-arm-docker-base) docker-compose.yml `version: '3'` `services:` `db:` `image: linuxserver/mariadb` `environment:` `- PUID=$PUID` `- PGID=$PGID` `- TZ=$TZ` `volumes:` `- ${DATABASE_DIR}:/config` ​ `seafile:` `depends_on:` `- db` `image: ${SEAFILE_IMAGE}` `restart: always` `environment:` `- PUID=${PGID-}` `- PGID=${PUID-}` `- TZ=${TZ-}` `- SQLITE=${SQLITE-}` `- SERVER_IP=${HOST-}` `- PORT=${PORT-}` `- USE_HTTPS=${USE_HTTPS-}` `- SEAFILE_ADMIN_EMAIL=${SEAFILE_ADMIN_EMAIL-}` `- SEAFILE_ADMIN_PASSWORD=${SEAFILE_ADMIN_PASSWORD-}` `- MYSQL_HOST=${MYSQL_HOST:-db}` `- MYSQL_PORT=${MYSQL_PORT-}` `- USE_EXISTING_DB=${USE_EXISTING_DB-}` `- MYSQL_USER=${MYSQL_USER-}` `- MYSQL_USER_PASSWD=${MYSQL_USER_PASSWD-}` `- MYSQL_USER_HOST=${MYSQL_USER_HOST-}` `- MYSQL_ROOT_PASSWD=${MYSQL_ROOT_PASSWD-}` `- CCNET_DB=${CCNET_DB-}` `- SEAFILE_DB=${SEAFILE_DB-}` `- SEAHUB_DB=${SEAHUB_DB-}` ​ `volumes:` `- media:/shared/media` `- ${SEAFILE_CONF_DIR}:/shared/conf` `- ${SEAFILE_LOGS_DIR}:/shared/logs` `- ${SEAFILE_DATA_DIR}:/shared/seafile-data` `- ${SEAFILE_SEAHUB_DIR}:/shared/seahub-data` ​ `volumes:` `media:` `#~conf:` `#~logs:` `#~data:` `#~seahub:` `#~db:` ​ ​ Reverse proxy: `version: "3.3"` `services:` `nginx:` `container_name: 'nginx-service'` `build:` `context: .` `dockerfile: docker/nginx.Dockerfile` `ports:` `- 80:80` `- 443:443` `volumes:` `- ./config:/config` `- /etc/letsencrypt:/etc/letsencrypt:ro` `- /tmp/acme_challenge:/tmp/acme_challenge` `networks:` `- nginx_reverse_proxy` `restart: always` ​ `networks:` `nginx_reverse_proxy:` `driver: bridge` ​ config.conf: `####` [`storage.`](https://storage.haarman.info)`mydomain.com` `server {` `listen 80;` `listen [::]:80;` `server_name` [`storage.`](https://storage.haarman.info)`mydomain.com;` `location / {` `return 301 https://$host$request_uri;` `} location ~ /.well-known/acme-challenge {` `allow all;` `root /tmp/acme_challenge;` `}` `}` ​ `server {` `listen 443 ssl;` `listen [::]:443 ssl http2;` `server_name` [`storage.`](https://storage.haarman.info)`mydomain.com;` `ssl_certificate /etc/letsencrypt/live/storage.mydomain.com/fullchain.pem;` `ssl_certificate_key /etc/letsencrypt/live/storage.mydomain.com/privkey.pem;` `location / {` `proxy_pass http://`[`192.168.16.3`](https://192.168.16.3)`: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-Host $server_name;` `proxy_set_header X-Forwarded-Proto https;` ​ `access_log /var/log/nginx/seahub.access.log;` `error_log /var/log/nginx/seahub.error.log;` ​ `proxy_read_timeout 1200s;` ​ `# used for view/edit office file via Office Online Server` `#` [`https://manual.seafile.com/deploy/deploy_with_nginx.html`](https ://manual.seafile.com/deploy/deploy_with_nginx.html) `# Nginx settings client_max_body_size is by default 1M. Uploading a file bigger than this limit will give you an error` `# message HTTP error code 413 ("Request Entity Too Large").` `# You should use 0 to disable this feature or write the same value than for the parameter` `# max_upload_size in section [fileserver] of seafile.conf. Client uploads are only partly effected by this limit.` `# With a limit of 100 MiB they can safely upload files of any size.` `client_max_body_size 0;` `}` ​ `location /media {` `root /opt/seafile/seafile-server-latest/seahub;` `}` ​ `location /seafdav {` `#` [`https://manual.seafile.com/extension/webdav.html`](https://manua l.seafile.com/extension/webdav.html) `proxy_pass http://`[`192.168.16.3`](https://192.168.16.3)`:8080;` `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-Host $server_name;` `proxy_set_header X-Forwarded-Proto https;` `proxy_http_version 1.1;` `proxy_connect_timeout 36000s;` `proxy_read_timeout 36000s;` `proxy_send_timeout 36000s;` `send_timeout 36000s;` `client_max_body_size 0;` ​ `# if you want to support file uploads larger than 4GB, we suggest to install Nginx version >= 1.8.0 and` `# add the following option to Nginx config file (set to "off") -` [` https://manual.seafile.com/deploy/deploy_with_nginx.html`](https://man ual.seafile.com/deploy/deploy_with_nginx.html) `proxy_request_buffering off;` `access_log /var/log/nginx/seafdav.access.log;` `error_log /var/log/nginx/seafdav.error.log;` `}` `location /seafhttp {` `rewrite ^/seafhttp(.*)$ $1 break;` `proxy_pass http://seafile-arm-docker_default:8082;` `client_max_body_size 0;` `proxy_connect_timeout 36000s;` `proxy_read_timeout 36000s;` `proxy_send_timeout 36000s;` `send_timeout 36000s;` `# if you want to support file uploads larger than 4GB, we suggest to install Nginx version >= 1.8.0 and` `# add the following option to Nginx config file (set to "off") -` [` https://manual.seafile.com/deploy/deploy_with_nginx.html`](https://man ual.seafile.com/deploy/deploy_with_nginx.html) `proxy_request_buffering off;` `}` ​ `location /seafmedia {` `rewrite ^/seafmedia(.*)$ /media$1 break;` `root /opt/seafile/seafile-server-latest/seahub;` `}` `}` ​ ​ `#### default` `server {` `listen 80;` `listen [::]:80;` `server_name mydomain.com;` `location / {` `return 301 https://$host$request_uri;` `}` ​ `location ~ /.well-known/acme-challenge {` `allow all;` `root /tmp/acme_challenge;` `}` `}` `server {` `listen 443 ssl;` `listen [::]:443 ssl http2;` `server_name mydomain.com;` `ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem;` `ssl_certificate_key /etc/letsencrypt/live/mydomain.com/privkey.pem;` `}` ​ ​ Bonus question: I see linuxserver/mariadb running as well after running docker ps. Is that port 3306 closed for access from outside the container? So it will not interfere with other sql containers that I might have running on that port? ​ ​ ---------------------------------------------------------------------- fyijesuisunchat · 2023-11-07 02:44 Nginx and Seafile don’t share a docker bridge network in your configuration (Seafile will generate a default bridge network as it’s not defined specifically, while Nginx will be on nginx\_reverse\_proxy), so they can only see each other via your host’s local IP and their respective port – to put it simply, whatever address you’re using to access Seafile without the reverse proxy is what you need to pass to the reverse proxy. You could also attach them to the same docker bridge network so they can access each other by container name (e.g. http://seafile:8000). ---------------------------------------------------------------------- mhmert · 2023-11-07 09:57 That worked like a charm. Such an easy fix, thanks! Now, however, my css files are not loading. nginx log: nginx-service | 2023/11/07 09:36:12 [error] 22#22: *2 open() "/shared/media/img/seafile-logo.png" failed (2: No such file or directory), client: 192.168.50.1, server: storage.mydomain.com, request: "GET /media/img/seafile-logo.png HTTP/1.1", host: "storage.mydomain.com", referrer: "https://storage.mydomain.com/accounts/login/?next=/" and when I take a look in the folders of my seafile container I see that /shared/media/img/seafile-logo.png does exist. ​ seafile.conf file: include mime.types; server { listen 80; listen [::]:80; server_name storage.mydomain.com; rewrite ^ https://$http_host$request_uri? permanent; # force redirect http to https server_tokens off; } server { listen 443; listen [::]:443 ssl http2; server_name storage.mydomain.com; # all ssl related config moved to ssl.conf ssl_certificate /etc/letsencrypt/live/storage..mydomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/storage..mydomain.com/privkey.pem; server_tokens off; location / { proxy_pass http://seafile: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-Host $server_name; proxy_set_header X-Forwarded-Proto https; proxy_read_timeout 1200s; client_max_body_size 0; } location /seafhttp { rewrite ^/seafhttp(.*)$ $1 break; proxy_pass http://seafile:8082; client_max_body_size 0; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_connect_timeout 36000s; proxy_read_timeout 36000s; proxy_send_timeout 36000s; send_timeout 36000s; } location /media { root /shared; } } my nginx reverse proxy docker-compose.yml: version: "3.3" services: nginx: container_name: 'nginx-service' build: context: . dockerfile: docker/nginx.Dockerfile ports: - 80:80 - 443:443 volumes: - ./config:/config - /etc/letsencrypt:/etc/letsencrypt:ro - /tmp/acme_challenge:/tmp/acme_challenge networks: - nginx_reverse_proxy restart: always networks: nginx_reverse_proxy: driver: bridge my seafile docker compose file: version: '3' services: db: image: linuxserver/mariadb environment: - PUID=${PUID} - PGID=${PGID} - TZ=$TZ volumes: - ${DATABASE_DIR}:/config networks: - seafile seafile: depends_on: - db image: ${SEAFILE_IMAGE} restart: always ports: - 8000:8000/tcp - 8080:8080/tcp - 8082:8082/tcp - 8083:8083/tcp environment: - PUID=${PGID-} - PGID=${PUID-} - TZ=${TZ-} - SQLITE=${SQLITE-} - SERVER_IP=${HOST-} - PORT=${PORT-} - USE_HTTPS=${USE_HTTPS-} - SEAFILE_ADMIN_EMAIL=${SEAFILE_ADMIN_EMAIL-} - SEAFILE_ADMIN_PASSWORD=${SEAFILE_ADMIN_PASSWORD-} - MYSQL_HOST=${MYSQL_HOST:-db} - MYSQL_PORT=${MYSQL_PORT-} - USE_EXISTING_DB=${USE_EXISTING_DB-} - MYSQL_USER=${MYSQL_USER-} - MYSQL_USER_PASSWD=${MYSQL_USER_PASSWD-} - MYSQL_USER_HOST=${MYSQL_USER_HOST-} - MYSQL_ROOT_PASSWD=${MYSQL_ROOT_PASSWD-} - CCNET_DB=${CCNET_DB-} - SEAFILE_DB=${SEAFILE_DB-} - SEAHUB_DB=${SEAHUB_DB-} volumes: - media:/shared/media - ${SEAFILE_CONF_DIR}:/shared/conf - ${SEAFILE_LOGS_DIR}:/shared/logs - ${SEAFILE_DATA_DIR}:/shared/seafile-data - ${SEAFILE_SEAHUB_DIR}:/shared/seahub-data networks: - nginx_reverse_proxy - seafile volumes: media: #~conf: #~logs: #~data: #~seahub: #~db: networks: seafile: nginx_reverse_proxy: name: nginx_https_docker_nginx_reverse_proxy external: true ---------------------------------------------------------------------- fyijesuisunchat · 2023-11-07 14:51 Are they loading if you access Seafile without the reverse proxy? If so I think this location directive is likely the culprit: } location /media { root /shared; } Try deleting it. My understanding is that Seafile has an embedded proxy, which if you were trying to replace completely I think you'd need this for, but as you're just wanting to reverse proxy with your Nginx configuration this looks like it is interfering. ---------------------------------------------------------------------- mhmert · 2023-11-07 16:47 that solved my issue, thank you so much!