Why use a reverse proxy
- TLS termination — BlindCast doesn’t handle HTTPS. Your proxy terminates TLS and forwards HTTP to BlindCast.
- Admin protection — The
/admindashboard serves static files without authentication. A proxy can gate it behind SSO, HTTP Basic Auth, or IP allowlists. - Rate limiting — Protect key derivation (
/keys) and API endpoints from abuse. - Setup endpoint security — Block
POST /api/v1/setupfrom the internet to prevent unauthorized admin key creation.
nginx
Quick start with Docker Compose
The server ships with a proxy overlay that adds nginx in front of BlindCast:- Adds an nginx service on port 80 that proxies to BlindCast
- Sets
TRUST_PROXY=1on BlindCast so Express reads real client IPs from the forwarded header (trusts exactly one proxy hop)
Configuration reference
The proxy config is atdocker/nginx-proxy.conf. Key sections:
Forwarded headers — Every proxied route sends X-Forwarded-For, X-Forwarded-Proto, X-Real-IP, and Host to BlindCast:
CORS headers — The proxy does not add CORS headers. Express handles CORS for all proxied routes. Adding CORS at both layers causes duplicate
Access-Control-Allow-Origin headers, which browsers reject.
Protecting /admin with auth_request
Use nginx’sauth_request to gate the admin dashboard behind an external auth provider (Auth0, Okta, Azure AD via oauth2-proxy, etc.):
- Uncomment the
auth_requestlines innginx-proxy.conf:
- Uncomment and configure the auth verification endpoint:
- Add your auth backend (e.g., oauth2-proxy) as a Docker service alongside nginx.
Protecting /admin with HTTP Basic Auth
For simple deployments, use nginx’s built-in basic auth:Rate limiting
Uncomment thelimit_req_zone directives at the top of nginx-proxy.conf:
limit_req in the relevant location blocks:
TLS termination
The config includes a commented-out TLS server block. Uncomment it and provide your certificate paths:Caddy
Caddy handles TLS automatically with Let’s Encrypt. A minimal Caddyfile:Forward auth for /admin
Use Caddy’sforward_auth to protect the admin dashboard:
Blocking the setup endpoint
AWS ALB / Cloud Load Balancers
For AWS ALB, GCP Cloud Load Balancing, or Cloudflare:-
Target group — Point to BlindCast container on port 4100. Use
/healthfor health checks. - Listener rules — Route all paths to the BlindCast target group.
-
Admin protection — Use the load balancer’s built-in auth integration:
- AWS ALB: Add an authenticate-cognito or authenticate-oidc action on the
/admin*path rule. - GCP: Use Identity-Aware Proxy (IAP) to gate
/admin. - Cloudflare: Use Cloudflare Access to protect the
/adminpath.
- AWS ALB: Add an authenticate-cognito or authenticate-oidc action on the
-
Set
TRUST_PROXY— Cloud load balancers add their ownX-Forwarded-Forheaders. SetTRUST_PROXY=trueon the BlindCast container.
TRUST_PROXY environment variable
When BlindCast runs behind a proxy, setTRUST_PROXY so Express reads the real client IP from forwarded headers.
Setup wizard security
The setup endpoint (POST /api/v1/setup) creates the first admin API key. It has no authentication — it only works when zero API keys exist in the database. This creates a race condition: if the server is network-accessible before you run setup, an attacker could claim the admin key first.
Recommended: use ADMIN_API_KEY in production
Set theADMIN_API_KEY environment variable to bootstrap with a known key. This skips the setup wizard entirely and eliminates the race condition:
admin scope. Store it in a secret manager (AWS Secrets Manager, HashiCorp Vault, Doppler).
Alternative: temporarily unblock the setup endpoint
If you prefer the setup wizard:- Uncomment
proxy_passin the/api/v1/setuplocation block - Run
docker compose upand complete setup at/admin - Re-block the endpoint by commenting out
proxy_passand reloading nginx:
Next steps
- Docker Setup — base Docker Compose configuration
- API Keys — key scopes and management
- Admin Dashboard — browser-based management
- Production Checklist — full production readiness guide