diff options
Diffstat (limited to 'nixos/modules')
-rw-r--r-- | nixos/modules/module-list.nix | 1 | ||||
-rw-r--r-- | nixos/modules/programs/fish.nix | 3 | ||||
-rw-r--r-- | nixos/modules/services/continuous-integration/gitlab-runner.nix | 83 | ||||
-rw-r--r-- | nixos/modules/services/databases/openldap.nix | 30 | ||||
-rw-r--r-- | nixos/modules/services/hardware/undervolt.nix | 7 | ||||
-rw-r--r-- | nixos/modules/services/networking/blockbook-frontend.nix | 272 | ||||
-rw-r--r-- | nixos/modules/services/networking/corerad.nix | 2 | ||||
-rw-r--r-- | nixos/modules/services/networking/nsd.nix | 7 | ||||
-rw-r--r-- | nixos/modules/services/networking/radicale.nix | 11 | ||||
-rw-r--r-- | nixos/modules/services/web-servers/apache-httpd/default.nix | 1 | ||||
-rw-r--r-- | nixos/modules/services/web-servers/nginx/default.nix | 4 | ||||
-rw-r--r-- | nixos/modules/services/web-servers/traefik.nix | 4 | ||||
-rw-r--r-- | nixos/modules/system/boot/loader/grub/grub.nix | 62 | ||||
-rw-r--r-- | nixos/modules/system/boot/loader/grub/install-grub.pl | 45 | ||||
-rw-r--r-- | nixos/modules/virtualisation/containers.nix | 25 | ||||
-rw-r--r-- | nixos/modules/virtualisation/podman.nix | 28 |
16 files changed, 532 insertions, 53 deletions
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index fd6294f2d7c..cf25ae3157e 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -589,6 +589,7 @@ ./services/networking/autossh.nix ./services/networking/bird.nix ./services/networking/bitlbee.nix + ./services/networking/blockbook-frontend.nix ./services/networking/charybdis.nix ./services/networking/cjdns.nix ./services/networking/cntlm.nix diff --git a/nixos/modules/programs/fish.nix b/nixos/modules/programs/fish.nix index 48b324a0fe8..39b92edf2ac 100644 --- a/nixos/modules/programs/fish.nix +++ b/nixos/modules/programs/fish.nix @@ -102,6 +102,9 @@ in programs.fish.shellAliases = mapAttrs (name: mkDefault) cfge.shellAliases; + # Required for man completions + documentation.man.generateCaches = true; + environment.etc."fish/foreign-env/shellInit".text = cfge.shellInit; environment.etc."fish/foreign-env/loginShellInit".text = cfge.loginShellInit; environment.etc."fish/foreign-env/interactiveShellInit".text = cfge.interactiveShellInit; diff --git a/nixos/modules/services/continuous-integration/gitlab-runner.nix b/nixos/modules/services/continuous-integration/gitlab-runner.nix index eacfed85ddf..4cff19839a2 100644 --- a/nixos/modules/services/continuous-integration/gitlab-runner.nix +++ b/nixos/modules/services/continuous-integration/gitlab-runner.nix @@ -1,14 +1,16 @@ { config, lib, pkgs, ... }: +with builtins; with lib; let cfg = config.services.gitlab-runner; hasDocker = config.virtualisation.docker.enable; - hashedServices = with builtins; (mapAttrs' (name: service: nameValuePair - "${name}_${config.networking.hostName}_${ + hashedServices = mapAttrs' + (name: service: nameValuePair + "${name}_${config.networking.hostName}_${ substring 0 12 (hashString "md5" (unsafeDiscardStringContext (toJSON service)))}" service) - cfg.services); + cfg.services; configPath = "$HOME/.gitlab-runner/config.toml"; configureScript = pkgs.writeShellScriptBin "gitlab-runner-configure" ( if (cfg.configFile != null) then '' @@ -76,7 +78,7 @@ let ++ map (v: "--docker-allowed-images ${escapeShellArg v}") service.dockerAllowedImages ++ map (v: "--docker-allowed-services ${escapeShellArg v}") service.dockerAllowedServices ) - ))} && sleep 1 + ))} && sleep 1 || exit 1 fi '') hashedServices)} @@ -89,8 +91,17 @@ let # update global options remarshal --if toml --of json ${configPath} \ - | jq -cM '.check_interval = ${toString cfg.checkInterval} | - .concurrent = ${toString cfg.concurrent}' \ + | jq -cM ${escapeShellArg (concatStringsSep " | " [ + ".check_interval = ${toJSON cfg.checkInterval}" + ".concurrent = ${toJSON cfg.concurrent}" + ".sentry_dsn = ${toJSON cfg.sentryDSN}" + ".listen_address = ${toJSON cfg.prometheusListenAddress}" + ".session_server.listen_address = ${toJSON cfg.sessionServer.listenAddress}" + ".session_server.advertise_address = ${toJSON cfg.sessionServer.advertiseAddress}" + ".session_server.session_timeout = ${toJSON cfg.sessionServer.sessionTimeout}" + "del(.[] | nulls)" + "del(.session_server[] | nulls)" + ])} \ | remarshal --if json --of toml \ | sponge ${configPath} @@ -141,6 +152,66 @@ in 0 does not mean unlimited. ''; }; + sentryDSN = mkOption { + type = types.nullOr types.str; + default = null; + example = "https://public:private@host:port/1"; + description = '' + Data Source Name for tracking of all system level errors to Sentry. + ''; + }; + prometheusListenAddress = mkOption { + type = types.nullOr types.str; + default = null; + example = "localhost:8080"; + description = '' + Address (<host>:<port>) on which the Prometheus metrics HTTP server + should be listening. + ''; + }; + sessionServer = mkOption { + type = types.submodule { + options = { + listenAddress = mkOption { + type = types.nullOr types.str; + default = null; + example = "0.0.0.0:8093"; + description = '' + An internal URL to be used for the session server. + ''; + }; + advertiseAddress = mkOption { + type = types.nullOr types.str; + default = null; + example = "runner-host-name.tld:8093"; + description = '' + The URL that the Runner will expose to GitLab to be used + to access the session server. + Fallbacks to <option>listenAddress</option> if not defined. + ''; + }; + sessionTimeout = mkOption { + type = types.int; + default = 1800; + description = '' + How long in seconds the session can stay active after + the job completes (which will block the job from finishing). + ''; + }; + }; + }; + default = { }; + example = literalExample '' + { + listenAddress = "0.0.0.0:8093"; + } + ''; + description = '' + The session server allows the user to interact with jobs + that the Runner is responsible for. A good example of this is the + <link xlink:href="https://docs.gitlab.com/ee/ci/interactive_web_terminal/index.html">interactive web terminal</link>. + ''; + }; gracefulTermination = mkOption { type = types.bool; default = false; diff --git a/nixos/modules/services/databases/openldap.nix b/nixos/modules/services/databases/openldap.nix index 9b4d9a98b74..7472538b887 100644 --- a/nixos/modules/services/databases/openldap.nix +++ b/nixos/modules/services/databases/openldap.nix @@ -5,14 +5,14 @@ with lib; let cfg = config.services.openldap; - openldap = pkgs.openldap; + openldap = cfg.package; dataFile = pkgs.writeText "ldap-contents.ldif" cfg.declarativeContents; configFile = pkgs.writeText "slapd.conf" ((optionalString cfg.defaultSchemas '' - include ${pkgs.openldap.out}/etc/schema/core.schema - include ${pkgs.openldap.out}/etc/schema/cosine.schema - include ${pkgs.openldap.out}/etc/schema/inetorgperson.schema - include ${pkgs.openldap.out}/etc/schema/nis.schema + include ${openldap.out}/etc/schema/core.schema + include ${openldap.out}/etc/schema/cosine.schema + include ${openldap.out}/etc/schema/inetorgperson.schema + include ${openldap.out}/etc/schema/nis.schema '') + '' ${cfg.extraConfig} database ${cfg.database} @@ -46,6 +46,18 @@ in "; }; + package = mkOption { + type = types.package; + default = pkgs.openldap; + description = '' + OpenLDAP package to use. + + This can be used to, for example, set an OpenLDAP package + with custom overrides to enable modules or other + functionality. + ''; + }; + user = mkOption { type = types.str; default = "openldap"; @@ -152,10 +164,10 @@ in "; example = literalExample '' ''' - include ${pkgs.openldap.out}/etc/schema/core.schema - include ${pkgs.openldap.out}/etc/schema/cosine.schema - include ${pkgs.openldap.out}/etc/schema/inetorgperson.schema - include ${pkgs.openldap.out}/etc/schema/nis.schema + include ${openldap.out}/etc/schema/core.schema + include ${openldap.out}/etc/schema/cosine.schema + include ${openldap.out}/etc/schema/inetorgperson.schema + include ${openldap.out}/etc/schema/nis.schema database bdb suffix dc=example,dc=org diff --git a/nixos/modules/services/hardware/undervolt.nix b/nixos/modules/services/hardware/undervolt.nix index da627af73bc..828032dc573 100644 --- a/nixos/modules/services/hardware/undervolt.nix +++ b/nixos/modules/services/hardware/undervolt.nix @@ -25,8 +25,11 @@ let in { options.services.undervolt = { - enable = mkEnableOption - "Intel CPU undervolting service (WARNING: may permanently damage your hardware!)"; + enable = mkEnableOption '' + Undervolting service for Intel CPUs. + + Warning: This service is not endorsed by Intel and may permanently damage your hardware. Use at your own risk! + ''; verbose = mkOption { type = types.bool; diff --git a/nixos/modules/services/networking/blockbook-frontend.nix b/nixos/modules/services/networking/blockbook-frontend.nix new file mode 100644 index 00000000000..61938e51e06 --- /dev/null +++ b/nixos/modules/services/networking/blockbook-frontend.nix @@ -0,0 +1,272 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + eachBlockbook = config.services.blockbook-frontend; + + blockbookOpts = { config, lib, name, ...}: { + + options = { + + enable = mkEnableOption "blockbook-frontend application."; + + package = mkOption { + type = types.package; + default = pkgs.blockbook; + description = "Which blockbook package to use."; + }; + + user = mkOption { + type = types.str; + default = "blockbook-frontend-${name}"; + description = "The user as which to run blockbook-frontend-${name}."; + }; + + group = mkOption { + type = types.str; + default = "${config.user}"; + description = "The group as which to run blockbook-frontend-${name}."; + }; + + certFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/etc/secrets/blockbook-frontend-${name}/certFile"; + description = '' + To enable SSL, specify path to the name of certificate files without extension. + Expecting <filename>certFile.crt</filename> and <filename>certFile.key</filename>. + ''; + }; + + configFile = mkOption { + type = with types; nullOr path; + default = null; + example = "${config.dataDir}/config.json"; + description = "Location of the blockbook configuration file."; + }; + + coinName = mkOption { + type = types.str; + default = "Bitcoin"; + example = "Bitcoin"; + description = '' + See <link xlink:href="https://github.com/trezor/blockbook/blob/master/bchain/coins/blockchain.go#L61"/> + for current of coins supported in master (Note: may differ from release). + ''; + }; + + cssDir = mkOption { + type = types.path; + default = "${config.package}/share/css/"; + example = "${config.dataDir}/static/css/"; + description = '' + Location of the dir with <filename>main.css</filename> CSS file. + By default, the one shipped with the package is used. + ''; + }; + + dataDir = mkOption { + type = types.path; + default = "/var/lib/blockbook-frontend-${name}"; + description = "Location of blockbook-frontend-${name} data directory."; + }; + + debug = mkOption { + type = types.bool; + default = false; + description = "Debug mode, return more verbose errors, reload templates on each request."; + }; + + internal = mkOption { + type = types.nullOr types.str; + default = ":9030"; + example = ":9030"; + description = "Internal http server binding <literal>[address]:port</literal>."; + }; + + messageQueueBinding = mkOption { + type = types.str; + default = "tcp://127.0.0.1:38330"; + example = "tcp://127.0.0.1:38330"; + description = "Message Queue Binding <literal>address:port</literal>."; + }; + + public = mkOption { + type = types.nullOr types.str; + default = ":9130"; + example = ":9130"; + description = "Public http server binding <literal>[address]:port</literal>."; + }; + + rpc = { + url = mkOption { + type = types.str; + default = "http://127.0.0.1"; + description = "URL for JSON-RPC connections."; + }; + + port = mkOption { + type = types.port; + default = 8030; + description = "Port for JSON-RPC connections."; + }; + + user = mkOption { + type = types.str; + default = "rpc"; + example = "rpc"; + description = "Username for JSON-RPC connections."; + }; + + password = mkOption { + type = types.str; + default = "rpc"; + example = "rpc"; + description = '' + RPC password for JSON-RPC connections. + Warning: this is stored in cleartext in the Nix store!!! + Use <literal>configFile</literal> or <literal>passwordFile</literal> if needed. + ''; + }; + + passwordFile = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + File containing password of the RPC user. + Note: This options is ignored when <literal>configFile</literal> is used. + ''; + }; + }; + + sync = mkOption { + type = types.bool; + default = true; + description = "Synchronizes until tip, if together with zeromq, keeps index synchronized."; + }; + + templateDir = mkOption { + type = types.path; + default = "${config.package}/share/templates/"; + example = "${config.dataDir}/templates/static/"; + description = "Location of the HTML templates. By default, ones shipped with the package are used."; + }; + + extraConfig = mkOption { + type = types.attrs; + default = {}; + example = literalExample '' { + alternative_estimate_fee = "whatthefee-disabled"; + alternative_estimate_fee_params = "{\"url\": \"https://whatthefee.io/data.json\", \"periodSeconds\": 60}"; + fiat_rates = "coingecko"; + fiat_rates_params = "{\"url\": \"https://api.coingecko.com/api/v3\", \"coin\": \"bitcoin\", \"periodSeconds\": 60}"; + coin_shortcut = "BTC"; + coin_label = "Bitcoin"; + xpub_magic = 76067358; + xpub_magic_segwit_p2sh = 77429938; + xpub_magic_segwit_native = 78792518; + }''; + description = '' + Additional configurations to be appended to <filename>coin.conf</filename>. + Overrides any already defined configuration options. + See <link xlink:href="https://github.com/trezor/blockbook/tree/master/configs/coins"/> + for current configuration options supported in master (Note: may differ from release). + ''; + }; + + extraCmdLineOptions = mkOption { + type = types.listOf types.str; + default = []; + example = [ "-workers=1" "-dbcache=0" "-logtosderr" ]; + description = '' + Extra command line options to pass to Blockbook. + Run blockbook --help to list all available options. + ''; + }; + }; + }; +in +{ + # interface + + options = { + services.blockbook-frontend = mkOption { + type = types.attrsOf (types.submodule blockbookOpts); + default = {}; + description = "Specification of one or more blockbook-frontend instances."; + }; + }; + + # implementation + + config = mkIf (eachBlockbook != {}) { + + systemd.services = mapAttrs' (blockbookName: cfg: ( + nameValuePair "blockbook-frontend-${blockbookName}" ( + let + configFile = if cfg.configFile != null then cfg.configFile else + pkgs.writeText "config.conf" (builtins.toJSON ( { + coin_name = "${cfg.coinName}"; + rpc_user = "${cfg.rpc.user}"; + rpc_pass = "${cfg.rpc.password}"; + rpc_url = "${cfg.rpc.url}:${toString cfg.rpc.port}"; + message_queue_binding = "${cfg.messageQueueBinding}"; + } // cfg.extraConfig) + ); + in { + description = "blockbook-frontend-${blockbookName} daemon"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + preStart = '' + ln -sf ${cfg.templateDir} ${cfg.dataDir}/static/ + ln -sf ${cfg.cssDir} ${cfg.dataDir}/static/ + ${optionalString (cfg.rpc.passwordFile != null && cfg.configFile == null) '' + CONFIGTMP=$(mktemp) + ${pkgs.jq}/bin/jq ".rpc_pass = \"$(cat ${cfg.rpc.passwordFile})\"" ${configFile} > $CONFIGTMP + mv $CONFIGTMP ${cfg.dataDir}/${blockbookName}-config.json + ''} + ''; + serviceConfig = { + User = cfg.user; + Group = cfg.group; + ExecStart = '' + ${cfg.package}/bin/blockbook \ + ${if (cfg.rpc.passwordFile != null && cfg.configFile == null) then + "-blockchaincfg=${cfg.dataDir}/${blockbookName}-config.json" + else + "-blockchaincfg=${configFile}" + } \ + -datadir=${cfg.dataDir} \ + ${optionalString (cfg.sync != false) "-sync"} \ + ${optionalString (cfg.certFile != null) "-certfile=${toString cfg.certFile}"} \ + ${optionalString (cfg.debug != false) "-debug"} \ + ${optionalString (cfg.internal != null) "-internal=${toString cfg.internal}"} \ + ${optionalString (cfg.public != null) "-public=${toString cfg.public}"} \ + ${toString cfg.extraCmdLineOptions} + ''; + Restart = "on-failure"; + WorkingDirectory = cfg.dataDir; + LimitNOFILE = 65536; + }; + } + ) )) eachBlockbook; + + systemd.tmpfiles.rules = flatten (mapAttrsToList (blockbookName: cfg: [ + "d ${cfg.dataDir} 0750 ${cfg.user} ${cfg.group} - -" + "d ${cfg.dataDir}/static 0750 ${cfg.user} ${cfg.group} - -" + ]) eachBlockbook); + + users.users = mapAttrs' (blockbookName: cfg: ( + nameValuePair "blockbook-frontend-${blockbookName}" { + name = cfg.user; + group = cfg.group; + home = cfg.dataDir; + isSystemUser = true; + })) eachBlockbook; + + users.groups = mapAttrs' (instanceName: cfg: ( + nameValuePair "${cfg.group}" { })) eachBlockbook; + }; +} diff --git a/nixos/modules/services/networking/corerad.nix b/nixos/modules/services/networking/corerad.nix index 5d73c0a0d77..1c414c53a98 100644 --- a/nixos/modules/services/networking/corerad.nix +++ b/nixos/modules/services/networking/corerad.nix @@ -77,6 +77,8 @@ in { AmbientCapabilities = "CAP_NET_ADMIN CAP_NET_RAW"; NoNewPrivileges = true; DynamicUser = true; + Type = "notify"; + NotifyAccess = "main"; ExecStart = "${getBin cfg.package}/bin/corerad -c=${cfg.configFile}"; Restart = "on-failure"; }; diff --git a/nixos/modules/services/networking/nsd.nix b/nixos/modules/services/networking/nsd.nix index 6e3eed0c557..3ecbd06ee41 100644 --- a/nixos/modules/services/networking/nsd.nix +++ b/nixos/modules/services/networking/nsd.nix @@ -11,8 +11,6 @@ let # build nsd with the options needed for the given config nsdPkg = pkgs.nsd.override { - configFile = "${configFile}/nsd.conf"; - bind8Stats = cfg.bind8Stats; ipv6 = cfg.ipv6; ratelimit = cfg.ratelimit.enable; @@ -897,7 +895,10 @@ in + "want, please enable 'services.nsd.rootServer'."; }; - environment.systemPackages = [ nsdPkg ]; + environment = { + systemPackages = [ nsdPkg ]; + etc."nsd/nsd.conf".source = "${configFile}/nsd.conf"; + }; users.groups.${username}.gid = config.ids.gids.nsd; diff --git a/nixos/modules/services/networking/radicale.nix b/nixos/modules/services/networking/radicale.nix index 30bf22586f8..5af035fd59e 100644 --- a/nixos/modules/services/networking/radicale.nix +++ b/nixos/modules/services/networking/radicale.nix @@ -8,8 +8,10 @@ let confFile = pkgs.writeText "radicale.conf" cfg.config; - # This enables us to default to version 2 while still not breaking configurations of people with version 1 - defaultPackage = if versionAtLeast config.system.stateVersion "17.09" then { + defaultPackage = if versionAtLeast config.system.stateVersion "20.09" then { + pkg = pkgs.radicale3; + text = "pkgs.radicale3"; + } else if versionAtLeast config.system.stateVersion "17.09" then { pkg = pkgs.radicale2; text = "pkgs.radicale2"; } else { @@ -35,8 +37,9 @@ in defaultText = defaultPackage.text; description = '' Radicale package to use. This defaults to version 1.x if - <literal>system.stateVersion < 17.09</literal> and version 2.x - otherwise. + <literal>system.stateVersion < 17.09</literal>, version 2.x if + <literal>17.09 ≤ system.stateVersion < 20.09</literal>, and + version 3.x otherwise. ''; }; diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix index 8abee7130d7..e1d1217943b 100644 --- a/nixos/modules/services/web-servers/apache-httpd/default.nix +++ b/nixos/modules/services/web-servers/apache-httpd/default.nix @@ -708,6 +708,7 @@ in wantedBy = [ "multi-user.target" ]; wants = concatLists (map (hostOpts: [ "acme-${hostOpts.hostName}.service" "acme-selfsigned-${hostOpts.hostName}.service" ]) vhostsACME); after = [ "network.target" "fs.target" ] ++ map (hostOpts: "acme-selfsigned-${hostOpts.hostName}.service") vhostsACME; + before = map (hostOpts: "acme-${hostOpts.hostName}.service") vhostsACME; path = [ pkg pkgs.coreutils pkgs.gnugrep ]; diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index 8a015bb3556..4c4b7f39e6b 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -693,6 +693,10 @@ in wantedBy = [ "multi-user.target" ]; wants = concatLists (map (vhostConfig: ["acme-${vhostConfig.serverName}.service" "acme-selfsigned-${vhostConfig.serverName}.service"]) acmeEnabledVhosts); after = [ "network.target" ] ++ map (vhostConfig: "acme-selfsigned-${vhostConfig.serverName}.service") acmeEnabledVhosts; + # Nginx needs to be started in order to be able to request certificates + # (it's hosting the acme challenge after all) + # This fixes https://github.com/NixOS/nixpkgs/issues/81842 + before = map (vhostConfig: "acme-${vhostConfig.serverName}.service") acmeEnabledVhosts; stopIfChanged = false; preStart = '' ${cfg.preStart} diff --git a/nixos/modules/services/web-servers/traefik.nix b/nixos/modules/services/web-servers/traefik.nix index 0631a26569c..4ab7307c3b6 100644 --- a/nixos/modules/services/web-servers/traefik.nix +++ b/nixos/modules/services/web-servers/traefik.nix @@ -20,10 +20,10 @@ let in valueType; dynamicConfigFile = if cfg.dynamicConfigFile == null then pkgs.runCommand "config.toml" { - buildInputs = [ pkgs.yj ]; + buildInputs = [ pkgs.remarshal ]; preferLocalBuild = true; } '' - yj -jt -i \ + remarshal -if json -of toml \ < ${ pkgs.writeText "dynamic_config.json" (builtins.toJSON cfg.dynamicConfigOptions) diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix index 3975372e15e..b760c3f96dd 100644 --- a/nixos/modules/system/boot/loader/grub/grub.nix +++ b/nixos/modules/system/boot/loader/grub/grub.nix @@ -55,6 +55,7 @@ let storePath = config.boot.loader.grub.storePath; bootloaderId = if args.efiBootloaderId == null then "NixOS${efiSysMountPoint'}" else args.efiBootloaderId; timeout = if config.boot.loader.timeout == null then -1 else config.boot.loader.timeout; + users = if cfg.users == {} || cfg.version != 1 then cfg.users else throw "GRUB version 1 does not support user accounts."; inherit efiSysMountPoint; inherit (args) devices; inherit (efi) canTouchEfiVariables; @@ -137,6 +138,67 @@ in ''; }; + users = mkOption { + default = {}; + example = { + root = { hashedPasswordFile = "/path/to/file"; }; + }; + description = '' + User accounts for GRUB. When specified, the GRUB command line and + all boot options except the default are password-protected. + All passwords and hashes provided will be stored in /boot/grub/grub.cfg, + and will be visible to any local user who can read this file. Additionally, + any passwords and hashes provided directly in a Nix configuration + (as opposed to external files) will be copied into the Nix store, and + will be visible to all local users. + ''; + type = with types; attrsOf (submodule { + options = { + hashedPasswordFile = mkOption { + example = "/path/to/file"; + default = null; + type = with types; uniq (nullOr str); + description = '' + Specifies the path to a file containing the password hash + for the account, generated with grub-mkpasswd-pbkdf2. + This hash will be stored in /boot/grub/grub.cfg, and will + be visible to any local user who can read this file. + ''; + }; + hashedPassword = mkOption { + example = "grub.pbkdf2.sha512.10000.674DFFDEF76E13EA...2CC972B102CF4355"; + default = null; + type = with types; uniq (nullOr str); + description = '' + Specifies the password hash for the account, + generated with grub-mkpasswd-pbkdf2. + This hash will be copied to the Nix store, and will be visible to all local users. + ''; + }; + passwordFile = mkOption { + example = "/path/to/file"; + default = null; + type = with types; uniq (nullOr str); + description = '' + Specifies the path to a file containing the + clear text password for the account. + This password will be stored in /boot/grub/grub.cfg, and will + be visible to any local user who can read this file. + ''; + }; + password = mkOption { + example = "Pa$$w0rd!"; + default = null; + type = with types; uniq (nullOr str); + description = '' + Specifies the clear text password for the account. + This password will be copied to the Nix store, and will be visible to all local users. + ''; + }; + }; + }); + }; + mirroredBoots = mkOption { default = [ ]; example = [ diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl index e469b18abd0..918a66866e9 100644 --- a/nixos/modules/system/boot/loader/grub/install-grub.pl +++ b/nixos/modules/system/boot/loader/grub/install-grub.pl @@ -247,6 +247,45 @@ if ($grubVersion == 1) { } else { + my @users = (); + foreach my $user ($dom->findnodes('/expr/attrs/attr[@name = "users"]/attrs/attr')) { + my $name = $user->findvalue('@name') or die; + my $hashedPassword = $user->findvalue('./attrs/attr[@name = "hashedPassword"]/string/@value'); + my $hashedPasswordFile = $user->findvalue('./attrs/attr[@name = "hashedPasswordFile"]/string/@value'); + my $password = $user->findvalue('./attrs/attr[@name = "password"]/string/@value'); + my $passwordFile = $user->findvalue('./attrs/attr[@name = "passwordFile"]/string/@value'); + + if ($hashedPasswordFile) { + open(my $f, '<', $hashedPasswordFile) or die "Can't read file '$hashedPasswordFile'!"; + $hashedPassword = <$f>; + chomp $hashedPassword; + } + if ($passwordFile) { + open(my $f, '<', $passwordFile) or die "Can't read file '$passwordFile'!"; + $password = <$f>; + chomp $password; + } + + if ($hashedPassword) { + if (index($hashedPassword, "grub.pbkdf2.") == 0) { + $conf .= "\npassword_pbkdf2 $name $hashedPassword"; + } + else { + die "Password hash for GRUB user '$name' is not valid!"; + } + } + elsif ($password) { + $conf .= "\npassword $name $password"; + } + else { + die "GRUB user '$name' has no password!"; + } + push(@users, $name); + } + if (@users) { + $conf .= "\nset superusers=\"" . join(' ',@users) . "\"\n"; + } + if ($copyKernels == 0) { $conf .= " " . $grubStore->search; @@ -350,7 +389,7 @@ sub copyToKernelsDir { } sub addEntry { - my ($name, $path) = @_; + my ($name, $path, $options) = @_; return unless -e "$path/kernel" && -e "$path/initrd"; my $kernel = copyToKernelsDir(Cwd::abs_path("$path/kernel")); @@ -396,7 +435,7 @@ sub addEntry { $conf .= " " . ($xen ? "module" : "kernel") . " $kernel $kernelParams\n"; $conf .= " " . ($xen ? "module" : "initrd") . " $initrd\n\n"; } else { - $conf .= "menuentry \"$name\" {\n"; + $conf .= "menuentry \"$name\" " . ($options||"") . " {\n"; $conf .= $grubBoot->search . "\n"; if ($copyKernels == 0) { $conf .= $grubStore->search . "\n"; @@ -413,7 +452,7 @@ sub addEntry { # Add default entries. $conf .= "$extraEntries\n" if $extraEntriesBeforeNixOS; -addEntry("NixOS - Default", $defaultConfig); +addEntry("NixOS - Default", $defaultConfig, "--unrestricted"); $conf .= "$extraEntries\n" unless $extraEntriesBeforeNixOS; diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix index 7d184575640..105f0f2710e 100644 --- a/nixos/modules/virtualisation/containers.nix +++ b/nixos/modules/virtualisation/containers.nix @@ -34,6 +34,25 @@ in ''; }; + containersConf = mkOption { + default = {}; + description = "containers.conf configuration"; + type = types.submodule { + options = { + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra configuration that should be put in the containers.conf + configuration file + ''; + + }; + }; + }; + }; + registries = { search = mkOption { type = types.listOf types.str; @@ -93,6 +112,12 @@ in config = lib.mkIf cfg.enable { + environment.etc."containers/containers.conf".text = '' + [network] + cni_plugin_dirs = ["${pkgs.cni-plugins}/bin/"] + + '' + cfg.containersConf.extraConfig; + environment.etc."containers/registries.conf".source = toTOML "registries.conf" { registries = lib.mapAttrs (n: v: { registries = v; }) cfg.registries; }; diff --git a/nixos/modules/virtualisation/podman.nix b/nixos/modules/virtualisation/podman.nix index 652850bf500..e0e2f04e24c 100644 --- a/nixos/modules/virtualisation/podman.nix +++ b/nixos/modules/virtualisation/podman.nix @@ -28,6 +28,10 @@ let in { + imports = [ + (lib.mkRenamedOptionModule [ "virtualisation" "podman" "libpod" ] [ "virtualisation" "containers" "containersConf" ]) + ]; + meta = { maintainers = lib.teams.podman.members; }; @@ -67,25 +71,6 @@ in ''; }; - libpod = mkOption { - default = {}; - description = "Libpod configuration"; - type = types.submodule { - options = { - - extraConfig = mkOption { - type = types.lines; - default = ""; - description = '' - Extra configuration that should be put in the libpod.conf - configuration file - ''; - - }; - }; - }; - }; - package = lib.mkOption { type = types.package; default = podmanPackage; @@ -103,11 +88,6 @@ in environment.systemPackages = [ cfg.package ] ++ lib.optional cfg.dockerCompat dockerCompat; - environment.etc."containers/libpod.conf".text = '' - cni_plugin_dir = ["${pkgs.cni-plugins}/bin/"] - - '' + cfg.libpod.extraConfig; - environment.etc."cni/net.d/87-podman-bridge.conflist".source = copyFile "${pkgs.podman-unwrapped.src}/cni/87-podman-bridge.conflist"; # Enable common /etc/containers configuration |