feat: add nixarr

This commit is contained in:
Moritz Böhme 2025-08-25 21:09:59 +02:00
parent e6cae70857
commit 974b872e83
No known key found for this signature in database
GPG key ID: 970C6E89EB0547A9
42 changed files with 1161 additions and 4 deletions

View file

@ -0,0 +1,73 @@
{
pkgs,
config,
lib,
...
}: let
cfg = config.nixarr.autobrr;
createAdminUser = pkgs.writeShellApplication {
name = "create-admin-user";
runtimeInputs = [config.nixarr.autobrr.package];
text = ''
file="${cfg.stateDir}/admin-created"
if [ ! -f $file ]; then
autobrrctl --config "${cfg.stateDir}" create-user admin < "${config.clan.core.vars.generators.nixarr-autobrr.files.password.path}"
touch "$file"
fi
'';
};
in {
clan.core.vars.generators."nixarr-autobrr" = {
prompts.password = {
type = "hidden";
persist = true;
description = "Leave empty to generate automatically";
};
files.password = {};
runtimeInputs = [
pkgs.coreutils
pkgs.xkcdpass
];
script = ''
prompt_value="$(cat "$prompts/password")"
if [[ -n "''${prompt_value-}" ]]; then
echo "$prompt_value" | tr -d "\n" > "$out"/password
else
xkcdpass --numwords 4 --delimiter - --count 1 | tr -d "\n" > "$out"/password
fi
'';
};
systemd.services.autobrr-setup = {
description = "Setup autobrr user";
wantedBy = ["default.target"];
requires = ["autobrr.service"];
after = ["autobrr.service"];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = lib.getExe createAdminUser;
};
};
nixarr.autobrr = {
enable = true;
vpn.enable = true;
settings = {
checkForUpdates = false;
port = 7474;
host = lib.mkForce "192.168.15.1";
logLevel = "INFO";
};
};
services.nginx.virtualHosts."autobrr.moritz.place" = {
forceSSL = true;
useACMEHost = "any.moritz.place";
locations."/" = {
proxyPass = "http://192.168.15.1:${builtins.toString config.nixarr.autobrr.settings.port}";
};
};
}

View file

@ -0,0 +1,33 @@
{
inputs,
config,
...
}: {
imports = [
inputs.nixarr.nixosModules.default
./autobrr.nix
./jellyfin.nix
./jellyseerr.nix
./ntfy.nix
./prowlarr.nix
./radarr.nix
./recyclarr.nix
./sonarr.nix
./transmission.nix
];
nixarr = {
enable = true;
stateDir = "/var/lib/nixarr";
mediaDir = "/data/nixarr";
vpn = {
enable = true;
wgConf = config.clan.core.vars.generators.nixarr-vpn.files.config.path;
};
};
clan.core.vars.generators."nixarr-vpn" = {
prompts.config.type = "multiline";
prompts.config.persist = true;
};
}

View file

@ -0,0 +1,49 @@
{
config,
lib,
pkgs,
...
}: {
nixarr.jellyfin = {
# NOTE: cannot set password so just set the generated one manually
enable = true;
};
services.nginx.virtualHosts."jellyfin.moritz.place" = {
forceSSL = true;
useACMEHost = "any.moritz.place";
locations."/" = {
proxyPass = "http://127.0.0.1:8096";
};
};
# 1. enable vaapi on OS-level
systemd.services.jellyfin.environment.LIBVA_DRIVER_NAME = "iHD"; # Or "i965" if using older driver
environment.sessionVariables = {LIBVA_DRIVER_NAME = "iHD";}; # Same here
hardware.graphics = {
enable = true;
extraPackages = with pkgs; [
intel-media-driver # For Broadwell (2014) or newer processors. LIBVA_DRIVER_NAME=iHD
libva-vdpau-driver # Previously vaapiVdpau
intel-compute-runtime # OpenCL filter support (hardware tonemapping and subtitle burn-in)
vpl-gpu-rt # QSV on 11th gen or newer
intel-ocl # OpenCL support
];
};
nixpkgs.config.allowUnfreePredicate = pkg:
builtins.elem (lib.getName pkg) [
"intel-ocl"
];
clan.core.vars.generators."nixarr-ds-share".prompts.config = {
type = "multiline";
persist = true;
};
fileSystems."/mnt/ds_media" = {
device = "//192.168.0.2/media/";
fsType = "cifs";
options = let
# this line prevents hanging on network split
automount_opts = "x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s";
in ["${automount_opts},credentials=${config.clan.core.vars.generators.nixarr-ds-share.files.config.path},gid=${builtins.toString config.users.groups.media.gid}"];
};
}

View file

@ -0,0 +1,17 @@
{
pkgs,
config,
...
}: {
nixarr.jellyseerr = {
# NOTE: cannot set password so just set the generated one manually
enable = true;
};
services.nginx.virtualHosts."jellyseerr.moritz.place" = {
forceSSL = true;
useACMEHost = "any.moritz.place";
locations."/" = {
proxyPass = "http://127.0.0.1:5055";
};
};
}

View file

@ -0,0 +1,72 @@
{
pkgs,
config,
lib,
...
}: let
createAdminUser = pkgs.writeShellApplication {
name = "create-admin-user";
runtimeInputs = [config.services.ntfy-sh.package];
text = ''
file="/var/lib/ntfy-sh/admin-created"
if [ ! -f $file ]; then
NTFY_PASSWORD="$(cat "${config.clan.core.vars.generators.ntfy.files.password.path}")" ntfy user add --role=admin admin
touch "$file"
fi
'';
};
in {
clan.core.vars.generators."ntfy" = {
prompts.password = {
type = "hidden";
persist = true;
description = "Leave empty to generate automatically";
};
files.password = {};
runtimeInputs = [
pkgs.coreutils
pkgs.xkcdpass
];
script = ''
prompt_value="$(cat "$prompts/password")"
if [[ -n "''${prompt_value-}" ]]; then
echo "$prompt_value" | tr -d "\n" > "$out"/password
else
xkcdpass --numwords 4 --delimiter - --count 1 | tr -d "\n" > "$out"/password
fi
'';
};
services.ntfy-sh = {
enable = true;
settings = {
base-url = "https://ntfy.moritz.place";
listen-http = ":2586";
behind-proxy = true;
auth-default-access = "deny-all";
};
};
systemd.services.ntfy-sh-setup = {
description = "Setup ntfy user";
wantedBy = ["default.target"];
requires = ["ntfy-sh.service"];
after = ["ntfy-sh.service"];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = lib.getExe createAdminUser;
};
};
services.nginx.virtualHosts."ntfy.moritz.place" = {
forceSSL = true;
useACMEHost = "any.moritz.place";
locations."/" = {
proxyPass = "http://127.0.0.1:2586";
proxyWebsockets = true;
};
};
}

View file

@ -0,0 +1,46 @@
{
config,
pkgs,
...
}: {
clan.core.vars.generators."nixarr-prowlarr" = {
prompts.password = {
type = "hidden";
persist = true;
description = "Leave empty to generate automatically";
};
files.password.deploy = false;
runtimeInputs = [
pkgs.coreutils
pkgs.xkcdpass
];
script = ''
prompt_value="$(cat "$prompts/password")"
if [[ -n "''${prompt_value-}" ]]; then
echo "$prompt_value" | tr -d "\n" > "$out"/password
else
xkcdpass --numwords 4 --delimiter - --count 1 | tr -d "\n" > "$out"/password
fi
'';
};
nixarr.prowlarr = {
# NOTE: cannot set password so just set the generated one manually
enable = true;
vpn.enable = true;
};
services.flaresolverr.enable = true;
systemd.services.flaresolverr.vpnConfinement = {
enable = true;
vpnNamespace = "wg";
};
services.nginx.virtualHosts."prowlarr.moritz.place" = {
forceSSL = true;
useACMEHost = "any.moritz.place";
locations."/" = {
proxyPass = "http://127.0.0.1:${builtins.toString config.nixarr.prowlarr.port}";
};
};
}

View file

@ -0,0 +1,48 @@
{
pkgs,
config,
...
}: {
clan.core.vars.generators."nixarr-radarr" = {
prompts.password = {
type = "hidden";
persist = true;
description = "Leave empty to generate automatically";
};
files.password.deploy = false;
runtimeInputs = [
pkgs.coreutils
pkgs.xkcdpass
];
script = ''
prompt_value="$(cat "$prompts/password")"
if [[ -n "''${prompt_value-}" ]]; then
echo "$prompt_value" | tr -d "\n" > "$out"/password
else
xkcdpass --numwords 4 --delimiter - --count 1 | tr -d "\n" > "$out"/password
fi
'';
};
nixarr.radarr = {
# NOTE: cannot set password so just set the generated one manually
enable = true;
};
services.nginx.virtualHosts."radarr.moritz.place" = {
forceSSL = true;
useACMEHost = "any.moritz.place";
locations."/" = {
proxyPass = "http://127.0.0.1:7878";
};
};
fileSystems."/mnt/ds_movies" = {
device = "//192.168.0.2/media/movies";
fsType = "cifs";
options = let
# this line prevents hanging on network split
automount_opts = "x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s";
in ["${automount_opts},credentials=${config.clan.core.vars.generators.nixarr-ds-share.files.config.path},gid=${builtins.toString config.users.groups.media.gid},uid=${builtins.toString config.users.users.radarr.uid}"];
};
}

View file

@ -0,0 +1,284 @@
{pkgs, ...}: {
nixarr.recyclarr = {
# NOTE: cannot set password so just set the generated one manually
enable = true;
configFile = pkgs.writeTextFile {
name = "config.yaml";
text =
/*
yaml
*/
''
radarr:
movies:
api_key: !env_var RADARR_API_KEY
base_url: http://127.0.0.1:7878
delete_old_custom_formats: true
quality_definition:
type: movie
media_naming:
folder: default
movie:
rename: true
standard: default
include:
# Comment out any of the following includes to disable them
- template: radarr-quality-definition-movie
- template: radarr-quality-profile-hd-bluray-web
- template: radarr-custom-formats-hd-bluray-web
- template: radarr-quality-definition-movie
- template: radarr-quality-profile-uhd-bluray-web
- template: radarr-custom-formats-uhd-bluray-web
- template: radarr-quality-definition-anime
- template: radarr-quality-profile-anime
- template: radarr-custom-formats-anime
custom_formats:
# Movie Versions
- trash_ids:
# Uncomment any of the following lines to prefer these movie versions
# - 570bc9ebecd92723d2d21500f4be314c # Remaster
# - eca37840c13c6ef2dd0262b141a5482f # 4K Remaster
# - e0c07d59beb37348e975a930d5e50319 # Criterion Collection
# - 9d27d9d2181838f76dee150882bdc58c # Masters of Cinema
# - db9b4c4b53d312a3ca5f1378f6440fc9 # Vinegar Syndrome
# - 957d0f44b592285f26449575e8b1167e # Special Edition
# - eecf3a857724171f968a66cb5719e152 # IMAX
# - 9f6cbff8cfe4ebbc1bde14c7b7bec0de # IMAX Enhanced
assign_scores_to:
- name: HD Bluray + WEB
# Optional
- trash_ids:
# - b6832f586342ef70d9c128d40c07b872 # Bad Dual Groups
# - cc444569854e9de0b084ab2b8b1532b2 # Black and White Editions
# - ae9b7c9ebde1f3bd336a8cbd1ec4c5e5 # No-RlsGroup
# - 7357cf5161efbf8c4d5d0c30b4815ee2 # Obfuscated
# - 5c44f52a8714fdd79bb4d98e2673be1f # Retags
# - f537cf427b64c38c8e36298f657e4828 # Scene
assign_scores_to:
- name: HD Bluray + WEB
- trash_ids:
# Uncomment the next six lines to allow x265 HD releases with HDR/DV
- dc98083864ea246d05a42df0d05f81cc # x265 (HD)
assign_scores_to:
- name: HD Bluray + WEB
score: 0
- trash_ids:
- 839bea857ed2c0a8e084f3cbdbd65ecb # x265 (no HDR/DV)
assign_scores_to:
- name: HD Bluray + WEB
# Audio
- trash_ids:
# Uncomment the next section to enable Advanced Audio Formats
# - 496f355514737f7d83bf7aa4d24f8169 # TrueHD Atmos
# - 2f22d89048b01681dde8afe203bf2e95 # DTS X
# - 417804f7f2c4308c1f4c5d380d4c4475 # ATMOS (undefined)
# - 1af239278386be2919e1bcee0bde047e # DD+ ATMOS
# - 3cafb66171b47f226146a0770576870f # TrueHD
# - dcf3ec6938fa32445f590a4da84256cd # DTS-HD MA
# - a570d4a0e56a2874b64e5bfa55202a1b # FLAC
# - e7c2fcae07cbada050a0af3357491d7b # PCM
# - 8e109e50e0a0b83a5098b056e13bf6db # DTS-HD HRA
# - 185f1dd7264c4562b9022d963ac37424 # DD+
# - f9f847ac70a0af62ea4a08280b859636 # DTS-ES
# - 1c1a4c5e823891c75bc50380a6866f73 # DTS
# - 240770601cc226190c367ef59aba7463 # AAC
# - c2998bd0d90ed5621d8df281e839436e # DD
assign_scores_to:
- name: UHD Bluray + WEB
# Movie Versions
- trash_ids:
# Uncomment any of the following lines to prefer these movie versions
# - 570bc9ebecd92723d2d21500f4be314c # Remaster
# - eca37840c13c6ef2dd0262b141a5482f # 4K Remaster
# - e0c07d59beb37348e975a930d5e50319 # Criterion Collection
# - 9d27d9d2181838f76dee150882bdc58c # Masters of Cinema
# - db9b4c4b53d312a3ca5f1378f6440fc9 # Vinegar Syndrome
# - 957d0f44b592285f26449575e8b1167e # Special Edition
# - eecf3a857724171f968a66cb5719e152 # IMAX
# - 9f6cbff8cfe4ebbc1bde14c7b7bec0de # IMAX Enhanced
assign_scores_to:
- name: UHD Bluray + WEB
# Optional
- trash_ids:
# - b6832f586342ef70d9c128d40c07b872 # Bad Dual Groups
# - cc444569854e9de0b084ab2b8b1532b2 # Black and White Editions
# - ae9b7c9ebde1f3bd336a8cbd1ec4c5e5 # No-RlsGroup
# - 7357cf5161efbf8c4d5d0c30b4815ee2 # Obfuscated
# - 5c44f52a8714fdd79bb4d98e2673be1f # Retags
# - f537cf427b64c38c8e36298f657e4828 # Scene
assign_scores_to:
- name: UHD Bluray + WEB
- trash_ids:
# Uncomment the next six lines to allow x265 HD releases with HDR/DV
- dc98083864ea246d05a42df0d05f81cc # x265 (HD)
assign_scores_to:
- name: UHD Bluray + WEB
score: 0
- trash_ids:
- 839bea857ed2c0a8e084f3cbdbd65ecb # x265 (no HDR/DV)
assign_scores_to:
- name: UHD Bluray + WEB
- trash_ids:
# Comment out the next line if you and all of your users' setups are fully DV compatible
- 923b6abef9b17f937fab56cfcf89e1f1 # DV (WEBDL)
# HDR10+ Boost - Uncomment the next two lines if any of your devices DO support HDR10+
# - b17886cb4158d9fea189859409975758 # HDR10Plus Boost
# - 55a5b50cb416dea5a50c4955896217ab # DV HDR10+ Boost
assign_scores_to:
- name: UHD Bluray + WEB
# Optional SDR
# Only ever use ONE of the following custom formats:
# SDR - block ALL SDR releases
# SDR (no WEBDL) - block UHD/4k Remux and Bluray encode SDR releases, but allow SDR WEB
- trash_ids:
# - 9c38ebb7384dada637be8899efa68e6f # SDR
- 25c12f78430a3a23413652cbd1d48d77 # SDR (no WEBDL)
assign_scores_to:
- name: UHD Bluray + WEB
# Anime
- trash_ids:
- 064af5f084a0a24458cc8ecd3220f93f # Uncensored
assign_scores_to:
- name: Remux-1080p - Anime
score: 0 # Adjust scoring as desired
- trash_ids:
- a5d148168c4506b55cf53984107c396e # 10bit
assign_scores_to:
- name: Remux-1080p - Anime
score: 0 # Adjust scoring as desired
- trash_ids:
- 4a3b087eea2ce012fcc1ce319259a3be # Anime Dual Audio
assign_scores_to:
- name: Remux-1080p - Anime
score: 0 # Adjust scoring as desired
sonarr:
series:
api_key: !env_var SONARR_API_KEY
base_url: http://127.0.0.1:8989
delete_old_custom_formats: true
quality_definition:
type: series
media_naming:
series: default
season: default
episodes:
rename: true
standard: default
daily: default
anime: default
include:
# Comment out any of the following includes to disable them
- template: sonarr-quality-definition-series
- template: sonarr-v4-quality-profile-web-1080p
- template: sonarr-v4-custom-formats-web-1080p
- template: sonarr-quality-definition-series
- template: sonarr-v4-quality-profile-web-2160p
- template: sonarr-v4-custom-formats-web-2160p
- template: sonarr-quality-definition-anime
- template: sonarr-v4-quality-profile-anime
- template: sonarr-v4-custom-formats-anime
# Custom Formats: https://recyclarr.dev/wiki/yaml/config-reference/custom-formats/
custom_formats:
# Optional
- trash_ids:
# - 32b367365729d530ca1c124a0b180c64 # Bad Dual Groups
# - 82d40da2bc6923f41e14394075dd4b03 # No-RlsGroup
# - e1a997ddb54e3ecbfe06341ad323c458 # Obfuscated
# - 06d66ab109d4d2eddb2794d21526d140 # Retags
# - 1b3994c551cbb92a2c781af061f4ab44 # Scene
assign_scores_to:
- name: WEB-1080p
- trash_ids:
# Uncomment the next six lines to allow x265 HD releases with HDR/DV
- 47435ece6b99a0b477caf360e79ba0bb # x265 (HD)
assign_scores_to:
- name: WEB-1080p
score: 0
- trash_ids:
- 9b64dff695c2115facf1b6ea59c9bd07 # x265 (no HDR/DV)
assign_scores_to:
- name: WEB-1080p
# HDR Formats
- trash_ids:
# Comment out the next line if you and all of your users' setups are fully DV compatible
- 9b27ab6498ec0f31a3353992e19434ca # DV (WEBDL)
# HDR10+ Boost - Uncomment the next two lines if any of your devices DO support HDR10+
# - 0dad0a507451acddd754fe6dc3a7f5e7 # HDR10+ Boost
# - 385e9e8581d33133c3961bdcdeffb7b4 # DV HDR10+ Boost
assign_scores_to:
- name: WEB-2160p
# Optional
- trash_ids:
# - 32b367365729d530ca1c124a0b180c64 # Bad Dual Groups
# - 82d40da2bc6923f41e14394075dd4b03 # No-RlsGroup
# - e1a997ddb54e3ecbfe06341ad323c458 # Obfuscated
# - 06d66ab109d4d2eddb2794d21526d140 # Retags
# - 1b3994c551cbb92a2c781af061f4ab44 # Scene
assign_scores_to:
- name: WEB-2160p
- trash_ids:
# Uncomment the next six lines to allow x265 HD releases with HDR/DV
- 47435ece6b99a0b477caf360e79ba0bb # x265 (HD)
assign_scores_to:
- name: WEB-2160p
score: 0
- trash_ids:
- 9b64dff695c2115facf1b6ea59c9bd07 # x265 (no HDR/DV)
assign_scores_to:
- name: WEB-2160p
# Optional SDR
# Only ever use ONE of the following custom formats:
# SDR - block ALL SDR releases
# SDR (no WEBDL) - block UHD/4k Remux and Bluray encode SDR releases, but allow SDR WEB
- trash_ids:
# - 2016d1676f5ee13a5b7257ff86ac9a93 # SDR
- 83304f261cf516bb208c18c54c0adf97 # SDR (no WEBDL)
assign_scores_to:
- name: WEB-2160p
# Anime
- trash_ids:
- 026d5aadd1a6b4e550b134cb6c72b3ca # Uncensored
assign_scores_to:
- name: Remux-1080p - Anime
score: 0 # Adjust scoring as desired
- trash_ids:
- b2550eb333d27b75833e25b8c2557b38 # 10bit
assign_scores_to:
- name: Remux-1080p - Anime
score: 0 # Adjust scoring as desired
- trash_ids:
- 418f50b10f1907201b6cfdf881f467b7 # Anime Dual Audio
assign_scores_to:
- name: Remux-1080p - Anime
score: 0 # Adjust scoring as desired
'';
};
};
}

View file

@ -0,0 +1,48 @@
{
pkgs,
config,
...
}: {
clan.core.vars.generators."nixarr-sonarr" = {
prompts.password = {
type = "hidden";
persist = true;
description = "Leave empty to generate automatically";
};
files.password.deploy = false;
runtimeInputs = [
pkgs.coreutils
pkgs.xkcdpass
];
script = ''
prompt_value="$(cat "$prompts/password")"
if [[ -n "''${prompt_value-}" ]]; then
echo "$prompt_value" | tr -d "\n" > "$out"/password
else
xkcdpass --numwords 4 --delimiter - --count 1 | tr -d "\n" > "$out"/password
fi
'';
};
nixarr.sonarr = {
# NOTE: cannot set password so just set the generated one manually
enable = true;
};
services.nginx.virtualHosts."sonarr.moritz.place" = {
forceSSL = true;
useACMEHost = "any.moritz.place";
locations."/" = {
proxyPass = "http://127.0.0.1:8989";
};
};
fileSystems."/mnt/ds_tv" = {
device = "//192.168.0.2/media/tv";
fsType = "cifs";
options = let
# this line prevents hanging on network split
automount_opts = "x-systemd.automount,noauto,x-systemd.idle-timeout=60,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s";
in ["${automount_opts},credentials=${config.clan.core.vars.generators.nixarr-ds-share.files.config.path},gid=${builtins.toString config.users.groups.media.gid},uid=${builtins.toString config.users.users.sonarr.uid}"];
};
}

View file

@ -0,0 +1,106 @@
{
inputs,
config,
pkgs,
lib,
...
}: let
transmissionUserName = "admin";
in {
imports = [inputs.nixarr.nixosModules.default];
clan.core.vars.generators."nixarr-transmission" = {
prompts.password = {
type = "hidden";
persist = true;
description = "Leave empty to generate automatically";
};
files.credentialsFile = {};
files.password.deploy = false;
files.cross-seed-credentialsFile = {};
runtimeInputs = [
pkgs.coreutils
pkgs.xkcdpass
pkgs.mkpasswd
pkgs.openssl
];
script = ''
prompt_value="$(cat "$prompts/password")"
if [[ -n "''${prompt_value-}" ]]; then
echo "$prompt_value" | tr -d "\n" > "$out"/password
else
xkcdpass --numwords 4 --delimiter - --count 1 | tr -d "\n" > "$out"/password
fi
PASS="$(cat "$out/password")"
SALT="$(openssl rand -hex 4)"
HASH="$(echo -n "$PASS$SALT" | sha1sum | cut -d" " -f 1)"
echo "{\"rpc-password\": \"{$HASH$SALT\", \"rpc-authentication-required\": true, \"rpc-username\": \"${transmissionUserName}\"}" > $out/credentialsFile
echo "{\"transmissionRpcUrl\": \"http://admin:$PASS@localhost:9091/transmission/rpc\"}" > $out/cross-seed-credentialsFile
'';
};
nixarr.transmission = {
enable = true;
vpn.enable = true;
peerPort = 39350;
credentialsFile = config.clan.core.vars.generators.nixarr-transmission.files.credentialsFile.path;
};
services.nginx.virtualHosts."torrent.moritz.place" = {
forceSSL = true;
useACMEHost = "any.moritz.place";
locations."/" = {
proxyPass = "http://127.0.0.1:${builtins.toString config.nixarr.transmission.uiPort}";
};
};
nixarr.transmission.privateTrackers.cross-seed = {
enable = true;
extraSettings = {
delay = 30;
matchMode = "partial";
skipRecheck = true;
autoResumeMaxDownload = 52428800;
ignoreNonRelevantFilesToResume = false;
linkDirs = [
"${config.nixarr.mediaDir}/torrents/.linking"
];
excludeOlder = "2 weeks";
excludeRecentSearch = "3 days";
searchCadence = "1 day";
snatchTimeout = "30 seconds";
searchTimeout = "2 minutes";
};
indexIds = [
4
1
];
};
systemd.services.cross-seed = {
serviceConfig = {
ExecStartPre = let
cross-seed-credentialsFile = config.clan.core.vars.generators.nixarr-transmission.files.cross-seed-credentialsFile.path;
cfg = config.util-nixarr.services.cross-seed;
in
lib.mkAfter [
(
"+"
+ pkgs.writeShellScript "transmission-prestart-custom" ''
tmp="$(mktemp)"
${pkgs.jq}/bin/jq --slurp add '${cfg.dataDir}/config.json' '${cross-seed-credentialsFile}' > "$tmp"
install -D -m 600 -o '${cfg.user}' "$tmp" '${cfg.dataDir}/config.json'
rm -rf "$tmp"
''
)
];
};
};
systemd.tmpfiles.rules = let
cfg = config.nixarr;
in lib.mkAfter [
"d '${cfg.mediaDir}/torrents/.linking' 0750 cross-seed cross-seed - -"
"d '${cfg.mediaDir}/torrents/.cross-seed' 0750 cross-seed cross-seed - -"
];
}