From 139259a37711f4a38371ef47c391535ea8d00e90 Mon Sep 17 00:00:00 2001 From: ppom <38916722+ppom0@users.noreply.github.com> Date: Mon, 17 Jul 2023 18:40:54 +0200 Subject: [PATCH] slskd: init module (#233648) * slskd: init module * Update nixos/modules/services/web-apps/slskd.nix * Update nixos/modules/services/web-apps/slskd.nix * add description to slskd module options --------- Co-authored-by: ppom Co-authored-by: Sandro --- nixos/modules/module-list.nix | 1 + nixos/modules/services/web-apps/slskd.nix | 211 ++++++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 nixos/modules/services/web-apps/slskd.nix diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 97abbe21911..03337c5a248 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1255,6 +1255,7 @@ ./services/web-apps/rss-bridge.nix ./services/web-apps/selfoss.nix ./services/web-apps/shiori.nix + ./services/web-apps/slskd.nix ./services/web-apps/snipe-it.nix ./services/web-apps/sogo.nix ./services/web-apps/trilium.nix diff --git a/nixos/modules/services/web-apps/slskd.nix b/nixos/modules/services/web-apps/slskd.nix new file mode 100644 index 00000000000..33353a59440 --- /dev/null +++ b/nixos/modules/services/web-apps/slskd.nix @@ -0,0 +1,211 @@ +{ lib, pkgs, config, ... }: + +let + settingsFormat = pkgs.formats.yaml {}; +in { + options.services.slskd = with lib; with types; { + enable = mkEnableOption "enable slskd"; + + rotateLogs = mkEnableOption "enable an unit and timer that will rotate logs in /var/slskd/logs"; + + package = mkPackageOptionMD pkgs "slskd" { }; + + nginx = mkOption { + description = lib.mdDoc "options for nginx"; + example = { + enable = true; + domain = "example.com"; + contextPath = "/slskd"; + }; + type = submodule ({name, config, ...}: { + options = { + enable = mkEnableOption "enable nginx as a reverse proxy"; + + domainName = mkOption { + type = str; + description = "Domain you want to use"; + }; + contextPath = mkOption { + type = types.path; + default = "/"; + description = lib.mdDoc '' + The context path, i.e., the last part of the slskd + URL. Typically '/' or '/slskd'. Default '/' + ''; + }; + }; + }); + }; + + environmentFile = mkOption { + type = path; + description = '' + Path to a file containing secrets. + It must at least contain the variable `SLSKD_SLSK_PASSWORD` + ''; + }; + + openFirewall = mkOption { + type = bool; + description = '' + Whether to open the firewall for services.slskd.settings.listen_port"; + ''; + default = false; + }; + + settings = mkOption { + description = lib.mdDoc '' + Configuration for slskd, see + [available options](https://github.com/slskd/slskd/blob/master/docs/config.md) + `APP_DIR` is set to /var/lib/slskd, where default download & incomplete directories, + log and databases will be created. + ''; + default = {}; + type = submodule { + freeformType = settingsFormat.type; + options = { + + soulseek = { + username = mkOption { + type = str; + description = "Username on the Soulseek Network"; + }; + listen_port = mkOption { + type = port; + description = "Port to use for communication on the Soulseek Network"; + default = 50000; + }; + }; + + web = { + port = mkOption { + type = port; + default = 5001; + description = "The HTTP listen port"; + }; + url_base = mkOption { + type = path; + default = config.services.slskd.nginx.contextPath; + defaultText = "config.services.slskd.nginx.contextPath"; + description = lib.mdDoc '' + The context path, i.e., the last part of the slskd URL + ''; + }; + }; + + shares = { + directories = mkOption { + type = listOf str; + description = lib.mdDoc '' + Paths to your shared directories. See + [documentation](https://github.com/slskd/slskd/blob/master/docs/config.md#directories) + for advanced usage + ''; + }; + }; + + directories = { + incomplete = mkOption { + type = nullOr path; + description = "Directory where downloading files are stored"; + defaultText = "/incomplete"; + default = null; + }; + downloads = mkOption { + type = nullOr path; + description = "Directory where downloaded files are stored"; + defaultText = "/downloads"; + default = null; + }; + }; + }; + }; + }; + }; + + config = let + cfg = config.services.slskd; + + confWithoutNullValues = (lib.filterAttrs (key: value: value != null) cfg.settings); + + configurationYaml = settingsFormat.generate "slskd.yml" confWithoutNullValues; + + in lib.mkIf cfg.enable { + + users = { + users.slskd = { + isSystemUser = true; + group = "slskd"; + }; + groups.slskd = {}; + }; + + # Reverse proxy configuration + services.nginx.enable = true; + services.nginx.virtualHosts."${cfg.nginx.domainName}" = { + forceSSL = true; + enableACME = true; + locations = { + "${cfg.nginx.contextPath}" = { + proxyPass = "http://localhost:${toString cfg.settings.web.port}"; + proxyWebsockets = true; + }; + }; + }; + + # Hide state & logs + systemd.tmpfiles.rules = [ + "d /var/lib/slskd/data 0750 slskd slskd - -" + "d /var/lib/slskd/logs 0750 slskd slskd - -" + ]; + + systemd.services.slskd = { + description = "A modern client-server application for the Soulseek file sharing network"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "simple"; + User = "slskd"; + EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile; + StateDirectory = "slskd"; + ExecStart = "${cfg.package}/bin/slskd --app-dir /var/lib/slskd --config ${configurationYaml}"; + Restart = "on-failure"; + ReadOnlyPaths = map (d: builtins.elemAt (builtins.split "[^/]*(/.+)" d) 1) cfg.settings.shares.directories; + LockPersonality = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateMounts = true; + PrivateTmp = true; + PrivateUsers = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectSystem = "strict"; + RemoveIPC = true; + RestrictNamespaces = true; + RestrictSUIDSGID = true; + }; + }; + + networking.firewall.allowedTCPPorts = lib.optional cfg.openFirewall cfg.settings.soulseek.listen_port; + + systemd.services.slskd-rotatelogs = lib.mkIf cfg.rotateLogs { + description = "Rotate slskd logs"; + serviceConfig = { + Type = "oneshot"; + User = "slskd"; + ExecStart = [ + "${pkgs.findutils}/bin/find /var/lib/slskd/logs/ -type f -mtime +10 -delete" + "${pkgs.findutils}/bin/find /var/lib/slskd/logs/ -type f -mtime +1 -exec ${pkgs.gzip}/bin/gzip -q {} ';'" + ]; + }; + startAt = "daily"; + }; + + }; +}