CallMeTechie
DE Login
Home Products Blog About Contact

Setting Up Reverse Proxy Routes

📖 Usage · Updated 1 month ago

You have a service that you want to reach from the internet under your own domain — e.g. Nextcloud on the NAS as cloud.example.com, or Home Assistant as home.example.com, or an SSH server on ssh.example.com:22. All three work through the route wizard, but with slightly different settings.

This guide shows the three typical scenarios and walks step by step through the 6-stage wizard.


The three scenarios

Scenario When? Target-Kind Route type
A: Direct to the peer The target device runs GateControl client + WireGuard peer http or l4
B: Via home gateway into the LAN Target device has nothing installed (typical for NAS WebUIs, router admin, IoT) gateway http or l4
C: L4 port forward Any TCP/UDP service, no HTTP (SSH, Minecraft, MQTT) peer or gateway l4

In all three cases you work through the same wizard, but at Step 1 (target) and Step 2 (transport) you choose different options.


Preparation: set the DNS record

Regardless of the scenario — before creating the route, the DNS record must be in place.

  1. In the DNS panel of your domain provider, create an A record:
    • Name: cloud (or home, ssh, …)
    • Value: the public IPv4 of your GateControl server
    • TTL: 300 (5 min, so you can correct it quickly later)
  2. If the provider offers a proxy mode (Cloudflare):
    • For HTTP routes: proxy off. Caddy fetches the cert directly from Let's Encrypt — that won't work with Cloudflare proxy in front, because LE then sees the wrong IP.
    • For L4 routes: proxy off. Cloudflare only proxies HTTP/HTTPS.
  3. Wait for propagation (usually 1–5 min):
    dig +short cloud.example.com
    
    must return your server IP.

At the end of Step 1 the wizard runs a DNS check (POST /api/v1/routes/check-dns). That's a warning if it doesn't match, not a hard stopper. Meaning: you can save even with wrong DNS, but the cert won't come.


Scenario A: Direct peer (HTTP)

Example: Nextcloud runs on your home NAS, and the NAS has the GateControl client installed (WG peer, gets the IP 10.8.0.12). Nextcloud listens on http://10.8.0.12:80 (or another port).

  1. Routes+ Add → wizard opens.
  2. Step 1 — Target
    • Route type: HTTP
    • Domain: cloud.example.com
    • Target-Kind: Peer (default)
    • Select peer: home-nas
    • Target port: 80
  3. Step 2 — Transport
    • Backend HTTPS: off (Nextcloud speaks HTTP internally).
    • If the backend is HTTPS (e.g. Synology DSM :5001): tick it + Accept self-signed on.
  4. Step 3 — Authentication
    • None, Basic-Auth, or Route-Auth (email+password with passkey).
    • Nextcloud has its own auth → no extra auth needed.
  5. Step 4 — Access
    • IP whitelist/blacklist (CIDR list).
    • Peer ACL: only specific peers may access.
    • Default: open to all. For an internally accessible Nextcloud that's enough — Nextcloud has its own auth.
  6. Step 5 — Reliability
    • Uptime monitoring, rate limiting, request mirroring, circuit breaker, retry. All optional. For the start: leave off.
  7. Step 6 — Review
    • Go through everything once more, Save.

Caddy loads the new config, registers the Let's Encrypt cert (HTTP-01 challenge, port 80 must be free), and after ~30 seconds you open https://cloud.example.com in the browser.


Scenario B: Via home gateway into the LAN (HTTP)

Example: Synology DSM on 192.168.1.10:5001 (HTTPS with self-signed cert), no GateControl client installed. You have a home gateway container running, see first-gateway-setup.md.

Prerequisite: the home gateway peer is online, visible under Peers & ClientsHome Gateways.

  1. Routes+ Add.
  2. Step 1 — Target
    • Route type: HTTP
    • Domain: dsm.example.com
    • Target-Kind: Gateway
    • Select gateway peer: homeserver-nuc
    • Target LAN host: 192.168.1.10 (the IP/hostname in the LAN of the gateway, not a VPN IP)
    • Target LAN port: 5001
  3. Step 2 — Transport
    • Backend HTTPS: on (DSM speaks HTTPS).
    • Accept self-signed: on (DSM has a self-signed cert in the default config).
  4. Step 3 — Authentication
    • DSM has its own auth → Route-Auth and Basic-Auth not needed. If you want to, put a Basic-Auth in front.
  5. Step 4 — Access
    • IP whitelist is sensible (e.g. only your home IP + office IP). DSM otherwise gets constantly probed by scanners.
  6. Step 5 — Reliability
    • For gateway routes, uptime monitoring can be useful to separate gateway outages from route outages.
  7. Step 6 — Save.

How it works internally: Caddy sends the request to the WG IP of the gateway, the gateway container receives the request, reads out the X-Gateway-Target header and proxies it to 192.168.1.10:5001 in the LAN. TLS terminates at Caddy on the server, the gateway→LAN hop goes either HTTP (if Backend HTTPS off) or HTTPS (if on).


Scenario C: L4 port forward

Example: SSH access to a LAN box. Publicly as ssh.example.com:22.

  1. Routes+ Add.
  2. Step 1 — Target
    • Route type: L4
    • Domain: ssh.example.com (optional — L4 routes without domain also work, but are then only reachable via server-IP:port)
    • L4 listen port: 22 (the port on the GateControl server that the client targets from outside)
    • L4 protocol: TCP
    • Target-Kind: peer or gateway
    • For gateway: Target LAN host 192.168.1.20, Target LAN port 22
  3. Step 2 — Transport
    • TLS mode (three options):
      • none — pure TCP/UDP proxy, no cert. Correct for SSH, Minecraft, MQTT-plain, MySQL etc.
      • passthrough — Caddy does not terminate TLS, passes the TLS session straight through to the backend. Only useful if the backend itself has a valid cert, e.g. Nginx in the LAN with its own LE.
      • terminate — Caddy terminates TLS at the server with a Let's Encrypt cert and then speaks plain TCP to the backend. Only for HTTPS-like protocols; pointless for SSH/Minecraft.
  4. Step 3 — Authentication
    • For L4 no server-side auth plugin is available (same as with SSH — the auth is done by the backend protocol itself).
  5. Step 4 — Access
    • IP filter urgently recommended for SSH. Peer ACL only applies to clients with a WG tunnel, so it doesn't help with publicly reachable L4 routes.
  6. Step 5 — Reliability
    • L4 has no mirror, no retry, no rate limit — the options are greyed out. Uptime monitoring works (TCP connect check).
  7. Step 6 — Save.

Test:

ssh -p 22 user@ssh.example.com

Adding auth in front (optional)

If the backend has no auth of its own (e.g. a Grafana without login, an internal wiki) you can put Route-Auth in front:

  • Basic-Auth: simple user/password, HTTP auth dialog in the browser.
  • Route-Auth (email+password): server shows a GateControl login page, user has to log in with their admin credentials or a separate route user. Passkey flow available.

You'll find both in Step 3 of the wizard. Further reading ../AUTHENTICATION.md.


Troubleshooting

502 Bad Gateway

The most common error page when a fresh route doesn't work.

Check steps:

  1. Backend reachable? From the GateControl host:
    curl -v http://10.8.0.12:80       # Scenario A
    curl -vk https://192.168.1.10:5001 # Scenario B (test from the gateway!)
    
  2. For gateway routes: gateway container online? Heartbeat fresh? (See first-gateway-setup.md — Troubleshooting.)
  3. Firewall on the backend host: many NAS firewalls block foreign subnets by default. The gateway brings the request from 10.8.0.0/24, that must be allowed. Alternative: add the gateway host to the LAN firewall allowlist.
  4. Port correct? Typos in target_lan_port / target_port don't throw 502 at config level directly, but silently on connect failure.

DNS error in the wizard check

The wizard shows "DNS does not point to server IP".

Possible causes:

  • Record not yet propagated → wait 5 min, check dig +short ….
  • Cloudflare proxy on → proxy off (grey out the orange cloud).
  • Wrong A record (CNAME instead of A can work, but must ultimately resolve to your IP).
  • Multiple IPs in the A record → only one of them is the server.

The wizard is tolerant here: the warning doesn't block save. But as long as DNS is wrong, no cert will come.

Certificate doesn't come

See the detailed guide in certificates.md. Short:

  • Port 80 reachable on the server? (ACME HTTP-01)
  • DNS correct? (point 1)
  • Let's Encrypt rate limit hit? (50 certs / week / registered domain)
  • Caddy logs: docker logs gatecontrol 2>&1 | grep -i "acme\|tls.obtain"

Route to Synology DSM: "backend broken" but DSM runs

DSM with self-signed cert on :5001: Backend HTTPS on and Accept self-signed on. Otherwise Caddy fails at the certificate verify. Not to be confused: self_signed_accept is a per-route flag, not a global switch.

L4 route with tls_mode=terminate won't get a cert

L4 TLS works differently from HTTP TLS in Caddy — see section "L4 route with TLS terminate" in certificates.md.


Further reading

Cookie Settings

We use cookies to improve your experience. Essential cookies are always active.

Privacy Policy
ESC
↑↓ navigate open esc close