Inbound traffic falls into two groups with very different exposure needs:Documentation Index
Fetch the complete documentation index at: https://docs.noxus.ai/llms.txt
Use this file to discover all available pages before exploring further.
- 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.| Service | Internal port | Public hostname (typical) | Who connects |
|---|---|---|---|
| Frontend (Next.js) | 8080 (3000 on VM) | app.example.com | Users’ browsers |
| Backend API (FastAPI) | 8080 (8100 on VM) | api.example.com | Browsers, API clients, SSE |
| Relays (FastAPI) | 8080 (5003 on VM) | relay.example.com | External SaaS webhooks |
| Workers | 8080 (internal) | — | Never exposed |
| Plugin server / sandbox | 8500 / 8080 (internal) | — | Never 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.| Channel | Mechanism | Needs public inbound? | Notes |
|---|---|---|---|
| WhatsApp (Cloud API) | Meta POSTs to your webhook | Yes | No polling alternative — webhook is mandatory |
| Microsoft Teams | Teams POSTs change notifications | Yes | No polling fallback |
| Telegram | setWebhook registers your URL; Telegram POSTs updates | Yes | A getUpdates polling fallback is not implemented |
| Generic webhook trigger | External system POSTs to /webhook/{group_id}/{trigger_id} | Yes | The whole point is to receive external calls |
| Google Chat | Webhook or Pub/Sub | Only in webhook mode | Switch to Pub/Sub mode to make it outbound-only |
| Slack | Socket Mode (outbound WS) or Events webhook | No, with Socket Mode | Socket Mode opens an outbound WebSocket to Slack, so no inbound is needed |
| Gmail | Relay polls the Gmail API | No | Outbound polling loop |
| Outlook / email | Relay polls the provider | No | Outbound polling loop |
| Knowledge base sync | Worker polls the source | No | Periodic outbound polling |
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.