v0.5.1 · MIT · Linux server, macOS or Linux laptop
No-downtime deploys on bare metal.
Buy a server, install Vela, deploy from your laptop over SSH. One binary does both ends. No containers, no orchestrator, no platform bill: the new release takes traffic only after its health check passes.
curl -fsSL https://raw.githubusercontent.com/raskell-io/vela/main/install.sh | bashFig. 1 One deploy
$ vela deploy ./target/release/my-app
deploying my-app to root@203.0.113.7
uploading artifact...
activating...
deployed my-app to root@203.0.113.7- Upload
- Start on a fresh port
- Health check
- Swap the proxy
- Drain the old release
:10001 to :10002.What a deploy does
The old release keeps serving until the new one proves itself.
Fig. 2 The deploy sequence
Upload
The client tars your binary or BEAM release and copies it with
scp. The server unpacks it into a new, read-only release directory.Start on a fresh port
Vela runs
pre_start(your migrations), then starts the new release on a random port between 10000 and 20000 withPORTandVELA_DATA_DIRset.Health check
It asks your health path up to 30 times, a second apart. Anything but a 200 kills the new instance; the old one never noticed.
Swap the proxy
The built-in proxy points the domain at the new port and the
currentsymlink moves. Requests in flight finish where they started.Drain the old release
The old instance gets
drainseconds, thenSIGTERM, thenSIGKILL. The last five releases stay on disk forvela rollback.
Two strategies
Overlap when you can, take turns when you write to SQLite.
Fig. 3 Two instances over time
Blue-green default
Both instances run for a moment, so no request ever finds nothing listening. Use it for anything that keeps its state elsewhere.
Sequential
The old instance stops before the new one opens the database, so two writers never share a SQLite file. Your data directory survives every deploy.
serving health checking draining time →
In the binary
The parts you would otherwise glue together.
- Reverse proxy
- Routes by domain, passes WebSockets through, redirects HTTP to HTTPS. Built on hyper, inside the daemon.
- TLS by itself
- Let's Encrypt over ACME HTTP-01, renewed 30 days before expiry. Or a Cloudflare Origin certificate, with optional mTLS for Authenticated Origin Pulls.
- SSH as the control plane
- The client runs
scpandsshwith the keys you already have. No tokens, no deploy API to secure. - Rust and Elixir
- Compiled binaries or BEAM releases. When cross-compiling is a pain,
remote = truebuilds on the server fromgit archive. - Postgres and NATS
- Declare them in
Vela.toml. Vela installs and provisions them and injectsDATABASE_URLorNATS_URL. - Secrets and rollback
- Per-app secrets in a mode 0600 file, referenced as
${secret:KEY}.vela rollbackgoes back one release. - Backups
- Scheduled copies of app data, secrets and
pg_dumpoutput, to a local path or S3. SQLite is checkpointed first. - Supervision
- Restarts apps that crash and restores them when the daemon restarts.
vela setupwrites a hardened systemd unit. - Status and logs
vela status --jsonprobes every health path live;vela logs my-app -ftails output from your laptop.
Vela.toml
One file in your repo.
[app]
name = "my-app"
domain = "my-app.example.com"
[deploy]
server = "root@your-server.example.com"
type = "binary" # or "beam" for Elixir
binary = "my-app"
health = "/health"
strategy = "blue-green" # or "sequential" for SQLite apps
pre_start = "bin/migrate" # failure aborts the deploy
[env]
DATABASE_PATH = "${data_dir}/my-app.db"
SECRET_KEY_BASE = "${secret:SECRET_KEY_BASE}"
[services.postgres]
version = "17"
databases = ["my_app_prod"]Your app
Four things it has to do.
- Listen on
$PORT. Vela picks the port; read it from the environment. - Answer its health path. Return 200 within 30 seconds of starting.
- Shut down on
SIGTERM. Finish what you are doing;SIGKILLfollows after a timeout. - Keep files in
$VELA_DATA_DIR. Databases and uploads there survive every deploy; release directories are read-only.
Scope
One server, on purpose.
Vela deploys to a single machine. It does not schedule across a cluster, and it is not trying to. If one good server runs your product, Vela is the whole platform.
Next: isolation between apps.
Apps on the same server are not yet separated by Linux namespaces or cgroups, and memory and CPU limits in [resources] are not enforced yet. Process isolation and resource limits are the next milestones. Follow along in the releases.
Fig. 4 The whole platform
.--------------------------------------.
/ /|
+--------------------------------------+ |
| vela serve :80 :443 | |
| .................................. | |
| proxy my-app.example.com -> 02 | |
| .................................. | |
| [01] my-app :10001 stopped | |
| [02] my-app :10002 live | |
| [--] postgres :5432 up | |
| .................................. | |
| /var/vela/apps/my-app/data | +
| |/
+--------------------------------------+
| |
=== ===