Compare commits
24 Commits
837562b519
...
7cc521933d
| Author | SHA1 | Date | |
|---|---|---|---|
| 7cc521933d | |||
| c95a949b12 | |||
| 96973b6a8c | |||
| ec44dbe4ff | |||
| 204da9209a | |||
| d6838844ca | |||
| b4b30f6c78 | |||
| ac11a6d765 | |||
| 3ea7ad8a1c | |||
| be6d4f50cd | |||
| 66d0dcb3c3 | |||
| 86f6e7b617 | |||
| 4d1d1cfe76 | |||
| c2af6384bd | |||
| 32d4c7002c | |||
| 45f8838f3c | |||
| eab22b92fa | |||
| d8ca911a13 | |||
| fd055b3af0 | |||
| 74307df8e3 | |||
| 9a4dc02b20 | |||
| 709ab63d5a | |||
| 4b2316b18a | |||
| a5007d9d37 |
@@ -13,21 +13,27 @@ jobs:
|
|||||||
fmt:
|
fmt:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v5
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: DeterminateSystems/nix-installer-action@main
|
uses: DeterminateSystems/nix-installer-action@v3
|
||||||
|
|
||||||
- run: nix fmt -- --check .
|
- run: nix fmt -- --check .
|
||||||
|
|
||||||
|
build-website:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Install Nix
|
||||||
|
uses: DeterminateSystems/nix-installer-action@v3
|
||||||
|
|
||||||
|
- run: nix build
|
||||||
|
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: DeterminateSystems/nix-installer-action@main
|
uses: DeterminateSystems/nix-installer-action@main
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
Added:
|
Added:
|
||||||
- `whisparr` service
|
- `whisparr` service
|
||||||
- `komgarr` service
|
- `komgarr` service
|
||||||
- `stash` service
|
|
||||||
|
|
||||||
Fixed:
|
Fixed:
|
||||||
- Cross-seed now uses `transmission` user.
|
- Cross-seed now uses `transmission` user.
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ like shown in this example flake:
|
|||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||||
nixarr.url = "github:rasmus-kirk/nixarr";
|
nixarr.url = "github:nix-media-server/nixarr";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = {
|
outputs = {
|
||||||
|
|||||||
@@ -31,10 +31,11 @@ option, which by default is set to `/data/media`.
|
|||||||
|
|
||||||
## Transmission
|
## Transmission
|
||||||
|
|
||||||
Transmission should already be setup and running since it's configured
|
Transmission should already be setup and running since it's configured with
|
||||||
with JSON, and can therefore be configured with nix. The most basic settings are already set. See the following links for more info:
|
JSON, and can therefore be configured with nix. The most basic settings are
|
||||||
|
already set. See the following links for more info:
|
||||||
|
|
||||||
- [The configured Nixarr defaults for transmission](https://github.com/rasmus-kirk/nixarr/blob/28d1be070deb1a064c1967889c11c8921752fa09/nixarr/transmission/default.nix#L355)
|
- [The configured Nixarr defaults for transmission](https://github.com/nix-media-server/nixarr/blob/28d1be070deb1a064c1967889c11c8921752fa09/nixarr/transmission/default.nix#L355)
|
||||||
- [The `nixarr.transmission` options](https://nixarr.com/nixos-options/#nixarr.transmission.enable)
|
- [The `nixarr.transmission` options](https://nixarr.com/nixos-options/#nixarr.transmission.enable)
|
||||||
- [Settings that can be passed through `nixarr.transmission.settings`]
|
- [Settings that can be passed through `nixarr.transmission.settings`]
|
||||||
|
|
||||||
|
|||||||
@@ -29,9 +29,6 @@ Then you can set that port for a service, for example
|
|||||||
|
|
||||||
## Debugging Ports
|
## Debugging Ports
|
||||||
|
|
||||||
> **Note:** See [this GH issue](https://github.com/rasmus-kirk/nixarr/issues/27)
|
|
||||||
> first, since it's a common problem
|
|
||||||
|
|
||||||
You can debug an open port using the
|
You can debug an open port using the
|
||||||
[nixarr.vpn.vpnTestService](https://nixarr.com/options.html#nixarr.vpn.vpntestservice.enable):
|
[nixarr.vpn.vpnTestService](https://nixarr.com/options.html#nixarr.vpn.vpntestservice.enable):
|
||||||
|
|
||||||
|
|||||||
Generated
+7
-7
@@ -2,16 +2,16 @@
|
|||||||
"nodes": {
|
"nodes": {
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1761016216,
|
"lastModified": 1765608474,
|
||||||
"narHash": "sha256-G/iC4t/9j/52i/nm+0/4ybBmAF4hzR8CNHC75qEhjHo=",
|
"narHash": "sha256-9Wx53UK0z8Di5iesJID0tS1dRKwGxI4i7tsSanOHhF0=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "481cf557888e05d3128a76f14c76397b7d7cc869",
|
"rev": "28bb483c11a1214a73f9fd2d9928a6e2ea86ec71",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"ref": "nixos-25.05",
|
"ref": "nixos-25.11",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
@@ -25,11 +25,11 @@
|
|||||||
},
|
},
|
||||||
"vpnconfinement": {
|
"vpnconfinement": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1759956062,
|
"lastModified": 1765634578,
|
||||||
"narHash": "sha256-NUZu0Rb0fwUjfdp51zMm0xM3lcK8Kw4c97LLog7+JjA=",
|
"narHash": "sha256-Fujb9sn1cj+u/bzfo2RbQkcAvJ7Ch1pimJzFie4ptb4=",
|
||||||
"owner": "Maroka-chan",
|
"owner": "Maroka-chan",
|
||||||
"repo": "VPN-Confinement",
|
"repo": "VPN-Confinement",
|
||||||
"rev": "fabe7247b720b5eb4c3c053e24a2b3b70e64c52b",
|
"rev": "f2989e1e3cb06c7185939e9ddc368f88b998616a",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
description = "The Nixarr Media Server Nixos Module";
|
description = "The Nixarr Media Server Nixos Module";
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05";
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
|
||||||
|
|
||||||
vpnconfinement.url = "github:Maroka-chan/VPN-Confinement";
|
vpnconfinement.url = "github:Maroka-chan/VPN-Confinement";
|
||||||
|
|
||||||
@@ -27,91 +27,102 @@
|
|||||||
|
|
||||||
# Helper to provide system-specific attributes
|
# Helper to provide system-specific attributes
|
||||||
forAllSystems = f:
|
forAllSystems = f:
|
||||||
nixpkgs.lib.genAttrs supportedSystems (system:
|
nixpkgs.lib.genAttrs supportedSystems (
|
||||||
f {
|
system:
|
||||||
pkgs = import nixpkgs {
|
f {
|
||||||
inherit system;
|
pkgs = import nixpkgs {
|
||||||
config.allowUnfree = true;
|
inherit system;
|
||||||
};
|
config.allowUnfree = true;
|
||||||
});
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
in {
|
in {
|
||||||
nixosModules.default.imports = [./nixarr vpnconfinement.nixosModules.default];
|
nixosModules.default.imports = [
|
||||||
|
./nixarr
|
||||||
|
vpnconfinement.nixosModules.default
|
||||||
|
];
|
||||||
|
|
||||||
# Add tests attribute to the flake outputs
|
# Add tests attribute to the flake outputs
|
||||||
# To run interactively run:
|
# To run interactively run:
|
||||||
# > nix build .#checks.x86_64-linux.monitoring-test.driver -L
|
# > nix build .#checks.x86_64-linux.monitoring-test.driver -L
|
||||||
checks = forAllSystems ({pkgs}: {
|
checks = forAllSystems (
|
||||||
permissions-test = pkgs.callPackage ./tests/permissions-test.nix {
|
{pkgs}: {
|
||||||
inherit (self) nixosModules;
|
permissions-test = pkgs.callPackage ./tests/permissions-test.nix {
|
||||||
};
|
inherit (self) nixosModules;
|
||||||
simple-test = pkgs.callPackage ./tests/simple-test.nix {
|
|
||||||
inherit (self) nixosModules;
|
|
||||||
};
|
|
||||||
# vpn-confinement-test = pkgs.callPackage ./tests/vpn-confinement-test.nix {
|
|
||||||
# inherit (self) nixosModules;
|
|
||||||
# };
|
|
||||||
});
|
|
||||||
|
|
||||||
devShells = forAllSystems ({pkgs}: {
|
|
||||||
default = pkgs.mkShell {
|
|
||||||
packages = with pkgs; [
|
|
||||||
alejandra
|
|
||||||
nixd
|
|
||||||
];
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
packages = forAllSystems ({pkgs}: let
|
|
||||||
website = website-builder.lib {
|
|
||||||
pkgs = pkgs;
|
|
||||||
src = "${self}";
|
|
||||||
timestamp = self.lastModified;
|
|
||||||
headerTitle = "Nixarr";
|
|
||||||
standalonePages = [
|
|
||||||
{
|
|
||||||
title = "Nixarr - Media Server Nixos Module";
|
|
||||||
inputFile = ./README.md;
|
|
||||||
outputFile = "index.html";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
includedDirs = ["docs"];
|
|
||||||
articleDirs = ["docs/wiki"];
|
|
||||||
navbar = [
|
|
||||||
{
|
|
||||||
title = "Home";
|
|
||||||
location = "/";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
title = "Options";
|
|
||||||
location = "/nixos-options";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
title = "Wiki";
|
|
||||||
location = "/wiki";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
title = "Github";
|
|
||||||
location = "https://github.com/rasmus-kirk/nixarr";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
favicons = {
|
|
||||||
# For all browsers
|
|
||||||
"16x16" = "/docs/img/favicons/16x16.png";
|
|
||||||
"32x32" = "/docs/img/favicons/32x32.png";
|
|
||||||
# For Google and Android
|
|
||||||
"48x48" = "/docs/img/favicons/48x48.png";
|
|
||||||
"192x192" = "/docs/img/favicons/192x192.png";
|
|
||||||
# For iPad
|
|
||||||
"167x167" = "/docs/img/favicons/167x167.png";
|
|
||||||
# For iPhone
|
|
||||||
"180x180" = "/docs/img/favicons/180x180.png";
|
|
||||||
};
|
};
|
||||||
nixosModules = ./nixarr;
|
simple-test = pkgs.callPackage ./tests/simple-test.nix {
|
||||||
};
|
inherit (self) nixosModules;
|
||||||
in {
|
};
|
||||||
default = website.package;
|
# vpn-confinement-test = pkgs.callPackage ./tests/vpn-confinement-test.nix {
|
||||||
debug = website.loop;
|
# inherit (self) nixosModules;
|
||||||
});
|
# };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
devShells = forAllSystems (
|
||||||
|
{pkgs}: {
|
||||||
|
default = pkgs.mkShell {
|
||||||
|
packages = with pkgs; [
|
||||||
|
alejandra
|
||||||
|
nixd
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
packages = forAllSystems (
|
||||||
|
{pkgs}: let
|
||||||
|
website = website-builder.lib {
|
||||||
|
pkgs = pkgs;
|
||||||
|
src = "${self}";
|
||||||
|
timestamp = self.lastModified;
|
||||||
|
headerTitle = "Nixarr";
|
||||||
|
standalonePages = [
|
||||||
|
{
|
||||||
|
title = "Nixarr - Media Server Nixos Module";
|
||||||
|
inputFile = ./README.md;
|
||||||
|
outputFile = "index.html";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
includedDirs = ["docs"];
|
||||||
|
articleDirs = ["docs/wiki"];
|
||||||
|
navbar = [
|
||||||
|
{
|
||||||
|
title = "Home";
|
||||||
|
location = "/";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
title = "Options";
|
||||||
|
location = "/nixos-options";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
title = "Wiki";
|
||||||
|
location = "/wiki";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
title = "Github";
|
||||||
|
location = "https://github.com/nix-media-server/nixarr";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
favicons = {
|
||||||
|
# For all browsers
|
||||||
|
"16x16" = "/docs/img/favicons/16x16.png";
|
||||||
|
"32x32" = "/docs/img/favicons/32x32.png";
|
||||||
|
# For Google and Android
|
||||||
|
"48x48" = "/docs/img/favicons/48x48.png";
|
||||||
|
"192x192" = "/docs/img/favicons/192x192.png";
|
||||||
|
# For iPad
|
||||||
|
"167x167" = "/docs/img/favicons/167x167.png";
|
||||||
|
# For iPhone
|
||||||
|
"180x180" = "/docs/img/favicons/180x180.png";
|
||||||
|
};
|
||||||
|
nixosModules = ./nixarr;
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
default = website.package;
|
||||||
|
debug = website.loop;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
formatter = forAllSystems ({pkgs}: pkgs.alejandra);
|
formatter = forAllSystems ({pkgs}: pkgs.alejandra);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ in {
|
|||||||
Group = globals.bazarr.group;
|
Group = globals.bazarr.group;
|
||||||
SyslogIdentifier = "bazarr";
|
SyslogIdentifier = "bazarr";
|
||||||
ExecStart = pkgs.writeShellScript "start-bazarr" ''
|
ExecStart = pkgs.writeShellScript "start-bazarr" ''
|
||||||
${pkgs.bazarr}/bin/bazarr \
|
${cfg.package}/bin/bazarr \
|
||||||
--config '${cfg.stateDir}' \
|
--config '${cfg.stateDir}' \
|
||||||
--port ${toString cfg.port} \
|
--port ${toString cfg.port} \
|
||||||
--no-update True
|
--no-update True
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
# Utilities for defining *arr service settings, options, and configs.
|
||||||
|
#
|
||||||
|
# Copied from nixpkgs master as of 2025-11-11: https://raw.githubusercontent.com/NixOS/nixpkgs/cf540f8c9840457ed90a315dd635bceecb78495a/nixos/modules/services/misc/servarr/settings-options.nix
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
}: {
|
||||||
|
mkServarrSettingsOptions = name: port:
|
||||||
|
lib.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
freeformType = (pkgs.formats.ini {}).type;
|
||||||
|
options = {
|
||||||
|
update = {
|
||||||
|
mechanism = lib.mkOption {
|
||||||
|
type = with lib.types;
|
||||||
|
nullOr (enum [
|
||||||
|
"external"
|
||||||
|
"builtIn"
|
||||||
|
"script"
|
||||||
|
]);
|
||||||
|
description = "which update mechanism to use";
|
||||||
|
default = "external";
|
||||||
|
};
|
||||||
|
automatically = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Automatically download and install updates.";
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
server = {
|
||||||
|
port = lib.mkOption {
|
||||||
|
type = lib.types.port;
|
||||||
|
description = "Port Number";
|
||||||
|
default = port;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
log = {
|
||||||
|
analyticsEnabled = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = "Send Anonymous Usage Data";
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
example = lib.options.literalExpression ''
|
||||||
|
{
|
||||||
|
update.mechanism = "internal";
|
||||||
|
server = {
|
||||||
|
urlbase = "localhost";
|
||||||
|
port = ${toString port};
|
||||||
|
bindaddress = "*";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
Attribute set of arbitrary config options.
|
||||||
|
Please consult the documentation at the [wiki](https://wiki.servarr.com/useful-tools#using-environment-variables-for-config).
|
||||||
|
|
||||||
|
WARNING: this configuration is stored in the world-readable Nix store!
|
||||||
|
For secrets use [](#opt-services.${name}.environmentFiles).
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
mkServarrEnvironmentFiles = name:
|
||||||
|
lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.path;
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
Environment file to pass secret configuration values.
|
||||||
|
Each line must follow the `${lib.toUpper name}__SECTION__KEY=value` pattern.
|
||||||
|
Please consult the documentation at the [wiki](https://wiki.servarr.com/useful-tools#using-environment-variables-for-config).
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
mkServarrSettingsEnvVars = name: settings:
|
||||||
|
lib.pipe settings [
|
||||||
|
(lib.mapAttrsRecursive (
|
||||||
|
path: value:
|
||||||
|
lib.optionalAttrs (value != null) {
|
||||||
|
name = lib.toUpper "${name}__${lib.concatStringsSep "__" path}";
|
||||||
|
value = toString (
|
||||||
|
if lib.isBool value
|
||||||
|
then lib.boolToString value
|
||||||
|
else value
|
||||||
|
);
|
||||||
|
}
|
||||||
|
))
|
||||||
|
(lib.collect (x: lib.isString x.name or false && lib.isString x.value or false))
|
||||||
|
lib.listToAttrs
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -6,9 +6,12 @@
|
|||||||
}:
|
}:
|
||||||
with lib; let
|
with lib; let
|
||||||
cfg = config.nixarr.readarr-audiobook;
|
cfg = config.nixarr.readarr-audiobook;
|
||||||
|
service-cfg = config.services.readarr-audiobook;
|
||||||
globals = config.util-nixarr.globals;
|
globals = config.util-nixarr.globals;
|
||||||
nixarr = config.nixarr;
|
nixarr = config.nixarr;
|
||||||
port = 9494;
|
port = 9494;
|
||||||
|
|
||||||
|
arr-settings-options = import ../lib/arr-settings-options.nix {inherit lib pkgs;};
|
||||||
in {
|
in {
|
||||||
options.nixarr.readarr-audiobook = {
|
options.nixarr.readarr-audiobook = {
|
||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
@@ -69,6 +72,46 @@ in {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# A tweaked copy of services.readarr from nixpkgs
|
||||||
|
options.services.readarr-audiobook = {
|
||||||
|
enable = lib.mkEnableOption "Readarr-Audiobook, a Usenet/BitTorrent audiobook downloader";
|
||||||
|
|
||||||
|
dataDir = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "The directory where Readarr-Audiobook stores its data files.";
|
||||||
|
};
|
||||||
|
|
||||||
|
package = lib.mkPackageOption pkgs "readarr" {};
|
||||||
|
|
||||||
|
openFirewall = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = ''
|
||||||
|
Open ports in the firewall for Readarr-Audiobook.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# Uses name in description to refer to
|
||||||
|
# `services.readarr-audiobook.environmentFiles`.
|
||||||
|
settings = arr-settings-options.mkServarrSettingsOptions "readarr-audiobook" port;
|
||||||
|
|
||||||
|
# Uses name in description to document `READARR__*` environment variables.
|
||||||
|
environmentFiles = arr-settings-options.mkServarrEnvironmentFiles "readarr";
|
||||||
|
|
||||||
|
user = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = ''
|
||||||
|
User account under which Readarr-Audiobook runs.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
group = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = ''
|
||||||
|
Group under which Readarr-Audiobook runs.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
config = mkIf (nixarr.enable && cfg.enable) {
|
config = mkIf (nixarr.enable && cfg.enable) {
|
||||||
assertions = [
|
assertions = [
|
||||||
{
|
{
|
||||||
@@ -96,17 +139,30 @@ in {
|
|||||||
"d '${nixarr.mediaDir}/library/audiobooks' 0775 ${globals.libraryOwner.user} ${globals.libraryOwner.group} - -"
|
"d '${nixarr.mediaDir}/library/audiobooks' 0775 ${globals.libraryOwner.user} ${globals.libraryOwner.group} - -"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
services.readarr-audiobook = {
|
||||||
|
enable = cfg.enable;
|
||||||
|
package = cfg.package;
|
||||||
|
settings.server.port = cfg.port;
|
||||||
|
openFirewall = cfg.openFirewall;
|
||||||
|
dataDir = cfg.stateDir;
|
||||||
|
user = globals.readarr-audiobook.user;
|
||||||
|
group = globals.readarr-audiobook.group;
|
||||||
|
};
|
||||||
|
|
||||||
systemd.services.readarr-audiobook = {
|
systemd.services.readarr-audiobook = {
|
||||||
description = "Readarr-Audiobook";
|
description = "Readarr-Audiobook";
|
||||||
after = ["network.target"];
|
after = ["network.target"];
|
||||||
wantedBy = ["multi-user.target"];
|
wantedBy = ["multi-user.target"];
|
||||||
environment.READARR__SERVER__PORT = builtins.toString cfg.port;
|
|
||||||
|
# Uses name to define `READARR__*` environment variables.
|
||||||
|
environment = arr-settings-options.mkServarrSettingsEnvVars "readarr" service-cfg.settings;
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "simple";
|
Type = "simple";
|
||||||
User = globals.readarr-audiobook.user;
|
User = service-cfg.user;
|
||||||
Group = globals.readarr-audiobook.group;
|
Group = service-cfg.group;
|
||||||
ExecStart = "${lib.getExe cfg.package} -nobrowser -data=${cfg.stateDir}";
|
EnvironmentFile = service-cfg.environmentFiles;
|
||||||
|
ExecStart = "${lib.getExe service-cfg.package} -nobrowser -data=${service-cfg.dataDir}";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -94,19 +94,14 @@ in {
|
|||||||
"d '${nixarr.mediaDir}/library/books' 0775 ${globals.libraryOwner.user} ${globals.libraryOwner.group} - -"
|
"d '${nixarr.mediaDir}/library/books' 0775 ${globals.libraryOwner.user} ${globals.libraryOwner.group} - -"
|
||||||
];
|
];
|
||||||
|
|
||||||
systemd.services.readarr = {
|
services.readarr = {
|
||||||
description = "Readarr";
|
enable = cfg.enable;
|
||||||
after = ["network.target"];
|
package = cfg.package;
|
||||||
wantedBy = ["multi-user.target"];
|
settings.server.port = cfg.port;
|
||||||
environment.READARR__SERVER__PORT = builtins.toString cfg.port;
|
openFirewall = cfg.openFirewall;
|
||||||
|
dataDir = cfg.stateDir;
|
||||||
serviceConfig = {
|
user = globals.readarr.user;
|
||||||
Type = "simple";
|
group = globals.readarr.group;
|
||||||
User = globals.readarr.user;
|
|
||||||
Group = globals.readarr.group;
|
|
||||||
ExecStart = "${lib.getExe cfg.package} -nobrowser -data=${cfg.stateDir}";
|
|
||||||
Restart = "on-failure";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall = mkIf cfg.openFirewall {
|
networking.firewall = mkIf cfg.openFirewall {
|
||||||
|
|||||||
@@ -8,7 +8,57 @@ with lib; let
|
|||||||
cfg = config.nixarr.recyclarr;
|
cfg = config.nixarr.recyclarr;
|
||||||
globals = config.util-nixarr.globals;
|
globals = config.util-nixarr.globals;
|
||||||
nixarr = config.nixarr;
|
nixarr = config.nixarr;
|
||||||
format = pkgs.formats.yaml {};
|
# This is a carbon copy of the yaml implementation in nixpkgs https://github.com/NixOS/nixpkgs/blob/fde6c4aec177afa2d0248b1c5983e2a72a231442/pkgs/pkgs-lib/formats.nix#L210-L231
|
||||||
|
# except we've replaced json2yaml for yq-go to allow it to parse custom yaml tags
|
||||||
|
# ideally this would some day be upstreamed, see https://github.com/NixOS/nix/issues/4910 and https://github.com/nix-media-server/nixarr/issues/91
|
||||||
|
yamlGenerator = {preserved-tags ? []}: let
|
||||||
|
selectors =
|
||||||
|
pkgs.lib.strings.concatStringsSep "|"
|
||||||
|
(builtins.map (
|
||||||
|
# this is yq for "for all the scalers, if they match this regex, do a regex substitution and set the tag"
|
||||||
|
x: ''
|
||||||
|
with((.. | select(kind == "scalar") | select(tag == "!!str") | select(test("^!${x} .*"))); . = sub("!${x} ", "") | . tag="!${x}")
|
||||||
|
''
|
||||||
|
)
|
||||||
|
preserved-tags);
|
||||||
|
in {
|
||||||
|
generate = name: value:
|
||||||
|
pkgs.callPackage (
|
||||||
|
{
|
||||||
|
runCommand,
|
||||||
|
yq-go,
|
||||||
|
}:
|
||||||
|
runCommand name
|
||||||
|
{
|
||||||
|
nativeBuildInputs = [yq-go];
|
||||||
|
value = builtins.toJSON value;
|
||||||
|
passAsFile = ["value"];
|
||||||
|
preferLocalBuild = true;
|
||||||
|
}
|
||||||
|
''
|
||||||
|
yq '${selectors}' "$valuePath" -o yaml > $out
|
||||||
|
''
|
||||||
|
) {};
|
||||||
|
type = let
|
||||||
|
baseType = pkgs.lib.types.oneOf [
|
||||||
|
pkgs.lib.types.bool
|
||||||
|
pkgs.lib.types.int
|
||||||
|
pkgs.lib.types.float
|
||||||
|
pkgs.lib.types.str
|
||||||
|
(pkgs.lib.types.attrsOf valueType)
|
||||||
|
(pkgs.lib.types.listOf valueType)
|
||||||
|
];
|
||||||
|
valueType =
|
||||||
|
(pkgs.lib.types.nullOr baseType)
|
||||||
|
// {
|
||||||
|
description = "Yaml value";
|
||||||
|
};
|
||||||
|
in
|
||||||
|
valueType;
|
||||||
|
};
|
||||||
|
format = yamlGenerator {
|
||||||
|
preserved-tags = ["env_var"];
|
||||||
|
};
|
||||||
|
|
||||||
# Generate configuration file from Nix attribute set if provided
|
# Generate configuration file from Nix attribute set if provided
|
||||||
generatedConfigFile = format.generate "recyclarr-config.yml" cfg.configuration;
|
generatedConfigFile = format.generate "recyclarr-config.yml" cfg.configuration;
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ with lib; let
|
|||||||
runtimeInputs = with pkgs; [yq];
|
runtimeInputs = with pkgs; [yq];
|
||||||
|
|
||||||
text = ''
|
text = ''
|
||||||
|
while [ ! -f "${nixarr.prowlarr.stateDir}/config.xml" ]; do
|
||||||
|
echo "Waiting for prowlarr to start..."
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
touch ${cfg.stateDir}/prowlarr-api-key
|
touch ${cfg.stateDir}/prowlarr-api-key
|
||||||
chmod 400 ${cfg.stateDir}/prowlarr-api-key
|
chmod 400 ${cfg.stateDir}/prowlarr-api-key
|
||||||
chown ${globals.transmission.user} ${cfg.stateDir}/prowlarr-api-key
|
chown ${globals.transmission.user} ${cfg.stateDir}/prowlarr-api-key
|
||||||
@@ -49,6 +54,12 @@ with lib; let
|
|||||||
+ ''
|
+ ''
|
||||||
TMP_JSON=$(mktemp)
|
TMP_JSON=$(mktemp)
|
||||||
CRED_FILE="/run/secrets/cross-seed/credentialsFile.json"
|
CRED_FILE="/run/secrets/cross-seed/credentialsFile.json"
|
||||||
|
|
||||||
|
while [ ! -f "${nixarr.prowlarr.stateDir}/config.xml" ]; do
|
||||||
|
echo "Waiting for prowlarr to start..."
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
PROWLARR_API_KEY=$(xq -r '.Config.ApiKey' "${nixarr.prowlarr.stateDir}/config.xml")
|
PROWLARR_API_KEY=$(xq -r '.Config.ApiKey' "${nixarr.prowlarr.stateDir}/config.xml")
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
CRED_DIR=$(dirname "$CRED_FILE")
|
CRED_DIR=$(dirname "$CRED_FILE")
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
nixosModules,
|
nixosModules,
|
||||||
lib ? pkgs.lib,
|
lib ? pkgs.lib,
|
||||||
}:
|
}:
|
||||||
pkgs.nixosTest {
|
pkgs.testers.nixosTest {
|
||||||
name = "nixarr-permissions-test";
|
name = "nixarr-permissions-test";
|
||||||
|
|
||||||
nodes.machine = {
|
nodes.machine = {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
nixosModules,
|
nixosModules,
|
||||||
lib ? pkgs.lib,
|
lib ? pkgs.lib,
|
||||||
}:
|
}:
|
||||||
pkgs.nixosTest {
|
pkgs.testers.nixosTest {
|
||||||
name = "simple-test";
|
name = "simple-test";
|
||||||
|
|
||||||
nodes.machine = {
|
nodes.machine = {
|
||||||
|
|||||||
@@ -43,19 +43,27 @@ The test ensures that:
|
|||||||
wgGatewayPort = 51820;
|
wgGatewayPort = 51820;
|
||||||
|
|
||||||
# Generate real WireGuard keys
|
# Generate real WireGuard keys
|
||||||
wgGatewayPrivateKey = pkgs.runCommand "wg-gateway-private" {buildInputs = [pkgs.wireguard-tools];} ''
|
wgGatewayPrivateKey =
|
||||||
wg genkey > $out
|
pkgs.runCommand "wg-gateway-private" {buildInputs = [pkgs.wireguard-tools];}
|
||||||
'';
|
''
|
||||||
wgGatewayPublicKey = pkgs.runCommand "wg-gateway-public" {buildInputs = [pkgs.wireguard-tools];} ''
|
wg genkey > $out
|
||||||
cat ${wgGatewayPrivateKey} | wg pubkey > $out
|
'';
|
||||||
'';
|
wgGatewayPublicKey =
|
||||||
|
pkgs.runCommand "wg-gateway-public" {buildInputs = [pkgs.wireguard-tools];}
|
||||||
|
''
|
||||||
|
cat ${wgGatewayPrivateKey} | wg pubkey > $out
|
||||||
|
'';
|
||||||
|
|
||||||
wgClientPrivateKey = pkgs.runCommand "wg-client-private" {buildInputs = [pkgs.wireguard-tools];} ''
|
wgClientPrivateKey =
|
||||||
wg genkey > $out
|
pkgs.runCommand "wg-client-private" {buildInputs = [pkgs.wireguard-tools];}
|
||||||
'';
|
''
|
||||||
wgClientPublicKey = pkgs.runCommand "wg-client-public" {buildInputs = [pkgs.wireguard-tools];} ''
|
wg genkey > $out
|
||||||
cat ${wgClientPrivateKey} | wg pubkey > $out
|
'';
|
||||||
'';
|
wgClientPublicKey =
|
||||||
|
pkgs.runCommand "wg-client-public" {buildInputs = [pkgs.wireguard-tools];}
|
||||||
|
''
|
||||||
|
cat ${wgClientPrivateKey} | wg pubkey > $out
|
||||||
|
'';
|
||||||
|
|
||||||
# Network configuration
|
# Network configuration
|
||||||
wgGatewayAddr = "10.100.0.1";
|
wgGatewayAddr = "10.100.0.1";
|
||||||
@@ -92,7 +100,7 @@ The test ensures that:
|
|||||||
PersistentKeepalive = 25
|
PersistentKeepalive = 25
|
||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
pkgs.nixosTest {
|
pkgs.testers.nixosTest {
|
||||||
name = "nixarr-vpn-confinement-test";
|
name = "nixarr-vpn-confinement-test";
|
||||||
|
|
||||||
# Disable interactive mode to avoid hanging
|
# Disable interactive mode to avoid hanging
|
||||||
@@ -128,7 +136,10 @@ in
|
|||||||
"${internetClientIP}/24"
|
"${internetClientIP}/24"
|
||||||
"${internetClientIPv6}/64"
|
"${internetClientIPv6}/64"
|
||||||
];
|
];
|
||||||
gateway = ["${internetGatewayIP}" "${internetGatewayIPv6}"];
|
gateway = [
|
||||||
|
"${internetGatewayIP}"
|
||||||
|
"${internetGatewayIPv6}"
|
||||||
|
];
|
||||||
routes = [
|
routes = [
|
||||||
{
|
{
|
||||||
Destination = "${wgSubnet}";
|
Destination = "${wgSubnet}";
|
||||||
@@ -189,7 +200,10 @@ in
|
|||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}: {
|
}: {
|
||||||
virtualisation.vlans = [1 2]; # VLAN 1 for LAN, VLAN 2 for Internet
|
virtualisation.vlans = [
|
||||||
|
1
|
||||||
|
2
|
||||||
|
]; # VLAN 1 for LAN, VLAN 2 for Internet
|
||||||
|
|
||||||
networking = {
|
networking = {
|
||||||
interfaces.eth1 = {
|
interfaces.eth1 = {
|
||||||
@@ -224,19 +238,28 @@ in
|
|||||||
|
|
||||||
firewall = {
|
firewall = {
|
||||||
enable = true;
|
enable = true;
|
||||||
allowedUDPPorts = [wgGatewayPort 51413];
|
allowedUDPPorts = [
|
||||||
|
wgGatewayPort
|
||||||
|
51413
|
||||||
|
];
|
||||||
allowedTCPPorts = [51413];
|
allowedTCPPorts = [51413];
|
||||||
};
|
};
|
||||||
|
|
||||||
wireguard.interfaces.wg0 = {
|
wireguard.interfaces.wg0 = {
|
||||||
ips = ["${wgGatewayAddr}/24" "${wgGatewayAddrV6}/64"];
|
ips = [
|
||||||
|
"${wgGatewayAddr}/24"
|
||||||
|
"${wgGatewayAddrV6}/64"
|
||||||
|
];
|
||||||
listenPort = wgGatewayPort;
|
listenPort = wgGatewayPort;
|
||||||
privateKeyFile = "${wgGatewayPrivateKey}";
|
privateKeyFile = "${wgGatewayPrivateKey}";
|
||||||
|
|
||||||
peers = [
|
peers = [
|
||||||
{
|
{
|
||||||
publicKey = builtins.readFile wgClientPublicKey;
|
publicKey = builtins.readFile wgClientPublicKey;
|
||||||
allowedIPs = ["${wgClientAddr}/32" "${wgClientAddrV6}/128"];
|
allowedIPs = [
|
||||||
|
"${wgClientAddr}/32"
|
||||||
|
"${wgClientAddrV6}/128"
|
||||||
|
];
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user