CLI & althost.yaml¶
The althost CLI (cli/) deploys services declaratively from an althost.yaml
in a directory. It authenticates with an API key.
Install¶
The install is one line. It downloads and installs the latest CLI (like the runner installer):
curl -s "https://api.althost.dev/v1/cli/script" | sh
This fetches cli.zip. It installs its deps. It puts althost at
~/.local/bin/althost. Add that dir to your PATH if it is not there already.
You can configure credentials in the same step:
curl -s "https://api.althost.dev/v1/cli/script" | sh -s -- \
--server https://api.althost.dev --api-key ak_xxx
Or from a checkout:
cd cli && npm install
npm link # exposes `althost` on your PATH (or run: node cli/index.mjs)
Configure¶
Credentials resolve in this order: flags → env (ALTHOST_SERVER /
ALTHOST_API_KEY) → ~/.althost/cli.json.
althost config --server https://api.althost.dev --api-key ak_xxx
This writes ~/.althost/cli.json (mode 600). The key needs the
services:deploy scope. It also needs services:read for status.
althost.yaml¶
staticApps:
site: # a prebuilt dir — uploaded by `deploy`
path: ./dist
node: my-computer
app: # built locally by `build`
build:
command: npm run build # runs in the project dir
output: dist # the dir uploaded after the build
node: my-computer
services:
api:
image: myorg/api:1.2.3
replicas: 2 # optional, default 1
memory: 512 # optional MB, default 256
node: my-computer # optional: node id or label to run on
worker:
image: myorg/worker:latest
memory: 256
containers:
cache: { image: redis:7, port: 6379, node: my-computer }
databases:
main: { engine: postgres, version: "16", tier: dev, node: my-computer }
Commands¶
althost build [dir] # run each static app's build command, then upload its output
althost deploy [dir] # deploy <dir>/althost.yaml (default: current directory)
althost services # list services and their status
althost logs <name> [-f] # tail a service/container's logs (--follow to stream)
althost status # show current resource state
althost config ... # save server/api-key
althost logout # remove saved credentials (~/.althost/cli.json)
althost cleanup # remove credentials + leftover temp build dirs
althost help
logs resolves <name> against your services then containers. It prints
recent output. --follow (-f) keeps polling for new lines. Both services
and logs need a key with the read scope.
deploy is idempotent. It creates new resources and updates existing ones by
name. It prints created / updated / unchanged per resource. A changed
image bumps the service version so the runner redeploys it. It uploads any
static app path dirs as-is. They must already be built.
$ althost deploy .
Deploying 2 service(s) from /app/althost.yaml
• api updated (v3, provisioning)
• worker created (v1, provisioning)
Done.
Building static apps locally¶
build is the local-build path. For each static app it either:
- has a
build:block — it runscommandin the project directory. It then zips and uploads the resultingoutputdir. You need not commit a prebuilt directory; or - has only a
path:— it zips and uploads that prebuilt dir as-is.
Either way it uploads a new version. The runner downloads and serves that
version. Both are driven entirely by the yaml. The key needs
static-apps:deploy.
$ althost build .
Building 1 static app(s) from /app/althost.yaml
$ npm run build
↑ app built + uploaded (v4)
Done.
Building service & container images locally¶
A build: block on a service or container builds a container image locally.
It uploads the image as an artifact. The build requires no registry. build runs
docker build on the context. It runs docker save on the image. It declares
the resource (its image is just the build tag). It uploads the tarball. The
runner downloads the latest artifact. It loads the artifact and deploys it.
Containers use a blue-green deploy. A failed load or health-check keeps the
previous version serving.
services:
api:
build:
context: . # dir containing the Dockerfile (default ".")
dockerfile: Dockerfile # optional
tag: myorg/api:local # optional; default althost-local/<name>:latest
node: my-computer
containers:
web:
build: { context: ./web }
port: 8080
node: my-computer
$ althost build .
Building 1 target(s) from /app/althost.yaml
$ docker build -t althost-local/web:latest ./web
↑ containers/web built + uploaded (v3, althost-local/web:latest)
Done.
The builder is docker by default. Set ALTHOST_DOCKER (e.g. nerdctl,
podman) to match your local runtime. The key needs services:deploy /
containers:deploy.
Large images upload in chunks automatically. Any image over
ALTHOST_ARTIFACT_CHUNK_MB (default 32 MB) splits into chunks. Each chunk
uploads and retries independently. A single network blip does not restart the
whole upload. A proxy's request-body limit does not bound the transfer. Smaller
images use a single request.
Retention: the control plane keeps the newest ARTIFACT_RETENTION
(default 5) versions per target. It drops anything older than
ARTIFACT_RETENTION_DAYS (default 7). Whichever prunes more applies. Old
tarballs do not accumulate. The currently-deployed (latest) version is always
kept, even if it is older than the age limit. The system enforces the count cap
on each upload. The age cap runs on a daily sweep.
This is the local-build path of althost's build/artifact pipeline. Automated
git-triggered pipelines (a builder agent on a dedicated machine) build on the
same build → artifact → deploy loop.