nixos/services.radicle: remove with lib;

This commit is contained in:
Felix Buehler 2024-08-30 00:46:43 +02:00
parent 1f34eeb672
commit 11dd437b65

View File

@ -1,5 +1,4 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.radicle;
@ -14,18 +13,18 @@ let
# Convenient wrapper to run `rad` in the namespaces of `radicle-node.service`
rad-system = pkgs.writeShellScriptBin "rad-system" ''
set -o allexport
${toShellVars env}
${lib.toShellVars env}
# Note that --env is not used to preserve host's envvars like $TERM
exec ${getExe' pkgs.util-linux "nsenter"} -a \
-t "$(${getExe' config.systemd.package "systemctl"} show -P MainPID radicle-node.service)" \
-S "$(${getExe' config.systemd.package "systemctl"} show -P UID radicle-node.service)" \
-G "$(${getExe' config.systemd.package "systemctl"} show -P GID radicle-node.service)" \
${getExe' cfg.package "rad"} "$@"
exec ${lib.getExe' pkgs.util-linux "nsenter"} -a \
-t "$(${lib.getExe' config.systemd.package "systemctl"} show -P MainPID radicle-node.service)" \
-S "$(${lib.getExe' config.systemd.package "systemctl"} show -P UID radicle-node.service)" \
-G "$(${lib.getExe' config.systemd.package "systemctl"} show -P GID radicle-node.service)" \
${lib.getExe' cfg.package "rad"} "$@"
'';
commonServiceConfig = serviceName: {
environment = env // {
RUST_LOG = mkDefault "info";
RUST_LOG = lib.mkDefault "info";
};
path = [
pkgs.gitMinimal
@ -41,11 +40,11 @@ let
"network-online.target"
];
wantedBy = [ "multi-user.target" ];
serviceConfig = mkMerge [
serviceConfig = lib.mkMerge [
{
BindReadOnlyPaths = [
"${cfg.configFile}:${env.RAD_HOME}/config.json"
"${if types.path.check cfg.publicKey then cfg.publicKey else pkgs.writeText "radicle.pub" cfg.publicKey}:${env.RAD_HOME}/keys/radicle.pub"
"${if lib.types.path.check cfg.publicKey then cfg.publicKey else pkgs.writeText "radicle.pub" cfg.publicKey}:${env.RAD_HOME}/keys/radicle.pub"
];
KillMode = "process";
StateDirectory = [ "radicle" ];
@ -107,7 +106,7 @@ let
pkgs.gitMinimal
cfg.package
pkgs.iana-etc
(getLib pkgs.nss)
(lib.getLib pkgs.nss)
pkgs.tzdata
];
};
@ -116,11 +115,11 @@ in
{
options = {
services.radicle = {
enable = mkEnableOption "Radicle Seed Node";
package = mkPackageOption pkgs "radicle-node" { };
privateKeyFile = mkOption {
enable = lib.mkEnableOption "Radicle Seed Node";
package = lib.mkPackageOption pkgs "radicle-node" { };
privateKeyFile = lib.mkOption {
# Note that a key encrypted by systemd-creds is not a path but a str.
type = with types; either path str;
type = with lib.types; either path str;
description = ''
Absolute file path to an SSH private key,
usually generated by `rad auth`.
@ -130,44 +129,44 @@ in
and the string after as a path encrypted with `systemd-creds`.
'';
};
publicKey = mkOption {
type = with types; either path str;
publicKey = lib.mkOption {
type = with lib.types; either path str;
description = ''
An SSH public key (as an absolute file path or directly as a string),
usually generated by `rad auth`.
'';
};
node = {
listenAddress = mkOption {
type = types.str;
listenAddress = lib.mkOption {
type = lib.types.str;
default = "[::]";
example = "127.0.0.1";
description = "The IP address on which `radicle-node` listens.";
};
listenPort = mkOption {
type = types.port;
listenPort = lib.mkOption {
type = lib.types.port;
default = 8776;
description = "The port on which `radicle-node` listens.";
};
openFirewall = mkEnableOption "opening the firewall for `radicle-node`";
extraArgs = mkOption {
type = with types; listOf str;
openFirewall = lib.mkEnableOption "opening the firewall for `radicle-node`";
extraArgs = lib.mkOption {
type = with lib.types; listOf str;
default = [ ];
description = "Extra arguments for `radicle-node`";
};
};
configFile = mkOption {
type = types.package;
configFile = lib.mkOption {
type = lib.types.package;
internal = true;
default = (json.generate "config.json" cfg.settings).overrideAttrs (previousAttrs: {
preferLocalBuild = true;
# None of the usual phases are run here because runCommandWith uses buildCommand,
# so just append to buildCommand what would usually be a checkPhase.
buildCommand = previousAttrs.buildCommand + optionalString cfg.checkConfig ''
buildCommand = previousAttrs.buildCommand + lib.optionalString cfg.checkConfig ''
ln -s $out config.json
install -D -m 644 /dev/stdin keys/radicle.pub <<<"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBgFMhajUng+Rjj/sCFXI9PzG8BQjru2n7JgUVF1Kbv5 snakeoil"
export RAD_HOME=$PWD
${getExe' pkgs.buildPackages.radicle-node "rad"} config >/dev/null || {
${lib.getExe' pkgs.buildPackages.radicle-node "rad"} config >/dev/null || {
cat -n config.json
echo "Invalid config.json according to rad."
echo "Please double-check your services.radicle.settings (producing the config.json above),"
@ -177,13 +176,13 @@ in
'';
});
};
checkConfig = mkEnableOption "checking the {file}`config.json` file resulting from {option}`services.radicle.settings`" // { default = true; };
settings = mkOption {
checkConfig = lib.mkEnableOption "checking the {file}`config.json` file resulting from {option}`services.radicle.settings`" // { default = true; };
settings = lib.mkOption {
description = ''
See https://app.radicle.xyz/nodes/seed.radicle.garden/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5/tree/radicle/src/node/config.rs#L275
'';
default = { };
example = literalExpression ''
example = lib.literalExpression ''
{
web.pinned.repositories = [
"rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5" # heartwood
@ -191,27 +190,27 @@ in
];
}
'';
type = types.submodule {
type = lib.types.submodule {
freeformType = json.type;
};
};
httpd = {
enable = mkEnableOption "Radicle HTTP gateway to radicle-node";
package = mkPackageOption pkgs "radicle-httpd" { };
listenAddress = mkOption {
type = types.str;
enable = lib.mkEnableOption "Radicle HTTP gateway to radicle-node";
package = lib.mkPackageOption pkgs "radicle-httpd" { };
listenAddress = lib.mkOption {
type = lib.types.str;
default = "127.0.0.1";
description = "The IP address on which `radicle-httpd` listens.";
};
listenPort = mkOption {
type = types.port;
listenPort = lib.mkOption {
type = lib.types.port;
default = 8080;
description = "The port on which `radicle-httpd` listens.";
};
nginx = mkOption {
nginx = lib.mkOption {
# Type of a single virtual host, or null.
type = types.nullOr (types.submodule (
recursiveUpdate (import ../web-servers/nginx/vhost-options.nix { inherit config lib; }) {
type = lib.types.nullOr (lib.types.submodule (
lib.recursiveUpdate (import ../web-servers/nginx/vhost-options.nix { inherit config lib; }) {
options.serverName = {
default = "radicle-${config.networking.hostName}.${config.networking.domain}";
defaultText = "radicle-\${config.networking.hostName}.\${config.networking.domain}";
@ -219,7 +218,7 @@ in
}
));
default = null;
example = literalExpression ''
example = lib.literalExpression ''
{
serverAliases = [
"seed.''${config.networking.domain}"
@ -237,8 +236,8 @@ in
If this is set to null (the default), no nginx virtual host will be configured.
'';
};
extraArgs = mkOption {
type = with types; listOf str;
extraArgs = lib.mkOption {
type = with lib.types; listOf str;
default = [ ];
description = "Extra arguments for `radicle-httpd`";
};
@ -246,19 +245,19 @@ in
};
};
config = mkIf cfg.enable (mkMerge [
config = lib.mkIf cfg.enable (lib.mkMerge [
{
systemd.services.radicle-node = mkMerge [
systemd.services.radicle-node = lib.mkMerge [
(commonServiceConfig "radicle-node")
{
description = "Radicle Node";
documentation = [ "man:radicle-node(1)" ];
serviceConfig = {
ExecStart = "${getExe' cfg.package "radicle-node"} --force --listen ${cfg.node.listenAddress}:${toString cfg.node.listenPort} ${escapeShellArgs cfg.node.extraArgs}";
Restart = mkDefault "on-failure";
ExecStart = "${lib.getExe' cfg.package "radicle-node"} --force --listen ${cfg.node.listenAddress}:${toString cfg.node.listenPort} ${lib.escapeShellArgs cfg.node.extraArgs}";
Restart = lib.mkDefault "on-failure";
RestartSec = "30";
SocketBindAllow = [ "tcp:${toString cfg.node.listenPort}" ];
SystemCallFilter = mkAfter [
SystemCallFilter = lib.mkAfter [
# Needed by git upload-pack which calls alarm() and setitimer() when providing a rad clone
"@timer"
];
@ -271,11 +270,11 @@ in
{
serviceConfig =
let keyCred = builtins.split ":" "${cfg.privateKeyFile}"; in
if length keyCred > 1
if lib.length keyCred > 1
then {
LoadCredentialEncrypted = [ cfg.privateKeyFile ];
# Note that neither %d nor ${CREDENTIALS_DIRECTORY} works in BindReadOnlyPaths=
BindReadOnlyPaths = [ "/run/credentials/radicle-node.service/${head keyCred}:${env.RAD_HOME}/keys/radicle" ];
BindReadOnlyPaths = [ "/run/credentials/radicle-node.service/${lib.head keyCred}:${env.RAD_HOME}/keys/radicle" ];
}
else {
LoadCredential = [ "radicle:${cfg.privateKeyFile}" ];
@ -288,7 +287,7 @@ in
rad-system
];
networking.firewall = mkIf cfg.node.openFirewall {
networking.firewall = lib.mkIf cfg.node.openFirewall {
allowedTCPPorts = [ cfg.node.listenPort ];
};
@ -304,19 +303,19 @@ in
};
}
(mkIf cfg.httpd.enable (mkMerge [
(lib.mkIf cfg.httpd.enable (lib.mkMerge [
{
systemd.services.radicle-httpd = mkMerge [
systemd.services.radicle-httpd = lib.mkMerge [
(commonServiceConfig "radicle-httpd")
{
description = "Radicle HTTP gateway to radicle-node";
documentation = [ "man:radicle-httpd(1)" ];
serviceConfig = {
ExecStart = "${getExe' cfg.httpd.package "radicle-httpd"} --listen ${cfg.httpd.listenAddress}:${toString cfg.httpd.listenPort} ${escapeShellArgs cfg.httpd.extraArgs}";
Restart = mkDefault "on-failure";
ExecStart = "${lib.getExe' cfg.httpd.package "radicle-httpd"} --listen ${cfg.httpd.listenAddress}:${toString cfg.httpd.listenPort} ${lib.escapeShellArgs cfg.httpd.extraArgs}";
Restart = lib.mkDefault "on-failure";
RestartSec = "10";
SocketBindAllow = [ "tcp:${toString cfg.httpd.listenPort}" ];
SystemCallFilter = mkAfter [
SystemCallFilter = lib.mkAfter [
# Needed by git upload-pack which calls alarm() and setitimer() when providing a git clone
"@timer"
];
@ -328,12 +327,12 @@ in
];
}
(mkIf (cfg.httpd.nginx != null) {
(lib.mkIf (cfg.httpd.nginx != null) {
services.nginx.virtualHosts.${cfg.httpd.nginx.serverName} = lib.mkMerge [
cfg.httpd.nginx
{
forceSSL = mkDefault true;
enableACME = mkDefault true;
forceSSL = lib.mkDefault true;
enableACME = lib.mkDefault true;
locations."/" = {
proxyPass = "http://${cfg.httpd.listenAddress}:${toString cfg.httpd.listenPort}";
recommendedProxySettings = true;
@ -342,8 +341,8 @@ in
];
services.radicle.settings = {
node.alias = mkDefault cfg.httpd.nginx.serverName;
node.externalAddresses = mkDefault [
node.alias = lib.mkDefault cfg.httpd.nginx.serverName;
node.externalAddresses = lib.mkDefault [
"${cfg.httpd.nginx.serverName}:${toString cfg.node.listenPort}"
];
};