Deployment Prerequisites
Audience: operators installing a Stella Ops deployment or planning to add tenants to one.
This runbook defines the operator prerequisites for adding tenants under a single operator trust boundary. It is anchored in ADR-005.
Trust Boundary
Run Stella Ops inside one operator trust boundary. All tenants in a deployment must share the same operator, security team, incident-response authority, and data-residency posture. Do not expose tenant self-service signup, and do not use one deployment as shared SaaS infrastructure for unrelated tenants.
Tenant Inventory Expectations
Tenants are expected to represent environments, business units, sub-organizations, or other logical scopes under the same operator. When you add a tenant, prove that both stores agree: Authority’s tenant catalog and Platform’s shared.tenants projection must list the same tenant. The QA reference shape for this is the tenant-fairness fixture FIXTURE-T7-001.
Resource Headroom
Operators must monitor shared deployment resources at the deployment level: PostgreSQL volume free space, RustFS or object-store capacity, and router QPS. Stella Ops does not currently enforce per-tenant storage quota, per-tenant object-store quota, or tenant-partitioned router rate limits.
Offboarding
Tenant offboarding is soft-suspend only today through Authority’s POST /console/admin/tenants/{tenantId}/suspend. Hard tenant-delete is manual and cross-database: every service owns its own database, so tenant data sits in each of them. There is no supported product endpoint that deletes all tenant data, validates every database, and records a dry-run audit. The QA plan tracks the hard-delete test shape as TOPO-124.
Release-bundle install sequence
Verified 2026-09-26 against 942a18727c, in devops/release/bundle/install.sh and its PowerShell twin install.ps1, which run the same steps. The bundle README is the customer-facing version.
- Check prerequisites. Docker with the Compose v2 plugin, a reachable daemon and
openssl(Linux and macOS; PowerShell uses .NET). The installer warns below 4 vCPU, 16 GiB RAM or 50 GB free disk. On Linux, a non-root install that is not uid 10001 also needssetfacl. The bundle must containdocker-compose.pinned.yml, the digest-pinned stack written at release; the installer starts that file only and stops when it is absent (PCD-1, 2026-09-26). The tag-formdocker-compose.ymlresolves every image toSTELLA_VERSION, which is not the tag every service is pinned at, so it is never the start path. - Verify the bundle. When
release-manifest.yaml.sig, a public key andcosignare present, the signature must verify or the install stops. Every file checksum in the manifest is then checked; a mismatch stops the install. - Generate
.env. From.env.example, eachGENERATED_*placeholder gets its own random value, and eachSTELLAOPS_POSTGRES_<SERVICE>_CONNECTIONline gets its own password. The administrator password is drawn to satisfy Authority’s shipped password policy (config/etc/authority/plugins/standard.yaml). A re-run keeps an existing.envand refuses a hand-set administrator password that breaks the policy. - Generate installation key material. Signing keys, the gateway certificate, the per-install CA bundles and the agent CA passphrase; see Installation Secrets.
- Prepare runtime directories, then stop here when run with
--no-start(-NoStart). That run prints the start command:docker compose --env-file .env -f docker-compose.pinned.yml -f secrets/docker-compose.installation.yml up -d. - Pull images by the pinned references, or use local images with
--offline(-Offline). - Start the stack and wait for health. First start runs every service’s own migrations. The installer also stops with Authority’s own reason when Authority logs that it could not create the administrator.
- Import the offline vulnerability-data seed. When the bundle carries
data/vulnerabilities/mirror-seed.v1.ndjson.sha256, the installer checks the seed bytes against it and imports them into the Vulnerabilities hub through the hub’s own import route. The outcome is recorded instate/vulnerability-seed-import.json; a re-run skips a seed already imported. The seed is third-party data under its sources’ terms, and the installer prints the pointer tothird-party-licenses/DATA-NOTICES.md(“Hub mirror seeds”). - Print the console address. The URL uses
STELLA_PUBLIC_HOST, the origin Authority registers for the console. WithSTELLA_BIND_ADDRESS=0.0.0.0and no public host, the installer warns that browser sign-in will fail.
What the first start configures without an operator step:
- One database and role per service.
config/postgres-init/20-service-databases.shderives them from the connection lines in.env. The services the bundle starts, and the database each one uses, are listed in the generated service inventory; the migration authority per database is in the ownership matrix. - Doctor registration. The services with a
*_DOCTOR_REGISTRATION_ENABLEDline in.env.exampleregister their checks with Platform’s Doctor registry at start. Each switch is on by default; set one tofalseto stop that service registering. - Trust of the gateway certificate. Every service mounts the generated CA bundle, so internal HTTPS to the gateway and Authority verifies.
- Signals posture drain. The bundle’s
.env.examplesetsSIGNALS_ENVIRONMENT_STATE_REPLICA_ENABLED=trueandSIGNALS_DOCTOR_REGISTRATION_ENABLED=true, and the installer generatesSTELLAOPS_SIGNALS_DOCTOR_CLIENT_SECRET, sosignals’ posture replica has a configured drain and the service reaches healthy on a fresh install (SPRINT_20260925_001CIC-4). No other bundle service declares a start dependency onsignals.
Installation Secrets
A release-bundle install generates its per-installation secrets before the first start, and never ships them. install.sh and install.ps1 write them into the bundle directory, where the bundle’s compose file mounts them. A re-run keeps every key file and passphrase that already exists, so a secret is never replaced by accident. The CA bundles under secrets/ca/ are the exception: they are rebuilt on every run from the shipped bundle plus the installation’s gateway certificate. The full list is in the bundle README, section “Secrets and keys the installer generates” (devops/release/bundle/README.md). Three of them decide whether a service starts:
config/etc/jobengine/keys/packsregistry-export-dev.pemand.pub.pem. An EC P-256 key pair, mounted read-only at/app/etc/jobengine/keys/.jobengine-websigns the PacksRegistry offline-seed export with the private key and refuses to start when the configured file is missing. Give the public key to anyone who verifies an export; see Pack signing and RBAC.secrets/packsregistry/packs-signing.pem, with its public halfconfig/etc/jobengine/keys/packs-signing.pub.pem. An RSA 3072 key pair.jobengine-webruns theProductionhosting environment and reads the public half, mounted read-only at/app/etc/jobengine/keys/, as its pack verification key; it refuses to start when that file is missing or empty. The installer signs the shipped pack seed with the private half intosecrets/packsregistry/seed/, rewriting it on every run, andjobengine-webrefuses an unsigned seed. The private half is never mounted. Back it up: a new key re-signs the seed, and packs signed with the old key no longer verify.secrets/registry/agent-ca-root-password. The passphrase of the Release Orchestrator agent CA root keystore, mounted read-only at/etc/secrets/agent-ca-root-password..envpointsRELEASE_ORCHESTRATOR_AGENT_CA_ROOT_PFX_PASSWORD_FILEat it. A configured passphrase file is authoritative, so a missing or empty file stopsrelease-orchestrator. Back it up withsecrets/registry/agent-ca/: replacing it locks the host out of the keystore, and every enrolled agent then has to be re-enrolled.
To supply your own custody-managed material instead, place it at the same path before running the installer. The installer keeps it.
What This Deployment Is NOT
- Not shared-tenancy SaaS for unrelated customers.
- Not a deployment where tenants are expected to defend against each other.
- Not a tenant self-service signup system.
- Not a deployment with per-tenant storage headroom enforcement.
- Not an automated hard-delete/offboarding system for tenant-scoped erasure.
Where To Read More
- ADR-005: Single-Operator Multi-Environment Tenancy
- ADR-002: Multi-Tenant Selection With Same API Key
- SaaS and MSP Licensing Guidance
- Multi-Tenant Same-Key Rollout and Compatibility Policy
- Multi-Tenant SaaS Prerequisites Roadmap
