In this post i will briefly describe how to get the Forge “Forgejo” running on NixOS and with it, a custom runner comparable to GitHub Actions, but with a twist.

Basic setup

First, you will need to add the Forgejo service to your configuration. I will use a config snippet, that can be integrated in both classic and flake-based NixOS.

let
  # domain = "https://git.example.com";
  domain = <your_url>;
in
{
  # other configuration omitted
  services.forgejo = {
    enable = true;

    # this is for demo purposes, maybe you need different DB settings
    database.createDatabase = true;

    settings = {
      server = {
        # I use http because i maintain a separate reverse proxy,
        # the URLs still need to point to the exposed URL with https
        PROTOCOL = "http";
        ROOT_URL = "${domain}";
        DOMAIN = "${domain}";
      };

      actions = {
        ENABLED = true;
        # Get the default actions like checkout etc.
        DEFAULT_ACTIONS_URL = "https://code.forgejo.org";
      };
    };
  };
}

Depending on your firewall settings, you might need to open a port aswell. In my case (reverse proxy on another host) i have used the following code alongside my configuration. If you are using a reverse proxy on your host itself, these settings might differ.

networking.firewall.allowedTCPPorts = [
  config.services.forgejo.settings.server.HTTP_PORT
];

Extending the setup with out runner

After a succesful nixos-rebuild switch we can integrate our runner. We need to do this in 2 steps, because we need an access token, which we currently cannot obtain in any other way than the Forgejo GUI. The settings can be found in “User Settings” -> “Actions” -> “Runner” -> “Create a new runner” button. You can place the following code in the same .nix file. Right now, we have to use the `gitea-actions-runner` service, since there is no separate module packaged in NixPkgs right now. But since it is just the `act` runner, it does not matter and they are compatible (at the time of writing).

{
    let
      # domain = "https://git.example.com";
      domain = <your_url>;
    in
    {
      # other configuration omitted
    services.gitea-actions-runner.instances = {
      "local" = {
        enable = true;
        name = "LocalRunner";
        # those are images chosen for this demo, except the "native:host" you can choose any valid docker image
        # in the form "<tag>:<image>" whereas tag is later used in the `runs-on` value in the action .yml file
        labels = [ "debian-latest:docker://node:18-bullseye" "rust-x86:docker://ghcr.io/catthehacker/ubuntu:full-22.04c"  "native:host"] ;
        hostPackages = with pkgs; [
          # enter whatever packages you need here,
          # this is only for the native runner, not to container ones
          # this runs directly on the host machine
          bash
          coreutils
          curl
          gawk
          gitMinimal
          gnused
          nodejs
          wget
          cargo
        ];
        url = "${domain}";
        # do not forget to insert the token you recieved in the forgejo GUI
        token = "<YOUR_TOKEN>";
      };
    };
  }
}

After adding this configuration, we need to nixos-rebuild switch again for changes to take effect.