Docs
Deploying
On one Hetzner server, a deploy shouldn't cost a run, and a bad one should be easy to undo. The scripts that do it come with each morca release. This page is the outline; docs/hetzner.md in the repository is the full runbook. On AWS, orca aws makes and updates the stack.
The scripts
Since 0.19.0 the deploy tooling is a release asset, so deploying needs no checkout of
morca's repository. It unpacks to orca-hetzner-<version>/, and the scripts
print that version:
curl -fsSL https://github.com/morca-dev/morca/releases/latest/download/orca-hetzner.tar.gz | tar -xz
cd orca-hetzner-<version>
cp hetzner.env.example hetzner.env # fill in every line
./up.sh --dry-run # prints every hcloud and ssh command; runs none
./up.sh up.sh makes the firewall, the Volume and the server, puts the settings
and secrets on it and starts the containers: Postgres, the scheduler, the UI, the
sampler, the apps and the Cloudflare tunnel
(First setup).
Deploys
./deploy.sh a1b2c3d # the image at that tag; starts again what changed
./deploy.sh a1b2c3d console=latest # one app on another tag
./deploy.sh --all a1b2c3d # every container again, changed or not Only what changed starts again (since 0.18.0). orca-stack
apply compares each container's image, env file, flags and mounts with what it
runs, and leaves it alone when nothing differs; orca-stack plan says what
an apply would do. A census-only deploy replaces the console and nothing else, and
Postgres is never restarted.
The UI and the apps without downtime (since 0.18.0). A new UI or app
starts beside the old one, takes its name on the network once it's healthy (the UI's
/healthz), and the old one finishes its requests and stops. One that
never gets healthy is removed and the old one keeps serving. Remote workers talk only
to the UI, so their runs go on through a deploy.
The scheduler. Restarting it kills the runs it holds, so when the plan
replaces it, deploy.sh pauses the pipelines, waits for the scheduler's
running runs (not those on remote workers), backs the database up, applies, registers
the pipelines from the new image and unpauses what it paused. When the plan doesn't
replace the scheduler, nothing is paused.
Apps
From 0.26.0, an app's setup lives with its code. The stack names the apps it runs, and
the app's own image says what each one gets, in its
[apps.<name>] table. The deploy script
no longer hard-codes any of it:
APPS=console # which apps this stack runs
SECRETS_FILE=secrets.sops.yaml # holds secrets/orca/posthog-key, if the app asks for it - Read from the image.
morca-stack planandapplyrun the app image'smorca config apps, with the stack's overlay laid on it, and write the app's env file (/etc/orca/app-<name>.env, mode 600) from what it declares. That file holds itsenv, the lake withlake = true, each secret andPORT;port,checkandmemory_gbset how the container runs. - Secrets. A secret the app asks for,
orca/<id>, is a keysecrets/orca/<id>inSECRETS_FILE, sent to the server like the stack's other secrets. If the server doesn't have one, the deploy stops at the plan, before anything is paused or replaced. Values are never printed, and changing one replaces the app, without downtime. - Before 0.26.0.
APPS=console:8080still works: the port is used for an app whose table gives none, and a port that differs from the table's is refused. An app the image doesn't declare, or an image from before 0.26.0, gets the fixed env of before, the lake and the UI's PostHog key asPOSTHOG_KEY, and the plan says so. - Per stack. What one stack runs differently, such as an app's
envon dev, goes in that stack's overlay: amorca.toml-shaped file named byCONFIG_OVERLAY_FILEinhetzner.env, checked in the new image before a deploy changes anything (A stack's overlay).
The full runbook is Apps in docs/hetzner.md (#331, #332).
Overlapping schedulers
Since 0.18.0, with orca-stack configure OVERLAP=1 (off by default), a
deploy that replaces the scheduler doesn't pause. The new scheduler starts beside the
old one and takes the lead, and the old one starts nothing more, finishes its runs
under its own image and exits (#232). A
migration that raises the schema's floor refuses the overlap, and the deploy then
pauses and waits as above, saying why.
Rollbacks
./deploy.sh --rollback # back to the tags deployed before
ssh root@<ip> orca-stack apply --app console=<sha> # only an app
Each deploy keeps the tags it replaced and, when it replaces anything, a database
backup first (since 0.16.0). --rollback applies the previous tags and, if
the scheduler was replaced, registers the pipelines again, so runs start with the code
that's deployed. Postgres isn't rolled back: an older morca runs on a newer schema
whose migrations since are additive. Only a migration that raises the floor needs the
backup restored (Rolling back).
Settings and secrets
Settings from hetzner.env (since 0.18.0). Every deploy,
rollbacks too, brings the server's settings and secret files in line with
hetzner.env and prints the names of what changed, never a value. So
hetzner.env is where a setting changes: a hand edit to
/etc/orca/settings.env is undone by the next deploy, and an extra line
belongs in EXTRA_ENV_FILE.
Secrets encrypted with SOPS (since 0.19.0). A secret file that
hetzner.env names as *.sops or *.sops.<ext>
is decrypted with sops -d on its way to the server and never written to a
file on the laptop, so the laptop keeps one age key instead of plain tokens
(Secrets on your
laptop). One SECRETS_FILE can hold every secret, decrypted once,
so a Secure Enclave key asks for Touch ID once per deploy
(#265).
Rescaling
./rescale.sh up # CAX21 -> CAX41, keeping the disk
./rescale.sh down # CAX41 -> CAX21
For an import, rescale.sh changes the server's type. It pauses every
pipeline and waits for the running runs, those on remote workers too, since the UI
they talk to goes down with the server; backs up, changes the type, waits for the
scheduler and unpauses what it paused. The server is down for a few minutes
(Rescaling for an
import).
Next
- morca #247:
orca deployin the CLI, with the scripts built into the binary and the settings in the app's repository. - morca #250: a dev stack and a release flow that promotes the image tested there to production.
- morca #263: deploying on GCP's ARM machines beside Hetzner, and the scripts working against any host with SSH.