Skip to content

raskell-io/vela

Repository files navigation

Vela

No-downtime app deployment on bare metal. One binary. No containers. No bullshit.


Buy a server. Install Vela. Deploy your apps from your laptop over SSH. That's it.

No Docker. No Kubernetes. No YAML-driven orbital complexity. No $500/month for an app that nobody uses yet.

What It Does

# On your server
vela serve

# From your laptop
vela deploy ./target/release/my-app

Vela uploads your binary (or BEAM release), starts it on a fresh port, runs a health check, swaps the proxy, and drains the old instance. Zero downtime. Under a minute.

How It Works

┌─────────────────────────────────────────────┐
│  Your server                                │
│                                             │
│  Vela daemon                                │
│  ├── Reverse proxy (:80/:443, auto-TLS)     │
│  ├── Process manager (start, health, swap)  │
│  └── IPC socket (/var/vela/vela.sock)       │
│                                             │
│  Apps                                       │
│  ├── next.ai         → :10001               │
│  └── giga.app        → :10002               │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│  Your laptop                                │
│                                             │
│  vela deploy  →  scp + ssh  →  server       │
└─────────────────────────────────────────────┘
  • One binary — same vela runs on server and laptop
  • Embedded proxy — hyper-based reverse proxy with auto-TLS via Let's Encrypt (with auto-renewal)
  • SSH is the control plane — no tokens, no API keys, no custom auth
  • SQLite-aware — persistent data directories survive deploys; sequential strategy avoids write contention
  • Rust and Elixir — deploy compiled binaries or BEAM releases

Install

curl -fsSL https://raw.githubusercontent.com/raskell-io/vela/main/install.sh | bash

Binaries are available for Linux (amd64, arm64) and macOS (amd64, arm64).

Quick Start

1. Server Setup

# Install vela on your server
curl -fsSL https://raw.githubusercontent.com/raskell-io/vela/main/install.sh | bash

# Create config
mkdir -p /etc/vela
cat > /etc/vela/server.toml <<'EOF'
data_dir = "/var/vela"

[proxy]
http_port = 80
https_port = 443

[tls]
acme_email = "you@example.com"
staging = true  # Use staging first, switch to false once verified
EOF

# Install systemd service and start
vela setup
sudo systemctl enable --now vela

2. Project Setup

cd my-app
vela init --name my-app --domain my-app.example.com
# Edit Vela.toml → set deploy.server = "root@your-server-ip"

3. Deploy

cargo build --release
vela deploy ./target/release/my-app

Elixir/Phoenix

MIX_ENV=prod mix release
vela deploy ./_build/prod/rel/my_app

See docs/elixir-phoenix.md for the full guide.

Vela.toml

[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"    # runs before app starts; failure aborts deploy
post_deploy = "bin/notify"   # runs after traffic swap; failure is logged only

[env]
DATABASE_PATH = "${data_dir}/my-app.db"
SECRET_KEY_BASE = "${secret:SECRET_KEY_BASE}"

[services.postgres]
version = "17"
databases = ["my_app_prod"]

# [services.nats]
# jetstream = true

# [build]
# remote = true
# command = "cargo build --release"

Commands

Command Description
vela serve Start the server daemon (Linux)
vela setup Generate and install systemd service
vela init Generate a Vela.toml
vela deploy <artifact> Deploy an app
vela status [--json] Show running apps (with live health, PID, uptime)
vela logs <app> [-f] Tail app logs
vela rollback [<app>] Roll back to previous release
vela secret set <app> KEY=VALUE Set a secret
vela secret list <app> List secret keys
vela secret remove <app> KEY Remove a secret
vela backup Trigger a manual backup
vela apps List apps (server-side)

Deploy Strategies

Blue-green (default) — New instance starts alongside old. After health check passes, traffic swaps and old instance drains. True zero downtime.

Sequential — Old instance stops, new instance starts. Sub-second blip. Use for SQLite apps to avoid write contention during the overlap window.

Your App Needs To

  1. Listen on $PORT — Vela assigns a random port (10000-20000). Your app must read the PORT env var and bind to it.
  2. Respond on your health path — If you set health = "/health", return HTTP 200 within 30 seconds of startup.
  3. Handle SIGTERM — Vela sends SIGTERM for graceful shutdown, then SIGKILL after a timeout.
  4. Use $VELA_DATA_DIR for persistent files — databases, uploads, anything that survives deploys.

Documentation

Status

All core functionality is built, tested, and working:

  • Single binary (server + client)

  • SSH-based deploy pipeline (tarball upload → extract → health check → swap)

  • Reverse proxy with domain-based routing (hyper)

  • Auto-TLS via Let's Encrypt (ACME HTTP-01 with SNI-based cert resolution)

  • Static TLS support (Cloudflare Origin Certs, custom certs)

  • Blue-green and sequential deploy strategies

  • Process manager with port allocation and graceful shutdown (SIGTERM → SIGKILL)

  • IPC daemon architecture (Unix socket for deploy coordination)

  • Filesystem-backed state (no database dependency)

  • Secret management (per-app, file-backed, mode 0600)

  • Environment variable substitution (${data_dir}, ${secret:KEY})

  • Rollback to previous release

  • App restore on daemon restart

  • Log capture and streaming (vela logs -f)

  • Release sandbox (read-only release directories)

  • Elixir/Phoenix BEAM release support

  • systemd service generation with hardening (vela setup)

  • CI/CD pipeline with multi-platform release builds

  • Install script (auto-detects platform)

  • Process supervision with auto-restart on crash

  • Manifest env vars persisted across daemon restarts

  • Deploy hooks (pre_start and post_deploy)

  • HTTP → HTTPS redirect (with ACME challenge passthrough)

  • ACME certificate auto-renewal (checks daily, renews at 30 days before expiry)

  • Service dependencies: Postgres lifecycle management (install, provision, DATABASE_URL injection)

  • Service dependencies: NATS lifecycle management (download, supervise, NATS_URL injection)

  • Service dependencies framework (ServiceManager with per-service state persistence)

  • Scheduled backups (app data, secrets, pg_dump — local or S3)

  • Remote build support (git archive upload, build on server)

  • Machine-readable status (vela status --json with live health probes, PID, uptime)

Coming next:

  • Process isolation (Linux namespaces, cgroups v2)
  • Resource limits (memory, CPU weight)

Building from Source

# Requires Rust 1.93+
cargo install --path .

License

MIT