Deployment Configuration
The backend ships with a Helm chart (charts/ska-octopus-backend) that exposes
a concise values.yaml interface. This page explains each value, how it maps to
the running container, and the typical ways you can override the defaults for a
production deployment.
Chart Structure at a Glance
The chart is designed around a single backend Deployment, an optional MongoDB
dependency, and supporting K8s primitives (Service, Ingress, secrets).
The relevant values file is located at:
ska-octopus-backend/charts/ska-octopus-backend/values.yaml
Each section in the values file configures a specific cluster resource:
Section |
Controls |
Typical overrides |
|---|---|---|
|
Backend container image reference. |
Pin to an internal registry tag or your own build. |
|
ClusterIP port exposed for other services. |
Rarely changed; adjust if 8000 clashes. |
|
Host and path routing to the backend Service. |
Set to match your ingress controller and DNS hostname. |
|
Config UI credentials (inline value or existing secret). |
Provide a unique secret in production. |
|
Local |
Supply production-local accounts or disable when MSAL is used exclusively. |
|
Environment variables projected into the container. |
Override service URLs, feature toggles, and fallback secrets. |
|
Auxiliary Tango components for end-to-end testing. |
Toggle on for demo clusters; off in production. |
Backend Image and Scaling
Set the backend image via:
image:
backend:
repository: harbor.skao.int/staging/ska-octopus-backend
tag: 0.1.48
pullPolicy: IfNotPresent
repositoryandtagmust point to the container that includes the backend build you want to deploy.pullPolicycan be tightened toAlwayswhen usinglatest-style tags or loosened toIfNotPresentfor repeatable releases.
Replica counts are controlled independently for the backend API and the static frontend bundle used by the Config UI:
replicaCountBackend: 1
replicaCountFrontend: 1
Increase replicaCountBackend for availability or throughput. Only raise
replicaCountFrontend if you rely on the built-in static Config UI hosting.
Service and Ingress
The service block defines the internal ClusterIP port:
service:
backend:
port: 8000
If you front the backend with an ingress controller, set the host/path configuration to match your DNS and routing requirements:
ingress:
enabled: true
host: octopus.example.org
paths:
backend: /octopus
Leaving
hostblank allows other charts (such asska-octopus) to inject the value.When
paths.backendis empty, the ingress routes requests to/.If you deploy with the provided Makefile defaults (
KUBE_NAMESPACE=octopus,HELM_RELEASE=ska-octopus-backend), the chart automatically renders the base path as/octopus/ska-octopus-backend, so the GraphQL explorer lives athttps://<ingress-host>/octopus/ska-octopus-backend/graphqlunless you override the path.
Base path helper and chart scoping
Helm template names are global. To avoid collisions with sibling Octopus charts
(e.g., the frontend), this chart exposes a namespaced helper
ska-octopus-backend.basePath. It always reads ingress.paths.backend, and the
value is reused in:
Ingress path rules (
<basePath>/graphql,<basePath>/auth, etc.).The
ROOT_PATHenvironment variable inside the backend container.
Keep the backend and frontend base paths aligned by setting both
ingress.paths.backend and ingress.paths.frontend in a shared values file:
ingress:
host: octopus.example.org
paths:
backend: /octopus
frontend: /octopus
This ensures the SPA and API live under the same prefix and avoids accidental mix-ups when multiple charts are rendered together.
Config UI Credentials
The Config UI requires a password to access administrative screens. The chart supports two patterns:
Reference an existing secret (
configUi.password.secretName/secretKey).Have Helm create a secret by providing
createSecret: trueand a literalvalue.
configUi:
password:
createSecret: false
secretName: octopus-config-ui-password
secretKey: cfg-ui-password
optional: false
value: ""
Secret-config-ui (recommended): create a secret containing the config-ui password and point
secretName/secretKeyat it. Example:kubectl -n ska-octopus-suite create secret generic octopus-config-ui-password \ --from-literal=cfg-ui-password='super-secret-password' \ --dry-run=client -o yaml | kubectl apply -f -
The backend reads the projected value into the CFG_UI_PASSWORD environment
variable at runtime, hashing it internally. Set optional: true if you provide
the password through another channel (for example, a Vault operator).
Local Auth Users
Local development and some deployments rely on static username/password pairs
for /auth/login. Populate those accounts via the authUsers block:
authUsers:
createSecret: false
secretName: octopus-auth-users
secretKey: auth-users.json
envVarName: OCTOPUS_AUTH_USERS
optional: false
value: ""
JSON payload: supply a JSON list or mapping of users. Each entry may include
username,password(plaintext),hashed(precomputed bcrypt),role,groups, andfull_name.Secret-backed (recommended): create a secret containing the JSON payload and point
secretName/secretKeyat it. Example:kubectl -n ska-octopus-suite create secret generic octopus-auth-users \ --from-literal='auth-users.json=[{"username":"admin","password":"change-me","role":"Admin"}]' \ --dry-run=client -o yaml | kubectl apply -f -
Set
createSecret: trueto have Helm emit anOpaquesecret using the literalvalue. This keeps simple test clusters self-contained.
The backend reads the JSON into memory at startup. If no valid user entries are found, it falls back to the built-in development accounts.
Environment Variables (vars)
The vars section projects configuration into the container as environment
variables. Each entry can be:
A simple string, rendered directly.
A mapping with rich options:
JWT_SECRET:
value: s3cr3t
secretName: octopus-jwt
secretKey: token
optional: false
useSecretLookup: true
Field semantics:
Field |
Description |
When to use |
|---|---|---|
|
Default literal applied when no secret is available. |
Provide safe development fallbacks. |
|
Name of the Kubernetes secret to source. |
Reference platform-managed secrets. |
|
Key within the secret. |
Override when the secret uses non-default key names. |
|
Mark the projection as optional. |
Set to |
|
When |
Disable for secrets created during the upgrade itself. |
|
Provide a raw |
Needed for advanced projections. |
Common entries include database DSNs, external API URLs, feature toggles, and widget registry settings. Review the upstream defaults for inspiration and override them in your environment-specific values file.
Warning
Before deploying to any shared cluster, update backend vars in your values
overlay. The defaults in charts/ska-octopus-backend/values.yaml target test
services and will not match SKAO production endpoints.
Key vars to verify for every deployment:
Tango connectivity:
TANGO_DBSandTANGO_HOST.EDA (HDB++) DSN:
HDBPP_PG_DSN_EDA(setsecretName/secretKeyor a literal value).ODA API URL:
ODA_URL.Data stores and auth:
MONGO_URI,JWT_SECRET,ALLOWED_ORIGINS.Auth provider selection:
AUTH_PROVIDER(comma-separated list; supported values:local,keycloak,msal; multiple providers can be active simultaneously, e.g.AUTH_PROVIDER=local,keycloak).Keycloak (when
keycloakinAUTH_PROVIDER):KEYCLOAK_URL,KEYCLOAK_REALM,KEYCLOAK_CLIENT_ID,KEYCLOAK_AUDIENCE, andKEYCLOAK_ROLE_*(see Keycloak Setup for Octopus).Widget registry:
WIDGET_ARTEFACT_BASE,WIDGET_ALLOWED_HOSTS,WIDGET_ALLOWED_NPM_SCOPES.
Optional MongoDB
The chart can spin up a single-node MongoDB instance for development clusters:
mongodb:
enabled: true
image: mongo:6.0
auth:
enabled: false
service:
port: 27017
Disable this block when using a managed service by setting enabled: false
and updating the corresponding URLs in vars.
Tango, Test Devices, and Demo Helpers
Two optional subcharts help create a fully self-contained demo environment:
ska-octopus-tangogqlcpp: toggles the Tango GraphQL gateway (C++ implementation). Enable this when you need Tango data in a sandbox cluster. Itsconfig.attributePrefetchThreadsvalue defaults to8, providing one process-wide device-prefetch pool shared fairly across station requests. Fallback subscriptions use a separate fixed pool configured byconfig.subscriptions.pollThreads(default4), so tracking a large fleet does not allocate one sleeping thread per device.octopus-tangodevice: deploys the Tango test device used in end-to-end pipelines. Customize the environment variables (DEVICE_PRESET,PUSH_DELAY, etc.) to match your testing scenario.
Both sections default to enabled: false to keep production clusters lean.
Putting It All Together
For production, maintain a dedicated values overlay that:
Points
image.backendto a released tag.References platform-managed secrets for
configUi.password,authUsers, and any sensitive entries undervars.Disables bundled MongoDB when external services are provided.
Sets ingress host/path to match your DNS.
Raises replica counts to meet availability targets.
Apply the release with:
helm upgrade --install ska-octopus-backend ./charts/ska-octopus-backend \
--namespace ska-octopus-suite \
-f values-production.yaml
This approach keeps secret material out of version control while making the deployment repeatable across environments.
GraphQL upstream HTTP pooling
Dynamic HTTP GraphQL resolvers share one aiohttp.ClientSession and connection
pool per backend worker. Per-request authentication is passed explicitly and
response cookies are never retained. This avoids creating/leaking a session or
opening a fresh DNS lookup and TCP connection for every browser query. The pool
can be tuned with:
GQL_HTTP_CONNECTION_LIMIT(default256): maximum open connections per worker.GQL_HTTP_DNS_CACHE_TTL_S(default300): Kubernetes DNS cache lifetime in seconds.GQL_HTTP_KEEPALIVE_TIMEOUT_S(default30): idle connection lifetime in seconds.
OIDC token verification and JWKS retrieval run outside the asyncio event loop, so an initial identity-provider lookup cannot stall unrelated GraphQL calls.