sneeuwvlok/modules/nixos/services/media/default.nix
Chris Kruining 2d3da197ee
Some checks failed
Test action / kaas (push) Failing after 1s
lets actually commit for once...
2025-11-20 00:05:34 +01:00

307 lines
7.9 KiB
Nix

{ pkgs, lib, namespace, config, inputs, system, ... }:
let
inherit (lib) mkIf mkEnableOption mkOption;
inherit (lib.types) str;
cfg = config.${namespace}.services.media;
arr = ["radarr" ];
in
{
options.${namespace}.services.media = {
enable = mkEnableOption "Enable media services";
user = mkOption {
type = str;
default = "media";
};
group = mkOption {
type = str;
default = "media";
};
path = mkOption {
type = str;
default = "/var/media";
};
};
config = mkIf cfg.enable {
#=========================================================================
# Dependencies
#=========================================================================
environment.systemPackages = with pkgs; [
podman-tui
jellyfin
jellyfin-web
jellyfin-ffmpeg
jellyseerr
mediainfo
id3v2
yt-dlp
];
#=========================================================================
# Prepare system
#=========================================================================
users = {
users.${cfg.user} = {
isSystemUser = true;
group = cfg.group;
};
groups.${cfg.group} = {};
};
systemd.tmpfiles.rules = [
"d '${cfg.path}/series' 0700 ${cfg.user} ${cfg.group} - -"
"d '${cfg.path}/movies' 0700 ${cfg.user} ${cfg.group} - -"
"d '${cfg.path}/music' 0700 ${cfg.user} ${cfg.group} - -"
"d '${cfg.path}/qbittorrent' 0700 ${cfg.user} ${cfg.group} - -"
"d '${cfg.path}/sabnzbd' 0700 ${cfg.user} ${cfg.group} - -"
"d '${cfg.path}/reiverr/config' 0700 ${cfg.user} ${cfg.group} - -"
"d '${cfg.path}/downloads/incomplete' 0700 ${cfg.user} ${cfg.group} - -"
"d '${cfg.path}/downloads/done' 0700 ${cfg.user} ${cfg.group} - -"
"d /var/lib/radarrApplyTerraform 0755 ${cfg.user} ${cfg.group} -"
];
#=========================================================================
# Services
#=========================================================================
services = let
arr-services =
arr
|> lib.imap (i: service: {
name = service;
value = {
enable = true;
openFirewall = true;
environmentFiles = [
config.sops.templates."${service}/config.env".path
];
settings = {
auth.authenticationMethod = "External";
server = {
bindaddress = "0.0.0.0";
port = 2000 + i;
};
postgres = {
host = "localhost";
port = "5432";
user = service;
maindb = service;
logdb = service;
};
};
}
// (if service != "prowlarr" then { user = cfg.user; group = cfg.group; } else {});
})
|> lib.listToAttrs
;
in
arr-services // {
bazarr = {
enable = true;
openFirewall = true;
user = cfg.user;
group = cfg.group;
listenPort = 2005;
};
# port is harcoded in nixpkgs module
jellyfin = {
enable = true;
openFirewall = true;
user = cfg.user;
group = cfg.group;
};
flaresolverr = {
enable = true;
openFirewall = true;
port = 2007;
};
qbittorrent = {
enable = true;
openFirewall = true;
webuiPort = 2008;
serverConfig = {
LegalNotice.Accepted = true;
};
user = cfg.user;
group = cfg.group;
};
# port is harcoded in nixpkgs module
sabnzbd = {
enable = true;
openFirewall = true;
configFile = "${cfg.path}/sabnzbd/config.ini";
user = cfg.user;
group = cfg.group;
};
postgresql =
let
databases = arr |> lib.concatMap (s: [ s "${s}-log" ]);
in
{
enable = true;
ensureDatabases = arr;
ensureUsers = arr |> lib.map (service: {
name = service;
ensureDBOwnership = true;
});
};
caddy = {
enable = true;
virtualHosts = {
"jellyfin.kruining.eu".extraConfig = ''
reverse_proxy http://[::1]:8096
'';
};
};
};
systemd.services.radarrApplyTerraform =
let
# this is a nix package, the generated json file to be exact
terraformConfiguration = inputs.terranix.lib.terranixConfiguration {
inherit system;
modules = [
({ config, lib, ... }: {
config = {
variable = {
api_key = {
type = "string";
description = "Radarr api key";
};
};
terraform.required_providers.radarr = {
source = "devopsarr/radarr";
version = "2.2.0";
};
provider.radarr = {
url = "http://127.0.0.1:2001";
api_key = lib.tfRef "var.api_key";
};
resource = {
radarr_root_folder.local = {
path = "/var/media/movies";
};
};
};
})
];
};
in
{
description = "Radarr terraform apply";
wantedBy = [ "multi-user.target" ];
wants = [ "radarr.service" ];
script = ''
#!/usr/bin/env bash
if [ "$(systemctl is-active radarr)" != "active" ]; then
echo "Radarr is not running"
exit 1
fi
# Sleep for a bit to give radarr the chance to start up
sleep 5s
# Print the path to the source for easier debugging
echo "config location: ${terraformConfiguration}"
# Copy infra code into workspace
cp -f ${terraformConfiguration} config.tf.json
# Initialize OpenTofu
${lib.getExe pkgs.opentofu} init
# Run the infrastructure code
# ${lib.getExe pkgs.opentofu} plan -var-file='${config.sops.templates."radarr/config.tfvars".path}'
${lib.getExe pkgs.opentofu} apply -auto-approve -var-file='${config.sops.templates."radarr/config.tfvars".path}'
'';
serviceConfig = {
Type = "oneshot";
User = cfg.user;
Group = cfg.group;
WorkingDirectory = "/var/lib/radarrApplyTerraform";
EnvironmentFile = [
config.sops.templates."radarr/config.env".path
];
};
};
systemd.services.jellyfin.serviceConfig.killSignal = lib.mkForce "SIGKILL";
sops = {
secrets =
arr
|> lib.map (service: {
name = "${service}/apikey";
value = {
owner = cfg.user;
group = cfg.group;
restartUnits = [ "${service}.service" ];
};
})
|> lib.listToAttrs
;
templates =
let
apikeys =
arr
|> lib.map (service: {
name = "${service}/config.env";
value = {
owner = cfg.user;
group = cfg.group;
restartUnits = [ "${service}.service" ];
content = ''
${lib.toUpper service}__AUTH__APIKEY="${config.sops.placeholder."${service}/apikey"}"
'';
};
})
|> lib.listToAttrs;
tfvars =
arr
|> lib.map(service: {
name = "${service}/config.tfvars";
value = {
owner = cfg.user;
group = cfg.group;
restartUnits = [ "${service}ApplyTerraform.service" ];
content = ''
api_key = "${config.sops.placeholder."${service}/apikey"}"
'';
};
})
|> lib.listToAttrs;
in
apikeys // tfvars
;
};
};
}