main
  1{
  2  den,
  3  lib,
  4  ...
  5}: {
  6  den.aspects.services.forgejo.runner = {
  7    includes = [den.aspects.services.podman];
  8    settings.host = {
  9      instances = lib.mkOption {
 10        type = lib.types.attrsOf (lib.types.submodule ({name, ...}: {
 11          options = {
 12            name = lib.mkOption {
 13              type = lib.types.str;
 14              default = name;
 15            };
 16            servers = lib.mkOption {
 17              type = lib.types.attrsOf (lib.types.submodule {
 18                options = {
 19                  url = lib.mkOption {
 20                    type = lib.types.str;
 21                  };
 22                  uuid = lib.mkOption {
 23                    type = lib.types.str;
 24                  };
 25                  tokenFileAged = lib.mkOption {
 26                    type = lib.types.path;
 27                  };
 28                  labels = lib.mkOption {
 29                    type = lib.types.listOf lib.types.str;
 30                    description = "Extra labels used for this server.";
 31                    default = [];
 32                  };
 33                };
 34              });
 35              default = {};
 36            };
 37            labels = lib.mkOption {
 38              type = lib.types.listOf lib.types.str;
 39              default = [];
 40            };
 41            extraEnvironments = lib.mkOption {
 42              type = lib.types.attrsOf lib.types.str;
 43              default = {};
 44            };
 45            extraSettings = lib.mkOption {
 46              type = lib.types.attrsOf lib.types.anything;
 47              default = {};
 48            };
 49          };
 50        }));
 51        default = {};
 52      };
 53    };
 54
 55    persist = {
 56      directoies = [
 57        {
 58          directory = "/var/lib/private/forgejo-runner";
 59          user = "nobody";
 60          group = "nogroup";
 61          mode = "0700";
 62        }
 63      ];
 64    };
 65
 66    nixos = {
 67      host,
 68      config,
 69      ...
 70    }: let
 71      cfg = host.settings.services.forgejo.runner;
 72      mkServerTokenSecretName = instance: server: "forgejo-runner-${instance}-${server}-token";
 73    in {
 74      # If you would like to use docker runners in combination with cache actions,
 75      # be sure to add docker bridge interfaces “br-*” to the firewalls’ trusted interfaces.
 76      # See https://forgejo.org/docs/next/admin/actions/runner-installation/#nixos
 77      networking.firewall.trustedInterfaces =
 78        if (config.networking.nftables.enable)
 79        then ["br-*"]
 80        else ["br-+"];
 81
 82      services.forgejo-runner.instances =
 83        lib.mapAttrs (instance: instanceCfg: {
 84          enable = true;
 85
 86          settings = lib.mkMerge [
 87            {
 88              runner.labels = lib.unique (instanceCfg.labels ++ (lib.concatLists (lib.mapAttrsToList (_: serverCfg: serverCfg.labels) instanceCfg.servers)));
 89              server.connections =
 90                lib.mapAttrs (server: serverCfg: {
 91                  inherit (serverCfg) url uuid;
 92                })
 93                instanceCfg.servers;
 94              cache = {
 95                enabled = true;
 96                # See https://forgejo.org/docs/latest/user/actions/advanced-features/#cache
 97                # ONLY for podman backend
 98                proxy_port = 4000;
 99                actions_cache_url_override = "http://host.containers.internal:4000";
100              };
101              container = {
102                enable_ipv6 = true;
103                options = "--cap-add sys_admin --cap-add mknod --device /dev/fuse";
104              };
105            }
106            instanceCfg.extraSettings
107          ];
108
109          secrets = {
110            server.connections =
111              lib.mapAttrs (server: _: {
112                token_url = config.vaultix.secrets.${mkServerTokenSecretName instance server}.path;
113              })
114              instanceCfg.servers;
115          };
116        })
117        cfg.instances;
118
119      vaultix.secrets = lib.mergeAttrsList (
120        lib.mapAttrsToList (instance: instanceCfg:
121          lib.mapAttrs' (
122            server: serverCfg:
123              lib.nameValuePair (mkServerTokenSecretName instance server) {
124                file = serverCfg.tokenFileAged;
125              }
126          )
127          instanceCfg.servers)
128        cfg.instances
129      );
130    };
131  };
132}