If your CI/CD pipelines live in YAML files that break in ways you can’t reproduce locally, Dagger is worth a look. It lets you write pipelines in Python, Go, or TypeScript instead of YAML, and runs every step inside containers. The same code works on your laptop, in GitHub Actions, in GitLab CI, and anywhere else Docker runs.
This guide covers installing Dagger on Rocky Linux 10 (and AlmaLinux 10) with Docker Engine, handling the kernel module dependency that trips up most people, and running a real pipeline with SELinux in enforcing mode. Rocky and AlmaLinux share the same RHEL 10 base, so every command here works on both.
Verified working: April 2026 on Rocky Linux 10.1 (kernel 6.12), SELinux enforcing, Docker 29.4.0, Dagger v0.20.3
What You Need
- Rocky Linux 10 or AlmaLinux 10 server with at least 2 GB RAM
- Root or sudo access
- Internet access (Dagger pulls container images at runtime)
- SELinux in enforcing mode (default on Rocky/AlmaLinux, and Dagger works fine with it)
1. Install Required Kernel Modules
Rocky Linux 10’s minimal install ships without several netfilter kernel modules that Docker needs. If you skip this step, Docker will fail to start with an iptables error about xt_addrtype. Install the kernel-modules-extra package first:
sudo dnf install -y kernel-modules-extra
This installs netfilter modules (xt_addrtype, br_netfilter, ip_tables) for the latest available kernel. If your running kernel is older than the installed modules, reboot to pick up the new kernel:
sudo reboot
After the reboot, verify the kernel version and load the required modules:
uname -r
You should see the updated kernel:
6.12.0-124.45.1.el10_1.x86_64
Load the modules Docker requires:
sudo modprobe xt_addrtype
sudo modprobe br_netfilter
sudo modprobe ip_tables
Make them persistent across reboots:
echo -e "xt_addrtype\nbr_netfilter\nip_tables" | sudo tee /etc/modules-load.d/docker.conf
2. Install Docker Engine
Dagger requires a container runtime. Docker is the primary choice, though Podman and nerdctl are also supported. If you already have Docker Engine installed, skip ahead.
Add the Docker CE repository for RHEL:
sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
Install Docker Engine and its components:
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Enable and start the Docker service:
sudo systemctl enable --now docker
Confirm Docker is running:
docker --version
Expected output:
Docker version 29.4.0, build 9d7ad9f
Add your user to the docker group to avoid running every command with sudo:
sudo usermod -aG docker $USER
newgrp docker
3. Install the Dagger CLI
The install script auto-detects your platform, downloads the latest stable binary, and verifies its checksum:
curl -fsSL https://dl.dagger.io/dagger/install.sh | BIN_DIR=/usr/local/bin sudo -E sh
The output confirms the installation:
installed /usr/local/bin/dagger
Verify the version:
dagger version
Output:
dagger v0.20.3 (image://registry.dagger.io/engine:v0.20.3) linux/amd64
4. Verify SELinux Compatibility
One of the first things to check on RHEL-family systems: does Dagger work with SELinux in enforcing mode? The answer is yes. Docker’s SELinux policies cover the Dagger Engine container, and no custom setsebool or semanage rules are needed.
Confirm SELinux is enforcing:
getenforce
This should return Enforcing.
5. Create and Run Your First Dagger Module
Initialize a module with the Python SDK. Dagger also supports Go and TypeScript as official SDKs:
mkdir ~/my-project && cd ~/my-project
dagger init --name=my-project --sdk=python
On the first run, Dagger pulls the engine image (registry.dagger.io/engine:v0.20.3), starts it as a Docker container, and generates the Python SDK scaffolding. This takes about 30 seconds:
connect
┆ starting engine
┆ connecting to engine
┆ INF connected client-version=v0.20.3 server-version=v0.20.3
load module: .
┆ initializing module
┆ module SDK: run codegen DONE [8.4s]
Initialized module my-project in /home/rocky/my-project
The engine runs as a persistent Docker container. Verify it:
docker ps --filter name=dagger --format "table {{.Names}}\t{{.Image}}\t{{.Status}}"
Output:
NAMES IMAGE STATUS
dagger-engine-v0.20.3 registry.dagger.io/engine:v0.20.3 Up 2 minutes
Run the generated example function:
dagger call container-echo --string-arg="Hello from Rocky Linux" stdout
Dagger loads the module, pulls an Alpine container, runs the echo command, and returns the result:
MyProject.containerEcho(stringArg: "Hello from Rocky Linux"): Container!
┆ Container.from(address: "alpine:latest"): Container! CACHED [1.0s]
┆ withExec echo 'Hello from Rocky Linux'
┆ | Hello from Rocky Linux
MyProject.containerEcho DONE [4.0s]
Hello from Rocky Linux
Check for SELinux denials after running the pipeline:
sudo ausearch -m avc -ts recent
The output should show <no matches>, confirming no SELinux policy violations occurred.
6. Open Firewall Ports (if firewalld is active)
Dagger itself does not listen on any external ports. All communication happens through the Docker socket. If your pipelines expose services (like a test web server), open those ports through firewalld:
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
Cloud VMs often ship with firewalld inactive. Check with sudo firewall-cmd --state. If it returns not running, no firewall rules are needed.
Rocky Linux 10 vs Ubuntu 24.04: Differences for Dagger
If you’re following multiple guides, here’s what differs between the two platforms:
| Item | Rocky Linux 10 / AlmaLinux 10 | Ubuntu 24.04 |
|---|---|---|
| Docker repo URL | download.docker.com/linux/rhel/ | download.docker.com/linux/ubuntu/ |
| Add repo command | dnf config-manager --add-repo | echo "deb ..." | tee |
| Kernel modules | Requires kernel-modules-extra + reboot | Included by default |
| SELinux | Enforcing (works, no custom rules needed) | Not present (uses AppArmor) |
| Firewall | firewalld (often inactive on cloud VMs) | ufw (often inactive on cloud VMs) |
| Python version | 3.12.11 | 3.12.3 |
| Dagger install | Identical install script | Identical install script |
| Dagger behavior | Identical | Identical |
The Dagger CLI and engine are the same on both platforms. The only real difference is the kernel module dependency on Rocky/AlmaLinux, which is a one-time fix.
Troubleshooting
Error: “Extension addrtype revision 0 not supported, missing kernel module?”
This is the most common failure when installing Docker on Rocky Linux 10. The xt_addrtype kernel module is missing because the minimal install doesn’t include kernel-modules-extra. The fix:
sudo dnf install -y kernel-modules-extra
sudo reboot
After reboot, load the modules and restart Docker:
sudo modprobe xt_addrtype br_netfilter ip_tables
sudo systemctl restart docker
Error: “failed to start daemon: Error initializing network controller”
Same root cause as above. Docker’s bridge driver needs iptables/nftables modules that aren’t loaded. The full error includes “failed to add jump rules to ipv4 NAT table.” Install kernel-modules-extra, reboot, and load the modules.
Dagger command hangs or times out
If dagger call hangs, the Docker daemon is likely not running. Check with sudo systemctl status docker. If Docker failed to start, the kernel module issue above is the most likely cause on Rocky Linux 10.
SELinux blocking Docker or Dagger
In testing, Dagger worked without any SELinux denials. Docker’s built-in SELinux policies handle the Dagger Engine container correctly. If you do encounter denials, check with:
sudo ausearch -m avc -ts recent
sudo sealert -a /var/log/audit/audit.log
Never disable SELinux (setenforce 0) as a workaround. If a denial appears, apply the specific boolean or context that the sealert output suggests.