From d446c3f3dfe84beb23e26edde581c0cbc762bd58 Mon Sep 17 00:00:00 2001 From: Ivan Date: Fri, 7 Nov 2025 13:19:56 -0600 Subject: [PATCH] Add microVM setup files --- microvm/.gitignore | 5 ++ microvm/README.md | 121 +++++++++++++++++++++++++++ microvm/setup.sh | 198 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 324 insertions(+) create mode 100644 microvm/.gitignore create mode 100644 microvm/README.md create mode 100755 microvm/setup.sh diff --git a/microvm/.gitignore b/microvm/.gitignore new file mode 100644 index 0000000..b300cae --- /dev/null +++ b/microvm/.gitignore @@ -0,0 +1,5 @@ +firecracker-config.json +rootfs.ext4 +vmlinux.bin +reticulum-go +vsock.sock \ No newline at end of file diff --git a/microvm/README.md b/microvm/README.md new file mode 100644 index 0000000..94795ca --- /dev/null +++ b/microvm/README.md @@ -0,0 +1,121 @@ +# Reticulum-Go MicroVM + +Minimal Firecracker microVM setup for running Reticulum-Go. + +## Prerequisites + +- Firecracker binary installed +- Go compiler +- Root privileges (for network setup and KVM access) +- Linux host system with KVM support +- Access to `/dev/kvm` + +## Important: Nested Virtualization + +**If running inside a QEMU/KVM VM**, nested virtualization must be enabled: + +1. **Host QEMU configuration**: Start your QEMU VM with nested KVM: + ```bash + qemu-system-x86_64 -cpu host -enable-kvm -machine q35,accel=kvm ... + ``` + +2. **Enable nested KVM on host** (if not already): + ```bash + # Check if nested is enabled + cat /sys/module/kvm_intel/parameters/nested # Intel + cat /sys/module/kvm_amd/parameters/nested # AMD + + # Enable nested (Intel) + echo "options kvm_intel nested=1" | sudo tee /etc/modprobe.d/kvm.conf + + # Enable nested (AMD) + echo "options kvm_amd nested=1" | sudo tee /etc/modprobe.d/kvm.conf + + # Reboot host + ``` + +3. **Inside the VM**, check if `/dev/kvm` exists: + ```bash + ls -l /dev/kvm + ``` + +**Alternative**: If nested virtualization isn't available, consider: +- Running Firecracker directly on the host machine +- Using QEMU directly instead of Firecracker +- Using Docker/LXC containers instead + +## KVM Setup + +Ensure your user has access to `/dev/kvm`: + +```bash +# Check if /dev/kvm exists +ls -l /dev/kvm + +# Add your user to the kvm group (recommended) +sudo usermod -aG kvm $USER + +# Or set ACL (alternative) +sudo setfacl -m u:$USER:rw /dev/kvm + +# Log out and back in for group changes to take effect +``` + +## Setup + +Run the setup script: + +```bash +./setup.sh +``` + +This will: +- Check for Firecracker installation +- Download vmlinux.bin kernel +- Build Reticulum-Go binary +- Create rootfs.ext4 disk image +- Generate firecracker-config.json + +## Running + +1. Create tap interface: +```bash +sudo ip tuntap add tap0 mode tap +sudo ip addr add 172.16.0.1/24 dev tap0 +sudo ip link set tap0 up +``` + +2. Enable IP forwarding: +```bash +sudo sysctl -w net.ipv4.ip_forward=1 +``` + +3. Start Firecracker: +```bash +# Clean up any old socket files first +rm -f /tmp/firecracker.sock microvm/vsock.sock + +firecracker --api-sock /tmp/firecracker.sock --config-file firecracker-config.json +``` + +4. Connect to console (in another terminal): +```bash +firecracker --api-sock /tmp/firecracker.sock +``` + +## Configuration + +- **CPU**: 1 vCPU +- **Memory**: 128 MiB +- **Network**: tap0 interface +- **Disk**: rootfs.ext4 (100MB) + +Modify `firecracker-config.json` to adjust resources. + +## Files + +- `vmlinux.bin` - Linux kernel +- `rootfs.ext4` - Root filesystem with binary +- `firecracker-config.json` - Firecracker configuration +- `reticulum-go` - Compiled binary + diff --git a/microvm/setup.sh b/microvm/setup.sh new file mode 100755 index 0000000..25f05bb --- /dev/null +++ b/microvm/setup.sh @@ -0,0 +1,198 @@ +#!/bin/sh +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +MICROVM_DIR="$SCRIPT_DIR" +BINARY_NAME="reticulum-go" +FIRECRACKER_VERSION="v1.8.0" +FIRECRACKER_REPO="firecracker-microvm/firecracker" +VMLINUX_URL="https://s3.amazonaws.com/spec.ccfc.min/img/hello/kernel/hello-vmlinux.bin" + +check_command() { + if ! command -v "$1" >/dev/null 2>&1; then + echo "Error: $1 is not installed" >&2 + exit 1 + fi +} + +check_firecracker() { + if ! command -v firecracker >/dev/null 2>&1; then + echo "Error: firecracker binary is not installed" >&2 + echo "Install from: https://github.com/firecracker-microvm/firecracker/releases" >&2 + exit 1 + fi + echo "Firecracker found: $(firecracker --version 2>&1 || echo 'version check failed')" +} + +download_vmlinux() { + VMLINUX_PATH="$MICROVM_DIR/vmlinux.bin" + if [ -f "$VMLINUX_PATH" ]; then + echo "vmlinux.bin already exists, skipping download" + return + fi + + echo "Downloading vmlinux.bin from AWS S3..." + if ! command -v curl >/dev/null 2>&1; then + echo "Error: curl required to download vmlinux.bin" >&2 + exit 1 + fi + + curl -fsSL -o "$VMLINUX_PATH" "$VMLINUX_URL" + chmod +x "$VMLINUX_PATH" + echo "Downloaded: $VMLINUX_PATH" +} + +build_binary() { + echo "Building binary..." + cd "$PROJECT_ROOT" + GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o "$MICROVM_DIR/$BINARY_NAME" ./cmd/reticulum-go + echo "Binary built: $MICROVM_DIR/$BINARY_NAME" +} + +create_rootfs() { + ROOTFS_PATH="$MICROVM_DIR/rootfs.ext4" + if [ -f "$ROOTFS_PATH" ]; then + echo "rootfs.ext4 already exists, skipping creation" + return + fi + + echo "Creating rootfs..." + TMP_DIR=$(mktemp -d) + trap "rm -rf $TMP_DIR" EXIT + + mkdir -p "$TMP_DIR/bin" "$TMP_DIR/etc" "$TMP_DIR/dev" "$TMP_DIR/proc" "$TMP_DIR/sys" "$TMP_DIR/tmp" + + cp "$MICROVM_DIR/$BINARY_NAME" "$TMP_DIR/bin/" + chmod +x "$TMP_DIR/bin/$BINARY_NAME" + + cat > "$TMP_DIR/etc/inittab" < "$TMP_DIR/etc/rc" </dev/null + mkfs.ext4 -F "$ROOTFS_PATH" >/dev/null 2>&1 + + TMP_MOUNT=$(mktemp -d) + mount -o loop "$ROOTFS_PATH" "$TMP_MOUNT" 2>/dev/null || { + echo "Error: Failed to mount rootfs. You may need root privileges or use a different method." >&2 + rm -rf "$TMP_DIR" "$TMP_MOUNT" + exit 1 + } + trap "umount $TMP_MOUNT 2>/dev/null; rm -rf $TMP_DIR $TMP_MOUNT" EXIT + + cp -r "$TMP_DIR"/* "$TMP_MOUNT/" + umount "$TMP_MOUNT" + rm -rf "$TMP_DIR" "$TMP_MOUNT" + echo "Rootfs created: $ROOTFS_PATH" +} + +create_config() { + CONFIG_PATH="$MICROVM_DIR/firecracker-config.json" + API_SOCK="${API_SOCK:-/tmp/firecracker.sock}" + VSOCK_SOCK="${VSOCK_SOCK:-$MICROVM_DIR/vsock.sock}" + + cat > "$CONFIG_PATH" </dev/null 2>&1; then + echo "Error: firecracker binary is not installed" >&2 + echo "Install from: https://github.com/firecracker-microvm/firecracker/releases" >&2 + exit 1 + fi + echo "Firecracker found: $(firecracker --version 2>&1 || echo 'version check failed')" +} + +check_kvm() { + if [ ! -c /dev/kvm ]; then + echo "Warning: /dev/kvm not found. KVM may not be available." >&2 + return + fi + + if [ ! -r /dev/kvm ] || [ ! -w /dev/kvm ]; then + echo "Warning: /dev/kvm exists but you may not have read/write access." >&2 + echo "Add yourself to the kvm group: sudo usermod -aG kvm $USER" >&2 + echo "Or set ACL: sudo setfacl -m u:$USER:rw /dev/kvm" >&2 + else + echo "KVM access OK" + fi +} + +cleanup_sockets() { + echo "Cleaning up old socket files..." + rm -f /tmp/firecracker.sock "$MICROVM_DIR/vsock.sock" + echo "Cleanup complete" +} + +main() { + echo "Setting up microVM..." + + cleanup_sockets + + check_command go + check_firecracker + check_kvm + + download_vmlinux + build_binary + create_rootfs + create_config + + echo "" + echo "Setup complete!" + echo "Files created in: $MICROVM_DIR" + echo "" + echo "To run the microVM:" + echo " 1. Ensure KVM access: sudo usermod -aG kvm $USER (then logout/login)" + echo " 2. Create tap interface: sudo ip tuntap add tap0 mode tap" + echo " 3. Start firecracker: firecracker --api-sock /tmp/firecracker.sock --config-file $CONFIG_PATH" +} + +main "$@" +