VyOs Kernel Setup for Incus Agent

VyOS with Incus Agent Compilation Guide

This guide walks you through compiling VyOS with support for the Incus agent, which requires adding 9P filesystem support to the kernel configuration.

Prerequisites

  • Docker installed on your system
  • Git installed
  • Sufficient disk space for kernel compilation
  • Root/sudo access

Step 1: Clone VyOS Build Repository

First, clone the VyOS build repository and navigate to the kernel build directory:

git clone https://github.com/vyos/vyos-build.git
cd vyos-build/scripts/package-build/linux-kernel

Step 2: Clone Linux Kernel Source

Download the Linux kernel source code:

git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git

Step 3: Configure Kernel for Incus Agent

Create the fix_9p_config.sh script (provided below) and make it executable:

chmod +x fix_9p_config.sh

Run the script to add 9P settings required for the Incus agent:

./fix_9p_config.sh arch/x86/configs/vyos_defconfig

This script will automatically configure the kernel with the necessary 9P filesystem support.

Step 4: Build the Kernel

Navigate back to the main VyOS build directory and start the Docker container:

cd ../../../  # Return to main vyos-build directory
docker run --rm -it --privileged -v $(pwd):/vyos -w /vyos vyos/vyos-build:current bash

Step 5: Install Dependencies and Build

Inside the Docker container, install the required build dependencies:

sudo su
apt install -y bc kmod libelf-dev libssl-dev flex bison python3 libpfm4 libtraceevent-dev libunwind-dev libdw-dev libdebuginfod-dev systemtap-sdt-dev libslang2-dev libperl-dev python3-dev
exit

Navigate to the kernel build directory and checkout the desired kernel version:

cd scripts/package-build/linux-kernel
git checkout <kernel_version>  # Replace with your desired kernel version
./build-kernel.sh

Step 6: Copy Built Packages

Copy the generated .deb files to the main packages directory:

cp *.deb ../../../packages/

The following .deb files should be generated:

  • linux-headers-6.6.96-vyos_6.6.96-1_amd64.deb
  • linux-image-6.6.96-vyos_6.6.96-1_amd64.deb
  • linux-libc-dev_6.6.96-1_amd64.deb
  • linux-perf-6.6.96-vyos_6.6.96-1_amd64.deb

Step 7: Add Incus Agent Package

Add the Incus agent .deb file to the same packages directory where you copied the kernel packages.

Step 8: Build VyOS ISO Image

From the main VyOS build directory, clean any previous builds and create the ISO image:

sudo make clean
sudo ./build-vyos-image --architecture amd64 --build-by "eminent" generic

Kernel Configuration Script

Below is the fix_9p_config.sh script that configures the kernel for 9P filesystem support:

#!/bin/bash

# 9P Kernel Configuration Fixer Script
# Usage: ./fix_9p_config.sh <defconfig_file>

set -e

# Check if file argument is provided
if [ $# -ne 1 ]; then
    echo "Usage: $0 <defconfig_file>"
    echo "Example: $0 arch/x86/configs/vyos_defconfig"
    exit 1
fi

DEFCONFIG_FILE="$1"

# Check if file exists
if [ ! -f "$DEFCONFIG_FILE" ]; then
    echo "Error: File '$DEFCONFIG_FILE' not found!"
    exit 1
fi

echo "=== 9P Kernel Configuration Fixer ==="
echo "Processing file: $DEFCONFIG_FILE"

# Create backup
BACKUP_FILE="${DEFCONFIG_FILE}.backup.$(date +%Y%m%d_%H%M%S)"
cp "$DEFCONFIG_FILE" "$BACKUP_FILE"
echo "Backup created: $BACKUP_FILE"

# Define required 9P configurations
declare -a REQUIRED_CONFIGS=(
    "CONFIG_NET_9P=y"
    "CONFIG_NET_9P_FD=y"
    "CONFIG_NET_9P_VIRTIO=y"
    "CONFIG_NET_9P_XEN=m"
    "CONFIG_NET_9P_RDMA=m"
    "CONFIG_9PNET=y"
    "CONFIG_9P_FS=y"
    "CONFIG_9P_FSCACHE=y"
    "CONFIG_9P_FS_POSIX_ACL=y"
    "CONFIG_9P_FS_SECURITY=y"
    "CONFIG_FSCACHE=y"
    "CONFIG_CACHEFILES=y"
    "CONFIG_VIRTIO_PCI=y"
    "CONFIG_VIRTIO=y"
    "CONFIG_VIRTIO_CONSOLE=y"
    "CONFIG_NETWORK_FILESYSTEMS=y"
    "CONFIG_NETFS_SUPPORT=y"
)

# Define configs to check for conflicts (both enabled and disabled forms)
declare -a CONFLICT_PATTERNS=(
    "CONFIG_NET_9P"
    "CONFIG_9PNET"
    "CONFIG_9P_FS"
    "CONFIG_9P_FSCACHE"
    "CONFIG_9P_FS_POSIX_ACL"
    "CONFIG_9P_FS_SECURITY"
    "CONFIG_FSCACHE"
    "CONFIG_CACHEFILES"
    "CONFIG_VIRTIO_PCI"
    "CONFIG_VIRTIO"
    "CONFIG_VIRTIO_CONSOLE"
    "CONFIG_NETWORK_FILESYSTEMS"
    "CONFIG_NETFS_SUPPORT"
)

echo ""
echo "=== Step 1: Checking for conflicting entries ==="

# Remove all existing instances of these configs (both enabled and disabled)
for pattern in "${CONFLICT_PATTERNS[@]}"; do
    # Count how many instances exist
    count=$(grep -c "^${pattern}=" "$DEFCONFIG_FILE" 2>/dev/null || true)
    disabled_count=$(grep -c "^# ${pattern} is not set" "$DEFCONFIG_FILE" 2>/dev/null || true)

    if [ "$count" -gt 0 ] || [ "$disabled_count" -gt 0 ]; then
        echo "  Found conflicts for $pattern: $count enabled, $disabled_count disabled"

        # Remove all instances (enabled and disabled)
        sed -i "/^${pattern}=/d" "$DEFCONFIG_FILE"
        sed -i "/^# ${pattern} is not set/d" "$DEFCONFIG_FILE"

        echo "  Removed all instances of $pattern"
    fi
done

echo ""
echo "=== Step 2: Adding required 9P configurations ==="

# Find a good place to insert configs (after comments, before first real config)
insert_line=$(grep -n "^CONFIG_" "$DEFCONFIG_FILE" | head -1 | cut -d: -f1)
if [ -z "$insert_line" ]; then
    # If no CONFIG lines found, add at end of file
    insert_line=$(wc -l < "$DEFCONFIG_FILE")
    ((insert_line++))
else
    # Insert before first CONFIG line
    ((insert_line--))
fi

echo "  Inserting configs at line $insert_line"

# Create temporary file with new configs
temp_file=$(mktemp)

# Add header comment
echo "# 9P Filesystem Support (Added by fix_9p_config.sh)" >> "$temp_file"

# Add all required configs
for config in "${REQUIRED_CONFIGS[@]}"; do
    echo "$config" >> "$temp_file"
    echo "  Added: $config"
done

echo "" >> "$temp_file"

# Insert the new configs into the original file
head -n "$insert_line" "$DEFCONFIG_FILE" > "${temp_file}.part1"
tail -n +$((insert_line + 1)) "$DEFCONFIG_FILE" > "${temp_file}.part2"

cat "${temp_file}.part1" "$temp_file" "${temp_file}.part2" > "$DEFCONFIG_FILE"

# Cleanup temp files
rm -f "$temp_file" "${temp_file}.part1" "${temp_file}.part2"

echo ""
echo "=== Step 3: Verification ==="

# Verify all required configs are present and no conflicts remain
echo "  Checking for required configs:"
all_present=true
for config in "${REQUIRED_CONFIGS[@]}"; do
    if grep -q "^${config}$" "$DEFCONFIG_FILE"; then
        echo "    ✓ $config"
    else
        echo "    ✗ $config - NOT FOUND!"
        all_present=false
    fi
done

echo ""
echo "  Checking for remaining conflicts:"
conflicts_found=false
for pattern in "${CONFLICT_PATTERNS[@]}"; do
    # Check for duplicates
    count=$(grep -c "^${pattern}=" "$DEFCONFIG_FILE" 2>/dev/null || true)
    disabled_count=$(grep -c "^# ${pattern} is not set" "$DEFCONFIG_FILE" 2>/dev/null || true)

    if [ "$count" -gt 1 ]; then
        echo "    ⚠  WARNING: Multiple enabled entries for $pattern ($count found)"
        conflicts_found=true
    fi

    if [ "$disabled_count" -gt 0 ]; then
        echo "    ⚠  WARNING: Disabled entries still present for $pattern ($disabled_count found)"
        conflicts_found=true
    fi
done

echo ""
echo "=== Summary ==="
if [ "$all_present" = true ] && [ "$conflicts_found" = false ]; then
    echo "✅ SUCCESS: All 9P configurations added successfully!"
    echo "✅ No conflicts detected."
else
    echo "❌ Issues detected. Please review the warnings above."
fi

echo ""
echo "📁 Original file backed up to: $BACKUP_FILE"
echo "📝 Modified file: $DEFCONFIG_FILE"
echo ""
echo "Next steps:"
echo "1. Review the changes: diff $BACKUP_FILE $DEFCONFIG_FILE"
echo "2. Build the kernel: ./build-kernel.sh"
echo "3. Verify 9P support: grep 9P linux/.config"

exit 0

What This Process Does

  1. Kernel Configuration: The script automatically adds 9P filesystem support to the VyOS kernel configuration, which is essential for the Incus agent to function properly.

  2. 9P Filesystem: This provides the communication channel between the Incus host and the VyOS container, allowing for file sharing and agent communication.

  3. Custom Build: Creates a custom VyOS image with Incus agent support built-in.

Troubleshooting

  • Build Failures: Ensure all dependencies are installed and you have sufficient disk space
  • 9P Support: Verify 9P support is enabled by checking grep 9P linux/.config after kernel build
  • Container Issues: Make sure Docker has sufficient privileges and resources allocated

Notes

  • Replace <kernel_version> with the specific kernel version you want to build (e.g., v6.6.96)
  • The build process may take considerable time depending on your system specifications
  • Ensure you have the correct Incus agent .deb package for your target architecture
1 Like

I’ve moved this to the Tutorials category.

Thank you

If 9p is the only thing missing in the kernel, then you could use the same trick we’re using with the RHEL derivatives (which also are lacking the module).

For those, we have incus config device add NAME agent disk source=agent:config

This provides what you’d normally get from 9p over a cd-rom drive instead.
That then lets you mount the cdrom (/dev/cdrom or equivalent) and treat it the same as 9p, which typically means copying the content over to /run/incus_agent and then running the agent from there.

If that works in your scenario, that’d save you the rather annoying step of building a custom kernel.

I will try that thank you.

This method works with latest vyos stream: vyos-1.5-stream-2025-Q2-generic-amd64.iso