Everything you need on a Linux host to build the guest image, and bring fc-orchestrator and fc-node up from scratch.
Firepeel is two Go binaries and a NixOS-built guest image. The host needs virtualization support, a couple of Linux networking tools, and a database — nothing exotic.
| Requirement | Used for | Notes |
|---|---|---|
| Linux host + KVM | Firecracker runs guests as KVM VMs | /dev/kvm must exist and be writable by fc-node (runs as root) |
| cgroup v2 | Per-VM CPU/memory accounting | Unified hierarchy mounted at /sys/fs/cgroup — default on any modern distro |
| Firecracker binary | The actual VM process fc-node execs | Static binary from GitHub releases, on $PATH or in /opt/firecracker/bin |
nftables (nft) |
Host firewall baseline + per-tenant NAT/forward rules | fc-node shells out to nft directly, no iptables fallback |
WireGuard + wireguard-tools |
Encrypted overlay network between nodes | Kernel ≥5.6 has WireGuard built in; older kernels need the wireguard module |
| iproute2 / netlink | Bridges, veths, taps, netns per tenant | fc-node talks to the kernel directly via netlink, but keep ip around for debugging |
| Go 1.25+ | Building fc-orchestrator and fc-node | Both go.mod files pin go 1.25.0 |
| PostgreSQL | Orchestrator's durable state — VM registry, tap/index allocation | Orchestrator runs its own migrations on startup |
| Nix (flakes) + microvm.nix | Building the guest kernel, initrd, and root filesystem | Only needed on whichever machine builds the guest image — not on every node |
os.Geteuid() and refuses to start unless it's running as root — it needs
raw access to netns, cgroups, and taps that an unprivileged process can't touch.
Run through these in order on the node that will run fc-node. Steps 1–5 are plain host setup; steps 6–8 are Firepeel itself.
Check that virtualization is enabled and the kernel module is loaded before installing anything else.
ls -l /dev/kvm lsmod | grep kvm # kvm_intel or kvm_amd should be listed
If /dev/kvm is missing, enable virtualization (VT-x/AMD-V) in the BIOS/hypervisor and reboot.
Download the latest release for your architecture and place it somewhere fc-node's findBinary lookup will see — on $PATH, or under /usr/local/bin, /usr/local/sbin, or /opt/firecracker/bin.
ARCH=$(uname -m)
release_url=$(curl -s https://api.github.com/repos/firecracker-microvm/firecracker/releases/latest \
| grep browser_download_url | grep "${ARCH}.tgz" | cut -d '"' -f4)
curl -L "$release_url" -o firecracker.tgz
tar xzf firecracker.tgz
sudo install -m 0755 release-*/firecracker-*-"${ARCH}" /usr/local/bin/firecracker
firecracker --version
These provide the host firewall, the cross-node overlay, and general Linux networking. On Debian/Ubuntu:
sudo apt update sudo apt install -y nftables wireguard-tools iproute2
On a NixOS host, add to configuration.nix instead:
networking.nftables.enable = true; environment.systemPackages = with pkgs; [ wireguard-tools iproute2 ];
curl -LO https://go.dev/dl/go1.25.0.linux-amd64.tar.gz sudo tar -C /usr/local -xzf go1.25.0.linux-amd64.tar.gz export PATH=$PATH:/usr/local/go/bin go version
Only needed on the host running fc-orchestrator. Create the database and role the orchestrator expects by default (override with DATABASE_URL):
sudo apt install -y postgresql sudo -u postgres psql -c "CREATE DATABASE fcorch;" sudo -u postgres psql -c "CREATE USER fcorch WITH PASSWORD 'fcorch';" sudo -u postgres psql -c "GRANT ALL ON DATABASE fcorch TO fcorch;"
The orchestrator runs its own schema migrations on startup — no manual SQL beyond creating the database.
The guest is a minimal NixOS built with microvm.nix
against the configuration.nix already checked into this project — the same recipe
used to build the base image running on this server. Install Nix with flakes enabled first:
sh <(curl -L https://nixos.org/nix/install) --daemon mkdir -p ~/.config/nix echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf
Wrap the existing configuration.nix in a flake that pulls in microvm.nix:
# flake.nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
microvm.url = "github:astro/microvm.nix";
microvm.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = { self, nixpkgs, microvm }: {
packages.x86_64-linux.firecracker-base =
(nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [ microvm.nixosModules.microvm ./configuration.nix ];
}).config.microvm.declaredRunner;
};
}
Build it, then copy the three artifacts fc-node expects at /opt/firecracker/base/:
nix build .#firecracker-base sudo mkdir -p /opt/firecracker/base sudo cp result/vmlinux /opt/firecracker/base/vmlinux sudo cp result/initrd /opt/firecracker/base/initrd sudo cp result/store.erofs /opt/firecracker/base/store.erofs
result/ after the build (ls -la result) to confirm the kernel,
initrd, and erofs store image filenames before copying — microvm.nix's output layout has changed
across releases.
cd fc-orchestrator go build -o fc-orchestrator . export DATABASE_URL="postgres://fcorch:fcorch@localhost:5432/fcorch?sslmode=disable" export LISTEN_ADDR=":8080" ./fc-orchestrator
On startup it connects to Postgres, runs migrations, and starts listening on LISTEN_ADDR — you should see connected to database in the log.
cd fc-node go build -o fc-node . export NODE_ID="node-1" export LISTEN_ADDR=":8081" export NODE_ADDR="<this-host-ip>:8081" export ORCHESTRATOR_URL="http://<orchestrator-host>:8080" sudo -E ./fc-node
fc-node must run as root. On startup it loads (or generates) its WireGuard keypair, installs the nftables firewall baseline, and registers itself with the orchestrator — registration blocks until the orchestrator is reachable.
With both services running, confirm the cluster works end-to-end:
curl -X POST http://localhost:8080/vm/launch \
-H "Content-Type: application/json" \
-d '{"instancename": "smoke-test", "tenant": "demo"}'
curl "http://localhost:8080/vm/list?tenant=demo"
See the full endpoint reference on the home page, or open the
web console at index.html in /var/lib/firepeel2/ to drive the same
launch/stop/console flow from the browser.