§08 · Deploy & operate

Install with exo-install

The recommended path. One binary applies the CRDs, the operator, and the platform through your own kubectl, with pre-flight checks and generated secrets.

exo-install installs the whole platform. The manifests are embedded in the binary and applied through your existing kubectl, so your kubeconfig auth (exec plugins, OIDC, cloud IAM) works unchanged. It never talks to the API server directly; it runs kubectl apply, so dry-runs, RBAC, and audit behave exactly as they do for your own manifests.

What exo-install does

It installs three layers in dependency order: the six autonomic.sh CRDs, the autonomic-manager operator (Deployment, RBAC, admission webhook), and the platform (backend/UI Deployment, Service, Secret, ConfigMap, and an optional in-cluster Postgres). The embedded manifests are pinned copies derived from the operator manifests under exo/exo-install/manifests/ and the repo-root deploy.yaml. Defaults point at the published images: docker.io/adaptivelive/autonomic-manager for the operator and docker.io/adaptivelive/exo (pinned to the installer's own release tag) for the platform. Any secret you don't supply is generated.

Set EXO_ENCRYPTION_KEY

EXO_ENCRYPTION_KEY is the 32-byte AES-256 root key that wraps every encrypted column, and the backend won't start without it. The installer auto-generates one when you don't pass --encryption-key (or leave the interactive prompt blank), then prints it once after install:

after install (stderr)
⚠ SAVE YOUR ENCRYPTION KEY — back it up now
EXO_ENCRYPTION_KEY=4f3c2a9e8b7d6c5a4f3c2a9e8b7d6c5a

Copy that value somewhere safe immediately. To supply your own instead:

terminal· bash
exo-install install --yes --encryption-key "$(openssl rand -hex 16)"

Commands

exo-install <command>· text
1(none) Launch the guided full-terminal installer
2precheck Verify toolchain, cluster reachability, and RBAC (alias: check)
3install Install CRDs + operator + platform (alias: apply, up)
4crds Install only the six autonomic CRDs
5operator Install CRDs + operator (manager, RBAC, webhook)
6platform Install only the backend/UI (+ optional Postgres)
7render Print rendered manifests to stdout, apply nothing (alias: template)
8config Write a config file via the interactive wizard
9uninstall Remove selected components in reverse order (alias: down)
10version Print the installer version

install runs the pre-flight checks first unless you pass --skip-precheck. Configuration resolves in three layers, each overriding the last: built-in defaults → --config file → CLI flags.

Pre-flight checks

exo-install precheck validates the environment before you touch the cluster. Hard failures abort the install; advisory ones only warn.

what precheck verifies· text
1Binaries kubectl (required) · helm (required with --helm) · docker, git (advisory)
2Cluster current context set (required) · API reachable via cluster-info (required)
3 server version (advisory)
4RBAC can-i create: customresourcedefinitions, clusterroles,
5 namespaces, deployments (advisory — warns, does not block)

Interactive mode

Run it with no arguments for a guided full-terminal installer: arrow-key menus, inline validation, masked secret entry. It walks namespaces and images → database choice → secrets & operator mode → cluster connection → component selection → pre-flight → plan → apply.

terminal· bash
exo-install

Scripted install

For CI or a repeatable runbook, drive it by subcommand and flags:

terminal· bash
exo-install precheck
exo-install install --yes
exo-install install --dry-run

--yes skips confirmation prompts; --dry-run sends kubectl apply --dry-run=server so the API server validates without mutating. --timeout (default 5m) bounds each rollout wait.

Installing individual pieces

Each component has its own subcommand, useful for split-cluster topologies:

terminal· bash
exo-install crds
exo-install operator --managed --base-url https://exo.example.com
exo-install platform --namespace exo --image adaptivelive/exo:v0.4.8
exo-install render crds | kubectl apply -f -

What gets created

CRDs: two namespaced resources in group autonomic.sh/v1alpha1: agents and tools. The installer waits for each to report established before moving on.

operator → ns autonomic-system (default)· text
1ServiceAccount/autonomic-manager
2ClusterRole + ClusterRoleBinding/autonomic-manager (CRDs, deployments, pods/exec,
3 secrets, leases, webhooks, RBAC)
4Service/autonomic-manager 443 webhook · 8080 metrics · 8081 probes · 8082 invoke
5Deployment/autonomic-manager --leader-elect, replicas=1, non-root
6ValidatingWebhookConfiguration/autonomic-pods-exec (pods/exec + tool admission;
7 omitted with --webhook=false)
platform → ns exo (default)· text
1Secret/exo-secrets EXO_ENCRYPTION_KEY · EXO_JWT_SECRET · EXO_DATABASE_DSN · EXO_CLAUDE_API_KEY
2ConfigMap/exo-config EXO_PORT=9092 · EXO_JWT_EXPIRY
3Service/exo-app 9092/TCP, type ClusterIP (default)
4Deployment/exo-app replicas=2, /api/health probes, rolling update
5StatefulSet/exo-postgres postgres:16-alpine + 10Gi PVC (omitted with --postgres=false)

Flag reference

Connection & execution. These control kubectl and how the install runs.

global flags· text
1--kubeconfig <path> kubeconfig file (default: $KUBECONFIG / ~/.kube/config)
2--context <name> kube-context (default: current-context)
3--dry-run server-side validate, no mutations
4--config <file> load config from JSON (flags still override)
5--interactive prompt for config
6--skip-precheck skip pre-flight checks (not recommended)
7--yes assume yes to prompts
8--timeout <dur> per-rollout wait (default: 5m)
9--helm install the operator via its Helm chart
10--helm-chart <path|ref> chart location (required with --helm)

Operator. The autonomic-manager deployment.

operator flags (defaults)· text
1--operator-namespace autonomic-system
2--manager-image docker.io/adaptivelive/autonomic-manager:v0.3.1
3--manager-pull-policy IfNotPresent
4--operator-replicas 1
5--managed false (phone home to --base-url)
6--base-url https://exo.adaptive.live
7--webhook true (pods/exec + tool admission webhook)
8--webhook-failure-policy Fail (or Ignore)
9--webhook-timeout 5 (seconds)

Platform. The exo-app backend/UI deployment.

platform flags (defaults)· text
1--namespace exo
2--image docker.io/adaptivelive/exo:latest
3--pull-policy IfNotPresent
4--replicas 2
5--service-type ClusterIP (or NodePort, LoadBalancer)
6--jwt-expiry 24h
7--jwt-secret "" (auto-generated if blank)
8--encryption-key "" (EXO_ENCRYPTION_KEY, 32 bytes; auto-generated + printed if blank)
9--claude-api-key "" (platform-default Anthropic key, base64'd; optional)

Database. In-cluster Postgres or an external instance.

database flags (defaults)· text
1--postgres true (deploy in-cluster Postgres StatefulSet)
2--db-dsn "" (external DSN, required when --postgres=false)
3--pg-user exo
4--pg-password "" (auto-generated if blank)
5--pg-db exo
6--pg-storage 10Gi (PVC size)

Generated secrets

Any secret you don't supply is generated at apply time and written into the cluster Secrets, never logged:

auto-generated· text
1EXO_ENCRYPTION_KEY 32 hex chars when --encryption-key is blank → Secret/exo-secrets (SAVE IT)
2EXO_JWT_SECRET 64 hex chars when --jwt-secret is blank → Secret/exo-secrets
3POSTGRES_PASSWORD 36 hex chars when --postgres and no pw → Secret/exo-postgres
4EXO_DATABASE_DSN derived from the in-cluster Postgres → Secret/exo-secrets

Bring your own database

Skip the bundled Postgres and point the platform at a managed instance:

terminal· bash
exo-install install --postgres=false \
--db-dsn "host=db.example.com user=exo dbname=exo sslmode=require"

Config files

Capture every knob in a JSON file and reuse it; flags still override the file.

terminal· bash
exo-install config -o exo-install.json
exo-install install --config exo-install.json --namespace staging
exo-install.json (excerpt)· json
1{
2 "operatorNamespace": "autonomic-system",
3 "managerImage": "docker.io/adaptivelive/autonomic-manager:v0.3.1",
4 "operatorManaged": false,
5 "operatorBaseURL": "https://exo.adaptive.live",
6 "webhookEnabled": true,
7 "platformNamespace": "exo",
8 "platformImage": "docker.io/adaptivelive/exo:latest",
9 "platformReplicas": 2,
10 "serviceType": "ClusterIP",
11 "jwtExpiry": "24h",
12 "postgres": true,
13 "postgresStorage": "10Gi"
14}

Helm for the operator

Uninstall

Removes components in reverse order: platform → operator → CRDs.

terminal· bash
exo-install uninstall