diff --git a/.just/machine.just b/.just/machine.just index 207185a..d07986b 100644 --- a/.just/machine.just +++ b/.just/machine.just @@ -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 diff --git a/modules/nixos/desktop/cosmic/default.nix b/modules/nixos/desktop/cosmic/default.nix index ff4d047..cba6955 100644 --- a/modules/nixos/desktop/cosmic/default.nix +++ b/modules/nixos/desktop/cosmic/default.nix @@ -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; }; }; diff --git a/modules/nixos/services/communication/matrix/default.nix b/modules/nixos/services/communication/matrix/default.nix index 33af8e4..ccdbbaa 100644 --- a/modules/nixos/services/communication/matrix/default.nix +++ b/modules/nixos/services/communication/matrix/default.nix @@ -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; }; diff --git a/modules/nixos/services/media/default.nix b/modules/nixos/services/media/default.nix index 79d2307..c10a08e 100644 --- a/modules/nixos/services/media/default.nix +++ b/modules/nixos/services/media/default.nix @@ -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"; }; } diff --git a/modules/nixos/services/media/glance/default.nix b/modules/nixos/services/media/glance/default.nix index 333035d..6af52ef 100644 --- a/modules/nixos/services/media/glance/default.nix +++ b/modules/nixos/services/media/glance/default.nix @@ -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 - ]; - } ]; } diff --git a/modules/nixos/services/media/jellyfin/default.nix b/modules/nixos/services/media/jellyfin/default.nix new file mode 100644 index 0000000..d4323f3 --- /dev/null +++ b/modules/nixos/services/media/jellyfin/default.nix @@ -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"; + }; +} diff --git a/modules/nixos/services/media/servarr/default.nix b/modules/nixos/services/media/servarr/default.nix index 057b810..bc911f7 100644 --- a/modules/nixos/services/media/servarr/default.nix +++ b/modules/nixos/services/media/servarr/default.nix @@ -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,12 +148,28 @@ in { ... }: { config = { - variable = { - api_key = { - type = "string"; - description = "${service} api key"; - }; - }; + variable = + cfg + |> lib'.mapAttrsToList (s: _: { + "${s}_api_key" = { + type = "string"; + 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}"; @@ -164,40 +188,116 @@ 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 = { - "${service}_root_folder" = mkIf (lib.elem service ["radarr" "sonarr" "whisparr"]) ( - rootFolders - |> lib.imap (i: f: lib.nameValuePair "local${toString i}" {path = f;}) - |> lib.listToAttrs - ); + resource = + { + "${service}_root_folder" = mkIf (lib.elem service ["radarr" "sonarr" "whisparr"]) ( + rootFolders + |> lib.imap (i: f: lib.nameValuePair "local${toString i}" {path = f;}) + |> lib.listToAttrs + ); - "${service}_download_client_qbittorrent" = mkIf (lib.elem service ["radarr" "sonarr" "lidarr" "whisparr"]) { - "main" = { - name = "qBittorrent"; - enable = true; - priority = 1; - host = "localhost"; - username = "admin"; - password = "poChieN5feeph0igeaCadeJ9Xux0ohmuy6ruH5ieThaPheib3iuzoo0ahw1aiceif1feegioh9Aimau0pai5thoh5ieH0aechohw"; - url_base = "/"; - port = 2008; + "${service}_download_client_qbittorrent" = mkIf (lib.elem service ["radarr" "sonarr" "lidarr" "whisparr"]) { + "main" = { + name = "qBittorrent"; + enable = true; + priority = 1; + host = "localhost"; + username = "admin"; + 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"; - # enable = true; - # priority = 1; - # host = "localhost"; - # url_base = "/"; - # port = 8080; - # }; - # }; - }; + "${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; + + # 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"; diff --git a/modules/nixos/services/media/servarr/lib.nix b/modules/nixos/services/media/servarr/lib.nix new file mode 100644 index 0000000..8ee412b --- /dev/null +++ b/modules/nixos/services/media/servarr/lib.nix @@ -0,0 +1,2 @@ +{lib, ...}: { +} diff --git a/systems/x86_64-linux/manwe/default.nix b/systems/x86_64-linux/manwe/default.nix index a2c478f..84b180b 100644 --- a/systems/x86_64-linux/manwe/default.nix +++ b/systems/x86_64-linux/manwe/default.nix @@ -24,6 +24,7 @@ application = { steam.enable = true; + zen.enable = true; }; editor = { diff --git a/systems/x86_64-linux/ulmo/default.nix b/systems/x86_64-linux/ulmo/default.nix index e661dd8..4203859 100644 --- a/systems/x86_64-linux/ulmo/default.nix +++ b/systems/x86_64-linux/ulmo/default.nix @@ -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; }; }; diff --git a/systems/x86_64-linux/ulmo/secrets.yml b/systems/x86_64-linux/ulmo/secrets.yml index 4c9cc8d..646c768 100644 --- a/systems/x86_64-linux/ulmo/secrets.yml +++ b/systems/x86_64-linux/ulmo/secrets.yml @@ -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