Managed environments
VMs that codai provisions for you on OpenStack or Hetzner — sizes, regions, start and stop, idle auto-stop and snapshots.
A managed environment is a VM that codai creates, enrols and looks after. You pick a provider and a size; a worker that runs every minute provisions the machine, installs codaid through cloud-init, stops it when idle and bills it per second of runtime.
Managed providers are rolling out and enabled per account. Until yours is enabled, POST /v1/environments with a managed provider answers 403 — Provider 'hetzner' is not available yet; use 'byo' (bring your own machine) — and the hub shows the managed options as coming soon. Bring your own server works for everyone.
Providers and regions
provider | Where | Default region |
|---|---|---|
openstack | codai cloud on Cloudify (EU, Romania), Ubuntu 24.04 | eu-east-1 |
hetzner | Hetzner Cloud | nbg1 (the machine types below exist in fsn1, hel1 and nbg1) |
The local provider value exists in the schema but is reserved; it is not provisioned.
Sizes
size | vCPU | RAM (billed) | OpenStack flavor | Hetzner type | Rate |
|---|---|---|---|---|---|
small (default) | 2 | 2 GB | b2i.2c-2g | cx23 | €0.03 / h |
medium | 4 | 4 GB | b2i.4c-4g | cx33 | €0.06 / h |
large | 8 | 8 GB | b2i.8c-8g | cx43 | €0.12 / h |
Rate = vCPU × €0.01/h + GB RAM × €0.005/h, stored on the environment at creation (hourlyRateMicroEur: 30 000 / 60 000 / 120 000 micro-EUR). Disk is whatever the flavor or server type ships with. GPU environments are coming soon.
Create one
In hub.codai.ro/projects, open a project → New environment, choose codai cloud (OpenStack) or Hetzner, a size, the idle timeout (5–1440 minutes) and an optional monthly budget cap in euro.
The environment starts in creating. The worker creates the server (creating → enrolling once it has a public IP), cloud-init installs codaid as a system service and enrols it with a token the worker mints, and the environment becomes running. On both providers this took about two to three minutes in production. At enrolment the daemon of a managed machine receives its own API key under the environment owner; destroying the environment revokes it.
| Step | Time limit | On timeout |
|---|---|---|
| Create the server | 10 min | retried; after 3 consecutive provider failures the environment is parked in error |
| Daemon enrols | 15 min | error, reason enroll_timeout — a late enrolment still recovers it to running |
Start from stopped | 10 min | error |
The worker never destroys a machine on an error path; you decide.
Lifecycle
| Action | Allowed from | Goes to | Role |
|---|---|---|---|
stop | running | stopping → stopped | maintainer |
start | stopped | starting → running | maintainer |
archive | stopped | archiving → archived | maintainer |
destroy | any state except destroying/destroyed | destroying → destroyed | owner |
Anything else answers 409 invalid_transition. Hub buttons, codaid env start|stop|destroy and POST /v1/environments/{id}/{action} all go through the same transition table.
What stop and start do on each provider:
| Stop | Start | |
|---|---|---|
| OpenStack | Shelve, then shelve-offload: the server id and public IP are kept, compute is released. | Unshelve the same server. |
| Hetzner | Take a snapshot, then delete the server. | Create a new server from the snapshot. The previous snapshot is deleted after the next stop. |
archive runs the same stop path and parks the machine in archived; the only way out of archived is destroy. destroy deletes the server (and on Hetzner its snapshot) and revokes the daemon key.
Idle auto-stop
Every environment has idle_timeout_minutes (default 30, 5–1440; change it with PATCH /v1/environments/{id} or in the hub). The worker stops a running managed environment when
now − max(last_activity_at, started_at) > idle_timeout_minuteswith reason idle. Activity is:
- any exec, terminal or port-stream byte from an attached client, through the relay;
- daemon heartbeats reporting
humanoragentactivity — anidleheartbeat never counts; - requests the daemon itself makes to the gateway with its key (for example an agent loop running inside the machine);
- your own start/stop/archive/destroy requests.
Open preview traffic from third parties counts only as port-stream bytes, so a public preview with visitors keeps the machine awake. Activity is recorded at most once a minute.
The machine can also be stopped for billing reasons — insufficient_funds, billing_error or budget_exceeded; see billing. The reason is shown on the environment page and returned as stateReason.
Coming soon
Prebuilds (a warm pool per project), GPU environments and choosing the region in the hub are not available yet.