Reverse Proxy Configuration Generator

Put Nginx in front of the apps you self-host on a Raspberry Pi — Home Assistant, dashboards, Docker containers, anything listening on a local port — without hand-writing the config. Pick a starting preset (plain HTTP on your LAN, HTTPS with Let's Encrypt, a WebSocket app, or a Docker container), add one card per app/subdomain, and get a live nginx site configuration you can copy straight to /etc/nginx/sites-available/. The generator checks the mistakes that actually break reverse proxies: TLS with no certificate paths, a proxy pointed at its own port, duplicate server_names, missing WebSocket upgrade headers — and hands you the exact install commands, including nginx -t, which validates the file before it is ever loaded.

🔒 100% private — nothing is uploaded or stored. The nginx configuration is generated entirely in your browser. If you upload an existing site file it is parsed locally and never sent to a server, so you can safely import configs that contain your domains, internal ports or certificate paths.

1 · Starting point

Pick a preset to fill the form with a working baseline. Choosing a preset replaces the current apps — everything can be edited afterwards.

2 · Apps (one card per subdomain)

Each app gets its own server block. Point each one at the port the app actually listens on locally (find it with ss -tlnp | grep nginx… sorry — ss -tlnp).

3 · Global settings

Port Nginx answers on when TLS is off. 80 is standard; use 8080 if something else owns 80.

Import an existing config (optional)

Paste an nginx site file (e.g. from cat /etc/nginx/sites-available/mysite) or upload it — it is parsed in your browser and loaded into the form above. One card per server block that has a proxy_pass; TLS settings, certificate paths and upload size are picked up too. Everything else is reported and left out.

Your reverse proxy configuration

ready

Install it (three commands)

Run on the Raspberry Pi. Step 3 is the safety net: nginx -t validates the file and only reloads if it parses — a typo can't take Nginx (and every proxied app) down.

How a reverse proxy works on a Pi

Your apps listen on local ports (127.0.0.1:8080, :8123…) so strangers can't reach them directly. Nginx is the single public front door: it listens on 80/443, matches the request's Host header to a server_name, and forwards the request to the right local port. One Pi, many subdomains — homeassistant.pi.example.com and grafana.pi.example.com can both point at the same machine's IP and land on different apps.

The proxy also terminates TLS (the certificate lives in Nginx, not in every app), can add authentication in front of apps that have none, and tells the real client address to the app through the X-Forwarded-For header — which is why well-behaved apps show your IP instead of 127.0.0.1 in their logs.

The mistakes that actually break reverse proxies

  1. WebSockets silently fail (or time out after 60 seconds). Nginx's default Connection: close handling kills WebSocket handshakes. The fix is the Upgrade/Connection "upgrade" header pair plus a long proxy_read_timeout — tick WebSocket on any app with live updates and this generator writes both.
  2. The trailing-slash trap in proxy_pass. location /app/ { proxy_pass http://127.0.0.1:8080; } forwards the full path (/app/login), but proxy_pass http://127.0.0.1:8080/; (with a slash) strips the /app prefix first. Most apps expect their own root, so this generator adds the trailing slash when you set a path prefix — and flags it if your app is one of the few that wants the full path.
  3. The proxy points at its own port. proxy_pass http://127.0.0.1:80 where Nginx itself listens on 80 is an infinite loop — requests bounce forever until they time out. The generator flags any backend port that equals the listen port.
  4. certbot can't renew because port 80 is blocked or taken. If your app owns port 80, either move it to another port and let Nginx serve 80 (the redirect server here doubles as the ACME webroot), or use certbot --nginx. A certificate that can't renew is a site that breaks in ~90 days.
  5. The app generates http:// links behind HTTPS. Apps that build absolute URLs from the request see X-Forwarded-Proto: http (or nothing) and hand out insecure links. This generator always sends X-Forwarded-Proto; if an app still misbehaves, it usually needs a one-line setting like TRUSTED_PROXY or PUBLIC_URL.
  6. Duplicate server_name across site files. Two server blocks claiming the same name (often in two different files under sites-enabled/) and Nginx serves whichever it reads first — your edits to the "right" file appear to do nothing. The generator flags duplicates within this config; check old files with grep -r server_name /etc/nginx/sites-enabled/.

Key directives reference

DirectiveWhat it does
listen 443 ssl;Answer on port 443 and terminate TLS. (On modern Nginx you can add http2, but HTTP/2 over a Pi is often more trouble than it's worth.)
server_nameThe Host header this block answers for. One per subdomain; the first block in a file is the default for anything unmatched.
proxy_pass http://host:port;Where the request actually goes. Trailing slash = strip the location prefix before forwarding.
proxy_set_header Host $host;Forward the original hostname (not 127.0.0.1) so virtual-hosted apps and URL generation work.
proxy_set_header X-Real-IP / X-Forwarded-ForTell the app who really asked — without these, every request looks like it came from localhost.
proxy_set_header X-Forwarded-Proto $scheme;Tells the app the original scheme (http/https) so it builds https:// links behind TLS.
Upgrade / Connection "upgrade"The WebSocket handshake pair. Only needed on locations that carry WebSockets — harmless elsewhere, but this generator keeps them out of plain-HTTP locations.
client_max_body_sizeLargest request body Nginx accepts before answering 413. The default is 1M — uploads bigger than that fail at the proxy, not the app.
proxy_read_timeoutHow long to wait between chunks from the app before Nginx answers 504. WebSockets and streaming need it raised well past the 60s default.
auth_basic + auth_basic_user_filePassword gate in front of an app that has no login of its own. Create the file with htpasswd -c /etc/nginx/.htpasswd <user>.

Luke Keam
Spot a bug or want a custom utility built? I'd love to hear from you. Get in touch
Luke Keam | techgeek.biz