diff options
Diffstat (limited to 'nixos/modules')
-rw-r--r-- | nixos/modules/config/nix-channel.nix | 2 | ||||
-rw-r--r-- | nixos/modules/image/repart.md | 137 | ||||
-rw-r--r-- | nixos/modules/image/repart.nix | 51 | ||||
-rw-r--r-- | nixos/modules/module-list.nix | 7 | ||||
-rw-r--r-- | nixos/modules/programs/direnv.nix | 2 | ||||
-rw-r--r-- | nixos/modules/services/networking/bitcoind.nix | 3 | ||||
-rw-r--r-- | nixos/modules/services/security/privacyidea.nix | 458 | ||||
-rw-r--r-- | nixos/modules/virtualisation/oci-containers.nix | 39 |
8 files changed, 54 insertions, 645 deletions
diff --git a/nixos/modules/config/nix-channel.nix b/nixos/modules/config/nix-channel.nix index 4abc846b08586..0565c9cc8dad9 100644 --- a/nixos/modules/config/nix-channel.nix +++ b/nixos/modules/config/nix-channel.nix @@ -99,7 +99,7 @@ in systemd.tmpfiles.rules = lib.mkIf cfg.channel.enable [ "f /root/.nix-channels -" - ''w "/root/.nix-channels" - - - - "${config.system.defaultChannel} nixos\n"'' + ''w+ "/root/.nix-channels" - - - - ${config.system.defaultChannel} nixos\n'' ]; }; } diff --git a/nixos/modules/image/repart.md b/nixos/modules/image/repart.md deleted file mode 100644 index 6d0675f21a033..0000000000000 --- a/nixos/modules/image/repart.md +++ /dev/null @@ -1,137 +0,0 @@ -# Building Images via `systemd-repart` {#sec-image-repart} - -You can build disk images in NixOS with the `image.repart` option provided by -the module [image/repart.nix][]. This module uses `systemd-repart` to build the -images and exposes it's entire interface via the `repartConfig` option. - -[image/repart.nix]: https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/image/repart.nix - -An example of how to build an image: - -```nix -{ config, modulesPath, ... }: { - - imports = [ "${modulesPath}/image/repart.nix" ]; - - image.repart = { - name = "image"; - partitions = { - "esp" = { - contents = { - ... - }; - repartConfig = { - Type = "esp"; - ... - }; - }; - "root" = { - storePaths = [ config.system.build.toplevel ]; - repartConfig = { - Type = "root"; - Label = "nixos"; - ... - }; - }; - }; - }; - -} -``` - -## Nix Store Partition {#sec-image-repart-store-partition} - -You can define a partition that only contains the Nix store and then mount it -under `/nix/store`. Because the `/nix/store` part of the paths is already -determined by the mount point, you have to set `stripNixStorePrefix = true;` so -that the prefix is stripped from the paths before copying them into the image. - -```nix -fileSystems."/nix/store".device = "/dev/disk/by-partlabel/nix-store" - -image.repart.partitions = { - "store" = { - storePaths = [ config.system.build.toplevel ]; - stripNixStorePrefix = true; - repartConfig = { - Type = "linux-generic"; - Label = "nix-store"; - ... - }; - }; -}; -``` - -## Appliance Image {#sec-image-repart-appliance} - -The `image/repart.nix` module can also be used to build self-contained [software -appliances][]. - -[software appliances]: https://en.wikipedia.org/wiki/Software_appliance - -The generation based update mechanism of NixOS is not suited for appliances. -Updates of appliances are usually either performed by replacing the entire -image with a new one or by updating partitions via an A/B scheme. See the -[Chrome OS update process][chrome-os-update] for an example of how to achieve -this. The appliance image built in the following example does not contain a -`configuration.nix` and thus you will not be able to call `nixos-rebuild` from -this system. - -[chrome-os-update]: https://chromium.googlesource.com/aosp/platform/system/update_engine/+/HEAD/README.md - -```nix -let - pkgs = import <nixpkgs> { }; - efiArch = pkgs.stdenv.hostPlatform.efiArch; -in -(pkgs.nixos [ - ({ config, lib, pkgs, modulesPath, ... }: { - - imports = [ "${modulesPath}/image/repart.nix" ]; - - boot.loader.grub.enable = false; - - fileSystems."/".device = "/dev/disk/by-label/nixos"; - - image.repart = { - name = "image"; - partitions = { - "esp" = { - contents = { - "/EFI/BOOT/BOOT${lib.toUpper efiArch}.EFI".source = - "${pkgs.systemd}/lib/systemd/boot/efi/systemd-boot${efiArch}.efi"; - - "/loader/entries/nixos.conf".source = pkgs.writeText "nixos.conf" '' - title NixOS - linux /EFI/nixos/kernel.efi - initrd /EFI/nixos/initrd.efi - options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} - ''; - - "/EFI/nixos/kernel.efi".source = - "${config.boot.kernelPackages.kernel}/${config.system.boot.loader.kernelFile}"; - - "/EFI/nixos/initrd.efi".source = - "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}"; - }; - repartConfig = { - Type = "esp"; - Format = "vfat"; - SizeMinBytes = "96M"; - }; - }; - "root" = { - storePaths = [ config.system.build.toplevel ]; - repartConfig = { - Type = "root"; - Format = "ext4"; - Label = "nixos"; - Minimize = "guess"; - }; - }; - }; - }; - - }) -]).image -``` diff --git a/nixos/modules/image/repart.nix b/nixos/modules/image/repart.nix index 926791d857012..41e6110885b85 100644 --- a/nixos/modules/image/repart.nix +++ b/nixos/modules/image/repart.nix @@ -34,12 +34,13 @@ let }; }); default = { }; - example = lib.literalExpression '' { - "/EFI/BOOT/BOOTX64.EFI".source = - "''${pkgs.systemd}/lib/systemd/boot/efi/systemd-bootx64.efi"; + example = lib.literalExpression '' + { + "/EFI/BOOT/BOOTX64.EFI".source = + "''${pkgs.systemd}/lib/systemd/boot/efi/systemd-bootx64.efi"; - "/loader/entries/nixos.conf".source = systemdBootEntry; - } + "/loader/entries/nixos.conf".source = systemdBootEntry; + } ''; description = lib.mdDoc "The contents to end up in the filesystem image."; }; @@ -96,26 +97,27 @@ in partitions = lib.mkOption { type = with lib.types; attrsOf (submodule partitionOptions); default = { }; - example = lib.literalExpression '' { - "10-esp" = { - contents = { - "/EFI/BOOT/BOOTX64.EFI".source = - "''${pkgs.systemd}/lib/systemd/boot/efi/systemd-bootx64.efi"; - } - repartConfig = { - Type = "esp"; - Format = "fat"; + example = lib.literalExpression '' + { + "10-esp" = { + contents = { + "/EFI/BOOT/BOOTX64.EFI".source = + "''${pkgs.systemd}/lib/systemd/boot/efi/systemd-bootx64.efi"; + } + repartConfig = { + Type = "esp"; + Format = "fat"; + }; }; - }; - "20-root" = { - storePaths = [ config.system.build.toplevel ]; - repartConfig = { - Type = "root"; - Format = "ext4"; - Minimize = "guess"; + "20-root" = { + storePaths = [ config.system.build.toplevel ]; + repartConfig = { + Type = "root"; + Format = "ext4"; + Minimize = "guess"; + }; }; }; - }; ''; description = lib.mdDoc '' Specify partitions as a set of the names of the partitions with their @@ -206,10 +208,7 @@ in | tee repart-output.json ''; - meta = { - maintainers = with lib.maintainers; [ nikstur ]; - doc = ./repart.md; - }; + meta.maintainers = with lib.maintainers; [ nikstur ]; }; } diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 4949eb6f298e3..2a6ca202024b1 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1176,7 +1176,6 @@ ./services/security/opensnitch.nix ./services/security/pass-secret-service.nix ./services/security/physlock.nix - ./services/security/privacyidea.nix ./services/security/shibboleth-sp.nix ./services/security/sks.nix ./services/security/sshguard.nix @@ -1531,5 +1530,9 @@ ./virtualisation/waydroid.nix ./virtualisation/xe-guest-utilities.nix ./virtualisation/xen-dom0.nix - { documentation.nixos.extraModules = [ ./virtualisation/qemu-vm.nix ]; } + { documentation.nixos.extraModules = [ + ./virtualisation/qemu-vm.nix + ./image/repart.nix + ]; + } ] diff --git a/nixos/modules/programs/direnv.nix b/nixos/modules/programs/direnv.nix index 77a6568e73b88..2566fa7699bb5 100644 --- a/nixos/modules/programs/direnv.nix +++ b/nixos/modules/programs/direnv.nix @@ -54,7 +54,7 @@ in { }; imports = [ - (lib.mkRemovedOptionModule ["programs" "direnv" "persistDerivations"] "persistDerivations was removed as it is on longer necessary") + (lib.mkRemovedOptionModule ["programs" "direnv" "persistDerivations"] "persistDerivations was removed as it is no longer necessary") ]; config = lib.mkIf cfg.enable { diff --git a/nixos/modules/services/networking/bitcoind.nix b/nixos/modules/services/networking/bitcoind.nix index a86d52b7202d8..a48066b43b162 100644 --- a/nixos/modules/services/networking/bitcoind.nix +++ b/nixos/modules/services/networking/bitcoind.nix @@ -3,8 +3,7 @@ with lib; let - - eachBitcoind = config.services.bitcoind; + eachBitcoind = filterAttrs (bitcoindName: cfg: cfg.enable) config.services.bitcoind; rpcUserOpts = { name, ... }: { options = { diff --git a/nixos/modules/services/security/privacyidea.nix b/nixos/modules/services/security/privacyidea.nix deleted file mode 100644 index 664335cb58e89..0000000000000 --- a/nixos/modules/services/security/privacyidea.nix +++ /dev/null @@ -1,458 +0,0 @@ -{ config, lib, options, pkgs, ... }: - -with lib; - -let - cfg = config.services.privacyidea; - opt = options.services.privacyidea; - - uwsgi = pkgs.uwsgi.override { plugins = [ "python3" ]; python3 = pkgs.python310; }; - python = uwsgi.python3; - penv = python.withPackages (const [ pkgs.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+psycopg2:///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} - ''; - - renderValue = x: - if isList x then concatMapStringsSep "," (x: ''"${x}"'') x - else if isString x && hasInfix "," x then ''"${x}"'' - else x; - - ldapProxyConfig = pkgs.writeText "ldap-proxy.ini" - (generators.toINI {} - (flip mapAttrs cfg.ldap-proxy.settings - (const (mapAttrs (const renderValue))))); - - privacyidea-token-janitor = pkgs.writeShellScriptBin "privacyidea-token-janitor" '' - exec -a privacyidea-token-janitor \ - /run/wrappers/bin/sudo -u ${cfg.user} \ - env PRIVACYIDEA_CONFIGFILE=${cfg.stateDir}/privacyidea.cfg \ - ${penv}/bin/privacyidea-token-janitor $@ - ''; -in - -{ - options = { - services.privacyidea = { - enable = mkEnableOption (lib.mdDoc "PrivacyIDEA"); - - environmentFile = mkOption { - type = types.nullOr types.path; - default = null; - example = "/root/privacyidea.env"; - description = lib.mdDoc '' - File to load as environment file. Environment variables - from this file will be interpolated into the config file - using `envsubst` which is helpful for specifying - secrets: - ``` - { services.privacyidea.secretKey = "$SECRET"; } - ``` - - The environment-file can now specify the actual secret key: - ``` - SECRET=veryverytopsecret - ``` - ''; - }; - - stateDir = mkOption { - type = types.str; - default = "/var/lib/privacyidea"; - description = lib.mdDoc '' - Directory where all PrivacyIDEA files will be placed by default. - ''; - }; - - superuserRealm = mkOption { - type = types.listOf types.str; - default = [ "super" "administrators" ]; - description = lib.mdDoc '' - The realm where users are allowed to login as administrators. - ''; - }; - - secretKey = mkOption { - type = types.str; - example = "t0p s3cr3t"; - description = lib.mdDoc '' - This is used to encrypt the auth_token. - ''; - }; - - pepper = mkOption { - type = types.str; - example = "Never know..."; - description = lib.mdDoc '' - This is used to encrypt the admin passwords. - ''; - }; - - encFile = mkOption { - type = types.str; - default = "${cfg.stateDir}/enckey"; - defaultText = literalExpression ''"''${config.${opt.stateDir}}/enckey"''; - description = lib.mdDoc '' - This is used to encrypt the token data and token passwords - ''; - }; - - auditKeyPrivate = mkOption { - type = types.str; - default = "${cfg.stateDir}/private.pem"; - defaultText = literalExpression ''"''${config.${opt.stateDir}}/private.pem"''; - description = lib.mdDoc '' - Private Key for signing the audit log. - ''; - }; - - auditKeyPublic = mkOption { - type = types.str; - default = "${cfg.stateDir}/public.pem"; - defaultText = literalExpression ''"''${config.${opt.stateDir}}/public.pem"''; - description = lib.mdDoc '' - Public key for checking signatures of the audit log. - ''; - }; - - adminPasswordFile = mkOption { - type = types.path; - description = lib.mdDoc "File containing password for the admin user"; - }; - - adminEmail = mkOption { - type = types.str; - example = "admin@example.com"; - description = lib.mdDoc "Mail address for the admin user"; - }; - - extraConfig = mkOption { - type = types.lines; - default = ""; - description = lib.mdDoc '' - Extra configuration options for pi.cfg. - ''; - }; - - user = mkOption { - type = types.str; - default = "privacyidea"; - description = lib.mdDoc "User account under which PrivacyIDEA runs."; - }; - - group = mkOption { - type = types.str; - default = "privacyidea"; - description = lib.mdDoc "Group account under which PrivacyIDEA runs."; - }; - - tokenjanitor = { - enable = mkEnableOption (lib.mdDoc "automatic runs of the token janitor"); - interval = mkOption { - default = "quarterly"; - type = types.str; - description = lib.mdDoc '' - Interval in which the cleanup program is supposed to run. - See {manpage}`systemd.time(7)` for further information. - ''; - }; - action = mkOption { - type = types.enum [ "delete" "mark" "disable" "unassign" ]; - description = lib.mdDoc '' - Which action to take for matching tokens. - ''; - }; - unassigned = mkOption { - default = false; - type = types.bool; - description = lib.mdDoc '' - Whether to search for **unassigned** tokens - and apply [](#opt-services.privacyidea.tokenjanitor.action) - onto them. - ''; - }; - orphaned = mkOption { - default = true; - type = types.bool; - description = lib.mdDoc '' - Whether to search for **orphaned** tokens - and apply [](#opt-services.privacyidea.tokenjanitor.action) - onto them. - ''; - }; - }; - - ldap-proxy = { - enable = mkEnableOption (lib.mdDoc "PrivacyIDEA LDAP Proxy"); - - configFile = mkOption { - type = types.nullOr types.path; - default = null; - description = lib.mdDoc '' - Path to PrivacyIDEA LDAP Proxy configuration (proxy.ini). - ''; - }; - - user = mkOption { - type = types.str; - default = "pi-ldap-proxy"; - description = lib.mdDoc "User account under which PrivacyIDEA LDAP proxy runs."; - }; - - group = mkOption { - type = types.str; - default = "pi-ldap-proxy"; - description = lib.mdDoc "Group account under which PrivacyIDEA LDAP proxy runs."; - }; - - settings = mkOption { - type = with types; attrsOf (attrsOf (oneOf [ str bool int (listOf str) ])); - default = {}; - description = lib.mdDoc '' - Attribute-set containing the settings for `privacyidea-ldap-proxy`. - It's possible to pass secrets using env-vars as substitutes and - use the option [](#opt-services.privacyidea.ldap-proxy.environmentFile) - to inject them via `envsubst`. - ''; - }; - - environmentFile = mkOption { - default = null; - type = types.nullOr types.str; - description = lib.mdDoc '' - Environment file containing secrets to be substituted into - [](#opt-services.privacyidea.ldap-proxy.settings). - ''; - }; - }; - }; - }; - - config = mkMerge [ - - (mkIf cfg.enable { - - assertions = [ - { - assertion = cfg.tokenjanitor.enable -> (cfg.tokenjanitor.orphaned || cfg.tokenjanitor.unassigned); - message = '' - privacyidea-token-janitor has no effect if neither orphaned nor unassigned tokens - are to be searched. - ''; - } - ]; - - environment.systemPackages = [ pkgs.privacyidea (hiPrio privacyidea-token-janitor) ]; - - services.postgresql.enable = mkDefault true; - - systemd.services.privacyidea-tokenjanitor = mkIf cfg.tokenjanitor.enable { - environment.PRIVACYIDEA_CONFIGFILE = "${cfg.stateDir}/privacyidea.cfg"; - path = [ penv ]; - serviceConfig = { - CapabilityBoundingSet = [ "" ]; - ExecStart = "${pkgs.writeShellScript "pi-token-janitor" '' - ${optionalString cfg.tokenjanitor.orphaned '' - echo >&2 "Removing orphaned tokens..." - privacyidea-token-janitor find \ - --orphaned true \ - --action ${cfg.tokenjanitor.action} - ''} - ${optionalString cfg.tokenjanitor.unassigned '' - echo >&2 "Removing unassigned tokens..." - privacyidea-token-janitor find \ - --assigned false \ - --action ${cfg.tokenjanitor.action} - ''} - ''}"; - Group = cfg.group; - LockPersonality = true; - MemoryDenyWriteExecute = true; - ProtectHome = true; - ProtectHostname = true; - ProtectKernelLogs = true; - ProtectKernelModules = true; - ProtectKernelTunables = true; - ProtectSystem = "strict"; - ReadWritePaths = cfg.stateDir; - Type = "oneshot"; - User = cfg.user; - WorkingDirectory = cfg.stateDir; - }; - }; - systemd.timers.privacyidea-tokenjanitor = mkIf cfg.tokenjanitor.enable { - wantedBy = [ "timers.target" ]; - timerConfig.OnCalendar = cfg.tokenjanitor.interval; - timerConfig.Persistent = true; - }; - - systemd.services.privacyidea = let - piuwsgi = pkgs.writeText "uwsgi.json" (builtins.toJSON { - uwsgi = { - buffer-size = 8192; - 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 = "${cfg.stateDir}/privacyidea.cfg"; - preStart = let - pi-manage = "${config.security.sudo.package}/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 - umask 077 - ${lib.getBin pkgs.envsubst}/bin/envsubst -o ${cfg.stateDir}/privacyidea.cfg \ - -i "${piCfgFile}" - chown ${cfg.user}:${cfg.group} ${cfg.stateDir}/privacyidea.cfg - if ! test -e "${cfg.stateDir}/db-created"; then - ${config.security.sudo.package}/bin/sudo -u ${pgsu} ${psql}/bin/createuser --no-superuser --no-createdb --no-createrole ${cfg.user} - ${config.security.sudo.package}/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"; - EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile; - ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID"; - NotifyAccess = "main"; - KillSignal = "SIGQUIT"; - }; - }; - - users.users.privacyidea = mkIf (cfg.user == "privacyidea") { - group = cfg.group; - isSystemUser = true; - }; - - users.groups.privacyidea = mkIf (cfg.group == "privacyidea") {}; - }) - - (mkIf cfg.ldap-proxy.enable { - - assertions = [ - { assertion = let - xor = a: b: a && !b || !a && b; - in xor (cfg.ldap-proxy.settings == {}) (cfg.ldap-proxy.configFile == null); - message = "configFile & settings are mutually exclusive for services.privacyidea.ldap-proxy!"; - } - ]; - - warnings = mkIf (cfg.ldap-proxy.configFile != null) [ - "Using services.privacyidea.ldap-proxy.configFile is deprecated! Use the RFC42-style settings option instead!" - ]; - - systemd.services.privacyidea-ldap-proxy = let - ldap-proxy-env = pkgs.python3.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; - StateDirectory = "privacyidea-ldap-proxy"; - EnvironmentFile = mkIf (cfg.ldap-proxy.environmentFile != null) - [ cfg.ldap-proxy.environmentFile ]; - ExecStartPre = - "${pkgs.writeShellScript "substitute-secrets-ldap-proxy" '' - umask 0077 - ${pkgs.envsubst}/bin/envsubst \ - -i ${ldapProxyConfig} \ - -o $STATE_DIRECTORY/ldap-proxy.ini - ''}"; - ExecStart = let - configPath = if cfg.ldap-proxy.settings != {} - then "%S/privacyidea-ldap-proxy/ldap-proxy.ini" - else cfg.ldap-proxy.configFile; - in '' - ${ldap-proxy-env}/bin/twistd \ - --nodaemon \ - --pidfile= \ - -u ${cfg.ldap-proxy.user} \ - -g ${cfg.ldap-proxy.group} \ - ldap-proxy \ - -c ${configPath} - ''; - Restart = "always"; - }; - }; - - users.users.pi-ldap-proxy = mkIf (cfg.ldap-proxy.user == "pi-ldap-proxy") { - group = cfg.ldap-proxy.group; - isSystemUser = true; - }; - - users.groups.pi-ldap-proxy = mkIf (cfg.ldap-proxy.group == "pi-ldap-proxy") {}; - }) - ]; - -} diff --git a/nixos/modules/virtualisation/oci-containers.nix b/nixos/modules/virtualisation/oci-containers.nix index 71f5d7a752c8c..65e97d53724f2 100644 --- a/nixos/modules/virtualisation/oci-containers.nix +++ b/nixos/modules/virtualisation/oci-containers.nix @@ -239,6 +239,26 @@ let mkService = name: container: let dependsOn = map (x: "${cfg.backend}-${x}.service") container.dependsOn; escapedName = escapeShellArg name; + preStartScript = pkgs.writeShellApplication { + name = "pre-start"; + runtimeInputs = [ ]; + text = '' + ${cfg.backend} rm -f ${name} || true + ${optionalString (isValidLogin container.login) '' + cat ${container.login.passwordFile} | \ + ${cfg.backend} login \ + ${container.login.registry} \ + --username ${container.login.username} \ + --password-stdin + ''} + ${optionalString (container.imageFile != null) '' + ${cfg.backend} load -i ${container.imageFile} + ''} + ${optionalString (cfg.backend == "podman") '' + rm -f /run/podman-${escapedName}.ctr-id + ''} + ''; + }; in { wantedBy = [] ++ optional (container.autoStart) "multi-user.target"; after = lib.optionals (cfg.backend == "docker") [ "docker.service" "docker.socket" ] @@ -253,23 +273,6 @@ let else if cfg.backend == "podman" then [ config.virtualisation.podman.package ] else throw "Unhandled backend: ${cfg.backend}"; - preStart = '' - ${cfg.backend} rm -f ${name} || true - ${optionalString (isValidLogin container.login) '' - cat ${container.login.passwordFile} | \ - ${cfg.backend} login \ - ${container.login.registry} \ - --username ${container.login.username} \ - --password-stdin - ''} - ${optionalString (container.imageFile != null) '' - ${cfg.backend} load -i ${container.imageFile} - ''} - ${optionalString (cfg.backend == "podman") '' - rm -f /run/podman-${escapedName}.ctr-id - ''} - ''; - script = concatStringsSep " \\\n " ([ "exec ${cfg.backend} run" "--rm" @@ -318,7 +321,7 @@ let ### # ExecReload = ...; ### - + ExecStartPre = [ "${preStartScript}/bin/pre-start" ]; TimeoutStartSec = 0; TimeoutStopSec = 120; Restart = "always"; |