From e5c699fcb0e2810af5d914c633fb405b433324f8 Mon Sep 17 00:00:00 2001 From: Nikolaos Karaolidis Date: Thu, 3 Jul 2025 12:10:22 +0100 Subject: [PATCH] Add jupiter transmission container Signed-off-by: Nikolaos Karaolidis --- .../console/podman/authelia/default.nix | 5 +- .../storm/configs/console/podman/default.nix | 1 + .../console/podman/traefik/default.nix | 6 +- .../console/podman/transmission/default.nix | 83 +++++++++++++++++++ .../docker/transmission-protonvpn/default.nix | 21 +++-- .../transmission-protonvpn/entrypoint.sh | 38 +++++---- packages/sas/cacert/default.nix | 2 +- 7 files changed, 129 insertions(+), 27 deletions(-) create mode 100644 hosts/jupiter/users/storm/configs/console/podman/transmission/default.nix diff --git a/hosts/jupiter/users/storm/configs/console/podman/authelia/default.nix b/hosts/jupiter/users/storm/configs/console/podman/authelia/default.nix index efb106a..67c0faa 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/authelia/default.nix +++ b/hosts/jupiter/users/storm/configs/console/podman/authelia/default.nix @@ -135,10 +135,11 @@ in email = "nick@karaolidis.com"; groups = [ "admins" - "gitea" - "outline" "vaultwarden" "nextcloud" + "media" + "gitea" + "outline" "shlink" ]; }; diff --git a/hosts/jupiter/users/storm/configs/console/podman/default.nix b/hosts/jupiter/users/storm/configs/console/podman/default.nix index 0c34d51..26bf44a 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/default.nix +++ b/hosts/jupiter/users/storm/configs/console/podman/default.nix @@ -18,6 +18,7 @@ in (import ./shlink { inherit user home; }) (import ./sish { inherit user home; }) (import ./traefik { inherit user home; }) + (import ./transmission { inherit user home; }) (import ./vaultwarden { inherit user home; }) (import ./whoami { inherit user home; }) ]; diff --git a/hosts/jupiter/users/storm/configs/console/podman/traefik/default.nix b/hosts/jupiter/users/storm/configs/console/podman/traefik/default.nix index 39c7272..5991079 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/traefik/default.nix +++ b/hosts/jupiter/users/storm/configs/console/podman/traefik/default.nix @@ -35,7 +35,10 @@ in }; virtualisation.quadlet = { - networks.traefik = { }; + networks = { + traefik-ext = { }; + traefik.networkConfig.internal = true; + }; volumes.traefik = { }; @@ -44,6 +47,7 @@ in containerConfig = { image = "docker-archive:${selfPkgs.docker-traefik}"; networks = [ + networks.traefik-ext.ref networks.traefik.ref networks.prometheus.ref ]; diff --git a/hosts/jupiter/users/storm/configs/console/podman/transmission/default.nix b/hosts/jupiter/users/storm/configs/console/podman/transmission/default.nix new file mode 100644 index 0000000..173a11f --- /dev/null +++ b/hosts/jupiter/users/storm/configs/console/podman/transmission/default.nix @@ -0,0 +1,83 @@ +{ + user ? throw "user argument is required", + home ? throw "home argument is required", +}: +{ + config, + inputs, + pkgs, + system, + ... +}: +let + selfPkgs = inputs.self.packages.${system}; + hmConfig = config.home-manager.users.${user}; + inherit (hmConfig.virtualisation.quadlet) volumes networks; +in +{ + home-manager.users.${user} = { + sops.secrets."transmission/protonvpn".sopsFile = ../../../../../../secrets/secrets.yaml; + + systemd.user.tmpfiles.rules = [ + "d /mnt/storage/private/storm/containers/storage/volumes/transmission-data/_data 700 storm storm" + ]; + + virtualisation.quadlet = { + # Not internal, we need network access for obvious reasons + networks.transmission = { }; + + volumes.transmission-config = { }; + + containers = { + transmission = { + containerConfig = { + image = "docker-archive:${selfPkgs.docker-transmission-protonvpn}"; + networks = [ + networks.transmission.ref + networks.traefik.ref + ]; + addCapabilities = [ "NET_ADMIN" ]; + volumes = + let + config = (pkgs.formats.json { }).generate "settings.override.json" { + ratio-limit-enabled = true; + ratio-limit = 5; + }; + in + [ + "${hmConfig.sops.secrets."transmission/protonvpn".path}:/etc/wireguard/privatekey:ro" + "${config}:/etc/transmission/settings.override.json:ro" + "${volumes.transmission-config.ref}:/etc/transmission" + "/mnt/storage/private/storm/containers/storage/volumes/transmission-data/_data:/var/lib/transmission" + ]; + environments = { + WIREGUARD_PUBLIC_KEY = "zctOjv4DH2gzXtLQy86Tp0vnT+PNpMsxecd2vUX/i0U="; + WIREGUARD_ENDPOINT = "146.70.179.50:51820"; + }; + labels = [ + "traefik.enable=true" + "traefik.http.routers.transmission.rule=Host(`torrent.karaolidis.com`)" + "traefik.http.routers.transmission.middlewares=authelia@docker" + ]; + }; + + unitConfig.After = [ "sops-nix.service" ]; + }; + + authelia-init.containerConfig.volumes = + let + config = (pkgs.formats.yaml { }).generate "transmission.yaml" { + access_control.rules = [ + { + domain = "torrent.karaolidis.com"; + policy = "one_factor"; + subject = [ "group:media" ]; + } + ]; + }; + in + [ "${config}:/etc/authelia/conf.d/transmission.yaml:ro" ]; + }; + }; + }; +} diff --git a/packages/docker/transmission-protonvpn/default.nix b/packages/docker/transmission-protonvpn/default.nix index 56587d0..b8a6c2d 100644 --- a/packages/docker/transmission-protonvpn/default.nix +++ b/packages/docker/transmission-protonvpn/default.nix @@ -6,6 +6,11 @@ let destination = "/bin/entrypoint"; text = builtins.readFile ./entrypoint.sh; }; + + flood-for-transmission = pkgs.runCommandLocal "flood-for-transmission" { } '' + mkdir -p $out/var/www + cp -r ${pkgs.flood-for-transmission} $out/var/www/transmission + ''; in pkgs.dockerTools.buildImage { name = "transmission-protonvpn"; @@ -13,19 +18,20 @@ pkgs.dockerTools.buildImage { copyToRoot = pkgs.buildEnv { name = "root"; - paths = with pkgs; [ + paths = [ entrypoint - transmission_4 flood-for-transmission - wireguard-tools - libnatpmp - curl - jq + pkgs.transmission_4 + pkgs.wireguard-tools + pkgs.libnatpmp + pkgs.curl + pkgs.jq ]; pathsToLink = [ "/bin" "/lib" "/share" + "/var" ]; }; @@ -43,7 +49,8 @@ pkgs.dockerTools.buildImage { "/var/lib/transmission" = { }; }; Env = [ - "TRANSMISSION_WEB_HOME=${pkgs.flood-for-transmission}" + "TRANSMISSION_HOME=/etc/transmission" + "TRANSMISSION_WEB_HOME=/var/www/transmission" ]; }; } diff --git a/packages/docker/transmission-protonvpn/entrypoint.sh b/packages/docker/transmission-protonvpn/entrypoint.sh index dc38baf..4d9d2f1 100644 --- a/packages/docker/transmission-protonvpn/entrypoint.sh +++ b/packages/docker/transmission-protonvpn/entrypoint.sh @@ -9,7 +9,9 @@ WIREGUARD_ADDRESS="${WIREGUARD_ADDRESS:-10.2.0.2/32}" WIREGUARD_DNS="${WIREGUARD_DNS:-10.2.0.1}" WIREGUARD_PEER_IP="${WIREGUARD_ENDPOINT%%:*}" -DEFAULT_IFACE=$(ip route show default | awk '/default/ {print $5; exit}') + +DEFAULT_GATEWAY="$(ip route show default | awk '/default/ {print $3; exit}')" +DEFAULT_INTERFACE="$(ip route show default | awk '/default/ {print $5; exit}')" ip link add dev wg0 type wireguard @@ -19,21 +21,23 @@ wg set wg0 peer "$WIREGUARD_PUBLIC_KEY" allowed-ips "$WIREGUARD_ALLOWED_IPS" end ip link set up dev wg0 -ip route add "$WIREGUARD_PEER_IP/32" dev "$DEFAULT_IFACE" +ip route add "$WIREGUARD_PEER_IP/32" via "$DEFAULT_GATEWAY" dev "$DEFAULT_INTERFACE" ip route add 0.0.0.0/0 dev wg0 echo "nameserver $WIREGUARD_DNS" > /etc/resolv.conf -PIPE=$(mktemp -u) -mkfifo "$PIPE" - BIND_IP="${WIREGUARD_ADDRESS%%/*}" -transmission-daemon -d \ +rm -f "$TRANSMISSION_HOME/settings.json" + +default_settings="$(\ + transmission-daemon -d \ --no-portmap \ --bind-address-ipv4 "$BIND_IP" \ --bind-address-ipv6 "::1" \ - "$@" 2> /etc/transmission/settings.json + "$@" 2>&1)" + +echo "$default_settings" > "$TRANSMISSION_HOME/settings.json" tmpfile="$(mktemp)" jq '. + { @@ -43,21 +47,23 @@ jq '. + { "download-dir": "/var/lib/transmission", "incomplete-dir": "/var/lib/transmission/incomplete", "rename-partial-files": true -}' /etc/transmission/settings.json > "$tmpfile" -mv "$tmpfile" /etc/transmission/settings.json +}' "$TRANSMISSION_HOME/settings.json" > "$tmpfile" +mv "$tmpfile" "$TRANSMISSION_HOME/settings.json" -if [ -f /etc/transmission/settings.override.json ]; then +if [ -f "$TRANSMISSION_HOME/settings.override".json ]; then tmpfile="$(mktemp)" jq -s \ '.[0] * .[1]' \ - /etc/transmission/settings.json \ - /etc/transmission/settings.override.json \ + "$TRANSMISSION_HOME/settings.json" \ + "$TRANSMISSION_HOME/settings.override.json" \ > "$tmpfile" - mv "$tmpfile" /etc/transmission/settings.json + mv "$tmpfile" "$TRANSMISSION_HOME/settings.json" fi +PIPE=$(mktemp -u) +mkfifo "$PIPE" + transmission-daemon -f \ - --config-dir /etc/transmission \ --no-portmap \ --bind-address-ipv4 "$BIND_IP" \ --bind-address-ipv6 "::1" \ @@ -72,7 +78,7 @@ tee "$CAT_PIPE" "$GREP_PIPE" < "$PIPE" > /dev/null & cat "$CAT_PIPE" & grep -q -m 1 "Serving RPC and Web requests on 0.0.0.0:9091" < "$GREP_PIPE" -rpc_path="$(jq -r '.["rpc-url"]' /etc/transmission/settings.json)" +rpc_path="$(jq -r '.["rpc-url"]' "$TRANSMISSION_HOME/settings.json")" rpc_url="http://127.0.0.1:9091${rpc_path}rpc/" ( @@ -109,7 +115,7 @@ cleanup() { kill -INT "$PID" "$NATPMP_PID" || true ip route del 0.0.0.0/0 dev wg0 - ip route del "$WIREGUARD_PEER_IP/32" dev "$DEFAULT_IFACE" + ip route del "$WIREGUARD_PEER_IP/32" via "$DEFAULT_GATEWAY" dev "$DEFAULT_INTERFACE" ip link set down dev wg0 ip link delete dev wg0 diff --git a/packages/sas/cacert/default.nix b/packages/sas/cacert/default.nix index 77de159..8af52bf 100644 --- a/packages/sas/cacert/default.nix +++ b/packages/sas/cacert/default.nix @@ -5,7 +5,7 @@ pkgs.stdenv.mkDerivation rec { src = builtins.fetchurl { url = "http://certificates.sas.com/pki/sascacertsbundle.txt"; - sha256 = "sha256:0naqfhyh7ri1lxkyx8kdh4bmrd59j9gnfxfi12ggfqkii9n37lj6"; + sha256 = "sha256:1lah292kqhw6mkj63870qh8fjm44ll4jdqz87pfgr4sb803w1i15"; }; phases = [ "installPhase" ];