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
+3 -3
View File
@@ -1,3 +1,3 @@
./result result
./hugo/public hugo/public
./hugo/content/index.md hugo/content/index.md
+10 -10
View File
@@ -1,4 +1,4 @@
# servarr.enable # Nixarr
This is a nixos module that aims to make the installation and management of This is a nixos module that aims to make the installation and management of
running the "*Arrs" as easy, and pain free, as possible. running the "*Arrs" as easy, and pain free, as possible.
@@ -6,24 +6,24 @@ running the "*Arrs" as easy, and pain free, as possible.
## Options ## Options
The documentation for the options can be found The documentation for the options can be found
[here](https://rasmus-kirk.github.io/servarr.enable/) [here](https://rasmus-kirk.github.io/nixarr/)
## Features ## Features
- **Run services through a VPN:** You can run any service that this module - **Run services through a VPN:** You can run any service that this module
supports through a VPN, fx `servarr.*.useVpn = true;` supports through a VPN, fx `nixarr.*.useVpn = true;`
- **Automatic Directories, Users and Permissions:** The module automatically - **Automatic Directories, Users and Permissions:** The module automatically
creates directories and users for your media library. It also sets sane creates directories and users for your media library. It also sets sane
permissions. permissions.
- **State Management:** All services support state management and all state - **State Management:** All services support state management and all state
that they manage is by default in `/data/.state/servarr/*` that they manage is by default in `/data/.state/nixarr/*`
- **Optional Automatic Port Forwarding:** This module has a UPNP module that - **Optional Automatic Port Forwarding:** This module has a UPNP module that
lets services request ports from your router automatically, if you enable it. lets services request ports from your router automatically, if you enable it.
To run services through a VPN, you must provide a wg-quick config file: To run services through a VPN, you must provide a wg-quick config file:
```nix ```nix
servarr.vpn = { nixarr.vpn = {
enable = true; enable = true;
# IMPORTANT: This file must _not_ be in the config git directory # IMPORTANT: This file must _not_ be in the config git directory
# You can usually get this wireguard file from your VPN provider # You can usually get this wireguard file from your VPN provider
@@ -36,12 +36,12 @@ servarr.vpn = {
Full example can be seen below: Full example can be seen below:
```nix ```nix
servarr = { nixarr = {
enable = true; enable = true;
# These two values are also the default, but you can set them to whatever # These two values are also the default, but you can set them to whatever
# else you want # else you want
mediaDir = "/data/media"; mediaDir = "/data/media";
stateDir = "/data/media/.state/servarr"; stateDir = "/data/media/.state/nixarr";
vpn = { vpn = {
enable = true; enable = true;
@@ -87,7 +87,7 @@ Add DDNS-support.
### State Directories ### State Directories
- [ ] Jellyfin: PR is merged, wait for nixpkgs to update - [ ] Jellyfin: PR is merged, just need to do add it here
- [ ] prowlarr: Works for vpn, probably need to create my own prowlarr systemd service... - [ ] prowlarr: Works for vpn, probably need to create my own prowlarr systemd service...
- [x] sonarr: Works - [x] sonarr: Works
- [x] radarr: Works - [x] radarr: Works
@@ -100,7 +100,7 @@ Using buildarr would allow setup services to integrate with each other upon
activation with no user input, definitely nice. activation with no user input, definitely nice.
Needs to be added to nixpkgs, not too hard, but is not worth it if the Needs to be added to nixpkgs, not too hard, but is not worth it if the
project is abandoned project is abandoned.
- [ ] Package with nix - [ ] Package with nix
- [ ] Add to nixpkgs - [ ] Add to nixpkgs
@@ -112,7 +112,7 @@ idea how this could be done, but would simplify things _a lot_.
### cross-seed ### cross-seed
Create a cross-seed service. Create support for the [cross-seed](https://github.com/cross-seed/cross-seed) service.
- [ ] Package with nix - [ ] Package with nix
- [ ] Create nix service daemon - [ ] Create nix service daemon
+3 -3
View File
@@ -1,5 +1,5 @@
{ {
description = "The servarr.enable nixos module"; description = "The Nixarr Nixos Module for Hosting the \"*Arrs\"";
nixConfig = { nixConfig = {
extra-substituters = ["https://nix-community.cachix.org"]; extra-substituters = ["https://nix-community.cachix.org"];
@@ -46,8 +46,8 @@
flake = { flake = {
nixosModules = rec { nixosModules = rec {
servarr = import ./servarr; nixarr = import ./nixarr;
default = servarr; default = nixarr;
}; };
}; };
+1 -1
View File
@@ -13,7 +13,7 @@
config._module.check = false; config._module.check = false;
} }
#inputs.home-manager.nixosModules.default #inputs.home-manager.nixosModules.default
./servarr ./nixarr
]; ];
}; };
optionsDocNixos = nixosOptionsDoc { optionsDocNixos = nixosOptionsDoc {
+17 -15
View File
@@ -4,7 +4,7 @@
... ...
}: }:
with lib; let with lib; let
cfg = config.servarr; cfg = config.nixarr;
in { in {
imports = [ imports = [
./jellyfin ./jellyfin
@@ -16,13 +16,15 @@ in {
./transmission ./transmission
]; ];
options.servarr = { options.nixarr = {
enable = mkEnableOption '' enable = mkEnableOption ''
My servarr setup. Lets you host the servarr services optionally Primarily, lets you host the "*Arrs" services optionally through a VPN.
through a VPN. It is possible, BUT NOT RECOMENDED, to have
prowlarr/sonarr/radarr/readarr/lidarr behind a VPN. Generally, you It is possible, _but not recommended_, to have
should use VPN on transmission and maybe jellyfin, depending on your prowlarr/sonarr/radarr/readarr/lidarr behind a VPN, because it can cause
setup. Also sets permissions and creates folders. rate limiting issues. Generally, you should use VPN on transmission
and maybe jellyfin, depending on your setup. Also sets permissions
and creates directories.
- Jellyfin - Jellyfin
- Lidarr - Lidarr
@@ -168,14 +170,14 @@ in {
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [
# State dirs # State dirs
"d '${cfg.stateDir}' 0755 root root - -" "d '${cfg.stateDir}' 0755 root root - -"
"d '${cfg.stateDir}/servarr' 0755 root root - -" "d '${cfg.stateDir}/nixarr' 0755 root root - -"
"d '${cfg.stateDir}/servarr/jellyfin' 0700 jellyfin root - -" "d '${cfg.stateDir}/nixarr/jellyfin' 0700 jellyfin root - -"
"d '${cfg.stateDir}/servarr/transmission' 0700 transmission root - -" "d '${cfg.stateDir}/nixarr/transmission' 0700 transmission root - -"
"d '${cfg.stateDir}/servarr/sonarr' 0700 sonarr root - -" "d '${cfg.stateDir}/nixarr/sonarr' 0700 sonarr root - -"
"d '${cfg.stateDir}/servarr/radarr' 0700 radarr root - -" "d '${cfg.stateDir}/nixarr/radarr' 0700 radarr root - -"
"d '${cfg.stateDir}/servarr/readarr' 0700 readarr root - -" "d '${cfg.stateDir}/nixarr/readarr' 0700 readarr root - -"
"d '${cfg.stateDir}/servarr/lidarr' 0700 lidarr root - -" "d '${cfg.stateDir}/nixarr/lidarr' 0700 lidarr root - -"
"d '${cfg.stateDir}/servarr/prowlarr' 0700 prowlarr root - -" "d '${cfg.stateDir}/nixarr/prowlarr' 0700 prowlarr root - -"
# Media dirs # Media dirs
"d '${cfg.mediaDir}' 0775 root media - -" "d '${cfg.mediaDir}' 0775 root media - -"
@@ -4,12 +4,12 @@
... ...
}: }:
with lib; let with lib; let
cfg = config.servarr.jellyfin; cfg = config.nixarr.jellyfin;
defaultPort = 8096; defaultPort = 8096;
servarr = config.servarr; nixarr = config.nixarr;
dnsServers = config.lib.vpn.dnsServers; dnsServers = config.lib.vpn.dnsServers;
in { in {
options.servarr.jellyfin = { options.nixarr.jellyfin = {
enable = mkOption { enable = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
@@ -18,7 +18,7 @@ in {
stateDir = mkOption { stateDir = mkOption {
type = types.path; type = types.path;
default = "${servarr.stateDir}/servarr/jellyfin"; default = "${nixarr.stateDir}/nixarr/jellyfin";
description = lib.mdDoc "The state directory for jellyfin"; description = lib.mdDoc "The state directory for jellyfin";
}; };
@@ -112,7 +112,7 @@ in {
extraFlags = ["--network-namespace-path=/var/run/netns/wg"]; extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = { bindMounts = {
"${servarr.mediaDir}/library".isReadOnly = false; "${nixarr.mediaDir}/library".isReadOnly = false;
"${cfg.stateDir}".isReadOnly = false; "${cfg.stateDir}".isReadOnly = false;
}; };
@@ -4,11 +4,11 @@
... ...
}: }:
with lib; let with lib; let
cfg = config.servarr.lidarr; cfg = config.nixarr.lidarr;
dnsServers = config.lib.vpn.dnsServers; dnsServers = config.lib.vpn.dnsServers;
servarr = config.servarr; nixarr = config.nixarr;
in { in {
options.servarr.lidarr = { options.nixarr.lidarr = {
enable = mkOption { enable = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
@@ -17,7 +17,7 @@ in {
stateDir = mkOption { stateDir = mkOption {
type = types.path; type = types.path;
default = "${servarr.stateDir}/servarr/lidarr"; default = "${nixarr.stateDir}/nixarr/lidarr";
description = lib.mdDoc "The state directory for lidarr"; description = lib.mdDoc "The state directory for lidarr";
}; };
@@ -51,7 +51,7 @@ in {
extraFlags = ["--network-namespace-path=/var/run/netns/wg"]; extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = { bindMounts = {
"${servarr.mediaDir}".isReadOnly = false; "${nixarr.mediaDir}".isReadOnly = false;
"${cfg.stateDir}".isReadOnly = false; "${cfg.stateDir}".isReadOnly = false;
}; };
@@ -8,10 +8,10 @@
with lib; let with lib; let
defaultPort = 9696; defaultPort = 9696;
dnsServers = config.lib.vpn.dnsServers; dnsServers = config.lib.vpn.dnsServers;
servarr = config.servarr; nixarr = config.nixarr;
cfg = config.servarr.prowlarr; cfg = config.nixarr.prowlarr;
in { in {
options.servarr.prowlarr = { options.nixarr.prowlarr = {
enable = mkOption { enable = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
@@ -20,7 +20,7 @@ in {
stateDir = mkOption { stateDir = mkOption {
type = types.path; type = types.path;
default = "${servarr.stateDir}/servarr/prowlarr"; default = "${nixarr.stateDir}/nixarr/prowlarr";
description = lib.mdDoc '' description = lib.mdDoc ''
The state directory for prowlarr. Currently doesn't work, except with VPN. The state directory for prowlarr. Currently doesn't work, except with VPN.
''; '';
@@ -6,12 +6,12 @@
... ...
}: }:
with lib; let with lib; let
cfg = config.servarr.radarr; cfg = config.nixarr.radarr;
defaultPort = 7878; defaultPort = 7878;
servarr = config.servarr; nixarr = config.nixarr;
dnsServers = config.lib.vpn.dnsServers; dnsServers = config.lib.vpn.dnsServers;
in { in {
options.servarr.radarr = { options.nixarr.radarr = {
enable = mkOption { enable = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
@@ -20,7 +20,7 @@ in {
stateDir = mkOption { stateDir = mkOption {
type = types.path; type = types.path;
default = "${servarr.stateDir}/servarr/radarr"; default = "${nixarr.stateDir}/nixarr/radarr";
description = lib.mdDoc "The state directory for radarr"; description = lib.mdDoc "The state directory for radarr";
}; };
@@ -54,7 +54,7 @@ in {
extraFlags = ["--network-namespace-path=/var/run/netns/wg"]; extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = { bindMounts = {
"${servarr.mediaDir}".isReadOnly = false; "${nixarr.mediaDir}".isReadOnly = false;
"${cfg.stateDir}".isReadOnly = false; "${cfg.stateDir}".isReadOnly = false;
}; };
@@ -4,11 +4,11 @@
... ...
}: }:
with lib; let with lib; let
cfg = config.servarr.readarr; cfg = config.nixarr.readarr;
servarr = config.servarr; nixarr = config.nixarr;
dnsServers = config.lib.vpn.dnsServers; dnsServers = config.lib.vpn.dnsServers;
in { in {
options.servarr.readarr = { options.nixarr.readarr = {
enable = mkOption { enable = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
@@ -17,7 +17,7 @@ in {
stateDir = mkOption { stateDir = mkOption {
type = types.path; type = types.path;
default = "${servarr.stateDir}/servarr/readarr"; default = "${nixarr.stateDir}/nixarr/readarr";
description = lib.mdDoc "The state directory for readarr"; description = lib.mdDoc "The state directory for readarr";
}; };
@@ -51,7 +51,7 @@ in {
extraFlags = ["--network-namespace-path=/var/run/netns/wg"]; extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = { bindMounts = {
"${servarr.mediaDir}".isReadOnly = false; "${nixarr.mediaDir}".isReadOnly = false;
"${cfg.stateDir}".isReadOnly = false; "${cfg.stateDir}".isReadOnly = false;
}; };
@@ -5,12 +5,12 @@
... ...
}: }:
with lib; let with lib; let
cfg = config.servarr.sonarr; cfg = config.nixarr.sonarr;
defaultPort = 8989; defaultPort = 8989;
servarr = config.servarr; nixarr = config.nixarr;
dnsServers = config.lib.vpn.dnsServers; dnsServers = config.lib.vpn.dnsServers;
in { in {
options.servarr.sonarr = { options.nixarr.sonarr = {
enable = mkOption { enable = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
@@ -19,7 +19,7 @@ in {
stateDir = mkOption { stateDir = mkOption {
type = types.path; type = types.path;
default = "${servarr.stateDir}/sonarr"; default = "${nixarr.stateDir}/sonarr";
description = lib.mdDoc "The state directory for sonarr"; description = lib.mdDoc "The state directory for sonarr";
}; };
@@ -51,7 +51,7 @@ in {
extraFlags = ["--network-namespace-path=/var/run/netns/wg"]; extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = { bindMounts = {
"${servarr.mediaDir}".isReadOnly = false; "${nixarr.mediaDir}".isReadOnly = false;
"${cfg.stateDir}".isReadOnly = false; "${cfg.stateDir}".isReadOnly = false;
}; };
@@ -6,11 +6,11 @@
... ...
}: }:
with lib; let with lib; let
cfg = config.servarr.transmission; cfg = config.nixarr.transmission;
servarr = config.servarr; nixarr = config.nixarr;
dnsServers = config.lib.vpn.dnsServers; dnsServers = config.lib.vpn.dnsServers;
in { in {
options.servarr.transmission = { options.nixarr.transmission = {
enable = mkOption { enable = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
@@ -19,13 +19,13 @@ in {
stateDir = mkOption { stateDir = mkOption {
type = types.path; type = types.path;
default = "${servarr.stateDir}/servarr/transmission"; default = "${nixarr.stateDir}/nixarr/transmission";
description = lib.mdDoc "The state directory for transmission. Only works with useVpn option."; description = lib.mdDoc "The state directory for transmission. Only works with useVpn option.";
}; };
downloadDir = mkOption { downloadDir = mkOption {
type = types.path; type = types.path;
default = "${servarr.mediaDir}/torrents"; default = "${nixarr.mediaDir}/torrents";
description = lib.mdDoc '' description = lib.mdDoc ''
The directory for transmission to download to. The directory for transmission to download to.
''; '';
@@ -76,11 +76,11 @@ in {
openPeerPorts = true; openPeerPorts = true;
settings = settings =
{ {
download-dir = "${servarr.mediaDir}/torrents"; download-dir = "${nixarr.mediaDir}/torrents";
incomplete-dir-enabled = true; incomplete-dir-enabled = true;
incomplete-dir = "${servarr.mediaDir}/torrents/.incomplete"; incomplete-dir = "${nixarr.mediaDir}/torrents/.incomplete";
watch-dir-enabled = true; watch-dir-enabled = true;
watch-dir = "${servarr.mediaDir}/torrents/.watch"; watch-dir = "${nixarr.mediaDir}/torrents/.watch";
rpc-port = cfg.uiPort; rpc-port = cfg.uiPort;
rpc-whitelist-enabled = true; rpc-whitelist-enabled = true;
@@ -117,7 +117,7 @@ in {
extraFlags = ["--network-namespace-path=/var/run/netns/wg"]; extraFlags = ["--network-namespace-path=/var/run/netns/wg"];
bindMounts = { bindMounts = {
"${servarr.mediaDir}/torrents".isReadOnly = false; "${nixarr.mediaDir}/torrents".isReadOnly = false;
"/var/lib/transmission" = { "/var/lib/transmission" = {
hostPath = cfg.stateDir; hostPath = cfg.stateDir;
isReadOnly = false; isReadOnly = false;
@@ -158,11 +158,11 @@ in {
openPeerPorts = true; openPeerPorts = true;
settings = settings =
{ {
download-dir = "${servarr.mediaDir}/torrents"; download-dir = "${nixarr.mediaDir}/torrents";
incomplete-dir-enabled = true; incomplete-dir-enabled = true;
incomplete-dir = "${servarr.mediaDir}/torrents/.incomplete"; incomplete-dir = "${nixarr.mediaDir}/torrents/.incomplete";
watch-dir-enabled = true; watch-dir-enabled = true;
watch-dir = "${servarr.mediaDir}/torrents/.watch"; watch-dir = "${nixarr.mediaDir}/torrents/.watch";
rpc-bind-address = "192.168.15.1"; rpc-bind-address = "192.168.15.1";
rpc-port = cfg.uiPort; rpc-port = cfg.uiPort;