From 66b96a843fd17fbdf28e0d59cdb51b93ed2a1feb Mon Sep 17 00:00:00 2001 From: GHOSCHT <31184695+GHOSCHT@users.noreply.github.com> Date: Thu, 7 Mar 2024 16:47:34 +0100 Subject: [PATCH] Arion: Add media stack --- hosts/franz/arion/media/arion-compose.nix | 381 ++++++++++++++++++++++ hosts/franz/arion/media/arion-pkgs.nix | 6 + hosts/franz/arion/media/default.nix | 73 +++++ 3 files changed, 460 insertions(+) create mode 100644 hosts/franz/arion/media/arion-compose.nix create mode 100644 hosts/franz/arion/media/arion-pkgs.nix create mode 100644 hosts/franz/arion/media/default.nix diff --git a/hosts/franz/arion/media/arion-compose.nix b/hosts/franz/arion/media/arion-compose.nix new file mode 100644 index 0000000..429e074 --- /dev/null +++ b/hosts/franz/arion/media/arion-compose.nix @@ -0,0 +1,381 @@ +{pkgs, ...}: { + project.name = "media"; + + networks.dmz = { + name = "dmz"; + external = true; + }; + + docker-compose.volumes = { + jellyfin_cache = null; + }; + + services = { + jellyfin.service = { + image = "jellyfin/jellyfin:latest"; + container_name = "jellyfin"; + ports = [ + "8096:8096" + ]; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.jellyfin.entrypoints" = "websecure"; + "traefik.http.routers.jellyfin.rule" = "Host(`jellyfin.ghoscht.com`)"; + "traefik.http.services.jellyfin.loadbalancer.server.port" = "8096"; + "traefik.http.services.jellyfin.loadbalancer.passHostHeader" = "true"; + "traefik.http.routers.jellyfin.tls" = "true"; + "traefik.http.routers.jellyfin.tls.certresolver" = "letsencrypt"; + }; + volumes = [ + "jellyfin_cache:/cache" + "/home/ghoscht/.docker/media/jellyfin_data:/config" + "/home/ghoscht/.docker/media/data/tv:/tv" + "/home/ghoscht/.docker/media/data/anime:/anime" + "/home/ghoscht/.docker/media/data/movies:/movies" + ]; + environment = { + PUID = 1000; + PGID = 1000; + TZ = "Europe/Berlin"; + }; + restart = "always"; + networks = [ + "dmz" + ]; + }; + navidrome.service = { + image = "deluan/navidrome:latest"; + container_name = "navidrome"; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.navidrome.entrypoints" = "websecure"; + "traefik.http.routers.navidrome.rule" = "Host(`navidrome.ghoscht.com`)"; + "traefik.http.services.navidrome.loadbalancer.server.port" = "4533"; + "traefik.http.routers.navidrome.tls" = "true"; + "traefik.http.routers.navidrome.tls.certresolver" = "letsencrypt"; + }; + volumes = [ + "/home/ghoscht/.docker/media/navidrome_data:/data" + "/home/ghoscht/.docker/media/data/music:/music" + ]; + environment = { + ND_SESSIONTIMEOUT = "336h"; + }; + env_file = [ + "/home/ghoscht/.docker/media/navidrome.env" + ]; + restart = "always"; + networks = [ + "dmz" + ]; + }; + vpn.service = { + image = "haugene/transmission-openvpn"; + container_name = "transmission"; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.transmission.entrypoints" = "websecure"; + "traefik.http.routers.transmission.rule" = "Host(`transmission.ghoscht.com`)"; + "traefik.http.services.transmission.loadbalancer.server.port" = "9091"; + "traefik.docker.network" = "dmz"; + "traefik.http.routers.transmission.tls" = "true"; + "traefik.http.routers.transmission.tls.certresolver" = "letsencrypt"; + }; + volumes = [ + "/home/ghoscht/.docker/media/transmission_data:/config" + "/home/ghoscht/.docker/media/data:/data" + ]; + environment = { + PUID = 1000; + PGID = 1000; + TZ = "Europe/Berlin"; + OPENVPN_PROVIDER = "WINDSCRIBE"; + OPENVPN_CONFIG = "Vienna-Hofburg-udp"; + OVPN_PROTOCOL = "udp"; + OPENVPN_OPTS = "--pull-filter ignore ping --ping 10 --ping-restart 120"; + LOCAL_NETWORK = "192.168.0.0/16"; + TRANSMISSION_DOWNLOAD_DIR = "/data/torrents"; + TRANSMISSION_INCOMPLETE_DIR = "/data/torrents/incomplete"; + TRANSMISSION_WEB_UI = "flood-for-transmission"; + }; + env_file = [ + "/home/ghoscht/.docker/media/windscribe.env" + ]; + capabilities = { + NET_ADMIN = true; + }; + restart = "always"; + networks = [ + "dmz" + ]; + }; + prowlarr.service = { + image = "linuxserver/prowlarr:latest"; + container_name = "prowlarr"; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.prowlarr.entrypoints" = "websecure"; + "traefik.http.routers.prowlarr.rule" = "Host(`prowlarr.ghoscht.com`)"; + "traefik.http.services.prowlarr.loadbalancer.server.port" = "9696"; + "traefik.docker.network" = "dmz"; + "traefik.http.routers.prowlarr.tls" = "true"; + "traefik.http.routers.prowlarr.tls.certresolver" = "letsencrypt"; + }; + volumes = [ + "/home/ghoscht/.docker/media/prowlarr_data:/config" + ]; + environment = { + PUID = 1000; + PGID = 1000; + TZ = "Europe/Berlin"; + }; + network_mode = "service:vpn"; + depends_on = { + vpn = {condition = "service_healthy";}; + }; + restart = "always"; + }; + sonarr.service = { + image = "linuxserver/sonarr:latest"; + container_name = "sonarr"; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.sonarr.entrypoints" = "websecure"; + "traefik.http.routers.sonarr.rule" = "Host(`sonarr.ghoscht.com`)"; + "traefik.http.services.sonarr.loadbalancer.server.port" = "8989"; + "traefik.docker.network" = "dmz"; + "traefik.http.routers.sonarr.tls" = "true"; + "traefik.http.routers.sonarr.tls.certresolver" = "letsencrypt"; + }; + volumes = [ + "/home/ghoscht/.docker/media/sonarr_data:/config" + "/home/ghoscht/.docker/media/data:/data" + ]; + environment = { + PUID = 1000; + PGID = 1000; + TZ = "Europe/Berlin"; + }; + network_mode = "service:vpn"; + depends_on = { + vpn = {condition = "service_healthy";}; + prowlarr = {condition = "service_started";}; + }; + restart = "always"; + }; + radarr.service = { + image = "linuxserver/radarr:latest"; + container_name = "radarr"; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.radarr.entrypoints" = "websecure"; + "traefik.http.routers.radarr.rule" = "Host(`radarr.ghoscht.com`)"; + "traefik.http.services.radarr.loadbalancer.server.port" = "7878"; + "traefik.docker.network" = "dmz"; + "traefik.http.routers.radarr.tls" = "true"; + "traefik.http.routers.radarr.tls.certresolver" = "letsencrypt"; + }; + volumes = [ + "/home/ghoscht/.docker/media/radarr_data:/config" + "/home/ghoscht/.docker/media/data:/data" + ]; + environment = { + PUID = 1000; + PGID = 1000; + TZ = "Europe/Berlin"; + }; + network_mode = "service:vpn"; + depends_on = { + vpn = {condition = "service_healthy";}; + prowlarr = {condition = "service_started";}; + }; + restart = "always"; + }; + lidarr.service = { + image = "linuxserver/lidarr:latest"; + container_name = "lidarr"; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.lidarr.entrypoints" = "websecure"; + "traefik.http.routers.lidarr.rule" = "Host(`lidarr.ghoscht.com`)"; + "traefik.http.services.lidarr.loadbalancer.server.port" = "8686"; + "traefik.http.routers.lidarr.service" = "lidarr"; + "traefik.docker.network" = "dmz"; + "traefik.http.routers.lidarr.tls" = "true"; + "traefik.http.routers.lidarr.tls.certresolver" = "letsencrypt"; + }; + volumes = [ + "/home/ghoscht/.docker/media/lidarr_data:/config" + "/home/ghoscht/.docker/media/data:/data" + "/home/ghoscht/.docker/media/lidarr_addons/custom-services.d:/custom-services.d" + "/home/ghoscht/.docker/media/lidarr_addons/custom-cont-init.d:/custom-cont-init.d" + ]; + environment = { + PUID = 1000; + PGID = 1000; + TZ = "Europe/Berlin"; + }; + network_mode = "service:vpn"; + depends_on = { + vpn = {condition = "service_healthy";}; + prowlarr = {condition = "service_started";}; + }; + restart = "always"; + }; + bazarr.service = { + image = "hotio/bazarr:latest"; + container_name = "bazarr"; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.bazarr.entrypoints" = "websecure"; + "traefik.http.routers.bazarr.rule" = "Host(`bazarr.ghoscht.com`)"; + "traefik.http.services.bazarr.loadbalancer.server.port" = "6767"; + "traefik.docker.network" = "dmz"; + "traefik.http.routers.bazarr.tls" = "true"; + "traefik.http.routers.bazarr.tls.certresolver" = "letsencrypt"; + }; + volumes = [ + "/home/ghoscht/.docker/media/bazarr_data:/config" + "/home/ghoscht/.docker/media/data:/data" + ]; + environment = { + PUID = 1000; + PGID = 1000; + TZ = "Europe/Berlin"; + }; + networks = ["dmz"]; + restart = "always"; + }; + jellyseerr.service = { + image = "fallenbagel/jellyseerr:latest"; + container_name = "jellyseerr"; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.jellyseerr.entrypoints" = "websecure"; + "traefik.http.routers.jellyseerr.rule" = "Host(`jellyseerr.ghoscht.com`)"; + "traefik.http.services.jellyseerr.loadbalancer.server.port" = "5055"; + "traefik.docker.network" = "dmz"; + "traefik.http.routers.jellyseerr.tls" = "true"; + "traefik.http.routers.jellyseerr.tls.certresolver" = "letsencrypt"; + }; + volumes = [ + "/home/ghoscht/.docker/media/jellyseerr_data:/app/config" + ]; + environment = { + PUID = 1000; + PGID = 1000; + TZ = "Europe/Berlin"; + }; + networks = ["dmz"]; + restart = "always"; + }; + autobrr.service = { + image = "ghcr.io/autobrr/autobrr:latest"; + container_name = "autobrr"; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.autobrr.entrypoints" = "websecure"; + "traefik.http.routers.autobrr.rule" = "Host(`autobrr.ghoscht.com`)"; + "traefik.http.services.autobrr.loadbalancer.server.port" = "7474"; + "traefik.docker.network" = "dmz"; + "traefik.http.routers.autobrr.tls" = "true"; + "traefik.http.routers.autobrr.tls.certresolver" = "letsencrypt"; + }; + volumes = [ + "/home/ghoscht/.docker/media/jellyseerr_data:/app/config" + ]; + environment = { + PUID = 1000; + PGID = 1000; + TZ = "Europe/Berlin"; + }; + network_mode = "service:vpn"; + depends_on = { + vpn = {condition = "service_healthy";}; + prowlarr = {condition = "service_started";}; + sonarr = {condition = "service_started";}; + radarr = {condition = "service_started";}; + }; + restart = "always"; + }; + deemix.service = { + image = "finniedj/deemix"; + container_name = "deemix"; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.deemix.entrypoints" = "websecure"; + "traefik.http.routers.deemix.rule" = "Host(`deemix.ghoscht.com`)"; + "traefik.http.services.deemix.loadbalancer.server.port" = "6595"; + "traefik.docker.network" = "dmz"; + "traefik.http.routers.deemix.tls" = "true"; + "traefik.http.routers.deemix.tls.certresolver" = "letsencrypt"; + }; + volumes = [ + "/home/ghoscht/.docker/media/jellyseerr_data:/app/config" + ]; + environment = { + PUID = 1000; + PGID = 1000; + UMASK_SET = 022; + TZ = "Europe/Berlin"; + }; + network_mode = "service:vpn"; + depends_on = { + vpn = {condition = "service_healthy";}; + }; + restart = "always"; + }; + unpackerr.service = { + image = "golift/unpackerr"; + container_name = "unpackerr"; + volumes = [ + "/home/ghoscht/.docker/media/data:/data" + ]; + user = "1000:1000"; + env_file = [ + "/home/ghoscht/.docker/media/unpackerr.env" + ]; + environment = { + TZ = "Europe/Berlin"; + # General config + UN_DEBUG = "false"; + UN_INTERVAL = "2m"; + UN_START_DELAY = "1m"; + UN_RETRY_DELAY = "5m"; + UN_MAX_RETRIES = 3; + UN_PARALLEL = 1; + UN_FILE_MODE = 0644; + UN_DIR_MODE = 0755; + # Sonarr Config + UN_SONARR_0_URL = "http://transmission:8989"; + UN_SONARR_0_PATHS_0 = "/data/torrents/tv"; + UN_SONARR_0_PROTOCOLS = "torrent"; + UN_SONARR_0_TIMEOUT = "10s"; + UN_SONARR_0_DELETE_ORIG = "false"; + UN_SONARR_0_DELETE_DELAY = "5m"; + # Radarr Config + UN_RADARR_0_URL = "http://transmission:7878"; + UN_RADARR_0_PATHS_0 = "/data/torrents/movies"; + UN_RADARR_0_PROTOCOLS = "torrent"; + UN_RADARR_0_TIMEOUT = "10s"; + UN_RADARR_0_DELETE_ORIG = "false"; + UN_RADARR_0_DELETE_DELAY = "5m"; + # Lidarr Config + UN_LIDARR_0_URL = "http://transmission:8686"; + UN_LIDARR_0_PATHS_0 = "/data/torrents/music"; + UN_LIDARR_0_PROTOCOLS = "torrent"; + UN_LIDARR_0_TIMEOUT = "10s"; + UN_LIDARR_0_DELETE_ORIG = "false"; + UN_LIDARR_0_DELETE_DELAY = "5m"; + }; + networks = ["dmz"]; + depends_on = { + vpn = {condition = "service_healthy";}; + prowlarr = {condition = "service_started";}; + sonarr = {condition = "service_started";}; + radarr = {condition = "service_started";}; + }; + restart = "always"; + }; + }; +} diff --git a/hosts/franz/arion/media/arion-pkgs.nix b/hosts/franz/arion/media/arion-pkgs.nix new file mode 100644 index 0000000..69aad13 --- /dev/null +++ b/hosts/franz/arion/media/arion-pkgs.nix @@ -0,0 +1,6 @@ +# Instead of pinning Nixpkgs, we can opt to use the one in NIX_PATH +import { + # We specify the architecture explicitly. Use a Linux remote builder when + # calling arion from other platforms. + system = "x86_64-linux"; +} diff --git a/hosts/franz/arion/media/default.nix b/hosts/franz/arion/media/default.nix new file mode 100644 index 0000000..9654db0 --- /dev/null +++ b/hosts/franz/arion/media/default.nix @@ -0,0 +1,73 @@ +{config, ...}: let + vars = import ../../../../vars.nix; +in { + virtualisation.arion = { + projects.media.settings = { + imports = [./arion-compose.nix]; + }; + }; + + sops.secrets."navidrome/spotify_id" = { + owner = vars.user; + }; + + sops.secrets."navidrome/spotify_secret" = { + owner = vars.user; + }; + sops.secrets."navidrome/lastfm_api_key" = { + owner = vars.user; + }; + sops.secrets."navidrome/lastfm_api_secret" = { + owner = vars.user; + }; + + sops.secrets."windscribe/openvpn_username" = { + owner = vars.user; + }; + sops.secrets."windscribe/openvpn_password" = { + owner = vars.user; + }; + + sops.secrets."unpackerr/sonarr_api_key" = { + owner = vars.user; + }; + sops.secrets."unpackerr/radarr_api_key" = { + owner = vars.user; + }; + sops.secrets."unpackerr/lidarr_api_key" = { + owner = vars.user; + }; + + sops.templates."navidrome.env" = { + path = "/home/${vars.user}/.docker/media/navidrome.env"; + owner = vars.user; + mode = "0775"; + content = '' + ND_SPOTIFY_ID="${config.sops.placeholder."navidrome/spotify_id"}" + ND_SPOTIFY_SECRET="${config.sops.placeholder."navidrome/spotify_secret"}" + ND_LASTFM_APIKEY="${config.sops.placeholder."navidrome/lastfm_api_key"}" + ND_LASTFM_SECRET="${config.sops.placeholder."navidrome/lastfm_api_secret"}" + ''; + }; + + sops.templates."windscribe.env" = { + path = "/home/${vars.user}/.docker/media/windscribe.env"; + owner = vars.user; + mode = "0775"; + content = '' + OPENVPN_USERNAME="${config.sops.placeholder."windscribe/openvpn_username"}" + OPENVPN_PASSWORD="${config.sops.placeholder."windscribe/openvpn_password"}" + ''; + }; + + sops.templates."unpackerr.env" = { + path = "/home/${vars.user}/.docker/media/unpackerr.env"; + owner = vars.user; + mode = "0775"; + content = '' + UN_SONARR_0_API_KEY="${config.sops.placeholder."unpackerr/sonarr_api_key"}" + UN_RADARR_0_API_KEY="${config.sops.placeholder."unpackerr/lidarr_api_key"}" + UN_LIDARR_0_API_KEY="${config.sops.placeholder."unpackerr/radarr_api_key"}" + ''; + }; +}