This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Overpass can put the web UI, REST API, gRPC, op ssh, and node tunnels behind
one ordinary HTTPS reverse proxy. Caddy owns public port 443; Overpass keeps
listening on its internal HTTPS port (normally 8443). No Caddy Layer 4 module
or extra public ports are required.
Overpass configuration
Enable TLS routing and set the public address clients and nodes should use:
proxy:
web_addr: 127.0.0.1:8443
public_addr: gate.acme.com:443
public_url: https://gate.acme.com
tls_routing: true
trusted_proxies:
- 127.0.0.1/32
tls_routing makes the public web address the advertised endpoint for every
protocol. The dedicated 3023–3025 listeners remain available for older
clients, but they do not need to be exposed publicly.
public_url gives Overpass the external browser/OIDC URL. Set it explicitly
when possible. If it is omitted, Overpass accepts X-Forwarded-Proto and
X-Forwarded-Host only from peers listed in trusted_proxies.
Caddy
Use the standard Caddy build and an ordinary reverse_proxy:
gate.acme.com {
reverse_proxy https://127.0.0.1:8443 {
transport http {
tls_insecure_skip_verify
}
}
}
That is the complete public routing configuration. Caddy terminates the public
TLS connection on port 443, obtains the public certificate, and forwards
HTTPS and WebSocket requests to Overpass. tls_insecure_skip_verify applies
only to Caddy's connection to Overpass's internal, self-signed HTTPS listener.
If Caddy reaches Overpass by a hostname covered by a trusted internal certificate, verify it normally instead:
gate.acme.com {
reverse_proxy https://overpass.internal:8443
}
Do not add a layer4 block, TCP proxy, SNI passthrough, or separate route for
the connection-upgrade endpoint. Caddy's normal WebSocket handling is enough.
How single-port routing crosses an HTTP proxy
Direct clients first offer Overpass's ALPN protocol on the public TLS
connection. When Caddy terminates that connection, the client automatically
opens a WebSocket at /api/v1/connection-upgrade and carries a second TLS
connection inside it. Overpass then routes that inner connection through the
same existing ALPN mux:
| Traffic | Inner ALPN |
|---|---|
Client SSH (op ssh) |
op-ssh/1 |
| Node reverse tunnel | op-tunnel/1 |
| gRPC login, enrollment, and admin | op-grpc/1 |
The outer TLS connection is authenticated using Caddy's public certificate (or
the configured --tls-pin). Overpass advertises its inner certificate pin over
that authenticated HTTPS connection, and the client verifies the inner TLS
connection against it. The fallback does not silently disable certificate
verification.
Direct ALPN routing still works when Overpass owns the public port or sits behind TLS passthrough. The HTTP/WebSocket fallback is automatic; operators do not select a client mode.
nginx
nginx also works as a normal HTTP reverse proxy. WebSocket upgrade headers are required:
server {
listen 443 ssl;
server_name gate.acme.com;
# ssl_certificate ...;
# ssl_certificate_key ...;
location / {
proxy_pass https://127.0.0.1:8443;
proxy_ssl_verify off; # internal self-signed certificate
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Traefik and other proxies work the same way: use an HTTPS/HTTP router and allow WebSocket upgrades. TCP passthrough remains supported but is not required.
Firewall and ports
Only the reverse proxy needs a public listener:
| Port | Exposure | Purpose |
|---|---|---|
443 |
Public | Caddy/other HTTPS reverse proxy |
8443 |
Private or loopback | Overpass HTTPS backend |
3023 |
Private | Legacy direct SSH routing |
3024 |
Private | Legacy direct node tunnels |
3025 |
Private | Legacy direct gRPC |
If Caddy and Overpass run in separate containers, bind 8443 to the private
container network rather than loopback and use that service address in the
Caddyfile.
OIDC
Register this redirect URI with the identity provider:
https://gate.acme.com/oidc/callback
It uses the public 443 URL, not Overpass's internal 8443 listener.
Troubleshooting
First verify the web route and upgrade endpoint reach Overpass:
curl -fsS https://gate.acme.com/api/v1/healthz
op login gate.acme.com:443 --debug
Common failures:
404for/api/v1/connection-upgrade: Caddy is pointing at an older Overpass server, or a path matcher excludes the endpoint.- WebSocket upgrade failure: an intermediary is removing the
UpgradeandConnectionheaders. The simple Caddy configuration above forwards them automatically. - Outer certificate error: the client does not trust Caddy's public
certificate, or
--tls-pinrefers to a different certificate. - Inner certificate-pin error: the HTTP response and inner TLS connection reached different Overpass instances with different persisted TLS certificates. Give replicas a shared TLS identity or use sticky routing.
- Login works but the advertised SSH/tunnel address is wrong: set
public_addr: gate.acme.com:443,public_url, andtls_routing: true.
Enable tls_routing only after upgrading op and node agents to a build that
supports the HTTP connection-upgrade transport. Older clients do not know how
to cross a TLS-terminating HTTP proxy.