Build a TLS-terminated reverse proxy that:
- Automatically provisions and renews TLS certificates.
- Authenticates visitors via GitHub OAuth ("Login with GitHub").
- After successful authorization, redirects the user back and serves the requested resource.
- Uses static files as the placeholder backend for now; replace with the real
opencodebackend later. - Supports routing requests to different upstream backends based on the authenticated GitHub username.
- Keeps moving parts to a minimum and, ideally, avoids writing custom application code.
Use Caddy for automatic TLS and the third-party caddy-security plugin for OAuth/OIDC authentication directly in the Caddyfile.
Pros
- Single binary/container.
- TLS and auth configured in one place.
- No separate authentication sidecar.
Cons
caddy-securityis a community plugin with less adoption thanoauth2-proxy.- It is unclear how cleanly it supports routing decisions based on the authenticated username.
Use Traefik as the edge proxy for TLS termination and routing. Put oauth2-proxy in front as a ForwardAuth middleware. oauth2-proxy performs the GitHub OAuth dance and injects the username in headers such as X-Forwarded-User. Traefik then routes requests to different backends using header-matching rules.
Pros
- Both projects are mature and well-documented.
oauth2-proxyhas a rich GitHub provider (orgs, teams, email allowlists).- Traefik supports header-based routing natively, making per-user backends straightforward.
- Easy to swap the static-file backend for
opencodelater.
Cons
- Two containers instead of one.
Same architecture as Option B, but use Caddy as the reverse proxy. Caddy handles TLS automatically and can match routes on the X-Forwarded-User header injected by oauth2-proxy.
Pros
- Caddy's Caddyfile is concise.
- Excellent automatic TLS.
Cons
- Caddy header matching works, but Traefik's router rule model is more purpose-built for this kind of dynamic routing.
Start with Option B (Traefik + oauth2-proxy). It limits the system to two well-supported containers, avoids custom authentication code, and gives clean per-user routing through Traefik header rules.
- Should authentication be open to any GitHub user, or restricted to a specific org/team/allowlist?
- What is the desired behavior for unauthenticated or unrecognized users (login page, 403, redirect)?
- Which domain(s) will be used so that TLS certificates can be provisioned?
Go to GitHub.com → Settings → Developer settings → OAuth Apps → New OAuth App and fill in:
| Field | Value |
|---|---|
| Application name | opencode-hosted (or any name) |
| Homepage URL | https://static.253.115.233.167.clients.your-server.de |
| Authorization callback URL | https://static.253.115.233.167.clients.your-server.de/oauth2/callback |
Click Register application, then copy the Client ID. Click Generate a new client secret and copy the Client Secret.
Edit oauth2-proxy/oauth2-proxy.cfg and replace the placeholders:
client_id = "YOUR_CLIENT_ID"
client_secret = "YOUR_CLIENT_SECRET"
docker compose up -dTraefik will automatically provision a Let's Encrypt TLS certificate for the domain.
Visit https://static.253.115.233.167.clients.your-server.de — you should be redirected to GitHub for login, then served the static page.
User → Traefik:443 (TLS) → oauth2-proxy:4180 (GitHub OAuth) → nginx:80 (static files)
Routes to different upstream backends per GitHub username can be added later via Traefik header-matching rules on X-Forwarded-User.