- Your users — browsers and API clients. Can stay entirely on a private network/VPN.
- External SaaS webhooks — third-party services pushing events to you. Require a publicly reachable endpoint.
Services and ports
Self-hosted Noxus puts a reverse proxy (nginx on VM, an ingress controller on Kubernetes) in front of three HTTP services. Only the proxy needs to be exposed.On Kubernetes these are three ingress hosts (main,
api., relay.) all
routing to internal port 8080. On the VM, nginx terminates TLS on 80/443
and proxies to the per-service ports. Only 443 (and 80 for redirect) needs
to be open at the edge.Inbound from your users (UI, API, streaming)
These power the product itself and are always required, but they only need to be reachable by your users — a LAN or VPN address is fine.- Frontend + Backend API over HTTPS.
- Server-Sent Events (SSE) — long-lived
GET/POSTresponses withtext/event-stream, used for live run progress (/v1/runs/{run_id}/events) and agent replies (/v1/conversations/{conversation_id}/streamand/events). Make sure your proxy does not buffer these responses and allows long-lived connections (disable response buffering; set a generous read timeout — streams can run for minutes). - WebSockets — used by optional interactive features (sandbox shell, playbook recording). If your proxy needs explicit WebSocket upgrade rules, add them; these features simply won’t work without them, but core usage is unaffected.
Inbound from external SaaS (channel webhooks)
Agent and trigger channels differ in whether the external service pushes events to you (needs public inbound) or whether Noxus pulls them (outbound only). This is the single biggest restricted-networking consideration.Securing the relay endpoint
If you must expose the relay for push channels, restrict it: each provider signs or carries a secret on its webhook (Slack signing secret, Telegram secret token, WhatsApp/Meta app secret, per-trigger tokens for generic webhooks). Keep the relay host on its own subdomain so you can apply WAF/rate-limit rules independently of the app.OAuth callbacks
When a user connects an integration (Google, Microsoft, Slack, GitHub…), the provider sends the user’s browser back to:- If your users reach the app over a VPN, an internal
BACKEND_URLworks for OAuth — no public inbound required. BACKEND_URLmust exactly match the redirect URI registered in each OAuth app, and the frontendredirect_urimust share the configuredFRONTEND_URLorigin (the backend validates this).- If you can’t expose an OAuth callback at all, fall back to manual credential entry (static API tokens) for providers that support it.