Orbit Console administrator guide
Documentation home · User guide
Service model and access
Orbit Console serves a FastAPI backend and browser UI on port 8080. The server
loads a registered kubeconfig for each Kubernetes operation. It does not
automatically use an in-cluster service account or a mounted default kubeconfig;
configurations must be registered in its registry.
The application provides no built-in authentication, user management, per-user registry isolation, or application-level authorisation. All users reaching an instance can select any registered configuration and operate with its credentials. Kubernetes RBAC remains the enforcement point for cluster operations. Treat the console as a shared privileged administration tool.
Place authentication and TLS termination in an upstream proxy or ingress and
restrict direct backend access. Protect /api/* and /ws/* as well as the UI.
The application currently configures permissive CORS; it is not an access-control
boundary. Browser shell traffic uses /ws/object/exec, so the proxy must support
WebSocket upgrades, authentication on that path, and suitable session timeouts.
The frontend uses root-relative paths and expects to be served at /.
Runtime configuration
| Variable | Default | Effect |
|---|---|---|
ORBIT_CONFIG_DIR |
/configs |
Writable registry directory holding kubeconfig files and index.json. |
ORBIT_CONFIG_DIR_FALLBACK |
.local-configs |
Used if creating the primary directory raises an exception. Relative paths resolve from the process working directory. |
CONTEXTS_READONLY |
false |
Disables kubeconfig registration and removal in the API and UI. True values are 1, true, yes, on, ignoring case and surrounding whitespace. |
These values are read at application startup; restart the process after changing
them. CONTEXTS_READONLY does not prevent context selection, patching or deleting
Kubernetes resources, reading logs, or opening shells. Use restricted kubeconfig
credentials when Kubernetes operations need to be read-only.
Fallback occurs only when creating the primary directory fails. It does not handle later failures to read or write an existing directory. In production, confirm that the intended persistent path is writable and in use: a fallback to container-local storage can make registrations disappear after replacement.
Run locally
Run from the repository root, because static files and templates use relative paths. For a local Python environment:
python3 -m venv .venv
. .venv/bin/activate
python -m pip install fastapi uvicorn kubernetes jinja2 python-multipart websockets
ORBIT_CONFIG_DIR="$PWD/.local-configs" \
python -m uvicorn app.main:app --host 127.0.0.1 --port 8080
Open http://127.0.0.1:8080 and register a kubeconfig. This installs runtime
dependencies for local use; the repository's Dockerfile defines the Alpine
package set used for its container build.
To run an approved release from the project's GitLab registry, replace
<approved-tag> and the host storage path below:
docker run --rm --name orbit-console \
-p 127.0.0.1:8080:8080 \
-e ORBIT_CONFIG_DIR=/configs \
-v /path/to/persistent/configs:/configs \
registry.gitlab.com/tak-os-platform/tak-os-containers/orbit-console:<approved-tag>
Ensure the mounted directory is writable by the container's runtime user. The
existing test.sh helper builds a local image and mounts .local-configs at
/configs; it also mounts a kubeconfig under /root/.kube/config, but that mount
does not register it in the application.
Kubernetes and Orbit Deploy
The companion tak-os-orbit-deployments/orbit-console project contains the Orbit
Deploy templates. Its deployment README specifies a Global Orbit Deployment in
kube-system:
apiVersion: k8s.tlspu.com/v1
kind: OrbitDeployment
metadata:
name: orbit-console
namespace: kube-system
spec:
source: https://gitlab.com/tak-os-platform/tak-os-orbit-deployments/orbit-console.git
The companion templates currently define:
| Resource | Configuration |
|---|---|
Deployment orbit-console |
One replica; container port 8080; ORBIT_CONFIG_DIR=/configs. |
PVC orbit-console-configs |
1Gi, ReadWriteOnce, mounted at /configs. |
Service orbit-console |
ClusterIP, port 8080 to container port 8080. |
Ingress orbit-console |
Root path on orbit-console.<domain>, TLS and long proxy timeouts; authentication annotations conditional on the oauth2-proxy Orbit Deployment. |
| Readiness and liveness | HTTP GET /api/health on port 8080. |
Review the rendered ingress and verify authentication before exposing it. The templates contain Orbit Deploy substitution and conditional syntax, so they must be rendered by Orbit Deploy before use as ordinary Kubernetes manifests.
Use one application process writing the registry at a time. The registry uses a
JSON file with atomic replacement, but has no lock around read-modify-write
operations. Multiple writers can lose updates. The companion rolling update
allows a surge pod; account for overlapping writers and ReadWriteOnce volume
attachment constraints when choosing rollout procedures. A stop-then-start
rollout avoids concurrent registry writers at the cost of downtime.
Allow outbound connections from the console to every registered Kubernetes API
server, with DNS and certificate validation working from the pod. Browser access
to cdn.jsdelivr.net supplies xterm.js 5.3.0, its CSS, and the fit addon 0.8.0.
Restricted environments must account for those external terminal assets.
Provision and maintain kubeconfigs
Use kubeconfigs from trusted administrators. They can contain credentials and authentication commands executed by the Kubernetes client on the console server. Prefer self-contained configurations with embedded certificate data where appropriate. Referenced files must exist at paths usable inside the runtime; exec authentication also requires its helper executable and environment there. The base image does not include every cloud provider's authentication tools.
Start with the permissions needed by the intended operators:
| Operation | Kubernetes access needed |
|---|---|
| Populate the tree | API discovery and list on resource kinds in the selected scope. |
| Populate namespace choices | list on core namespaces. |
| Read details and owners | get on selected resources and their owners. |
| Read logs | get on pods for details/container selection and on pods/log. |
| Open shell | Pod read access and get on pods/exec, matching the client's GET exec connection. |
| Edit | patch on the target resource; optional list on CRDs for schema lookup. |
| Delete | delete on the target resource. |
| Resolve Orbit Deploy provenance | list on orbit-deployments in API group k8s.tlspu.com, in the searched namespaces or across the cluster. |
These are operation requirements, not a recommendation to grant all of them. The UI is designed for cluster administrators; limited credentials may produce partial trees, missing namespace choices or incomplete ownership results.
Register configurations through the UI, or POST a JSON object with name and
kubeconfig to /api/configs through the authenticated service. Provision approved
entries before enabling CONTEXTS_READONLY=true, then restart. The lock rejects
registration and removal with HTTP 403; it does not make the filesystem
read-only.
Each successful registration creates a separate <config_id>.kubeconfig file
and a corresponding entry in index.json, including its contexts and default
context. Copying a kubeconfig into /configs alone does not register it. Context
names are extracted at registration, so replacing a file directly can leave the
index stale; use removal and registration for routine replacement. There is no
in-place update endpoint. Register and verify a replacement before removing the
old entry when continuity matters.
The application writes kubeconfigs as ordinary files without application-level encryption or explicit restrictive file modes. Restrict directory permissions, control the process umask, and protect the volume and backups as credential stores. A failed registration can leave an unindexed file because the file is written before validation; inspect and remove confirmed orphan files during maintenance. Do not delete files referenced by the index.
Removing a registration deletes its stored file and index entry. Revoke or rotate the underlying credential separately when removing access. Upstream sign-out does not revoke a stored Kubernetes credential.
Backup, restore and upgrades
Back up the entire active registry directory, including index.json and all
referenced kubeconfig files. Include any external credential files separately.
Record runtime settings, the deployed image tag, and proxy/ingress configuration.
The registry backup contains no Kubernetes workload data; back up managed
clusters through their own procedures.
For a consistent backup, stop the application or otherwise quiesce registration and removal while taking the copy or volume snapshot. Store it with restricted access and encryption appropriate for cluster credentials.
To restore:
- Stop the application and preserve the current registry if present.
- Restore the directory contents together, preserving index-to-file relationships.
- Set ownership and permissions so the runtime can read and write the directory.
- Mount it at
ORBIT_CONFIG_DIRand restart with the intended settings. - Check
/api/health, list registrations, then test a context with a harmless read operation. Confirm no fallback directory was used.
Before upgrading, back up the registry and record the previous image. Verify the
new release using health, persisted registrations, resource browsing and, if
required, logs and shell access. The companion Deployment has
revisionHistoryLimit: 0, so retain the previous image/configuration explicitly
instead of relying on Deployment revision history for rollback. Restore the
prior image through the deployment's source configuration if rollback is needed.
Health and troubleshooting
curl --fail http://127.0.0.1:8080/api/health
Expected response: {"status":"ok"}. This is process health only: it does not
validate stored credentials, registry writes, Kubernetes connectivity or browser
shell access. Uvicorn logs go to the process/container output. No application
metrics endpoint or per-user audit trail is implemented; use proxy and Kubernetes
audit facilities where needed.
For the companion deployment, these commands inspect state without modifying it:
kubectl -n kube-system get deployment,pods,service,ingress,pvc
kubectl -n kube-system logs deployment/orbit-console
| Symptom | Investigation |
|---|---|
| Startup fails | Check the working directory, installed dependencies, registry permissions and valid index.json. |
| Registrations disappear after restart | Verify the mounted volume, ORBIT_CONFIG_DIR and whether fallback storage was used. |
| Kubeconfig registers but cannot connect | Registration parses contexts only. Check API endpoint reachability from the runtime, CA data, credentials, external files and exec helpers. |
| Namespace list or tree is incomplete | Check discovery and list permissions. Resource listing exceptions are skipped; namespace-list failures yield no namespace choices. |
| Browsing takes a long time | Discovery lists each eligible resource type, and does not use a watch. Try a specific namespace and inspect API availability and cluster size. |
Configuration POST/DELETE returns 403 |
Check CONTEXTS_READONLY; other object-operation failures may originate in Kubernetes RBAC. |
| Shell fails | Check WebSocket proxying and authentication, browser terminal asset loading, pods/exec access, selected container state and /bin/sh. |
| Ownership lookup is incomplete | Check owner access and discovery. Unknown kinds fall back to heuristic pluralisation. Orbit Deploy lookup also needs its API and list permissions. |
| Edit fails or has unexpected results | Check Kubernetes validation and patch permissions. The generated form is limited; use normal Kubernetes tooling for complex patches. |
API reference
FastAPI exposes generated API documentation at /docs and an OpenAPI document at
/openapi.json. Protect those routes with the rest of the service. The repository's
docs/ directory contains these Markdown guides and is not mounted as web content.
| Method | Path | Purpose |
|---|---|---|
| GET | /api/health |
Process health. |
| GET | /api/configs |
Registrations and contexts_readonly. |
| POST | /api/configs |
Register { "name": "...", "kubeconfig": "..." }. |
| DELETE | /api/configs/{config_id} |
Remove a registration and its file. |
| GET | /api/resources/populated |
Populated kinds and object summaries for scope=ALL, CLUSTER or a namespace. |
| GET | /api/objects |
List one resource type. |
| GET | /api/object |
Read a full object. |
| PATCH | /api/object |
Apply { "object": { ... } } as a merge patch. |
| DELETE | /api/object |
Delete a Kubernetes object. |
| GET | /api/object/edit-schema |
CRD schema or a generic fallback. |
| GET | /api/object/owners |
Owner tree and linear provenance chain. |
| GET | /api/object/logs |
Plain-text pod logs; tail_lines defaults to 300. |
| WebSocket | /ws/object/exec |
Interactive pod shell using text input/output. |
Cluster operations use config_id and optional context query parameters.
Resource operations use api_version and the API resource's plural; single-object
operations also require name and a namespace for namespaced objects. Listing
supports all_namespaces. Logs and exec use namespace, pod_name, and optional
container. Exec's WebSocket route is not included in the generated OpenAPI
documentation.
