firepeel
No. 00 / getting started

from bare metal
to a running VM

Everything you need on a Linux host to build the guest image, and bring fc-orchestrator and fc-node up from scratch.

No. 01 / requirements

what you need

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
root required fc-node calls 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.
No. 02 / installation

setting up the host

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.

01

confirm KVM works

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.

02

install the Firecracker binary

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
03

install nftables, WireGuard, and iproute2

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 ];
04

install Go

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
05

install and configure PostgreSQL

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.

06

build the guest OS image with Nix

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
exact output paths vary by microvm.nix version Inspect 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.
07

build and run fc-orchestrator

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.

08

build and run fc-node

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.

No. 03 / verify

launch a test VM

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.