Contabo Runtime Integration
Last updated: 2026-08-09
This is an internal operational document. Customer-facing surfaces use the term **HostAgentics Cloud**; the provider name appears publicly only in the legally required subprocessor disclosure.
1. Runtime topology
The HostAgentics control plane may remain on its independent application platform, but customer OpenClaw, Hermes, and n8n workloads run exclusively on Contabo infrastructure.
2. Contabo API contract
The implementation uses Contabo's official REST API at `https://api.contabo.com/v1`:
`/compute/instances/{id}/cancel` endpoint. Contabo does not expose `DELETE` for an instance.
Reference: <https://api.contabo.com/>
The provider reconciles a deterministic shard display name before instance creation, so a worker crash after the external API call does not buy a duplicate VPS on retry.
3. Host bootstrap and SSH trust
`packages/provider-contabo/src/bootstrap.ts` generates valid `#cloud-config` YAML. It installs a Base64-encoded, mode-0700 bootstrap script through `write_files` and executes it with `runcmd`; a raw shell script is rejected by Contabo's user-data validator. The script installs Docker, restic, rsync, Caddy's container service, unattended security upgrades, and a deny-by-default firewall. SSH password authentication and interactive authentication are disabled; root is key-only.
The control channel does not use blind trust-on-first-use. `CONTABO_SSH_HOST_KEY_SEED` derives a unique Ed25519 server identity from the deterministic shard name. Cloud-init installs that identity, and every worker connection verifies the exact SSH wire-format public key. Before cloud-init replaces the distro key and writes the readiness marker, connections fail closed and are retried.
`CONTABO_CONTROL_PLANE_CIDRS` must contain only the public egress CIDRs of API/worker hosts. Production validation also requires a digest-pinned `CONTABO_CADDY_IMAGE`.
Runtime secrets are deliberately excluded from provider-visible cloud-init. They are delivered only after verified SSH is available and stored in mode-0600 files.
4. Provisioning mapping
| Provider-core operation | Contabo implementation |
| ----------------------- | --------------------------------------------------------------------------------------------- |
| `createProject` | Reconcile/create a Contabo VPS with cloud-init |
| `createEnvironment` | Poll instance state, verified SSH, and bootstrap readiness |
| `createService` | Create root-only metadata/env files and the private runtime network |
| `createVolume` | Create one dedicated host directory and record its explicit mount path |
| `setVariables` | Atomic mode-0600 env-file replacement/merge over verified SSH |
| `assignDomain` | Upsert Cloudflare A record, write Caddy site, reload edge proxy |
| `deployService` | Pull pinned image, apply CPU/RAM/PID/log limits, mount only declared volumes, start container |
| lifecycle/logs/metrics | Docker inspect/stats/logs through verified SSH |
| `updateServiceSource` | Persist a new tested digest; deployment recreates only that container |
| `deleteService` | Delete DNS/routes/container/config/volume only for the validated opaque service ID |
| `deleteProject` | Schedule the VPS cancellation for its next monthly contract date |
Provider IDs are opaque (`ctbhost:*`, `ctbsvc:*`, `ctbvol:*`, `ctbdep:*`) and validated before they influence a command or filesystem path. They never leave internal tables.
5. Domains and TLS
Cloudflare credentials must be restricted to DNS edits for the HostAgentics zone. Each runtime hostname gets an A record pointing to its shard. `CLOUDFLARE_RUNTIME_PROXY=false` is the conservative default; enable proxying only after end-to-end WebSocket, streaming, upload-size, and TLS-mode tests.
Caddy obtains and renews origin certificates, forwards WebSockets/streaming automatically, and routes only to containers attached to `hostagentics-edge`. Hermes gets two hostnames/ports (dashboard and authenticated API); n8n and OpenClaw get one.
6. Backups and restores
Whole-VPS snapshots are not used for customer backups: on a shared shard they would combine tenants and a rollback would affect unrelated runtimes. Instead:
7. Monitoring and limits
CPU and memory come from Docker stats; storage comes from exact dedicated volume paths. Public edge egress is read as exact byte counters from Docker's local API, mapped to the container interface attached to `hostagentics-edge`, and accumulated per billing period across container restarts. Internal n8n↔PostgreSQL traffic is therefore not charged against a customer's public-transfer allowance. The control plane stores observed values and applies the existing 70/85/95/100-percent warning and block rules.
Host-level monitors must additionally alert on CPU steal, disk latency, memory pressure, Docker/Caddy health, restic failures, and shard reachability. A shard with degraded health must set `accepting_new_runtimes=false` before evacuation.
8. Required live acceptance test
Automated tests mock provider and SSH boundaries; they do not spend money or prove a specific account's catalog, quota, firewall, or object-storage policy. Before enabling production checkout, use disposable credentials and run:
1. List products/images and set an exact Ubuntu image UUID available in the account. Copy the selected product ID and its actual RAM/vCPU values into the three shard settings; never reuse an old friendly plan name or example ID. A product shown by the marketing catalog is not sufficient: confirm that the Compute API has an offer for the provider's one-month (`period: 1`) contract, because catalog-only IDs can be rejected at creation time.
2. Create one disposable EU shard and verify its deterministic SSH host key and CIDR firewall.
3. Provision one runtime of each kind; verify n8n database isolation, OpenClaw auth, Hermes dashboard/API auth, WebSockets, uploads, and streaming.
4. Create a backup for every volume, destroy test data, restore, and verify application-level records/memories/workflows.
5. Restart containers and the VPS; confirm persistent data, transfer-counter continuity, Caddy recovery, and health reporting.
6. Run CPU-steal, disk, network, and concurrent-runtime load tests. Increase `CONTABO_SHARD_CAPACITY` only when the configured VPS can sustain the reserved 2 vCPU / 4 GiB per runtime plus the host reserve.
7. Delete the runtimes; verify DNS, restic snapshots, containers, env files, and volume paths are gone. Cancel the disposable VPS and Object Storage, then verify the returned `cancelDate`. Empty and delete every disposable S3 bucket before cancellation.
Production rollout is blocked until this checklist passes with real credentials.
The live harness supports both a pre-existing staging shard and an explicitly disposable host. The disposable mode requires `CONTABO_SMOKE_CREATE_HOST=disposable` together with `CONTABO_SMOKE_TEST_CONFIRM=create-and-delete-disposable`; it creates a billable VPS and attempts to cancel that VPS in a `finally` block even after a failed test. It also refuses unpinned Caddy images or an empty SSH CIDR allowlist. Run it only from an isolated staging account.
Contabo cancellations are contractual, not immediate deletion. A one-month VPS or Object Storage can remain visible and usable until its verified `cancelDate`; a same-day cancellation request may be rejected. Cleanup is complete only when disposable DNS records, buckets, objects, snapshots, and temporary Secrets API entries are gone and both billable resources show the intended future cancellation date. Do not mistake a still-`running` VPS with a populated `cancelDate` for an uncancelled orphan.