diff options
Diffstat (limited to 'nixos/modules/services')
-rw-r--r-- | nixos/modules/services/backup/znapzend.nix | 11 | ||||
-rw-r--r-- | nixos/modules/services/databases/postgresql.nix | 12 | ||||
-rw-r--r-- | nixos/modules/services/network-filesystems/ipfs.nix | 3 | ||||
-rw-r--r-- | nixos/modules/services/networking/pixiecore.nix | 2 | ||||
-rw-r--r-- | nixos/modules/services/security/privacyidea.nix | 279 | ||||
-rw-r--r-- | nixos/modules/services/web-servers/nginx/default.nix | 29 | ||||
-rw-r--r-- | nixos/modules/services/x11/window-managers/default.nix | 1 | ||||
-rw-r--r-- | nixos/modules/services/x11/window-managers/tinywm.nix | 25 |
8 files changed, 359 insertions, 3 deletions
diff --git a/nixos/modules/services/backup/znapzend.nix b/nixos/modules/services/backup/znapzend.nix index 98cd647f61a..8098617d11f 100644 --- a/nixos/modules/services/backup/znapzend.nix +++ b/nixos/modules/services/backup/znapzend.nix @@ -268,7 +268,8 @@ let mkSrcAttrs = srcCfg: with srcCfg; { enabled = onOff enable; - mbuffer = with mbuffer; if enable then "${pkgs.mbuffer}/bin/mbuffer" + # mbuffer is not referenced by its full path to accomodate non-NixOS systems or differing mbuffer versions between source and target + mbuffer = with mbuffer; if enable then "mbuffer" + optionalString (port != null) ":${toString port}" else "off"; mbuffer_size = mbuffer.size; post_znap_cmd = nullOff postsnap; @@ -357,6 +358,12 @@ in default = false; }; + features.oracleMode = mkEnableOption '' + Destroy snapshots one by one instead of using one long argument list. + If source and destination are out of sync for a long time, you may have + so many snapshots to destroy that the argument gets is too long and the + command fails. + ''; features.recvu = mkEnableOption '' recvu feature which uses <literal>-u</literal> on the receiving end to keep the destination filesystem unmounted. @@ -458,5 +465,5 @@ in }; }; - meta.maintainers = with maintainers; [ infinisil ]; + meta.maintainers = with maintainers; [ infinisil SlothOfAnarchy ]; } diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix index 93f5c1ca5f5..982480fbd99 100644 --- a/nixos/modules/services/databases/postgresql.nix +++ b/nixos/modules/services/databases/postgresql.nix @@ -17,6 +17,7 @@ let hba_file = '${pkgs.writeText "pg_hba.conf" cfg.authentication}' ident_file = '${pkgs.writeText "pg_ident.conf" cfg.identMap}' log_destination = 'stderr' + log_line_prefix = '${cfg.logLinePrefix}' listen_addresses = '${if cfg.enableTCPIP then "*" else "localhost"}' port = ${toString cfg.port} ${cfg.extraConfig} @@ -186,6 +187,17 @@ in ''; }; + logLinePrefix = mkOption { + type = types.str; + default = "[%p] "; + example = "%m [%p] "; + description = '' + A printf-style string that is output at the beginning of each log line. + Upstream default is <literal>'%m [%p] '</literal>, i.e. it includes the timestamp. We do + not include the timestamp, because journal has it anyway. + ''; + }; + extraPlugins = mkOption { type = types.listOf types.path; default = []; diff --git a/nixos/modules/services/network-filesystems/ipfs.nix b/nixos/modules/services/network-filesystems/ipfs.nix index 880f70ae141..1f5c14d777d 100644 --- a/nixos/modules/services/network-filesystems/ipfs.nix +++ b/nixos/modules/services/network-filesystems/ipfs.nix @@ -217,6 +217,9 @@ in { createHome = false; uid = config.ids.uids.ipfs; description = "IPFS daemon user"; + packages = [ + pkgs.ipfs-migrator + ]; }; }; diff --git a/nixos/modules/services/networking/pixiecore.nix b/nixos/modules/services/networking/pixiecore.nix index 0e32f182e2a..85aa40784af 100644 --- a/nixos/modules/services/networking/pixiecore.nix +++ b/nixos/modules/services/networking/pixiecore.nix @@ -115,7 +115,7 @@ in if cfg.mode == "boot" then [ "boot" cfg.kernel ] ++ optional (cfg.initrd != "") cfg.initrd - ++ optional (cfg.cmdLine != "") "--cmdline=${lib.escapeShellArg cfg.cmdLine}" + ++ optionals (cfg.cmdLine != "") [ "--cmdline" cfg.cmdLine ] else [ "api" cfg.apiServer ]; in '' diff --git a/nixos/modules/services/security/privacyidea.nix b/nixos/modules/services/security/privacyidea.nix new file mode 100644 index 00000000000..d6abfd0e271 --- /dev/null +++ b/nixos/modules/services/security/privacyidea.nix @@ -0,0 +1,279 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.privacyidea; + + uwsgi = pkgs.uwsgi.override { plugins = [ "python3" ]; }; + python = uwsgi.python3; + penv = python.withPackages (ps: [ ps.privacyidea ]); + logCfg = pkgs.writeText "privacyidea-log.cfg" '' + [formatters] + keys=detail + + [handlers] + keys=stream + + [formatter_detail] + class=privacyidea.lib.log.SecureFormatter + format=[%(asctime)s][%(process)d][%(thread)d][%(levelname)s][%(name)s:%(lineno)d] %(message)s + + [handler_stream] + class=StreamHandler + level=NOTSET + formatter=detail + args=(sys.stdout,) + + [loggers] + keys=root,privacyidea + + [logger_privacyidea] + handlers=stream + qualname=privacyidea + level=INFO + + [logger_root] + handlers=stream + level=ERROR + ''; + + piCfgFile = pkgs.writeText "privacyidea.cfg" '' + SUPERUSER_REALM = [ '${concatStringsSep "', '" cfg.superuserRealm}' ] + SQLALCHEMY_DATABASE_URI = 'postgresql:///privacyidea' + SECRET_KEY = '${cfg.secretKey}' + PI_PEPPER = '${cfg.pepper}' + PI_ENCFILE = '${cfg.encFile}' + PI_AUDIT_KEY_PRIVATE = '${cfg.auditKeyPrivate}' + PI_AUDIT_KEY_PUBLIC = '${cfg.auditKeyPublic}' + PI_LOGCONFIG = '${logCfg}' + ${cfg.extraConfig} + ''; + +in + +{ + options = { + services.privacyidea = { + enable = mkEnableOption "PrivacyIDEA"; + + stateDir = mkOption { + type = types.str; + default = "/var/lib/privacyidea"; + description = '' + Directory where all PrivacyIDEA files will be placed by default. + ''; + }; + + superuserRealm = mkOption { + type = types.listOf types.str; + default = [ "super" "administrators" ]; + description = '' + The realm where users are allowed to login as administrators. + ''; + }; + + secretKey = mkOption { + type = types.str; + example = "t0p s3cr3t"; + description = '' + This is used to encrypt the auth_token. + ''; + }; + + pepper = mkOption { + type = types.str; + example = "Never know..."; + description = '' + This is used to encrypt the admin passwords. + ''; + }; + + encFile = mkOption { + type = types.str; + default = "${cfg.stateDir}/enckey"; + description = '' + This is used to encrypt the token data and token passwords + ''; + }; + + auditKeyPrivate = mkOption { + type = types.str; + default = "${cfg.stateDir}/private.pem"; + description = '' + Private Key for signing the audit log. + ''; + }; + + auditKeyPublic = mkOption { + type = types.str; + default = "${cfg.stateDir}/public.pem"; + description = '' + Public key for checking signatures of the audit log. + ''; + }; + + adminPasswordFile = mkOption { + type = types.path; + description = "File containing password for the admin user"; + }; + + adminEmail = mkOption { + type = types.str; + example = "admin@example.com"; + description = "Mail address for the admin user"; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra configuration options for pi.cfg. + ''; + }; + + user = mkOption { + type = types.str; + default = "privacyidea"; + description = "User account under which PrivacyIDEA runs."; + }; + + group = mkOption { + type = types.str; + default = "privacyidea"; + description = "Group account under which PrivacyIDEA runs."; + }; + + ldap-proxy = { + enable = mkEnableOption "PrivacyIDEA LDAP Proxy"; + + configFile = mkOption { + type = types.path; + default = ""; + description = '' + Path to PrivacyIDEA LDAP Proxy configuration (proxy.ini). + ''; + }; + + user = mkOption { + type = types.str; + default = "pi-ldap-proxy"; + description = "User account under which PrivacyIDEA LDAP proxy runs."; + }; + + group = mkOption { + type = types.str; + default = "pi-ldap-proxy"; + description = "Group account under which PrivacyIDEA LDAP proxy runs."; + }; + }; + }; + }; + + config = mkMerge [ + + (mkIf cfg.enable { + + environment.systemPackages = [ python.pkgs.privacyidea ]; + + services.postgresql.enable = mkDefault true; + + systemd.services.privacyidea = let + piuwsgi = pkgs.writeText "uwsgi.json" (builtins.toJSON { + uwsgi = { + plugins = [ "python3" ]; + pythonpath = "${penv}/${uwsgi.python3.sitePackages}"; + socket = "/run/privacyidea/socket"; + uid = cfg.user; + gid = cfg.group; + chmod-socket = 770; + chown-socket = "${cfg.user}:nginx"; + chdir = cfg.stateDir; + wsgi-file = "${penv}/etc/privacyidea/privacyideaapp.wsgi"; + processes = 4; + harakiri = 60; + reload-mercy = 8; + stats = "/run/privacyidea/stats.socket"; + max-requests = 2000; + limit-as = 1024; + reload-on-as = 512; + reload-on-rss = 256; + no-orphans = true; + vacuum = true; + }; + }); + in { + wantedBy = [ "multi-user.target" ]; + after = [ "postgresql.service" ]; + path = with pkgs; [ openssl ]; + environment.PRIVACYIDEA_CONFIGFILE = piCfgFile; + preStart = let + pi-manage = "${pkgs.sudo}/bin/sudo -u privacyidea -HE ${penv}/bin/pi-manage"; + pgsu = config.services.postgresql.superUser; + psql = config.services.postgresql.package; + in '' + mkdir -p ${cfg.stateDir} /run/privacyidea + chown ${cfg.user}:${cfg.group} -R ${cfg.stateDir} /run/privacyidea + if ! test -e "${cfg.stateDir}/db-created"; then + ${pkgs.sudo}/bin/sudo -u ${pgsu} ${psql}/bin/createuser --no-superuser --no-createdb --no-createrole ${cfg.user} + ${pkgs.sudo}/bin/sudo -u ${pgsu} ${psql}/bin/createdb --owner ${cfg.user} privacyidea + ${pi-manage} create_enckey + ${pi-manage} create_audit_keys + ${pi-manage} createdb + ${pi-manage} admin add admin -e ${cfg.adminEmail} -p "$(cat ${cfg.adminPasswordFile})" + ${pi-manage} db stamp head -d ${penv}/lib/privacyidea/migrations + touch "${cfg.stateDir}/db-created" + chmod g+r "${cfg.stateDir}/enckey" "${cfg.stateDir}/private.pem" + fi + ${pi-manage} db upgrade -d ${penv}/lib/privacyidea/migrations + ''; + serviceConfig = { + Type = "notify"; + ExecStart = "${uwsgi}/bin/uwsgi --json ${piuwsgi}"; + ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID"; + NotifyAccess = "main"; + KillSignal = "SIGQUIT"; + StandardError = "syslog"; + }; + }; + + users.users.privacyidea = mkIf (cfg.user == "privacyidea") { + group = cfg.group; + }; + + users.groups.privacyidea = mkIf (cfg.group == "privacyidea") {}; + }) + + (mkIf cfg.ldap-proxy.enable { + + systemd.services.privacyidea-ldap-proxy = let + ldap-proxy-env = pkgs.python2.withPackages (ps: [ ps.privacyidea-ldap-proxy ]); + in { + description = "privacyIDEA LDAP proxy"; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + User = cfg.ldap-proxy.user; + Group = cfg.ldap-proxy.group; + ExecStart = '' + ${ldap-proxy-env}/bin/twistd \ + --nodaemon \ + --pidfile= \ + -u ${cfg.ldap-proxy.user} \ + -g ${cfg.ldap-proxy.group} \ + ldap-proxy \ + -c ${cfg.ldap-proxy.configFile} + ''; + Restart = "always"; + }; + }; + + users.users.pi-ldap-proxy = mkIf (cfg.ldap-proxy.user == "pi-ldap-proxy") { + group = cfg.ldap-proxy.group; + }; + + users.groups.pi-ldap-proxy = mkIf (cfg.ldap-proxy.group == "pi-ldap-proxy") {}; + }) + ]; + +} diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index 1e9cda7e478..312d2b0a21a 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -463,6 +463,14 @@ in ''; }; + enableSandbox = mkOption { + default = false; + type = types.bool; + description = '' + Starting Nginx web server with additional sandbox/hardening options. + ''; + }; + user = mkOption { type = types.str; default = "nginx"; @@ -710,6 +718,27 @@ in LogsDirectoryMode = "0750"; # Capabilities AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" "CAP_SYS_RESOURCE" ]; + CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" "CAP_SYS_RESOURCE" ]; + # Security + NoNewPrivileges = true; + } // optionalAttrs cfg.enableSandbox { + # Sandboxing + ProtectSystem = "strict"; + ProtectHome = mkDefault true; + PrivateTmp = true; + PrivateDevices = true; + ProtectHostname = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectControlGroups = true; + RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ]; + LockPersonality = true; + MemoryDenyWriteExecute = !(builtins.any (mod: (mod.allowMemoryWriteExecute or false)) pkgs.nginx.modules); + RestrictRealtime = true; + RestrictSUIDSGID = true; + PrivateMounts = true; + # System Call Filtering + SystemCallArchitectures = "native"; }; }; diff --git a/nixos/modules/services/x11/window-managers/default.nix b/nixos/modules/services/x11/window-managers/default.nix index 04a9fc46628..b815c5f16a1 100644 --- a/nixos/modules/services/x11/window-managers/default.nix +++ b/nixos/modules/services/x11/window-managers/default.nix @@ -30,6 +30,7 @@ in ./sawfish.nix ./stumpwm.nix ./spectrwm.nix + ./tinywm.nix ./twm.nix ./windowmaker.nix ./wmii.nix diff --git a/nixos/modules/services/x11/window-managers/tinywm.nix b/nixos/modules/services/x11/window-managers/tinywm.nix new file mode 100644 index 00000000000..8e5d9b9170c --- /dev/null +++ b/nixos/modules/services/x11/window-managers/tinywm.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.xserver.windowManager.tinywm; +in +{ + ###### interface + options = { + services.xserver.windowManager.tinywm.enable = mkEnableOption "tinywm"; + }; + + ###### implementation + config = mkIf cfg.enable { + services.xserver.windowManager.session = singleton { + name = "tinywm"; + start = '' + ${pkgs.tinywm}/bin/tinywm & + waitPID=$! + ''; + }; + environment.systemPackages = [ pkgs.tinywm ]; + }; +} |