This commit is contained in:
xqtc 2024-07-11 15:28:28 +02:00
parent b0f920cda3
commit f2df025507
5 changed files with 345 additions and 7 deletions

View file

@ -6,7 +6,7 @@
}: { }: {
programs.git = { programs.git = {
enable = true; enable = true;
userName = "xqtc161"; userName = "xqtc";
userEmail = "xqtc@tutanota.com"; userEmail = "xqtc@tutanota.com";
extraConfig = { extraConfig = {
init = { init = {

View file

@ -47,13 +47,13 @@
inlayHints = { inlayHints = {
closureStyle = "rust_analyzer"; closureStyle = "rust_analyzer";
}; };
typing.autoClosingAngleBrackets.enable = true; typing.autoClosingAngleBrackets.enable = true;
}; };
}; };
}; };
lsp = { lsp = {
enable = true; enable = true;
inlayHints = true; inlayHints = true;
servers = { servers = {
typst-lsp.enable = true; typst-lsp.enable = true;
typos-lsp.enable = true; typos-lsp.enable = true;

View file

@ -1,8 +1,19 @@
{ {
lib, lib,
config,
inputs, inputs,
pkgs,
... ...
}: { }: let
gitea-actions-runner-custom = import ./services/gitea-runner.nix;
in {
imports = [ gitea-actions-runner-custom ];
# config = { services.gitea-actions-runner = gitea-actions-runner-custom.config.services.gitea-actions-runner; };
sops.secrets.forgejo_runner_token = {
owner = "forgejo";
group = "forgejo";
mode = "0444";
};
services.forgejo = { services.forgejo = {
enable = true; enable = true;
settings.server = { settings.server = {
@ -12,11 +23,75 @@
settings = { settings = {
service = { service = {
DISABLE_REGISTRATION = true; DISABLE_REGISTRATION = true;
REQUIRE_SIGNIN_VIEW = true; # REQUIRE_SIGNIN_VIEW = true;
}; };
DEFAULT = { DEFAULT = {
APP_NAME = "Git so good it could be heroin"; APP_NAME = "Git so good it could be heroin";
APP_DESC = "For an account, contact me via Mastodon";
}; };
}; };
}; };
services.gitea-actions-runner-custom = {
package = pkgs.forgejo-actions-runner;
instances.default = {
enable = true;
name = "monolith";
url = "https://git.heroin.trade";
token = "";
labels = [
"ubuntu-latest:docker://node:16-bullseye"
"ubuntu-22.04:docker://node:16-bullseye"
"ubuntu-20.04:docker://node:16-bullseye"
"ubuntu-18.04:docker://node:16-buster"
"native:host"
];
hostPackages = with pkgs; [
bash
coreutils
curl
gawk
gitMinimal
gnused
nodejs
wget
];
};
};
# systemd.services.gitea-runner-default = {
# preStart = lib.mkForce ''
# export INSTANCE_DIR="$STATE_DIRECTORY/default"
# export TOKEN="$(cat /run/secrets/forgejo_runner_token)"
# mkdir -vp "$INSTANCE_DIR"
# cd "$INSTANCE_DIR"
#
# # force reregistration on changed labels
# export LABELS_FILE="$INSTANCE_DIR/.labels"
# # export LABELS_WANTED="$(echo 'ubuntu-latest:docker://node:16-bullseye
# # ubuntu-22.04:docker://node:16-bullseye
# # ubuntu-20.04:docker://node:16-bullseye
# # ubuntu-18.04:docker://node:16-buster' | sort)"
# export LABELS_WANTED="$(echo ${lib.strings.concatStrings config.services.gitea-actions-runner.instances.default.labels} | sort)"
# export LABELS_CURRENT="$(cat $LABELS_FILE 2>/dev/null || echo 0)"
#
# if [ ! -e "$INSTANCE_DIR/.runner" ] || [ "$LABELS_WANTED" != "$LABELS_CURRENT" ]; then
# # remove existing registration file, so that changing the labels forces a re-registration
# rm -v "$INSTANCE_DIR/.runner" || true
#
# # perform the registration
# /nix/store/z3v4091wwdhdb60m72k0pxkim8q7chrk-forgejo-runner-3.5.0/bin/act_runner register --no-interactive \
# --instance 'https://git.heroin.trade' \
# --token "$TOKEN" \
# --name 'monolith' \
# --labels 'ubuntu-latest:docker://node:16-bullseye,ubuntu-22.04:docker://node:16-bullseye,ubuntu-20.04:docker://node:16-bullseye,ubuntu-18.04:docker://node:16-buster' \
# --config /nix/store/99q15qaajdi7rqz4bxbmhpkch2v8wg4f-config.yaml
#
# # and write back the configured labels
# echo "$LABELS_WANTED" > "$LABELS_FILE"
# fi
# '';
# serviceConfig.DynamicUser = lib.mkForce false;
# serviceConfig.User = lib.mkForce "forgejo";
# serviceConfig.Group = lib.mkForce "forgejo";
# };
environment.systemPackages = with pkgs; [forgejo-runner];
} }

View file

@ -0,0 +1,262 @@
{ config
, lib
, pkgs
, utils
, ...
}:
let
inherit (lib)
any
attrValues
concatStringsSep
escapeShellArg
hasInfix
hasSuffix
optionalAttrs
optionals
literalExpression
mapAttrs'
mkEnableOption
mkOption
mkPackageOption
mkIf
nameValuePair
types
;
inherit (utils)
escapeSystemdPath
;
cfg = config.services.gitea-actions-runner-custom;
settingsFormat = pkgs.formats.yaml { };
# Check whether any runner instance label requires a container runtime
# Empty label strings result in the upstream defined defaultLabels, which require docker
# https://gitea.com/gitea/act_runner/src/tag/v0.1.5/internal/app/cmd/register.go#L93-L98
hasDockerScheme = instance:
instance.labels == [] || any (label: hasInfix ":docker:" label) instance.labels;
wantsContainerRuntime = any hasDockerScheme (attrValues cfg.instances);
hasHostScheme = instance: any (label: hasSuffix ":host" label) instance.labels;
# provide shorthands for whether container runtimes are enabled
hasDocker = config.virtualisation.docker.enable;
hasPodman = config.virtualisation.podman.enable;
tokenXorTokenFile = instance:
(instance.token == null && instance.tokenFile != null) ||
(instance.token != null && instance.tokenFile == null);
in
{
meta.maintainers = with lib.maintainers; [
hexa
];
options.services.gitea-actions-runner-custom = with types; {
package = mkPackageOption pkgs "gitea-actions-runner-custom" { };
instances = mkOption {
default = {};
description = ''
Gitea Actions Runner instances.
'';
type = attrsOf (submodule {
options = {
enable = mkEnableOption "Gitea Actions Runner instance";
name = mkOption {
type = str;
example = literalExpression "config.networking.hostName";
description = ''
The name identifying the runner instance towards the Gitea/Forgejo instance.
'';
};
url = mkOption {
type = str;
example = "https://forge.example.com";
description = ''
Base URL of your Gitea/Forgejo instance.
'';
};
token = mkOption {
type = nullOr str;
default = null;
description = ''
Plain token to register at the configured Gitea/Forgejo instance.
'';
};
tokenFile = mkOption {
type = nullOr (either str path);
default = null;
description = ''
Path to an environment file, containing the `TOKEN` environment
variable, that holds a token to register at the configured
Gitea/Forgejo instance.
'';
};
labels = mkOption {
type = listOf str;
example = literalExpression ''
[
# provide a debian base with nodejs for actions
"debian-latest:docker://node:18-bullseye"
# fake the ubuntu name, because node provides no ubuntu builds
"ubuntu-latest:docker://node:18-bullseye"
# provide native execution on the host
#"native:host"
]
'';
description = ''
Labels used to map jobs to their runtime environment. Changing these
labels currently requires a new registration token.
Many common actions require bash, git and nodejs, as well as a filesystem
that follows the filesystem hierarchy standard.
'';
};
settings = mkOption {
description = ''
Configuration for `act_runner daemon`.
See https://gitea.com/gitea/act_runner/src/branch/main/internal/pkg/config/config.example.yaml for an example configuration
'';
type = types.submodule {
freeformType = settingsFormat.type;
};
default = { };
};
hostPackages = mkOption {
type = listOf package;
default = with pkgs; [
bash
coreutils
curl
gawk
gitMinimal
gnused
nodejs
wget
];
defaultText = literalExpression ''
with pkgs; [
bash
coreutils
curl
gawk
gitMinimal
gnused
nodejs
wget
]
'';
description = ''
List of packages, that are available to actions, when the runner is configured
with a host execution label.
'';
};
};
});
};
};
config = mkIf (cfg.instances != {}) {
assertions = [ {
assertion = any tokenXorTokenFile (attrValues cfg.instances);
message = "Instances of gitea-actions-runner-custom can have `token` or `tokenFile`, not both.";
} {
assertion = wantsContainerRuntime -> hasDocker || hasPodman;
message = "Label configuration on gitea-actions-runner-custom instance requires either docker or podman.";
} ];
systemd.services = let
mkRunnerService = name: instance: let
wantsContainerRuntime = hasDockerScheme instance;
wantsHost = hasHostScheme instance;
wantsDocker = wantsContainerRuntime && config.virtualisation.docker.enable;
wantsPodman = wantsContainerRuntime && config.virtualisation.podman.enable;
configFile = settingsFormat.generate "config.yaml" instance.settings;
in
nameValuePair "gitea-runner-${escapeSystemdPath name}" {
inherit (instance) enable;
description = "Gitea Actions Runner";
wants = [ "network-online.target" ];
after = [
"network-online.target"
] ++ optionals (wantsDocker) [
"docker.service"
] ++ optionals (wantsPodman) [
"podman.service"
];
wantedBy = [
"multi-user.target"
];
environment = optionalAttrs (instance.token != null) {
TOKEN = "${instance.token}";
} // optionalAttrs (wantsPodman) {
DOCKER_HOST = "unix:///run/podman/podman.sock";
} // {
HOME = "/var/lib/gitea-runner/${name}";
};
path = with pkgs; [
coreutils
] ++ lib.optionals wantsHost instance.hostPackages;
serviceConfig = {
DynamicUser = true;
User = "gitea-runner";
StateDirectory = "gitea-runner";
WorkingDirectory = "-/var/lib/gitea-runner/${name}";
# gitea-runner might fail when gitea is restarted during upgrade.
Restart = "on-failure";
RestartSec = 2;
ExecStartPre = [(pkgs.writeShellScript "gitea-register-runner-${name}" ''
export INSTANCE_DIR="$STATE_DIRECTORY/${name}"
export TOKEN=$(cat /run/secrets/forgejo_runner_token)
mkdir -vp "$INSTANCE_DIR"
cd "$INSTANCE_DIR"
# force reregistration on changed labels
export LABELS_FILE="$INSTANCE_DIR/.labels"
export LABELS_WANTED="$(echo ${escapeShellArg (concatStringsSep "\n" instance.labels)} | sort)"
export LABELS_CURRENT="$(cat $LABELS_FILE 2>/dev/null || echo 0)"
if [ ! -e "$INSTANCE_DIR/.runner" ] || [ "$LABELS_WANTED" != "$LABELS_CURRENT" ]; then
# remove existing registration file, so that changing the labels forces a re-registration
rm -v "$INSTANCE_DIR/.runner" || true
# perform the registration
${cfg.package}/bin/act_runner register --no-interactive \
--instance ${escapeShellArg instance.url} \
--token "$TOKEN" \
--name ${escapeShellArg instance.name} \
--labels ${escapeShellArg (concatStringsSep "," instance.labels)} \
--config ${configFile}
# and write back the configured labels
echo "$LABELS_WANTED" > "$LABELS_FILE"
fi
'')];
ExecStart = "${cfg.package}/bin/act_runner daemon --config ${configFile}";
SupplementaryGroups = optionals (wantsDocker) [
"docker"
] ++ optionals (wantsPodman) [
"podman"
];
} // optionalAttrs (instance.tokenFile != null) {
EnvironmentFile = instance.tokenFile;
};
};
in mapAttrs' mkRunnerService cfg.instances;
};
}

View file

@ -5,6 +5,7 @@ public_keys:
nextcloud_password: ENC[AES256_GCM,data:lwqQio1I1xTv07bLRyrvig1HRyCxcueSPgDpPRhXBqCi8d42OJt7rA==,iv:R0JxpCJz9zycph9p7Ewwt4QTEXQxaxJ691aWCXfEsFE=,tag:Qz3dD2cOkmneEWP7tI54Dg==,type:str] nextcloud_password: ENC[AES256_GCM,data:lwqQio1I1xTv07bLRyrvig1HRyCxcueSPgDpPRhXBqCi8d42OJt7rA==,iv:R0JxpCJz9zycph9p7Ewwt4QTEXQxaxJ691aWCXfEsFE=,tag:Qz3dD2cOkmneEWP7tI54Dg==,type:str]
nextcloud_user_password: ENC[AES256_GCM,data:fkX/1pOgRLvhHTtoK9i5F0kO+mRKj40BH2s7VD7ifPEnyJhWqy5mvg==,iv:iEnW4Z8vCY9oapOpVZNuLMa50SXT01clYaScUN+q/k8=,tag:0G0Y8XCSj+dBAy6Cw8YOHg==,type:str] nextcloud_user_password: ENC[AES256_GCM,data:fkX/1pOgRLvhHTtoK9i5F0kO+mRKj40BH2s7VD7ifPEnyJhWqy5mvg==,iv:iEnW4Z8vCY9oapOpVZNuLMa50SXT01clYaScUN+q/k8=,tag:0G0Y8XCSj+dBAy6Cw8YOHg==,type:str]
paperless_password: ENC[AES256_GCM,data:OCrc00vUb+lgel8TmFm+9Ee4QJZZV7W6+Jl9+R7AfjfDh6v590ibvw==,iv:emM7g0JRcEH4xuYdvZN64drOhduXyQy6HwF1xByaLvE=,tag:D2O1qAeKtYWGf+Zd3RuBTQ==,type:str] paperless_password: ENC[AES256_GCM,data:OCrc00vUb+lgel8TmFm+9Ee4QJZZV7W6+Jl9+R7AfjfDh6v590ibvw==,iv:emM7g0JRcEH4xuYdvZN64drOhduXyQy6HwF1xByaLvE=,tag:D2O1qAeKtYWGf+Zd3RuBTQ==,type:str]
forgejo_runner_token: ENC[AES256_GCM,data:9JgYl6xQX6Cn5hLTDBw5R87k9+DRwPkpiQn8zQGlz/Zji+KIFxBGkw==,iv:TGohedGU5lLxuMk7MYxrfwiwQl0p6Ifj84d17j8DO2Q=,tag:dsrVA6+9raCcGTn9ty16hw==,type:str]
#ENC[AES256_GCM,data:UmGDAz/qalmP6Z2r4VSH802m9ddAoCQ8IaAtAmyQV+Psg0rNpLF7du5ykDepTyHAb6YAG1k2k9ziqfV8P9SUNMvLC7D3TmFk9oZtW8HLrN84tcbp9i4HDFfQ+Q==,iv:PzHlSFj0H4/eSab9j3y9lYAFUPMEb+G74M2/2cmv70A=,tag:GFstk6NgtJCNm207zO1fjQ==,type:comment] #ENC[AES256_GCM,data:UmGDAz/qalmP6Z2r4VSH802m9ddAoCQ8IaAtAmyQV+Psg0rNpLF7du5ykDepTyHAb6YAG1k2k9ziqfV8P9SUNMvLC7D3TmFk9oZtW8HLrN84tcbp9i4HDFfQ+Q==,iv:PzHlSFj0H4/eSab9j3y9lYAFUPMEb+G74M2/2cmv70A=,tag:GFstk6NgtJCNm207zO1fjQ==,type:comment]
sops: sops:
kms: [] kms: []
@ -57,8 +58,8 @@ sops:
a2ZHZmQ0dEVMZFlJRENmU2lGejFuMzAKOO3kTP/VWRYn5CrwPyjUIGS7kjxPvNYZ a2ZHZmQ0dEVMZFlJRENmU2lGejFuMzAKOO3kTP/VWRYn5CrwPyjUIGS7kjxPvNYZ
HMt+cCG9FYeJdqPpHWiM0TeHYUG0h7XlltIMg7KhE4Qj/GARegmuZQ== HMt+cCG9FYeJdqPpHWiM0TeHYUG0h7XlltIMg7KhE4Qj/GARegmuZQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2024-07-06T14:20:40Z" lastmodified: "2024-07-11T11:34:32Z"
mac: ENC[AES256_GCM,data:tiYyfsKlYF4j5YqIezO34L8nkGmHTWQeR7y6e3M2PFFujCqw87Q/WdAdKiyErvPmPwMbkyfXQZgIs2fAKx/C6t5lh5TFFQYZyvCV9A17y4vn8f5SK1HFDePQTfaCqQ4IlSXAXZYpBMMFJn+WBVJQUCb3xM5meuVYTTZpqE8dmso=,iv:NwLsBzVa/Kf9YS6lfS+4VpWkYxpqxPEbRHquuNJ0klY=,tag:LgsV5KBk0Dwij4jEbB99xA==,type:str] mac: ENC[AES256_GCM,data:R5jjjx7iG4wpbn+zUVUBNzUmSS8BESat33ypEWyIi3jQeu7qCJ+OOM+0Soa4AiK3AwS7k1JPfWN8qvcCvDvxeOcHRciqKvORjulfFCceq4RIpEtkcPQU9PQGpMoDg5fYpS8WK8l3qRRPrUYZvKSo1/9O+r0emxF3CYSaR5wOSOs=,iv:673UNciuctMnkEUfrOnGuX2nSQQP/OO1x8QGKaC3noc=,tag:lBnMJwZk4oO8ArAxXXf9Zg==,type:str]
pgp: [] pgp: []
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.8.1 version: 3.8.1