This commit is contained in:
rasmus-kirk
2024-02-21 10:33:00 +01:00
parent c8ecee1dba
commit f172e0c407
12 changed files with 75 additions and 73 deletions
+218
View File
@@ -0,0 +1,218 @@
{
config,
lib,
...
}:
with lib; let
cfg = config.nixarr;
in {
imports = [
./jellyfin
./radarr
./lidarr
./readarr
./sonarr
./prowlarr
./transmission
];
options.nixarr = {
enable = mkEnableOption ''
Primarily, lets you host the "*Arrs" services optionally through a VPN.
It is possible, _but not recommended_, to have
prowlarr/sonarr/radarr/readarr/lidarr behind a VPN, because it can cause
rate limiting issues. Generally, you should use VPN on transmission
and maybe jellyfin, depending on your setup. Also sets permissions
and creates directories.
- Jellyfin
- Lidarr
- Prowlarr
- Radarr
- Readarr
- Sonarr
- Transmission
Remember to read the options.
'';
mediaUsers = mkOption {
type = with types; listOf str;
default = [];
description = "Extra users to add the the media group, giving access to the media directory. You probably want to add your own user here.";
};
mediaDir = mkOption {
type = types.path;
default = "/data/media";
description = "The location of the media directory for the services.";
};
stateDir = mkOption {
type = types.path;
default = "/data/.state";
description = "The location of the state directory for the services.";
};
upnp.enable = mkEnableOption "Enable automatic port forwarding using UPNP.";
vpn = {
enable = mkEnableOption ''Enable vpn'';
wgConf = mkOption {
type = types.nullOr types.path;
default = null;
description = "REQUIRED! The path to the wireguard configuration file.";
};
dnsServers = mkOption {
type = with types; nullOr (listOf str);
default = null;
description = lib.mdDoc ''
Extra DNS servers for the VPN. If your wg config has a DNS field,
then this should not be necessary.
'';
example = ["1.1.1.2"];
};
vpnTestService = {
enable = mkEnableOption "Enable the vpn test service.";
port = mkOption {
type = types.port;
default = 12300;
description = lib.mdDoc ''
The port that the vpn test service listens to.
'';
example = 58403;
};
};
openTcpPorts = mkOption {
type = with types; listOf port;
default = [];
description = lib.mdDoc ''
What TCP ports to allow incoming traffic from. You might need this
if you're port forwarding on your VPN provider and you're setting
up services that is not covered in by this module.
'';
example = [46382 38473];
};
openUdpPorts = mkOption {
type = with types; listOf port;
default = [];
description = lib.mdDoc ''
What UDP ports to allow incoming traffic from. You might need this
if you're port forwarding on your VPN provider and you're setting
up services that is not covered in by this module.
'';
example = [46382 38473];
};
};
};
config = mkIf cfg.enable {
imports = [
../util
];
users.groups = {
media = {
members = cfg.mediaUsers;
gid = 992;
};
prowlarr = {};
transmission = {};
jellyfin = {};
};
# TODO: This is BAD. But seems necessary when using containers.
# The prefered solution is to just remove containerization.
# Look at https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/misc/ids.nix
users.users = {
jellyfin = {
isSystemUser = true;
uid = lib.mkForce 316;
};
sonarr = {
isSystemUser = true;
group = "media";
uid = lib.mkForce 274;
};
radarr = {
isSystemUser = true;
group = "media";
uid = lib.mkForce 275;
};
lidarr = {
isSystemUser = true;
group = "media";
uid = lib.mkForce 306;
};
readarr = {
isSystemUser = true;
group = "media";
uid = lib.mkForce 309;
};
transmission = {
isSystemUser = true;
group = "transmission";
uid = lib.mkForce 70;
};
prowlarr = {
isSystemUser = true;
group = "prowlarr";
uid = lib.mkForce 293;
};
};
systemd.tmpfiles.rules = [
# State dirs
"d '${cfg.stateDir}' 0755 root root - -"
"d '${cfg.stateDir}/nixarr' 0755 root root - -"
"d '${cfg.stateDir}/nixarr/jellyfin' 0700 jellyfin root - -"
"d '${cfg.stateDir}/nixarr/transmission' 0700 transmission root - -"
"d '${cfg.stateDir}/nixarr/sonarr' 0700 sonarr root - -"
"d '${cfg.stateDir}/nixarr/radarr' 0700 radarr root - -"
"d '${cfg.stateDir}/nixarr/readarr' 0700 readarr root - -"
"d '${cfg.stateDir}/nixarr/lidarr' 0700 lidarr root - -"
"d '${cfg.stateDir}/nixarr/prowlarr' 0700 prowlarr root - -"
# Media dirs
"d '${cfg.mediaDir}' 0775 root media - -"
"d '${cfg.mediaDir}/library' 0775 jellyfin media - -"
"d '${cfg.mediaDir}/library/series' 0775 jellyfin media - -"
"d '${cfg.mediaDir}/library/movies' 0775 jellyfin media - -"
"d '${cfg.mediaDir}/library/music' 0775 jellyfin media - -"
"d '${cfg.mediaDir}/library/books' 0775 jellyfin media - -"
"d '${cfg.mediaDir}/torrents' 0755 transmission media - -"
"d '${cfg.mediaDir}/torrents/.incomplete' 0755 transmission media - -"
"d '${cfg.mediaDir}/torrents/.watch' 0755 transmission media - -"
"d '${cfg.mediaDir}/torrents/manual' 0755 transmission media - -"
"d '${cfg.mediaDir}/torrents/liadarr' 0755 transmission media - -"
"d '${cfg.mediaDir}/torrents/radarr' 0755 transmission media - -"
"d '${cfg.mediaDir}/torrents/sonarr' 0755 transmission media - -"
"d '${cfg.mediaDir}/torrents/readarr' 0755 transmission media - -"
];
kirk.upnp.enable = cfg.upnp.enable;
kirk.vpnnamespace = {
enable = true;
accessibleFrom = [
"192.168.1.0/24"
"127.0.0.1"
];
dnsServers = cfg.vpn.dnsServers;
wireguardAddressPath = cfg.vpn.wgAddress;
wireguardConfigFile = cfg.vpn.wgConf;
vpnTestService = {
enable = cfg.vpn.vpnTestService.enable;
port = cfg.vpn.vpnTestService.port;
};
openTcpPorts = cfg.vpn.openTcpPorts;
openUdpPorts = cfg.vpn.openUdpPorts;
};
};
}
+143
View File
@@ -0,0 +1,143 @@
{
config,
lib,
...
}:
with lib; let
cfg = config.nixarr.jellyfin;
defaultPort = 8096;
nixarr = config.nixarr;
dnsServers = config.lib.vpn.dnsServers;
in {
options.nixarr.jellyfin = {
enable = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "enable jellyfin";
};
stateDir = mkOption {
type = types.path;
default = "${nixarr.stateDir}/nixarr/jellyfin";
description = lib.mdDoc "The state directory for jellyfin";
};
useVpn = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Use VPN with prowlarr";
};
nginx = {
enable = mkEnableOption "Enable nginx for jellyfin";
domainName = mkOption {
type = types.nullOr types.str;
default = null;
description = "REQUIRED! The domain name to host jellyfin on.";
};
acmeMail = mkOption {
type = types.nullOr types.str;
default = null;
description = "REQUIRED! The ACME mail.";
};
};
};
config =
#assert (!(cfg.useVpn && cfg.nginx.enable)) || abort "useVpn not compatible with nginx.enable.";
#assert (cfg.nginx.enable -> (cfg.nginx.domainName != null && cfg.nginx.acmeMail != null)) || abort "Both nginx.domain and nginx.acmeMail needs to be set if nginx.enable is set.";
mkIf cfg.enable
{
services.jellyfin.enable = cfg.enable;
networking.firewall.allowedTCPPorts =
if cfg.nginx.enable
then [
80 # http
443 # https
]
else [];
services.nginx = mkIf (cfg.nginx.enable || cfg.useVpn) {
enable = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
virtualHosts."${builtins.replaceStrings ["\n"] [""] cfg.nginx.domainName}" = mkIf cfg.nginx.enable {
enableACME = true;
forceSSL = true;
locations."/" = {
recommendedProxySettings = true;
proxyWebsockets = true;
proxyPass = "http://127.0.0.1:${builtins.toString defaultPort}";
};
};
virtualHosts."127.0.0.1:${builtins.toString defaultPort}" = mkIf cfg.useVpn {
listen = [
{
addr = "0.0.0.0";
port = defaultPort;
}
];
locations."/" = {
recommendedProxySettings = true;
proxyWebsockets = true;
proxyPass = "http://192.168.15.1:${builtins.toString defaultPort}";
};
};
};
security.acme = mkIf cfg.nginx.enable {
acceptTerms = true;
defaults.email = cfg.nginx.acmeMail;
};
util.vpnnamespace.portMappings = [
(
mkIf cfg.useVpn {
From = defaultPort;
To = defaultPort;
}
)
];
containers.jellyfin = mkIf cfg.useVpn {
autoStart = true;
ephemeral = true;
extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = {
"${nixarr.mediaDir}/library".isReadOnly = false;
"${cfg.stateDir}".isReadOnly = false;
};
config = {
users.groups.jellyfin = {};
users.users.jellyfin = {
uid = lib.mkForce config.users.users.jellyfin.uid;
isSystemUser = true;
group = "jellyfin";
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
networking.useHostResolvConf = lib.mkForce false;
services.resolved.enable = true;
networking.nameservers = dnsServers;
services.jellyfin = {
enable = true;
group = "jellyfin";
dataDir = "${cfg.stateDir}";
};
system.stateVersion = "23.11";
};
};
};
}
+106
View File
@@ -0,0 +1,106 @@
{
config,
lib,
...
}:
with lib; let
cfg = config.nixarr.lidarr;
dnsServers = config.lib.vpn.dnsServers;
nixarr = config.nixarr;
in {
options.nixarr.lidarr = {
enable = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Enable lidarr";
};
stateDir = mkOption {
type = types.path;
default = "${nixarr.stateDir}/nixarr/lidarr";
description = lib.mdDoc "The state directory for lidarr";
};
useVpn = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Use VPN with prowlarr";
};
};
config = mkIf cfg.enable {
services.lidarr = {
enable = cfg.enable;
user = "lidarr";
group = "media";
dataDir = cfg.stateDir;
};
util.vpnnamespace.portMappings = [
(
mkIf cfg.useVpn {
From = defaultPort;
To = defaultPort;
}
)
];
containers.lidarr = mkIf cfg.useVpn {
autoStart = true;
ephemeral = true;
extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = {
"${nixarr.mediaDir}".isReadOnly = false;
"${cfg.stateDir}".isReadOnly = false;
};
config = {
users.groups.media = {
gid = config.users.groups.media.gid;
};
users.users.lidarr = {
uid = lib.mkForce config.users.users.lidarr.uid;
isSystemUser = true;
group = "media";
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
networking.useHostResolvConf = lib.mkForce false;
services.resolved.enable = true;
networking.nameservers = dnsServers;
services.lidarr = {
enable = true;
group = "media";
dataDir = "${cfg.stateDir}";
};
system.stateVersion = "23.11";
};
};
services.nginx = mkIf cfg.useVpn {
enable = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
virtualHosts."127.0.0.1:${builtins.toString defaultPort}" = {
listen = [
{
addr = "0.0.0.0";
port = defaultPort;
}
];
locations."/" = {
recommendedProxySettings = true;
proxyWebsockets = true;
proxyPass = "http://192.168.15.1:${builtins.toString defaultPort}";
};
};
};
};
}
+108
View File
@@ -0,0 +1,108 @@
# TODO: Dir creation and file permissions in nix
{
pkgs,
config,
lib,
...
}:
with lib; let
defaultPort = 9696;
dnsServers = config.lib.vpn.dnsServers;
nixarr = config.nixarr;
cfg = config.nixarr.prowlarr;
in {
options.nixarr.prowlarr = {
enable = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Enable prowlarr";
};
stateDir = mkOption {
type = types.path;
default = "${nixarr.stateDir}/nixarr/prowlarr";
description = lib.mdDoc ''
The state directory for prowlarr. Currently doesn't work, except with VPN.
'';
};
useVpn = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Use VPN with prowlarr";
};
};
config = mkIf cfg.enable {
services.prowlarr = mkIf (!cfg.useVpn) {
enable = true;
openFirewall = true;
};
util.vpnnamespace.portMappings = [
(
mkIf cfg.useVpn {
From = defaultPort;
To = defaultPort;
}
)
];
containers.prowlarr = mkIf cfg.useVpn {
autoStart = true;
ephemeral = true;
extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = {
"/var/lib/prowlarr" = {
hostPath = cfg.stateDir;
isReadOnly = false;
};
};
config = {
users.groups.prowlarr = {};
users.users.prowlarr = {
uid = lib.mkForce config.users.users.prowlarr.uid;
isSystemUser = true;
group = "prowlarr";
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
networking.useHostResolvConf = lib.mkForce false;
services.resolved.enable = true;
networking.nameservers = dnsServers;
services.prowlarr = {
enable = true;
openFirewall = true;
};
system.stateVersion = "23.11";
};
};
services.nginx = mkIf cfg.useVpn {
enable = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
virtualHosts."127.0.0.1:${builtins.toString defaultPort}" = {
listen = [
{
addr = "0.0.0.0";
port = defaultPort;
}
];
locations."/" = {
recommendedProxySettings = true;
proxyWebsockets = true;
proxyPass = "http://192.168.15.1:${builtins.toString defaultPort}";
};
};
};
};
}
+109
View File
@@ -0,0 +1,109 @@
# TODO: Dir creation and file permissions in nix
{
pkgs,
config,
lib,
...
}:
with lib; let
cfg = config.nixarr.radarr;
defaultPort = 7878;
nixarr = config.nixarr;
dnsServers = config.lib.vpn.dnsServers;
in {
options.nixarr.radarr = {
enable = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Enable radarr";
};
stateDir = mkOption {
type = types.path;
default = "${nixarr.stateDir}/nixarr/radarr";
description = lib.mdDoc "The state directory for radarr";
};
useVpn = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Use VPN with radarr";
};
};
config = mkIf cfg.enable {
services.radarr = mkIf (!cfg.useVpn) {
enable = cfg.enable;
user = "radarr";
group = "media";
dataDir = cfg.stateDir;
};
util.vpnnamespace.portMappings = [
(
mkIf cfg.useVpn {
From = defaultPort;
To = defaultPort;
}
)
];
containers.radarr = mkIf cfg.useVpn {
autoStart = true;
ephemeral = true;
extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = {
"${nixarr.mediaDir}".isReadOnly = false;
"${cfg.stateDir}".isReadOnly = false;
};
config = {
users.groups.media = {
gid = config.users.groups.media.gid;
};
users.users.radarr = {
uid = lib.mkForce config.users.users.radarr.uid;
isSystemUser = true;
group = "media";
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
networking.useHostResolvConf = lib.mkForce false;
services.resolved.enable = true;
networking.nameservers = dnsServers;
services.radarr = {
enable = true;
group = "media";
dataDir = cfg.stateDir;
};
system.stateVersion = "23.11";
};
};
services.nginx = mkIf cfg.useVpn {
enable = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
virtualHosts."127.0.0.1:${builtins.toString defaultPort}" = {
listen = [
{
addr = "0.0.0.0";
port = defaultPort;
}
];
locations."/" = {
recommendedProxySettings = true;
proxyWebsockets = true;
proxyPass = "http://192.168.15.1:${builtins.toString defaultPort}";
};
};
};
};
}
+106
View File
@@ -0,0 +1,106 @@
{
config,
lib,
...
}:
with lib; let
cfg = config.nixarr.readarr;
nixarr = config.nixarr;
dnsServers = config.lib.vpn.dnsServers;
in {
options.nixarr.readarr = {
enable = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Enable readarr";
};
stateDir = mkOption {
type = types.path;
default = "${nixarr.stateDir}/nixarr/readarr";
description = lib.mdDoc "The state directory for readarr";
};
useVpn = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Use VPN with prowlarr";
};
};
config = mkIf cfg.enable {
services.readarr = {
enable = cfg.enable;
user = "readarr";
group = "media";
dataDir = cfg.stateDir;
};
util.vpnnamespace.portMappings = [
(
mkIf cfg.useVpn {
From = defaultPort;
To = defaultPort;
}
)
];
containers.readarr = mkIf cfg.useVpn {
autoStart = true;
ephemeral = true;
extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = {
"${nixarr.mediaDir}".isReadOnly = false;
"${cfg.stateDir}".isReadOnly = false;
};
config = {
users.groups.media = {
gid = config.users.groups.media.gid;
};
users.users.readarr = {
uid = lib.mkForce config.users.users.readarr.uid;
isSystemUser = true;
group = "media";
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
networking.useHostResolvConf = lib.mkForce false;
services.resolved.enable = true;
networking.nameservers = dnsServers;
services.readarr = {
enable = true;
group = "media";
dataDir = "${cfg.stateDir}";
};
system.stateVersion = "23.11";
};
};
services.nginx = mkIf cfg.useVpn {
enable = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
virtualHosts."127.0.0.1:${builtins.toString defaultPort}" = {
listen = [
{
addr = "0.0.0.0";
port = defaultPort;
}
];
locations."/" = {
recommendedProxySettings = true;
proxyWebsockets = true;
proxyPass = "http://192.168.15.1:${builtins.toString defaultPort}";
};
};
};
};
}
+108
View File
@@ -0,0 +1,108 @@
# TODO: Dir creation and file permissions in nix
{
config,
lib,
...
}:
with lib; let
cfg = config.nixarr.sonarr;
defaultPort = 8989;
nixarr = config.nixarr;
dnsServers = config.lib.vpn.dnsServers;
in {
options.nixarr.sonarr = {
enable = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Enable sonarr";
};
stateDir = mkOption {
type = types.path;
default = "${nixarr.stateDir}/sonarr";
description = lib.mdDoc "The state directory for sonarr";
};
useVpn = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Use VPN with sonarr";
};
};
config = mkIf cfg.enable {
services.sonarr = mkIf (!cfg.useVpn) {
enable = cfg.enable;
user = "sonarr";
group = "media";
dataDir = cfg.stateDir;
};
util.vpnnamespace.portMappings = [
(mkIf cfg.useVpn {
From = defaultPort;
To = defaultPort;
})
];
containers.sonarr = mkIf cfg.useVpn {
autoStart = true;
ephemeral = true;
extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = {
"${nixarr.mediaDir}".isReadOnly = false;
"${cfg.stateDir}".isReadOnly = false;
};
config = {
users.groups.media = {
gid = config.users.groups.media.gid;
};
users.users.sonarr = {
uid = lib.mkForce config.users.users.sonarr.uid;
isSystemUser = true;
group = "media";
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
networking.useHostResolvConf = lib.mkForce false;
services.resolved.enable = true;
networking.nameservers = dnsServers;
users.groups.media = {};
services.sonarr = {
enable = cfg.enable;
group = "media";
dataDir = cfg.stateDir;
};
system.stateVersion = "23.11";
};
};
services.nginx = mkIf cfg.useVpn {
enable = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
virtualHosts."127.0.0.1:${builtins.toString defaultPort}" = {
listen = [
{
addr = "0.0.0.0";
port = defaultPort;
}
];
locations."/" = {
recommendedProxySettings = true;
proxyWebsockets = true;
proxyPass = "http://192.168.15.1:${builtins.toString defaultPort}";
};
};
};
};
}
+232
View File
@@ -0,0 +1,232 @@
# TODO: Dir creation and file permissions in nix
{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.nixarr.transmission;
nixarr = config.nixarr;
dnsServers = config.lib.vpn.dnsServers;
in {
options.nixarr.transmission = {
enable = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Enable transmission";
};
stateDir = mkOption {
type = types.path;
default = "${nixarr.stateDir}/nixarr/transmission";
description = lib.mdDoc "The state directory for transmission. Only works with useVpn option.";
};
downloadDir = mkOption {
type = types.path;
default = "${nixarr.mediaDir}/torrents";
description = lib.mdDoc ''
The directory for transmission to download to.
'';
};
useVpn = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Run transmission through VPN";
};
useFlood = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc "Use the flood UI";
};
peerPort = mkOption {
type = types.port;
default = 50000;
description = "transmission peer traffic port.";
};
uiPort = mkOption {
type = types.port;
default = 9091;
description = "transmission web-UI port.";
};
extraConfig = mkOption {
type = types.attrs;
default = {};
description = "Extra settings config for the transmission service.";
};
};
config = mkIf cfg.enable {
services.transmission = mkIf (!cfg.useVpn) {
enable = true;
group = "media";
#home = cfg.stateDir;
webHome =
if cfg.useFlood
then pkgs.flood-for-transmission
else null;
package = pkgs.transmission_4;
openRPCPort = true;
openPeerPorts = true;
settings =
{
download-dir = "${nixarr.mediaDir}/torrents";
incomplete-dir-enabled = true;
incomplete-dir = "${nixarr.mediaDir}/torrents/.incomplete";
watch-dir-enabled = true;
watch-dir = "${nixarr.mediaDir}/torrents/.watch";
rpc-port = cfg.uiPort;
rpc-whitelist-enabled = true;
rpc-whitelist = "192.168.15.1,127.0.0.1";
rpc-authentication-required = true;
blocklist-enabled = true;
blocklist-url = "https://github.com/Naunter/BT_BlockLists/raw/master/bt_blocklists.gz";
encryption = 1;
utp-enabled = true;
port-forwarding-enabled = false;
anti-brute-force-enabled = true;
anti-brute-force-threshold = 10;
}
// cfg.extraConfig;
};
util.vpnnamespace = mkIf cfg.useVpn {
portMappings = [
{
From = cfg.uiPort;
To = cfg.uiPort;
}
];
openUdpPorts = [cfg.peerPort];
openTcpPorts = [cfg.peerPort];
};
containers.transmission = mkIf cfg.useVpn {
autoStart = true;
ephemeral = true;
extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = {
"${nixarr.mediaDir}/torrents".isReadOnly = false;
"/var/lib/transmission" = {
hostPath = cfg.stateDir;
isReadOnly = false;
};
};
config = {
users.groups.media = {
gid = config.users.groups.media.gid;
};
users.users.transmission = {
uid = lib.mkForce config.users.users.transmission.uid;
isSystemUser = true;
group = "media";
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
networking.useHostResolvConf = lib.mkForce false;
services.resolved.enable = true;
networking.nameservers = dnsServers;
systemd.services.transmission.serviceConfig = {
RootDirectoryStartOnly = lib.mkForce false;
RootDirectory = lib.mkForce "";
};
services.transmission = {
enable = true;
# This is maybe wrong, too afraid to fix it lol
group = "media";
webHome =
if cfg.useFlood
then pkgs.flood-for-transmission
else null;
package = pkgs.transmission_4;
openRPCPort = true;
openPeerPorts = true;
settings =
{
download-dir = "${nixarr.mediaDir}/torrents";
incomplete-dir-enabled = true;
incomplete-dir = "${nixarr.mediaDir}/torrents/.incomplete";
watch-dir-enabled = true;
watch-dir = "${nixarr.mediaDir}/torrents/.watch";
rpc-bind-address = "192.168.15.1";
rpc-port = cfg.uiPort;
rpc-whitelist-enabled = false;
rpc-whitelist = "192.168.15.1,127.0.0.1";
rpc-authentication-required = false;
blocklist-enabled = true;
blocklist-url = "https://github.com/Naunter/BT_BlockLists/raw/master/bt_blocklists.gz";
peer-port = cfg.peerPort;
dht-enabled = true;
pex-enabled = true;
utp-enabled = false;
encryption = 1;
port-forwarding-enabled = false;
anti-brute-force-enabled = true;
anti-brute-force-threshold = 10;
# 0 = None, 1 = Critical, 2 = Error, 3 = Warn, 4 = Info, 5 = Debug, 6 = Trace
message-level = 3;
}
// cfg.extraConfig;
};
environment.systemPackages = with pkgs; [
curl
wget
util-linux
unixtools.ping
coreutils
curl
bash
libressl
netcat-gnu
openresolv
dig
];
system.stateVersion = "23.11";
};
};
services.nginx = mkIf cfg.useVpn {
enable = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
virtualHosts."127.0.0.1:${builtins.toString cfg.uiPort}" = {
listen = [
{
addr = "0.0.0.0";
port = cfg.uiPort;
}
];
locations."/" = {
recommendedProxySettings = true;
proxyWebsockets = true;
proxyPass = "http://192.168.15.1:${builtins.toString cfg.uiPort}";
};
};
};
};
}