aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Audron <audron@cocaine.farm>2024-02-07 14:46:29 +0000
committerMax Audron <audron@cocaine.farm>2024-02-07 17:27:40 +0000
commit44ee565dfcf908df660751351d00caeb2ba39bc8 (patch)
tree43a11284abc04d0657901f56e579dd86166814da
parentupdate authentik (diff)
migrate tlmp setup to nixos
-rw-r--r--modules/tlmp/default.nix80
-rw-r--r--modules/tlmp/rtorrent.nix42
-rw-r--r--modules/tlmp/rtorrent.rc100
-rw-r--r--modules/tlmp/rutorrent.nix43
-rw-r--r--modules/tlmp/sonarr.nix57
5 files changed, 265 insertions, 57 deletions
diff --git a/modules/tlmp/default.nix b/modules/tlmp/default.nix
index e653b29..e9f286f 100644
--- a/modules/tlmp/default.nix
+++ b/modules/tlmp/default.nix
@@ -2,7 +2,7 @@
with self.lib.nginx;
{
- imports = [ ./rutorrent.nix ];
+ imports = [ ./rutorrent.nix ./rtorrent.nix ];
security.acme.certs = {
"media.cocaine.farm" = {
@@ -10,7 +10,37 @@ with self.lib.nginx;
};
};
- services.jellyfin.enable = true;
+ users = {
+ users.media = {
+ isSystemUser = true;
+ group = "media";
+ };
+ groups.media = {};
+ };
+
+ services.jellyfin = {
+ enable = true;
+ user = "media";
+ group = "media";
+ };
+
+ services.radarr = {
+ enable = true;
+ user = "media";
+ group = "media";
+ };
+
+ services.sonarr = {
+ enable = true;
+ package = pkgs.callPackage ./sonarr.nix {};
+ user = "media";
+ group = "media";
+ };
+
+ services.prowlarr = {
+ enable = true;
+ };
+
services.jackett =
let jackett = pkgs.jackett.overrideAttrs (prev: {
doCheck = false;
@@ -24,43 +54,47 @@ with self.lib.nginx;
services.rutorrent = {
enable = true;
hostName = "torrent.media.cocaine.farm";
- rpcSocket = "10.101.131.197";
plugins = lib.mkForce [ "data" "diskspace" "edit" "erasedata" "theme" "trafic" ];
nginx.enable = true;
};
+ virtualisation.oci-containers.containers = {
+ flaresolverr = {
+ image = "ghcr.io/flaresolverr/flaresolverr:v3.3.13";
+ autoStart = true;
+ ports = [
+ "10.10.0.2:8191:8191"
+ ];
+ };
+ };
+
services.nginx = {
enable = true;
virtualHosts = {
"media.cocaine.farm" = (proxyDomain "media.cocaine.farm" "http://127.0.0.1:8096/");
- "sonarr.media.cocaine.farm" = proxyDomainAuth "media.cocaine.farm" "http://10.101.73.6:80";
- "radarr.media.cocaine.farm" = proxyDomainAuth "media.cocaine.farm" "http://10.101.22.234:80";
+ "sonarr.media.cocaine.farm" = proxyDomainAuth "media.cocaine.farm" "http://127.0.0.1:8989";
+ "radarr.media.cocaine.farm" = proxyDomainAuth "media.cocaine.farm" "http://127.0.0.1:7878";
+ "prowlarr.media.cocaine.farm" = proxyDomainAuth "media.cocaine.farm" "http://127.0.0.1:9696";
"jackett.media.cocaine.farm" = proxyDomainAuth "media.cocaine.farm" "http://127.0.0.1:9117";
- "torrent.media.cocaine.farm" = {
- addSSL = true;
- useACMEHost = "media.cocaine.farm";
+ "torrent.media.cocaine.farm" = domainAuth "media.cocaine.farm";
+
+ "torrent.local" = {
+ listen = [{
+ addr = "10.10.0.2";
+ port = 80;
+ }];
locations."/RPC2" = {
extraConfig = ''
include ${pkgs.nginx}/conf/scgi_params;
- scgi_pass 10.101.131.197:5000;
+ scgi_pass unix:/run/rtorrent/rpc.sock;
'';
};
-
-
- # locations."/" = {
- # proxyPass = "http://127.0.0.1";
- # proxyWebsockets = true;
- # extraConfig = ''
- # proxy_pass_header Authorization;
-
- # proxy_set_header X-Forwarded-Proto $scheme;
- # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- # proxy_set_header Host $host;
- # proxy_set_header Upgrade $http_upgrade;
- # '';
- # };
};
};
};
+
+ networking.hosts = {
+ "10.10.0.2" = [ "torrent.local" ];
+ };
}
diff --git a/modules/tlmp/rtorrent.nix b/modules/tlmp/rtorrent.nix
new file mode 100644
index 0000000..bf72a2a
--- /dev/null
+++ b/modules/tlmp/rtorrent.nix
@@ -0,0 +1,42 @@
+{ config, lib, pkgs, ... }:
+
+{
+ systemd.services = {
+ wireguard-mullvad = {
+ bindsTo = [ "netns@mullvad.service" ];
+ after = [ "netns@mullvad.service" ];
+ };
+
+ rtorrent = {
+ bindsTo = [ "wireguard-mullvad.service" ];
+ after = [ "wireguard-mullvad.service" ];
+ unitConfig.JoinsNamespaceOf = "netns@mullvad.service";
+ serviceConfig.PrivateNetwork = true;
+ };
+ };
+
+ networking.wireguard.interfaces = {
+ mullvad = { # Caring Wasp
+ ips = [ "10.67.4.3/32" "fc00:bbbb:bbbb:bb01::4:402/128" ];
+ privateKeyFile = "/root/wireguard/privkey";
+ interfaceNamespace = "mullvad";
+
+ peers = [
+ { # de-fra-wg-006.relays.mullvad.net
+ publicKey = "nAF0wrLG2+avwQfqxnXhBGPUBCvc3QCqWKH4nK5PfEU=";
+ endpoint = "185.209.196.76:51820";
+ allowedIPs = [ "0.0.0.0/0" "::/0" ];
+ }
+ ];
+ };
+ };
+
+ services.rtorrent = {
+ enable = true;
+ # dataDir = "/mnt/media/download";
+ user = "media";
+ group = "media";
+
+ configText = lib.mkForce (lib.readFile ./rtorrent.rc);
+ };
+}
diff --git a/modules/tlmp/rtorrent.rc b/modules/tlmp/rtorrent.rc
new file mode 100644
index 0000000..3353f50
--- /dev/null
+++ b/modules/tlmp/rtorrent.rc
@@ -0,0 +1,100 @@
+#############################################################################
+# A minimal rTorrent configuration that provides the basic features
+# you want to have in addition to the built-in defaults.
+#
+# See https://github.com/rakshasa/rtorrent/wiki/CONFIG-Template
+# for an up-to-date version.
+#############################################################################
+
+# Instance layout (base paths)
+method.insert = cfg.basedir, private|const|string, (cat,"/mnt/media/")
+method.insert = cfg.watch, private|const|string, (cat,(cfg.basedir),"watch/")
+method.insert = cfg.logs, private|const|string, (cat,"/var/log/rtorrent/")
+method.insert = cfg.logfile, private|const|string, (cat,(cfg.logs),"rtorrent-",(system.time),".log")
+
+# Create instance directories
+execute.throw = bash, -c, (cat,\
+ "builtin cd \"", (cfg.basedir), "\" ",\
+ "&& mkdir -p .session download watch/{load,start}")
+
+# Listening port for incoming peer traffic (fixed; you can also randomize it)
+network.port_range.set = 50000-50000
+network.port_random.set = no
+
+# Tracker-less torrent and UDP tracker support
+# (conservative settings for 'private' trackers, change for 'public')
+dht.mode.set = disable
+protocol.pex.set = no
+trackers.use_udp.set = no
+
+# Peer settings
+throttle.max_uploads.set = 100
+throttle.max_uploads.global.set = 250
+
+throttle.min_peers.normal.set = 20
+throttle.max_peers.normal.set = 60
+throttle.min_peers.seed.set = 30
+throttle.max_peers.seed.set = 80
+trackers.numwant.set = 80
+
+protocol.encryption.set = allow_incoming,try_outgoing,enable_retry
+
+# Limits for file handle resources, this is optimized for
+# an `ulimit` of 1024 (a common default). You MUST leave
+# a ceiling of handles reserved for rTorrent's internal needs!
+network.http.max_open.set = 50
+network.max_open_files.set = 600
+network.max_open_sockets.set = 300
+
+# Memory resource usage (increase if you have a large number of items loaded,
+# and/or the available resources to spend)
+pieces.memory.max.set = 1800M
+network.xmlrpc.size_limit.set = 4M
+
+# Basic operational settings (no need to change these)
+session.path.set = (cat, (cfg.basedir), ".session")
+directory.default.set = (cat, (cfg.basedir), "download/")
+log.execute = (cat, (cfg.logs), "execute.log")
+##log.xmlrpc = (cat, (cfg.logs), "xmlrpc.log")
+execute.nothrow = bash, -c, (cat, "echo >",\
+ (session.path), "rtorrent.pid", " ", (system.pid))
+
+# Other operational settings (check & adapt)
+encoding.add = utf8
+system.umask.set = 0027
+system.cwd.set = (directory.default)
+network.http.dns_cache_timeout.set = 25
+##network.http.capath.set = "/etc/ssl/certs"
+##network.http.ssl_verify_peer.set = 0
+##network.http.ssl_verify_host.set = 0
+##pieces.hash.on_completion.set = no
+##keys.layout.set = qwerty
+
+##view.sort_current = seeding, greater=d.ratio=
+schedule2 = monitor_diskspace, 15, 60, ((close_low_diskspace, 1000M))
+
+# Some additional values and commands
+method.insert = system.startup_time, value|const, (system.time)
+method.insert = d.data_path, simple,\
+ "if=(d.is_multi_file),\
+ (cat, (d.directory), /),\
+ (cat, (d.directory), /, (d.name))"
+method.insert = d.session_file, simple, "cat=(session.path), (d.hash), .torrent"
+
+# Watch directories (add more as you like, but use unique schedule names)
+schedule2 = watch_start, 10, 10, ((load.start_verbose, (cat, (cfg.watch), "start/*.torrent")))
+schedule2 = watch_load, 11, 10, ((load.verbose, (cat, (cfg.watch), "load/*.torrent")))
+
+# Logging:
+# Levels = critical error warn notice info debug
+# Groups = connection_* dht_* peer_* rpc_* storage_* thread_* tracker_* torrent_*
+print = (cat, "Logging to ", (cfg.logfile))
+log.open_file = "log", (cfg.logfile)
+log.add_output = "info", "log"
+##log.add_output = "tracker_debug", "log"
+
+# XMLRPC
+network.scgi.open_local = /run/rtorrent/rpc.sock
+execute.nothrow = chmod,777,/run/rtorrent/rpc.sock
+
+### END of rtorrent.rc ###
diff --git a/modules/tlmp/rutorrent.nix b/modules/tlmp/rutorrent.nix
index 34bff4c..bfb8ef1 100644
--- a/modules/tlmp/rutorrent.nix
+++ b/modules/tlmp/rutorrent.nix
@@ -3,10 +3,10 @@
with lib;
let
- rutorrent = pkgs.callPackage ./rutorrent.pkg.nix {};
-
cfg = config.services.rutorrent;
+ rutorrent = pkgs.callPackage ./rutorrent.pkg.nix {};
+
rtorrentPluginDependencies = with pkgs; {
_task = [ procps ];
unpack = [ unzip unrar ];
@@ -128,7 +128,6 @@ in {
in []
++ (optional (cfg.nginx.exposeInsecureRPC2mount && (nginxVhostCfg.basicAuth == {} || nginxVhostCfg.basicAuthFile == null )) ''
You are using exposeInsecureRPC2mount without using basic auth on the virtual host. The exposed rpc mount allow for remote command execution.
-
Please make sure it is not accessible from the outside.
'');
@@ -139,7 +138,6 @@ in {
rutorrentConfig = pkgs.writeText "rutorrent-config.php" ''
<?php
// configuration parameters
-
// for snoopy client
@define('HTTP_USER_AGENT', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36', true);
@define('HTTP_TIME_OUT', 30, true); // in seconds
@@ -152,32 +150,22 @@ in {
'host' => 'PROXY_HOST_HERE',
'port' => 3128
);
-
@define('RPC_TIME_OUT', 5, true); // in seconds
-
@define('LOG_RPC_CALLS', false, true);
@define('LOG_RPC_FAULTS', true, true);
-
// for php
@define('PHP_USE_GZIP', false, true);
@define('PHP_GZIP_LEVEL', 2, true);
-
$schedule_rand = 10; // rand for schedulers start, +0..X seconds
-
$do_diagnostic = true;
$log_file = '${cfg.dataDir}/logs/errors.log'; // path to log file (comment or leave blank to disable logging)
-
$saveUploadedTorrents = true; // Save uploaded torrents to profile/torrents directory or not
$overwriteUploadedTorrents = false; // Overwrite existing uploaded torrents in profile/torrents directory or make unique name
-
$topDirectory = '/'; // Upper available directory. Absolute path with trail slash.
$forbidUserSettings = false;
-
- $scgi_port = 5000;
- $scgi_host = "${cfg.rpcSocket}";
-
+ $scgi_port = 0;
+ $scgi_host = "unix://${cfg.rpcSocket}";
$XMLRPCMountPoint = "/RPC2"; // DO NOT DELETE THIS LINE!!! DO NOT COMMENT THIS LINE!!!
-
$pathToExternals = array(
"php" => "${pkgs.php}/bin/php", // Something like /usr/bin/php. If empty, will be found in PATH.
"curl" => "${pkgs.curl}/bin/curl", // Something like /usr/bin/curl. If empty, will be found in PATH.
@@ -186,21 +174,16 @@ in {
"stat" => "${pkgs.coreutils}/bin/stat", // Something like /usr/bin/stat. If empty, will be found in PATH.
"pgrep" => "${pkgs.procps}/bin/pgrep", // TODO why can't we use phpEnv.PATH
);
-
$localhosts = array( // list of local interfaces
"127.0.0.1",
"localhost",
);
-
$profilePath = '${cfg.dataDir}/share'; // Path to user profiles
$profileMask = 0770; // Mask for files and directory creation in user profiles.
// Both Webserver and rtorrent users must have read-write access to it.
// For example, if Webserver and rtorrent users are in the same group then the value may be 0770.
-
$tempDirectory = null; // Temp directory. Absolute path with trail slash. If null, then autodetect will be used.
-
$canUseXSendFile = false; // If true then use X-Sendfile feature if it exist
-
$locale = "UTF8";
'';
in {
@@ -211,12 +194,9 @@ in {
mkdir -p ${cfg.dataDir}/{conf,logs,plugins} ${cfg.dataDir}/share/{settings,torrents,users}
ln -sf ${rutorrent}/conf/{access.ini,plugins.ini} ${cfg.dataDir}/conf/
ln -sf ${rutorrentConfig} ${cfg.dataDir}/conf/config.php
-
cp -r ${rutorrent}/php ${cfg.dataDir}/
-
${optionalString (cfg.plugins != [])
''cp -r ${concatMapStringsSep " " (p: "${rutorrent}/plugins/${p}") cfg.plugins} ${cfg.dataDir}/plugins/''}
-
chown -R ${cfg.user}:${cfg.group} ${cfg.dataDir}/{conf,share,logs,plugins}
chmod -R 755 ${cfg.dataDir}/{conf,share,logs,plugins}
'';
@@ -233,14 +213,14 @@ in {
"${cfg.user}" = {
home = cfg.dataDir;
group = cfg.group;
- # extraGroups = [ config.services.rtorrent.group ];
+ extraGroups = [ config.services.rtorrent.group ];
description = "ruTorrent Daemon user";
isSystemUser = true;
};
- # "${config.services.rtorrent.user}" = {
- # extraGroups = [ cfg.group ];
- # };
+ "${config.services.rtorrent.user}" = {
+ extraGroups = [ cfg.group ];
+ };
};
}
@@ -250,7 +230,7 @@ in {
envPath = lib.makeBinPath (getPluginDependencies phpPluginDependencies cfg.plugins);
pool = {
user = cfg.user;
- group = config.services.rutorrent.group;
+ group = config.services.rtorrent.group;
settings = mapAttrs (name: mkDefault) {
"listen.owner" = config.services.nginx.user;
"listen.group" = config.services.nginx.group;
@@ -270,13 +250,10 @@ in {
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
-
# Mitigate https://httpoxy.org/ vulnerabilities
fastcgi_param HTTP_PROXY "";
-
fastcgi_pass unix:${config.services.phpfpm.pools.rutorrent.socket};
fastcgi_index index.php;
-
include ${pkgs.nginx}/conf/fastcgi.conf;
'';
};
@@ -294,8 +271,6 @@ in {
scgi_pass unix:${cfg.rpcSocket};
'';
};
-
- # services.rtorrent.rpcGroup = "nginx";
})
]))
]);
diff --git a/modules/tlmp/sonarr.nix b/modules/tlmp/sonarr.nix
new file mode 100644
index 0000000..cf56476
--- /dev/null
+++ b/modules/tlmp/sonarr.nix
@@ -0,0 +1,57 @@
+{ lib, stdenv, fetchurl, dotnet-runtime, icu, ffmpeg, openssl, sqlite, curl, makeWrapper, nixosTests }:
+
+let
+ os = if stdenv.isDarwin then "osx" else "linux";
+ arch = {
+ x86_64-linux = "x64";
+ aarch64-linux = "arm64";
+ x86_64-darwin = "x64";
+ aarch64-darwin = "arm64";
+ }."${stdenv.hostPlatform.system}" or (throw "Unsupported system: ${stdenv.hostPlatform.system}");
+
+ hash = {
+ x64-linux_hash = "sha256-9YNhyhxnnn2CesXLJH5Cs7yB9w23YUAZPrk9vEHvevk=";
+ arm64-linux_hash = "sha256-RBCyfozmBpWrmsfMcdb1BqcBXj64CMDrgpMZTzj85ZQ=";
+ x64-osx_hash = "sha256-+AKENBZohBUEKQEM3L69EzC84MhCX3fGvsNFn5p2v84=";
+ arm64-osx_hash = "sha256-Arx8usecAN+d0NGL7Hv+rB4GG7p/KLAaqpJFgNg7C2Y=";
+ }."${arch}-${os}_hash";
+in
+stdenv.mkDerivation rec {
+ pname = "sonarr";
+ version = "4.0.1.929";
+
+ src = fetchurl {
+ url = "https://github.com/Sonarr/Sonarr/releases/download/v${version}/Sonarr.main.${version}.${os}-${arch}.tar.gz";
+ inherit hash;
+ };
+
+ nativeBuildInputs = [ makeWrapper ];
+
+ installPhase = ''
+ runHook preInstall
+
+ mkdir -p $out/{bin,share/sonarr-${version}}
+ cp -r * $out/share/sonarr-${version}/.
+
+ makeWrapper "${dotnet-runtime}/bin/dotnet" $out/bin/NzbDrone \
+ --add-flags "$out/share/sonarr-${version}/Sonarr.dll" \
+ --prefix PATH : ${lib.makeBinPath [ ffmpeg ]} \
+ --prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath [ curl sqlite openssl icu ]}
+
+ runHook postInstall
+ '';
+
+ passthru = {
+ updateScript = ./update.sh;
+ tests.smoke-test = nixosTests.sonarr;
+ };
+
+ meta = {
+ description = "Smart PVR for newsgroup and bittorrent users";
+ homepage = "https://sonarr.tv/";
+ license = lib.licenses.gpl3Only;
+ maintainers = with lib.maintainers; [ fadenb purcell ];
+ mainProgram = "NzbDrone";
+ platforms = lib.platforms.all;
+ };
+}