Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions nixos/doc/manual/release-notes/rl-2605.section.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

- [DankMaterialShell](https://danklinux.com), a complete desktop shell for Wayland compositors built with Quickshell. Available as [programs.dms-shell](#opt-programs.dms-shell.enable).

- [nemorosa](https://github.com/KyokoMiki/nemorosa), cross-seeding tool specifically designed for Gazelle-based music trackers. Available as [services.nemorosa](#opt-services.nemorosa.enable).

- [dms-greeter](https://danklinux.com), a modern display manager greeter for DankMaterialShell that works with greetd and supports multiple Wayland compositors. Available as [services.displayManager.dms-greeter](#opt-services.displayManager.dms-greeter.enable).

- [dsearch](https://github.com/AvengeMedia/danksearch), a fast filesystem search service with fuzzy matching. Available as [programs.dsearch](#opt-programs.dsearch.enable).
Expand Down
1 change: 1 addition & 0 deletions nixos/modules/module-list.nix
Original file line number Diff line number Diff line change
Expand Up @@ -1551,6 +1551,7 @@
./services/torrent/flexget.nix
./services/torrent/flood.nix
./services/torrent/magnetico.nix
./services/torrent/nemorosa.nix
./services/torrent/opentracker.nix
./services/torrent/peerflix.nix
./services/torrent/qbittorrent.nix
Expand Down
185 changes: 185 additions & 0 deletions nixos/modules/services/torrent/nemorosa.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
{
config,
lib,
pkgs,
utils,
maintainers,
...
}:
let
cfg = config.services.nemorosa;

inherit (lib)
getExe
mkEnableOption
mkIf
mkOption
mkPackageOption
;
inherit (lib.types)
port
str
submodule
;

settingsFormat = pkgs.formats.yaml { };
stateDir = "/var/lib/nemorosa";
configPath = "${stateDir}/config.yaml";
# YAML is a JSON superset
secretsReplacement = utils.genJqSecretsReplacement {
loadCredential = true;
} cfg.settings configPath;
in
{
options.services.nemorosa = {
enable = mkEnableOption "nemorosa";

package = mkPackageOption pkgs "nemorosa" { };

user = mkOption {
type = str;
default = "nemorosa";
description = "User to run nemorosa as.";
};

group = mkOption {
type = str;
default = "nemorosa";
description = "Group to run nemorosa as.";
};

settings = mkOption {
description = ''
Configuration options for nemorosa.
See [the nemorosa documentation](https://github.com/KyokoMiki/nemorosa/wiki/Configuration)
for all configuration options.

The configuration is processed using [utils.genJqSecretsReplacement](https://github.com/NixOS/nixpkgs/blob/master/nixos/lib/utils.nix#L232-L331) to handle secret substitution.
Use this for sensitive configuration options.
'';
default = { };
example = {
linking = {
enable_linking = true;
link_dirs = [ "/mnt/some/folder" ];
};
downloader = {
client = {
_secret = "/run/secrets/torrent-client-url";
};
};
target_site = [
{
server = "https://someurl.com";
api_key = {
_secret = "/run/secrets/someurl_api-key";
};
}
];
};
type = submodule {
freeformType = settingsFormat.type;
options = {
server = mkOption {
default = { };
description = "Web server configuration";
type = submodule {
freeformType = settingsFormat.type;
options = {
host = mkOption {
type = str;
default = "127.0.0.1";
description = "Host address the nemorosa daemon listens on.";
};
port = mkOption {
type = port;
default = 8256;
description = "Port the nemorosa daemon listens on.";
};
};
};
};
};
};
};
};

config = mkIf (cfg.enable) {
systemd = {
services.nemorosa = {
description = "nemorosa";
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];

preStart = secretsReplacement.script;

serviceConfig = {
Type = "simple";
User = cfg.user;
Group = cfg.group;
# On partial matches the torrent client also needs to write to the
# link_dirs. With default 755/644 permissions this is not possible,
# unless the user is the same as the torrent client user.
UMask = mkIf (cfg.user == "nemorosa") "0002";
StateDirectory = "nemorosa";
LoadCredential = secretsReplacement.credentials;

ExecStart = "${getExe cfg.package} --server --config ${configPath}";

SocketBindDeny = "any";
SocketBindAllow = cfg.settings.server.port;

# Based the qbittorrent hardening settings
CapabilityBoundingSet = "";
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateNetwork = false;
PrivateTmp = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = "yes";
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "full";
RemoveIPC = true;
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_NETLINK"
"AF_UNIX"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
SystemCallFilter = [ "@system-service" ];
};
};
};

users = {
users = mkIf (cfg.user == "nemorosa") {
nemorosa = {
group = cfg.group;
description = "nemorosa user";
isSystemUser = true;
home = stateDir;
};
};

groups = mkIf (cfg.group == "nemorosa") {
nemorosa = { };
};
};
};

meta.maintainers = with maintainers; [ undefined-landmark ];
}
1 change: 1 addition & 0 deletions nixos/tests/all-tests.nix
Original file line number Diff line number Diff line change
Expand Up @@ -1037,6 +1037,7 @@ in
nebula-lighthouse-service = runTest ./nebula-lighthouse-service.nix;
nebula.connectivity = runTest ./nebula/connectivity.nix;
nebula.reload = runTest ./nebula/reload.nix;
nemorosa = runTest ./nemorosa.nix;
neo4j = runTest ./neo4j.nix;
netbird = runTest ./netbird.nix;
netbox-upgrade = runTest ./web-apps/netbox-upgrade.nix;
Expand Down
68 changes: 68 additions & 0 deletions nixos/tests/nemorosa.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{ lib, pkgs, ... }:
{
name = "nemorosa";

meta = with pkgs.lib.maintainers; {
maintainers = [
undefined-landmark
];
};

nodes.machine =
let
qbitUrl = "qbittorrent+http://user:adminadmin@localhost:8080/";
# We create this secret in the Nix store (making it readable by everyone).
# DO NOT DO THIS OUTSIDE OF TESTS!!
testSecret = pkgs.writeText "qbitUrl" qbitUrl;
in
{
services.qbittorrent = {
enable = true;
serverConfig.Preferences.WebUI = {
Username = "user";
# password: "adminadmin" as ByteArray
Password_PBKDF2 = "@ByteArray(6DIf26VOpTCYbgNiO6DAFQ==:e6241eaAWGzRotQZvVA5/up9fj5wwSAThLgXI2lVMsYTu1StUgX9MgmElU3Sa/M8fs+zqwZv9URiUOObjqJGNw==)";
};
};

services.nemorosa = {
enable = true;
settings.downloader.client = lib.mkDefault qbitUrl;
};

specialisation.secretSubstition.configuration = {
services.nemorosa = {
enable = true;
settings = {
downloader.client = {
_secret = toString testSecret;
};
server.port = 8266;
};
};
};
};

testScript =
{ nodes, ... }:
let
secretSubst = "${nodes.machine.system.build.toplevel}/specialisation/secretSubstition";
in
# python
''
machine.start()

# Nemorosa initialization expects an available API connection. So the
# service will not start successfully. Do some basic checks on the
# console log as an alternative.
def test_log(port):
machine.wait_for_console_text("Configuration loaded successfully from: /var/lib/nemorosa/config.yaml")
machine.wait_for_console_text(f"Starting Nemorosa web server on 127.0.0.1:{port}")
machine.wait_for_console_text("Successfully connected to torrent client")

test_log(8256)

machine.succeed("${secretSubst}/bin/switch-to-configuration test")
test_log(8266)
'';
}
5 changes: 5 additions & 0 deletions pkgs/by-name/ne/nemorosa/package.nix
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
lib,
fetchFromGitHub,
nixosTests,
python3Packages,
}:

Expand Down Expand Up @@ -54,6 +55,10 @@ python3Packages.buildPythonApplication rec {

pythonImportsCheck = [ "nemorosa" ];

passthru = {
tests.testService = nixosTests.nemorosa;
};

meta = {
description = "Specialized cross-seeding tool designed for music torrents";
homepage = "https://github.com/KyokoMiki/nemorosa";
Expand Down
Loading