Run Nix on Forgejo Actions on NixOS

Posted on March 26, 2026 at 18:47

I will start by assuming that you have a Forgejo instance running, and you know what is Forgejo Actions. If that is not the case, I invite you to read the Forgejo User documentation and the Forgejo Admin documentation. They are a good read!

Please note that NixOS is not required to have a Forgejo Actions runner building nix code. I deploy my runner with NixOS because it is so damn simple to run and maintain.

Setup a runner

Registration token

Let's say that your forgejo instance is available at https://forgejo.example.net.

With an administrator account, go to https://forgejo.example.net/admin/actions/runners and get a registration token.

Get the token, and be ready to put it when needed.

If you put the registration token directly in your configuration file, it might end up in the nix store, which is publicly readable by any user on the machine. To prevent this you can encrypt it, I recommend using agenix for that. It uses SSH keys for the encryption and it works great.

OCI containers and Forgejo labels

The runner will need to have a label to know which jobs it can pick up. There are many labels from which you can choose from but for our usecase the docker label is enough.

I prefer to use Podman over Docker, but using Docker is just fine.

In the past I used the excellent guide from Robin Appelman which creates a container image with Nix pre-installed. But it required flakes, and every once in a while I had to update the flake's inputs, rebuild the image, and load it to the container tool.

I want something that is simpler, and requires less maintenance. Fortunately there are pre-built container images (which already work with existing GitHub workflows) for act (the Forgejo actions runner is based on act). A popular option is https://github.com/catthehacker/docker_images, and an alternative could be https://github.com/tcpipuk/act-runner.

I will name the images like they are GitHub Actions to keep things similar.

{ config, lib, pkgs, ... }:

{
  virtualisation.containers.enable = true;
  virtualisation.oci-containers.backend = "podman";
  virtualisation = {
    podman = {
      enable = true;
      dockerCompat = true;
    };
  };

  services.gitea-actions-runner = {
    package = pkgs.forgejo-runner;
    instances.forgejo-runner = {
      enable = true;
      name = "my-forgejo-runner"; # TODO: put a cute name for your runner
      token = "put-token-here"; # TODO: use agenix
      url = "https://forgejo.example.net/"; # TODO: put the link to your instance
      labels = [
        "node-24:docker://node:24-trixie"
        "ubuntu-24.04:docker://ghcr.io/catthehacker/ubuntu:runner-24.04"
        "ubuntu-latest:docker://ghcr.io/catthehacker/ubuntu:runner-latest"
      ];
      settings = {
        container.network = "host";
      };
    };
  };
}

You are done configuring the runner! Rebuild the NixOS machine and you should see the runner appear in https://forgejo.example.net/admin/actions/runners.

Write your workflow file

To make sure everything works, create a test git repo on Forgejo with a simple default.nix or shell.nix, and create a file in .forgejo/workflows/ci.yml.

To install Nix, simply use the install-nix-action from cachix. If you use npins, you can even set the path to nixpkgs directly to save time:

name: CI
on:
  push:
jobs:
  my_nix_job:
    runs-on: ubuntu-latest
    steps:
      - uses: https://data.forgejo.org/actions/checkout@v6
      - uses: https://github.com/cachix/install-nix-action@v31
      - name: Get Nixpkgs path
        run: |
          nixpkgs_path=$(nix eval --raw -f npins/default.nix nixpkgs)
          echo "NIX_PATH=nixpkgs=$nixpkgs_path" >> "$FORGEJO_ENV"
      - run: nix-build ./default.nix

Commit and push the file, and you should have the job being picked on https://forgejo.example.net/user/repo/actions!