This guide walks you through setting up Vela on a server and deploying your first app.
- A Linux server (Hetzner dedicated, bare metal, or any VPS)
- SSH access with key-based auth
- Your app builds to a binary (Rust, Go, etc.) or a BEAM release (Elixir/Phoenix)
SSH into your server and run the install script:
curl -fsSL https://raw.githubusercontent.com/raskell-io/vela/main/install.sh | bashThis detects your platform (linux/amd64 or linux/arm64), downloads the latest release, and installs it to /usr/local/bin/vela.
To install a specific version or to a different directory:
curl -fsSL https://raw.githubusercontent.com/raskell-io/vela/main/install.sh | bash -s -- --version v0.4.0 --to /opt/binCreate the server 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"
EOFStart the server as a systemd service (recommended):
# Generate and install the systemd unit file
vela setup
# Enable and start
sudo systemctl enable --now velaOr run manually for testing:
RUST_LOG=info vela serve --config /etc/vela/server.tomlImportant: The server config must be at /etc/vela/server.toml. All internal commands (_deploy, _rollback, _secret, _logs) use this as the default config path. If you use a non-default path, you'll need to configure the --config flag in your deploy commands.
The vela serve daemon must be running before you deploy. The deploy command communicates with the daemon via a Unix socket at /var/vela/vela.sock. If the daemon isn't running, deploys will fail with "failed to connect to vela daemon".
Run the same install script — it detects macOS/Linux and amd64/arm64 automatically:
curl -fsSL https://raw.githubusercontent.com/raskell-io/vela/main/install.sh | bashOr install to a user-local directory (no sudo needed):
curl -fsSL https://raw.githubusercontent.com/raskell-io/vela/main/install.sh | bash -s -- --to ~/.local/binOr build from source (requires Rust 1.93+):
cargo install --git https://github.com/raskell-io/velaIn your app's repository:
cd my-app
vela init --name my-app --domain my-app.example.comThis creates a Vela.toml:
[app]
name = "my-app"
domain = "my-app.example.com"
[deploy]
server = "root@your-server.example.com"
type = "binary"
binary = "my-app"
health = "/health"
[env]
# DATABASE_PATH = "${data_dir}/my-app.db"
[resources]
# memory = "512M"Edit [deploy].server to point at your server.
Build your app and deploy:
# Rust app
cargo build --release
vela deploy ./target/release/my-app
# Elixir/Phoenix app
MIX_ENV=prod mix release
vela deploy ./_build/prod/rel/my_appThat's it. Vela uploads the artifact, starts it, runs a health check, and swaps traffic.
# Check status
vela status
# Tail logs
vela logs my-app -f
# Visit your app
curl https://my-app.example.comFor a complete pre-flight checklist (firewall, DNS, TLS staging, troubleshooting), see Production Checklist.
vela deploycreates a tarball of your artifact- Uploads it to the server via
scp - Server extracts it to
/var/vela/apps/my-app/releases/<timestamp>/ - Server starts the new binary on a random port
- Server hits your health check endpoint until it returns 200
- Proxy swaps traffic from old instance to new
- Old instance drains connections and shuts down
Your app receives these environment variables:
| Variable | Value |
|---|---|
PORT |
The port to listen on |
VELA_PORT |
Same as PORT |
VELA_DATA_DIR |
Persistent data directory (survives deploys) |
VELA_APP_NAME |
Your app name |
Plus any variables you define in [env] in your Vela.toml.
Run the install script again to get the latest version:
curl -fsSL https://raw.githubusercontent.com/raskell-io/vela/main/install.sh | bashOr pin a specific version:
curl -fsSL https://raw.githubusercontent.com/raskell-io/vela/main/install.sh | bash -s -- --version v0.4.0