Provisioning lifecycle
Desired state, jobs and runner
Provisioning converts a commercial subscription and onboarding choices into versioned desired state, then lets the privileged runner converge the host.
Lifecycle
Hosting Service
Mivama Hosting Service links Customer, Stripe subscription, plan/version, primary hostname and lifecycle status. It owns the current desired-state generation and the last observed runtime result. User-editable choices are not trusted runner input until normalized by Core.
Desired state
desired_state.py creates a canonical specification containing tenant identity, hostname, resource limits, image/runtime choices, locale, timezone, WordPress preset, allowed plugins, storage and service generation. Each generation is immutable and content-hashed.
This separates intent from execution:
- retries use the same validated spec;
- a stale runner cannot apply an old generation;
- manual host drift is discoverable;
- later upgrades create a new generation rather than mutating history.
Secrets are references or separately transported material, not embedded in public job responses.
Job claim and execution
jobs.py creates typed jobs such as Apply, Inspect, Suspend, Resume, Backup and Decommission. The runner:
- authenticates to the runner-only API;
- claims an available job;
- verifies service, type, generation and desired-state hash;
- takes a per-service lock;
- writes temporary spec/secrets with mode 0600;
- invokes the fixed playbook mapped to the job type;
- sends heartbeats and the final structured result;
- removes temporary material.
The runner is root because tenant Linux identities, directories, networking, quotas, reverse proxy and containers require host privileges. WordPress commands inside a tenant run as the tenant/application user.
Reconciliation
Subscription document hooks trigger lifecycle reconciliation immediately. A daily scheduler reconciles all hosting subscriptions in case a webhook or queue event was missed. Idempotent apply and inspect operations are preferred over manual host edits.
Sources: provisioning/desired_state.py, jobs.py, lifecycle.py and runner/mivama_runner.py.