Skip to content
Belltoy

The Rust eBPF development environment on M1 macOS

Published at:

The eBPF (Extended Berkeley Packet Filter) is a powerful Linux kernel technology that allows developers to run sandboxed programs directly within the kernel, extending its functionality safely and efficiently without changing source code or loading modules.

On macOS, we need a virtual machine to test and run eBPF programs. There are several choices, including Docker, Lima, QEMU, VirtualBox, VMWare, etc. Some of them do not support all kinds of eBPF programs. For example, if you want to run XDP programs, you need to use a VM that supports full networking features. In this tutorial, we will set up an eBPF development environment using VirtualBox on an M1 macOS machine.

Before the Apple M1 (ARM architecture), I used VirtualBox on Intel macOS to run an Ubuntu VM for eBPF development. Back then, I was using the redbpf library, which has been deprecated, to write eBPF programs in Rust. After switching to M1 macOS, VirtualBox was not available for a long time. Recently, I found that VirtualBox now supports ARM architecture and can run ARM-based Linux distributions. This makes it possible to set up an eBPF development environment on M1 macOS using VirtualBox.

Prerequisites

brew install filosottile/musl-cross/musl-cross

By default, it will install full cross compiler toolchains targeting musl Linux amd64, arm64, and arm.

which x86_64-linux-musl-gcc
which aarch64-linux-musl-gcc

Install VirtualBox for Apple Silicon hosts from here.

Install rustup and Rust toolchain if you haven’t already:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup target install aarch64-unknown-linux-musl
rustup target install x86_64-unknown-linux-musl

Install vagrant via homebrew:

brew tap hashicorp/tap
brew install hashicorp/tap/hashicorp-vagrant

Install the vagrant-reload plugin to allow reloading the VM without destroying it:

vagrant plugin install vagrant-reload

Set up the VM

Create a Vagrantfile with the following content in your project directory:

Vagrant.configure("2") do |config|
  config.vm.box = "cloud-image/debian-13"
  config.vm.box_version = "20260112.2355.0"

  # Disable synced folder
  config.vm.synced_folder ".", "/vagrant", disabled: true
  config.vm.synced_folder ".", "/home/vagrant/aya-hello", automount: true

  config.vm.network "private_network", type: "dhcp"
  config.vm.box_check_update = false

  config.vagrant.plugins = ["vagrant-reload"]

  config.vm.provider "virtualbox" do |virtualbox|
    virtualbox.memory = 4096
    virtualbox.cpus = 2
  end

  # Eventually use cloud-init to execute jobs
  config.vm.cloud_init do |cloud_init|
    cloud_init.content_type = "text/cloud-config"
    cloud_init.inline = <<-EOF
      apt:
        ## Use mirrors if needed
        # primary:
        #   - arches: [default]
        #     uri: https://mirrors.ustc.edu.cn/debian
        # security:
        #   - arches: [default]
        #     uri: https://mirrors.ustc.edu.cn/debian-security

      package_update: true

      packages:
        - build-essential
        - linux-headers-arm64
        - dkms
        - bpfcc-tools
        - bpftool

      runcmd:
        - wget http://download.virtualbox.org/virtualbox/7.2.4/VBoxGuestAdditions_7.2.4.iso
        - mkdir /media/VBoxGuestAdditions
        - mount -o loop,ro VBoxGuestAdditions_7.2.4.iso /media/VBoxGuestAdditions
        - sh /media/VBoxGuestAdditions/VBoxLinuxAdditions-arm64.run
        - rm VBoxGuestAdditions_7.2.4.iso
        - umount /media/VBoxGuestAdditions
        - rmdir /media/VBoxGuestAdditions
        - sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen
        - echo 'LANG="en_US.UTF-8"' > /etc/default/locale
        - dpkg-reconfigure --frontend=noninteractive locales
        - update-locale LANG=en_US.UTF-8
        - chsh -s /bin/bash vagrant
    EOF
  end
endVagrantfile

Cross-compile and run eBPF program

To cross-compile the eBPF program for the VM, run the following command on your macOS host:

cargo build --release --target=aarch64-unknown-linux-musl

Start the VM:

vagrant up

Wait for the VM to be fully set up. This may take some time as it installs the necessary packages.

SSH into the VM:

vagrant ssh

Navigate to the shared folder where your project is located:

cd /home/vagrant/aya-hello

Run the eBPF program inside the VM:

sudo RUST_LOG=debug target/aarch64-unknown-linux-musl/release/aya-hello

Conclusion

You have successfully set up an eBPF development and test environment on M1 macOS using VirtualBox. VirtualBox provides a full-featured VM with networking support, making it suitable for testing various types of eBPF programs, including XDP.

If you are not developing eBPF programs for network devices, you can also consider other VM solutions such as Docker, Lima, or QEMU, based on your requirements.

You can find the complete code for this tutorial in the aya-hello repository.

References


Share this post:

Previous Post
Manage Erlang/OTP ELP versions easyly
Next Post
从客户端角度深度理解 Kafka