reconfig - no mkfunction

This commit is contained in:
Joseph Hanson 2025-02-10 11:20:38 -06:00
parent 934af3c9b8
commit 5161eba75c
Signed by: jahanson
SSH key fingerprint: SHA256:vy6dKBECV522aPAwklFM3ReKAVB086rT3oWwiuiFG7o

View file

@ -54,147 +54,10 @@ let
# Function to create instance-specific configuration # Function to create instance-specific configuration
mkRadarrInstance = name: instanceCfg: { mkRadarrInstance = name: instanceCfg: {
assertions = [
{
assertion = !(instanceCfg.db.host != "" && instanceCfg.db.hostFile != "");
message = "Specify either a direct database host via db.host or a file via db.hostFile (leave direct host empty).";
}
{
assertion = !(instanceCfg.db.user != "radarr" && instanceCfg.db.userFile != "");
message = "Specify either a direct database user via db.user or a file via db.userFile.";
}
{
assertion = !(instanceCfg.apiKey != "" && instanceCfg.apiKeyFile != "");
message = "Specify either a direct API key via apiKey or a file via apiKeyFile (leave direct API key empty).";
}
];
systemd.tmpfiles.rules = [
"d ${instanceCfg.dataDir} 0775 ${instanceCfg.user} ${instanceCfg.group}"
];
systemd.services."radarr-${name}" = { systemd.services."radarr-${name}" = {
description = "Radarr (${name})"; description = "Radarr (${name})";
after = [
"network.target"
"nss-lookup.target"
];
wantedBy = [ "multi-user.target" ];
environment = lib.mkMerge [
{
RADARR__APP__INSTANCENAME = name;
RADARR__APP__THEME = "dark";
RADARR__AUTH__METHOD = "External";
RADARR__AUTH__REQUIRED = "DisabledForLocalAddresses";
RADARR__LOG__DBENABLED = "False";
RADARR__LOG__LEVEL = "info";
RADARR__SERVER__PORT = toString instanceCfg.port;
RADARR__UPDATE__BRANCH = "develop";
}
(lib.mkIf instanceCfg.db.enable {
RADARR__POSTGRES__PORT = toString instanceCfg.db.port;
RADARR__POSTGRES__MAINDB = instanceCfg.db.dbname;
})
instanceCfg.extraEnvVars
];
serviceConfig = lib.mkMerge [
{
Name = "radarr-${name}";
Type = "simple";
User = instanceCfg.user;
Group = instanceCfg.group;
ExecStart = utils.escapeSystemdExecArgs [
(lib.getExe instanceCfg.package)
"-nobrowser"
"-data=${instanceCfg.dataDir}"
"-port=${toString instanceCfg.port}"
];
WorkingDirectory = instanceCfg.dataDir;
RuntimeDirectory = "radarr-${name}";
LogsDirectory = "radarr-${name}";
RuntimeDirectoryMode = "0750";
Restart = "on-failure";
RestartSec = 5;
}
(lib.mkIf instanceCfg.hardening {
CapabilityBoundingSet = [ "" ];
DeviceAllow = [ "" ];
DevicePolicy = "closed";
LockPersonality = true;
MemoryDenyWriteExecute = false;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateTmp = true;
ProtectControlGroups = true;
ProtectHome = "read-only";
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectSystem = "strict";
ReadWritePaths = [
instanceCfg.dataDir
instanceCfg.moviesDir
"/var/log/radarr-${name}"
"/eru/media"
];
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_NETLINK"
];
RestrictNamespaces = [
"uts"
"ipc"
"pid"
"user"
"cgroup"
"net"
];
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
];
})
(lib.mkIf instanceCfg.db.enable {
ExecStartPre = "+${pkgs.writeShellScript "radarr-${name}-pre-script" ''
mkdir -p /run/radarr-${name}
rm -f /run/radarr-${name}/secrets.env
# Helper function to safely write variables
write_var() {
local var_name="$1"
local value="$2"
if [ -n "$value" ]; then
printf "%s=%s\n" "$var_name" "$value" >> /run/radarr-${name}/secrets.env
fi
}
# API Key (direct value or file)
if [ -n "${instanceCfg.apiKey}" ]; then
write_var "RADARR__AUTH__APIKEY" "${instanceCfg.apiKey}"
else
write_var "RADARR__AUTH__APIKEY" "$(cat ${instanceCfg.apiKeyFile})"
fi
# Database Configuration
write_var "RADARR__POSTGRES__HOST" "$([ -n "${instanceCfg.db.host}" ] && echo "${instanceCfg.db.host}" || cat "${instanceCfg.db.hostFile}")"
write_var "RADARR__POSTGRES__USER" "$([ -n "${instanceCfg.db.user}" ] && echo "${instanceCfg.db.user}" || cat "${instanceCfg.db.userFile}")"
write_var "RADARR__POSTGRES__PASSWORD" "$(cat ${instanceCfg.db.passwordFile})"
# Final permissions
chmod 600 /run/radarr-${name}/secrets.env
chown ${instanceCfg.user}:${instanceCfg.group} /run/radarr-${name}/secrets.env
''}";
EnvironmentFile = (
[ "-/run/radarr-${name}/secrets.env" ]
++ lib.optional (
instanceCfg.extraEnvVarFile != null && instanceCfg.extraEnvVarFile != ""
) instanceCfg.extraEnvVarFile
);
})
];
}; };
networking.firewall = mkIf instanceCfg.openFirewall { networking.firewall = mkIf instanceCfg.openFirewall {
@ -317,12 +180,200 @@ in
}; };
}; };
config = mkIf cfg.enable (mkMerge [ config = mkIf cfg.enable {
# Create services for each enabled instance # Add assertions for all instances
(mkMerge ( assertions = flatten (
mapAttrsToList ( mapAttrsToList (
name: instanceCfg: mkIf instanceCfg.enable (mkRadarrInstance name instanceCfg) name: instanceCfg:
if instanceCfg.enable then
[
{
assertion = !(instanceCfg.db.host != "" && instanceCfg.db.hostFile != "");
message = "Specify either a direct database host via db.host or a file via db.hostFile (leave direct host empty).";
}
{
assertion = !(instanceCfg.db.user != "radarr" && instanceCfg.db.userFile != "");
message = "Specify either a direct database user via db.user or a file via db.userFile.";
}
{
assertion = !(instanceCfg.apiKey != "" && instanceCfg.apiKeyFile != "");
message = "Specify either a direct API key via apiKey or a file via apiKeyFile (leave direct API key empty).";
}
]
else
[ ]
) cfg.instances ) cfg.instances
)) );
]);
# Create systemd tmpfiles rules for each enabled instance
systemd.tmpfiles.rules = flatten (
mapAttrsToList (
name: instanceCfg:
if instanceCfg.enable then
[
"d ${instanceCfg.dataDir} 0775 ${instanceCfg.user} ${instanceCfg.group}"
]
else
[ ]
) cfg.instances
);
# Create services for each enabled instance
systemd.services = mapAttrs' (
name: instanceCfg:
nameValuePair "radarr-${name}" (
mkIf instanceCfg.enable {
description = "Radarr (${name})";
after = [
"network.target"
"nss-lookup.target"
];
wantedBy = [ "multi-user.target" ];
environment = lib.mkMerge [
{
RADARR__APP__INSTANCENAME = name;
RADARR__APP__THEME = "dark";
RADARR__AUTH__METHOD = "External";
RADARR__AUTH__REQUIRED = "DisabledForLocalAddresses";
RADARR__LOG__DBENABLED = "False";
RADARR__LOG__LEVEL = "info";
RADARR__SERVER__PORT = toString instanceCfg.port;
RADARR__UPDATE__BRANCH = "develop";
}
(lib.mkIf instanceCfg.db.enable {
RADARR__POSTGRES__PORT = toString instanceCfg.db.port;
RADARR__POSTGRES__MAINDB = instanceCfg.db.dbname;
})
instanceCfg.extraEnvVars
];
serviceConfig = lib.mkMerge [
{
Type = "simple";
User = instanceCfg.user;
Group = instanceCfg.group;
ExecStart = utils.escapeSystemdExecArgs [
(lib.getExe instanceCfg.package)
"-nobrowser"
"-data=${instanceCfg.dataDir}"
"-port=${toString instanceCfg.port}"
];
WorkingDirectory = instanceCfg.dataDir;
RuntimeDirectory = "radarr-${name}";
LogsDirectory = "radarr-${name}";
RuntimeDirectoryMode = "0750";
Restart = "on-failure";
RestartSec = 5;
}
(lib.mkIf instanceCfg.hardening {
CapabilityBoundingSet = [ "" ];
DeviceAllow = [ "" ];
DevicePolicy = "closed";
LockPersonality = true;
MemoryDenyWriteExecute = false;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateTmp = true;
ProtectControlGroups = true;
ProtectHome = "read-only";
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectSystem = "strict";
ReadWritePaths = [
instanceCfg.dataDir
instanceCfg.moviesDir
"/var/log/radarr-${name}"
"/eru/media"
];
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_NETLINK"
];
RestrictNamespaces = [
"uts"
"ipc"
"pid"
"user"
"cgroup"
"net"
];
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
];
})
(lib.mkIf instanceCfg.db.enable {
ExecStartPre = "+${pkgs.writeShellScript "radarr-${name}-pre-script" ''
mkdir -p /run/radarr-${name}
rm -f /run/radarr-${name}/secrets.env
# Helper function to safely write variables
write_var() {
local var_name="$1"
local value="$2"
if [ -n "$value" ]; then
printf "%s=%s\n" "$var_name" "$value" >> /run/radarr-${name}/secrets.env
fi
}
# API Key (direct value or file)
if [ -n "${instanceCfg.apiKey}" ]; then
write_var "RADARR__AUTH__APIKEY" "${instanceCfg.apiKey}"
else
write_var "RADARR__AUTH__APIKEY" "$(cat ${instanceCfg.apiKeyFile})"
fi
# Database Configuration
write_var "RADARR__POSTGRES__HOST" "$([ -n "${instanceCfg.db.host}" ] && echo "${instanceCfg.db.host}" || cat "${instanceCfg.db.hostFile}")"
write_var "RADARR__POSTGRES__USER" "$([ -n "${instanceCfg.db.user}" ] && echo "${instanceCfg.db.user}" || cat "${instanceCfg.db.userFile}")"
write_var "RADARR__POSTGRES__PASSWORD" "$(cat ${instanceCfg.db.passwordFile})"
# Final permissions
chmod 600 /run/radarr-${name}/secrets.env
chown ${instanceCfg.user}:${instanceCfg.group} /run/radarr-${name}/secrets.env
''}";
EnvironmentFile = (
[ "-/run/radarr-${name}/secrets.env" ]
++ lib.optional (
instanceCfg.extraEnvVarFile != null && instanceCfg.extraEnvVarFile != ""
) instanceCfg.extraEnvVarFile
);
})
];
}
)
) cfg.instances;
# Firewall configurations
networking.firewall = mkMerge (
mapAttrsToList (
name: instanceCfg:
mkIf (instanceCfg.enable && instanceCfg.openFirewall) {
allowedTCPPorts = [ instanceCfg.port ];
}
) cfg.instances
);
# Users and groups
users = mkMerge (
mapAttrsToList (
name: instanceCfg:
mkIf instanceCfg.enable {
groups.${instanceCfg.group} = { };
users = mkIf (instanceCfg.user == "radarr") {
radarr = {
inherit (instanceCfg) group;
isSystemUser = true;
# home = instanceCfg.dataDir;
home = "/nahar/radarr";
};
};
}
) cfg.instances
);
};
} }