This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

superconfig / 2configs / services / flix / default.nix
9.8 kB 367 lines
1{ config, pkgs, ... }: 2{ 3 users.users.download = { 4 isSystemUser = true; 5 uid = 1001; 6 group = "download"; 7 }; 8 users.groups.download.members = [ 9 "transmission" 10 "sabnzbd" 11 ]; 12 services.transmission = { 13 enable = true; 14 package = pkgs.transmission_4; 15 home = "/var/state/transmission"; 16 group = "download"; 17 downloadDirPermissions = "775"; 18 settings = { 19 download-dir = "/var/download/transmission"; 20 incomplete-dir-enabled = false; 21 rpc-bind-address = "::"; 22 message-level = 1; 23 umask = 18; 24 rpc-whitelist-enabled = false; 25 rpc-host-whitelist-enabled = false; 26 # stop seeding after reaching 5.0 ratio 27 ratio-limit = 5; 28 ratio-limit-enabled = true; 29 # limit concurrent seeding to reduce resource usage 30 seed-queue-enabled = true; 31 seed-queue-size = 20; 32 }; 33 }; 34 35 # garbage collection for old torrents 36 systemd.services.transmission-gc = { 37 description = "Remove old completed torrents from Transmission"; 38 after = [ "transmission.service" ]; 39 path = [ 40 pkgs.transmission_4 41 pkgs.jq 42 pkgs.coreutils 43 pkgs.gawk 44 pkgs.gnugrep 45 pkgs.findutils 46 ]; 47 script = '' 48 set -efu 49 TRANSMISSION_HOST="128.0.0.1:9091" 50 MAX_AGE_DAYS=30 51 MIN_RATIO=5.0 52 53 # get list of all torrents as JSON 54 torrents=$(transmission-remote "$TRANSMISSION_HOST" -l 2>/dev/null | tail -n +2 | head -n -1 || true) 55 56 if [ -z "$torrents" ]; then 57 echo "No torrents found" 58 exit 0 59 fi 60 61 # process each torrent 62 echo "$torrents" | while read -r line; do 63 id=$(echo "$line" | awk '{print $1}' | tr -d '*') 64 # skip if not a valid ID 65 [ -z "$id" ] || [ "$id" = "ID" ] && continue 66 67 # get torrent info 68 info=$(transmission-remote "$TRANSMISSION_HOST" -t "$id" -i 2>/dev/null || continue) 69 70 # extract ratio and completion status 71 ratio=$(echo "$info" | grep "Ratio:" | awk '{print $2}') 72 percent=$(echo "$info" | grep "Percent Done:" | awk '{print $3}' | tr -d '%') 73 state=$(echo "$info" | grep "State:" | cut -d: -f2- | xargs) 74 75 # skip if not 100% complete 76 [ "$percent" != "100" ] && continue 77 78 # check if ratio reached 79 ratio_reached=false 80 if [ -n "$ratio" ] && [ "$ratio" != "None" ]; then 81 if awk "BEGIN {exit !($ratio >= $MIN_RATIO)}"; then 82 ratio_reached=true 83 fi 84 fi 85 86 # check age via date added 87 date_added=$(echo "$info" | grep "Date added:" | cut -d: -f2- | xargs) 88 if [ -n "$date_added" ]; then 89 added_epoch=$(date -d "$date_added" +%s 2>/dev/null || echo 0) 90 now_epoch=$(date +%s) 91 age_days=$(( (now_epoch - added_epoch) / 86400 )) 92 else 93 age_days=0 94 fi 95 96 # remove if ratio reached OR older than max age 97 if [ "$ratio_reached" = "true" ]; then 98 echo "Removing torrent $id (ratio: $ratio >= $MIN_RATIO)" 99 transmission-remote "$TRANSMISSION_HOST" -t "$id" --remove-and-delete 100 elif [ "$age_days" -ge "$MAX_AGE_DAYS" ]; then 101 echo "Removing torrent $id (age: $age_days days >= $MAX_AGE_DAYS)" 102 transmission-remote "$TRANSMISSION_HOST" -t "$id" --remove-and-delete 103 fi 104 done 105 ''; 106 serviceConfig = { 107 Type = "oneshot"; 108 User = "transmission"; 109 }; 110 }; 111 112 systemd.timers.transmission-gc = { 113 wantedBy = [ "timers.target" ]; 114 timerConfig = { 115 OnCalendar = "daily"; 116 Persistent = true; 117 RandomizedDelaySec = "1h"; 118 }; 119 }; 120 systemd.services.transmission-watcher = { 121 wantedBy = [ "multi-user.target" ]; 122 startAt = "*:0/5"; 123 path = [ 124 pkgs.curl 125 pkgs.systemdMinimal 126 ]; 127 script = '' 128 set -efu -o pipefail 129 # don't restart if transmission is currently starting or stopping 130 state=$(systemctl show -p ActiveState --value transmission.service) 131 if [ "$state" = "activating" ] || [ "$state" = "deactivating" ]; then 132 echo "transmission is $state, skipping" 133 exit 0 134 fi 135 # check if transmission responds (with timeout) 136 if ! curl -SsfL --max-time 10 http://transmission.r; then 137 echo "transmission not responding, restarting" 138 systemctl restart transmission.service 139 fi 140 ''; 141 }; 142 143 security.acme.defaults.email = "spam@krebsco.de"; 144 security.acme.acceptTerms = true; 145 security.acme.certs."yellow.r".server = config.krebs.ssl.acmeURL; 146 security.acme.certs."jelly.r".server = config.krebs.ssl.acmeURL; 147 security.acme.certs."radar.r".server = config.krebs.ssl.acmeURL; 148 security.acme.certs."sonar.r".server = config.krebs.ssl.acmeURL; 149 security.acme.certs."transmission.r".server = config.krebs.ssl.acmeURL; 150 services.nginx = { 151 enable = true; 152 package = pkgs.nginx.override { 153 modules = with pkgs.nginxModules; [ 154 fancyindex 155 ]; 156 }; 157 virtualHosts."yellow.r" = { 158 serverAliases = [ "flix.r" ]; 159 default = true; 160 enableACME = true; 161 addSSL = true; 162 locations."/" = { 163 root = "/var/download"; 164 extraConfig = '' 165 fancyindex on; 166 include ${pkgs.nginx}/conf/mime.types; 167 include ${pkgs.writeText "extrMime" '' 168 types { 169 video/webm mkv; 170 } 171 ''}; 172 create_full_put_path on; 173 ''; 174 }; 175 176 }; 177 virtualHosts."jelly.r" = { 178 enableACME = true; 179 addSSL = true; 180 locations."/".extraConfig = '' 181 proxy_pass http://localhost:8096/; 182 proxy_set_header Accept-Encoding ""; 183 ''; 184 }; 185 virtualHosts."transmission.r" = { 186 enableACME = true; 187 addSSL = true; 188 locations."/" = { 189 proxyWebsockets = true; 190 proxyPass = "http://128.0.0.1:9091"; 191 }; 192 }; 193 virtualHosts."radar.r" = { 194 enableACME = true; 195 addSSL = true; 196 locations."/" = { 197 proxyWebsockets = true; 198 proxyPass = "http://localhost:7878"; 199 }; 200 }; 201 virtualHosts."sonar.r" = { 202 enableACME = true; 203 addSSL = true; 204 locations."/" = { 205 proxyWebsockets = true; 206 proxyPass = "http://localhost:8989"; 207 # sonar.r now has forced authentication 208 extraConfig = '' 209 proxy_set_header Authorization "Basic a3JlYnM6YWlkc2JhbGxz"; 210 ''; 211 }; 212 }; 213 }; 214 215 services.samba = { 216 enable = true; 217 enableNmbd = false; 218 settings.global = { 219 "hosts allow" = "42::/16 10.243.0.0/16 10.244.0.0/16 fdcc:c5da:5295:c853:d499::/80"; 220 "use sendfile" = "true"; 221 "disable netbios" = "true"; 222 "mangled names" = "illegal"; 223 "socket options" = "TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=65536 SO_SNDBUF=65536"; 224 "load printers" = "false"; 225 "disable spoolss" = "true"; 226 "printcap name" = "/dev/null"; 227 "map to guest" = "Bad User"; 228 "max log size" = "50"; 229 "dns proxy" = "no"; 230 "security" = "user"; 231 "syslog only" = "yes"; 232 }; 233 shares.public = { 234 comment = "Warez"; 235 path = "/var/download"; 236 public = "yes"; 237 "only guest" = "yes"; 238 "create mask" = "0644"; 239 "directory mask" = "2777"; 240 writable = "no"; 241 printable = "no"; 242 }; 243 }; 244 245 networking.firewall.allowedTCPPorts = [ 246 80 # nginx 247 443 # nginx 248 9091 # transmission web 249 8096 # jellyfin 250 8920 # jellyfin 251 51413 # transmission traffic 252 445 # smbd 253 111 # smbd 254 2049 # smbd 255 4000 # smbd 256 4001 # smbd 257 4002 # smbd 258 ]; 259 networking.firewall.allowedUDPPorts = [ 260 51413 # transmission traffic 261 1900 # jellyfin 262 7359 # jellyfin 263 111 # smbd 264 2049 # smbd 265 4000 # smbd 266 4001 # smbd 267 4002 # smbd 268 ]; 269 krebs.iptables = { 270 enable = true; 271 tables.nat.PREROUTING.rules = [ 272 # transmission rpc port 273 { 274 predicate = "-i retiolum -p tcp --dport 9091"; 275 target = "DNAT --to-destination fdb4:3310:947::2"; 276 v4 = false; 277 } 278 ]; 279 tables.filter.FORWARD.policy = "ACCEPT"; # we need this so we can forward into the the transmission network namespace 280 }; 281 282 systemd.services.flix-index = { 283 wantedBy = [ "multi-user.target" ]; 284 path = [ 285 pkgs.coreutils 286 pkgs.findutils 287 pkgs.inotify-tools 288 ]; 289 startAt = "hourly"; 290 serviceConfig = { 291 Type = "oneshot"; 292 ExecStart = pkgs.writers.writeDash "flix-index" '' 293 set -efu 294 index(){ 295 find . -type f > "$DIR"/index.tmp 296 mv "$DIR"/index.tmp "$DIR"/index 297 } 298 299 DIR=/var/download 300 cd "$DIR" 301 index 302 ''; 303 }; 304 }; 305 306 services.jellyfin = { 307 enable = true; 308 group = "download"; 309 }; 310 311 # request managment 312 services.jellyseerr = { 313 enable = true; 314 openFirewall = true; 315 }; 316 317 # movies 318 services.radarr = { 319 enable = true; 320 openFirewall = true; 321 user = "download"; 322 group = "download"; 323 }; 324 325 # shows 326 services.sonarr = { 327 enable = true; 328 openFirewall = true; 329 user = "download"; 330 group = "download"; 331 }; 332 # sonarr needs unsecure packages 333 nixpkgs.config.permittedInsecurePackages = [ 334 "aspnetcore-runtime-wrapped-6.0.36" 335 "aspnetcore-runtime-6.0.36" 336 "dotnet-sdk-wrapped-6.0.428" 337 "dotnet-sdk-6.0.428" 338 "olm-3.2.16" 339 ]; 340 341 # indexers 342 services.prowlarr = { 343 enable = true; 344 openFirewall = true; 345 }; 346 347 # flaresolverr for bypassing cloudflare on some indexers 348 services.flaresolverr = { 349 enable = true; 350 openFirewall = true; 351 }; 352 353 # subtitles 354 services.bazarr = { 355 enable = true; 356 openFirewall = true; 357 user = "download"; 358 group = "download"; 359 }; 360 361 # usenet download client 362 services.sabnzbd = { 363 enable = true; 364 group = "download"; 365 openFirewall = true; 366 }; 367}