Run Dew behind a reverse proxy
Dew serves HTTPS itself, so it doesn’t need a reverse proxy. If you already run one, or your network requires one, this guide sets it up so large uploads stay fast, Let’s Encrypt keeps working where it can, and Dew’s logs show each visitor’s real address.
You need:
- A running Dew server (see Get started with Dew)
- Access to your proxy’s configuration and to Dew’s
compose.yaml - Your domain’s DNS record and your router’s port 443 pointing at the proxy, not at Dew
If you control the router, the simplest setup is no proxy at all: forward public port 443 straight to Dew. Dew then sees every visitor’s address and Let’s Encrypt works with no extra settings.
1. Choose how the proxy passes traffic to Dew
Section titled “1. Choose how the proxy passes traffic to Dew”Traffic reaches Dew in one of three ways, and the choice decides who holds the public certificate.
| Setup | Public certificate | Visitor addresses in Dew | Let’s Encrypt in Dew |
|---|---|---|---|
| Port forward (router or firewall NAT, no proxy) | Dew’s | Real visitor addresses | Works when the public port is 443 |
| Passthrough (the proxy forwards the encrypted connection by hostname) | Dew’s | The proxy’s address for everyone | Works when the public port is 443 |
| Terminating (the proxy decrypts, then connects to Dew over HTTPS) | The proxy’s | Real visitor addresses, once you trust the proxy | Not available: the proxy manages the certificate |
Choose passthrough when you want Dew to keep managing its certificate and don’t need per-visitor addresses. Choose terminating when the proxy already manages certificates for your sites, or when a WAF or application gateway must inspect traffic.
Dew doesn’t support the PROXY protocol, so in passthrough mode Dew’s logs and rate limits see the proxy’s address for every visitor.
2. Set Dew’s ports
Section titled “2. Set Dew’s ports”Dew listens on one HTTPS port, 443 by default. Behind a proxy, pick a free internal port such as 8443 and make it reachable only by the proxy. Ports are set in Dew’s compose.yaml: the port Dew listens on as DEW_HTTPS_PORT, and the port visitors use as DEW_PUBLIC_HTTPS_PORT.
On Synology, skip this step. Dew uses the NAS’s own network and already listens on port 8843, so the upstream is 127.0.0.1:8843. Use it wherever the examples below show 127.0.0.1:8443, and block port 8843 for other machines in the DSM firewall.
-
In
compose.yaml, add these lines to theenvironment:list of thedewservice (addenvironment:if it isn’t there yet):DEW_PUBLIC_HTTPS_PORTis the port visitors use, usually 443. Dew uses it in every link and email it sends, and for its reachability check and Let’s Encrypt. -
Change the
ports:lines of thedewservice to match where your proxy runs:- Proxy container on the same host: delete the
ports:section, so Dew publishes no port on the host. Attach the proxy container to Dew’s network,dew_default, and usedew:8443as the upstream. - Proxy on the same host, outside Docker (a local nginx, for example): publish the port on the loopback address only,
- "127.0.0.1:8443:8443". The upstream is127.0.0.1:8443. - Proxy on another machine (a WAF, Azure Application Gateway, F5, an nginx on another server): publish the port,
- "8443:8443", and firewall the host so only the proxy can reach it. The upstream is<dew-host>:8443.
- Proxy container on the same host: delete the
-
Run
docker compose up -din the folder that holdscompose.yaml.docker compose restartdoesn’t apply changed settings.
3. Configure your proxy
Section titled “3. Configure your proxy”Every proxy in front of Dew needs these settings:
- Pass the original hostname to Dew. Dew answers only for the domains you added, and returns “not found” for anything else.
- Turn off buffering of both uploads and downloads. A proxy that collects each upload before passing it on halves upload speed and stops upload speed limits from working. A proxy that collects downloads makes them sit at 0 bytes, then jump.
- No body-size limit, or one above your largest allowed upload.
- Long idle timeouts. Dew has no request time limit, because a large upload or download can take hours. In nginx,
proxy_read_timeoutandproxy_send_timeoutare the longest pause allowed between data, not the whole transfer, so1hcovers any transfer. - HTTP/1.1 to browsers, not HTTP/2. Browsers upload to Dew over several connections at once, which HTTP/2 merges into one. Measured browser uploads are about half as fast through a proxy with HTTP/2 turned on.
- HTTPS all the way to Dew. Dew only accepts HTTPS, and its upstream accepts HTTP/1.1 only. A proxy that offers only HTTP/2 to its upstream fails to connect.
Dew doesn’t use WebSockets, so no upgrade settings are needed, and it always serves HTTPS, so it doesn’t need X-Forwarded-Proto.
The examples below assume Dew listens on 127.0.0.1:8443 and your domain is files.example.com.
nginx, terminating
Section titled “nginx, terminating”On nginx older than 1.25.1, delete the http2 off; line and remove http2 from every port 443 listen line, so listen 443 ssl http2; becomes listen 443 ssl;. That older setting applies to every site on the port, so on a shared nginx that needs HTTP/2 for other sites, use passthrough instead.
With a terminating proxy, Dew can’t get a Let’s Encrypt certificate. When you add the domain in Dew, import a certificate in the certificate step (the one your proxy uses works).
nginx, passthrough
Section titled “nginx, passthrough”Only one listener can own port 443, so on an nginx that also serves other sites, move their listen 443 ssl lines to an internal port such as 127.0.0.1:8444. The default line above sends every other hostname there.
Skip step 4: a passthrough proxy can’t tell Dew the visitor’s address.
Caddy, terminating
Section titled “Caddy, terminating”protocols h1 turns off HTTP/2 and HTTP/3 for every site on port 443. Standard Caddy can’t pass connections through by hostname, so on a Caddy that serves other sites, either accept HTTP/1.1 for them or put nginx, HAProxy or Traefik in passthrough mode in front.
Caddy checks the certificate on Dew’s own port. If it isn’t publicly trusted, add tls_trust_pool file /path/to/dew-certificate.pem to the transport block, or for a test setup only, tls_insecure_skip_verify.
HAProxy, passthrough
Section titled “HAProxy, passthrough”Traefik, passthrough
Section titled “Traefik, passthrough”For a terminating Traefik, use an HTTP router pointing at https://127.0.0.1:8443 with serversTransport.serverName: files.example.com, and complete step 4 with Traefik’s address.
Cloudflare proxy
Section titled “Cloudflare proxy”Cloudflare’s proxy terminates HTTPS, so treat it like a terminating proxy and set DEW_TRUSTED_PROXIES to Cloudflare’s IP ranges. Two Cloudflare settings affect uploads:
- Request body buffering: keep it at Standard (the default) or None, not Full.
- Upload size per request: Cloudflare caps each request at 100 MB on Free, 200 MB on Pro and 500 MB on Business. Dew uploads in pieces of 16 MB, so this is only a concern with S3 storage and files over about 150 GB, where pieces grow (32 MB at 300 GB, over 100 MB at 1 TB). If your uploads are that large, raise the limit with Cloudflare or use a DNS-only record for Dew.
4. Tell Dew about the proxy
Section titled “4. Tell Dew about the proxy”A terminating proxy tells Dew each visitor’s address in a forwarding header, and Dew only reads it from proxies you trust. Until then, audit logs, rate limits and upload speed limits see the proxy’s address for everyone.
-
Open
https://files.example.comthrough the proxy, then open System → System. On the System tab, Dew shows Reverse proxy detected at the address the proxy connects from. The domain wizard’s proxy step shows the same notice after its check.
-
Select Trust this proxy. It applies at once, with no restart. A proxy container on a Docker network is trusted with its whole network, so it stays trusted when the container is recreated with a new address. A proxy anywhere else is trusted by its exact address.
If the notice adds “Only trust it if this server’s port can’t be reached from the internet except through this proxy”, the proxy reaches Dew through Docker’s gateway, which also passes on visitors who connect to Dew’s port directly. Trust it only when Dew’s port is closed to the internet, for example published on 127.0.0.1 or blocked in the firewall.
To stop trusting a proxy, select Remove next to it under Reverse proxy.
Set trusted proxies in compose.yaml
Section titled “Set trusted proxies in compose.yaml”Use DEW_TRUSTED_PROXIES instead of the button for Cloudflare (its addresses are public, so Dew never offers the button), when Dew has its own address on your network (a macvlan or ipvlan network, such as Unraid’s br0), or to trust the proxy before first setup. When it is set, proxies trusted with the button are ignored.
-
In
compose.yaml, add this line to theenvironment:list of thedewservice (addenvironment:if it isn’t there yet). Separate several addresses or ranges with commas: -
Run
docker compose up -d. On Synology, stop the dew project in Container Manager, add the line to the project’s YAML, then build the project again.
Check it worked
Section titled “Check it worked”- Open
https://files.example.com: Dew loads with no certificate warning. - Open System → System. On the System tab, Reverse proxy shows Trusted with your proxy’s network or address, Configured when set with
DEW_TRUSTED_PROXIES(terminating proxies), or None detected (passthrough and port forward). - Sign in from another network, then open the Access logs tab: your request shows your own address, not the proxy’s.
- Upload a large file and watch the speed: it should match an upload without the proxy. A speed of about half points to HTTP/2 or buffering in the proxy.
If something doesn’t work
Section titled “If something doesn’t work”| What you see | What to do |
|---|---|
| Reverse proxy shows Not trusted on the System tab of System → System | Dew receives forwarding headers from a proxy it doesn’t trust. Select Trust this proxy under it. If a proxy is already listed as trusted, it isn’t the one connecting: remove it, then trust the detected address. |
| Reverse proxy shows None detected although a terminating proxy is in front | Dew checks the first requests after it starts. Restart the container with docker compose restart, open Dew through the proxy, then reload System → System. |
| Every visitor has the same address in the logs | Terminating proxy: complete step 4. Passthrough proxy: expected; use a port forward if you need visitor addresses. |
| Dew answers “not found” through the proxy | The proxy isn’t passing the original hostname. In nginx, add proxy_set_header Host $host;. |
| Browser uploads are about half as fast as expected | The proxy uses HTTP/2 towards browsers. Turn it off as shown in step 3. |
| Downloads sit at 0 bytes, then jump | The proxy is collecting downloads first. In nginx, set proxy_buffering off;. In Caddy, flush_interval -1. |
| Large uploads stop partway | The proxy’s timeout or body-size limit is too low. See step 3. |
| The proxy can’t connect to Dew | Point the proxy at https://, not http://, and make sure it offers HTTP/1.1 to Dew. |
| The domain wizard says “Let’s Encrypt needs this server on port 443 from the internet.” | DEW_PUBLIC_HTTPS_PORT is set to a port other than 443. Set it to 443 or remove it, and run docker compose up -d. Let’s Encrypt also needs visitors to reach Dew itself on port 443, through a port forward or passthrough. With a terminating proxy, import a certificate instead. |
| Links in emails include the wrong port | Set DEW_PUBLIC_HTTPS_PORT to the port visitors use and run docker compose up -d. |
For more detail, open System → System and the Error logs tab. Each failed request has a reference such as REF-a3f8b2c1 that you can quote when you contact support at support@getdew.io.
