diff options
Diffstat (limited to 'nixos/modules/services/misc')
19 files changed, 255 insertions, 96 deletions
diff --git a/nixos/modules/services/misc/amazon-ssm-agent.nix b/nixos/modules/services/misc/amazon-ssm-agent.nix index 20b836abe164..89a1c0766510 100644 --- a/nixos/modules/services/misc/amazon-ssm-agent.nix +++ b/nixos/modules/services/misc/amazon-ssm-agent.nix @@ -41,6 +41,7 @@ in { # See https://github.com/aws/amazon-ssm-agent/blob/mainline/packaging/linux/amazon-ssm-agent.service systemd.services.amazon-ssm-agent = { inherit (cfg.package.meta) description; + wants = [ "network-online.target" ]; after = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; diff --git a/nixos/modules/services/misc/bcg.nix b/nixos/modules/services/misc/bcg.nix index 9da4a879cdd0..ad0b9c871342 100644 --- a/nixos/modules/services/misc/bcg.nix +++ b/nixos/modules/services/misc/bcg.nix @@ -154,7 +154,7 @@ in in { description = "BigClown Gateway"; wantedBy = [ "multi-user.target" ]; - wants = mkIf config.services.mosquitto.enable [ "mosquitto.service" ]; + wants = [ "network-online.target" ] ++ lib.optional config.services.mosquitto.enable "mosquitto.service"; after = [ "network-online.target" ]; preStart = '' umask 077 diff --git a/nixos/modules/services/misc/domoticz.nix b/nixos/modules/services/misc/domoticz.nix index fd9fcf0b78eb..315092f93351 100644 --- a/nixos/modules/services/misc/domoticz.nix +++ b/nixos/modules/services/misc/domoticz.nix @@ -35,6 +35,7 @@ in { systemd.services."domoticz" = { description = pkgDesc; wantedBy = [ "multi-user.target" ]; + wants = [ "network-online.target" ]; after = [ "network-online.target" ]; serviceConfig = { DynamicUser = true; diff --git a/nixos/modules/services/misc/etcd.nix b/nixos/modules/services/misc/etcd.nix index 73bdeb3b0afd..ee6a56db31d3 100644 --- a/nixos/modules/services/misc/etcd.nix +++ b/nixos/modules/services/misc/etcd.nix @@ -152,9 +152,10 @@ in { }; config = mkIf cfg.enable { - systemd.tmpfiles.rules = [ - "d '${cfg.dataDir}' 0700 etcd - - -" - ]; + systemd.tmpfiles.settings."10-etcd".${cfg.dataDir}.d = { + user = "etcd"; + mode = "0700"; + }; systemd.services.etcd = { description = "etcd key-value store"; diff --git a/nixos/modules/services/misc/etesync-dav.nix b/nixos/modules/services/misc/etesync-dav.nix index 9d99d548d95b..ae2b5ad04343 100644 --- a/nixos/modules/services/misc/etesync-dav.nix +++ b/nixos/modules/services/misc/etesync-dav.nix @@ -59,6 +59,7 @@ in systemd.services.etesync-dav = { description = "etesync-dav - A CalDAV and CardDAV adapter for EteSync"; + wants = [ "network-online.target" ]; after = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; path = [ pkgs.etesync-dav ]; diff --git a/nixos/modules/services/misc/lidarr.nix b/nixos/modules/services/misc/lidarr.nix index 4dc0fc63863b..8ceb567e8801 100644 --- a/nixos/modules/services/misc/lidarr.nix +++ b/nixos/modules/services/misc/lidarr.nix @@ -45,9 +45,10 @@ in }; config = mkIf cfg.enable { - systemd.tmpfiles.rules = [ - "d '${cfg.dataDir}' 0700 ${cfg.user} ${cfg.group} - -" - ]; + systemd.tmpfiles.settings."10-lidarr".${cfg.dataDir}.d = { + inherit (cfg) user group; + mode = "0700"; + }; systemd.services.lidarr = { description = "Lidarr"; diff --git a/nixos/modules/services/misc/llama-cpp.nix b/nixos/modules/services/misc/llama-cpp.nix new file mode 100644 index 000000000000..4d76456fb2fd --- /dev/null +++ b/nixos/modules/services/misc/llama-cpp.nix @@ -0,0 +1,111 @@ +{ config, lib, pkgs, utils, ... }: + +let + cfg = config.services.llama-cpp; +in { + + options = { + + services.llama-cpp = { + enable = lib.mkEnableOption "LLaMA C++ server"; + + package = lib.mkPackageOption pkgs "llama-cpp" { }; + + model = lib.mkOption { + type = lib.types.path; + example = "/models/mistral-instruct-7b/ggml-model-q4_0.gguf"; + description = "Model path."; + }; + + extraFlags = lib.mkOption { + type = lib.types.listOf lib.types.str; + description = "Extra flags passed to llama-cpp-server."; + example = ["-c" "4096" "-ngl" "32" "--numa"]; + default = []; + }; + + host = lib.mkOption { + type = lib.types.str; + default = "127.0.0.1"; + example = "0.0.0.0"; + description = "IP address the LLaMA C++ server listens on."; + }; + + port = lib.mkOption { + type = lib.types.port; + default = 8080; + description = "Listen port for LLaMA C++ server."; + }; + + openFirewall = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Open ports in the firewall for LLaMA C++ server."; + }; + }; + + }; + + config = lib.mkIf cfg.enable { + + systemd.services.llama-cpp = { + description = "LLaMA C++ server"; + after = ["network.target"]; + wantedBy = ["multi-user.target"]; + + serviceConfig = { + Type = "idle"; + KillSignal = "SIGINT"; + ExecStart = "${cfg.package}/bin/llama-cpp-server --log-disable --host ${cfg.host} --port ${builtins.toString cfg.port} -m ${cfg.model} ${utils.escapeSystemdExecArgs cfg.extraFlags}"; + Restart = "on-failure"; + RestartSec = 300; + + # for GPU acceleration + PrivateDevices = false; + + # hardening + DynamicUser = true; + CapabilityBoundingSet = ""; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + "AF_UNIX" + ]; + NoNewPrivileges = true; + PrivateMounts = true; + PrivateTmp = true; + PrivateUsers = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectSystem = "strict"; + MemoryDenyWriteExecute = true; + LockPersonality = true; + RemoveIPC = true; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ + "@system-service" + "~@privileged" + "~@resources" + ]; + SystemCallErrorNumber = "EPERM"; + ProtectProc = "invisible"; + ProtectHostname = true; + ProcSubset = "pid"; + }; + }; + + networking.firewall = lib.mkIf cfg.openFirewall { + allowedTCPPorts = [ cfg.port ]; + }; + + }; + + meta.maintainers = with lib.maintainers; [ newam ]; +} diff --git a/nixos/modules/services/misc/mediatomb.nix b/nixos/modules/services/misc/mediatomb.nix index d421d74c53ad..03235e9a1265 100644 --- a/nixos/modules/services/misc/mediatomb.nix +++ b/nixos/modules/services/misc/mediatomb.nix @@ -357,6 +357,7 @@ in { description = "${cfg.serverName} media Server"; # Gerbera might fail if the network interface is not available on startup # https://github.com/gerbera/gerbera/issues/1324 + wants = [ "network-online.target" ]; after = [ "network.target" "network-online.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig.ExecStart = "${binaryCommand} --port ${toString cfg.port} ${interfaceFlag} ${configFlag} --home ${cfg.dataDir}"; diff --git a/nixos/modules/services/misc/metabase.nix b/nixos/modules/services/misc/metabase.nix index 883fa0b95911..5fc18e27eaae 100644 --- a/nixos/modules/services/misc/metabase.nix +++ b/nixos/modules/services/misc/metabase.nix @@ -77,6 +77,7 @@ in { systemd.services.metabase = { description = "Metabase server"; wantedBy = [ "multi-user.target" ]; + wants = [ "network-online.target" ]; after = [ "network-online.target" ]; environment = { MB_PLUGINS_DIR = "${dataDir}/plugins"; diff --git a/nixos/modules/services/misc/moonraker.nix b/nixos/modules/services/misc/moonraker.nix index 750dca9d0373..f043cc83bf05 100644 --- a/nixos/modules/services/misc/moonraker.nix +++ b/nixos/modules/services/misc/moonraker.nix @@ -103,17 +103,18 @@ in { config = mkIf cfg.enable { warnings = [] - ++ optional (cfg.settings ? update_manager) - ''Enabling update_manager is not supported on NixOS and will lead to non-removable warnings in some clients.'' - ++ optional (cfg.configDir != null) - '' - services.moonraker.configDir has been deprecated upstream and will be removed. - - Action: ${ - if cfg.configDir == unifiedConfigDir then "Simply remove services.moonraker.configDir from your config." - else "Move files from `${cfg.configDir}` to `${unifiedConfigDir}` then remove services.moonraker.configDir from your config." - } - ''; + ++ (optional (head (cfg.settings.update_manager.enable_system_updates or [false])) '' + Enabling system updates is not supported on NixOS and will lead to non-removable warnings in some clients. + '') + ++ (optional (cfg.configDir != null) '' + services.moonraker.configDir has been deprecated upstream and will be removed. + + Action: ${ + if cfg.configDir == unifiedConfigDir + then "Simply remove services.moonraker.configDir from your config." + else "Move files from `${cfg.configDir}` to `${unifiedConfigDir}` then remove services.moonraker.configDir from your config." + } + ''); assertions = [ { diff --git a/nixos/modules/services/misc/nix-gc.nix b/nixos/modules/services/misc/nix-gc.nix index 97596d28cd89..de6bd76c7eb9 100644 --- a/nixos/modules/services/misc/nix-gc.nix +++ b/nixos/modules/services/misc/nix-gc.nix @@ -1,7 +1,5 @@ { config, lib, ... }: -with lib; - let cfg = config.nix.gc; in @@ -14,14 +12,14 @@ in nix.gc = { - automatic = mkOption { + automatic = lib.mkOption { default = false; - type = types.bool; + type = lib.types.bool; description = lib.mdDoc "Automatically run the garbage collector at a specific time."; }; - dates = mkOption { - type = types.str; + dates = lib.mkOption { + type = lib.types.singleLineStr; default = "03:15"; example = "weekly"; description = lib.mdDoc '' @@ -33,9 +31,9 @@ in ''; }; - randomizedDelaySec = mkOption { + randomizedDelaySec = lib.mkOption { default = "0"; - type = types.str; + type = lib.types.singleLineStr; example = "45min"; description = lib.mdDoc '' Add a randomized delay before each garbage collection. @@ -45,9 +43,9 @@ in ''; }; - persistent = mkOption { + persistent = lib.mkOption { default = true; - type = types.bool; + type = lib.types.bool; example = false; description = lib.mdDoc '' Takes a boolean argument. If true, the time when the service @@ -61,10 +59,10 @@ in ''; }; - options = mkOption { + options = lib.mkOption { default = ""; example = "--max-freed $((64 * 1024**3))"; - type = types.str; + type = lib.types.singleLineStr; description = lib.mdDoc '' Options given to {file}`nix-collect-garbage` when the garbage collector is run automatically. @@ -89,7 +87,8 @@ in systemd.services.nix-gc = lib.mkIf config.nix.enable { description = "Nix Garbage Collector"; script = "exec ${config.nix.package.out}/bin/nix-collect-garbage ${cfg.options}"; - startAt = optional cfg.automatic cfg.dates; + serviceConfig.Type = "oneshot"; + startAt = lib.optional cfg.automatic cfg.dates; }; systemd.timers.nix-gc = lib.mkIf cfg.automatic { diff --git a/nixos/modules/services/misc/nix-ssh-serve.nix b/nixos/modules/services/misc/nix-ssh-serve.nix index b656692ca01c..cf9d6339c69b 100644 --- a/nixos/modules/services/misc/nix-ssh-serve.nix +++ b/nixos/modules/services/misc/nix-ssh-serve.nix @@ -1,4 +1,4 @@ -{ config, lib, ... }: +{ config, lib, pkgs, ... }: with lib; let cfg = config.nix.sshServe; @@ -46,7 +46,7 @@ in { description = "Nix SSH store user"; isSystemUser = true; group = "nix-ssh"; - useDefaultShell = true; + shell = pkgs.bashInteractive; }; users.groups.nix-ssh = {}; diff --git a/nixos/modules/services/misc/ntfy-sh.nix b/nixos/modules/services/misc/ntfy-sh.nix index 98134e94eeed..b8b077240115 100644 --- a/nixos/modules/services/misc/ntfy-sh.nix +++ b/nixos/modules/services/misc/ntfy-sh.nix @@ -79,12 +79,6 @@ in cache-file = mkDefault "/var/lib/ntfy-sh/cache-file.db"; }; - systemd.tmpfiles.rules = [ - "f ${cfg.settings.auth-file} 0600 ${cfg.user} ${cfg.group} - -" - "d ${cfg.settings.attachment-cache-dir} 0700 ${cfg.user} ${cfg.group} - -" - "f ${cfg.settings.cache-file} 0600 ${cfg.user} ${cfg.group} - -" - ]; - systemd.services.ntfy-sh = { description = "Push notifications server"; diff --git a/nixos/modules/services/misc/ollama.nix b/nixos/modules/services/misc/ollama.nix index 9794bbbec464..d9359d2b5cd4 100644 --- a/nixos/modules/services/misc/ollama.nix +++ b/nixos/modules/services/misc/ollama.nix @@ -9,6 +9,13 @@ in { enable = lib.mkEnableOption ( lib.mdDoc "Server for local large language models" ); + listenAddress = lib.mkOption { + type = lib.types.str; + default = "127.0.0.1:11434"; + description = lib.mdDoc '' + Specifies the bind address on which the ollama server HTTP interface listens. + ''; + }; package = lib.mkPackageOption pkgs "ollama" { }; }; }; @@ -23,6 +30,7 @@ in { environment = { HOME = "%S/ollama"; OLLAMA_MODELS = "%S/ollama/models"; + OLLAMA_HOST = cfg.listenAddress; }; serviceConfig = { ExecStart = "${lib.getExe cfg.package} serve"; diff --git a/nixos/modules/services/misc/paperless.nix b/nixos/modules/services/misc/paperless.nix index 3c6832958f59..9780a4d72257 100644 --- a/nixos/modules/services/misc/paperless.nix +++ b/nixos/modules/services/misc/paperless.nix @@ -141,12 +141,12 @@ in `''${dataDir}/paperless-manage createsuperuser`. The default superuser name is `admin`. To change it, set - option {option}`extraConfig.PAPERLESS_ADMIN_USER`. + option {option}`settings.PAPERLESS_ADMIN_USER`. WARNING: When changing the superuser name after the initial setup, the old superuser will continue to exist. To disable login for the web interface, set the following: - `extraConfig.PAPERLESS_AUTO_LOGIN_USERNAME = "admin";`. + `settings.PAPERLESS_AUTO_LOGIN_USERNAME = "admin";`. WARNING: Only use this on a trusted system without internet access to Paperless. ''; }; @@ -297,6 +297,7 @@ in wantedBy = [ "paperless-scheduler.service" ]; before = [ "paperless-scheduler.service" ]; after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; serviceConfig = defaultServiceConfig // { User = cfg.user; Type = "oneshot"; diff --git a/nixos/modules/services/misc/portunus.nix b/nixos/modules/services/misc/portunus.nix index 7036a372d1ea..ebb3bc8f0851 100644 --- a/nixos/modules/services/misc/portunus.nix +++ b/nixos/modules/services/misc/portunus.nix @@ -37,6 +37,15 @@ in ''; }; + seedSettings = lib.mkOption { + type = with lib.types; nullOr (attrsOf (listOf (attrsOf anything))); + default = null; + description = lib.mdDoc '' + Seed settings for users and groups. + See upstream for format <https://github.com/majewsky/portunus#seeding-users-and-groups-from-static-configuration> + ''; + }; + stateDir = mkOption { type = types.path; default = "/var/lib/portunus"; @@ -172,49 +181,53 @@ in "127.0.0.1" = [ cfg.domain ]; }; - services.dex = mkIf cfg.dex.enable { - enable = true; - settings = { - issuer = "https://${cfg.domain}/dex"; - web.http = "127.0.0.1:${toString cfg.dex.port}"; - storage = { - type = "sqlite3"; - config.file = "/var/lib/dex/dex.db"; - }; - enablePasswordDB = false; - connectors = [{ - type = "ldap"; - id = "ldap"; - name = "LDAP"; - config = { - host = "${cfg.domain}:636"; - bindDN = "uid=${cfg.ldap.searchUserName},ou=users,${cfg.ldap.suffix}"; - bindPW = "$DEX_SEARCH_USER_PASSWORD"; - userSearch = { - baseDN = "ou=users,${cfg.ldap.suffix}"; - filter = "(objectclass=person)"; - username = "uid"; - idAttr = "uid"; - emailAttr = "mail"; - nameAttr = "cn"; - preferredUsernameAttr = "uid"; - }; - groupSearch = { - baseDN = "ou=groups,${cfg.ldap.suffix}"; - filter = "(objectclass=groupOfNames)"; - nameAttr = "cn"; - userMatchers = [{ userAttr = "DN"; groupAttr = "member"; }]; - }; + services = { + dex = mkIf cfg.dex.enable { + enable = true; + settings = { + issuer = "https://${cfg.domain}/dex"; + web.http = "127.0.0.1:${toString cfg.dex.port}"; + storage = { + type = "sqlite3"; + config.file = "/var/lib/dex/dex.db"; }; - }]; - - staticClients = forEach cfg.dex.oidcClients (client: { - inherit (client) id; - redirectURIs = [ client.callbackURL ]; - name = "OIDC for ${client.id}"; - secretEnv = "DEX_CLIENT_${client.id}"; - }); + enablePasswordDB = false; + connectors = [{ + type = "ldap"; + id = "ldap"; + name = "LDAP"; + config = { + host = "${cfg.domain}:636"; + bindDN = "uid=${cfg.ldap.searchUserName},ou=users,${cfg.ldap.suffix}"; + bindPW = "$DEX_SEARCH_USER_PASSWORD"; + userSearch = { + baseDN = "ou=users,${cfg.ldap.suffix}"; + filter = "(objectclass=person)"; + username = "uid"; + idAttr = "uid"; + emailAttr = "mail"; + nameAttr = "cn"; + preferredUsernameAttr = "uid"; + }; + groupSearch = { + baseDN = "ou=groups,${cfg.ldap.suffix}"; + filter = "(objectclass=groupOfNames)"; + nameAttr = "cn"; + userMatchers = [{ userAttr = "DN"; groupAttr = "member"; }]; + }; + }; + }]; + + staticClients = forEach cfg.dex.oidcClients (client: { + inherit (client) id; + redirectURIs = [ client.callbackURL ]; + name = "OIDC for ${client.id}"; + secretEnv = "DEX_CLIENT_${client.id}"; + }); + }; }; + + portunus.seedPath = lib.mkIf (cfg.seedSettings != null) (pkgs.writeText "seed.json" (builtins.toJSON cfg.seedSettings)); }; systemd.services = { @@ -230,7 +243,10 @@ in description = "Self-contained authentication service"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; - serviceConfig.ExecStart = "${cfg.package.out}/bin/portunus-orchestrator"; + serviceConfig = { + ExecStart = "${cfg.package}/bin/portunus-orchestrator"; + Restart = "on-failure"; + }; environment = { PORTUNUS_LDAP_SUFFIX = cfg.ldap.suffix; PORTUNUS_SERVER_BINARY = "${cfg.package}/bin/portunus-server"; diff --git a/nixos/modules/services/misc/radarr.nix b/nixos/modules/services/misc/radarr.nix index 618341cf614f..a5f264331ed3 100644 --- a/nixos/modules/services/misc/radarr.nix +++ b/nixos/modules/services/misc/radarr.nix @@ -40,9 +40,10 @@ in }; config = mkIf cfg.enable { - systemd.tmpfiles.rules = [ - "d '${cfg.dataDir}' 0700 ${cfg.user} ${cfg.group} - -" - ]; + systemd.tmpfiles.settings."10-radarr".${cfg.dataDir}.d = { + inherit (cfg) user group; + mode = "0700"; + }; systemd.services.radarr = { description = "Radarr"; diff --git a/nixos/modules/services/misc/readarr.nix b/nixos/modules/services/misc/readarr.nix index 3c84b13485a4..73868b4baa95 100644 --- a/nixos/modules/services/misc/readarr.nix +++ b/nixos/modules/services/misc/readarr.nix @@ -45,9 +45,10 @@ in }; config = mkIf cfg.enable { - systemd.tmpfiles.rules = [ - "d '${cfg.dataDir}' 0700 ${cfg.user} ${cfg.group} - -" - ]; + systemd.tmpfiles.settings."10-readarr".${cfg.dataDir}.d = { + inherit (cfg) user group; + mode = "0700"; + }; systemd.services.readarr = { description = "Readarr"; diff --git a/nixos/modules/services/misc/taskserver/helper-tool.py b/nixos/modules/services/misc/taskserver/helper-tool.py index fec05728b2b6..b1eebb07686b 100644 --- a/nixos/modules/services/misc/taskserver/helper-tool.py +++ b/nixos/modules/services/misc/taskserver/helper-tool.py @@ -61,6 +61,10 @@ def run_as_taskd_user(): os.setuid(uid) +def run_as_taskd_group(): + gid = grp.getgrnam(TASKD_GROUP).gr_gid + os.setgid(gid) + def taskd_cmd(cmd, *args, **kwargs): """ Invoke taskd with the specified command with the privileges of the 'taskd' @@ -90,7 +94,7 @@ def certtool_cmd(*args, **kwargs): """ return subprocess.check_output( [CERTTOOL_COMMAND] + list(args), - preexec_fn=lambda: os.umask(0o077), + preexec_fn=run_as_taskd_group, stderr=subprocess.STDOUT, **kwargs ) @@ -156,17 +160,33 @@ def generate_key(org, user): sys.stderr.write(msg.format(user)) return - basedir = os.path.join(TASKD_DATA_DIR, "keys", org, user) - if os.path.exists(basedir): + keysdir = os.path.join(TASKD_DATA_DIR, "keys" ) + orgdir = os.path.join(keysdir , org ) + userdir = os.path.join(orgdir , user ) + if os.path.exists(userdir): raise OSError("Keyfile directory for {} already exists.".format(user)) - privkey = os.path.join(basedir, "private.key") - pubcert = os.path.join(basedir, "public.cert") + privkey = os.path.join(userdir, "private.key") + pubcert = os.path.join(userdir, "public.cert") try: - os.makedirs(basedir, mode=0o700) + # We change the permissions and the owner ship of the base directories + # so that cfg.group and cfg.user could read the directories' contents. + # See also: https://bugs.python.org/issue42367 + for bd in [keysdir, orgdir, userdir]: + # Allow cfg.group, but not others to read the contents of this group + os.makedirs(bd, exist_ok=True) + # not using mode= argument to makedirs intentionally - forcing the + # permissions we want + os.chmod(bd, mode=0o750) + os.chown( + bd, + uid=pwd.getpwnam(TASKD_USER).pw_uid, + gid=grp.getgrnam(TASKD_GROUP).gr_gid, + ) certtool_cmd("-p", "--bits", CERT_BITS, "--outfile", privkey) + os.chmod(privkey, 0o640) template_data = [ "organization = {0}".format(org), @@ -187,7 +207,7 @@ def generate_key(org, user): "--outfile", pubcert ) except: - rmtree(basedir) + rmtree(userdir) raise |