Elastic burst compute
6 targets · 5 transient classes · plan proposed
HOST-004. Elastic burst compute policy and the provider adapter plan. Nothing here provisions anything: the console renders this register and holds no provider credential, and scripts/jarvisos-burst.mjs refuses every billable verb without an owner authorisation grant. Measurements marked 'measured' were taken on VIN on 2026-08-17; every price is arithmetic on a number nobody has yet checked against an invoice, which is gap burst-prices-unverified.
This page provisions nothing and holds no provider credential. It renders the register and the arithmetic
derived from it; scripts/jarvisos-burst.mjs is the only thing that could call a provider, and it
refuses every billable verb without an owner authorisation grant.
Recurring, per month
€5.00
the VPS the estate already pays for
Variable, per month
€0.24
projected against a €10.00 ceiling
Transient hours
133.5 h
across 5 workload classes
Past break-even
0/6
burst is still the cheap answer
Needs a person
8/17
9 run unattended
Credentials present
0/4
nothing here can spend anything today
The comparison
scored 0–4 on each axis, derived from declared facts
Cost is scored at projected utilisation, not at list price: a machine is only expensive in proportion to how
much of it you buy. Targets nothing routes work to are scored at a
20 h/month reference so that being idle is not mistaken for being cheap.
| Target |
Decision |
Hours |
Per month |
Total monthly cost | Startup latency | API controllability | Snapshots | Bandwidth | Tailscale attach |
Weighted |
|
VIN as it is
permanent · hetzner · vin
|
Adopted |
0.0 h
scored at 20 h
|
€5.00
unverified
|
2
|
4
|
3
|
3
|
4
|
4
|
3.15 |
|
VIN upgraded to CPX31
permanent · hetzner
|
Rejected |
0.0 h
scored at 20 h
|
€15.59
unverified
|
0
|
4
|
3
|
3
|
4
|
4
|
2.55 |
|
Home1 scratch worker
owned · self · home1
|
Adopted |
108.0 h
|
€0.00
measured
|
4
|
3
|
2
|
2
|
4
|
4
|
3.30 |
|
Hetzner CPX41 burst node
elastic · hetzner-cloud
|
Standby |
5.5 h
|
€0.24
unverified
|
3
|
2
|
4
|
3
|
4
|
3
|
3.05 |
|
Hetzner CAX31 burst node (ARM)
elastic · hetzner-cloud
|
Standby |
0.0 h
scored at 20 h
|
€0.00
unverified
|
3
|
2
|
4
|
3
|
4
|
3
|
3.05 |
|
GitHub Actions hosted runner
managed · github
|
Standby |
20.0 h
|
€0.00
unverified
|
4
|
2
|
2
|
0
|
4
|
3
|
2.75 |
Weights: Total monthly cost 0.3 · Startup latency 0.2 · API controllability 0.15 · Snapshots 0.1 · Bandwidth 0.1 · Tailscale attach 0.15.
The six axes the task named. Cost leads because the estate's stated optimisation is zero recurring cost; startup and mesh attach are next because a burst target that takes four minutes to become reachable is not usable for interactive work whatever it costs. Snapshots and bandwidth are real but rarely decide anything at this scale.
Rejected, and why
- VIN upgraded to CPX31 — It buys 720 hours a month of capacity to serve roughly 34 hours of transient work, and it buys them every month forever. At the projected utilisation the same work costs under a euro on demand. It also fails to fix the thing that is actually wrong: the memory pressure on VIN is caused by workloads the placement plan already moves to home1, so the upgrade would pay to keep them in the wrong place.
Rejected options stay in the register, keep being priced and keep being scored. An option that
disappears when it loses stops being evidence that a choice was made.
Break-even
where elastic stops being the cheap answer
Derived, not declared. Above the line the honest recommendation is the permanent machine — which is the one
claim that makes this a policy rather than an argument for elastic compute.
| Elastic option |
Against |
Break-even |
Projected |
Verdict |
| Hetzner CPX41 burst node |
VIN as it is €5.00/mo |
115 h |
5.5 h |
below it
|
| Hetzner CPX41 burst node |
VIN upgraded to CPX31 €15.59/mo |
360 h |
5.5 h |
below it
|
| Hetzner CAX31 burst node (ARM) |
VIN as it is €5.00/mo |
388 h |
0.0 h |
below it
|
| Hetzner CAX31 burst node (ARM) |
VIN upgraded to CPX31 €15.59/mo |
never — cheaper at any utilisation |
0.0 h |
below it
|
| GitHub Actions hosted runner |
VIN as it is €5.00/mo |
44 h |
20.0 h |
below it
|
| GitHub Actions hosted runner |
VIN upgraded to CPX31 €15.59/mo |
68 h |
20.0 h |
below it
|
Who signs for what
9 automatic · 8 owner-gated
Read-only inventory and health run unattended because they are free and cannot change anything. Everything that provisions, resizes, rebuilds, snapshots or deletes spends money or destroys something, and every one of those requires a scoped, budget-capped, expiring, single-use grant issued by the owner.
Runs unattended
An operation may run unattended if and only if its effect is 'read' and it is not billable. There is no third condition and no exception list.
- inventory: which burst resources exist right now, in which project, with which labels
- health: power state, uptime and metrics of a running burst node
- pricing: the provider's own price list, which is how every euro on this page gets verified
- usage: minutes and traffic consumed so far this month, which is how the ceiling is watched
- estimate: arithmetic performed locally on the numbers above
Requires the owner
Any operation that is billable, or whose effect is create, mutate or destroy, requires a valid grant. Declaring such an operation automatic fails npm run check.
- provision: create a server, a volume or a floating address
- resize: change a server type, in either direction — scaling down still bills the change
- rebuild: replace a running server's image
- snapshot: create or keep an image, which is per-GB rent for as long as it exists
- delete: destroy a server, image, volume or firewall
- dispatch: start a hosted CI run, which consumes a metered minute allowance
What makes a grant a grant
Required fields: scope, budgetEur, expiresAt, issuedAt, issuedBy, nonce, reason. Single use, at most
24 hours, written to /var/lib/jarvisos/secrets/burst-grants at mode 0600.
- An expired grant is not a grant.
- A replayed nonce is not a grant.
- A grant whose ceiling exceeds the policy's per-run ceiling is not a grant.
- A grant that does not name the operation is not a grant.
- A refused operation is refused. It is never retried with a stronger credential.
One grant covers a create and its own teardown. The reaper may delete only resources labelled with that grant's nonce, and may delete nothing else — otherwise a lease that has to wake a human to be enforced is not a lease.
| Operation |
Call |
Effect |
Billable |
Approval |
Credential |
|
hz-pricing
The provider's own price list. Every euro in this register is arithmetic on a number that this call is how you check.
|
GET /v1/pricing |
read |
free |
auto
|
hetzner-read
not resolvable
|
|
hz-server-types
Available server types with their per-hour and per-month prices, used to resolve a workload profile to a concrete type.
|
GET /v1/server_types |
read |
free |
auto
|
hetzner-read
not resolvable
|
|
hz-servers-list
Inventory. What exists in the burst project right now, with labels. The call the reaper decides on and the call that answers 'is anything running that nobody remembers'.
|
GET /v1/servers |
read |
free |
auto
|
hetzner-read
not resolvable
|
|
hz-server-get
Health of one burst node: power state, creation time and therefore its age against the lease.
|
GET /v1/servers/{id} |
read |
free |
auto
|
hetzner-read
not resolvable
|
|
hz-server-metrics
CPU, disk and network series for a running burst node. Read-only and free, so a stuck job is visible without touching it.
|
GET /v1/servers/{id}/metrics |
read |
free |
auto
|
hetzner-read
not resolvable
|
|
hz-images-list
Which snapshots exist and how large they are, which is the same question as how much per-GB rent is being paid this month.
|
GET /v1/images |
read |
free |
auto
|
hetzner-read
not resolvable
|
|
hz-firewalls-list
The deny-all-inbound firewall every burst node is created with. Read so the console can say whether it still exists before anything is provisioned into it.
|
GET /v1/firewalls |
read |
free |
auto
|
hetzner-read
not resolvable
|
|
hz-server-create
Create a burst node: server type from the workload profile, no primary IPv4, deny-all-inbound firewall, cloud-init that joins the tailnet with an ephemeral pre-authorised key, and labels carrying the grant nonce and the lease deadline.
|
POST /v1/servers |
create |
bills |
owner
|
hetzner-write
not resolvable
|
|
hz-server-delete
Destroy a burst node. The only teardown that stops the invoice, and therefore the only teardown this contract recognises.
|
DELETE /v1/servers/{id} |
destroy |
bills |
owner
|
hetzner-write
not resolvable
|
|
hz-server-poweroff
Power a burst node off without deleting it. Present in the adapter so the contract can say what it is for, which is debugging a failed run before destroying the evidence.
THIS DOES NOT STOP BILLING. A powered-off server bills at the full rate until it is deleted. It is not teardown and this register refuses to let any target declare it as such.
|
POST /v1/servers/{id}/actions/poweroff |
mutate |
bills |
owner
|
hetzner-write
not resolvable
|
|
hz-server-resize
Change a server type, in either direction. Never used on a burst node — a burst node is destroyed and recreated — and present only because resizing VIN is the rejected option this register is compared against.
Reboots the server. On VIN that is a TLS and forward-auth outage for every published hostname, and upgrade_disk is irreversible: a disk that grew cannot shrink back to the smaller tier.
|
POST /v1/servers/{id}/actions/change_type |
mutate |
bills |
owner
|
hetzner-write
not resolvable
|
|
hz-server-rebuild
Replace a running server's image. Not billable — it changes no tier — and still owner-gated, because destroying a filesystem is destructive whether or not it costs anything.
Erases the root filesystem. This is the operation that proves billable and dangerous are two different axes.
|
POST /v1/servers/{id}/actions/rebuild |
mutate |
free |
owner
|
hetzner-write
not resolvable
|
|
hz-image-create
Snapshot a burst node to make the next boot faster. Creates a recurring per-GB charge that lasts until somebody deletes it.
The only operation here that converts variable cost into recurring cost. Every snapshot carries an expiry label and the reaper enforces it.
|
POST /v1/servers/{id}/actions/create_image |
create |
bills |
owner
|
hetzner-write
not resolvable
|
|
hz-image-delete
Delete a snapshot and stop paying rent on it.
|
DELETE /v1/images/{id} |
destroy |
free |
owner
|
hetzner-write
not resolvable
|
|
gh-runs-list
Which dispatched CI runs exist and what happened to them.
|
GET /repos/{owner}/{repo}/actions/runs |
read |
free |
auto
|
github-read
not resolvable
|
|
gh-billing-actions
Minutes consumed against the free allowance this month. The automatic read that watches the ceiling, so the first sign of running over is not an invoice.
|
GET /users/{user}/settings/billing/actions |
read |
free |
auto
|
github-read
not resolvable
|
|
gh-workflow-dispatch
Start a hosted CI run. Free inside the monthly allowance and roughly ten times the CPX41 hourly rate outside it, so it is metered work and therefore owner-gated.
|
POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches |
create |
bills |
owner
|
github-dispatch
not resolvable
|
Transient workload classes
Zero recurring cost is the default and the rollback plan. Every workload class must have at least one free eligible target, so that switching the elastic options off is one field in this file rather than a migration. Paid capacity is allowed only where a measured operational problem is recorded next to the spend, in paidBecause and paidEvidence.
Coding agent worker
100.0 h/month · secret · ephemeral
A `claude -p` worker dispatched by the control plane against one repository. Memory-hungry, CPU-light, and the largest single consumer of VIN's memory today.
2 vCPU · 2 GB · 10 GB ·
25 min × 120/month × 2 concurrent
| Eligible target |
Fits |
Per run |
Per month |
Start p95 |
Score |
|
→ Home1 scratch worker
preferred
|
yes |
€0.00 |
€0.00 |
20s |
3.30 |
|
Hetzner CPX41 burst node
|
yes |
€0.02 |
€4.33 |
75s |
2.75 |
Measured at 366 and 337 MiB resident on VIN on 2026-08-16, about 40% of that node's total memory. The placement plan already moves this class to home1, and it needs a repository checkout and a model API key — material that should not be created and destroyed inside a rented block device.
Costs nothing at this utilisation, so nothing here needs authorising.
x86 container image build
8.0 h/month · internal · ephemeral
Building and pushing an image the estate will actually run. Bursty CPU, large disk churn, no durable state of its own.
4 vCPU · 8 GB · 40 GB ·
12 min × 40/month
| Eligible target |
Fits |
Per run |
Per month |
Start p95 |
Score |
|
→ Home1 scratch worker
preferred
|
yes |
€0.00 |
€0.00 |
20s |
3.30 |
|
Hetzner CPX41 burst node
|
yes |
< €0.01 |
€0.35 |
75s |
3.05 |
|
GitHub Actions hosted runner
|
too small |
€0.00 |
€0.00 |
2m |
2.75 |
Eight hours a month. It fits inside home1 comfortably and the images are pushed onto the tailnet anyway, so building them there avoids a WAN round trip of the whole layer set. CPX41 is the overflow when home1 is busy or down; the ARM node is deliberately not eligible because the artefact is x86.
Costs nothing at this utilisation, so nothing here needs authorising.
Repeatable benchmark run
4.0 h/month · public · ephemeral
A timing run whose whole value is that the numbers are comparable between runs. Needs cores nobody else is using for the length of the run.
8 vCPU · 16 GB · 40 GB ·
30 min × 8/month
| Eligible target |
Fits |
Per run |
Per month |
Start p95 |
Score |
|
Home1 scratch worker
|
yes |
€0.00 |
€0.00 |
20s |
3.30 |
|
→ Hetzner CPX41 burst node
preferred
|
yes |
€0.02 |
€0.17 |
75s |
3.05 |
The one class in this register where paid capacity removes a measured operational problem. It is also the cheapest line in it.
Paid capacity, and why it is allowed here
A benchmark sharing cores with the agent fleet, the control plane and the databases measures the noise, not the change. Home1 is the estate's default compute node precisely because it is busy; four hours a month of a machine with nothing else on it is the only way these numbers mean anything. The alternative interpretation — that the numbers do not need to be comparable — makes the workload pointless rather than cheap.
Evidence: VIN's own load average of 0.04 alongside 527 MiB of swap in use is the shape of the problem: contention on this estate is invisible in CPU and lethal in memory, so a benchmark on a shared node is unreproducible in a way that does not show up in the load average. Cost of the fix at the declared rate: 4 h/month at EUR 0.0433/h, about EUR 0.17/month, against EUR 10.59/month for the permanent upgrade that would still be contended and would still only be 4 vCPU.
Repository test suite
20.0 h/month · internal · ephemeral
npm test and npm run check on every push. Short, frequent, and entirely self-contained: it needs a checkout and Node, and nothing from the estate.
2 vCPU · 4 GB · 10 GB ·
6 min × 200/month
| Eligible target |
Fits |
Per run |
Per month |
Start p95 |
Score |
|
Home1 scratch worker
|
yes |
€0.00 |
€0.00 |
20s |
3.30 |
|
Hetzner CAX31 burst node (ARM)
|
yes |
< €0.01 |
€0.26 |
75s |
3.05 |
|
→ GitHub Actions hosted runner
preferred
|
yes |
€0.00 |
€0.00 |
2m |
2.75 |
Twenty hours a month, which is 1200 minutes against a 2000-minute free allowance. It needs no tailnet access at all — this repository has zero runtime dependencies and the suite is pure Node — so it is the one class that can safely run on hardware the estate does not control. Home1 is the fallback the moment the allowance is short, and the ARM node is eligible because the test suite is architecture-portable even though the images are not.
Costs nothing at this utilisation, so nothing here needs authorising.
Offsite restore rehearsal
1.5 h/month · secret · ephemeral
Pull the encrypted offsite copy onto a machine that has never seen it, decrypt it, and prove it restores. Large disk, long run, once a month.
2 vCPU · 4 GB · 200 GB ·
90 min × 1/month
| Eligible target |
Fits |
Per run |
Per month |
Start p95 |
Score |
|
Home1 scratch worker
|
yes |
€0.00 |
€0.00 |
20s |
3.30 |
|
→ Hetzner CPX41 burst node
preferred
|
yes |
€0.06 |
€0.06 |
75s |
3.05 |
Eligible on home1 as the free fallback, and the fallback is genuinely worse rather than merely cheaper — which is what a fallback is supposed to be.
Paid capacity, and why it is allowed here
A restore drill run on home1 rehearses the case where home1 still exists, which is the case that does not need the offsite copy. Restoring onto a machine in a different failure domain, from nothing but the bucket and the passphrase, is the only version of this drill that proves anything. One and a half hours a month.
Evidence: config/placement.json failure domains: home1 and the NAS are both fd-home-rack, and the offsite copy in fd-offsite exists specifically to survive that domain. A drill inside the domain it is protecting against is a test with the failure removed. Cost at the declared rate: 1.5 h/month at EUR 0.0433/h, about EUR 0.07/month.
Lifecycle of one burst run
-
select
auto
Resolve the workload class to a target: the highest weighted score among eligible targets that fit the profile, free targets first at equal score.
Pure arithmetic on this file. Costs nothing, changes nothing, and is the step that usually ends with 'home1'.
-
estimate
auto
hz-pricing
Derive the per-run cost and the month-to-date spend against the ceiling.
Reads the provider's price list so the estimate is against today's prices rather than the ones written in this file.
-
authorise
owner
The owner issues a grant: scope, ceiling, expiry, nonce, reason. JarvisOS cannot issue one to itself.
The gate. Everything above this line is free and reversible; everything below it is neither.
-
provision
owner
hz-server-create
Create the node with no public IPv4, a deny-all-inbound firewall, and labels carrying the grant nonce and the lease deadline.
Bounded by: The grant's ceiling and the target's monthlyCeilingEur, whichever is lower.
-
attach
owner
cloud-init installs tailscaled and joins the tailnet with an ephemeral, tagged, pre-authorised key that expires with the node.
Part of the create call's user_data, so it is the same authorisation. The key is ephemeral and tagged tag:burst: an ACL grants tag:burst only the ports a job needs, and a node that dies leaves no tailnet record behind.
-
verify
auto
hz-server-get
Confirm the node is up, reachable over the tailnet and inside its lease before any work is sent to it.
-
run
auto
Dispatch the job over the tailnet using the existing remote dispatch contract in config/remote.json.
Deliberately the same dispatch path as home1. A burst node is just another node with a shorter life; inventing a second way to run work on it would double the surface that has to be trusted.
-
collect
auto
Pull the evidence back before teardown. Anything not collected is gone, because the disk is about to be deleted.
-
destroy
owner
hz-server-delete
Delete the node. Not stop, not power off — delete.
Bounded by: Servers labelled with the nonce of the grant that created them, and nothing else.
-
reap
owner
hz-server-delete
Sweep for burst resources past their lease deadline and delete them, then sweep for snapshots past their expiry and delete those.
Bounded by: Same nonce restriction. Carried by the grant that created each resource, which is what lets an unattended timer enforce a lease without holding a standing authority to delete.
Runs on VIN, never on a burst node. A machine cannot be trusted to delete itself, and the case the reaper exists for is precisely the one where the burst node is wedged.
Credentials
Provider credentials are never in this file, in any config, in argv, in a log line, in a report or in browser storage. Each is declared by name and location only and resolved at call time from an environment variable or a 0600 file under /var/lib/jarvisos/secrets, outside this working tree and owned by the jarvis service account.
| Credential |
Variable |
Protected location |
Ability |
Rotation |
Present |
| hetzner-readRead-only inventory, health, pricing and image listing in the burst-only project. The credential every automatic operation uses. |
HCLOUD_TOKEN_READ |
/var/lib/jarvisos/secrets/hetzner-read.token mode 0600 |
read-only
|
180 d |
absent |
| hetzner-writeCreate and destroy burst nodes and their snapshots. The credential the owner authorisation policy exists to gate. |
HCLOUD_TOKEN_WRITE |
/var/lib/jarvisos/secrets/hetzner-write.token mode 0600 |
can spend
|
90 d |
absent |
| github-readRead dispatched run status and the Actions minute allowance. |
GITHUB_TOKEN_BURST_READ |
/var/lib/jarvisos/secrets/github-burst-read.token mode 0600 |
read-only
|
180 d |
absent |
| github-dispatchStart a hosted CI run, spending metered minutes. |
GITHUB_TOKEN_BURST_DISPATCH |
/var/lib/jarvisos/secrets/github-burst-dispatch.token mode 0600 |
can spend
|
90 d |
absent |
Presence only. Nothing on this page has opened one of these files or read one of these variables, and no
value from either appears in this document, in /api/v1/burst or in any log line.
Rollback and recovery
| If this happens |
Do this |
Who |
Reversible |
Time |
| The elastic experiment is abandoned |
Set decision to 'reject' on hetzner-cpx41, hetzner-cax31 and github-actions, and set every workload's preferredTarget to its free eligible target. Revoke both Hetzner tokens in the provider console and delete the burst project. npm run check enforces that a free fallback existed for every class, so this is an edit rather than a migration. |
operator |
yes |
minutes |
| A burst node is wedged and the reaper did not delete it |
node scripts/jarvisos-burst.mjs reap --confirm, or delete the server in the Hetzner console. The monthly cap bounds the damage in the meantime: worst case is the target's cap, not the hourly rate multiplied by however long nobody looked. |
operator |
yes |
under an hour, bounded by the cap regardless |
| The write credential leaks |
Revoke the token in the Hetzner console. Because it is scoped to the burst-only project, the blast radius is burst nodes and their snapshots — VIN, its volumes and its snapshots are in a different project and are not reachable with it. Delete the burst project outright if in doubt. |
owner |
yes |
minutes, and this project separation is the reason it is minutes |
| A grant is issued in error |
Delete the grant file from /var/lib/jarvisos/secrets/burst-grants/. It is single-use and expiring; an unspent grant that is deleted was never spent. If it was already spent, the resource it created carries its nonce and is deletable by that label. |
owner |
yes |
immediate |
| The permanent upgrade turns out to have been right after all |
The register says so before the invoice does: when projected hours cross the derived break-even, the console raises burst-exceeds-breakeven and names the permanent option and its price. Resize VIN with hz-server-resize, accepting the reboot of the public edge, or provision a second permanent node so the edge is never rebooted for a capacity decision. |
owner |
no |
a resize is a reboot; a disk that grew cannot shrink back |
| Tailscale attach fails on a new burst node |
The node is unreachable and must be destroyed rather than debugged: it has no public IPv4 and no inbound firewall rule, which is the design working. Debug by provisioning with a serial console session in the provider UI, never by adding an address. |
operator |
yes |
minutes |
Gaps
-
i Note: The reaper is written but nothing runs it on a schedule
operator
A lease is only a lease if something enforces it. Until a timer on VIN runs `jarvisos-burst.mjs reap`, the lease is a comment and the monthly cap is the only real bound. Installing that timer is part of enabling the first elastic target, not a follow-up.
-
i Note: No tailnet ACL for tag:burst exists yet
owner
The design has burst nodes joining with an ephemeral key tagged tag:burst, and an ACL granting that tag only the ports a job needs. Without the ACL an ephemeral node joins with whatever the tailnet's default policy allows, which on a flat tailnet is everything. Writing the ACL is an owner action in the Tailscale admin console.
-
i Note: Offsite restore rehearsal handles secret material on Hetzner CPX41 burst node
restore-drill
A rented machine that is created, used and deleted leaves the material in somebody else's block store until it is overwritten. Keep this class on owned hardware, or state what is done about it.
-
i Note: Every price in this register is unverified against an invoice or the live price list
owner
No provider credential exists on this node, so hz-pricing has never been called and the figures are from published list prices carried in this file. The arithmetic is sound; the inputs are assumptions. Verify before the first authorised run, not after the first bill.
-
i Note: Home1's capacity is declared, not measured, so the free default may not actually fit the workloads routed to it
operator
Inherited from HOST-001 gap G1: home1 was not reachable or enumerable from this sandbox. It is confirmed present on the tailnet as uk-james-home1 and idle, which is not the same as confirmed to have 8 cores and 32 GB. If it does not, the burst targets stop being overflow and start being load-bearing.
-
i Note: The provider adapter is a plan; not one operation in it has ever been run
operator
No Hetzner or GitHub burst credential exists in /var/lib/jarvisos/secrets. Startup latency, the cloud-init tailnet attach and the reaper's label filter are all estimated rather than measured. The first authorised run is also the first test.
-
i Note: Hetzner API tokens are read or read-write for a whole project; there is no 'may create but not delete' scope
owner
The write credential is therefore broader than this contract wants. The mitigation is structural rather than token-based: burst resources live in their own Hetzner project containing nothing else, so the widest thing that token can do is destroy the burst project. VIN is in a different project and is not reachable with it. Creating that project is an owner action and has not been done.
-
i Note: The restore drill needs the offsite passphrase, which by policy is on no node
owner
config/placement.json requires the offsite encryption passphrase to live in offline custody only, and the placement validator enforces it. So the drill cannot be fully automatic: the owner supplies the passphrase into the burst node's session for the length of the run, and the node is destroyed afterwards. That is workable, and it is also why the drill class is marked secret and raises burst-secret-off-owned-hardware.
Notes
-
i Note: Repository test suite prefers GitHub Actions hosted runner; the arithmetic prefers Home1 scratch worker
ci-test
Weighted 3.30 against 2.75 at 20.0 h/month. The preference may still be right — it can encode something the six axes do not — but it should be a decision rather than an oversight.
-
i Note: No credential is resolvable for provider "hetzner-cloud"
hetzner-cloud
The adapter is a plan, not a running integration: nothing can be provisioned, and nothing can be billed either. Mint a scoped token into the declared protected location when the owner authorises the first run.
-
i Note: No credential is resolvable for provider "github"
github
The adapter is a plan, not a running integration: nothing can be provisioned, and nothing can be billed either. Mint a scoped token into the declared protected location when the owner authorises the first run.
-
i Note: Hetzner CPX41 burst node's price is unverified
hetzner-cpx41
Every euro on this page is arithmetic on a number nobody has checked against an invoice. Verify before the first authorised run, not after the first bill.
-
i Note: Hetzner CPX41 burst node: keeping a warm image costs €0.14/month
hetzner-cpx41
12 GB at €0.01/GB/month, every month, whether or not anything boots from it. Expiry is 30 days. This is the recurring cost trade: it buys back roughly 45s of cold-boot provisioning per run.
-
i Note: Hetzner CAX31 burst node (ARM)'s price is unverified
hetzner-cax31
Every euro on this page is arithmetic on a number nobody has checked against an invoice. Verify before the first authorised run, not after the first bill.
-
i Note: Hetzner CAX31 burst node (ARM): keeping a warm image costs €0.12/month
hetzner-cax31
10 GB at €0.01/GB/month, every month, whether or not anything boots from it. Expiry is 30 days. This is the recurring cost trade: it buys back roughly 45s of cold-boot provisioning per run.
-
i Note: GitHub Actions hosted runner's price is unverified
github-actions
Every euro on this page is arithmetic on a number nobody has checked against an invoice. Verify before the first authorised run, not after the first bill.
-
i Note: The cheapest burst target cannot build the artefacts this estate runs
operator
hetzner-cax31 is ARM. Container images built there will not run on VIN or home1 without emulation, and benchmark numbers taken there are not comparable with anything else in the estate. It is eligible only for architecture-portable work, which today is the test suite.
How to read this page
- Transient work gets transient capacity. A build that runs for six hours a month does not justify a machine that runs for 720, and an upgrade bought for a peak is paid for at every trough.
- A burst node is created, used and destroyed. It holds no durable state, it is reached over the tailnet and never from the public internet, it carries a lease, and teardown means destroy — powering a server off stops the CPU, not the invoice.
- Every billable operation is attributable to one authorisation grant, one target and one ceiling. An unattributable euro is a bug in this contract, not a rounding error.
Source: config/burst.json · machine-readable at /api/v1/burst ·
narrative in docs/BURST-COMPUTE.md · the placement decision this sits on top of is at
the placement plan and docs/HOSTING-TOPOLOGY.md.