diff options
Diffstat (limited to 'nixos')
44 files changed, 919 insertions, 137 deletions
diff --git a/nixos/doc/manual/release-notes/rl-1709.xml b/nixos/doc/manual/release-notes/rl-1709.xml index a1e443818012..55b39209f0d5 100644 --- a/nixos/doc/manual/release-notes/rl-1709.xml +++ b/nixos/doc/manual/release-notes/rl-1709.xml @@ -107,7 +107,7 @@ rmdir /var/lib/ipfs/.ipfs The <literal>mysql</literal> default <literal>dataDir</literal> has changed from <literal>/var/mysql</literal> to <literal>/var/lib/mysql</literal>. </para> <para> - Radicale's default package has changed from 1.x to 2.x. Instructions to migrate can be found <link xlink:href="http://radicale.org/1to2/"> here </link>. It is also possible to use the newer version by setting the <literal>package</literal> to <literal>radicale2</literal>, which is done automatically when <literal>stateVersion</literal> is 17.09 or higher. + Radicale's default package has changed from 1.x to 2.x. Instructions to migrate can be found <link xlink:href="http://radicale.org/1to2/"> here </link>. It is also possible to use the newer version by setting the <literal>package</literal> to <literal>radicale2</literal>, which is done automatically when <literal>stateVersion</literal> is 17.09 or higher. The <literal>extraArgs</literal> option has been added to allow passing the data migration arguments specified in the instructions; see the <filename xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/radicale.nix">radicale.nix</filename> NixOS test for an example migration. </para> </listitem> <listitem> @@ -255,6 +255,15 @@ rmdir /var/lib/ipfs/.ipfs See the overlays chapter of the Nixpkgs manual for more details. </para> </listitem> + <listitem> + <para> + <literal>sha256</literal> argument value of + <literal>dockerTools.pullImage</literal> expression must be + updated since the mechanism to download the image has been + changed. Skopeo is now used to pull the image instead of the + Docker daemon. + </para> + </listitem> </itemizedlist> diff --git a/nixos/modules/config/networking.nix b/nixos/modules/config/networking.nix index 619f36cd5150..5fa91ec9cfbc 100644 --- a/nixos/modules/config/networking.nix +++ b/nixos/modules/config/networking.nix @@ -9,7 +9,9 @@ let cfg = config.networking; dnsmasqResolve = config.services.dnsmasq.enable && config.services.dnsmasq.resolveLocalQueries; - hasLocalResolver = config.services.bind.enable || dnsmasqResolve; + bindResolve = config.services.bind.enable && + config.services.bind.resolveLocalQueries; + hasLocalResolver = bindResolve || dnsmasqResolve; resolvconfOptions = cfg.resolvconfOptions ++ optional cfg.dnsSingleRequest "single-request" diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 9ebac8852bb2..eb478f66d40f 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -301,10 +301,12 @@ ./services/misc/gitlab.nix ./services/misc/gitolite.nix ./services/misc/gogs.nix + ./services/misc/gollum.nix ./services/misc/gpsd.nix #./services/misc/ihaskell.nix ./services/misc/irkerd.nix ./services/misc/jackett.nix + ./services/misc/logkeys.nix ./services/misc/leaps.nix ./services/misc/mantisbt.nix ./services/misc/mathics.nix @@ -460,6 +462,7 @@ ./services/networking/lldpd.nix ./services/networking/logmein-hamachi.nix ./services/networking/mailpile.nix + ./services/networking/matterbridge.nix ./services/networking/mjpg-streamer.nix ./services/networking/minidlna.nix ./services/networking/miniupnpd.nix @@ -510,6 +513,7 @@ ./services/networking/smokeping.nix ./services/networking/softether.nix ./services/networking/spiped.nix + ./services/networking/squid.nix ./services/networking/sslh.nix ./services/networking/ssh/lshd.nix ./services/networking/ssh/sshd.nix diff --git a/nixos/modules/profiles/base.nix b/nixos/modules/profiles/base.nix index 687cd9d80d36..39b8553976eb 100644 --- a/nixos/modules/profiles/base.nix +++ b/nixos/modules/profiles/base.nix @@ -20,6 +20,7 @@ # Some networking tools. pkgs.fuse + pkgs.fuse3 pkgs.sshfs-fuse pkgs.socat pkgs.screen diff --git a/nixos/modules/programs/xonsh.nix b/nixos/modules/programs/xonsh.nix index c0be2d8884b3..49cc4906e038 100644 --- a/nixos/modules/programs/xonsh.nix +++ b/nixos/modules/programs/xonsh.nix @@ -21,7 +21,7 @@ in enable = mkOption { default = false; description = '' - Whether to configure xnosh as an interactive shell. + Whether to configure xonsh as an interactive shell. ''; type = types.bool; }; diff --git a/nixos/modules/security/wrappers/default.nix b/nixos/modules/security/wrappers/default.nix index a6dc8faaae98..1f64213accd4 100644 --- a/nixos/modules/security/wrappers/default.nix +++ b/nixos/modules/security/wrappers/default.nix @@ -155,7 +155,10 @@ in ###### implementation config = { - security.wrappers.fusermount.source = "${pkgs.fuse}/bin/fusermount"; + security.wrappers = { + fusermount.source = "${pkgs.fuse}/bin/fusermount"; + fusermount3.source = "${pkgs.fuse3}/bin/fusermount3"; + }; boot.specialFileSystems.${parentWrapperDir} = { fsType = "tmpfs"; diff --git a/nixos/modules/services/databases/influxdb.nix b/nixos/modules/services/databases/influxdb.nix index 9ffe9fdea2ce..eeab33309fda 100644 --- a/nixos/modules/services/databases/influxdb.nix +++ b/nixos/modules/services/databases/influxdb.nix @@ -171,7 +171,7 @@ in if [ "$(id -u)" = 0 ]; then chown -R ${cfg.user}:${cfg.group} ${cfg.dataDir}; fi ''; postStart = mkBefore '' - until ${pkgs.curl.bin}/bin/curl -s -o /dev/null 'http://127.0.0.1${toString configOptions.http.bind-address}'/ping; do + until ${pkgs.curl.bin}/bin/curl -s -o /dev/null ${if configOptions.http.https-enabled then "-k https" else "http"}://127.0.0.1${toString configOptions.http.bind-address}/ping; do sleep 1; done ''; diff --git a/nixos/modules/services/databases/mysql.nix b/nixos/modules/services/databases/mysql.nix index 50766093307d..845e6d4c22ef 100644 --- a/nixos/modules/services/databases/mysql.nix +++ b/nixos/modules/services/databases/mysql.nix @@ -30,6 +30,10 @@ let master-password = ${cfg.replication.masterPassword} master-port = ${toString cfg.replication.masterPort} ''} + ${optionalString (cfg.ensureUsers != []) + '' + plugin-load-add = auth_socket.so + ''} ${cfg.extraOptions} ''; @@ -123,6 +127,46 @@ in description = "A file containing SQL statements to be executed on the first startup. Can be used for granting certain permissions on the database"; }; + ensureDatabases = mkOption { + default = []; + description = '' + Ensures that the specified databases exist. + This option will never delete existing databases, especially not when the value of this + option is changed. This means that databases created once through this option or + otherwise have to be removed manually. + ''; + example = [ + "nextcloud" + "piwik" + ]; + }; + + ensureUsers = mkOption { + default = []; + description = '' + Ensures that the specified users exist and have at least the ensured permissions. + The MySQL users will be identified using Unix socket authentication. This authenticates the Unix user with the + same name only, and that without the need for a password. + This option will never delete existing users or remove permissions, especially not when the value of this + option is changed. This means that users created and permissions assigned once through this option or + otherwise have to be removed manually. + ''; + example = [ + { + name = "nextcloud"; + ensurePermissions = { + "nextcloud.*" = "ALL PRIVILEGES"; + }; + } + { + name = "backup"; + ensurePermissions = { + "*.*" = "SELECT, LOCK TABLES"; + }; + } + ]; + }; + # FIXME: remove this option; it's a really bad idea. rootPassword = mkOption { default = null; @@ -305,6 +349,24 @@ in rm /tmp/mysql_init fi + + ${optionalString (cfg.ensureDatabases != []) '' + ( + ${concatMapStrings (database: '' + echo "CREATE DATABASE IF NOT EXISTS ${database};" + '') cfg.ensureDatabases} + ) | ${mysql}/bin/mysql -u root -N + ''} + + ${concatMapStrings (user: + '' + ( echo "CREATE USER IF NOT EXISTS '${user.name}'@'localhost' IDENTIFIED WITH ${if mysql == pkgs.mariadb then "unix_socket" else "auth_socket"};" + ${concatStringsSep "\n" (mapAttrsToList (database: permission: '' + echo "GRANT ${permission} ON ${database} TO '${user.name}'@'localhost';" + '') user.ensurePermissions)} + ) | ${mysql}/bin/mysql -u root -N + '') cfg.ensureUsers} + ''; # */ }; diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix index 135d3b277378..6057acc531a3 100644 --- a/nixos/modules/services/mail/dovecot.nix +++ b/nixos/modules/services/mail/dovecot.nix @@ -9,6 +9,8 @@ let baseDir = "/run/dovecot2"; stateDir = "/var/lib/dovecot"; + canCreateMailUserGroup = cfg.mailUser != null && cfg.mailGroup != null; + dovecotConf = concatStrings [ '' base_dir = ${baseDir} @@ -314,17 +316,18 @@ in description = "Dovecot user"; group = cfg.group; } - ++ optional cfg.createMailUser - { name = cfg.mailUser; - description = "Virtual Mail User"; + ++ optional (cfg.createMailUser && cfg.mailUser != null) + ({ name = cfg.mailUser; + description = "Virtual Mail User"; + } // optionalAttrs (cfg.mailGroup != null) { group = cfg.mailGroup; - }; + }); users.extraGroups = optional (cfg.group == "dovecot2") { name = "dovecot2"; gid = config.ids.gids.dovecot2; } - ++ optional cfg.createMailUser + ++ optional (cfg.createMailUser && cfg.mailGroup != null) { name = cfg.mailGroup; }; diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix index 412355fb35b5..d6c8ac547246 100644 --- a/nixos/modules/services/misc/gitlab.nix +++ b/nixos/modules/services/misc/gitlab.nix @@ -142,9 +142,9 @@ let GITLAB_UPLOADS_PATH = "${cfg.statePath}/uploads"; GITLAB_LOG_PATH = "${cfg.statePath}/log"; GITLAB_SHELL_PATH = "${cfg.packages.gitlab-shell}"; - GITLAB_SHELL_CONFIG_PATH = "${cfg.statePath}/home/config.yml"; + GITLAB_SHELL_CONFIG_PATH = "${cfg.statePath}/shell/config.yml"; GITLAB_SHELL_SECRET_PATH = "${cfg.statePath}/config/gitlab_shell_secret"; - GITLAB_SHELL_HOOKS_PATH = "${cfg.statePath}/home/hooks"; + GITLAB_SHELL_HOOKS_PATH = "${cfg.statePath}/shell/hooks"; GITLAB_REDIS_CONFIG_FILE = pkgs.writeText "gitlab-redis.yml" redisYml; prometheus_multiproc_dir = "/run/gitlab"; RAILS_ENV = "production"; @@ -555,6 +555,7 @@ in { openssh nodejs procps + gnupg ]; preStart = '' mkdir -p ${cfg.backupPath} @@ -567,7 +568,7 @@ in { mkdir -p ${cfg.statePath}/tmp/pids mkdir -p ${cfg.statePath}/tmp/sockets - rm -rf ${cfg.statePath}/config ${cfg.statePath}/home/hooks + rm -rf ${cfg.statePath}/config ${cfg.statePath}/shell/hooks mkdir -p ${cfg.statePath}/config tr -dc A-Za-z0-9 < /dev/urandom | head -c 32 > ${cfg.statePath}/config/gitlab_shell_secret diff --git a/nixos/modules/services/misc/gogs.nix b/nixos/modules/services/misc/gogs.nix index ad2e36d04d53..d6e827a53fdf 100644 --- a/nixos/modules/services/misc/gogs.nix +++ b/nixos/modules/services/misc/gogs.nix @@ -257,7 +257,7 @@ in in the Nix store. Use database.passwordFile instead.''; # Create database passwordFile default when password is configured. - services.gogs.database.passwordFile = mkIf (cfg.database.password != "") + services.gogs.database.passwordFile = (mkDefault (toString (pkgs.writeTextFile { name = "gogs-database-password"; text = cfg.database.password; diff --git a/nixos/modules/services/misc/gollum.nix b/nixos/modules/services/misc/gollum.nix new file mode 100644 index 000000000000..81fb024f9094 --- /dev/null +++ b/nixos/modules/services/misc/gollum.nix @@ -0,0 +1,92 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.gollum; +in + +{ + options.services.gollum = { + enable = mkOption { + type = types.bool; + default = false; + description = "Enable the Gollum service."; + }; + + address = mkOption { + type = types.str; + default = "0.0.0.0"; + description = "IP address on which the web server will listen."; + }; + + port = mkOption { + type = types.int; + default = 4567; + description = "Port on which the web server will run."; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = "Content of the configuration file"; + }; + + branch = mkOption { + type = types.str; + default = "master"; + example = "develop"; + description = "Git branch to serve"; + }; + + stateDir = mkOption { + type = types.path; + default = "/var/lib/gollum"; + description = "Specifies the path of the repository directory. If it does not exist, Gollum will create it on startup."; + }; + + }; + + config = mkIf cfg.enable { + + users.users.gollum = { + group = config.users.users.gollum.name; + description = "Gollum user"; + createHome = false; + }; + + users.groups.gollum = { }; + + systemd.services.gollum = { + description = "Gollum wiki"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + path = [ pkgs.git ]; + + preStart = let + userName = config.users.users.gollum.name; + groupName = config.users.groups.gollum.name; + in '' + # All of this is safe to be run on an existing repo + mkdir -p ${cfg.stateDir} + git init ${cfg.stateDir} + chmod 755 ${cfg.stateDir} + chown -R ${userName}:${groupName} ${cfg.stateDir} + ''; + + serviceConfig = { + User = config.users.extraUsers.gollum.name; + Group = config.users.extraGroups.gollum.name; + PermissionsStartOnly = true; + ExecStart = '' + ${pkgs.gollum}/bin/gollum \ + --port ${toString cfg.port} \ + --host ${cfg.address} \ + --config ${builtins.toFile "gollum-config.rb" cfg.extraConfig} \ + --ref ${cfg.branch} \ + ${cfg.stateDir} + ''; + }; + }; + }; +} diff --git a/nixos/modules/services/misc/logkeys.nix b/nixos/modules/services/misc/logkeys.nix new file mode 100644 index 000000000000..6051c884465d --- /dev/null +++ b/nixos/modules/services/misc/logkeys.nix @@ -0,0 +1,23 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.services.logkeys; +in { + options.services.logkeys = { + enable = mkEnableOption "logkeys service"; + }; + + config = mkIf cfg.enable { + systemd.services.logkeys = { + description = "LogKeys Keylogger Daemon"; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = "${pkgs.logkeys}/bin/logkeys -s"; + ExecStop = "${pkgs.logkeys}/bin/logkeys -k"; + Type = "forking"; + }; + }; + }; +} diff --git a/nixos/modules/services/monitoring/prometheus/node-exporter.nix b/nixos/modules/services/monitoring/prometheus/node-exporter.nix index 0cf0b85afb57..b5b852438d77 100644 --- a/nixos/modules/services/monitoring/prometheus/node-exporter.nix +++ b/nixos/modules/services/monitoring/prometheus/node-exporter.nix @@ -33,7 +33,7 @@ in { default = []; example = ''[ "systemd" ]''; description = '' - Collectors to enable, additionally to the defaults. + Collectors to enable. Only collectors explicitly listed here will be enabled. ''; }; diff --git a/nixos/modules/services/network-filesystems/glusterfs.nix b/nixos/modules/services/network-filesystems/glusterfs.nix index 7454eeef803f..e7f52bc4a7d1 100644 --- a/nixos/modules/services/network-filesystems/glusterfs.nix +++ b/nixos/modules/services/network-filesystems/glusterfs.nix @@ -5,6 +5,22 @@ with lib; let inherit (pkgs) glusterfs rsync; + tlsCmd = if (cfg.tlsSettings != null) then + '' + mkdir -p /var/lib/glusterd + touch /var/lib/glusterd/secure-access + '' + else + '' + rm -f /var/lib/glusterd/secure-access + ''; + + restartTriggers = if (cfg.tlsSettings != null) then [ + config.environment.etc."ssl/glusterfs.pem".source + config.environment.etc."ssl/glusterfs.key".source + config.environment.etc."ssl/glusterfs.ca".source + ] else []; + cfg = config.services.glusterfs; in @@ -30,6 +46,41 @@ in description = "Extra flags passed to the GlusterFS daemon"; default = []; }; + + tlsSettings = mkOption { + description = '' + Make the server communicate via TLS. + This means it will only connect to other gluster + servers having certificates signed by the same CA. + + Enabling this will create a file <filename>/var/lib/glusterd/secure-access</filename>. + Disabling will delete this file again. + + See also: https://gluster.readthedocs.io/en/latest/Administrator%20Guide/SSL/ + ''; + default = null; + type = types.nullOr (types.submodule { + options = { + tlsKeyPath = mkOption { + default = null; + type = types.str; + description = "Path to the private key used for TLS."; + }; + + tlsPem = mkOption { + default = null; + type = types.path; + description = "Path to the certificate used for TLS."; + }; + + caCert = mkOption { + default = null; + type = types.path; + description = "Path certificate authority used to sign the cluster certificates."; + }; + }; + }); + }; }; }; @@ -40,7 +91,14 @@ in services.rpcbind.enable = true; + environment.etc = mkIf (cfg.tlsSettings != null) { + "ssl/glusterfs.pem".source = cfg.tlsSettings.tlsPem; + "ssl/glusterfs.key".source = cfg.tlsSettings.tlsKeyPath; + "ssl/glusterfs.ca".source = cfg.tlsSettings.caCert; + }; + systemd.services.glusterd = { + inherit restartTriggers; description = "GlusterFS, a clustered file-system server"; @@ -57,6 +115,8 @@ in + '' mkdir -p /var/lib/glusterd/hooks/ ${rsync}/bin/rsync -a ${glusterfs}/var/lib/glusterd/hooks/ /var/lib/glusterd/hooks/ + + ${tlsCmd} '' # `glusterfind` needs dirs that upstream installs at `make install` phase # https://github.com/gluster/glusterfs/blob/v3.10.2/tools/glusterfind/Makefile.am#L16-L17 @@ -75,6 +135,7 @@ in }; systemd.services.glustereventsd = { + inherit restartTriggers; description = "Gluster Events Notifier"; diff --git a/nixos/modules/services/network-filesystems/ipfs.nix b/nixos/modules/services/network-filesystems/ipfs.nix index cd320c5c4620..36e5efecf431 100644 --- a/nixos/modules/services/network-filesystems/ipfs.nix +++ b/nixos/modules/services/network-filesystems/ipfs.nix @@ -6,7 +6,7 @@ let cfg = config.services.ipfs; ipfsFlags = toString ([ - #(optionalString cfg.autoMount "--mount") + (optionalString cfg.autoMount "--mount") (optionalString cfg.autoMigrate "--migrate") (optionalString cfg.enableGC "--enable-gc") (optionalString (cfg.serviceFdlimit != null) "--manage-fdlimit=false") @@ -37,9 +37,10 @@ let baseService = recursiveUpdate commonEnv { wants = [ "ipfs-init.service" ]; preStart = '' + ipfs repo fsck # workaround for BUG #4212 (https://github.com/ipfs/go-ipfs/issues/4214) ipfs --local config Addresses.API ${cfg.apiAddress} ipfs --local config Addresses.Gateway ${cfg.gatewayAddress} - '' + optionalString false/*cfg.autoMount*/ '' + '' + optionalString cfg.autoMount '' ipfs --local config Mounts.FuseAllowOther --json true ipfs --local config Mounts.IPFS ${cfg.ipfsMountDir} ipfs --local config Mounts.IPNS ${cfg.ipnsMountDir} @@ -91,24 +92,22 @@ in { }; defaultMode = mkOption { - description = "systemd service that is enabled by default"; type = types.enum [ "online" "offline" "norouting" ]; default = "online"; + description = "systemd service that is enabled by default"; }; autoMigrate = mkOption { type = types.bool; default = false; - description = '' - Whether IPFS should try to migrate the file system automatically. - ''; + description = "Whether IPFS should try to migrate the file system automatically"; }; - #autoMount = mkOption { - # type = types.bool; - # default = false; - # description = "Whether IPFS should try to mount /ipfs and /ipns at startup."; - #}; + autoMount = mkOption { + type = types.bool; + default = false; + description = "Whether IPFS should try to mount /ipfs and /ipns at startup."; + }; ipfsMountDir = mkOption { type = types.str; @@ -137,26 +136,22 @@ in { enableGC = mkOption { type = types.bool; default = false; - description = '' - Whether to enable automatic garbage collection. - ''; + description = "Whether to enable automatic garbage collection"; }; emptyRepo = mkOption { type = types.bool; default = false; - description = '' - If set to true, the repo won't be initialized with help files - ''; + description = "If set to true, the repo won't be initialized with help files"; }; extraConfig = mkOption { type = types.attrs; - description = toString [ - "Attrset of daemon configuration to set using `ipfs config`, every time the daemon starts." - "These are applied last, so may override configuration set by other options in this module." - "Keep in mind that this configuration is stateful; i.e., unsetting anything in here does not reset the value to the default!" - ]; + description = '' + Attrset of daemon configuration to set using <command>ipfs config</command>, every time the daemon starts. + These are applied last, so may override configuration set by other options in this module. + Keep in mind that this configuration is stateful; i.e., unsetting anything in here does not reset the value to the default! + ''; default = {}; example = { Datastore.StorageMax = "100GB"; @@ -179,10 +174,8 @@ in { serviceFdlimit = mkOption { type = types.nullOr types.int; default = null; - description = '' - The fdlimit for the IPFS systemd unit or `null` to have the daemon attempt to manage it. - ''; - example = 256*1024; + description = "The fdlimit for the IPFS systemd unit or <literal>null</literal> to have the daemon attempt to manage it"; + example = 64*1024; }; }; @@ -192,6 +185,9 @@ in { config = mkIf cfg.enable { environment.systemPackages = [ wrapped ]; + environment.etc."fuse.conf" = mkIf cfg.autoMount { text = '' + user_allow_other + ''; }; users.extraUsers = mkIf (cfg.user == "ipfs") { ipfs = { @@ -211,11 +207,11 @@ in { description = "IPFS Initializer"; after = [ "local-fs.target" ]; - before = [ "ipfs.service" "ipfs-offline.service" ]; + before = [ "ipfs.service" "ipfs-offline.service" "ipfs-norouting.service" ]; preStart = '' install -m 0755 -o ${cfg.user} -g ${cfg.group} -d ${cfg.dataDir} - '' + optionalString false/*cfg.autoMount*/ '' + '' + optionalString cfg.autoMount '' install -m 0755 -o ${cfg.user} -g ${cfg.group} -d ${cfg.ipfsMountDir} install -m 0755 -o ${cfg.user} -g ${cfg.group} -d ${cfg.ipnsMountDir} ''; diff --git a/nixos/modules/services/networking/bind.nix b/nixos/modules/services/networking/bind.nix index 763283dfe7a2..9f533eedf6e1 100644 --- a/nixos/modules/services/networking/bind.nix +++ b/nixos/modules/services/networking/bind.nix @@ -151,6 +151,15 @@ in "; }; + resolveLocalQueries = mkOption { + type = types.bool; + default = true; + description = '' + Whether bind should resolve local queries (i.e. add 127.0.0.1 to + /etc/resolv.conf, overriding networking.nameserver). + ''; + }; + }; }; diff --git a/nixos/modules/services/networking/coturn.nix b/nixos/modules/services/networking/coturn.nix index 65273a4bf939..b3c64490d97e 100644 --- a/nixos/modules/services/networking/coturn.nix +++ b/nixos/modules/services/networking/coturn.nix @@ -307,7 +307,8 @@ in { systemd.services.coturn = { description = "coturn TURN server"; - after = [ "network.target" ]; + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; unitConfig = { diff --git a/nixos/modules/services/networking/dhcpcd.nix b/nixos/modules/services/networking/dhcpcd.nix index cdba14be21f0..d283c7624335 100644 --- a/nixos/modules/services/networking/dhcpcd.nix +++ b/nixos/modules/services/networking/dhcpcd.nix @@ -153,10 +153,14 @@ in config = mkIf enableDHCP { - systemd.services.dhcpcd = + systemd.services.dhcpcd = let + cfgN = config.networking; + hasDefaultGatewaySet = (cfgN.defaultGateway != null && cfgN.defaultGateway.address != "") + || (cfgN.defaultGateway6 != null && cfgN.defaultGateway6.address != ""); + in { description = "DHCP Client"; - wantedBy = [ "network-online.target" ]; + wantedBy = optional (!hasDefaultGatewaySet) "network-online.target"; after = [ "network.target" ]; wants = [ "network.target" ]; diff --git a/nixos/modules/services/networking/dnsmasq.nix b/nixos/modules/services/networking/dnsmasq.nix index fcf5aa5f175b..3d1b931de07e 100644 --- a/nixos/modules/services/networking/dnsmasq.nix +++ b/nixos/modules/services/networking/dnsmasq.nix @@ -42,7 +42,7 @@ in default = true; description = '' Whether dnsmasq should resolve local queries (i.e. add 127.0.0.1 to - /etc/resolv.conf). + /etc/resolv.conf overriding networking.nameservers). ''; }; diff --git a/nixos/modules/services/networking/matterbridge.nix b/nixos/modules/services/networking/matterbridge.nix new file mode 100644 index 000000000000..5526e2ba23ac --- /dev/null +++ b/nixos/modules/services/networking/matterbridge.nix @@ -0,0 +1,96 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + + cfg = config.services.matterbridge; + + matterbridgeConfToml = pkgs.writeText "matterbridge.toml" (cfg.configFile); + +in + +{ + options = { + services.matterbridge = { + enable = mkEnableOption "Matterbridge chat platform bridge"; + + configFile = mkOption { + type = types.str; + example = '' + #WARNING: as this file contains credentials, be sure to set correct file permissions [irc] + [irc.freenode] + Server="irc.freenode.net:6667" + Nick="matterbot" + + [mattermost] + [mattermost.work] + #do not prefix it wit http:// or https:// + Server="yourmattermostserver.domain" + Team="yourteam" + Login="yourlogin" + Password="yourpass" + PrefixMessagesWithNick=true + + [[gateway]] + name="gateway1" + enable=true + [[gateway.inout]] + account="irc.freenode" + channel="#testing" + + [[gateway.inout]] + account="mattermost.work" + channel="off-topic" + ''; + description = '' + The matterbridge configuration file in the TOML file format. + ''; + }; + user = mkOption { + type = types.str; + default = "matterbridge"; + description = '' + User which runs the matterbridge service. + ''; + }; + + group = mkOption { + type = types.str; + default = "matterbridge"; + description = '' + Group which runs the matterbridge service. + ''; + }; + }; + }; + + config = mkMerge [ + (mkIf cfg.enable { + + users.extraUsers = mkIf (cfg.user == "matterbridge") [ + { name = "matterbridge"; + group = "matterbridge"; + } ]; + + users.extraGroups = mkIf (cfg.group == "matterbridge") [ + { name = "matterbridge"; + } ]; + + systemd.services.matterbridge = { + description = "Matterbridge chat platform bridge"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + serviceConfig = { + User = cfg.user; + Group = cfg.group; + ExecStart = "${pkgs.matterbridge.bin}/bin/matterbridge -conf ${matterbridgeConfToml}"; + Restart = "always"; + RestartSec = "10"; + }; + }; + }) + ]; +} + diff --git a/nixos/modules/services/networking/namecoind.nix b/nixos/modules/services/networking/namecoind.nix index 9df9f67cde83..11f7d7e5caef 100644 --- a/nixos/modules/services/networking/namecoind.nix +++ b/nixos/modules/services/networking/namecoind.nix @@ -173,7 +173,7 @@ in serviceConfig = { User = "namecoin"; - Griup = "namecoin"; + Group = "namecoin"; ExecStart = "${pkgs.altcoins.namecoind}/bin/namecoind -conf=${configFile} -datadir=${dataDir} -printtoconsole"; ExecStop = "${pkgs.coreutils}/bin/kill -KILL $MAINPID"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; diff --git a/nixos/modules/services/networking/radicale.nix b/nixos/modules/services/networking/radicale.nix index f1b8edf43713..56f2e976cff5 100644 --- a/nixos/modules/services/networking/radicale.nix +++ b/nixos/modules/services/networking/radicale.nix @@ -48,6 +48,12 @@ in configuration file. ''; }; + + services.radicale.extraArgs = mkOption { + type = types.listOf types.string; + default = []; + description = "Extra arguments passed to the Radicale daemon."; + }; }; config = mkIf cfg.enable { @@ -71,7 +77,11 @@ in after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { - ExecStart = "${cfg.package}/bin/radicale -C ${confFile} -f"; + ExecStart = concatStringsSep " " ([ + "${cfg.package}/bin/radicale" "-C" confFile + ] ++ ( + map escapeShellArg cfg.extraArgs + )); User = "radicale"; Group = "radicale"; }; diff --git a/nixos/modules/services/networking/squid.nix b/nixos/modules/services/networking/squid.nix new file mode 100644 index 000000000000..b220c21b604f --- /dev/null +++ b/nixos/modules/services/networking/squid.nix @@ -0,0 +1,169 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.squid; + + + squidConfig = pkgs.writeText "squid.conf" + (if cfg.configText != null then cfg.configText else + '' + # + # Recommended minimum configuration (3.5): + # + + # Example rule allowing access from your local networks. + # Adapt to list your (internal) IP networks from where browsing + # should be allowed + acl localnet src 10.0.0.0/8 # RFC 1918 possible internal network + acl localnet src 172.16.0.0/12 # RFC 1918 possible internal network + acl localnet src 192.168.0.0/16 # RFC 1918 possible internal network + acl localnet src 169.254.0.0/16 # RFC 3927 link-local (directly plugged) machines + acl localnet src fc00::/7 # RFC 4193 local private network range + acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines + + acl SSL_ports port 443 # https + acl Safe_ports port 80 # http + acl Safe_ports port 21 # ftp + acl Safe_ports port 443 # https + acl Safe_ports port 70 # gopher + acl Safe_ports port 210 # wais + acl Safe_ports port 1025-65535 # unregistered ports + acl Safe_ports port 280 # http-mgmt + acl Safe_ports port 488 # gss-http + acl Safe_ports port 591 # filemaker + acl Safe_ports port 777 # multiling http + acl CONNECT method CONNECT + + # + # Recommended minimum Access Permission configuration: + # + # Deny requests to certain unsafe ports + http_access deny !Safe_ports + + # Deny CONNECT to other than secure SSL ports + http_access deny CONNECT !SSL_ports + + # Only allow cachemgr access from localhost + http_access allow localhost manager + http_access deny manager + + # We strongly recommend the following be uncommented to protect innocent + # web applications running on the proxy server who think the only + # one who can access services on "localhost" is a local user + http_access deny to_localhost + + # Application logs to syslog, access and store logs have specific files + cache_log syslog + access_log stdio:/var/log/squid/access.log + cache_store_log stdio:/var/log/squid/store.log + + # Required by systemd service + pid_filename /run/squid.pid + + # Run as user and group squid + cache_effective_user squid squid + + # + # INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS + # + ${cfg.extraConfig} + + # Example rule allowing access from your local networks. + # Adapt localnet in the ACL section to list your (internal) IP networks + # from where browsing should be allowed + http_access allow localnet + http_access allow localhost + + # And finally deny all other access to this proxy + http_access deny all + + # Squid normally listens to port 3128 + http_port ${toString cfg.proxyPort} + + # Leave coredumps in the first cache dir + coredump_dir /var/cache/squid + + # + # Add any of your own refresh_pattern entries above these. + # + refresh_pattern ^ftp: 1440 20% 10080 + refresh_pattern ^gopher: 1440 0% 1440 + refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 + refresh_pattern . 0 20% 4320 + ''); + +in + +{ + + options = { + + services.squid = { + + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to run squid web proxy."; + }; + + proxyPort = mkOption { + type = types.int; + default = 3128; + description = "TCP port on which squid will listen."; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Squid configuration. Contents will be added + verbatim to the configuration file. + ''; + }; + + configText = mkOption { + type = types.nullOr types.lines; + default = null; + description = '' + Verbatim contents of squid.conf. If null (default), use the + autogenerated file from NixOS instead. + ''; + }; + + }; + + }; + + config = mkIf cfg.enable { + + users.users.squid = { + isSystemUser = true; + group = "squid"; + home = "/var/cache/squid"; + createHome = true; + }; + + users.groups.squid = {}; + + systemd.services.squid = { + description = "Squid caching web proxy"; + after = [ "network.target" "nss-lookup.target" ]; + wantedBy = [ "multi-user.target"]; + preStart = '' + mkdir -p "/var/log/squid" + chown squid:squid "/var/log/squid" + ''; + serviceConfig = { + Type="forking"; + PIDFile="/run/squid.pid"; + PermissionsStartOnly = true; + ExecStart = "${pkgs.squid}/bin/squid -YCs -f ${squidConfig}"; + }; + }; + + }; + +} \ No newline at end of file diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix index 0f58536b4b73..8828429a8178 100644 --- a/nixos/modules/services/networking/ssh/sshd.nix +++ b/nixos/modules/services/networking/ssh/sshd.nix @@ -103,6 +103,15 @@ in ''; }; + sftpFlags = mkOption { + type = with types; listOf str; + default = []; + example = [ "-f AUTHPRIV" "-l INFO" ]; + description = '' + Commandline flags to add to sftp-server. + ''; + }; + permitRootLogin = mkOption { default = "prohibit-password"; type = types.enum ["yes" "without-password" "prohibit-password" "forced-commands-only" "no"]; @@ -208,7 +217,7 @@ in }; moduliFile = mkOption { - example = "services.openssh.moduliFile = /etc/my-local-ssh-moduli;"; + example = "/etc/my-local-ssh-moduli;"; type = types.path; description = '' Path to <literal>moduli</literal> file to install in @@ -338,7 +347,7 @@ in ''} ${optionalString cfg.allowSFTP '' - Subsystem sftp ${cfgc.package}/libexec/sftp-server + Subsystem sftp ${cfgc.package}/libexec/sftp-server ${concatStringsSep " " cfg.sftpFlags} ''} PermitRootLogin ${cfg.permitRootLogin} diff --git a/nixos/modules/services/networking/tinc.nix b/nixos/modules/services/networking/tinc.nix index 7a786b54ccbb..d5db328310c1 100644 --- a/nixos/modules/services/networking/tinc.nix +++ b/nixos/modules/services/networking/tinc.nix @@ -199,8 +199,10 @@ in buildInputs = [ pkgs.makeWrapper ]; buildCommand = '' mkdir -p $out/bin - ${concatStringsSep "\n" (mapAttrsToList (network: data: '' - makeWrapper ${data.package}/bin/tinc "$out/bin/tinc.${network}" --add-flags "--pidfile=/run/tinc.${network}.pid" + ${concatStringsSep "\n" (mapAttrsToList (network: data: + optionalString (versionAtLeast data.package.version "1.1pre") '' + makeWrapper ${data.package}/bin/tinc "$out/bin/tinc.${network}" \ + --add-flags "--pidfile=/run/tinc.${network}.pid" '') cfg.networks)} ''; }; diff --git a/nixos/modules/services/security/hologram-agent.nix b/nixos/modules/services/security/hologram-agent.nix index 49b5c935267b..6c53a2df6306 100644 --- a/nixos/modules/services/security/hologram-agent.nix +++ b/nixos/modules/services/security/hologram-agent.nix @@ -33,6 +33,8 @@ in { }; config = mkIf cfg.enable { + boot.kernelModules = [ "dummy" ]; + networking.interfaces.dummy0 = { ipAddress = "169.254.169.254"; prefixLength = 32; diff --git a/nixos/modules/services/ttys/kmscon.nix b/nixos/modules/services/ttys/kmscon.nix index 8bad42927e3f..88e488425bce 100644 --- a/nixos/modules/services/ttys/kmscon.nix +++ b/nixos/modules/services/ttys/kmscon.nix @@ -60,6 +60,7 @@ in { ConditionPathExists=/dev/tty0 [Service] + ExecStart= ExecStart=${pkgs.kmscon}/bin/kmscon "--vt=%I" ${cfg.extraOptions} --seats=seat0 --no-switchvt --configdir ${configDir} --login -- ${pkgs.shadow}/bin/login -p UtmpIdentifier=%I TTYPath=/dev/%I diff --git a/nixos/modules/system/boot/systemd-unit-options.nix b/nixos/modules/system/boot/systemd-unit-options.nix index 9be10a8283ed..43a9c28bb694 100644 --- a/nixos/modules/system/boot/systemd-unit-options.nix +++ b/nixos/modules/system/boot/systemd-unit-options.nix @@ -35,21 +35,40 @@ in rec { description = '' If set to false, this unit will be a symlink to /dev/null. This is primarily useful to prevent specific - template instances (e.g. <literal>serial-getty@ttyS0</literal>) - from being started. + template instances + (e.g. <literal>serial-getty@ttyS0</literal>) from being + started. Note that <literal>enable=true</literal> does not + make a unit start by default at boot; if you want that, see + <literal>wantedBy</literal>. ''; }; requiredBy = mkOption { default = []; type = types.listOf types.str; - description = "Units that require (i.e. depend on and need to go down with) this unit."; + description = '' + Units that require (i.e. depend on and need to go down with) + this unit. The discussion under <literal>wantedBy</literal> + applies here as well: inverse <literal>.requires</literal> + symlinks are established. + ''; }; wantedBy = mkOption { default = []; type = types.listOf types.str; - description = "Units that want (i.e. depend on) this unit."; + description = '' + Units that want (i.e. depend on) this unit. The standard way + to make a unit start by default at boot is to set this option + to <literal>[ "multi-user.target" ]</literal>. That's despite + the fact that the systemd.unit(5) manpage says this option + goes in the <literal>[Install]</literal> section that controls + the behaviour of <literal>systemctl enable</literal>. Since + such a process is stateful and thus contrary to the design of + NixOS, setting this option instead causes the equivalent + inverse <literal>.wants</literal> symlink to be present, + establishing the same desired relationship in a stateless way. + ''; }; aliases = mkOption { diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix index 1922d2924bc5..6ceb36714b28 100644 --- a/nixos/modules/tasks/filesystems.nix +++ b/nixos/modules/tasks/filesystems.nix @@ -217,7 +217,7 @@ in # Add the mount helpers to the system path so that `mount' can find them. system.fsPackages = [ pkgs.dosfstools ]; - environment.systemPackages = [ pkgs.fuse ] ++ config.system.fsPackages; + environment.systemPackages = with pkgs; [ fuse3 fuse ] ++ config.system.fsPackages; environment.etc.fstab.text = let diff --git a/nixos/modules/tasks/network-interfaces-scripted.nix b/nixos/modules/tasks/network-interfaces-scripted.nix index 15b36cfcb113..adc048f3ca2c 100644 --- a/nixos/modules/tasks/network-interfaces-scripted.nix +++ b/nixos/modules/tasks/network-interfaces-scripted.nix @@ -73,6 +73,9 @@ let then [ "${dev}-netdev.service" ] else optional (dev != null && dev != "lo" && !config.boot.isContainer) (subsystemDevice dev); + hasDefaultGatewaySet = (cfg.defaultGateway != null && cfg.defaultGateway.address != "") + || (cfg.defaultGateway6 != null && cfg.defaultGateway6.address != ""); + networkLocalCommands = { after = [ "network-setup.service" ]; bindsTo = [ "network-setup.service" ]; @@ -85,7 +88,7 @@ let before = [ "network.target" "shutdown.target" ]; wants = [ "network.target" ]; conflicts = [ "shutdown.target" ]; - wantedBy = [ "multi-user.target" ]; + wantedBy = [ "multi-user.target" ] ++ optional hasDefaultGatewaySet "network-online.target"; unitConfig.ConditionCapability = "CAP_NET_ADMIN"; @@ -102,7 +105,7 @@ let '' # Set the static DNS configuration, if given. ${pkgs.openresolv}/sbin/resolvconf -m 1 -a static <<EOF - ${optionalString (cfg.nameservers != [] && cfg.domain != null) '' + ${optionalString (cfg.domain != null) '' domain ${cfg.domain} ''} ${optionalString (cfg.search != []) ("search " + concatStringsSep " " cfg.search)} diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix index a7ceb104b577..f61d80f55991 100644 --- a/nixos/release-combined.nix +++ b/nixos/release-combined.nix @@ -94,9 +94,6 @@ in rec { (all nixos.tests.keymap.neo) (all nixos.tests.keymap.qwertz) nixos.tests.plasma5.x86_64-linux # avoid big build on i686 - (all nixos.tests.kernel-latest) - (all nixos.tests.kernel-lts) - (all nixos.tests.kernel-params) #(all nixos.tests.lightdm) (all nixos.tests.login) (all nixos.tests.misc) @@ -119,7 +116,6 @@ in rec { (all nixos.tests.sddm.default) (all nixos.tests.simple) (all nixos.tests.slim) - nixos.tests.sysctl.x86_64-linux # i686 fails (all nixos.tests.udisks2) (all nixos.tests.xfce) diff --git a/nixos/release.nix b/nixos/release.nix index 38c446c1f8a4..a200535f3f4a 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -236,6 +236,7 @@ in rec { tests.containers-macvlans = callTest tests/containers-macvlans.nix {}; tests.docker = hydraJob (import tests/docker.nix { system = "x86_64-linux"; }); tests.docker-edge = hydraJob (import tests/docker-edge.nix { system = "x86_64-linux"; }); + tests.dovecot = callTest tests/dovecot.nix {}; tests.dnscrypt-proxy = callTest tests/dnscrypt-proxy.nix { system = "x86_64-linux"; }; tests.ecryptfs = callTest tests/ecryptfs.nix {}; tests.etcd = hydraJob (import tests/etcd.nix { system = "x86_64-linux"; }); @@ -253,10 +254,12 @@ in rec { tests.gocd-server = callTest tests/gocd-server.nix {}; tests.gnome3 = callTest tests/gnome3.nix {}; tests.gnome3-gdm = callTest tests/gnome3-gdm.nix {}; + tests.grafama = callTest tests/grafana.nix {}; tests.hardened = callTest tests/hardened.nix { }; tests.hibernate = callTest tests/hibernate.nix {}; tests.hound = callTest tests/hound.nix {}; tests.i3wm = callTest tests/i3wm.nix {}; + tests.initrd-network-ssh = callTest tests/initrd-network-ssh.nix {}; tests.installer = callSubTests tests/installer.nix {}; tests.influxdb = callTest tests/influxdb.nix {}; tests.ipv6 = callTest tests/ipv6.nix {}; @@ -267,7 +270,6 @@ in rec { tests.kernel-copperhead = callTest tests/kernel-copperhead.nix {}; tests.kernel-latest = callTest tests/kernel-latest.nix {}; tests.kernel-lts = callTest tests/kernel-lts.nix {}; - tests.kernel-params = callTest tests/kernel-params.nix {}; tests.keystone = callTest tests/keystone.nix {}; tests.kubernetes = hydraJob (import tests/kubernetes.nix { system = "x86_64-linux"; }); tests.latestKernel.login = callTest tests/login.nix { latestKernel = true; }; @@ -313,7 +315,6 @@ in rec { tests.slim = callTest tests/slim.nix {}; tests.smokeping = callTest tests/smokeping.nix {}; tests.snapper = callTest tests/snapper.nix {}; - tests.sysctl = callTest tests/sysctl.nix {}; tests.taskserver = callTest tests/taskserver.nix {}; tests.tomcat = callTest tests/tomcat.nix {}; tests.udisks2 = callTest tests/udisks2.nix {}; diff --git a/nixos/tests/dovecot.nix b/nixos/tests/dovecot.nix new file mode 100644 index 000000000000..3814855ed8e7 --- /dev/null +++ b/nixos/tests/dovecot.nix @@ -0,0 +1,64 @@ +import ./make-test.nix { + name = "dovecot"; + + machine = { pkgs, ... }: { + imports = [ common/user-account.nix ]; + services.postfix.enable = true; + services.dovecot2.enable = true; + services.dovecot2.protocols = [ "imap" "pop3" ]; + environment.systemPackages = let + sendTestMail = pkgs.writeScriptBin "send-testmail" '' + #!${pkgs.stdenv.shell} + exec sendmail -vt <<MAIL + From: root@localhost + To: alice@localhost + Subject: Very important! + + Hello world! + MAIL + ''; + + testImap = pkgs.writeScriptBin "test-imap" '' + #!${pkgs.python3.interpreter} + import imaplib + + with imaplib.IMAP4('localhost') as imap: + imap.login('alice', 'foobar') + imap.select() + status, refs = imap.search(None, 'ALL') + assert status == 'OK' + assert len(refs) == 1 + status, msg = imap.fetch(refs[0], 'BODY[TEXT]') + assert status == 'OK' + assert msg[0][1].strip() == b'Hello world!' + ''; + + testPop = pkgs.writeScriptBin "test-pop" '' + #!${pkgs.python3.interpreter} + import poplib + + pop = poplib.POP3('localhost') + try: + pop.user('alice') + pop.pass_('foobar') + assert len(pop.list()[1]) == 1 + status, fullmail, size = pop.retr(1) + assert status.startswith(b'+OK ') + body = b"".join(fullmail[fullmail.index(b""):]).strip() + assert body == b'Hello world!' + finally: + pop.quit() + ''; + + in [ sendTestMail testImap testPop ]; + }; + + testScript = '' + $machine->waitForUnit('postfix.service'); + $machine->waitForUnit('dovecot2.service'); + $machine->succeed('send-testmail'); + $machine->waitUntilFails('[ "$(postqueue -p)" != "Mail queue is empty" ]'); + $machine->succeed('test-imap'); + $machine->succeed('test-pop'); + ''; +} diff --git a/nixos/tests/grafana.nix b/nixos/tests/grafana.nix new file mode 100644 index 000000000000..16b8181498a6 --- /dev/null +++ b/nixos/tests/grafana.nix @@ -0,0 +1,25 @@ +import ./make-test.nix ({ lib, ... }: +{ + name = "grafana"; + + meta = with lib.maintainers; { + maintainers = [ willibutz ]; + }; + + machine = { config, pkgs, ... }: { + services.grafana = { + enable = true; + addr = "localhost"; + analytics.reporting.enable = false; + domain = "localhost"; + security.adminUser = "testusername"; + }; + }; + + testScript = '' + $machine->start; + $machine->waitForUnit("grafana.service"); + $machine->waitForOpenPort(3000); + $machine->succeed("curl -sS http://127.0.0.1:3000/"); + ''; +}) diff --git a/nixos/tests/hardened.nix b/nixos/tests/hardened.nix index 1d9a9043e03a..ee7ffe83ba34 100644 --- a/nixos/tests/hardened.nix +++ b/nixos/tests/hardened.nix @@ -32,5 +32,15 @@ import ./make-test.nix ({ pkgs, ...} : { subtest "userns", sub { $machine->fail("unshare --user"); }; + + # Test dmesg restriction + subtest "dmesg", sub { + $machine->fail("su -l alice -c dmesg"); + }; + + # Test access to kcore + subtest "kcore", sub { + $machine->fail("cat /proc/kcore"); + }; ''; }) diff --git a/nixos/tests/initrd-network-ssh.nix b/nixos/tests/initrd-network-ssh.nix new file mode 100644 index 000000000000..596610493921 --- /dev/null +++ b/nixos/tests/initrd-network-ssh.nix @@ -0,0 +1,74 @@ +import ./make-test.nix ({ pkgs, lib, ... }: + +let + keys = pkgs.runCommand "gen-keys" { + outputs = [ "out" "dbPub" "dbPriv" "sshPub" "sshPriv" ]; + buildInputs = with pkgs; [ dropbear openssh ]; + } + '' + touch $out + dropbearkey -t rsa -f $dbPriv -s 4096 | sed -n 2p > $dbPub + ssh-keygen -q -t rsa -b 4096 -N "" -f client + mv client $sshPriv + mv client.pub $sshPub + ''; + +in { + name = "initrd-network-ssh"; + meta = with lib.maintainers; { + maintainers = [ willibutz ]; + }; + + nodes = with lib; rec { + server = + { config, pkgs, ... }: + { + boot.kernelParams = [ + "ip=${ + (head config.networking.interfaces.eth1.ip4).address + }:::255.255.255.0::eth1:none" + ]; + boot.initrd.network = { + enable = true; + ssh = { + enable = true; + authorizedKeys = [ "${readFile keys.sshPub}" ]; + port = 22; + hostRSAKey = keys.dbPriv; + }; + }; + boot.initrd.preLVMCommands = '' + while true; do + if [ -f fnord ]; then + poweroff + fi + sleep 1 + done + ''; + }; + + client = + { config, pkgs, ... }: + { + environment.etc.knownHosts = { + text = concatStrings [ + "server," + "${toString (head (splitString " " ( + toString (elemAt (splitString "\n" config.networking.extraHosts) 2) + )))} " + "${readFile keys.dbPub}" + ]; + }; + }; + }; + + testScript = '' + startAll; + $client->waitForUnit("network.target"); + $client->copyFileFromHost("${keys.sshPriv}","/etc/sshKey"); + $client->succeed("chmod 0600 /etc/sshKey"); + $client->waitUntilSucceeds("ping -c 1 server"); + $client->succeed("ssh -i /etc/sshKey -o UserKnownHostsFile=/etc/knownHosts server 'touch /fnord'"); + $client->shutdown; + ''; +}) diff --git a/nixos/tests/ipfs.nix b/nixos/tests/ipfs.nix index a93f8f175c55..c6bc61545245 100644 --- a/nixos/tests/ipfs.nix +++ b/nixos/tests/ipfs.nix @@ -23,8 +23,7 @@ import ./make-test.nix ({ pkgs, ...} : { services.ipfs = { enable = true; defaultMode = "norouting"; - # not yet. See #28621 - #autoMount = true; + autoMount = true; }; networking.firewall.allowedTCPPorts = [ 4001 ]; }; @@ -51,7 +50,6 @@ import ./make-test.nix ({ pkgs, ...} : { $getter->mustSucceed("ipfs --api /ip4/127.0.0.1/tcp/5001 swarm connect /ip4/$addrIp/tcp/4001/ipfs/$addrId"); $getter->mustSucceed("[ -n \"\$(ipfs --api /ip4/127.0.0.1/tcp/5001 cat /ipfs/$ipfsHash | grep fnord)\" ]"); - # not yet. See #28621 - # $getter->mustSucceed("[ -n \"$(cat /ipfs/$ipfsHash | grep fnord)\" ]"); + $getter->mustSucceed("[ -n \"$(cat /ipfs/$ipfsHash | grep fnord)\" ]"); ''; }) diff --git a/nixos/tests/kernel-params.nix b/nixos/tests/kernel-params.nix deleted file mode 100644 index 14a393356911..000000000000 --- a/nixos/tests/kernel-params.nix +++ /dev/null @@ -1,24 +0,0 @@ -import ./make-test.nix ({ pkgs, ...} : { - name = "kernel-params"; - meta = with pkgs.stdenv.lib.maintainers; { - maintainers = [ nequissimus ]; - }; - - machine = { config, lib, pkgs, ... }: - { - boot.kernelPackages = pkgs.linuxPackages; - boot.kernelParams = [ - "nohibernate" - "page_poison=1" - "vsyscall=none" - ]; - }; - - testScript = - '' - $machine->fail("cat /proc/cmdline | grep page_poison=0"); - $machine->succeed("cat /proc/cmdline | grep nohibernate"); - $machine->succeed("cat /proc/cmdline | grep page_poison=1"); - $machine->succeed("cat /proc/cmdline | grep vsyscall=none"); - ''; -}) diff --git a/nixos/tests/misc.nix b/nixos/tests/misc.nix index 1b24551009c9..79290861cb0b 100644 --- a/nixos/tests/misc.nix +++ b/nixos/tests/misc.nix @@ -25,6 +25,8 @@ import ./make-test.nix ({ pkgs, ...} : { }; users.users.sybil = { isNormalUser = true; group = "wheel"; }; security.sudo = { enable = true; wheelNeedsPassword = false; }; + boot.kernel.sysctl."vm.swappiness" = 1; + boot.kernelParams = [ "vsyscall=emulate" ]; }; testScript = @@ -117,5 +119,18 @@ import ./make-test.nix ({ pkgs, ...} : { subtest "sudo", sub { $machine->succeed("su - sybil -c 'sudo true'"); }; + + # Test sysctl + subtest "sysctl", sub { + $machine->waitForUnit("systemd-sysctl.service"); + $machine->succeed('[ `sysctl -ne vm.swappiness` = 1 ]'); + $machine->execute('sysctl vm.swappiness=60'); + $machine->succeed('[ `sysctl -ne vm.swappiness` = 60 ]'); + }; + + # Test boot parameters + subtest "bootparam", sub { + $machine->succeed('grep -Fq vsyscall=emulate /proc/cmdline'); + }; ''; }) diff --git a/nixos/tests/networking.nix b/nixos/tests/networking.nix index 6a7e628d8ef1..7708775f73f3 100644 --- a/nixos/tests/networking.nix +++ b/nixos/tests/networking.nix @@ -105,7 +105,7 @@ let startAll; $client->waitForUnit("network.target"); - $router->waitForUnit("network.target"); + $router->waitForUnit("network-online.target"); # Make sure dhcpcd is not started $client->fail("systemctl status dhcpcd.service"); @@ -157,7 +157,7 @@ let startAll; $client->waitForUnit("network.target"); - $router->waitForUnit("network.target"); + $router->waitForUnit("network-online.target"); # Wait until we have an ip address on each interface $client->waitUntilSucceeds("ip addr show dev eth1 | grep -q '192.168.1'"); diff --git a/nixos/tests/radicale.nix b/nixos/tests/radicale.nix index bec86d2cb284..2c888469d0a4 100644 --- a/nixos/tests/radicale.nix +++ b/nixos/tests/radicale.nix @@ -2,12 +2,8 @@ let user = "someuser"; password = "some_password"; port = builtins.toString 5232; -in - import ./make-test.nix ({ pkgs, lib, ... }: { - name = "radicale"; - meta.maintainers = with lib.maintainers; [ aneeshusa infinisil ]; - machine = { + common = { pkgs, ... }: { services.radicale = { enable = true; config = '' @@ -29,11 +25,81 @@ in ${pkgs.apacheHttpd}/bin/htpasswd -bcB "$out" ${user} ${password} ''; }; - - # This tests whether the web interface is accessible to an authenticated user - testScript = '' - $machine->waitForUnit('radicale.service'); - $machine->waitForOpenPort(${port}); - $machine->succeed('curl --fail http://${user}:${password}@localhost:${port}/.web/'); - ''; + +in + + import ./make-test.nix ({ pkgs, lib, ... }@args: { + name = "radicale"; + meta.maintainers = with lib.maintainers; [ aneeshusa infinisil ]; + + nodes = rec { + radicale = radicale1; # Make the test script read more nicely + radicale1 = lib.recursiveUpdate (common args) { + nixpkgs.overlays = [ + (self: super: { + radicale1 = super.radicale1.overrideAttrs (oldAttrs: { + propagatedBuildInputs = with self.pythonPackages; + (oldAttrs.propagatedBuildInputs or []) ++ [ passlib ]; + }); + }) + ]; + }; + radicale1_export = lib.recursiveUpdate radicale1 { + services.radicale.extraArgs = [ + "--export-storage" "/tmp/collections-new" + ]; + }; + radicale2_verify = lib.recursiveUpdate radicale2 { + services.radicale.extraArgs = [ "--verify-storage" ]; + }; + radicale2 = lib.recursiveUpdate (common args) { + system.stateVersion = "17.09"; + }; + }; + + # This tests whether the web interface is accessible to an authenticated user + testScript = { nodes }: let + switchToConfig = nodeName: let + newSystem = nodes.${nodeName}.config.system.build.toplevel; + in "${newSystem}/bin/switch-to-configuration test"; + in '' + # Check Radicale 1 functionality + $radicale->succeed('${switchToConfig "radicale1"} >&2'); + $radicale->waitForUnit('radicale.service'); + $radicale->waitForOpenPort(${port}); + $radicale->succeed('curl --fail http://${user}:${password}@localhost:${port}/someuser/calendar.ics/'); + + # Export data in Radicale 2 format + $radicale->succeed('systemctl stop radicale'); + $radicale->succeed('ls -al /tmp/collections'); + $radicale->fail('ls -al /tmp/collections-new'); + # Radicale exits immediately after exporting storage + $radicale->succeed('${switchToConfig "radicale1_export"} >&2'); + $radicale->waitUntilFails('systemctl status radicale'); + $radicale->succeed('ls -al /tmp/collections'); + $radicale->succeed('ls -al /tmp/collections-new'); + + # Verify data in Radicale 2 format + $radicale->succeed('rm -r /tmp/collections/${user}'); + $radicale->succeed('mv /tmp/collections-new/collection-root /tmp/collections'); + $radicale->succeed('${switchToConfig "radicale2_verify"} >&2'); + $radicale->waitUntilFails('systemctl status radicale'); + my ($retcode, $logs) = $radicale->execute('journalctl -u radicale -n 5'); + if ($retcode != 0 || index($logs, 'Verifying storage') == -1) { + die "Radicale 2 didn't verify storage" + } + if (index($logs, 'failed') != -1 || index($logs, 'exception') != -1) { + die "storage verification failed" + } + + # Check Radicale 2 functionality + $radicale->succeed('${switchToConfig "radicale2"} >&2'); + $radicale->waitForUnit('radicale.service'); + $radicale->waitForOpenPort(${port}); + my ($retcode, $output) = $radicale->execute('curl --fail http://${user}:${password}@localhost:${port}/someuser/calendar.ics/'); + if ($retcode != 0 || index($output, 'VCALENDAR') == -1) { + die "Could not read calendar from Radicale 2" + } + $radicale->succeed('curl --fail http://${user}:${password}@localhost:${port}/.web/'); + ''; }) diff --git a/nixos/tests/sysctl.nix b/nixos/tests/sysctl.nix deleted file mode 100644 index d7220cabb22c..000000000000 --- a/nixos/tests/sysctl.nix +++ /dev/null @@ -1,25 +0,0 @@ -import ./make-test.nix ({ pkgs, ...} : { - name = "sysctl"; - meta = with pkgs.stdenv.lib.maintainers; { - maintainers = [ nequissimus ]; - }; - - machine = { config, lib, pkgs, ... }: - { - boot.kernelPackages = pkgs.linuxPackages; - boot.kernel.sysctl = { - "kernel.dmesg_restrict" = true; # Restrict dmesg access - "net.core.bpf_jit_enable" = false; # Turn off bpf JIT - "user.max_user_namespaces" = 0; # Disable user namespaces - "vm.swappiness" = 2; # Low swap usage - }; - }; - - testScript = - '' - $machine->succeed("sysctl kernel.dmesg_restrict | grep 'kernel.dmesg_restrict = 1'"); - $machine->succeed("sysctl net.core.bpf_jit_enable | grep 'net.core.bpf_jit_enable = 0'"); - $machine->succeed("sysctl user.max_user_namespaces | grep 'user.max_user_namespaces = 0'"); - $machine->succeed("sysctl vm.swappiness | grep 'vm.swappiness = 2'"); - ''; -}) diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix index 4f7cb176d96f..a1ab7614871a 100644 --- a/nixos/tests/virtualbox.nix +++ b/nixos/tests/virtualbox.nix @@ -461,11 +461,11 @@ in mapAttrs mkVBoxTest { my $test1IP = waitForIP_test1 1; my $test2IP = waitForIP_test2 1; - $machine->succeed("echo '$test2IP' | nc '$test1IP' 1234"); - $machine->succeed("echo '$test1IP' | nc '$test2IP' 1234"); + $machine->succeed("echo '$test2IP' | nc -N '$test1IP' 1234"); + $machine->succeed("echo '$test1IP' | nc -N '$test2IP' 1234"); - $machine->waitUntilSucceeds("nc '$test1IP' 5678 >&2"); - $machine->waitUntilSucceeds("nc '$test2IP' 5678 >&2"); + $machine->waitUntilSucceeds("nc -N '$test1IP' 5678 < /dev/null >&2"); + $machine->waitUntilSucceeds("nc -N '$test2IP' 5678 < /dev/null >&2"); shutdownVM_test1; shutdownVM_test2; |