Deploying to a host
The path from a folder on your laptop to a running site on a host you control.
A host is a running crisptastic host process that serves sealed Capsules,
selects a site by domain, and injects secrets into memory. Deploying means:
build a Capsule, put it where the host can read it, and tell the host to
activate it.
The host can be another port on your laptop, a machine on your LAN, or a production box — the commands are identical. Only the addresses and which certificates you hold change.
Keys, once
# Age X25519 recipient: the host's identity. Capsules are encrypted TO it.
age-keygen -o server.agekey # keep secret on the host
# Ed25519 deployment signer: proves who built a Capsule.
crisptastic capsule keygen --private release.pk8 --public release.pub
# keep release.pk8 with whoever deploys; give release.pub to every host
Build and seal
crisptastic deploy ./my-site \
--recipient age1xxxxxxxx... \
--signing-key ./release.pk8 \
--out ../capsules/my-site.age
deploy runs the deterministic build, moves the values of
your declared [env] / [env_from_process] names into a separate encrypted
section, signs the payload, and encrypts the whole Capsule to the host's
recipient. The output is opaque ciphertext; its SHA-256 digest is its identity.
Get the Capsule to the host
Copied file — point the host straight at the .age file.
Object storage — publish once; hosts pull by digest. Publishing is idempotent because the key is the digest.
crisptastic capsule publish ../capsules/my-site.age --store-dir ../capsule-store
# -> published capsule digest <sha256>
# or S3-compatible storage (Capsule stays ciphertext):
export CRISPTASTIC_CAPSULE_S3_BUCKET=my-capsules
export CRISPTASTIC_CAPSULE_S3_REGION=eu-west-1
export CRISPTASTIC_CAPSULE_S3_ACCESS_KEY=...
export CRISPTASTIC_CAPSULE_S3_SECRET_KEY=...
crisptastic capsule publish ../capsules/my-site.age --s3
# deploy + publish in one step:
crisptastic deploy ./my-site --recipient age1... --signing-key ./release.pk8 \
--out ../capsules/my-site.age --publish-s3
Run a host and activate
Start a host with a management listener (mutual TLS). Generate development
certificates with lab/scripts/gen-mtls-certs.sh, or use your own PKI.
crisptastic host \
--identity ./server.agekey \
--trusted-signer ./release.pub \
--host-root /var/lib/crisptastic \
--deployments-root /var/lib/crisptastic/deployments \
--store-dir /var/lib/crisptastic/capsule-store \
--bind 127.0.0.1:6174 \
--management-bind 127.0.0.1:7443 \
--management-cert ./certs/server.crt \
--management-key ./certs/server.key \
--management-client-ca ./certs/client-ca.crt \
--development-process-profile # laptop only; omit in production
Then, from wherever you deploy from:
crisptastic notify \
--peer 127.0.0.1:7443 \
--digest <sha256> \
--client-cert ./certs/client.crt \
--client-key ./certs/client.key \
--server-ca ./certs/server.crt
notify calls POST /v1/deployments/activate over mTLS. The host pulls the
Capsule (if using a store), verifies digest, byte length, signature, schema,
domains and secret-name set, unpacks public files atomically under a fresh
deployment UUID, moves secrets into a tenant-scoped memory generation, and
makes the domains routable only when everything is ready. A client without a
trusted certificate is rejected and the running routes are left untouched.
Static digests instead of a management call
A host can also start with fixed Capsules or digests — useful for immutable, GitOps-style deploys:
crisptastic host ../capsules/a.age ../capsules/b.age --identity ... --trusted-signer ...
crisptastic host --digest <sha256-a> --digest <sha256-b> --store-dir ... --identity ... --trusted-signer ...
Redeploying and rollback
Re-activating a domain builds the new runtime fully, swaps the routing pointer under a write lock, and drops the retired runtime after in-flight requests finish (its secrets zeroize). To roll back, activate the previous Capsule digest — it is still in the store. An unknown or unregistered domain always fails closed with HTTP 421.
Same laptop, second port
To rehearse the whole flow locally: run a host on :6174 / :7443 as above
with --development-process-profile, deploy your site to a --store-dir, and
notify 127.0.0.1:7443. A separate computer is the same, with its LAN address
in --peer and matching certificate SANs.