Reverse proxy & TLS
The installer runs this step for you automatically at the end of installation, but it’s worth understanding what it sets up — and useful if you ever need to reconfigure it by hand.
Why a reverse proxy
Section titled “Why a reverse proxy”Orbit’s api and web containers only ever listen on 127.0.0.1 inside the server — nothing is
reachable from outside the box until something in front of them terminates TLS and proxies
traffic in. That’s nginx’s job here, running directly on the host (not inside a container).
What gets proxied where
Section titled “What gets proxied where”A single nginx server block for your domain routes:
/hubs/→ the API, with WebSocket upgrade headers and a long read timeout (SignalR’s real-time notifications need both — a normal 60-second timeout kills the connection mid-session)./api/→ the API./hangfire→ the background-job dashboard (gated at the app level too; you can add an IP allowlist here for a second layer).- everything else (
/) → the web frontend.
upstream thinkbooks_api { server 127.0.0.1:8080;}upstream thinkbooks_web { server 127.0.0.1:8081;}
server { listen 443 ssl http2; server_name YOUR_DOMAIN;
ssl_certificate /etc/letsencrypt/live/YOUR_DOMAIN/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/YOUR_DOMAIN/privkey.pem;
client_max_body_size 55M; # matches the app's upload cap plus headroom
location /hubs/ { proxy_pass http://thinkbooks_api; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; # ... } location /api/ { proxy_pass http://thinkbooks_api; /* ... */ } location /hangfire { proxy_pass http://thinkbooks_api; /* ... */ } location / { proxy_pass http://thinkbooks_web; /* ... */ }}Certificates come from Let’s Encrypt via certbot:
certbot certonly --nginx -d YOUR_DOMAINA plain-HTTP server block handles the ACME HTTP-01 challenge and redirects everything else to HTTPS.
Verifying image authenticity (optional)
Section titled “Verifying image authenticity (optional)”Every image Orbit pulls is signed keyless via Sigstore/cosign at build time. To verify one yourself:
cosign verify \ --certificate-identity-regexp "^https://github.com/Kuzium-Technologies/thinkbooks/.github/workflows/deploy.yml.*" \ --certificate-oidc-issuer https://token.actions.githubusercontent.com \ ghcr.io/kuzium-technologies/thinkbooks/api:latestNext: Updates & licensing.