Operations
elements man deploy/operations Read as markdownServices, migrations on production, redirects, packages, the preDeploy hook, and logging in to a machine by hand.
Services
Custom backend services deploy alongside the main app. Each service runs as a systemd unit, listens on its own port, and routes through the load balancer based on its declared domains.
deploy: {
services: [
{
name: "transcode-worker",
build: "go build -o services/transcode-worker/bin/transcode-worker ./cmd/transcode",
bin: "services/transcode-worker/bin/transcode-worker",
port: 8082,
domains: ["transcode.example.com"],
},
],
}
build runs locally before any SSH. The output binary at bin is then synced
to each machine. If build fails, the deploy aborts before any machine is
touched.
Migrations on Production
All pending migrations apply inside a single Postgres transaction. If migration 7 of 10 fails, all 10 roll back and the database is left exactly as it was before the deploy started. The schema either advances completely or not at all.
Migrations are forward-only. There is no automatic rollback for a migration that has already succeeded. If a release ships a bad migration, fix it with a new migration.
Long-running migrations block the deploy, and that is by design. The new release does not start serving traffic until the app database schema is ready.
A few Postgres DDL statements (CREATE INDEX CONCURRENTLY, VACUUM,
REINDEX CONCURRENTLY) cannot run inside a transaction and will fail under this
model. Apply those out of band: run the SQL directly via
elements db -connect=production and add a no-op migration file to keep
environments in sync.
Redirects
deploy: {
redirects: {
"www.example.com": "example.com",
},
}
The load balancer issues a 301 from source to destination before any service
routing. A typical use is redirecting www to apex, or apex to www.
Packages
OS packages are installed on every deploy machine during provisioning.
deploy: {
packages: ["ffmpeg", "imagemagick"],
}
Elements diffs the package list against the per-machine state, so
already-installed packages are not reinstalled. Per-environment or per-machine
packages entries extend this list.
preDeploy
Local commands run before any service builds and before any SSH. They run sequentially and fail fast.
deploy: {
preDeploy: [
"npm run lint",
"go build ./...",
],
}
Use for cross-cutting prep that doesn't belong to a single service.
Logging In to a Machine
elements deploy -json reports every failure, local and remote, and it is the
only thing a deploy needs. The commands below are for a human operator holding a
question the diagnostics did not answer. They are not a step in a deploy, and
reaching for one after a failed deploy trades a report the user can act on for a
tour of a machine.
elements ssh -connect=production # ssh into the first production machine
elements ssh -connect=production#production2 # specific machine
elements build -connect=production -json # query build state on the machine
Server logs are written to
/elements/projects/<project>/.elements/logs/project.log on the machine.
elements db -connect=production is not in that category. It is the normal way
to run sql against a deployed database, including the out-of-band DDL above.
Related
- Build:
elements man build. The deploy is a build that ships the release to a remote machine. - Migrations:
elements man migrations. The frozen-after-deploy rule and transaction batching. - Database:
elements man database. The bundled Postgres cluster and the