This page gets both running. It takes about 15 minutes on a fresh server, most of it installing Nix and Podman.
On NixOS? Skip to NixOS. The rest of this page is for Debian, Ubuntu, and other systemd distributions.
How Russel runs
The installer creates a dedicated system account calledrussel. The control plane and every app run as that account, never as root and never as your own login user. So an app that escaped its container would find no SSH keys, no sudo, and none of your files.
You need sudo once, to install. After that, nothing runs as root.
1. Prepare the server
You need a Linux x86_64 server with systemd. A cheap VPS without KVM is fine: apps run as rootless Podman containers by default. Install Podman and the pieces rootless Podman needs (Debian 12, Ubuntu 22.04 or newer):
Note: use the daemon install. The russel account builds through the Nix daemon; a single-user Nix install belongs to one user and can’t be shared with it.
Check the server. The installer can tell you what’s still missing, and how to fix it:
FAIL. Lines marked warn are about optional features like microVMs. From a checkout, ./contrib/install.sh check does the same.
2. Install Russel on the server
Pick one of these. Both run the same checks first and stop if something is missing.Option A: download a release
SHA256SUMS before installing anything. You must name a version; there is no “latest”.
The release binaries need glibc 2.35 or newer (Ubuntu 22.04+, Debian 12+). On older distributions, on musl (Alpine), or on NixOS, build from source instead.
Option B: build from source
You need a Rust toolchain (rustup).What install.sh host did
- Created the
russelsystem account: no login shell, nosudo, home/var/lib/russel. It gets its own range of sub-IDs for rootless Podman, and “linger”, so it runs from boot without anyone logged in. - Created
/var/lib/russel(mode0700, owned byrussel). All Russel state lives here. - Generated an API token in
/etc/russel/env(ownerroot, grouprussel, mode0640). The token is never printed. - Added you (the user who ran
sudo) to therusselgroup, so you can read the token. - Installed
russel-ctrlto/usr/local/binand the dashboard to/usr/local/share/russel/dashboard. - Installed and started the system service
russel-ctrl, running asrusseland listening on127.0.0.1:7878only, with authentication required.
install.sh cli installed russel to ~/.local/bin. Make sure that directory is on your PATH.
Log out and back in (or run newgrp russel) before the next step. Group membership only applies to new logins.
3. Connect the CLI
The control plane only listens on127.0.0.1. Never expose port 7878 to the network. Reach it in one of three ways.
Same server
russel origin shows which control plane the CLI talks to and whether it is reachable. russel ps shows an empty table on a fresh install.
From your laptop, over SSH (recommended)
Install the CLI on the laptop (Option A withcli, or Option B’s install.sh cli). Then copy the token and open a tunnel:
./contrib/install.sh connect user@server does the same. connect starts a background SSH forward from the laptop’s 127.0.0.1:7878 to the server’s. It fails loudly if the forward cannot be set up. Keep it running while you use the CLI or dashboard. If you prefer to run it by hand:
From anywhere, over HTTPS
Put Caddy or nginx in front of127.0.0.1:7878 on the server, then log in with the HTTPS URL:
http:// to anything but loopback. Proxy configs: TLS reverse proxy.
Fish shell: don’tsourcethe env file; fish can’t readKEY=VALUEfiles.--token-fileworks in every shell.
4. Open the dashboard
Openhttp://127.0.0.1:7878/ (through the tunnel from a laptop, or your HTTPS URL). Paste the token from /etc/russel/env into Settings. The dashboard keeps it for that browser tab only; russel login does not fill it in. More: Dashboard.
5. Check the install
On the server:/var/lib/russel/ctrl.log; reading it needs sudo, because only russel can open that directory. journalctl -u russel-ctrl shows start-up errors.
You’re ready: Quickstart deploys an example app in a few minutes.
Optional: microVMs (experimental)
Containers are the default and what most servers should use. MicroVMs give each app its own kernel through Cloud Hypervisor. They need hardware virtualization, which most cheap VPSes don’t expose. You needcloud-hypervisor v52 or newer (older versions hang when cpus > 1), virtiofsd, and passt on PATH. install.sh check warns about each missing one.
When /dev/kvm exists, install.sh host adds russel to the kvm group and installs the release microVM kernel at /var/lib/russel/_pool/kernel/bzImage. Nothing else needs root. Without /dev/kvm, the installer prints “containers only” and moves on. To use your own kernel, build nix build .#microvm-kernel and set RUSSEL_KERNEL_PATH to result/bzImage in /etc/russel/env.
NixOS
Use theservices.russel module, not install.sh host and not the release binaries. Build russel-ctrl from source on the NixOS machine (Option B, cargo build only), install it, and point the module at it:
russel account, 127.0.0.1:7878, authentication required, /var/lib/russel at mode 0700, rootless Podman. The service is russel.service (systemctl status russel). For microVMs add services.russel.microvms.enable = true;. Details: systemd + NixOS.
Upgrade
Run the same install command with the new version. Your token and/var/lib/russel are kept, and the service restarts:
git pull, rebuild, and run sudo ./contrib/install.sh host again. If the new binary fails to start, the installer puts the old one back.
Never delete /etc/russel/env or /var/lib/russel when upgrading. Backups: Upgrades + backups.
Moving from an older per-user install
Earlier builds ofinstall.sh host ran russel-ctrl as your own user, from ~/.config/systemd/user. The new installer finds that setup and stops with the steps to move over:
russel ps, thenrussel destroyeach service. The newrusselaccount can’t take over containers that your own Podman started.systemctl --user disable --now russel-ctrl, then delete~/.config/systemd/user/russel-ctrl.service.sudo ./contrib/install.sh --take-state-ownership host. This gives/var/lib/russel(secrets, history, volumes) torussel, and keeps the token from~/.config/russel/env, so your existingrussel loginkeeps working.
russel deploy your services again.
Uninstall
Remove the control plane with:russel-ctrl, turns off linger for russel, ends its remaining processes, and deletes the unit, /usr/local/bin/russel-ctrl (and the .previous backup next to it), and /usr/local/share/russel. It keeps /var/lib/russel and /etc/russel/env, so a later install.sh host picks up your services, volumes, and token. It also keeps the russel account and its subuid/subgid ranges.
Containers live in the russel account’s Podman store, so the command stops when services still exist. Run russel ps, then russel destroy each service, then uninstall. sudo ./contrib/install.sh uninstall --force skips that check and leaves the containers orphaned.
To remove everything, add --purge:
/var/lib/russel (secrets, history, volumes), /etc/russel, the russel user and group, and its lines in /etc/subuid and /etc/subgid. Back up anything you need first: Upgrades + backups. The flags also work before the subcommand, so --force --purge uninstall does the same thing. The CLI on your laptop is separate: delete ~/.local/bin/russel if you want it gone.