Behind a reverse proxy
The recommended layout for a production server: two domains, not a single published port. The proxy and S5W live on a shared docker network, and the proxy does TLS.
Layout
| Domain | Points to | What | Who needs it |
|---|---|---|---|
s5.example.com |
s5w:9090 |
API and file delivery | your applications and their users |
s5w.example.com |
s5w:9091 |
admin panel | administrators |
The panel talks to the API inside the container, so its domain needs no access to the API domain — and vice versa. If the panel is not needed from outside at all, you can skip the second domain and open it through an SSH tunnel.
What to configure in any case
- A shared network with the proxy
Attach the S5W container to the docker network the proxy runs in. Ports need not be published then: the proxy reaches the container by its service name (
s5w). - PUBLIC_BASE_URL — the API domain's address
PUBLIC_BASE_URL=https://s5.example.com. Without it, file addresses are built from the request, and in the panel from the panel’s domain — that is, they point to the wrong place. The panel shows a warning. - Request body size — at least 32 MiB
Details are below.
- TRUSTED_PROXIES — nothing needed by default
A proxy on a docker network falls into the private ranges and is already trusted: the real client address is taken from
X-Forwarded-For. Change it only if containers you do not trust share that network, see TRUSTED_PROXIES.
docker compose for S5W
services:
s5w:
image: flytachi/s5w:latest
environment:
ADMIN_LOGIN: admin
ADMIN_PASSWORD: ${S5W_ADMIN_PASSWORD}
PUBLIC_BASE_URL: https://s5.example.com # links point to the API domain
volumes:
- s5w_data:/var/lib/s5w
networks: [proxy]
stop_grace_period: 45s
restart: unless-stopped
volumes:
s5w_data:
networks:
proxy:
external: true # the network the proxy lives innginx-proxy-manager
Create two Proxy Hosts:
| Field | API | Panel |
|---|---|---|
| Domain Names | s5.example.com |
s5w.example.com |
| Scheme | http |
http |
| Forward Hostname / IP | s5w |
s5w |
| Forward Port | 9090 |
9091 |
| Block Common Exploits | can be on | can be on |
| Websockets Support | not needed | not needed |
| SSL | certificate, Force SSL | certificate, Force SSL |
- Body size in nginx-proxy-manager is 2000 MB by default — no need to change it.
- Close the panel. For the panel host create an Access List — by IP or with a login and password — and select it in the host’s settings.
traefik
services:
s5w:
image: flytachi/s5w:latest
environment:
ADMIN_LOGIN: admin
ADMIN_PASSWORD: ${S5W_ADMIN_PASSWORD}
PUBLIC_BASE_URL: https://s5.example.com
volumes:
- s5w_data:/var/lib/s5w
networks: [proxy]
stop_grace_period: 45s
restart: unless-stopped
labels:
- traefik.enable=true
# API and delivery
- traefik.http.routers.s5w-api.rule=Host(`s5.example.com`)
- traefik.http.routers.s5w-api.entrypoints=websecure
- traefik.http.routers.s5w-api.tls.certresolver=le
- traefik.http.routers.s5w-api.service=s5w-api
- traefik.http.services.s5w-api.loadbalancer.server.port=9090
# admin panel
- traefik.http.routers.s5w-ui.rule=Host(`s5w.example.com`)
- traefik.http.routers.s5w-ui.entrypoints=websecure
- traefik.http.routers.s5w-ui.tls.certresolver=le
- traefik.http.routers.s5w-ui.service=s5w-ui
- traefik.http.services.s5w-ui.loadbalancer.server.port=9091
volumes:
s5w_data:
networks:
proxy:
external: truewebsecure and le are the entry point and the certificate resolver from your traefik
configuration. traefik has no body size limit by default. To close the panel, add a
basicAuth or ipAllowList middleware to the s5w-ui router.
nginx
# API and delivery
server {
listen 443 ssl;
http2 on;
server_name s5.example.com;
# ssl_certificate / ssl_certificate_key …
client_max_body_size 32m;
location / {
proxy_pass http://s5w:9090;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# admin panel
server {
listen 443 ssl;
http2 on;
server_name s5w.example.com;
# ssl_certificate / ssl_certificate_key …
client_max_body_size 32m;
location / {
proxy_pass http://s5w:9091;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}http://s5w:9090 works if nginx is on the same docker network. If nginx runs on the host,
publish the ports on loopback only (127.0.0.1:9090:9090, 127.0.0.1:9091:9091) and proxy to
http://127.0.0.1:9090.
Request body size
The application accepts a request body of up to 32 MiB. The proxy must not let through less:
| Proxy | Default | What to do |
|---|---|---|
| nginx-proxy-manager | 2000 MB | nothing |
| traefik | no limit | nothing |
| nginx | 1 MB | client_max_body_size 32m; |
Why 32 MiB is enough for files of any size: the panel uploads files over 16 MiB in chunks of
8 MiB, and API clients should do the same — a single POST /v1/files request accepts a file of
up to 32 MiB, anything larger goes through chunked upload.
How to tell who rejected a request: a 413 with an HTML page comes from the proxy, a 413
with JSON ({"code": 413, …}) comes from S5W (the bucket quota or the size limit).
Downloading large files
Delivery is streamed, and Range allows resumed downloads. Proxies with default settings cope
with this. If files are very large and clients’ connections are slow, check the read timeouts
on the proxy — for example, proxy_read_timeout in nginx: the connection must not drop while
data is still flowing.