diff options
Diffstat (limited to 'nixos')
31 files changed, 306 insertions, 85 deletions
diff --git a/nixos/maintainers/scripts/ec2/create-amis.sh b/nixos/maintainers/scripts/ec2/create-amis.sh index 5dc1c5aaed57..145eb49ced7a 100755 --- a/nixos/maintainers/scripts/ec2/create-amis.sh +++ b/nixos/maintainers/scripts/ec2/create-amis.sh @@ -18,7 +18,7 @@ state_dir=$HOME/amis/ec2-images home_region=eu-west-1 bucket=nixos-amis -regions=(eu-west-1 eu-west-2 eu-west-3 eu-central-1 +regions=(eu-west-1 eu-west-2 eu-west-3 eu-central-1 eu-north-1 us-east-1 us-east-2 us-west-1 us-west-2 ca-central-1 ap-southeast-1 ap-southeast-2 ap-northeast-1 ap-northeast-2 diff --git a/nixos/modules/security/acme.nix b/nixos/modules/security/acme.nix index 4c7f0ee657ce..b787a7675390 100644 --- a/nixos/modules/security/acme.nix +++ b/nixos/modules/security/acme.nix @@ -302,7 +302,7 @@ in lpath = "acme/${cert}"; apath = "/var/lib/${lpath}"; spath = "/var/lib/acme/.lego"; - rights = if data.allowKeysForGroup then "750" else "700"; + fileMode = if data.allowKeysForGroup then "640" else "600"; globalOpts = [ "-d" data.domain "--email" data.email "--path" "." "--key-type" data.keyType ] ++ optionals (cfg.acceptTerms) [ "--accept-tos" ] ++ optionals (data.dnsProvider != null && !data.dnsPropagationCheck) [ "--dns.disable-cp" ] @@ -331,7 +331,7 @@ in Group = data.group; PrivateTmp = true; StateDirectory = "acme/.lego ${lpath}"; - StateDirectoryMode = rights; + StateDirectoryMode = if data.allowKeysForGroup then "750" else "700"; WorkingDirectory = spath; # Only try loading the credentialsFile if the dns challenge is enabled EnvironmentFile = if data.dnsProvider != null then data.credentialsFile else null; @@ -354,10 +354,11 @@ in cp -p ${spath}/certificates/${keyName}.issuer.crt chain.pem ln -sf fullchain.pem cert.pem cat key.pem fullchain.pem > full.pem - chmod ${rights} *.pem - chown '${data.user}:${data.group}' *.pem fi + chmod ${fileMode} *.pem + chown '${data.user}:${data.group}' *.pem + ${data.postRun} ''; in @@ -399,7 +400,7 @@ in # Give key acme permissions chown '${data.user}:${data.group}' "${apath}/"{key,fullchain,full}.pem - chmod ${rights} "${apath}/"{key,fullchain,full}.pem + chmod ${fileMode} "${apath}/"{key,fullchain,full}.pem ''; serviceConfig = { Type = "oneshot"; diff --git a/nixos/modules/services/databases/mysql.nix b/nixos/modules/services/databases/mysql.nix index 8d520b82fb55..248bf0ebc915 100644 --- a/nixos/modules/services/databases/mysql.nix +++ b/nixos/modules/services/databases/mysql.nix @@ -21,6 +21,11 @@ let installOptions = "${mysqldOptions} ${lib.optionalString isMysqlAtLeast57 "--insecure"}"; + settingsFile = pkgs.writeText "my.cnf" ( + generators.toINI { listsAsDuplicateKeys = true; } cfg.settings + + optionalString (cfg.extraOptions != null) "[mysqld]\n${cfg.extraOptions}" + ); + in { @@ -76,9 +81,64 @@ in description = "Location where MySQL stores its table files"; }; + configFile = mkOption { + type = types.path; + default = settingsFile; + defaultText = "settingsFile"; + description = '' + Override the configuration file used by MySQL. By default, + NixOS generates one automatically from <option>services.mysql.settings</option>. + ''; + example = literalExample '' + pkgs.writeText "my.cnf" ''' + [mysqld] + datadir = /var/lib/mysql + bind-address = 127.0.0.1 + port = 3336 + plugin-load-add = auth_socket.so + + !includedir /etc/mysql/conf.d/ + '''; + ''; + }; + + settings = mkOption { + type = with types; attrsOf (attrsOf (oneOf [ bool int str (listOf str) ])); + default = {}; + description = '' + MySQL configuration. Refer to + <link xlink:href="https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html"/>, + <link xlink:href="https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html"/>, + and <link xlink:href="https://mariadb.com/kb/en/server-system-variables/"/> + for details on supported values. + + <note> + <para> + MySQL configuration options such as <literal>--quick</literal> should be treated as + boolean options and provided values such as <literal>true</literal>, <literal>false</literal>, + <literal>1</literal>, or <literal>0</literal>. See the provided example below. + </para> + </note> + ''; + example = literalExample '' + { + mysqld = { + key_buffer_size = "6G"; + table_cache = 1600; + log-error = "/var/log/mysql_err.log"; + plugin-load-add = [ "server_audit" "ed25519=auth_ed25519" ]; + }; + mysqldump = { + quick = true; + max_allowed_packet = "16M"; + }; + } + ''; + }; + extraOptions = mkOption { - type = types.lines; - default = ""; + type = with types; nullOr lines; + default = null; example = '' key_buffer_size = 6G table_cache = 1600 @@ -252,10 +312,27 @@ in config = mkIf config.services.mysql.enable { + warnings = optional (cfg.extraOptions != null) "services.mysql.`extraOptions` is deprecated, please use services.mysql.`settings`."; + services.mysql.dataDir = mkDefault (if versionAtLeast config.system.stateVersion "17.09" then "/var/lib/mysql" else "/var/mysql"); + services.mysql.settings.mysqld = mkMerge [ + { + datadir = cfg.dataDir; + bind-address = mkIf (cfg.bind != null) cfg.bind; + port = cfg.port; + plugin-load-add = optional (cfg.ensureUsers != []) "auth_socket.so"; + } + (mkIf (cfg.replication.role == "master" || cfg.replication.role == "slave") { + log-bin = "mysql-bin-${toString cfg.replication.serverId}"; + log-bin-index = "mysql-bin-${toString cfg.replication.serverId}.index"; + relay-log = "mysql-relay-bin"; + server-id = cfg.replication.serverId; + }) + ]; + users.users.mysql = { description = "MySQL server user"; group = "mysql"; @@ -266,25 +343,7 @@ in environment.systemPackages = [mysql]; - environment.etc."my.cnf".text = - '' - [mysqld] - port = ${toString cfg.port} - datadir = ${cfg.dataDir} - ${optionalString (cfg.bind != null) "bind-address = ${cfg.bind}" } - ${optionalString (cfg.replication.role == "master" || cfg.replication.role == "slave") - '' - log-bin=mysql-bin-${toString cfg.replication.serverId} - log-bin-index=mysql-bin-${toString cfg.replication.serverId}.index - relay-log=mysql-relay-bin - server-id = ${toString cfg.replication.serverId} - ''} - ${optionalString (cfg.ensureUsers != []) - '' - plugin-load-add = auth_socket.so - ''} - ${cfg.extraOptions} - ''; + environment.etc."my.cnf".source = cfg.configFile; systemd.tmpfiles.rules = [ "d '${cfg.dataDir}' 0700 ${cfg.user} mysql -" @@ -297,7 +356,7 @@ in after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; - restartTriggers = [ config.environment.etc."my.cnf".source ]; + restartTriggers = [ cfg.configFile ]; unitConfig.RequiresMountsFor = "${cfg.dataDir}"; diff --git a/nixos/modules/services/misc/disnix.nix b/nixos/modules/services/misc/disnix.nix index c21cb2afc3ca..b7b6eb7cd66e 100644 --- a/nixos/modules/services/misc/disnix.nix +++ b/nixos/modules/services/misc/disnix.nix @@ -61,10 +61,7 @@ in ++ optional cfg.useWebServiceInterface "${pkgs.dbus_java}/share/java/dbus.jar"; services.tomcat.webapps = optional cfg.useWebServiceInterface pkgs.DisnixWebService; - users.groups = singleton - { name = "disnix"; - gid = config.ids.gids.disnix; - }; + users.groups.disnix.gid = config.ids.gids.disnix; systemd.services = { disnix = mkIf cfg.enableMultiUser { diff --git a/nixos/modules/services/misc/zoneminder.nix b/nixos/modules/services/misc/zoneminder.nix index d7f7324580c0..d5b3537068d3 100644 --- a/nixos/modules/services/misc/zoneminder.nix +++ b/nixos/modules/services/misc/zoneminder.nix @@ -77,6 +77,8 @@ in { `config.services.zoneminder.database.createLocally` to true. Otherwise, when set to `false` (the default), you will have to create the database and database user as well as populate the database yourself. + Additionally, you will need to run `zmupdate.pl` yourself when + upgrading to a newer version. ''; webserver = mkOption { @@ -330,6 +332,8 @@ in { ${config.services.mysql.package}/bin/mysql < ${pkg}/share/zoneminder/db/zm_create.sql touch "/var/lib/${dirName}/db-created" fi + + ${zoneminder}/bin/zmupdate.pl -nointeractive ''; serviceConfig = { User = user; diff --git a/nixos/modules/services/monitoring/prometheus/exporters.nix b/nixos/modules/services/monitoring/prometheus/exporters.nix index 36ebffa44636..f9ad1457fc85 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters.nix @@ -29,6 +29,7 @@ let "fritzbox" "json" "mail" + "mikrotik" "minio" "nextcloud" "nginx" @@ -197,13 +198,25 @@ in config = mkMerge ([{ assertions = [ { - assertion = (cfg.snmp.configurationPath == null) != (cfg.snmp.configuration == null); + assertion = cfg.snmp.enable -> ( + (cfg.snmp.configurationPath == null) != (cfg.snmp.configuration == null) + ); message = '' Please ensure you have either `services.prometheus.exporters.snmp.configuration' or `services.prometheus.exporters.snmp.configurationPath' set! ''; } { - assertion = (cfg.mail.configFile == null) != (cfg.mail.configuration == {}); + assertion = cfg.mikrotik.enable -> ( + (cfg.mikrotik.configFile == null) != (cfg.mikrotik.configuration == null) + ); + message = '' + Please specify either `services.prometheus.exporters.mikrotik.configuration' + or `services.prometheus.exporters.mikrotik.configFile'. + ''; + } { + assertion = cfg.mail.enable -> ( + (cfg.mail.configFile == null) != (cfg.mail.configuration == null) + ); message = '' Please specify either 'services.prometheus.exporters.mail.configuration' or 'services.prometheus.exporters.mail.configFile'. diff --git a/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix b/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix index 8a90afa99842..fe8d905da3fe 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/blackbox.nix @@ -61,7 +61,7 @@ in { ExecStart = '' ${pkgs.prometheus-blackbox-exporter}/bin/blackbox_exporter \ --web.listen-address ${cfg.listenAddress}:${toString cfg.port} \ - --config.file ${adjustedConfigFile} \ + --config.file ${escapeShellArg adjustedConfigFile} \ ${concatStringsSep " \\\n " cfg.extraFlags} ''; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix b/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix index 1cc346418091..972104630275 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/collectd.nix @@ -66,7 +66,7 @@ in serviceConfig = { ExecStart = '' ${pkgs.prometheus-collectd-exporter}/bin/collectd_exporter \ - -log.format ${cfg.logFormat} \ + -log.format ${escapeShellArg cfg.logFormat} \ -log.level ${cfg.logLevel} \ -web.listen-address ${cfg.listenAddress}:${toString cfg.port} \ ${collectSettingsArgs} \ diff --git a/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix b/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix index e9fa26cb1f5a..68afba21d64a 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/dnsmasq.nix @@ -30,7 +30,7 @@ in ${pkgs.prometheus-dnsmasq-exporter}/bin/dnsmasq_exporter \ --listen ${cfg.listenAddress}:${toString cfg.port} \ --dnsmasq ${cfg.dnsmasqListenAddress} \ - --leases_path ${cfg.leasesPath} \ + --leases_path ${escapeShellArg cfg.leasesPath} \ ${concatStringsSep " \\\n " cfg.extraFlags} ''; }; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix b/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix index a01074758ff8..aba3533e4395 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/dovecot.nix @@ -64,7 +64,7 @@ in ${pkgs.prometheus-dovecot-exporter}/bin/dovecot_exporter \ --web.listen-address ${cfg.listenAddress}:${toString cfg.port} \ --web.telemetry-path ${cfg.telemetryPath} \ - --dovecot.socket-path ${cfg.socketPath} \ + --dovecot.socket-path ${escapeShellArg cfg.socketPath} \ --dovecot.scopes ${concatStringsSep "," cfg.scopes} \ ${concatStringsSep " \\\n " cfg.extraFlags} ''; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/json.nix b/nixos/modules/services/monitoring/prometheus/exporters/json.nix index 82a55bafc982..bd0026b55f72 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/json.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/json.nix @@ -27,7 +27,7 @@ in ExecStart = '' ${pkgs.prometheus-json-exporter}/bin/prometheus-json-exporter \ --port ${toString cfg.port} \ - ${cfg.url} ${cfg.configFile} \ + ${cfg.url} ${escapeShellArg cfg.configFile} \ ${concatStringsSep " \\\n " cfg.extraFlags} ''; }; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/mail.nix b/nixos/modules/services/monitoring/prometheus/exporters/mail.nix index 7d8c6fb61404..18c5c4dd1623 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/mail.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/mail.nix @@ -90,7 +90,7 @@ let Timeout until mails are considered "didn't make it". ''; }; - disableFileDelition = mkOption { + disableFileDeletion = mkOption { type = types.bool; default = false; description = '' @@ -127,8 +127,8 @@ in ''; }; configuration = mkOption { - type = types.submodule exporterOptions; - default = {}; + type = types.nullOr (types.submodule exporterOptions); + default = null; description = '' Specify the mailexporter configuration file to use. ''; @@ -147,8 +147,9 @@ in ExecStart = '' ${pkgs.prometheus-mail-exporter}/bin/mailexporter \ --web.listen-address ${cfg.listenAddress}:${toString cfg.port} \ + --web.telemetry-path ${cfg.telemetryPath} \ --config.file ${ - if cfg.configuration != {} then configurationFile else cfg.configFile + if cfg.configuration != null then configurationFile else (escapeShellArg cfg.configFile) } \ ${concatStringsSep " \\\n " cfg.extraFlags} ''; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix b/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix new file mode 100644 index 000000000000..62c2cc568476 --- /dev/null +++ b/nixos/modules/services/monitoring/prometheus/exporters/mikrotik.nix @@ -0,0 +1,66 @@ +{ config, lib, pkgs, options }: + +with lib; + +let + cfg = config.services.prometheus.exporters.mikrotik; +in +{ + port = 9436; + extraOpts = { + configFile = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Path to a mikrotik exporter configuration file. Mutually exclusive with + <option>configuration</option> option. + ''; + example = literalExample "./mikrotik.yml"; + }; + + configuration = mkOption { + type = types.nullOr types.attrs; + default = null; + description = '' + Mikrotik exporter configuration as nix attribute set. Mutually exclusive with + <option>configFile</option> option. + + See <link xlink:href="https://github.com/nshttpd/mikrotik-exporter/blob/master/README.md"/> + for the description of the configuration file format. + ''; + example = literalExample '' + { + devices = [ + { + name = "my_router"; + address = "10.10.0.1"; + user = "prometheus"; + password = "changeme"; + } + ]; + features = { + bgp = true; + dhcp = true; + routes = true; + optics = true; + }; + } + ''; + }; + }; + serviceOpts = let + configFile = if cfg.configFile != null + then cfg.configFile + else "${pkgs.writeText "mikrotik-exporter.yml" (builtins.toJSON cfg.configuration)}"; + in { + serviceConfig = { + # -port is misleading name, it actually accepts address too + ExecStart = '' + ${pkgs.prometheus-mikrotik-exporter}/bin/mikrotik-exporter \ + -config-file=${escapeShellArg configFile} \ + -port=${cfg.listenAddress}:${toString cfg.port} \ + ${concatStringsSep " \\\n " cfg.extraFlags} + ''; + }; + }; +} diff --git a/nixos/modules/services/monitoring/prometheus/exporters/minio.nix b/nixos/modules/services/monitoring/prometheus/exporters/minio.nix index ab3e3d7d5d50..d6dd62f871bd 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/minio.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/minio.nix @@ -54,8 +54,8 @@ in ${pkgs.prometheus-minio-exporter}/bin/minio-exporter \ -web.listen-address ${cfg.listenAddress}:${toString cfg.port} \ -minio.server ${cfg.minioAddress} \ - -minio.access-key ${cfg.minioAccessKey} \ - -minio.access-secret ${cfg.minioAccessSecret} \ + -minio.access-key ${escapeShellArg cfg.minioAccessKey} \ + -minio.access-secret ${escapeShellArg cfg.minioAccessSecret} \ ${optionalString cfg.minioBucketStats "-minio.bucket-stats"} \ ${concatStringsSep " \\\n " cfg.extraFlags} ''; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix b/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix index 5f9a52053f79..aee6bd5e66ce 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/nextcloud.nix @@ -50,7 +50,7 @@ in -u ${cfg.username} \ -t ${cfg.timeout} \ -l ${cfg.url} \ - -p @${cfg.passwordFile} \ + -p ${escapeShellArg "@${cfg.passwordFile}"} \ ${concatStringsSep " \\\n " cfg.extraFlags} ''; }; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix b/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix index d50564717eaf..3b6ef1631f89 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/postfix.nix @@ -67,15 +67,15 @@ in ${pkgs.prometheus-postfix-exporter}/bin/postfix_exporter \ --web.listen-address ${cfg.listenAddress}:${toString cfg.port} \ --web.telemetry-path ${cfg.telemetryPath} \ - --postfix.showq_path ${cfg.showqPath} \ + --postfix.showq_path ${escapeShellArg cfg.showqPath} \ ${concatStringsSep " \\\n " (cfg.extraFlags ++ optional cfg.systemd.enable "--systemd.enable" ++ optional cfg.systemd.enable (if cfg.systemd.slice != null then "--systemd.slice ${cfg.systemd.slice}" else "--systemd.unit ${cfg.systemd.unit}") ++ optional (cfg.systemd.enable && (cfg.systemd.journalPath != null)) - "--systemd.journal_path ${cfg.systemd.journalPath}" - ++ optional (!cfg.systemd.enable) "--postfix.logfile_path ${cfg.logfilePath}")} + "--systemd.journal_path ${escapeShellArg cfg.systemd.journalPath}" + ++ optional (!cfg.systemd.enable) "--postfix.logfile_path ${escapeShellArg cfg.logfilePath}")} ''; }; }; diff --git a/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix b/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix index fe7ae8a8ac90..045e48a3d0f8 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/snmp.nix @@ -19,7 +19,7 @@ in configuration = mkOption { type = types.nullOr types.attrs; - default = {}; + default = null; description = '' Snmp exporter configuration as nix attribute set. Mutually exclusive with 'configurationPath' option. ''; @@ -36,15 +36,15 @@ in }; logFormat = mkOption { - type = types.str; - default = "logger:stderr"; + type = types.enum ["logfmt" "json"]; + default = "logfmt"; description = '' - Set the log target and format. + Output format of log messages. ''; }; logLevel = mkOption { - type = types.enum ["debug" "info" "warn" "error" "fatal"]; + type = types.enum ["debug" "info" "warn" "error"]; default = "info"; description = '' Only log messages with the given severity or above. @@ -54,13 +54,13 @@ in serviceOpts = let configFile = if cfg.configurationPath != null then cfg.configurationPath - else "${pkgs.writeText "snmp-eporter-conf.yml" (builtins.toJSON cfg.configuration)}"; + else "${pkgs.writeText "snmp-exporter-conf.yml" (builtins.toJSON cfg.configuration)}"; in { serviceConfig = { ExecStart = '' ${pkgs.prometheus-snmp-exporter.bin}/bin/snmp_exporter \ - --config.file=${configFile} \ - --log.format=${cfg.logFormat} \ + --config.file=${escapeShellArg configFile} \ + --log.format=${escapeShellArg cfg.logFormat} \ --log.level=${cfg.logLevel} \ --web.listen-address=${cfg.listenAddress}:${toString cfg.port} \ ${concatStringsSep " \\\n " cfg.extraFlags} diff --git a/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix b/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix index 9aa0f1b85aac..8d0e8764001c 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/unifi.nix @@ -55,8 +55,8 @@ in ${pkgs.prometheus-unifi-exporter}/bin/unifi_exporter \ -telemetry.addr ${cfg.listenAddress}:${toString cfg.port} \ -unifi.addr ${cfg.unifiAddress} \ - -unifi.username ${cfg.unifiUsername} \ - -unifi.password ${cfg.unifiPassword} \ + -unifi.username ${escapeShellArg cfg.unifiUsername} \ + -unifi.password ${escapeShellArg cfg.unifiPassword} \ -unifi.timeout ${cfg.unifiTimeout} \ ${optionalString cfg.unifiInsecure "-unifi.insecure" } \ ${concatStringsSep " \\\n " cfg.extraFlags} diff --git a/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix b/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix index 12153fa021ec..5b5a6e18fcd6 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/varnish.nix @@ -74,10 +74,10 @@ in ${pkgs.prometheus-varnish-exporter}/bin/prometheus_varnish_exporter \ --web.listen-address ${cfg.listenAddress}:${toString cfg.port} \ --web.telemetry-path ${cfg.telemetryPath} \ - --varnishstat-path ${cfg.varnishStatPath} \ + --varnishstat-path ${escapeShellArg cfg.varnishStatPath} \ ${concatStringsSep " \\\n " (cfg.extraFlags ++ optional (cfg.healthPath != null) "--web.health-path ${cfg.healthPath}" - ++ optional (cfg.instance != null) "-n ${cfg.instance}" + ++ optional (cfg.instance != null) "-n ${escapeShellArg cfg.instance}" ++ optional cfg.noExit "--no-exit" ++ optional cfg.withGoMetrics "--with-go-metrics" ++ optional cfg.verbose "--verbose" diff --git a/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix b/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix index 374f83a2939d..04421fc2d25a 100644 --- a/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix +++ b/nixos/modules/services/monitoring/prometheus/exporters/wireguard.nix @@ -59,7 +59,7 @@ in { ${optionalString cfg.verbose "-v"} \ ${optionalString cfg.singleSubnetPerField "-s"} \ ${optionalString cfg.withRemoteIp "-r"} \ - ${optionalString (cfg.wireguardConfig != null) "-n ${cfg.wireguardConfig}"} + ${optionalString (cfg.wireguardConfig != null) "-n ${escapeShellArg cfg.wireguardConfig}"} ''; }; }; diff --git a/nixos/modules/services/networking/freeradius.nix b/nixos/modules/services/networking/freeradius.nix index e192b70c129c..f3fdd576b65c 100644 --- a/nixos/modules/services/networking/freeradius.nix +++ b/nixos/modules/services/networking/freeradius.nix @@ -10,14 +10,15 @@ let { description = "FreeRadius server"; wantedBy = ["multi-user.target"]; - after = ["network-online.target"]; - wants = ["network-online.target"]; + after = ["network.target"]; + wants = ["network.target"]; preStart = '' ${pkgs.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout ''; serviceConfig = { - ExecStart = "${pkgs.freeradius}/bin/radiusd -f -d ${cfg.configDir} -l stdout -xx"; + ExecStart = "${pkgs.freeradius}/bin/radiusd -f -d ${cfg.configDir} -l stdout" + + optionalString cfg.debug " -xx"; ExecReload = [ "${pkgs.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout" "${pkgs.coreutils}/bin/kill -HUP $MAINPID" @@ -41,6 +42,16 @@ let ''; }; + debug = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable debug logging for freeradius (-xx + option). This should not be left on, since it includes + sensitive data such as passwords in the logs. + ''; + }; + }; in @@ -66,6 +77,7 @@ in }; systemd.services.freeradius = freeradiusService cfg; + warnings = optional cfg.debug "Freeradius debug logging is enabled. This will log passwords in plaintext to the journal!"; }; diff --git a/nixos/modules/services/networking/shorewall.nix b/nixos/modules/services/networking/shorewall.nix index c59a53669158..16383be2530f 100644 --- a/nixos/modules/services/networking/shorewall.nix +++ b/nixos/modules/services/networking/shorewall.nix @@ -26,13 +26,14 @@ in { description = "The shorewall package to use."; }; configs = lib.mkOption { - type = types.attrsOf types.str; + type = types.attrsOf types.lines; default = {}; description = '' This option defines the Shorewall configs. The attribute name defines the name of the config, and the attribute value defines the content of the config. ''; + apply = lib.mapAttrs (name: text: pkgs.writeText "${name}" text); }; }; }; @@ -62,7 +63,7 @@ in { ''; }; environment = { - etc = lib.mapAttrs' (name: conf: lib.nameValuePair "shorewall/${name}" {text=conf;}) cfg.configs; + etc = lib.mapAttrs' (name: conf: lib.nameValuePair "shorewall/${name}" {source=conf;}) cfg.configs; systemPackages = [ cfg.package ]; }; }; diff --git a/nixos/modules/services/networking/shorewall6.nix b/nixos/modules/services/networking/shorewall6.nix index 374e407cc7a1..e081aedc6c34 100644 --- a/nixos/modules/services/networking/shorewall6.nix +++ b/nixos/modules/services/networking/shorewall6.nix @@ -26,13 +26,14 @@ in { description = "The shorewall package to use."; }; configs = lib.mkOption { - type = types.attrsOf types.str; + type = types.attrsOf types.lines; default = {}; description = '' This option defines the Shorewall configs. The attribute name defines the name of the config, and the attribute value defines the content of the config. ''; + apply = lib.mapAttrs (name: text: pkgs.writeText "${name}" text); }; }; }; @@ -62,7 +63,7 @@ in { ''; }; environment = { - etc = lib.mapAttrs' (name: conf: lib.nameValuePair "shorewall6/${name}" {text=conf;}) cfg.configs; + etc = lib.mapAttrs' (name: conf: lib.nameValuePair "shorewall6/${name}" {source=conf;}) cfg.configs; systemPackages = [ cfg.package ]; }; }; diff --git a/nixos/modules/services/networking/wireguard.nix b/nixos/modules/services/networking/wireguard.nix index ff8e54a1ce20..e8f83f6dd8bf 100644 --- a/nixos/modules/services/networking/wireguard.nix +++ b/nixos/modules/services/networking/wireguard.nix @@ -428,7 +428,7 @@ in ++ (attrValues ( mapAttrs (name: value: { assertion = value.generatePrivateKeyFile -> (value.privateKey == null); - message = "networking.wireguard.interfaces.${name}.generatePrivateKey must not be set if networking.wireguard.interfaces.${name}.privateKey is set."; + message = "networking.wireguard.interfaces.${name}.generatePrivateKeyFile must not be set if networking.wireguard.interfaces.${name}.privateKey is set."; }) cfg.interfaces)) ++ map ({ interfaceName, peer, ... }: { assertion = (peer.presharedKey == null) || (peer.presharedKeyFile == null); diff --git a/nixos/modules/services/wayland/cage.nix b/nixos/modules/services/wayland/cage.nix index cac5c042ec16..c59ca9983a6c 100644 --- a/nixos/modules/services/wayland/cage.nix +++ b/nixos/modules/services/wayland/cage.nix @@ -51,6 +51,7 @@ in { conflicts = [ "getty@tty1.service" ]; restartIfChanged = false; + unitConfig.ConditionPathExists = "/dev/tty1"; serviceConfig = { ExecStart = '' ${pkgs.cage}/bin/cage \ @@ -59,7 +60,6 @@ in { ''; User = cfg.user; - ConditionPathExists = "/dev/tty1"; IgnoreSIGPIPE = "no"; # Log this user with utmp, letting it show up with commands 'w' and diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index c8602e5975b3..28b433104a1c 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -87,10 +87,17 @@ let ${optionalString (cfg.sslDhparam != null) "ssl_dhparam ${cfg.sslDhparam};"} ${optionalString (cfg.recommendedTlsSettings) '' - ssl_session_cache shared:SSL:42m; - ssl_session_timeout 23m; - ssl_ecdh_curve secp384r1; - ssl_prefer_server_ciphers on; + # Keep in sync with https://ssl-config.mozilla.org/#server=nginx&config=intermediate + + ssl_session_timeout 1d; + ssl_session_cache shared:SSL:10m; + # Breaks forward secrecy: https://github.com/mozilla/server-side-tls/issues/135 + ssl_session_tickets off; + # We don't enable insecure ciphers by default, so this allows + # clients to pick the most performant, per https://github.com/mozilla/server-side-tls/issues/260 + ssl_prefer_server_ciphers off; + + # OCSP stapling ssl_stapling on; ssl_stapling_verify on; ''} @@ -487,8 +494,9 @@ in sslCiphers = mkOption { type = types.str; - default = "EECDH+aRSA+AESGCM:EDH+aRSA:EECDH+aRSA:+AES256:+AES128:+SHA1:!CAMELLIA:!SEED:!3DES:!DES:!RC4:!eNULL"; - description = "Ciphers to choose from when negotiating tls handshakes."; + # Keep in sync with https://ssl-config.mozilla.org/#server=nginx&config=intermediate + default = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"; + description = "Ciphers to choose from when negotiating TLS handshakes."; }; sslProtocols = mkOption { diff --git a/nixos/modules/services/web-servers/uwsgi.nix b/nixos/modules/services/web-servers/uwsgi.nix index 3481b5e60403..4b74c329e3dc 100644 --- a/nixos/modules/services/web-servers/uwsgi.nix +++ b/nixos/modules/services/web-servers/uwsgi.nix @@ -32,7 +32,7 @@ let inherit plugins; } // removeAttrs c [ "type" "pythonPackages" ] // optionalAttrs (python != null) { - pythonpath = "${pythonEnv}/${python.sitePackages}"; + pyhome = "${pythonEnv}"; env = # Argh, uwsgi expects list of key-values there instead of a dictionary. let env' = c.env or []; diff --git a/nixos/modules/system/activation/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl index 641cf9faadc9..b82d69b3bb85 100644 --- a/nixos/modules/system/activation/switch-to-configuration.pl +++ b/nixos/modules/system/activation/switch-to-configuration.pl @@ -183,7 +183,7 @@ while (my ($unit, $state) = each %{$activePrev}) { # active after the system has resumed, which probably # should not be the case. Just ignore it. if ($unit ne "suspend.target" && $unit ne "hibernate.target" && $unit ne "hybrid-sleep.target") { - unless (boolIsTrue($unitInfo->{'RefuseManualStart'} // "no")) { + unless (boolIsTrue($unitInfo->{'RefuseManualStart'} // "no") || boolIsTrue($unitInfo->{'X-OnlyManualStart'} // "no")) { $unitsToStart{$unit} = 1; recordUnit($startListFile, $unit); # Don't spam the user with target units that always get started. @@ -222,7 +222,7 @@ while (my ($unit, $state) = each %{$activePrev}) { $unitsToReload{$unit} = 1; recordUnit($reloadListFile, $unit); } - elsif (!boolIsTrue($unitInfo->{'X-RestartIfChanged'} // "yes") || boolIsTrue($unitInfo->{'RefuseManualStop'} // "no") ) { + elsif (!boolIsTrue($unitInfo->{'X-RestartIfChanged'} // "yes") || boolIsTrue($unitInfo->{'RefuseManualStop'} // "no") || boolIsTrue($unitInfo->{'X-OnlyManualStart'} // "no")) { $unitsToSkip{$unit} = 1; } else { if (!boolIsTrue($unitInfo->{'X-StopIfChanged'} // "yes")) { diff --git a/nixos/modules/system/etc/etc.nix b/nixos/modules/system/etc/etc.nix index 57ade2880962..1f4d54a1ae20 100644 --- a/nixos/modules/system/etc/etc.nix +++ b/nixos/modules/system/etc/etc.nix @@ -94,7 +94,7 @@ in default = 0; type = types.int; description = '' - UID of created file. Only takes affect when the file is + UID of created file. Only takes effect when the file is copied (that is, the mode is not 'symlink'). ''; }; @@ -103,7 +103,7 @@ in default = 0; type = types.int; description = '' - GID of created file. Only takes affect when the file is + GID of created file. Only takes effect when the file is copied (that is, the mode is not 'symlink'). ''; }; @@ -113,7 +113,7 @@ in type = types.str; description = '' User name of created file. - Only takes affect when the file is copied (that is, the mode is not 'symlink'). + Only takes effect when the file is copied (that is, the mode is not 'symlink'). Changing this option takes precedence over <literal>uid</literal>. ''; }; @@ -123,7 +123,7 @@ in type = types.str; description = '' Group name of created file. - Only takes affect when the file is copied (that is, the mode is not 'symlink'). + Only takes effect when the file is copied (that is, the mode is not 'symlink'). Changing this option takes precedence over <literal>gid</literal>. ''; }; diff --git a/nixos/tests/docker-tools.nix b/nixos/tests/docker-tools.nix index 54dd97e5b139..51b472fcf9ce 100644 --- a/nixos/tests/docker-tools.nix +++ b/nixos/tests/docker-tools.nix @@ -137,5 +137,22 @@ import ./make-test-python.nix ({ pkgs, ... }: { # Ensure the two output paths (ls and hello) are in the layer "docker run bulk-layer ls /bin/hello", ) + + with subtest("Ensure correct behavior when no store is needed"): + # This check tests two requirements simultaneously + # 1. buildLayeredImage can build images that don't need a store. + # 2. Layers of symlinks are eliminated by the customization layer. + # + docker.succeed( + "docker load --input='${pkgs.dockerTools.examples.no-store-paths}'" + ) + + # Busybox will not recognize argv[0] and print an error message with argv[0], + # but it confirms that the custom-true symlink is present. + docker.succeed("docker run --rm no-store-paths custom-true |& grep custom-true") + + # This check may be loosened to allow an *empty* store rather than *no* store. + docker.succeed("docker run --rm no-store-paths ls /") + docker.fail("docker run --rm no-store-paths ls /nix/store") ''; }) diff --git a/nixos/tests/prometheus-exporters.nix b/nixos/tests/prometheus-exporters.nix index 3d0d00bfbe63..4fc3668cfafb 100644 --- a/nixos/tests/prometheus-exporters.nix +++ b/nixos/tests/prometheus-exporters.nix @@ -224,7 +224,7 @@ let after = [ "postfix.service" ]; requires = [ "postfix.service" ]; preStart = '' - mkdir -p 0600 mail-exporter/new + mkdir -p -m 0700 mail-exporter/new ''; serviceConfig = { ProtectHome = true; @@ -245,6 +245,46 @@ let ''; }; + mikrotik = { + exporterConfig = { + enable = true; + extraFlags = [ "-timeout=1s" ]; + configuration = { + devices = [ + { + name = "router"; + address = "192.168.42.48"; + user = "prometheus"; + password = "shh"; + } + ]; + features = { + bgp = true; + dhcp = true; + dhcpl = true; + dhcpv6 = true; + health = true; + routes = true; + poe = true; + pools = true; + optics = true; + w60g = true; + wlansta = true; + wlanif = true; + monitor = true; + ipsec = true; + }; + }; + }; + exporterTest = '' + wait_for_unit("prometheus-mikrotik-exporter.service") + wait_for_open_port(9436) + succeed( + "curl -sSf http://localhost:9436/metrics | grep -q 'mikrotik_scrape_collector_success{device=\"router\"} 0'" + ) + ''; + }; + nextcloud = { exporterConfig = { enable = true; @@ -363,6 +403,7 @@ let }; metricProvider = { services.rspamd.enable = true; + virtualisation.memorySize = 1024; }; exporterTest = '' wait_for_unit("rspamd.service") |