---
name: deploy-on-bootload
description: Deploy a container image to bootload (Firecracker microVM hosting) and get a public HTTPS URL. Use when the user asks to deploy, host, or ship an app/image on bootload — covers CLI install, token auth, deploys, domains, volumes, managed databases, secrets, logs, and costs.
---

# Deploy on bootload

bootload hosts each app in its own Firecracker microVM: push an OCI image,
get an HTTPS URL. Prepaid per-second billing. You drive it with the
`bootload` CLI; every command is non-interactive once `BOOTLOAD_TOKEN` is set.
Add `--plain` (or rely on piped-output detection) for stable, parseable output.

## 1. Install the CLI

```bash
curl -fsSL https://bootload.io/v1/cli/install.sh | sh
bootload version   # want v0.1.9 or newer
```

## 2. Authenticate (non-interactive)

Ask the user for an API token — they create one in the portal
(my.bootload.io → account → API keys) or with
`bootload token create agent --scope services:write --scope projects:read`
(the secret is shown once).

```bash
export BOOTLOAD_TOKEN=blt_...   # picked up by every command
```

Never echo the token. If a command returns 403, the token lacks a scope —
tell the user which one the error names.

## 3. Deploy

```bash
bootload deploy --name myapp --image ghcr.io/acme/myapp:latest --port 3000:http
```

- A public HTTPS URL is assigned automatically
  (`myapp-xxxxxx.fr1.apps.bootload.io`) and printed as a `route` line —
  no domain needed. (CLI ≥ v0.1.9; older CLIs need `--publish` explicitly.)
- `--port` must match what the image actually listens on (nginx → `80:http`,
  typical Node app → `3000:http`). A wrong port shows up as
  "health check never passed".
- Sizing: `--vcpu 1 --memory 512` are the defaults.
- Private registry? The user adds credentials first (portal → resources →
  registries). Or push a local image to bootload's own registry:
  `bootload image push <local-tag>` and deploy the reference it prints.

Watch it come up:

```bash
bootload status myapp        # replica state; healthy = serving
bootload logs myapp -f       # follow container output
```

## 4. Common shapes

**Custom domain** (user owns the DNS):
```bash
bootload domain add myapp.com          # prints the DNS record that proves ownership
bootload deploy --name web --image ... --domain www.myapp.com --port 3000:http
```

**Persistent data** — create the volume BEFORE the deploy that mounts it:
```bash
bootload volume create data --size 5gb
bootload deploy --name myapp --image ... --port 3000:http --volume data:/var/lib/data
```

**Managed database** (Postgres / MariaDB / Valkey / …) — internal-only,
credentials generated, reachable from sibling services in the project:
```bash
bootload database search
bootload database install postgres     # prints host + credentials (spends money)
# then from your app: postgres.internal:5432
```

**Sibling-only service** (no public URL): add `--internal`; siblings reach it
at `<name>.internal`. The CLI warns if a deploy would end up route-less.

**Secrets** (project-wide, or scoped to one service; applied at next boot):
```bash
printf '%s' 'postgres://...' | bootload secret set DATABASE_URL --service myapp
bootload restart myapp
```

**Scale:** `bootload scale myapp --replicas 2` (or autoscale:
`--min 1 --max 3 --target-cpu 70`).

## 5. Costs (tell the user before spending)

€4/vCPU-month + €2/GB-RAM-month, billed per second from a prepaid wallet;
the default 1 vCPU / 512 MB caps around €5/month. Volumes €0.10/GB-mo.
`bootload pricing` prints the full rate card; wallet errors mean the user
must top up (`bootload wallet topup --amount <euros>`).

## 6. When something is wrong

- `health check never passed on :PORT` → `--port` doesn't match the image.
- Deploy succeeded but no URL printed → CLI older than v0.1.9: re-run the
  install one-liner, or pass `--publish`.
- 403 → missing token scope · wallet/balance error → prepaid wallet is empty.
- Full CLI reference: https://bootload.io/docs/cli/ · docs:
  https://bootload.io/docs/ · machine-readable: https://bootload.io/llms-full.txt
