vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / networking / pyload.nix
blob93f8dd7d731a93cb7033299961e2b1b24dca35cc
1 { config, lib, pkgs, utils, ... }:
2 let
3   cfg = config.services.pyload;
5   stateDir = "/var/lib/pyload";
6 in
8   meta.maintainers = with lib.maintainers; [ ambroisie ];
10   options = with lib; {
11     services.pyload = {
12       enable = mkEnableOption "pyLoad download manager";
14       package = mkPackageOption pkgs "pyLoad" { default = [ "pyload-ng" ]; };
16       listenAddress = mkOption {
17         type = types.str;
18         default = "localhost";
19         example = "0.0.0.0";
20         description = "Address to listen on for the web UI.";
21       };
23       port = mkOption {
24         type = types.port;
25         default = 8000;
26         example = 9876;
27         description = "Port to listen on for the web UI.";
28       };
30       downloadDirectory = mkOption {
31         type = types.path;
32         default = "${stateDir}/downloads";
33         example = "/mnt/downloads";
34         description = "Directory to store downloads.";
35       };
37       user = mkOption {
38         type = types.str;
39         default = "pyload";
40         description = "User under which pyLoad runs, and which owns the download directory.";
41       };
43       group = mkOption {
44         type = types.str;
45         default = "pyload";
46         description = "Group under which pyLoad runs, and which owns the download directory.";
47       };
49       credentialsFile = mkOption {
50         type = with types; nullOr path;
51         default = null;
52         example = "/run/secrets/pyload-credentials.env";
53         description = ''
54           File containing {env}`PYLOAD_DEFAULT_USERNAME` and
55           {env}`PYLOAD_DEFAULT_PASSWORD` in the format of an `EnvironmentFile=`,
56           as described by {manpage}`systemd.exec(5)`.
58           If not given, they default to the username/password combo of
59           pyload/pyload.
60         '';
61       };
62     };
63   };
65   config = lib.mkIf cfg.enable {
66     systemd.tmpfiles.settings.pyload = {
67       ${cfg.downloadDirectory}.d = { inherit (cfg) user group; };
68     };
70     systemd.services.pyload = {
71       description = "pyLoad download manager";
72       wantedBy = [ "multi-user.target" ];
73       after = [ "network.target" ];
75       # NOTE: unlike what the documentation says, it looks like `HOME` is not
76       # defined with this service definition...
77       # Since pyload tries to do the equivalent of `cd ~`, it needs to be able
78       # to resolve $HOME, which fails when `RootDirectory` is set.
79       # FIXME: check if `SetLoginEnvironment` fixes this issue in version 255
80       environment = {
81         HOME = stateDir;
82         PYLOAD__WEBUI__HOST = cfg.listenAddress;
83         PYLOAD__WEBUI__PORT = builtins.toString cfg.port;
84       };
86       serviceConfig = {
87         ExecStart = utils.escapeSystemdExecArgs [
88           (lib.getExe cfg.package)
89           "--userdir"
90           "${stateDir}/config"
91           "--storagedir"
92           cfg.downloadDirectory
93         ];
95         User = cfg.user;
96         Group = cfg.group;
98         EnvironmentFile = lib.optional (cfg.credentialsFile != null) cfg.credentialsFile;
100         StateDirectory = "pyload";
101         WorkingDirectory = stateDir;
102         RuntimeDirectory = "pyload";
103         RuntimeDirectoryMode = "0700";
104         RootDirectory = "/run/pyload";
105         BindReadOnlyPaths = [
106           builtins.storeDir # Needed to run the python interpreter
107         ];
108         BindPaths = [
109           cfg.downloadDirectory
110         ];
112         # Hardening options
113         LockPersonality = true;
114         NoNewPrivileges = true;
115         PrivateDevices = true;
116         PrivateMounts = true;
117         PrivateTmp = true;
118         PrivateUsers = true;
119         ProcSubset = "pid";
120         ProtectClock = true;
121         ProtectControlGroups = true;
122         ProtectHome = true;
123         ProtectHostname = true;
124         ProtectKernelLogs = true;
125         ProtectKernelModules = true;
126         ProtectKernelTunables = true;
127         ProtectProc = "invisible";
128         ProtectSystem = "strict";
129         RemoveIPC = true;
130         RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX";
131         RestrictNamespaces = true;
132         RestrictRealtime = true;
133         RestrictSUIDSGID = true;
134         SystemCallArchitectures = "native";
135         SystemCallFilter = [ "@system-service" "~@resources" "~@privileged" ];
136         UMask = "0002";
137         CapabilityBoundingSet = [
138           "~CAP_BLOCK_SUSPEND"
139           "~CAP_BPF"
140           "~CAP_CHOWN"
141           "~CAP_IPC_LOCK"
142           "~CAP_KILL"
143           "~CAP_LEASE"
144           "~CAP_LINUX_IMMUTABLE"
145           "~CAP_NET_ADMIN"
146           "~CAP_SYS_ADMIN"
147           "~CAP_SYS_BOOT"
148           "~CAP_SYS_CHROOT"
149           "~CAP_SYS_NICE"
150           "~CAP_SYS_PACCT"
151           "~CAP_SYS_PTRACE"
152           "~CAP_SYS_RESOURCE"
153           "~CAP_SYS_TTY_CONFIG"
154         ];
155       };
156     };
158     users.users.pyload = lib.mkIf (cfg.user == "pyload") {
159       isSystemUser = true;
160       group = cfg.group;
161       home = stateDir;
162     };
164     users.groups.pyload = lib.mkIf (cfg.group == "pyload") { };
165   };