diff --git a/doc/languages-frameworks/ocaml.section.md b/doc/languages-frameworks/ocaml.section.md index acefddc7c2f2..7f2c2a63a00b 100644 --- a/doc/languages-frameworks/ocaml.section.md +++ b/doc/languages-frameworks/ocaml.section.md @@ -38,12 +38,12 @@ Here is a simple package example. - It uses the `fetchFromGitHub` fetcher to get its source. -- It also accept `duneVersion` parameter (valid value are `"1"`, `"2"`, and - `"3"`). The recommended practice it to set only if you don't want the default +- It also accepts a `duneVersion` parameter (valid values are `"1"`, `"2"`, and + `"3"`). The recommended practice is to set it only if you don't want the default value and/or it depends on something else like package version. You might see a not-supported argument `useDune2`. The behavior was `useDune2 = true;` => `duneVersion = "2";` and `useDune2 = false;` => `duneVersion = "1";`. It was - used at the time when dune3 didn't existed. + used at the time when dune3 didn't exist. - It sets the optional `doCheck` attribute such that tests will be run with `dune runtest -p angstrom` after the build (`dune build -p angstrom`) is diff --git a/lib/strings.nix b/lib/strings.nix index bcaaab9af4fb..7ee459f5b443 100644 --- a/lib/strings.nix +++ b/lib/strings.nix @@ -2434,7 +2434,13 @@ rec { if isStringLike x then let str = toString x; in substring 0 1 str == "/" - && dirOf str == storeDir + && (dirOf str == storeDir + # Match content‐addressed derivations, which _currently_ do not have a + # store directory prefix. + # This is a workaround for https://github.com/NixOS/nix/issues/12361 + # which was needed during the experimental phase of ca-derivations and + # should be removed once the issue has been resolved. + || builtins.match "/[0-9a-z]{52}" str != null) else false; diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index e86c366d4ce4..fde2d44e3efe 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -537,6 +537,7 @@ runTests { expr = let goodPath = "${builtins.storeDir}/d945ibfx9x185xf04b890y4f9g3cbb63-python-2.7.11"; + goodCAPath = "/1121rp0gvr1qya7hvy925g5kjwg66acz6sn1ra1hca09f1z5dsab"; in { storePath = isStorePath goodPath; storePathDerivation = isStorePath (import ../.. { system = "x86_64-linux"; }).hello; @@ -545,6 +546,12 @@ runTests { nonAbsolute = isStorePath (concatStrings (tail (stringToCharacters goodPath))); asPath = isStorePath (/. + goodPath); otherPath = isStorePath "/something/else"; + + caPath = isStorePath goodCAPath; + caPathAppendix = isStorePath + "${goodCAPath}/bin/python"; + caAsPath = isStorePath (/. + goodCAPath); + otherVals = { attrset = isStorePath {}; list = isStorePath []; @@ -557,6 +564,9 @@ runTests { storePathAppendix = false; nonAbsolute = false; asPath = true; + caPath = true; + caPathAppendix = false; + caAsPath = true; otherPath = false; otherVals = { attrset = false; diff --git a/maintainers/maintainer-list.nix b/maintainers/maintainer-list.nix index 278b084f9d59..da1751fb2ec5 100644 --- a/maintainers/maintainer-list.nix +++ b/maintainers/maintainer-list.nix @@ -4529,6 +4529,12 @@ github = "CnTeng"; githubId = 56501688; }; + coat = { + email = "kentsmith@gmail.com"; + name = "Kent Smith"; + github = "coat"; + githubId = 1661; + }; cobalt = { email = "cobalt@cobalt.rocks"; github = "Chaostheorie"; @@ -4587,6 +4593,11 @@ email = "jupiter@m.rdis.dev"; name = "Scott Little"; }; + coderofsalvation = { + github = "coderofsalvation"; + githubId = 180068; + name = "Leon van Kammen"; + }; codgician = { email = "codgician@outlook.com"; github = "codgician"; diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index 7cf681b8b8cd..e3c61c882cb4 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -225,6 +225,8 @@ - `strawberry` has been updated to 1.2, which drops support for the VLC backend and Qt 5. The `strawberry-qt5` package and `withGstreamer`/`withVlc` override options have been removed due to this. +- `nezha` and its agent `nezha-agent` have been updated to v1, which contains breaking changes. See the [official wiki](https://nezha.wiki/en_US/) for more details. + - `ps3-disc-dumper` was updated to 4.2.5, which removed the CLI project and now exclusively offers the GUI - [](#opt-services.nextcloud.config.dbtype) is unset by default, the previous default was `sqlite`. @@ -542,6 +544,8 @@ - `services.gitea` now supports CAPTCHA usage through the `services.gitea.captcha` variable. +- `services.soft-serve` now restarts upon config change. + - `bind.cacheNetworks` now only controls access for recursive queries, where it previously controlled access for all queries. - [`services.mongodb.enableAuth`](#opt-services.mongodb.enableAuth) now uses the newer [mongosh](https://github.com/mongodb-js/mongosh) shell instead of the legacy shell to configure the initial superuser. You can configure the mongosh package to use through the [`services.mongodb.mongoshPackage`](#opt-services.mongodb.mongoshPackage) option. diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 6a404afa8123..efa81f833fb5 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1507,6 +1507,7 @@ ./services/web-apps/gotosocial.nix ./services/web-apps/grav.nix ./services/web-apps/grocy.nix + ./services/web-apps/part-db.nix ./services/web-apps/pixelfed.nix ./services/web-apps/goatcounter.nix ./services/web-apps/guacamole-client.nix diff --git a/nixos/modules/services/backup/restic.nix b/nixos/modules/services/backup/restic.nix index aaddc5d16589..ce8bcc3994b8 100644 --- a/nixos/modules/services/backup/restic.nix +++ b/nixos/modules/services/backup/restic.nix @@ -195,6 +195,7 @@ in Extra arguments passed to restic backup. ''; example = [ + "--cleanup-cache" "--exclude-file=/etc/nixos/restic-ignore" ]; }; @@ -352,6 +353,7 @@ in filesFromTmpFile = "/run/restic-backups-${name}/includes"; doBackup = (backup.dynamicFilesFrom != null) || (backup.paths != null && backup.paths != [ ]); pruneCmd = lib.optionals (builtins.length backup.pruneOpts > 0) [ + (resticCmd + " unlock") (resticCmd + " forget --prune " + (lib.concatStringsSep " " backup.pruneOpts)) ]; checkCmd = lib.optionals backup.runCheck [ diff --git a/nixos/modules/services/misc/soft-serve.nix b/nixos/modules/services/misc/soft-serve.nix index e9719c02e41e..0c34d27d7542 100644 --- a/nixos/modules/services/misc/soft-serve.nix +++ b/nixos/modules/services/misc/soft-serve.nix @@ -59,6 +59,8 @@ in environment.SOFT_SERVE_DATA_PATH = stateDir; + restartTriggers = [ configFile ]; + serviceConfig = { Type = "simple"; DynamicUser = true; diff --git a/nixos/modules/services/monitoring/nezha-agent.nix b/nixos/modules/services/monitoring/nezha-agent.nix index 035485a939b8..87ecbfdde710 100644 --- a/nixos/modules/services/monitoring/nezha-agent.nix +++ b/nixos/modules/services/monitoring/nezha-agent.nix @@ -6,6 +6,11 @@ }: let cfg = config.services.nezha-agent; + + # nezha-agent uses yaml as the configuration file format. + # Since we need to use jq to update the content, so here we generate json + settingsFormat = pkgs.formats.json { }; + configFile = settingsFormat.generate "config.json" cfg.settings; in { meta = { @@ -16,141 +21,280 @@ in enable = lib.mkEnableOption "Agent of Nezha Monitoring"; package = lib.mkPackageOption pkgs "nezha-agent" { }; + debug = lib.mkEnableOption "verbose log"; - tls = lib.mkOption { + + settings = lib.mkOption { + description = '' + Generate to {file}`config.json` as a Nix attribute set. + Check the [guide](https://nezha.wiki/en_US/guide/agent.html) + for possible options. + ''; + type = lib.types.submodule { + freeformType = settingsFormat.type; + + options = { + disable_command_execute = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Disable executing the command from dashboard. + ''; + }; + disable_nat = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Disable NAT penetration. + ''; + }; + disable_send_query = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Disable sending TCP/ICMP/HTTP requests. + ''; + }; + gpu = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Enable GPU monitoring. + ''; + }; + tls = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Enable SSL/TLS encryption. + ''; + }; + temperature = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Enable temperature monitoring. + ''; + }; + use_ipv6_country_code = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Use ipv6 countrycode to report location. + ''; + }; + skip_connection_count = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Do not monitor the number of connections. + ''; + }; + skip_procs_count = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Do not monitor the number of processes. + ''; + }; + report_delay = lib.mkOption { + type = lib.types.enum [ + 1 + 2 + 3 + 4 + ]; + default = 3; + description = '' + The interval between system status reportings. + The value must be an integer from 1 to 4. + ''; + }; + server = lib.mkOption { + type = lib.types.str; + example = "127.0.0.1:8008"; + description = '' + Address to the dashboard. + ''; + }; + uuid = lib.mkOption { + type = with lib.types; nullOr str; + # pre-defined uuid of Dns in RFC 4122 + example = "6ba7b810-9dad-11d1-80b4-00c04fd430c8"; + default = null; + description = '' + Must be set to a unique identifier, preferably a UUID according to + RFC 4122. UUIDs can be generated with `uuidgen` command, found in + the `util-linux` package. + + Set {option}`services.nezha-agent.genUuid` to true to generate uuid + from {option}`networking.fqdn` automatically. + ''; + }; + }; + }; + }; + + genUuid = lib.mkOption { type = lib.types.bool; default = false; description = '' - Enable SSL/TLS encryption. + Whether to generate uuid from fqdn automatically. + Please note that changes in hostname/domain will result in different uuid. ''; }; - gpu = lib.mkOption { - type = lib.types.bool; - default = true; - description = '' - Enable GPU monitoring. - ''; - }; - temperature = lib.mkOption { - type = lib.types.bool; - default = true; - description = '' - Enable temperature monitoring. - ''; - }; - useIPv6CountryCode = lib.mkOption { - type = lib.types.bool; - default = true; - description = '' - Use ipv6 countrycode to report location. - ''; - }; - disableCommandExecute = lib.mkOption { - type = lib.types.bool; - default = true; - description = '' - Disable executing the command from dashboard. - ''; - }; - disableNat = lib.mkOption { - type = lib.types.bool; - default = false; - description = '' - Disable NAT penetration. - ''; - }; - disableSendQuery = lib.mkOption { - type = lib.types.bool; - default = false; - description = '' - Disable sending TCP/ICMP/HTTP requests. - ''; - }; - skipConnection = lib.mkOption { - type = lib.types.bool; - default = false; - description = '' - Do not monitor the number of connections. - ''; - }; - skipProcess = lib.mkOption { - type = lib.types.bool; - default = false; - description = '' - Do not monitor the number of processes. - ''; - }; - reportDelay = lib.mkOption { - type = lib.types.enum [ - 1 - 2 - 3 - 4 - ]; - default = 1; - description = '' - The interval between system status reportings. - The value must be an integer from 1 to 4 - ''; - }; - passwordFile = lib.mkOption { - type = with lib.types; nullOr str; + + clientSecretFile = lib.mkOption { + type = with lib.types; nullOr path; default = null; description = '' - Path to the file contained the password from dashboard. - ''; - }; - server = lib.mkOption { - type = lib.types.str; - description = '' - Address to the dashboard - ''; - }; - extraFlags = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ ]; - example = [ "--gpu" ]; - description = '' - Extra command-line flags passed to nezha-agent. + Path to the file contained the client_secret of the dashboard. ''; }; }; }; + imports = with lib; [ + (mkRenamedOptionModule + [ "services" "nezha-agent" "disableCommandExecute" ] + [ "services" "nezha-agent" "settings" "disable_command_execute" ] + ) + (mkRenamedOptionModule + [ "services" "nezha-agent" "disableNat" ] + [ "services" "nezha-agent" "settings" "disable_nat" ] + ) + (mkRenamedOptionModule + [ "services" "nezha-agent" "disableSendQuery" ] + [ "services" "nezha-agent" "settings" "disable_send_query" ] + ) + (mkRenamedOptionModule + [ "services" "nezha-agent" "gpu" ] + [ "services" "nezha-agent" "settings" "gpu" ] + ) + (mkRenamedOptionModule + [ "services" "nezha-agent" "tls" ] + [ "services" "nezha-agent" "settings" "tls" ] + ) + (mkRenamedOptionModule + [ "services" "nezha-agent" "temperature" ] + [ "services" "nezha-agent" "settings" "temperature" ] + ) + (mkRenamedOptionModule + [ "services" "nezha-agent" "useIPv6CountryCode" ] + [ "services" "nezha-agent" "settings" "use_ipv6_country_code" ] + ) + (mkRenamedOptionModule + [ "services" "nezha-agent" "skipConnection" ] + [ "services" "nezha-agent" "settings" "skip_connection_count" ] + ) + (mkRenamedOptionModule + [ "services" "nezha-agent" "skipProcess" ] + [ "services" "nezha-agent" "settings" "skip_procs_count" ] + ) + (mkRenamedOptionModule + [ "services" "nezha-agent" "reportDelay" ] + [ "services" "nezha-agent" "settings" "report_delay" ] + ) + (mkRenamedOptionModule + [ "services" "nezha-agent" "server" ] + [ "services" "nezha-agent" "settings" "server" ] + ) + (lib.mkRemovedOptionModule [ "services" "nezha-agent" "extraFlags" ] '' + Use `services.nezha-agent.settings` instead. + + Nezha-agent v1 is no longer configured via command line flags. + '') + (lib.mkRemovedOptionModule [ "services" "nezha-agent" "passwordFile" ] '' + Use `services.nezha-agent.clientSecretFile` instead. + + Nezha-agent v1 uses the client secret from the dashboard to connect. + '') + ]; + config = lib.mkIf cfg.enable { - systemd.packages = [ cfg.package ]; + assertions = [ + { + assertion = cfg.settings.uuid == null -> cfg.genUuid; + message = "Please set `service.nezha-agent.settings.uuid` while `genUuid` is false."; + } + { + assertion = cfg.settings.uuid != null -> !cfg.genUuid; + message = "When `service.nezha-agent.genUuid = true`, `settings.uuid` cannot be set."; + } + ]; + + services.nezha-agent.settings = { + debug = cfg.debug; + # Automatic updates should never be enabled in NixOS. + disable_auto_update = true; + disable_force_update = true; + }; systemd.services.nezha-agent = { serviceConfig = { - ProtectSystem = "full"; - PrivateDevices = "yes"; - PrivateTmp = "yes"; + Restart = "on-failure"; + StateDirectory = "nezha-agent"; + RuntimeDirectory = "nezha-agent"; + WorkingDirectory = "/var/lib/nezha-agent"; + ReadWritePaths = "/var/lib/nezha-agent"; + + LoadCredential = lib.optionalString ( + cfg.clientSecretFile != null + ) "client-secret:${cfg.clientSecretFile}"; + + # Hardening + ProcSubset = "all"; # Needed to get host information + DynamicUser = true; + RemoveIPC = true; + LockPersonality = true; + ProtectClock = true; + MemoryDenyWriteExecute = true; + PrivateUsers = true; + ProtectHostname = true; + RestrictSUIDSGID = true; + AmbientCapabilities = [ ]; + CapabilityBoundingSet = ""; NoNewPrivileges = true; + PrivateTmp = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectSystem = "strict"; + RestrictNamespaces = true; + RestrictRealtime = true; + SystemCallArchitectures = "native"; + UMask = "0066"; + SystemCallFilter = [ + "@system-service" + "~@privileged" + ]; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + ]; + PrivateDevices = "yes"; }; - path = [ cfg.package ]; + environment.HOME = "/var/lib/nezha-agent"; + enableStrictShellChecks = true; startLimitIntervalSec = 10; startLimitBurst = 3; - script = lib.concatStringsSep " " ( - [ - "${lib.getExe cfg.package}" - "--disable-auto-update" - "--disable-force-update" - "--password $(cat ${cfg.passwordFile})" - ] - ++ lib.optional cfg.debug "--debug" - ++ lib.optional cfg.disableCommandExecute "--disable-command-execute" - ++ lib.optional cfg.disableNat "--disable-nat" - ++ lib.optional cfg.disableSendQuery "--disable-send-query" - ++ lib.optional (cfg.reportDelay != null) "--report-delay ${toString cfg.reportDelay}" - ++ lib.optional (cfg.server != null) "--server ${cfg.server}" - ++ lib.optional cfg.skipConnection "--skip-conn" - ++ lib.optional cfg.skipProcess "--skip-procs" - ++ lib.optional cfg.tls "--tls" - ++ lib.optional cfg.gpu "--gpu" - ++ lib.optional cfg.temperature "--temperature" - ++ lib.optional cfg.useIPv6CountryCode "--use-ipv6-countrycode" - ++ cfg.extraFlags - ); + script = '' + cp "${configFile}" "''${RUNTIME_DIRECTORY}"/config.json + ${lib.optionalString (cfg.clientSecretFile != null) '' + ${lib.getExe pkgs.jq} --arg client_secret "$(<"''${CREDENTIALS_DIRECTORY}"/client-secret)" \ + '. + { client_secret: $client_secret }' < "''${RUNTIME_DIRECTORY}"/config.json > "''${RUNTIME_DIRECTORY}"/config.json.tmp + mv "''${RUNTIME_DIRECTORY}"/config.json.tmp "''${RUNTIME_DIRECTORY}"/config.json + ''} + ${lib.optionalString cfg.genUuid '' + ${lib.getExe pkgs.jq} --arg uuid "$(${lib.getExe' pkgs.util-linux "uuidgen"} --md5 -n @dns -N "${config.networking.fqdn}")" \ + '. + { uuid: $uuid }' < "''${RUNTIME_DIRECTORY}"/config.json > "''${RUNTIME_DIRECTORY}"/config.json.tmp + mv "''${RUNTIME_DIRECTORY}"/config.json.tmp "''${RUNTIME_DIRECTORY}"/config.json + ''} + ${lib.getExe cfg.package} --config "''${RUNTIME_DIRECTORY}"/config.json + ''; wantedBy = [ "multi-user.target" ]; }; }; diff --git a/nixos/modules/services/web-apps/part-db.nix b/nixos/modules/services/web-apps/part-db.nix new file mode 100644 index 000000000000..c165969aa620 --- /dev/null +++ b/nixos/modules/services/web-apps/part-db.nix @@ -0,0 +1,247 @@ +{ + pkgs, + config, + lib, + ... +}: +let + cfg = config.services.part-db; + pkg = cfg.package; + + inherit (lib) + mkEnableOption + mkPackageOption + mkOption + types + mkIf + ; +in +{ + meta.maintainers = with lib.maintainers; [ felbinger ]; + + options.services.part-db = { + enable = mkEnableOption "PartDB"; + + package = mkPackageOption pkgs "part-db" { }; + + phpPackage = mkPackageOption pkgs "php" { } // { + apply = + pkg: + pkg.override { + extraConfig = '' + memory_limit = 256M; + ''; + }; + }; + + enableNginx = mkOption { + type = types.bool; + default = true; + description = '' + Whether to enable nginx or not. If enabled, an nginx virtual host will + be created for access to part-db. If not enabled, then you may use + `''${config.services.part-db.package}/public` as your document root in + whichever webserver you wish to setup. + ''; + }; + + enablePostgresql = mkOption { + type = types.bool; + default = true; + description = '' + Whether to configure the postgresql database for part-db. If enabled, + a database and user will be created for part-db. + ''; + }; + + virtualHost = mkOption { + type = types.str; + default = "localhost"; + description = '' + The virtualHost at which you wish part-db to be served. + ''; + }; + + poolConfig = lib.mkOption { + type = lib.types.attrsOf ( + lib.types.oneOf [ + lib.types.str + lib.types.int + lib.types.bool + ] + ); + default = { }; + defaultText = '' + { + "pm" = "dynamic"; + "pm.max_children" = 32; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 2; + "pm.max_spare_servers" = 4; + "pm.max_requests" = 500; + } + ''; + description = '' + Options for the PartDB PHP pool. See the documentation on php-fpm.conf + for details on configuration directives. + ''; + }; + + settings = lib.mkOption { + default = { }; + description = '' + Options for part-db configuration. Refer to + for + details on supported values. All