Skip to content

Installation

This guide will walk you through manually installing and configuring Fireactions on a Linux machine.

Overview

Fireactions consists of several components working together:

  • Firecracker: A lightweight virtual machine monitor that runs the runner environments
  • Containerd: Container runtime that pulls and manages runner images
  • CNI Plugins: Networking layer that connects VMs to the host network
  • Linux Kernel: A minimal kernel image optimized for Firecracker VMs
  • Fireactions: The orchestration service that ties everything together

Prerequisites

Before you begin, ensure you have:

Required

  • Linux server with x86_64 (amd64) or aarch64 (arm64) architecture
  • Root or sudo access for system-level configuration
  • KVM virtualization support - Firecracker requires hardware virtualization
  • GitHub App credentials:
    • App ID
    • App must be installed on your target organization
    • Private key (PEM format)
    • See Creating GitHub Apps for setup instructions
  • Dedicated block device for Containerd storage (e.g., /dev/nvme1n1, /dev/sdb)
    • This will be used exclusively for container image storage via LVM
    • Minimum 50GB recommended, though this depends on your image sizes

Verify Hardware Virtualization

Firecracker requires KVM (Kernel-based Virtual Machine) support:

# Check if KVM device exists
ls -la /dev/kvm

# Check if your CPU supports virtualization
grep -E '(vmx|svm)' /proc/cpuinfo

If /dev/kvm doesn't exist: Enable VT-x in BIOS (Intel) or AMD-V in BIOS (AMD) or ensure nested virtualization is enabled (Cloud providers).

Step 1: Install System Dependencies

Install the base packages needed for downloading and managing components.

For Ubuntu/Debian:

apt-get update
apt-get install -y curl gnupg lvm2 tar

For RHEL/CentOS/Rocky Linux:

yum install -y curl lvm2 tar

Step 2: Install Firecracker

Firecracker is an open-source virtualization technology that enables lightweight virtual machines. It provides the isolation layer for each GitHub Actions runner.

First, determine your system architecture and find the latest version:

# Set architecture variable
export ARCH=$(case $(uname -m) in
  x86_64) echo "amd64" ;;
  aarch64) echo "arm64" ;;
esac)

# Check latest release at: https://github.com/firecracker-microvm/firecracker/releases
export FIRECRACKER_VERSION=1.9.1  # Replace with latest version

Download and install the Firecracker binary:

curl -fsSL -o firecracker.tgz \
  "https://github.com/firecracker-microvm/firecracker/releases/download/v${FIRECRACKER_VERSION}/firecracker-v${FIRECRACKER_VERSION}-$(uname -m).tgz"

tar -xzf firecracker.tgz --strip-components=1
mv firecracker-v${FIRECRACKER_VERSION}-$(uname -m) /usr/local/bin/firecracker
chmod +x /usr/local/bin/firecracker
rm firecracker.tgz

Verify the installation:

firecracker --version

You should see output like: Firecracker v1.9.1

Step 3: Install Containerd

Containerd is an industry-standard container runtime that manages the lifecycle of containers. Fireactions uses it to pull runner images from container registries and prepare root filesystems for the VMs.

Download and Install Containerd

Check for the latest release at https://github.com/containerd/containerd/releases:

export CONTAINERD_VERSION=1.7.24  # Replace with latest 1.7.x version

curl -fsSL -o containerd.tar.gz \
  "https://github.com/containerd/containerd/releases/download/v${CONTAINERD_VERSION}/containerd-${CONTAINERD_VERSION}-linux-${ARCH}.tar.gz"

tar -xzf containerd.tar.gz
mv bin/containerd /usr/local/bin/containerd
mv bin/ctr /usr/local/bin/ctr
rm -rf bin containerd.tar.gz

Create Containerd Systemd Service

Systemd will manage the Containerd daemon lifecycle:

cat > /etc/systemd/system/containerd.service << 'EOF'
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target

[Service]
Type=notify
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/containerd
Delegate=yes
KillMode=process
Restart=always
RestartSec=5
LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=infinity
TasksMax=infinity
OOMScoreAdjust=-999

[Install]
WantedBy=multi-user.target
EOF

Configure Containerd with Devmapper Snapshotter

Containerd uses snapshotters to manage container filesystem layers. The devmapper snapshotter with LVM thin provisioning provides efficient storage management and better performance for our use case.

Create the configuration directory and file:

mkdir -p /etc/containerd

cat > /etc/containerd/config.toml << 'EOF'
version = 2

root      = "/var/lib/containerd"
imports   = []
state     = "/run/containerd"
oom_score = 0

[grpc]
  address = "/run/containerd/containerd.sock"
  uid     = 0
  gid     = 0

[plugins]
  [plugins."io.containerd.snapshotter.v1.devmapper"]
    pool_name       = "containerd-thinpool"
    root_path       = "/var/lib/containerd/devmapper"
    base_image_size = "30GB"
    discard_blocks  = true
EOF

Adjust base_image_size as needed depending on your container image sizes.

Setup LVM Thin Pool for Containerd

LVM thin provisioning allows efficient storage allocation. Instead of pre-allocating disk space for each container, space is allocated on-demand.

Important: This will wipe the specified device. Ensure you're using the correct device and it contains no important data.

# Set your dedicated device path
export CONTAINERD_SNAPSHOTTER_DEVICE=/dev/nvme1n1  # CHANGE THIS

# Verify the device exists and is unmounted
lsblk ${CONTAINERD_SNAPSHOTTER_DEVICE}

Create the LVM physical volume and volume group:

# Create physical volume
pvcreate -f ${CONTAINERD_SNAPSHOTTER_DEVICE}

# Create volume group named 'containerd'
vgcreate containerd ${CONTAINERD_SNAPSHOTTER_DEVICE}

Configure thin pool auto-extension (prevents space exhaustion):

cat > /etc/lvm/profile/containerd.profile << 'EOF'
activation {
  thin_pool_autoextend_threshold=80
  thin_pool_autoextend_percent=20
}
EOF

This configuration enables automatic extension of the thin pool when it reaches 80% capacity, increasing its size by 20% each time.

Create the thin pool:

lvcreate --type thin-pool -q -n thinpool \
  --poolmetadatasize 1G \
  --profile containerd \
  --monitor y \
  -l "95%VG" containerd

This creates the thin pool named thinpool in the containerd volume group.

Start Containerd

Enable and start the Containerd service:

systemctl daemon-reload
systemctl enable containerd
systemctl start containerd

# Verify it's running
systemctl status containerd

# Test with a simple command
ctr version

Step 4: Install CNI Plugins

The Container Network Interface (CNI) provides networking for containers and VMs. Fireactions uses several CNI plugins to create isolated network namespaces and connect VMs to the host network.

Install Standard CNI Plugins

Check for the latest release at https://github.com/containernetworking/plugins/releases:

export CNI_VERSION=1.6.1  # Replace with latest version

curl -fsSL -o cni-plugins.tgz \
  "https://github.com/containernetworking/plugins/releases/download/v${CNI_VERSION}/cni-plugins-linux-${ARCH}-v${CNI_VERSION}.tgz"

mkdir -p /opt/cni/bin
tar -xzf cni-plugins.tgz -C /opt/cni/bin
rm cni-plugins.tgz

# Verify installation
ls -lh /opt/cni/bin/

This installs bridge, host-local, and firewall plugins, which are essential for networking functionality.

Install tc-redirect-tap Plugin

The tc-redirect-tap plugin uses Traffic Control (tc) to redirect packets between the VM's tap device and the host, providing better performance than traditional bridging.

curl -fsSL -o /opt/cni/bin/tc-redirect-tap \
  "https://github.com/hostinger/tc-redirect-tap/releases/download/v0.0.1/tc-redirect-tap-${ARCH}"
chmod +x /opt/cni/bin/tc-redirect-tap

# Verify
/opt/cni/bin/tc-redirect-tap --version

Configure CNI Network

Create the network configuration that Fireactions will use:

mkdir -p /etc/cni/net.d

cat > /etc/cni/net.d/10-fireactions.conflist << 'EOF'
{
  "cniVersion": "0.4.0",
  "name": "fireactions",
  "plugins": [
    {
      "bridge": "fireactions-br0",
      "forceAddress": false,
      "hairpinMode": true,
      "ipMasq": true,
      "ipam": {
        "dataDir": "/var/run/cni",
        "resolvConf": "/etc/resolv.conf",
        "subnet": "192.168.128.0/24",
        "type": "host-local"
      },
      "isDefaultGateway": true,
      "mtu": 1500,
      "type": "bridge"
    },
    {
      "type": "firewall"
    },
    {
      "type": "tc-redirect-tap"
    }
  ]
}
EOF

Adjust the configuration as needed, especially the subnet. We recommend using a big subnet range (e.g., /23) to accommodate future growth.

Step 5: Download Kernel Image

Firecracker VMs require a Linux kernel. We provide pre-built, optimized kernel images, which you can download as follows:

export KERNEL_VERSION=5.10  # or 6.1 for newer kernel

mkdir -p /var/lib/fireactions/kernels/${KERNEL_VERSION}
curl -fsSL -o /var/lib/fireactions/kernels/${KERNEL_VERSION}/vmlinux \
  "https://storage.googleapis.com/fireactions/kernels/${ARCH}/${KERNEL_VERSION}/vmlinux"

# Verify download
ls -lh /var/lib/fireactions/kernels/${KERNEL_VERSION}/vmlinux

The kernel is configured with minimal modules to reduce the attack surface and improve boot times.

Step 6: Install Fireactions

Now install the Fireactions orchestrator that coordinates all these components.

Download Fireactions Binary

Check for the latest release at https://github.com/hostinger/fireactions/releases:

export FIREACTIONS_VERSION=1.0.0  # Replace with latest version

curl -fsSL -o fireactions.tar.gz \
  "https://github.com/hostinger/fireactions/releases/download/v${FIREACTIONS_VERSION}/fireactions-v${FIREACTIONS_VERSION}-linux-${ARCH}.tar.gz"

tar -xzf fireactions.tar.gz
mv fireactions /usr/local/bin/fireactions
chmod +x /usr/local/bin/fireactions
rm fireactions.tar.gz

# Verify installation
fireactions version

Configure Sysctl for IP Forwarding

Enable IP forwarding to allow VMs to reach external networks:

cat > /etc/sysctl.d/99-fireactions.conf << 'EOF'
net.ipv4.conf.all.forwarding=1
net.ipv4.ip_forward=1
EOF

# Apply immediately
sysctl -p /etc/sysctl.d/99-fireactions.conf

Create Fireactions Configuration

Create the main configuration file. This tells Fireactions how to connect to GitHub and how to provision runners.

mkdir -p /etc/fireactions

Create /etc/fireactions/config.yaml with your specific values:

# Address where Fireactions will listen (change to 0.0.0.0:8080 for external access)
bind_address: 127.0.0.1:8080

# Prometheus metrics endpoint
metrics:
  enabled: true
  address: 127.0.0.1:8081

# GitHub App authentication
github:
  app_id: YOUR_GITHUB_APP_ID
  app_private_key: |
    -----BEGIN RSA PRIVATE KEY-----
    YOUR_PRIVATE_KEY_CONTENT_HERE
    -----END RSA PRIVATE KEY-----

# Runner pool configuration
pools:
- name: default
  replicas: 1  # Number of concurrent runners in this pool
  runner:
    name: default
    # Runner image - must be compatible with Fireactions
    image: ghcr.io/hostinger/fireactions-images/ubuntu22.04:latest
    image_pull_policy: IfNotPresent  # or Always to pull on every run
    group_id: 1  # Runner group ID in GitHub (1 = default)
    organization: YOUR_GITHUB_ORGANIZATION  # or use 'repository: owner/repo'
    labels:
    - self-hosted
    - fireactions
    # Add more labels to target specific workflows
    # - gpu
    # - large-runner
  firecracker:
    binary_path: firecracker
    kernel_image_path: /var/lib/fireactions/kernels/5.10/vmlinux
    kernel_args: "console=ttyS0 noapic reboot=k panic=1 pci=off nomodules rw"
    machine_config:
      mem_size_mib: 2048  # RAM per VM (adjust based on your workloads)
      vcpu_count: 2       # vCPUs per VM
    # Custom metadata passed to VMs (accessible via MMDS)
    metadata:
      pool: default
      environment: production

# Logging level: debug, info, warn, error
log_level: info

For all configuration options, see the configuration guide.

Create Fireactions Systemd Service

Set up Fireactions to run as a system service:

cat > /etc/systemd/system/fireactions.service << 'EOF'
[Unit]
Description=Fireactions
Documentation=https://github.com/hostinger/fireactions
After=network.target containerd.service
Requires=containerd.service

[Service]
User=root
Type=simple
KillMode=process
ExecStartPre=/usr/bin/which firecracker
ExecStartPre=/usr/bin/which containerd
ExecStart=/usr/local/bin/fireactions server --config /etc/fireactions/config.yaml
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

Start Fireactions

Enable and start the service:

systemctl daemon-reload
systemctl enable fireactions
systemctl start fireactions

Step 7: Verify Installation

Check Service Status

systemctl status fireactions

Expected output:

● fireactions.service - Fireactions
     Loaded: loaded (/etc/systemd/system/fireactions.service; enabled; preset: enabled)
     Active: active (running) since Mon 2024-12-09 10:30:15 UTC; 5min ago
       Docs: https://github.com/hostinger/fireactions
    Process: 3564 ExecStartPre=/usr/bin/which firecracker (code=exited, status=0/SUCCESS)
    Process: 3566 ExecStartPre=/usr/bin/which containerd (code=exited, status=0/SUCCESS)
   Main PID: 3571 (fireactions)
      Tasks: 15
     Memory: 45.2M
        CPU: 2.134s

Refer to Troubleshooting Guide in case of issues.