Skip to content
DezfilDocsv0.1.0

Reverse proxy and HTTPS

Serve Dezfil at your own domain over HTTPS, with Caddy or nginx in front of it.

Put Caddy or nginx in front of Dezfil to serve it at your own domain over HTTPS. The proxy holds the certificate and passes each request to Dezfil, which serves plain HTTP on port 3000.

  • You need: Dezfil running in Docker as Install sets it up, on port 3000 of 127.0.0.1 only.
  • A domain: a domain or subdomain of its own, such as maps.example.com, whose DNS record points at the server. Dezfil serves from the root of its address, not from a path such as example.com/maps/.
  • The proxy: Caddy, or nginx and certbot, installed on the same server, with ports 80 and 443 open to the internet.

Caddy

Put this site in /etc/caddy/Caddyfile, in place of the example site:

/etc/caddy/Caddyfile
<YOUR_DOMAIN> {
reverse_proxy 127.0.0.1:3000 {
header_up -Forwarded
header_up -X-Forwarded-Port
}
}
  • <YOUR_DOMAIN> is your domain, such as maps.example.com. Caddy gets a certificate for it by itself and sends plain HTTP visitors to HTTPS.
  • reverse_proxy 127.0.0.1:3000 passes every request to Dezfil, with the visitor’s address, host and scheme in forwarding headers.
  • The two header_up lines drop forwarding headers that Caddy would otherwise pass on from the visitor unchanged. Dezfil takes what a trusted proxy sends as true.

Load the new file:

Terminal
sudo systemctl reload caddy

Caddy passes uploads and the assistant’s answers through as they arrive, and sets no time limit on an answer, so the site needs nothing more.

Dezfil reads the visitor’s address and scheme from the proxy’s headers only when the connection comes from an address you trust.

With the proxy on the server and Dezfil in Docker, Dezfil sees the proxy’s requests arrive from the gateway of the container’s network. Print it:

Terminal
docker inspect --format '{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}' dezfil
Output
172.17.0.1

With Docker Compose the address differs, such as 172.18.0.1. If Dezfil runs on the server itself, outside Docker, the address is 127.0.0.1.

Start Dezfil again with that address in DEZFIL_TRUSTED_PROXIES:

Docker

Use your image and variables in the command, as Set a variable lists them, DEZFIL_SECRET_KEY too if you set one:

Terminal
docker rm -f dezfil
docker run -d --name dezfil -p 127.0.0.1:3000:3000 -v dezfil-data:/data \
-e DEZFIL_TRUSTED_PROXIES=<PROXY_ADDRESS> \
ghcr.io/dezfil/dezfil

The dezfil-data volume keeps your data.

From a trusted address, Dezfil reads:

  • The visitor’s address: from X-Forwarded-For or Forwarded, the nearest address that is not trusted. Dezfil counts failed sign-ins and requests to published maps per address.
  • The scheme, host and port: from X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-Port. Dezfil checks that each change a browser makes comes from its own pages at that address, and builds the sign-in links Users hands out with it.
  • HTTPS: when the scheme is https, Dezfil marks its session cookie as secure, so the browser sends it only over HTTPS.

From any other address, Dezfil drops these headers and uses the connection itself: the proxy’s address and plain HTTP. Sign-in through your domain then fails, and all visitors share one address’s limits.

Terminal
curl https://<YOUR_DOMAIN>/api/health
Output
{"status":"ready"}
  1. Open https://<YOUR_DOMAIN> and sign in with your Email and Password. You should see Home.
  2. As an admin, open Settings › System. In the Server settings card, you should see the Trusted proxies row with your proxy’s address and the Source Environment.

Set DEZFIL_TRUSTED_PROXIES to the address Dezfil sees your proxy’s requests arrive from, and have the proxy send the visitor’s address, host and scheme, as steps 1 and 2 do.

Session cookie name needs no change behind a proxy: it follows the port Dezfil listens on, not the one visitors use.

SettingVariableSettings keyDefaultValuesWhat it doesChanges
Trusted proxiesDEZFIL_TRUSTED_PROXIESunsetIP addresses or CIDR networks, separated by commas or spaces; a host name stops the server at startThe proxies whose forwarded visitor address, host, scheme and port Dezfil accepts.By variable, after a restart
Session cookie nameDEZFIL_SESSION_COOKIEport-basedASCII letters, digits and !#$%&'*+-.^_`|~; any other value stops the server at startBrowser session cookie name, derived from the listening port unless overridden.By variable, after a restart

Sign-in fails with “This request must come from the same instance.”

Section titled “Sign-in fails with “This request must come from the same instance.””

Dezfil reads its own address differently from your browser, most often http where the browser has https.

Run the docker inspect command of step 2 again: DEZFIL_TRUSTED_PROXIES must hold the address it prints. Then check that the proxy sends the headers of step 1.

Section titled “Sign-in links from Users point at 127.0.0.1:3000”

nginx sends its own upstream address as the host, and Dezfil builds the links Users hands out from it. Add the proxy_set_header Host and X-Forwarded-Host lines of step 1, then reload nginx. A link made while you opened Dezfil at another address, such as http://localhost:3000 over SSH, carries that address: make it again from your domain.

Pages show {"error":{"code":"invalid_request","message":"Invalid request provenance."}}

Section titled “Pages show {"error":{"code":"invalid_request","message":"Invalid request provenance."}}”

A trusted proxy sent forwarding headers that disagree, such as a Forwarded header beside different X-Forwarded-* values, or an X-Forwarded-Port that differs from the port the host names. Drop Forwarded at the proxy as step 1 does, and let one proxy set the X-Forwarded-* headers.

Dezfil stops or restarts right after it starts

Section titled “Dezfil stops or restarts right after it starts”

docker logs dezfil shows Error: Invalid ingress address or Error: Invalid trusted proxy network. DEZFIL_TRUSTED_PROXIES takes IP addresses and networks such as 172.17.0.0/16, separated by commas. A host name is refused.

nginx refuses larger requests unless told otherwise. Add client_max_body_size 0; to the server block, then reload nginx.

Long imports or queries fail after a minute behind nginx

Section titled “Long imports or queries fail after a minute behind nginx”

nginx answers 504 Gateway Time-out when Dezfil takes over 60 seconds to answer. Add proxy_read_timeout 3600s;, then reload nginx.

The assistant’s answer arrives in bursts behind nginx

Section titled “The assistant’s answer arrives in bursts behind nginx”

nginx holds the answer back until its buffers fill. Add proxy_buffering off;, then reload nginx.

Dezfil · Apache-2.0docs from 7439201b