Skip to content

// installation

Networking

Step 6 of 10 · Path A (bare metal)

Applies to

Product: Server · Audience: Platform Operator

DNS, TLS modes (cert-manager, existing secret, local), required outbound access and the network boundary between AISRV and inference. The network decisions flow directly into the Helm values – make them before the installation.

DNS

basebox runs under one hostname (global.domain) through which frontend, GraphQL (/graphql, /subscriptions), OpenAI-compatible API (/v1), application endpoints (/rest), media (/media) and Keycloak (/auth) are served. The hostname must resolve to the cluster's ingress IP – publicly, in internal DNS or, for evaluation, via /etc/hosts (basebox.local).

The hostname is also the basis for OIDC: the frontend expects VITE_BB_OIDC_DOMAIN as https://<domain>/auth/realms/ – with a trailing slash. The chart derives this from global.domain; if you change the hostname later, frontend and AISRV configuration must follow (failure patterns "Organisation not found", redirect loop – see FAQ).

TLS mode

global.tls.mode controls the chart's behaviour:

Mode Who provides the certificate AISRV JWKS mode When
cert-manager cert-manager creates and renews the secret global.tls.secretName via a ClusterIssuer JWKS URL Public domain with ACME (Let's Encrypt)
existing-secret You create a secret of type kubernetes.io/tls (tls.crt, tls.key) in the namespace; name = global.tls.secretName JWKS URL Internal CA, own certificate, private installation without internet
local The chart creates a self-signed secret (basebox-local-tls) if none exists JWKS file Evaluation (basebox.local); browser warns until a locally trusted certificate (e.g. mkcert) is provided

The hostname is not the distinguishing feature; basebox.internal can use local or existing-secret. What matters is the trust model. Let's Encrypt is not needed for private installations. Commands per mode: Using Helm charts.

Client devices must trust the issuing CA

With existing-secret and a certificate from your internal CA, and with local, the browser shows a secure connection only if the device trusts the issuing CA. Otherwise a security warning appears, even though the connection is encrypted.

  • Domain-joined PCs usually receive the root certificate of your internal CA automatically via group policy. Nothing to do there.
  • Devices not joined to the domain (test machines, personal devices, tablets) do not know the CA. Import the root certificate into the operating system's certificate store under "Trusted Root Certification Authorities", or distribute it through your device management.
  • Firefox may use its own certificate store. Enable security.enterprise_roots.enabled there or import the CA into Firefox itself.

With cert-manager and a public CA such as Let's Encrypt this step is not needed, because all devices already trust the CA.

Create an existing secret:

kubectl create namespace basebox --dry-run=client -o yaml | kubectl apply -f -
kubectl -n basebox create secret tls customer-tls \
  --cert=<PATH_TO_TLS_CERTIFICATE> \
  --key=<PATH_TO_TLS_PRIVATE_KEY>

Ingress

The chart ships nginx annotations you should know because they determine behaviour: proxy-body-size: 20m (uploads), large header buffers (JWT), proxy-read/send-timeout: 86400 (WebSocket, streaming), proxy-buffering: off (streaming), CORS (Authorization, Content-Type, X-Realm), cache control no-store. Details: Helm chart overview → Ingress configuration. A reverse proxy in front of the ingress must have the same properties – above all no buffering and long timeouts, otherwise streaming breaks.

Firewall

Inbound to the server:

Port Purpose
22/TCP SSH (restrict to the admin network)
443/TCP (80/TCP) Ingress for users and API clients
6443/TCP Kubernetes API – only if needed externally
10250/TCP Kubelet – only within the cluster

Outbound (installation and updates): HTTPS 443 to the package sources, NVIDIA, Kubernetes, Helm, registries and gitea.basebox.health – the full list with test commands under Required network access. Outbound in operation: only what integrations need – SMTP, LDAP/OIDC, connector target systems, web search provider (api.staan.ai or DuckDuckGo hosts). Overview of all paths: VPN / networking.

UFW example from Prepare the server:

sudo ufw allow 22/tcp && sudo ufw allow 443/tcp && sudo ufw allow 80/tcp
sudo ufw allow 6443/tcp && sudo ufw allow 10250/tcp
sudo ufw enable

The boundary AISRV ↔ inference

Users never talk to inference directly; only AISRV does. If inference runs on the same cluster, traffic stays internal (http://inference:8000). If it runs on a separate GPU host:

  • Only AISRV may reach the inference endpoint (firewall rule from AISRV nodes to the GPU host); end users may not.
  • The endpoint requires an API key, stored as a Kubernetes secret, never in values.
  • TLS when hosts or security zones are crossed. If the endpoint uses a certificate from a private CA, import the CA into the basebox workload – ingress certificate and inference certificate are separate trust decisions.
  • Prompts, retrieved context and document content travel over this path; both hosts belong in the same data processing boundary.

Worked example with values and verification steps: Deployment topologies.

Cluster DNS

On k3s with systemd-resolved, name resolution in inference and ragsrv-support fails ("Temporary error in name resolution"). Solution: point coredns at a reachable DNS server – FAQ.

Verify

nslookup <domain>                                   # points to the ingress IP
kubectl -n basebox get ingress                      # after installation: host = global.domain
kubectl -n basebox get secret <tls-secret> -o jsonpath='{.type}{"\n"}'   # kubernetes.io/tls
curl -fsSL https://gitea.basebox.health -o /dev/null && echo registry ok

Checklist

  • Hostname decided and set in DNS to the ingress IP
  • TLS mode chosen; certificate/secret or ClusterIssuer ready
  • Inbound ports 443 (and 22 for admins) open; 6443/10250 internal only
  • Outbound domains for installation allowed – or offline transfer
  • With external inference: firewall AISRV → GPU host, API key as secret, TLS/CA settled
  • Outbound paths for integrations (SMTP, LDAP/OIDC, connectors, web search) planned

Back: Storage · Next: Install basebox