diff options
author | Martin Weinelt <hexa@darmstadt.ccc.de> | 2024-02-01 12:24:57 +0100 |
---|---|---|
committer | Martin Weinelt <hexa@darmstadt.ccc.de> | 2024-02-01 12:25:11 +0100 |
commit | 27fa02d0f19b46920eaf78f74c6b700e31086379 (patch) | |
tree | 715ce671c4de5ecc52d4d40aa40a0b16cfd2ba00 /nixos/modules | |
parent | a7e73864b4d7a8dbd9df8e144e612ed1ed5577d4 (diff) | |
parent | 2c582510dbd6657db54222db0567e7c34bd9bb24 (diff) | |
download | nixlib-27fa02d0f19b46920eaf78f74c6b700e31086379.tar nixlib-27fa02d0f19b46920eaf78f74c6b700e31086379.tar.gz nixlib-27fa02d0f19b46920eaf78f74c6b700e31086379.tar.bz2 nixlib-27fa02d0f19b46920eaf78f74c6b700e31086379.tar.lz nixlib-27fa02d0f19b46920eaf78f74c6b700e31086379.tar.xz nixlib-27fa02d0f19b46920eaf78f74c6b700e31086379.tar.zst nixlib-27fa02d0f19b46920eaf78f74c6b700e31086379.zip |
Merge remote-tracking branch 'origin/staging-next' into staging
Conflicts: - pkgs/development/compilers/llvm/10/clang/default.nix - pkgs/development/compilers/llvm/8/clang/default.nix
Diffstat (limited to 'nixos/modules')
20 files changed, 748 insertions, 200 deletions
diff --git a/nixos/modules/config/no-x-libs.nix b/nixos/modules/config/no-x-libs.nix index 4727e5b85ef2..a50a03ce52d4 100644 --- a/nixos/modules/config/no-x-libs.nix +++ b/nixos/modules/config/no-x-libs.nix @@ -37,6 +37,7 @@ with lib; ghostscript = super.ghostscript.override { cupsSupport = false; x11Support = false; }; gjs = super.gjs.overrideAttrs { doCheck = false; installTests = false; }; # avoid test dependency on gtk3 gobject-introspection = super.gobject-introspection.override { x11Support = false; }; + gpg-tui = super.gpg-tui.override { x11Support = false; }; gpsd = super.gpsd.override { guiSupport = false; }; graphviz = super.graphviz-nox; gst_all_1 = super.gst_all_1 // { diff --git a/nixos/modules/image/repart-image.nix b/nixos/modules/image/repart-image.nix index a12b4fb14fb1..7ac47ee32ff4 100644 --- a/nixos/modules/image/repart-image.nix +++ b/nixos/modules/image/repart-image.nix @@ -32,6 +32,7 @@ , split , seed , definitionsDirectory +, sectorSize }: let @@ -94,6 +95,7 @@ runCommand imageFileBasename --definitions="$amendedRepartDefinitions" \ --split="${lib.boolToString split}" \ --json=pretty \ + ${lib.optionalString (sectorSize != null) "--sector-size=${toString sectorSize}"} \ ${imageFileBasename}.raw \ | tee repart-output.json diff --git a/nixos/modules/image/repart.nix b/nixos/modules/image/repart.nix index ed584d9bf997..6a933f0d83cc 100644 --- a/nixos/modules/image/repart.nix +++ b/nixos/modules/image/repart.nix @@ -135,6 +135,16 @@ in ''; }; + sectorSize = lib.mkOption { + type = with lib.types; nullOr int; + default = 512; + example = lib.literalExpression "4096"; + description = lib.mdDoc '' + The sector size of the disk image produced by systemd-repart. This + value must be a power of 2 between 512 and 4096. + ''; + }; + package = lib.mkPackageOption pkgs "systemd-repart" { # We use buildPackages so that repart images are built with the build # platform's systemd, allowing for cross-compiled systems to work. @@ -232,7 +242,7 @@ in in pkgs.callPackage ./repart-image.nix { systemd = cfg.package; - inherit (cfg) imageFileBasename compression split seed; + inherit (cfg) imageFileBasename compression split seed sectorSize; inherit fileSystems definitionsDirectory partitions; }; diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index db496f1d96b0..0eb88e7874f6 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1062,6 +1062,7 @@ ./services/networking/openvpn.nix ./services/networking/ostinato.nix ./services/networking/owamp.nix + ./services/networking/pyload.nix ./services/networking/pdns-recursor.nix ./services/networking/pdnsd.nix ./services/networking/peroxide.nix @@ -1342,6 +1343,7 @@ ./services/web-apps/plantuml-server.nix ./services/web-apps/plausible.nix ./services/web-apps/powerdns-admin.nix + ./services/web-apps/pretalx.nix ./services/web-apps/prosody-filer.nix ./services/web-apps/restya-board.nix ./services/web-apps/rimgo.nix diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix index 111be7057afc..ffbb558549f6 100644 --- a/nixos/modules/security/pam.nix +++ b/nixos/modules/security/pam.nix @@ -867,9 +867,6 @@ let { name = "gnupg"; enable = cfg.gnupg.enable; control = "optional"; modulePath = "${pkgs.pam_gnupg}/lib/security/pam_gnupg.so"; settings = { no-autostart = cfg.gnupg.noAutostart; }; } - { name = "cgfs"; enable = config.virtualisation.lxc.lxcfs.enable; control = "optional"; modulePath = "${pkgs.lxc}/lib/security/pam_cgfs.so"; args = [ - "-c" "all" - ]; } ]; }; }; diff --git a/nixos/modules/services/hardware/acpid.nix b/nixos/modules/services/hardware/acpid.nix index 6021aad09f45..821f4ef205fc 100644 --- a/nixos/modules/services/hardware/acpid.nix +++ b/nixos/modules/services/hardware/acpid.nix @@ -135,7 +135,6 @@ in wantedBy = [ "multi-user.target" ]; serviceConfig = { - PrivateNetwork = true; ExecStart = escapeShellArgs ([ "${pkgs.acpid}/bin/acpid" "--foreground" diff --git a/nixos/modules/services/misc/packagekit.nix b/nixos/modules/services/misc/packagekit.nix index 5a0d314d25cd..f4191a4453ca 100644 --- a/nixos/modules/services/misc/packagekit.nix +++ b/nixos/modules/services/misc/packagekit.nix @@ -13,7 +13,7 @@ let (iniFmt.generate "PackageKit.conf" (recursiveUpdate { Daemon = { - DefaultBackend = "nix"; + DefaultBackend = "test_nop"; KeepCache = false; }; } @@ -35,7 +35,7 @@ let in { imports = [ - (mkRemovedOptionModule [ "services" "packagekit" "backend" ] "Always set to Nix.") + (mkRemovedOptionModule [ "services" "packagekit" "backend" ] "Always set to test_nop, Nix backend is broken see #177946.") ]; options.services.packagekit = { diff --git a/nixos/modules/services/misc/paperless.nix b/nixos/modules/services/misc/paperless.nix index ca34a327dbdf..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. ''; }; diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix index 35db8a7376b1..0583b12fe7a3 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters.nix @@ -60,7 +60,6 @@ let "node" "nut" "openldap" - "openvpn" "pgbouncer" "php-fpm" "pihole" diff --git a/nixos/modules/services/monitoring/prometheus/exporters/openvpn.nix b/nixos/modules/services/monitoring/prometheus/exporters/openvpn.nix deleted file mode 100644 index 5b54dad99805..000000000000 --- a/nixos/modules/services/monitoring/prometheus/exporters/openvpn.nix +++ /dev/null @@ -1,39 +0,0 @@ -{ config, pkgs, lib, ... }: - -with lib; - -let - cfg = config.services.prometheus.exporters.openvpn; -in { - port = 9176; - extraOpts = { - statusPaths = mkOption { - type = types.listOf types.str; - description = lib.mdDoc '' - Paths to OpenVPN status files. Please configure the OpenVPN option - `status` accordingly. - ''; - }; - telemetryPath = mkOption { - type = types.str; - default = "/metrics"; - description = lib.mdDoc '' - Path under which to expose metrics. - ''; - }; - }; - - serviceOpts = { - serviceConfig = { - PrivateDevices = true; - ProtectKernelModules = true; - NoNewPrivileges = true; - ExecStart = '' - ${pkgs.prometheus-openvpn-exporter}/bin/openvpn_exporter \ - -openvpn.status_paths "${concatStringsSep "," cfg.statusPaths}" \ - -web.listen-address ${cfg.listenAddress}:${toString cfg.port} \ - -web.telemetry-path ${cfg.telemetryPath} - ''; - }; - }; -} diff --git a/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix b/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix index 840ce493ee81..452cb154bcf6 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix @@ -3,6 +3,7 @@ with lib; let + logPrefix = "services.prometheus.exporters.snmp"; cfg = config.services.prometheus.exporters.snmp; # This ensures that we can deal with string paths, path types and diff --git a/nixos/modules/services/networking/pyload.nix b/nixos/modules/services/networking/pyload.nix new file mode 100644 index 000000000000..f2b85499d4dd --- /dev/null +++ b/nixos/modules/services/networking/pyload.nix @@ -0,0 +1,147 @@ +{ config, lib, pkgs, utils, ... }: +let + cfg = config.services.pyload; + + stateDir = "/var/lib/pyload"; +in +{ + meta.maintainers = with lib.maintainers; [ ambroisie ]; + + options = with lib; { + services.pyload = { + enable = mkEnableOption "pyLoad download manager"; + + package = mkPackageOption pkgs "pyLoad" { default = [ "pyload-ng" ]; }; + + listenAddress = mkOption { + type = types.str; + default = "localhost"; + example = "0.0.0.0"; + description = "Address to listen on for the web UI."; + }; + + port = mkOption { + type = types.port; + default = 8000; + example = 9876; + description = "Port to listen on for the web UI."; + }; + + downloadDirectory = mkOption { + type = types.path; + default = "${stateDir}/downloads"; + example = "/mnt/downloads"; + description = "Directory to store downloads."; + }; + + credentialsFile = mkOption { + type = with types; nullOr path; + default = null; + example = "/run/secrets/pyload-credentials.env"; + description = '' + File containing {env}`PYLOAD_DEFAULT_USERNAME` and + {env}`PYLOAD_DEFAULT_PASSWORD` in the format of an `EnvironmentFile=`, + as described by {manpage}`systemd.exec(5)`. + + If not given, they default to the username/password combo of + pyload/pyload. + ''; + }; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.tmpfiles.settings.pyload = { + ${cfg.downloadDirectory}.d = { }; + }; + + systemd.services.pyload = { + description = "pyLoad download manager"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + # NOTE: unlike what the documentation says, it looks like `HOME` is not + # defined with this service definition... + # Since pyload tries to do the equivalent of `cd ~`, it needs to be able + # to resolve $HOME, which fails when `RootDirectory` is set. + # FIXME: check if `SetLoginEnvironment` fixes this issue in version 255 + environment = { + HOME = stateDir; + PYLOAD__WEBUI__HOST = cfg.listenAddress; + PYLOAD__WEBUI__PORT = builtins.toString cfg.port; + }; + + serviceConfig = { + ExecStart = utils.escapeSystemdExecArgs [ + (lib.getExe cfg.package) + "--userdir" + "${stateDir}/config" + "--storagedir" + cfg.downloadDirectory + ]; + + User = "pyload"; + Group = "pyload"; + DynamicUser = true; + + EnvironmentFile = lib.optional (cfg.credentialsFile != null) cfg.credentialsFile; + + StateDirectory = "pyload"; + WorkingDirectory = stateDir; + RuntimeDirectory = "pyload"; + RuntimeDirectoryMode = "0700"; + RootDirectory = "/run/pyload"; + BindReadOnlyPaths = [ + builtins.storeDir # Needed to run the python interpreter + ]; + BindPaths = [ + cfg.downloadDirectory + ]; + + # Hardening options + LockPersonality = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateMounts = true; + PrivateTmp = true; + PrivateUsers = true; + ProcSubset = "pid"; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectSystem = "strict"; + RemoveIPC = true; + RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX"; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ "@system-service" "~@resources" "~@privileged" ]; + UMask = "0002"; + CapabilityBoundingSet = [ + "~CAP_BLOCK_SUSPEND" + "~CAP_BPF" + "~CAP_CHOWN" + "~CAP_IPC_LOCK" + "~CAP_KILL" + "~CAP_LEASE" + "~CAP_LINUX_IMMUTABLE" + "~CAP_NET_ADMIN" + "~CAP_SYS_ADMIN" + "~CAP_SYS_BOOT" + "~CAP_SYS_CHROOT" + "~CAP_SYS_NICE" + "~CAP_SYS_PACCT" + "~CAP_SYS_PTRACE" + "~CAP_SYS_RESOURCE" + "~CAP_SYS_TTY_CONFIG" + ]; + }; + }; + }; +} diff --git a/nixos/modules/services/networking/seafile.nix b/nixos/modules/services/networking/seafile.nix index 9caabc60c78f..b2d12234900a 100644 --- a/nixos/modules/services/networking/seafile.nix +++ b/nixos/modules/services/networking/seafile.nix @@ -32,7 +32,8 @@ let dataDir = "${seafRoot}/data"; seahubDir = "${seafRoot}/seahub"; -in { +in +{ ###### Interface @@ -147,146 +148,151 @@ in { description = "Seafile components"; }; - systemd.services = let - securityOptions = { - ProtectHome = true; - PrivateUsers = true; - PrivateDevices = true; - ProtectClock = true; - ProtectHostname = true; - ProtectProc = "invisible"; - ProtectKernelModules = true; - ProtectKernelTunables = true; - ProtectKernelLogs = true; - ProtectControlGroups = true; - RestrictNamespaces = true; - LockPersonality = true; - RestrictRealtime = true; - RestrictSUIDSGID = true; - MemoryDenyWriteExecute = true; - SystemCallArchitectures = "native"; - RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" ]; - }; - in { - seaf-server = { - description = "Seafile server"; - partOf = [ "seafile.target" ]; - after = [ "network.target" ]; - wantedBy = [ "seafile.target" ]; - restartTriggers = [ ccnetConf seafileConf ]; - path = [ pkgs.sqlite ]; - serviceConfig = securityOptions // { - User = "seafile"; - Group = "seafile"; - DynamicUser = true; - StateDirectory = "seafile"; - RuntimeDirectory = "seafile"; - LogsDirectory = "seafile"; - ConfigurationDirectory = "seafile"; - ExecStart = '' - ${cfg.seafilePackage}/bin/seaf-server \ - --foreground \ - -F /etc/seafile \ - -c ${ccnetDir} \ - -d ${dataDir} \ - -l /var/log/seafile/server.log \ - -P /run/seafile/server.pid \ - -p /run/seafile - ''; + systemd.services = + let + securityOptions = { + ProtectHome = true; + PrivateUsers = true; + PrivateDevices = true; + ProtectClock = true; + ProtectHostname = true; + ProtectProc = "invisible"; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectKernelLogs = true; + ProtectControlGroups = true; + RestrictNamespaces = true; + LockPersonality = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + MemoryDenyWriteExecute = true; + SystemCallArchitectures = "native"; + RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" ]; }; - preStart = '' - if [ ! -f "${seafRoot}/server-setup" ]; then - mkdir -p ${dataDir}/library-template - mkdir -p ${ccnetDir}/{GroupMgr,misc,OrgMgr,PeerMgr} - sqlite3 ${ccnetDir}/GroupMgr/groupmgr.db ".read ${cfg.seafilePackage}/share/seafile/sql/sqlite/groupmgr.sql" - sqlite3 ${ccnetDir}/misc/config.db ".read ${cfg.seafilePackage}/share/seafile/sql/sqlite/config.sql" - sqlite3 ${ccnetDir}/OrgMgr/orgmgr.db ".read ${cfg.seafilePackage}/share/seafile/sql/sqlite/org.sql" - sqlite3 ${ccnetDir}/PeerMgr/usermgr.db ".read ${cfg.seafilePackage}/share/seafile/sql/sqlite/user.sql" - sqlite3 ${dataDir}/seafile.db ".read ${cfg.seafilePackage}/share/seafile/sql/sqlite/seafile.sql" - echo "${cfg.seafilePackage.version}-sqlite" > "${seafRoot}"/server-setup - fi - # checking for upgrades and handling them - # WARNING: needs to be extended to actually handle major version migrations - installedMajor=$(cat "${seafRoot}/server-setup" | cut -d"-" -f1 | cut -d"." -f1) - installedMinor=$(cat "${seafRoot}/server-setup" | cut -d"-" -f1 | cut -d"." -f2) - pkgMajor=$(echo "${cfg.seafilePackage.version}" | cut -d"." -f1) - pkgMinor=$(echo "${cfg.seafilePackage.version}" | cut -d"." -f2) - - if [[ $installedMajor == $pkgMajor && $installedMinor == $pkgMinor ]]; then - : - elif [[ $installedMajor == 8 && $installedMinor == 0 && $pkgMajor == 9 && $pkgMinor == 0 ]]; then - # Upgrade from 8.0 to 9.0 - sqlite3 ${dataDir}/seafile.db ".read ${pkgs.seahub}/scripts/upgrade/sql/9.0.0/sqlite3/seafile.sql" - echo "${cfg.seafilePackage.version}-sqlite" > "${seafRoot}"/server-setup - else - echo "Unsupported upgrade" >&2 - exit 1 - fi - ''; - }; + in + { + seaf-server = { + description = "Seafile server"; + partOf = [ "seafile.target" ]; + after = [ "network.target" ]; + wantedBy = [ "seafile.target" ]; + restartTriggers = [ ccnetConf seafileConf ]; + path = [ pkgs.sqlite ]; + serviceConfig = securityOptions // { + User = "seafile"; + Group = "seafile"; + DynamicUser = true; + StateDirectory = "seafile"; + RuntimeDirectory = "seafile"; + LogsDirectory = "seafile"; + ConfigurationDirectory = "seafile"; + ExecStart = '' + ${cfg.seafilePackage}/bin/seaf-server \ + --foreground \ + -F /etc/seafile \ + -c ${ccnetDir} \ + -d ${dataDir} \ + -l /var/log/seafile/server.log \ + -P /run/seafile/server.pid \ + -p /run/seafile + ''; + }; + preStart = '' + if [ ! -f "${seafRoot}/server-setup" ]; then + mkdir -p ${dataDir}/library-template + mkdir -p ${ccnetDir}/{GroupMgr,misc,OrgMgr,PeerMgr} + sqlite3 ${ccnetDir}/GroupMgr/groupmgr.db ".read ${cfg.seafilePackage}/share/seafile/sql/sqlite/groupmgr.sql" + sqlite3 ${ccnetDir}/misc/config.db ".read ${cfg.seafilePackage}/share/seafile/sql/sqlite/config.sql" + sqlite3 ${ccnetDir}/OrgMgr/orgmgr.db ".read ${cfg.seafilePackage}/share/seafile/sql/sqlite/org.sql" + sqlite3 ${ccnetDir}/PeerMgr/usermgr.db ".read ${cfg.seafilePackage}/share/seafile/sql/sqlite/user.sql" + sqlite3 ${dataDir}/seafile.db ".read ${cfg.seafilePackage}/share/seafile/sql/sqlite/seafile.sql" + echo "${cfg.seafilePackage.version}-sqlite" > "${seafRoot}"/server-setup + fi + # checking for upgrades and handling them + installedMajor=$(cat "${seafRoot}/server-setup" | cut -d"-" -f1 | cut -d"." -f1) + installedMinor=$(cat "${seafRoot}/server-setup" | cut -d"-" -f1 | cut -d"." -f2) + pkgMajor=$(echo "${cfg.seafilePackage.version}" | cut -d"." -f1) + pkgMinor=$(echo "${cfg.seafilePackage.version}" | cut -d"." -f2) - seahub = { - description = "Seafile Server Web Frontend"; - wantedBy = [ "seafile.target" ]; - partOf = [ "seafile.target" ]; - after = [ "network.target" "seaf-server.service" ]; - requires = [ "seaf-server.service" ]; - restartTriggers = [ seahubSettings ]; - environment = { - PYTHONPATH = "${pkgs.seahub.pythonPath}:${pkgs.seahub}/thirdpart:${pkgs.seahub}"; - DJANGO_SETTINGS_MODULE = "seahub.settings"; - CCNET_CONF_DIR = ccnetDir; - SEAFILE_CONF_DIR = dataDir; - SEAFILE_CENTRAL_CONF_DIR = "/etc/seafile"; - SEAFILE_RPC_PIPE_PATH = "/run/seafile"; - SEAHUB_LOG_DIR = "/var/log/seafile"; + if [[ $installedMajor == $pkgMajor && $installedMinor == $pkgMinor ]]; then + : + elif [[ $installedMajor == 8 && $installedMinor == 0 && $pkgMajor == 9 && $pkgMinor == 0 ]]; then + # Upgrade from 8.0 to 9.0 + sqlite3 ${dataDir}/seafile.db ".read ${pkgs.seahub}/scripts/upgrade/sql/9.0.0/sqlite3/seafile.sql" + echo "${cfg.seafilePackage.version}-sqlite" > "${seafRoot}"/server-setup + elif [[ $installedMajor == 9 && $installedMinor == 0 && $pkgMajor == 10 && $pkgMinor == 0 ]]; then + # Upgrade from 9.0 to 10.0 + sqlite3 ${dataDir}/seafile.db ".read ${pkgs.seahub}/scripts/upgrade/sql/10.0.0/sqlite3/seafile.sql" + echo "${cfg.seafilePackage.version}-sqlite" > "${seafRoot}"/server-setup + else + echo "Unsupported upgrade" >&2 + exit 1 + fi + ''; }; - serviceConfig = securityOptions // { - User = "seafile"; - Group = "seafile"; - DynamicUser = true; - RuntimeDirectory = "seahub"; - StateDirectory = "seafile"; - LogsDirectory = "seafile"; - ConfigurationDirectory = "seafile"; - ExecStart = '' - ${pkgs.seahub.python.pkgs.gunicorn}/bin/gunicorn seahub.wsgi:application \ - --name seahub \ - --workers ${toString cfg.workers} \ - --log-level=info \ - --preload \ - --timeout=1200 \ - --limit-request-line=8190 \ - --bind unix:/run/seahub/gunicorn.sock + + seahub = { + description = "Seafile Server Web Frontend"; + wantedBy = [ "seafile.target" ]; + partOf = [ "seafile.target" ]; + after = [ "network.target" "seaf-server.service" ]; + requires = [ "seaf-server.service" ]; + restartTriggers = [ seahubSettings ]; + environment = { + PYTHONPATH = "${pkgs.seahub.pythonPath}:${pkgs.seahub}/thirdpart:${pkgs.seahub}"; + DJANGO_SETTINGS_MODULE = "seahub.settings"; + CCNET_CONF_DIR = ccnetDir; + SEAFILE_CONF_DIR = dataDir; + SEAFILE_CENTRAL_CONF_DIR = "/etc/seafile"; + SEAFILE_RPC_PIPE_PATH = "/run/seafile"; + SEAHUB_LOG_DIR = "/var/log/seafile"; + }; + serviceConfig = securityOptions // { + User = "seafile"; + Group = "seafile"; + DynamicUser = true; + RuntimeDirectory = "seahub"; + StateDirectory = "seafile"; + LogsDirectory = "seafile"; + ConfigurationDirectory = "seafile"; + ExecStart = '' + ${pkgs.seahub.python.pkgs.gunicorn}/bin/gunicorn seahub.wsgi:application \ + --name seahub \ + --workers ${toString cfg.workers} \ + --log-level=info \ + --preload \ + --timeout=1200 \ + --limit-request-line=8190 \ + --bind unix:/run/seahub/gunicorn.sock + ''; + }; + preStart = '' + mkdir -p ${seahubDir}/media + # Link all media except avatars + for m in `find ${pkgs.seahub}/media/ -maxdepth 1 -not -name "avatars"`; do + ln -sf $m ${seahubDir}/media/ + done + if [ ! -e "${seafRoot}/.seahubSecret" ]; then + ${pkgs.seahub.python}/bin/python ${pkgs.seahub}/tools/secret_key_generator.py > ${seafRoot}/.seahubSecret + chmod 400 ${seafRoot}/.seahubSecret + fi + if [ ! -f "${seafRoot}/seahub-setup" ]; then + # avatars directory should be writable + install -D -t ${seahubDir}/media/avatars/ ${pkgs.seahub}/media/avatars/default.png + install -D -t ${seahubDir}/media/avatars/groups ${pkgs.seahub}/media/avatars/groups/default.png + # init database + ${pkgs.seahub}/manage.py migrate + # create admin account + ${pkgs.expect}/bin/expect -c 'spawn ${pkgs.seahub}/manage.py createsuperuser --email=${cfg.adminEmail}; expect "Password: "; send "${cfg.initialAdminPassword}\r"; expect "Password (again): "; send "${cfg.initialAdminPassword}\r"; expect "Superuser created successfully."' + echo "${pkgs.seahub.version}-sqlite" > "${seafRoot}/seahub-setup" + fi + if [ $(cat "${seafRoot}/seahub-setup" | cut -d"-" -f1) != "${pkgs.seahub.version}" ]; then + # update database + ${pkgs.seahub}/manage.py migrate + echo "${pkgs.seahub.version}-sqlite" > "${seafRoot}/seahub-setup" + fi ''; }; - preStart = '' - mkdir -p ${seahubDir}/media - # Link all media except avatars - for m in `find ${pkgs.seahub}/media/ -maxdepth 1 -not -name "avatars"`; do - ln -sf $m ${seahubDir}/media/ - done - if [ ! -e "${seafRoot}/.seahubSecret" ]; then - ${pkgs.seahub.python}/bin/python ${pkgs.seahub}/tools/secret_key_generator.py > ${seafRoot}/.seahubSecret - chmod 400 ${seafRoot}/.seahubSecret - fi - if [ ! -f "${seafRoot}/seahub-setup" ]; then - # avatars directory should be writable - install -D -t ${seahubDir}/media/avatars/ ${pkgs.seahub}/media/avatars/default.png - install -D -t ${seahubDir}/media/avatars/groups ${pkgs.seahub}/media/avatars/groups/default.png - # init database - ${pkgs.seahub}/manage.py migrate - # create admin account - ${pkgs.expect}/bin/expect -c 'spawn ${pkgs.seahub}/manage.py createsuperuser --email=${cfg.adminEmail}; expect "Password: "; send "${cfg.initialAdminPassword}\r"; expect "Password (again): "; send "${cfg.initialAdminPassword}\r"; expect "Superuser created successfully."' - echo "${pkgs.seahub.version}-sqlite" > "${seafRoot}/seahub-setup" - fi - if [ $(cat "${seafRoot}/seahub-setup" | cut -d"-" -f1) != "${pkgs.seahub.version}" ]; then - # update database - ${pkgs.seahub}/manage.py migrate - echo "${pkgs.seahub.version}-sqlite" > "${seafRoot}/seahub-setup" - fi - ''; }; - }; }; } diff --git a/nixos/modules/services/networking/strongswan-swanctl/module.nix b/nixos/modules/services/networking/strongswan-swanctl/module.nix index a98850923955..c1f0aeb64e96 100644 --- a/nixos/modules/services/networking/strongswan-swanctl/module.nix +++ b/nixos/modules/services/networking/strongswan-swanctl/module.nix @@ -5,6 +5,9 @@ with (import ./param-lib.nix lib); let cfg = config.services.strongswan-swanctl; + configFile = pkgs.writeText "swanctl.conf" + ( (paramsToConf cfg.swanctl swanctlParams) + + (concatMapStrings (i: "\ninclude ${i}") cfg.includes)); swanctlParams = import ./swanctl-params.nix lib; in { options.services.strongswan-swanctl = { @@ -21,6 +24,13 @@ in { }; swanctl = paramsToOptions swanctlParams; + includes = mkOption { + type = types.listOf types.path; + default = []; + description = '' + Extra configuration files to include in the swanctl configuration. This can be used to provide secret values from outside the nix store. + ''; + }; }; config = mkIf cfg.enable { @@ -31,8 +41,7 @@ in { } ]; - environment.etc."swanctl/swanctl.conf".text = - paramsToConf cfg.swanctl swanctlParams; + environment.etc."swanctl/swanctl.conf".source = configFile; # The swanctl command complains when the following directories don't exist: # See: https://wiki.strongswan.org/projects/strongswan/wiki/Swanctldirectory diff --git a/nixos/modules/services/web-apps/photoprism.nix b/nixos/modules/services/web-apps/photoprism.nix index e25b03484424..1716840e84e5 100644 --- a/nixos/modules/services/web-apps/photoprism.nix +++ b/nixos/modules/services/web-apps/photoprism.nix @@ -18,6 +18,9 @@ let in pkgs.writeShellScript "manage" '' ${setupEnv} + eval "$(${config.systemd.package}/bin/systemctl show -pUID,MainPID photoprism.service | ${pkgs.gnused}/bin/sed "s/UID/ServiceUID/")" + exec ${pkgs.util-linux}/bin/nsenter \ + -t $MainPID -m -S $ServiceUID -G $ServiceUID --wdns=${cfg.storagePath} \ exec ${cfg.package}/bin/photoprism "$@" ''; in diff --git a/nixos/modules/services/web-apps/pretalx.nix b/nixos/modules/services/web-apps/pretalx.nix new file mode 100644 index 000000000000..ff6218112d2f --- /dev/null +++ b/nixos/modules/services/web-apps/pretalx.nix @@ -0,0 +1,415 @@ +{ config +, lib +, pkgs +, utils +, ... +}: + +let + cfg = config.services.pretalx; + format = pkgs.formats.ini { }; + + configFile = format.generate "pretalx.cfg" cfg.settings; + + extras = cfg.package.optional-dependencies.redis + ++ lib.optionals (cfg.settings.database.backend == "mysql") cfg.package.optional-dependencies.mysql + ++ lib.optionals (cfg.settings.database.backend == "postgresql") cfg.package.optional-dependencies.postgres; + + pythonEnv = cfg.package.python.buildEnv.override { + extraLibs = [ (cfg.package.python.pkgs.toPythonModule cfg.package) ] + ++ (with cfg.package.python.pkgs; [ gunicorn ] + ++ lib.optional cfg.celery.enable celery) ++ extras; + }; +in + +{ + meta = with lib; { + maintainers = teams.c3d2.members; + }; + + options.services.pretalx = { + enable = lib.mkEnableOption (lib.mdDoc "pretalx"); + + package = lib.mkPackageOptionMD pkgs "pretalx" {}; + + group = lib.mkOption { + type = lib.types.str; + default = "pretalx"; + description = "Group under which pretalx should run."; + }; + + user = lib.mkOption { + type = lib.types.str; + default = "pretalx"; + description = "User under which pretalx should run."; + }; + + gunicorn.extraArgs = lib.mkOption { + type = with lib.types; listOf str; + default = [ + "--name=pretalx" + ]; + example = [ + "--name=pretalx" + "--workers=4" + "--max-requests=1200" + "--max-requests-jitter=50" + "--log-level=info" + ]; + description = lib.mdDoc '' + Extra arguments to pass to gunicorn. + See <https://docs.pretalx.org/administrator/installation.html#step-6-starting-pretalx-as-a-service> for details. + ''; + apply = lib.escapeShellArgs; + }; + + celery = { + enable = lib.mkOption { + type = lib.types.bool; + default = true; + example = false; + description = lib.mdDoc '' + Whether to set up celery as an asynchronous task runner. + ''; + }; + + extraArgs = lib.mkOption { + type = with lib.types; listOf str; + default = [ ]; + description = lib.mdDoc '' + Extra arguments to pass to celery. + + See <https://docs.celeryq.dev/en/stable/reference/cli.html#celery-worker> for more info. + ''; + apply = utils.escapeSystemdExecArgs; + }; + }; + + nginx = { + enable = lib.mkOption { + type = lib.types.bool; + default = true; + example = false; + description = lib.mdDoc '' + Whether to set up an nginx virtual host. + ''; + }; + + domain = lib.mkOption { + type = lib.types.str; + example = "talks.example.com"; + description = lib.mdDoc '' + The domain name under which to set up the virtual host. + ''; + }; + }; + + database.createLocally = lib.mkOption { + type = lib.types.bool; + default = true; + example = false; + description = lib.mdDoc '' + Whether to automatically set up the database on the local DBMS instance. + + Currently only supported for PostgreSQL. Not required for sqlite. + ''; + }; + + settings = lib.mkOption { + type = lib.types.submodule { + freeformType = format.type; + options = { + database = { + backend = lib.mkOption { + type = lib.types.enum [ + "postgresql" + ]; + default = "postgresql"; + description = lib.mdDoc '' + Database backend to use. + + Currently only PostgreSQL gets tested, and as such we don't support any other DBMS. + ''; + readOnly = true; # only postgres supported right now + }; + + host = lib.mkOption { + type = with lib.types; nullOr types.path; + default = if cfg.settings.database.backend == "postgresql" then "/run/postgresql" + else if cfg.settings.database.backend == "mysql" then "/run/mysqld/mysqld.sock" + else null; + defaultText = lib.literalExpression '' + if config.services.pretalx.settings..database.backend == "postgresql" then "/run/postgresql" + else if config.services.pretalx.settings.database.backend == "mysql" then "/run/mysqld/mysqld.sock" + else null + ''; + description = lib.mdDoc '' + Database host or socket path. + ''; + }; + + name = lib.mkOption { + type = lib.types.str; + default = "pretalx"; + description = lib.mdDoc '' + Database name. + ''; + }; + + user = lib.mkOption { + type = lib.types.str; + default = "pretalx"; + description = lib.mdDoc '' + Database username. + ''; + }; + }; + + filesystem = { + data = lib.mkOption { + type = lib.types.path; + default = "/var/lib/pretalx"; + description = lib.mdDoc '' + Base path for all other storage paths. + ''; + }; + logs = lib.mkOption { + type = lib.types.path; + default = "/var/log/pretalx"; + description = lib.mdDoc '' + Path to the log directory, that pretalx logs message to. + ''; + }; + static = lib.mkOption { + type = lib.types.path; + default = "${cfg.package.static}/"; + defaultText = lib.literalExpression "\${config.services.pretalx.package}.static}/"; + readOnly = true; + description = lib.mdDoc '' + Path to the directory that contains static files. + ''; + }; + }; + + celery = { + backend = lib.mkOption { + type = with lib.types; nullOr str; + default = lib.optionalString cfg.celery.enable "redis+socket://${config.services.redis.servers.pretalx.unixSocket}?virtual_host=1"; + defaultText = lib.literalExpression '' + optionalString config.services.pretalx.celery.enable "redis+socket://''${config.services.redis.servers.pretalx.unixSocket}?virtual_host=1" + ''; + description = lib.mdDoc '' + URI to the celery backend used for the asynchronous job queue. + ''; + }; + + broker = lib.mkOption { + type = with lib.types; nullOr str; + default = lib.optionalString cfg.celery.enable "redis+socket://${config.services.redis.servers.pretalx.unixSocket}?virtual_host=2"; + defaultText = lib.literalExpression '' + optionalString config.services.pretalx.celery.enable "redis+socket://''${config.services.redis.servers.pretalx.unixSocket}?virtual_host=2" + ''; + description = lib.mdDoc '' + URI to the celery broker used for the asynchronous job queue. + ''; + }; + }; + + redis = { + location = lib.mkOption { + type = with lib.types; nullOr str; + default = "unix://${config.services.redis.servers.pretalx.unixSocket}?db=0"; + defaultText = lib.literalExpression '' + "unix://''${config.services.redis.servers.pretalx.unixSocket}?db=0" + ''; + description = lib.mdDoc '' + URI to the redis server, used to speed up locking, caching and session storage. + ''; + }; + + session = lib.mkOption { + type = lib.types.bool; + default = true; + example = false; + description = lib.mdDoc '' + Whether to use redis as the session storage. + ''; + }; + }; + + site = { + url = lib.mkOption { + type = lib.types.str; + default = "https://${cfg.nginx.domain}"; + defaultText = lib.literalExpression "https://\${config.services.pretalx.nginx.domain}"; + example = "https://talks.example.com"; + description = lib.mdDoc '' + The base URI below which your pretalx instance will be reachable. + ''; + }; + }; + }; + }; + default = { }; + description = lib.mdDoc '' + pretalx configuration as a Nix attribute set. All settings can also be passed + from the environment. + + See <https://docs.pretalx.org/administrator/configure.html> for possible options. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + # https://docs.pretalx.org/administrator/installation.html + + environment.systemPackages = [ + (pkgs.writeScriptBin "pretalx-manage" '' + cd ${cfg.settings.filesystem.data} + sudo=exec + if [[ "$USER" != ${cfg.user} ]]; then + sudo='exec /run/wrappers/bin/sudo -u ${cfg.user} --preserve-env=PRETALX_CONFIG_FILE' + fi + export PRETALX_CONFIG_FILE=${configFile} + $sudo ${lib.getExe' pythonEnv "pretalx-manage"} "$@" + '') + ]; + + services = { + nginx = lib.mkIf cfg.nginx.enable { + enable = true; + recommendedGzipSettings = lib.mkDefault true; + recommendedOptimisation = lib.mkDefault true; + recommendedProxySettings = lib.mkDefault true; + recommendedTlsSettings = lib.mkDefault true; + upstreams.pretalx.servers."unix:/run/pretalx/pretalx.sock" = { }; + virtualHosts.${cfg.nginx.domain} = { + # https://docs.pretalx.org/administrator/installation.html#step-7-ssl + extraConfig = '' + more_set_headers Referrer-Policy same-origin; + more_set_headers X-Content-Type-Options nosniff; + ''; + locations = { + "/".proxyPass = "http://pretalx"; + "/media/" = { + alias = "${cfg.settings.filesystem.data}/data/media/"; + extraConfig = '' + access_log off; + more_set_headers Content-Disposition 'attachment; filename="$1"'; + expires 7d; + ''; + }; + "/static/" = { + alias = cfg.settings.filesystem.static; + extraConfig = '' + access_log off; + more_set_headers Cache-Control "public"; + expires 365d; + ''; + }; + }; + }; + }; + + postgresql = lib.mkIf (cfg.database.createLocally && cfg.settings.database.backend == "postgresql") { + enable = true; + ensureUsers = [ { + name = cfg.settings.database.user; + ensureDBOwnership = true; + } ]; + ensureDatabases = [ cfg.settings.database.name ]; + }; + + redis.servers.pretalx.enable = true; + }; + + systemd.services = let + commonUnitConfig = { + environment.PRETALX_CONFIG_FILE = configFile; + serviceConfig = { + User = "pretalx"; + Group = "pretalx"; + StateDirectory = [ "pretalx" "pretalx/media" ]; + LogsDirectory = "pretalx"; + WorkingDirectory = cfg.settings.filesystem.data; + SupplementaryGroups = [ "redis-pretalx" ]; + }; + }; + in { + pretalx-web = lib.recursiveUpdate commonUnitConfig { + description = "pretalx web service"; + after = [ + "network.target" + "redis-pretalx.service" + ] ++ lib.optionals (cfg.settings.database.backend == "postgresql") [ + "postgresql.service" + ] ++ lib.optionals (cfg.settings.database.backend == "mysql") [ + "mysql.service" + ]; + wantedBy = [ "multi-user.target" ]; + preStart = '' + versionFile="${cfg.settings.filesystem.data}/.version" + version=$(cat "$versionFile" 2>/dev/null || echo 0) + + if [[ $version != ${cfg.package.version} ]]; then + ${lib.getExe' pythonEnv "pretalx-manage"} migrate + + echo "${cfg.package.version}" > "$versionFile" + fi + ''; + serviceConfig = { + ExecStart = "${lib.getExe' pythonEnv "gunicorn"} --bind unix:/run/pretalx/pretalx.sock ${cfg.gunicorn.extraArgs} pretalx.wsgi"; + RuntimeDirectory = "pretalx"; + }; + }; + + pretalx-periodic = lib.recursiveUpdate commonUnitConfig { + description = "pretalx periodic task runner"; + # every 15 minutes + startAt = [ "*:3,18,33,48" ]; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${lib.getExe' pythonEnv "pretalx-manage"} runperiodic"; + }; + }; + + pretalx-clear-sessions = lib.recursiveUpdate commonUnitConfig { + description = "pretalx session pruning"; + startAt = [ "monthly" ]; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${lib.getExe' pythonEnv "pretalx-manage"} clearsessions"; + }; + }; + + pretalx-worker = lib.mkIf cfg.celery.enable (lib.recursiveUpdate commonUnitConfig { + description = "pretalx asynchronous job runner"; + after = [ + "network.target" + "redis-pretalx.service" + ] ++ lib.optionals (cfg.settings.database.backend == "postgresql") [ + "postgresql.service" + ] ++ lib.optionals (cfg.settings.database.backend == "mysql") [ + "mysql.service" + ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig.ExecStart = "${lib.getExe' pythonEnv "celery"} -A pretalx.celery_app worker ${cfg.celery.extraArgs}"; + }); + }; + + systemd.sockets.pretalx-web.socketConfig = { + ListenStream = "/run/pretalx/pretalx.sock"; + SocketUser = "nginx"; + }; + + users = { + groups."${cfg.group}" = {}; + users."${cfg.user}" = { + isSystemUser = true; + createHome = true; + home = cfg.settings.filesystem.data; + inherit (cfg) group; + }; + }; + }; +} diff --git a/nixos/modules/services/x11/desktop-managers/deepin.nix b/nixos/modules/services/x11/desktop-managers/deepin.nix index 7fdd50b1ed26..7d3acada6073 100644 --- a/nixos/modules/services/x11/desktop-managers/deepin.nix +++ b/nixos/modules/services/x11/desktop-managers/deepin.nix @@ -96,18 +96,10 @@ in "/share/dde-daemon" "/share/dsg" "/share/deepin-themes" + "/share/deepin" ]; environment.etc = { - "distribution.info".text = '' - [Distribution] - Name=NixOS - WebsiteName=www.nixos.org - Website=https://www.nixos.org - Logo=${pkgs.nixos-icons}/share/icons/hicolor/96x96/apps/nix-snowflake.png - LogoLight=${pkgs.nixos-icons}/share/icons/hicolor/32x32/apps/nix-snowflake.png - LogoTransparent=${pkgs.deepin.deepin-desktop-base}/share/pixmaps/distribution_logo_transparent.svg - ''; "deepin-installer.conf".text = '' system_info_vendor_name="Copyright (c) 2003-2023 NixOS contributors" ''; @@ -156,6 +148,7 @@ in deepin-sound-theme deepin-gtk-theme deepin-wallpapers + deepin-desktop-base startdde dde-dock diff --git a/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixos/modules/services/x11/desktop-managers/plasma5.nix index 38c858aaef05..677465f55c47 100644 --- a/nixos/modules/services/x11/desktop-managers/plasma5.nix +++ b/nixos/modules/services/x11/desktop-managers/plasma5.nix @@ -185,6 +185,8 @@ in }; }; + qt.enable = true; + environment.systemPackages = with pkgs.plasma5Packages; let @@ -253,6 +255,9 @@ in plasma-integration polkit-kde-agent + qqc2-breeze-style + qqc2-desktop-style + plasma-desktop plasma-workspace plasma-workspace-wallpapers diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py index 055afe95df60..a9978d7adf80 100644 --- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py +++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py @@ -18,7 +18,7 @@ from dataclasses import dataclass # These values will be replaced with actual values during the package build EFI_SYS_MOUNT_POINT = "@efiSysMountPoint@" TIMEOUT = "@timeout@" -EDITOR = bool("@editor@") +EDITOR = "@editor@" == "1" CONSOLE_MODE = "@consoleMode@" BOOTSPEC_TOOLS = "@bootspecTools@" DISTRO_NAME = "@distroName@" diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix index a126a6725e1b..ea4553b8208f 100644 --- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix +++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix @@ -22,11 +22,9 @@ let timeout = optionalString (config.boot.loader.timeout != null) config.boot.loader.timeout; - editor = if cfg.editor then "True" else "False"; - configurationLimit = if cfg.configurationLimit == null then 0 else cfg.configurationLimit; - inherit (cfg) consoleMode graceful; + inherit (cfg) consoleMode graceful editor; inherit (efi) efiSysMountPoint canTouchEfiVariables; |