Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d446c3f3df |
5
microvm/.gitignore
vendored
Normal file
5
microvm/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
firecracker-config.json
|
||||||
|
rootfs.ext4
|
||||||
|
vmlinux.bin
|
||||||
|
reticulum-go
|
||||||
|
vsock.sock
|
||||||
121
microvm/README.md
Normal file
121
microvm/README.md
Normal file
@@ -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
|
||||||
|
|
||||||
198
microvm/setup.sh
Executable file
198
microvm/setup.sh
Executable file
@@ -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" <<EOF
|
||||||
|
::sysinit:/bin/sh /etc/rc
|
||||||
|
::respawn:/bin/sh
|
||||||
|
ttyS0::respawn:/bin/sh
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > "$TMP_DIR/etc/rc" <<EOF
|
||||||
|
#!/bin/sh
|
||||||
|
mount -t proc proc /proc
|
||||||
|
mount -t sysfs sysfs /sys
|
||||||
|
/bin/$BINARY_NAME
|
||||||
|
EOF
|
||||||
|
chmod +x "$TMP_DIR/etc/rc"
|
||||||
|
|
||||||
|
ROOTFS_SIZE_MB=100
|
||||||
|
dd if=/dev/zero of="$ROOTFS_PATH" bs=1M count="$ROOTFS_SIZE_MB" 2>/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" <<EOF
|
||||||
|
{
|
||||||
|
"boot-source": {
|
||||||
|
"kernel_image_path": "$MICROVM_DIR/vmlinux.bin",
|
||||||
|
"boot_args": "console=ttyS0 reboot=k panic=1 pci=off root=/dev/vda rw"
|
||||||
|
},
|
||||||
|
"drives": [
|
||||||
|
{
|
||||||
|
"drive_id": "rootfs",
|
||||||
|
"path_on_host": "$MICROVM_DIR/rootfs.ext4",
|
||||||
|
"is_root_device": true,
|
||||||
|
"is_read_only": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"machine-config": {
|
||||||
|
"vcpu_count": 1,
|
||||||
|
"mem_size_mib": 128,
|
||||||
|
"smt": false
|
||||||
|
},
|
||||||
|
"network-interfaces": [
|
||||||
|
{
|
||||||
|
"iface_id": "eth0",
|
||||||
|
"guest_mac": "AA:FC:00:00:00:01",
|
||||||
|
"host_dev_name": "tap0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"vsock": {
|
||||||
|
"guest_cid": 3,
|
||||||
|
"uds_path": "$VSOCK_SOCK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo "Config created: $CONFIG_PATH"
|
||||||
|
echo "API socket: $API_SOCK"
|
||||||
|
echo "VSock socket: $VSOCK_SOCK"
|
||||||
|
}
|
||||||
|
|
||||||
|
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')"
|
||||||
|
}
|
||||||
|
|
||||||
|
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 "$@"
|
||||||
|
|
||||||
Reference in New Issue
Block a user