Compare commits

...

3 commits

Author SHA1 Message Date
Chris Kruining
ab9c4b4c14
.
Some checks failed
Test action / kaas (push) Failing after 0s
2025-12-31 00:41:52 +01:00
d2ee47f78c chore(secrets): set secret "whisparr/apikey" for machine "ulmo" 2025-12-28 21:28:31 +00:00
cfd5a40d3c chore(secrets): set secret "qbittorrent/password" for machine "ulmo" 2025-12-28 20:38:16 +00:00
11 changed files with 247 additions and 105 deletions

View file

@ -8,4 +8,4 @@
[no-exit-message]
@update machine:
just assert '-d "../systems/x86_64-linux/{{ machine }}"' "Machine {{ machine }} does not exist, must be one of: $(ls ../systems/x86_64-linux/ | sed ':a;N;$!ba;s/\n/, /g')"
nixos-rebuild switch -L --sudo --target-host {{ machine }} --flake ..#{{ machine }}
nixos-rebuild switch -L --sudo --target-host {{ machine }} --flake ..#{{ machine }} --log-format internal-json -v |& nom --json

View file

@ -5,7 +5,7 @@
inputs,
...
}: let
inherit (lib) mkIf mkEnableOption mkForce;
inherit (lib) mkIf mkEnableOption;
cfg = config.${namespace}.desktop.cosmic;
in {
@ -19,13 +19,7 @@ in {
config = mkIf cfg.enable {
services = {
displayManager = {
cosmic-greeter.enable = true;
autoLogin = {
enable = true;
user = "chris";
};
};
displayManager.cosmic-greeter.enable = true;
desktopManager.cosmic.enable = true;
};
};

View file

@ -52,11 +52,15 @@ in {
# Since we'll be using OIDC for auth disable all local options
enable_registration = false;
enable_registration_without_verification = false;
password_config.enabled = false;
password_config.enabled = true;
backchannel_logout_enabled = true;
experimental_features = {
msc2965_enabled = true;
};
sso = {
client_whitelist = ["http://[::1]:9092"];
client_whitelist = ["http://[::1]:9092/" "https://auth.kruining.eu/"];
update_profile_information = true;
};

View file

@ -35,13 +35,6 @@ in {
#=========================================================================
environment.systemPackages = with pkgs; [
podman-tui
jellyfin
jellyfin-web
jellyfin-ffmpeg
jellyseerr
mediainfo
id3v2
yt-dlp
];
#=========================================================================
@ -56,9 +49,6 @@ in {
};
systemd.tmpfiles.rules = [
# "d '${cfg.path}/series' 0770 ${cfg.user} ${cfg.group} - -"
# "d '${cfg.path}/movies' 0770 ${cfg.user} ${cfg.group} - -"
# "d '${cfg.path}/music' 0770 ${cfg.user} ${cfg.group} - -"
"d '${cfg.path}/qbittorrent' 0770 ${cfg.user} ${cfg.group} - -"
"d '${cfg.path}/sabnzbd' 0770 ${cfg.user} ${cfg.group} - -"
"d '${cfg.path}/downloads/incomplete' 0770 ${cfg.user} ${cfg.group} - -"
@ -77,34 +67,9 @@ in {
listenPort = 2005;
};
flaresolverr = {
enable = true;
openFirewall = true;
port = 2007;
};
# port is harcoded in nixpkgs module
jellyfin = {
enable = true;
openFirewall = true;
user = cfg.user;
group = cfg.group;
};
postgresql = {
enable = true;
};
caddy = {
enable = true;
virtualHosts = {
"jellyfin.kruining.eu".extraConfig = ''
reverse_proxy http://[::1]:8096
'';
};
};
};
systemd.services.jellyfin.serviceConfig.killSignal = lib.mkForce "SIGKILL";
};
}

View file

@ -130,16 +130,6 @@ in {
}
];
}
{
type = "videos";
channels = [
"UCXuqSBlHAE6Xw-yeJA0Tunw" # Linus Tech Tips
"UCR-DXc1voovS8nhAvccRZhg" # Jeff Geerling
"UCsBjURrPoezykLs9EqgamOA" # Fireship
"UCBJycsmduvYEL83R_U4JriQ" # Marques Brownlee
"UCHnyfMqiRRG1u-2MsSQLbXA" # Veritasium
];
}
];
}

View file

@ -0,0 +1,50 @@
{
pkgs,
config,
lib,
namespace,
inputs,
system,
...
}: let
inherit (builtins) toString;
inherit (lib) mkIf mkEnableOption mkOption types;
cfg = config.${namespace}.services.media.jellyfin;
in {
options.${namespace}.services.media.jellyfin = {
enable = mkEnableOption "Enable jellyfin server";
};
config = mkIf cfg.enable {
environment.systemPackages = with pkgs; [
jellyfin
jellyfin-web
jellyfin-ffmpeg
mediainfo
id3v2
yt-dlp
];
services = {
# port is harcoded in nixpkgs module
jellyfin = {
enable = true;
openFirewall = true;
user = "media";
group = "media";
};
caddy = {
enable = true;
virtualHosts = {
"jellyfin.kruining.eu".extraConfig = ''
reverse_proxy http://[::1]:8096
'';
};
};
};
systemd.services.jellyfin.serviceConfig.killSignal = lib.mkForce "SIGKILL";
};
}

View file

@ -11,6 +11,7 @@
inherit (lib) mkIf mkEnableOption mkOption types;
cfg = config.${namespace}.services.media.servarr;
servarr = import ./lib.nix {inherit lib;};
anyEnabled = cfg |> lib.attrNames |> lib.length |> (l: l > 0);
in {
options.${namespace}.services.media = {
@ -68,7 +69,7 @@ in {
};
};
}
// (lib.optionalAttrs (service != "prowlarr") {
// (lib.optionalAttrs (lib.elem service ["radarr" "sonarr" "lidarr" "whisparr"]) {
user = service;
group = "media";
});
@ -104,6 +105,12 @@ in {
group = "media";
};
flaresolverr = {
enable = true;
openFirewall = true;
port = 2007;
};
postgresql = {
ensureDatabases = cfg |> lib.attrNames;
ensureUsers =
@ -129,6 +136,7 @@ in {
}: (mkIf enable {
"${service}ApplyTerraform" = let
config' = config;
lib' = lib;
terraformConfiguration = inputs.terranix.lib.terranixConfiguration {
inherit system;
@ -140,13 +148,29 @@ in {
...
}: {
config = {
variable = {
api_key = {
variable =
cfg
|> lib'.mapAttrsToList (s: _: {
"${s}_api_key" = {
type = "string";
description = "${service} api key";
description = "${s} API key";
};
})
|> lib'.concat [
{
qbittorrent_api_key = {
type = "string";
description = "qbittorrent api key";
};
sabnzbd_api_key = {
type = "string";
description = "sabnzbd api key";
};
}
]
|> lib'.mkMerge;
terraform.required_providers.${service} = {
source = "devopsarr/${service}";
version =
@ -164,10 +188,11 @@ in {
provider.${service} = {
url = "http://127.0.0.1:${toString port}";
api_key = lib.tfRef "var.api_key";
api_key = lib.tfRef "var.${service}_api_key";
};
resource = {
resource =
{
"${service}_root_folder" = mkIf (lib.elem service ["radarr" "sonarr" "whisparr"]) (
rootFolders
|> lib.imap (i: f: lib.nameValuePair "local${toString i}" {path = f;})
@ -181,23 +206,98 @@ in {
priority = 1;
host = "localhost";
username = "admin";
password = "poChieN5feeph0igeaCadeJ9Xux0ohmuy6ruH5ieThaPheib3iuzoo0ahw1aiceif1feegioh9Aimau0pai5thoh5ieH0aechohw";
password = lib.tfRef "var.qbittorrent_api_key";
# password = "poChieN5feeph0igeaCadeJ9Xux0ohmuy6ruH5ieThaPheib3iuzoo0ahw1aiceif1feegioh9Aimau0pai5thoh5ieH0aechohw";
url_base = "/";
port = 2008;
};
};
# "${service}_download_client_sabnzbd" = mkIf (lib.elem service ["radarr" "sonarr" "lidarr" "whisparr"]) {
# "main" = {
# name = "SABnzbd";
"${service}_download_client_sabnzbd" = mkIf (lib.elem service ["radarr" "sonarr" "lidarr" "whisparr"]) {
"main" = {
name = "SABnzbd";
enable = true;
priority = 1;
host = "localhost";
api_key = lib.tfRef "var.sabnzbd_api_key";
url_base = "/";
port = 8080;
};
};
}
// (lib.optionalAttrs (service == "prowlarr") (
cfg
|> lib'.filterAttrs (s: _: lib'.elem s ["radarr" "sonarr" "lidarr" "whisparr"])
|> lib'.mapAttrsToList (s: {port, ...}: {
"prowlarr_application_${s}"."main" = let
p = cfg.prowlarr.port or config'.services.prowlarr.settings.server.port or 9696;
in {
name = s;
sync_level = "addOnly";
base_url = "http://localhost:${toString port}";
prowlarr_url = "http://localhost:${toString p}";
api_key = lib.tfRef "var.${s}_api_key";
# sync_categories = [3000 3010 3030];
};
})
|> lib'.concat [
{
"prowlarr_indexer" = {
"nyaa" = {
enable = true;
app_profile_id = 1;
priority = 1;
name = "Nyaa";
implementation = "nyaa";
config_contract = "nyaa_settings";
protocol = "torrent";
fields = [
{
name = "targetType";
value = "";
}
];
};
"nzbgeek" = {
enable = true;
app_profile_id = 2;
priority = 1;
name = "NZBgeek";
implementation = "nzbgeek";
config_contract = "nzbgeek_settings";
protocol = "torrent";
fields = [
];
};
# "nzbgeek" = {
# enable = true;
# priority = 1;
# host = "localhost";
# url_base = "/";
# port = 8080;
# };
# app_profile_id = 1;
# name = "NZBgeek";
# implementation = "nzbgeek";
# config_contract = "nzbgeek_settings";
# protocol = "torrent";
# fields = [
# # {
# # name = "";
# # value = "";
# # }
# ];
# };
};
}
]
|> lib'.mkMerge
));
};
})
];
@ -242,7 +342,7 @@ in {
then "plan"
else "apply -auto-approve"
} \
-var-file='${config.sops.templates."${service}/config.tfvars".path}'
-var-file='${config.sops.templates."servarr/config.tfvars".path}'
'';
serviceConfig = {
@ -295,26 +395,34 @@ in {
${lib.toUpper service}__AUTH__APIKEY="${config.sops.placeholder."${service}/apikey"}"
'';
};
"${service}/config.tfvars" = {
owner = service;
group = "media";
restartUnits = ["${service}.service"];
content = ''
api_key = "${config.sops.placeholder."${service}/apikey"}"
'';
};
};
}))
|> lib.concat [
{
secrets = {
"qbittorrent/password" = {};
"sabnzbd/apikey" = {};
"sabnzbd/sunnyweb/username" = {};
"sabnzbd/sunnyweb/password" = {};
};
templates = {
"servarr/config.tfvars" = {
owner = "media";
group = "media";
mode = "0440";
restartUnits = cfg |> lib.attrNames |> lib.map (s: "${s}.service");
content = ''
${
cfg
|> lib.attrNames
|> lib.map (s: "${s}_api_key = \"${config.sops.placeholder."${s}/apikey"}\"")
|> lib.join "\n"
}
qbittorrent_api_key = "${config.sops.placeholder."qbittorrent/password"}"
sabnzbd_api_key = "${config.sops.placeholder."sabnzbd/apikey"}"
'';
};
"sabnzbd/config.ini" = {
owner = "sabnzbd";
group = "media";

View file

@ -0,0 +1,2 @@
{lib, ...}: {
}

View file

@ -24,6 +24,7 @@
application = {
steam.enable = true;
zen.enable = true;
};
editor = {

View file

@ -38,6 +38,31 @@
'';
};
# virtualisation = {
# containers.enable = true;
# podman = {
# enable = true;
# dockerCompat = true;
# };
# oci-containers = {
# backend = "podman";
# containers = {
# homey = {
# image = "ghcr.io/athombv/homey-shs:latest";
# autoStart = true;
# privileged = true;
# volumes = [
# "/home/chris/.homey-shs:/homey/user"
# ];
# ports = [
# "4859:4859"
# ];
# };
# };
# };
# };
sneeuwvlok = {
services = {
backup.borg.enable = true;
@ -170,6 +195,7 @@
media.glance.enable = true;
media.mydia.enable = true;
media.nfs.enable = true;
media.jellyfin.enable = true;
media.servarr = {
radarr = {
enable = true;
@ -199,7 +225,7 @@
prowlarr = {
enable = true;
debug = true;
# debug = true;
port = 2004;
};
};

View file

@ -34,6 +34,8 @@ sabnzbd:
password: ENC[AES256_GCM,data:flw8AahqO1Mx,iv:Qhu8iVWMzzqy18y8dj3aHoBnSZatm74/tYvZ456l2sA=,tag:sCYBdw7kD0zJZFFr5EyPIQ==,type:str]
username: ENC[AES256_GCM,data:IboJ8WDWuVNgvrk7c3V8I5S6Xg==,iv:BRohMuQFQz2S+HFasIaok6npT3C5v/SlhAhbLQXfB0s=,tag:M3/u0WBQ3AufHqe4DCtsrA==,type:str]
apikey: ENC[AES256_GCM,data:j5sPXKbBhMdNHOuoTfZ+c8nGu5JameOgK2z428iLdP01Hi6MvHVaN8Zs8YxMoSBtOjdtIEC8MS+3m1S1rU/P4pCRfZpK5ua1DBHq4l0xROUqokFWjDcAmJJv3pYXl0cQxQcGKQ==,iv:v5hu3gmO1Zn1FfXkHLPGN9f7JOcQjzoQahdqJwfM+xY=,tag:uI1LFcTgcyRgAaTJ1kzKow==,type:str]
whisparr:
apikey: ENC[AES256_GCM,data:kIGCsd4mszm90PoQMzlSEBKw9Ow0GvP1qdLtwXYKkAb6b65l89v8lMWJ2X1MyD2gJX+P+Bv1F/2BSjUFXErq/UYnp4dAjwKi/ezGCbhjMutDM1FvwFWEHRnR3gjd9uXPWJ8Xhg==,iv:98aPQlcZHJovpnzACDs6RtKblLnHg6wyi+Er5DAowj8=,tag:Tl8jz/pWYWAtBCfoztKdyw==,type:str]
sops:
age:
- recipient: age19qfpf980tadguqq44zf6xwvjvl428dyrj46ha3n6aeqddwhtnuqqml7etq
@ -54,7 +56,7 @@ sops:
TTRWaHhpNWlkVDFmMFN4ZTNHMUxyNVkKV693pzTKRkZboQCMPr9IyMGSgxfuHXcb
Y6BNcp6Qg6PWtX5QI7wRkPNINAK1TEbRBba+b8h6gMmVU4DliQyFiQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2025-12-11T22:47:01Z"
mac: ENC[AES256_GCM,data:7d8MOO5luFUGI2DhHUQRoBG4097/KnKvmj32vbdgoPFQWuLmePAdhJJ+n2T3Si89eLNoZVpwd2gvunSLiKG+rTyvVxf3jx1bOuGOhL2VlbbnLHiJPhX6Wi3NhRRUDqWl3oNcq/G9f6Y+fJ5R+Cofkov+aTPhIAM+Ceq/7Bf+J/M=,iv:zpf8r+W2QjUAmULnjzEQdESF4cuNWa3aMIVo6FPe/YI=,tag:z5YFIqlS1URIRsnqjFLquw==,type:str]
lastmodified: "2025-12-28T21:28:31Z"
mac: ENC[AES256_GCM,data:vkGMgBkzmA2+xRIOfgUE01XG6jvTMTpm1vWXVHdZ5xE27s2mn8i6C64t1cia0n413qlKLB3y5qcbiHdRVhdLUoZFdBgFTjfixyIXOKZeVJskjJEqg2L0wZGtYIO8Y2KrfPb925qOffr7p0NcMf4c+d6bIqxHFEGb+jR/aWDOMNo=,iv:PK1FHycgOj2wtJt1UfWEAe0mKSBVksu8KWUxljSp2oo=,tag:F/xAAxJLUDqW9Dnwgrd0Rg==,type:str]
unencrypted_suffix: _unencrypted
version: 3.11.0