From 98425c9dcc393aec60b5775bde56c71d4db98209 Mon Sep 17 00:00:00 2001 From: Chris Kruining Date: Sat, 6 Dec 2025 17:39:16 +0100 Subject: [PATCH] kaas --- .forgejo/workflows/action.yml | 2 +- .just/machine.just | 2 +- .just/vars.just | 36 +- .justfile | 4 +- flake.lock | 6 +- .../services/development/forgejo/default.nix | 8 + modules/nixos/services/media/default.nix | 323 ++++++++++-------- .../nixos/services/media/mydia/default.nix | 44 ++- 8 files changed, 251 insertions(+), 174 deletions(-) diff --git a/.forgejo/workflows/action.yml b/.forgejo/workflows/action.yml index 684cfad..2c61087 100644 --- a/.forgejo/workflows/action.yml +++ b/.forgejo/workflows/action.yml @@ -12,4 +12,4 @@ jobs: steps: - name: Echo run: | - nix --version \ No newline at end of file + nix --version diff --git a/.just/machine.just b/.just/machine.just index cc7665e..ca10e1c 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 --use-remote-sudo --target-host {{ machine }} --flake ..#{{ machine }} + nixos-rebuild switch -L --use-remote-sudo --target-host {{ machine }} --flake ..#{{ machine }} diff --git a/.just/vars.just b/.just/vars.just index d8bd181..3b706da 100644 --- a/.just/vars.just +++ b/.just/vars.just @@ -1,36 +1,38 @@ -set unstable +set unstable := true base_path := invocation_directory() / "systems/x86_64-linux" + # sops := "nix shell nixpkgs#sops --command sops" # yq := "nix shell nixpkgs#yq --command yq" + sops := "sops" yq := "yq" @_default: - just --list + just --list [doc('list all vars of the target machine')] list machine: - sops decrypt {{ base_path }}/{{ machine }}/secrets.yml - + sops decrypt {{ base_path }}/{{ machine }}/secrets.yml + @edit machine: - sops edit {{ base_path }}/{{ machine }}/secrets.yml - + sops edit {{ base_path }}/{{ machine }}/secrets.yml + @set machine key value: - sops set {{ base_path }}/{{ machine }}/secrets.yml "$(printf '%s\n' '["{{ key }}"]' | sed -E 's#/#"]["#g; s/\["([0-9]+)"\]/[\1]/g')" "\"$(echo '{{ value }}' | sed 's/\"/\\\"/g')\"" + sops set {{ base_path }}/{{ machine }}/secrets.yml "$(printf '%s\n' '["{{ key }}"]' | sed -E 's#/#"]["#g; s/\["([0-9]+)"\]/[\1]/g')" "\"$(echo '{{ value }}' | sed 's/\"/\\\"/g')\"" - git add {{ base_path }}/{{ machine }}/secrets.yml - git commit -m 'chore(secrets): set secret "{{ key }}" for machine "{{ machine}}"' -- {{ base_path }}/{{ machine }}/secrets.yml > /dev/null + git add {{ base_path }}/{{ machine }}/secrets.yml + git commit -m 'chore(secrets): set secret "{{ key }}" for machine "{{ machine }}"' -- {{ base_path }}/{{ machine }}/secrets.yml > /dev/null + + echo "Done" - echo "Done" - @get machine key: - sops decrypt {{ base_path }}/{{ machine }}/secrets.yml | yq ".$(echo "{{ key }}" | sed -E 's/\//./g')" - + sops decrypt {{ base_path }}/{{ machine }}/secrets.yml | yq ".$(echo "{{ key }}" | sed -E 's/\//./g')" + @remove machine key: - sops unset {{ base_path }}/{{ machine }}/secrets.yml "$(printf '%s\n' '["{{ key }}"]' | sed -E 's#/#"]["#g; s/\["([0-9]+)"\]/[\1]/g')" + sops unset {{ base_path }}/{{ machine }}/secrets.yml "$(printf '%s\n' '["{{ key }}"]' | sed -E 's#/#"]["#g; s/\["([0-9]+)"\]/[\1]/g')" - git add {{ base_path }}/{{ machine }}/secrets.yml - git commit -m 'chore(secrets): removed secret "{{ key }}" from machine "{{ machine}}"' -- {{ base_path }}/{{ machine }}/secrets.yml > /dev/null + git add {{ base_path }}/{{ machine }}/secrets.yml + git commit -m 'chore(secrets): removed secret "{{ key }}" from machine "{{ machine }}"' -- {{ base_path }}/{{ machine }}/secrets.yml > /dev/null - echo "Done" \ No newline at end of file + echo "Done" diff --git a/.justfile b/.justfile index 3a15d20..75537e1 100644 --- a/.justfile +++ b/.justfile @@ -19,7 +19,7 @@ mod machine '.just/machine.just' [doc('Introspection on flake output')] @select key: - nix eval --json .#{{ key }} | jq . + nix eval --show-trace --json .#{{ key }} | jq . @@ -30,4 +30,4 @@ mod machine '.just/machine.just' [no-cd] [private] @assert condition message: - [ {{ condition }} ] || { echo -e 1>&2 "\n\x1b[1;41m Error \x1b[0m {{ message }}\n"; exit 1; } \ No newline at end of file + [ {{ condition }} ] || { echo -e 1>&2 "\n\x1b[1;41m Error \x1b[0m {{ message }}\n"; exit 1; } diff --git a/flake.lock b/flake.lock index 66f4631..9d00509 100644 --- a/flake.lock +++ b/flake.lock @@ -713,11 +713,11 @@ "nixpkgs": "nixpkgs_5" }, "locked": { - "lastModified": 1764840646, - "narHash": "sha256-ffhLaQWDm4iyf7j3uxmMXg5k7FRimaj8PXA4Jj9EpB0=", + "lastModified": 1764866402, + "narHash": "sha256-0NOWsPks+/vV5ZM9ti71hUPMLy3FzbEIlFI6vxARvuY=", "owner": "chris-kruining", "repo": "mydia", - "rev": "035fa63a276ed4dd9743fdf5ff50a651cabb9bcd", + "rev": "458fc9a21c6987d994bc7932efb6c49df25ba806", "type": "github" }, "original": { diff --git a/modules/nixos/services/development/forgejo/default.nix b/modules/nixos/services/development/forgejo/default.nix index c7aff89..114726e 100644 --- a/modules/nixos/services/development/forgejo/default.nix +++ b/modules/nixos/services/development/forgejo/default.nix @@ -184,6 +184,14 @@ in { }; }; + users = { + users."gitea-runner" = { + isSystemUser = true; + group = "gitea-runner"; + }; + groups."gitea-runner" = {}; + }; + sops.secrets = { "forgejo/action_runner_token" = { owner = "gitea-runner"; diff --git a/modules/nixos/services/media/default.nix b/modules/nixos/services/media/default.nix index 1950bf0..c880580 100644 --- a/modules/nixos/services/media/default.nix +++ b/modules/nixos/services/media/default.nix @@ -1,13 +1,19 @@ -{ pkgs, lib, namespace, config, inputs, system, ... }: -let +{ + pkgs, + lib, + namespace, + config, + inputs, + system, + ... +}: let inherit (lib) mkIf mkEnableOption mkOption; inherit (lib.types) str; cfg = config.${namespace}.services.media; - arr = ["radarr" ]; -in -{ + arr = ["radarr"]; +in { options.${namespace}.services.media = { enable = mkEnableOption "Enable media services"; @@ -69,117 +75,132 @@ in # Services #========================================================================= services = let - arr-services = + arr-services = arr |> lib.imap (i: service: { name = service; - value = { - enable = true; - openFirewall = true; + value = + { + enable = true; + openFirewall = true; - environmentFiles = [ - config.sops.templates."${service}/config.env".path - ]; + environmentFiles = [ + config.sops.templates."${service}/config.env".path + ]; - settings = { - auth.authenticationMethod = "External"; + settings = { + auth.authenticationMethod = "External"; - server = { - bindaddress = "0.0.0.0"; - port = 2000 + i; + server = { + bindaddress = "0.0.0.0"; + port = 2000 + i; + }; + + postgres = { + host = "localhost"; + port = "5432"; + user = service; + maindb = service; + logdb = service; + }; }; - - postgres = { - host = "localhost"; - port = "5432"; - user = service; - maindb = service; - logdb = service; - }; - }; - } - // (if service != "prowlarr" then { user = cfg.user; group = cfg.group; } else {}); + } + // ( + 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; + |> lib.listToAttrs; + in + arr-services + // { + bazarr = { + enable = true; + openFirewall = true; + user = cfg.user; + group = cfg.group; + listenPort = 2005; }; - user = cfg.user; - group = cfg.group; - }; + # port is harcoded in nixpkgs module + jellyfin = { + enable = true; + openFirewall = true; + user = cfg.user; + group = cfg.group; + }; - # port is harcoded in nixpkgs module - sabnzbd = { - enable = true; - openFirewall = true; - configFile = "${cfg.path}/sabnzbd/config.ini"; + flaresolverr = { + enable = true; + openFirewall = true; + port = 2007; + }; - user = cfg.user; - group = cfg.group; - }; + qbittorrent = { + enable = true; + openFirewall = true; + webuiPort = 2008; - postgresql = - let - databases = arr |> lib.concatMap (s: [ s "${s}-log" ]); - in - { - enable = true; - ensureDatabases = arr; - ensureUsers = arr |> lib.map (service: { - name = service; - ensureDBOwnership = true; - }); - }; + serverConfig = { + LegalNotice.Accepted = true; - caddy = { - enable = true; - virtualHosts = { - "jellyfin.kruining.eu".extraConfig = '' - reverse_proxy http://[::1]:8096 - ''; + Prefecences.WebUI = { + Username = "admin"; + }; + }; + + 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 + 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, + lib, + ... + }: { config = { variable = { api_key = { @@ -207,13 +228,12 @@ in }) ]; }; - in - { + in { description = "Radarr terraform apply"; - wantedBy = [ "multi-user.target" ]; - wants = [ "radarr.service" ]; - + wantedBy = ["multi-user.target"]; + wants = ["radarr.service"]; + script = '' #!/usr/bin/env bash @@ -255,53 +275,70 @@ in systemd.services.jellyfin.serviceConfig.killSignal = lib.mkForce "SIGKILL"; sops = { - secrets = - arr - |> lib.map (service: { - name = "${service}/apikey"; - value = { + secrets = let + arrSecrets = + arr + |> lib.map (service: { + name = "${service}/apikey"; + value = { + owner = cfg.user; + group = cfg.group; + restartUnits = ["${service}.service"]; + }; + }) + |> lib.listToAttrs; + in + arrSecrets + // { + # "qbittorrent/password" = {}; + "qbittorrent/password_hash" = {}; + }; + + 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; + + qbittorrent = { + "qbittorrent/password.conf" = { owner = cfg.user; group = cfg.group; - restartUnits = [ "${service}.service" ]; + restartUnits = ["qbittorrent.service"]; + path = "${config.services.qbittorrent.profileDir}/qBittorrent/config/password.conf"; + content = '' + [Preferences] + WebUI\Password_PBKDF2="${config.sops.placeholder."qbittorrent/password_hash"}" + ''; }; - }) - |> 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 - ; + }; + in + apikeys // tfvars // qbittorrent; }; }; } diff --git a/modules/nixos/services/media/mydia/default.nix b/modules/nixos/services/media/mydia/default.nix index 1dbacda..2bee38a 100644 --- a/modules/nixos/services/media/mydia/default.nix +++ b/modules/nixos/services/media/mydia/default.nix @@ -26,9 +26,17 @@ in { listenAddress = "0.0.0.0"; openFirewall = true; + mediaLibraries = [ + "/var/mydia/movies" + "/var/mydia/series" + ]; + database = { + # type = "sqlite"; + # uri = "file:///var/lib/mydia/mydia.db"; type = "postgres"; - uri = "postgres://localhost:5432/mydia?sslMode=disable"; + uri = "postgres://mydia@localhost:5432/mydia?sslmode=disable"; + passwordFile = config.sops.secrets."mydia/qbittorrent_password".path; }; secretKeyBaseFile = config.sops.secrets."mydia/secret_key_base".path; @@ -41,16 +49,38 @@ in { clientSecretFile = config.sops.secrets."mydia/oidc_secret".path; scopes = ["openid" "profile" "email"]; }; + + downloadClients = { + qbittorrent = { + type = "qbittorrent"; + host = "localhost"; + port = 2008; + username = "admin"; + passwordFile = config.sops.secrets."mydia/qbittorrent_password".path; + useSsl = false; + }; + }; }; - sops.secrets = - ["secret_key_base" "guardian_secret" "oidc_id" "oidc_secret"] - |> lib.map (name: - lib.nameValuePair "mydia/${name}" { + sops.secrets = let + base = + ["secret_key_base" "guardian_secret" "oidc_id" "oidc_secret"] + |> lib.map (name: + lib.nameValuePair "mydia/${name}" { + owner = config.services.mydia.user; + group = config.services.mydia.group; + restartUnits = ["mydia.service"]; + }) + |> lib.listToAttrs; + in + base + // { + "mydia/qbittorrent_password" = { owner = config.services.mydia.user; group = config.services.mydia.group; restartUnits = ["mydia.service"]; - }) - |> lib.listToAttrs; + key = "qbittorrent/password"; + }; + }; }; }