diff options
Diffstat (limited to 'nixos')
108 files changed, 2009 insertions, 870 deletions
diff --git a/nixos/doc/manual/administration/declarative-containers.xml b/nixos/doc/manual/administration/declarative-containers.xml index 2a98fb126231..d03dbc4d7055 100644 --- a/nixos/doc/manual/administration/declarative-containers.xml +++ b/nixos/doc/manual/administration/declarative-containers.xml @@ -15,7 +15,7 @@ containers.database = { config = { config, pkgs, ... }: { <xref linkend="opt-services.postgresql.enable"/> = true; - <xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql96; + <xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql_9_6; }; }; </programlisting> diff --git a/nixos/doc/manual/configuration/config-file.xml b/nixos/doc/manual/configuration/config-file.xml index 8a1a39c98c10..c77cfe137baa 100644 --- a/nixos/doc/manual/configuration/config-file.xml +++ b/nixos/doc/manual/configuration/config-file.xml @@ -197,10 +197,10 @@ swapDevices = [ { device = "/dev/disk/by-label/swap"; } ]; pkgs.emacs ]; -<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql90; +<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql_10; </programlisting> The latter option definition changes the default PostgreSQL package used - by NixOS’s PostgreSQL service to 9.0. For more information on packages, + by NixOS’s PostgreSQL service to 10.x. For more information on packages, including how to add new ones, see <xref linkend="sec-custom-packages"/>. </para> </listitem> diff --git a/nixos/doc/manual/configuration/firewall.xml b/nixos/doc/manual/configuration/firewall.xml index b66adcedce6e..47a19ac82c0f 100644 --- a/nixos/doc/manual/configuration/firewall.xml +++ b/nixos/doc/manual/configuration/firewall.xml @@ -34,13 +34,4 @@ Similarly, UDP port ranges can be opened through <xref linkend="opt-networking.firewall.allowedUDPPortRanges"/>. </para> - - <para> - Also of interest is -<programlisting> -<xref linkend="opt-networking.firewall.allowPing"/> = true; -</programlisting> - to allow the machine to respond to ping requests. (ICMPv6 pings are always - allowed.) - </para> </section> diff --git a/nixos/doc/manual/release-notes/rl-1809.xml b/nixos/doc/manual/release-notes/rl-1809.xml index 0ddf40acbfcc..8715a05f508b 100644 --- a/nixos/doc/manual/release-notes/rl-1809.xml +++ b/nixos/doc/manual/release-notes/rl-1809.xml @@ -637,6 +637,11 @@ $ nix-instantiate -E '(import <nixpkgsunstable> {}).gitFull' anyways for clarity. </para> </listitem> + <listitem> + <para> + Groups <literal>kvm</literal> and <literal>render</literal> are introduced now, as systemd requires them. + </para> + </listitem> </itemizedlist> </section> diff --git a/nixos/doc/manual/release-notes/rl-1903.xml b/nixos/doc/manual/release-notes/rl-1903.xml index 29520a0188db..6121d32346cb 100644 --- a/nixos/doc/manual/release-notes/rl-1903.xml +++ b/nixos/doc/manual/release-notes/rl-1903.xml @@ -132,6 +132,56 @@ the Python 2 or 3 version of the package. </para> </listitem> + <listitem> + <para> + Options + <literal>services.znc.confOptions.networks.<replaceable>name</replaceable>.userName</literal> and + <literal>services.znc.confOptions.networks.<replaceable>name</replaceable>.modulePackages</literal> + were removed. They were never used for anything and can therefore safely be removed. + </para> + </listitem> + <listitem> + <para> + Package <literal>wasm</literal> has been renamed <literal>proglodyte-wasm</literal>. The package + <literal>wasm</literal> will be pointed to <literal>ocamlPackages.wasm</literal> in 19.09, so + make sure to update your configuration if you want to keep <literal>proglodyte-wasm</literal> + </para> + </listitem> + <listitem> + <para> + OpenSMTPD has been upgraded to version 6.4.0p1. This release makes + backwards-incompatible changes to the configuration file format. See + <command>man smtpd.conf</command> for more information on the new file + format. + </para> + </listitem> + <listitem> + <para> + The versioned <varname>postgresql</varname> have been renamed to use + underscore number seperators. For example, <varname>postgresql96</varname> + has been renamed to <varname>postgresql_9_6</varname>. + </para> + </listitem> + <listitem> + <para> + Slurm introduces the new option + <literal>services.slurm.stateSaveLocation</literal>, + which is now set to <literal>/var/spool/slurm</literal> by default + (instead of <literal>/var/spool</literal>). + Make sure to move all files to the new directory or to set the option accordingly. + </para> + <para> + The slurmctld now runs as user <literal>slurm</literal> instead of <literal>root</literal>. + If you want to keep slurmctld running as <literal>root</literal>, set + <literal>services.slurm.user = root</literal>. + </para> + <para> + The options <literal>services.slurm.nodeName</literal> and + <literal>services.slurm.partitionName</literal> are now sets of + strings to correctly reflect that fact that each of these + options can occour more than once in the configuration. + </para> + </listitem> </itemizedlist> </section> @@ -150,6 +200,15 @@ Matomo version. </para> </listitem> + <listitem> + <para> + The deprecated <literal>truecrypt</literal> package has been removed + and <literal>truecrypt</literal> attribute is now an alias for + <literal>veracrypt</literal>. VeraCrypt is backward-compatible with + TrueCrypt volumes. Note that <literal>cryptsetup</literal> also + supports loading TrueCrypt volumes. + </para> + </listitem> </itemizedlist> </section> </section> diff --git a/nixos/lib/eval-config.nix b/nixos/lib/eval-config.nix index f71e264c3478..5f05b037bdde 100644 --- a/nixos/lib/eval-config.nix +++ b/nixos/lib/eval-config.nix @@ -53,7 +53,8 @@ in rec { inherit prefix check; modules = modules ++ extraModules ++ baseModules ++ [ pkgsModule ]; args = extraArgs; - specialArgs = { modulesPath = ../modules; } // specialArgs; + specialArgs = + { modulesPath = builtins.toString ../modules; } // specialArgs; }) config options; # These are the extra arguments passed to every module. In diff --git a/nixos/lib/test-driver/Machine.pm b/nixos/lib/test-driver/Machine.pm index a00fe25c2b8e..abcc1c50d4d8 100644 --- a/nixos/lib/test-driver/Machine.pm +++ b/nixos/lib/test-driver/Machine.pm @@ -250,7 +250,8 @@ sub connect { $self->start; local $SIG{ALRM} = sub { die "timed out waiting for the VM to connect\n"; }; - alarm 300; + # 50 minutes -- increased as a test, see #49441 + alarm 3000; readline $self->{socket} or die "the VM quit before connecting\n"; alarm 0; diff --git a/nixos/modules/config/networking.nix b/nixos/modules/config/networking.nix index 1ef5313d3fdd..627cce67e97d 100644 --- a/nixos/modules/config/networking.nix +++ b/nixos/modules/config/networking.nix @@ -16,6 +16,13 @@ let resolvconfOptions = cfg.resolvconfOptions ++ optional cfg.dnsSingleRequest "single-request" ++ optional cfg.dnsExtensionMechanism "edns0"; + + + localhostMapped4 = cfg.hosts ? "127.0.0.1" && elem "localhost" cfg.hosts."127.0.0.1"; + localhostMapped6 = cfg.hosts ? "::1" && elem "localhost" cfg.hosts."::1"; + + localhostMultiple = any (elem "localhost") (attrValues (removeAttrs cfg.hosts [ "127.0.0.1" "::1" ])); + in { @@ -23,8 +30,7 @@ in options = { networking.hosts = lib.mkOption { - type = types.attrsOf ( types.listOf types.str ); - default = {}; + type = types.attrsOf (types.listOf types.str); example = literalExample '' { "127.0.0.1" = [ "foo.bar.baz" ]; @@ -192,6 +198,29 @@ in config = { + assertions = [{ + assertion = localhostMapped4; + message = ''`networking.hosts` doesn't map "127.0.0.1" to "localhost"''; + } { + assertion = !cfg.enableIPv6 || localhostMapped6; + message = ''`networking.hosts` doesn't map "::1" to "localhost"''; + } { + assertion = !localhostMultiple; + message = '' + `networking.hosts` maps "localhost" to something other than "127.0.0.1" + or "::1". This will break some applications. Please use + `networking.extraHosts` if you really want to add such a mapping. + ''; + }]; + + networking.hosts = { + "127.0.0.1" = [ "localhost" ]; + } // optionalAttrs (cfg.hostName != "") { + "127.0.1.1" = [ cfg.hostName ]; + } // optionalAttrs cfg.enableIPv6 { + "::1" = [ "localhost" ]; + }; + environment.etc = { # /etc/services: TCP/UDP port assignments. "services".source = pkgs.iana-etc + "/etc/services"; @@ -199,29 +228,14 @@ in # /etc/protocols: IP protocol numbers. "protocols".source = pkgs.iana-etc + "/etc/protocols"; - # /etc/rpc: RPC program numbers. - "rpc".source = pkgs.glibc.out + "/etc/rpc"; - # /etc/hosts: Hostname-to-IP mappings. - "hosts".text = - let oneToString = set : ip : ip + " " + concatStringsSep " " ( getAttr ip set ); - allToString = set : concatMapStringsSep "\n" ( oneToString set ) ( attrNames set ); - userLocalHosts = optionalString - ( builtins.hasAttr "127.0.0.1" cfg.hosts ) - ( concatStringsSep " " ( remove "localhost" cfg.hosts."127.0.0.1" )); - userLocalHosts6 = optionalString - ( builtins.hasAttr "::1" cfg.hosts ) - ( concatStringsSep " " ( remove "localhost" cfg.hosts."::1" )); - otherHosts = allToString ( removeAttrs cfg.hosts [ "127.0.0.1" "::1" ]); - in - '' - 127.0.0.1 ${userLocalHosts} localhost - ${optionalString cfg.enableIPv6 '' - ::1 ${userLocalHosts6} localhost - ''} - ${otherHosts} - ${cfg.extraHosts} - ''; + "hosts".text = let + oneToString = set: ip: ip + " " + concatStringsSep " " set.${ip}; + allToString = set: concatMapStringsSep "\n" (oneToString set) (attrNames set); + in '' + ${allToString cfg.hosts} + ${cfg.extraHosts} + ''; # /etc/host.conf: resolver configuration file "host.conf".text = cfg.hostConf; @@ -251,6 +265,9 @@ in "resolv.conf".source = "${pkgs.systemd}/lib/systemd/resolv.conf"; } // optionalAttrs (config.services.resolved.enable && dnsmasqResolve) { "dnsmasq-resolv.conf".source = "/run/systemd/resolve/resolv.conf"; + } // optionalAttrs (pkgs.stdenv.hostPlatform.libc == "glibc") { + # /etc/rpc: RPC program numbers. + "rpc".source = pkgs.glibc.out + "/etc/rpc"; }; networking.proxy.envVars = @@ -296,4 +313,4 @@ in }; - } +} diff --git a/nixos/modules/config/pulseaudio.nix b/nixos/modules/config/pulseaudio.nix index e16a021ec20b..d4aa59506295 100644 --- a/nixos/modules/config/pulseaudio.nix +++ b/nixos/modules/config/pulseaudio.nix @@ -154,6 +154,18 @@ in { ''; }; + extraModules = mkOption { + type = types.listOf types.package; + default = []; + example = literalExample "[ pkgs.pulseaudio-modules-bt ]"; + description = '' + Extra pulseaudio modules to use. This is intended for out-of-tree + pulseaudio modules like extra bluetooth codecs. + + Extra modules take precedence over built-in pulseaudio modules. + ''; + }; + daemon = { logLevel = mkOption { type = types.str; @@ -236,6 +248,18 @@ in { systemd.packages = [ overriddenPackage ]; }) + (mkIf (cfg.extraModules != []) { + hardware.pulseaudio.daemon.config.dl-search-path = let + overriddenModules = builtins.map + (drv: drv.override { pulseaudio = overriddenPackage; }) + cfg.extraModules; + modulePaths = builtins.map + (drv: "${drv}/lib/pulse-${overriddenPackage.version}/modules") + # User-provided extra modules take precedence + (overriddenModules ++ [ overriddenPackage ]); + in lib.concatStringsSep ":" modulePaths; + }) + (mkIf hasZeroconf { services.avahi.enable = true; }) diff --git a/nixos/modules/config/system-path.nix b/nixos/modules/config/system-path.nix index c07e19bd03c4..1793dc628edf 100644 --- a/nixos/modules/config/system-path.nix +++ b/nixos/modules/config/system-path.nix @@ -19,7 +19,9 @@ let pkgs.diffutils pkgs.findutils pkgs.gawk - pkgs.glibc # for ldd, getent + pkgs.stdenv.cc.libc + pkgs.getent + pkgs.getconf pkgs.gnugrep pkgs.gnupatch pkgs.gnused diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix index 426e1666a814..137ee243813d 100644 --- a/nixos/modules/config/users-groups.nix +++ b/nixos/modules/config/users-groups.nix @@ -266,7 +266,7 @@ let (mkIf config.isNormalUser { group = mkDefault "users"; createHome = mkDefault true; - home = mkDefault "/home/${name}"; + home = mkDefault "/home/${config.name}"; useDefaultShell = mkDefault true; isSystemUser = mkDefault false; }) diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix index 6944d1a4f76b..f8524ab99e8a 100644 --- a/nixos/modules/hardware/video/nvidia.nix +++ b/nixos/modules/hardware/video/nvidia.nix @@ -1,6 +1,6 @@ # This module provides the proprietary NVIDIA X11 / OpenGL drivers. -{ config, lib, pkgs, pkgs_i686, ... }: +{ stdenv, config, lib, pkgs, pkgs_i686, ... }: with lib; @@ -23,7 +23,11 @@ let else null; nvidia_x11 = nvidiaForKernel config.boot.kernelPackages; - nvidia_libs32 = (nvidiaForKernel pkgs_i686.linuxPackages).override { libsOnly = true; kernel = null; }; + nvidia_libs32 = + if versionOlder nvidia_x11.version "391" then + ((nvidiaForKernel pkgs_i686.linuxPackages).override { libsOnly = true; kernel = null; }).out + else + (nvidiaForKernel config.boot.kernelPackages).lib32; enabled = nvidia_x11 != null; @@ -98,7 +102,7 @@ in assertions = [ { assertion = config.services.xserver.displayManager.gdm.wayland; - message = "NVidia drivers don't support wayland"; + message = "NVIDIA drivers don't support wayland"; } { assertion = !optimusCfg.enable || @@ -161,7 +165,7 @@ in }; hardware.opengl.package = nvidia_x11.out; - hardware.opengl.package32 = nvidia_libs32.out; + hardware.opengl.package32 = nvidia_libs32; environment.systemPackages = [ nvidia_x11.bin nvidia_x11.settings ] ++ lib.filter (p: p != null) [ nvidia_x11.persistenced ]; diff --git a/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix b/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix index 3dc0f606bf60..bcdbffdc20b7 100644 --- a/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix +++ b/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix @@ -7,4 +7,6 @@ imports = [ ./installation-cd-base.nix ]; + + fonts.fontconfig.enable = false; } diff --git a/nixos/modules/installer/virtualbox-demo.nix b/nixos/modules/installer/virtualbox-demo.nix index 8ca3592f3800..2e1b4b3998b5 100644 --- a/nixos/modules/installer/virtualbox-demo.nix +++ b/nixos/modules/installer/virtualbox-demo.nix @@ -22,4 +22,42 @@ with lib; powerManagement.enable = false; system.stateVersion = mkDefault "18.03"; + + installer.cloneConfigExtra = '' + # Let demo build as a trusted user. + # nix.trustedUsers = [ "demo" ]; + + # Mount a VirtualBox shared folder. + # This is configurable in the VirtualBox menu at + # Machine / Settings / Shared Folders. + # fileSystems."/mnt" = { + # fsType = "vboxsf"; + # device = "nameofdevicetomount"; + # options = [ "rw" ]; + # }; + + # By default, the NixOS VirtualBox demo image includes SDDM and Plasma. + # If you prefer another desktop manager or display manager, you may want + # to disable the default. + # services.xserver.desktopManager.plasma5.enable = lib.mkForce false; + # services.xserver.displayManager.sddm.enable = lib.mkForce false; + + # Enable GDM/GNOME by uncommenting above two lines and two lines below. + # services.xserver.displayManager.gdm.enable = true; + # services.xserver.desktopManager.gnome3.enable = true; + + # Set your time zone. + # time.timeZone = "Europe/Amsterdam"; + + # List packages installed in system profile. To search, run: + # \$ nix search wget + # environment.systemPackages = with pkgs; [ + # wget vim + # ]; + + # Enable the OpenSSH daemon. + # services.openssh.enable = true; + + system.stateVersion = mkDefault "18.03"; + ''; } diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index 0b4ed6d3b628..16737efb1856 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -331,6 +331,8 @@ zeronet = 304; lirc = 305; lidarr = 306; + slurm = 307; + kapacitor = 308; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -385,7 +387,7 @@ virtuoso = 44; #rtkit = 45; # unused dovecot2 = 46; - #dovenull = 47; # unused + dovenull2 = 47; prayer = 49; mpd = 50; clamav = 51; @@ -622,6 +624,8 @@ zeronet = 304; lirc = 305; lidarr = 306; + slurm = 307; + kapacitor = 308; # When adding a gid, make sure it doesn't match an existing # uid. Users and groups with the same name should have equal diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index f55c32fa511d..37e90232da2a 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -108,7 +108,6 @@ ./programs/oblogout.nix ./programs/plotinus.nix ./programs/qt5ct.nix - ./programs/rootston.nix ./programs/screen.nix ./programs/sedutil.nix ./programs/slock.nix @@ -121,11 +120,13 @@ ./programs/sysdig.nix ./programs/systemtap.nix ./programs/sway.nix + ./programs/sway-beta.nix ./programs/thefuck.nix ./programs/tmux.nix ./programs/udevil.nix ./programs/venus.nix ./programs/vim.nix + ./programs/wavemon.nix ./programs/way-cooler.nix ./programs/wireshark.nix ./programs/xfs_quota.nix @@ -149,6 +150,7 @@ ./security/duosec.nix ./security/hidepid.nix ./security/lock-kernel-modules.nix + ./security/misc.nix ./security/oath.nix ./security/pam.nix ./security/pam_usb.nix @@ -233,6 +235,7 @@ ./services/desktops/dleyna-server.nix ./services/desktops/flatpak.nix ./services/desktops/geoclue2.nix + ./services/desktops/gsignond.nix ./services/desktops/pipewire.nix ./services/desktops/gnome3/at-spi2-core.nix ./services/desktops/gnome3/chrome-gnome-shell.nix @@ -430,6 +433,7 @@ ./services/monitoring/hdaps.nix ./services/monitoring/heapster.nix ./services/monitoring/incron.nix + ./services/monitoring/kapacitor.nix ./services/monitoring/longview.nix ./services/monitoring/monit.nix ./services/monitoring/munin.nix @@ -503,6 +507,7 @@ ./services/networking/dnsmasq.nix ./services/networking/ejabberd.nix ./services/networking/epmd.nix + ./services/networking/eternal-terminal.nix ./services/networking/fakeroute.nix ./services/networking/ferm.nix ./services/networking/firefox/sync-server.nix @@ -634,7 +639,7 @@ ./services/networking/zerobin.nix ./services/networking/zeronet.nix ./services/networking/zerotierone.nix - ./services/networking/znc.nix + ./services/networking/znc/default.nix ./services/printing/cupsd.nix ./services/scheduling/atd.nix ./services/scheduling/chronos.nix diff --git a/nixos/modules/profiles/base.nix b/nixos/modules/profiles/base.nix index 5aaffa4f1f2a..7e14b0e21143 100644 --- a/nixos/modules/profiles/base.nix +++ b/nixos/modules/profiles/base.nix @@ -7,7 +7,7 @@ # Include some utilities that are useful for installing or repairing # the system. environment.systemPackages = [ - pkgs.w3m-nox # needed for the manual anyway + pkgs.w3m-nographics # needed for the manual anyway pkgs.testdisk # useful for repairing boot problems pkgs.ms-sys # for writing Microsoft boot sectors / MBRs pkgs.efibootmgr @@ -19,6 +19,9 @@ pkgs.cryptsetup # needed for dm-crypt volumes pkgs.mkpasswd # for generating password files + # Some text editors. + pkgs.vim + # Some networking tools. pkgs.fuse pkgs.fuse3 diff --git a/nixos/modules/profiles/clone-config.nix b/nixos/modules/profiles/clone-config.nix index 99d4774584f1..3f669ba7d2e1 100644 --- a/nixos/modules/profiles/clone-config.nix +++ b/nixos/modules/profiles/clone-config.nix @@ -48,6 +48,8 @@ let { imports = [ ${toString config.installer.cloneConfigIncludes} ]; + + ${config.installer.cloneConfigExtra} } ''; @@ -73,6 +75,13 @@ in ''; }; + installer.cloneConfigExtra = mkOption { + default = ""; + description = '' + Extra text to include in the cloned configuration.nix included in this + installer. + ''; + }; }; config = { diff --git a/nixos/modules/profiles/hardened.nix b/nixos/modules/profiles/hardened.nix index 38c5a42ba6fb..d712fb2514b1 100644 --- a/nixos/modules/profiles/hardened.nix +++ b/nixos/modules/profiles/hardened.nix @@ -16,6 +16,8 @@ with lib; security.lockKernelModules = mkDefault true; + security.allowUserNamespaces = mkDefault false; + security.apparmor.enable = mkDefault true; boot.kernelParams = [ @@ -59,18 +61,6 @@ with lib; # ... or at least apply some hardening to it boot.kernel.sysctl."net.core.bpf_jit_harden" = mkDefault true; - # A recurring problem with user namespaces is that there are - # still code paths where the kernel's permission checking logic - # fails to account for namespacing, instead permitting a - # namespaced process to act outside the namespace with the - # same privileges as it would have inside it. This is particularly - # bad in the common case of running as root within the namespace. - # - # Setting the number of allowed user namespaces to 0 effectively disables - # the feature at runtime. Attempting to create a user namespace - # with unshare will then fail with "no space left on device". - boot.kernel.sysctl."user.max_user_namespaces" = mkDefault 0; - # Raise ASLR entropy for 64bit & 32bit, respectively. # # Note: mmap_rnd_compat_bits may not exist on 64bit. diff --git a/nixos/modules/profiles/installation-device.nix b/nixos/modules/profiles/installation-device.nix index d51ed195580d..580ea4a58e5b 100644 --- a/nixos/modules/profiles/installation-device.nix +++ b/nixos/modules/profiles/installation-device.nix @@ -63,7 +63,7 @@ with lib; # Tell the Nix evaluator to garbage collect more aggressively. # This is desirable in memory-constrained environments that don't # (yet) have swap set up. - environment.variables.GC_INITIAL_HEAP_SIZE = "100000"; + environment.variables.GC_INITIAL_HEAP_SIZE = "1M"; # Make the installer more likely to succeed in low memory # environments. The kernel's overcommit heustistics bite us @@ -87,9 +87,6 @@ with lib; # console less cumbersome if the machine has a public IP. networking.firewall.logRefusedConnections = mkDefault false; - environment.systemPackages = [ pkgs.vim ]; - - # Allow the user to log in as root without a password. users.users.root.initialHashedPassword = ""; }; diff --git a/nixos/modules/programs/rootston.nix b/nixos/modules/programs/rootston.nix deleted file mode 100644 index 842d9e6cfb48..000000000000 --- a/nixos/modules/programs/rootston.nix +++ /dev/null @@ -1,103 +0,0 @@ -{ config, pkgs, lib, ... }: - -with lib; - -let - cfg = config.programs.rootston; - - rootstonWrapped = pkgs.writeScriptBin "rootston" '' - #! ${pkgs.runtimeShell} - if [[ "$#" -ge 1 ]]; then - exec ${pkgs.rootston}/bin/rootston "$@" - else - ${cfg.extraSessionCommands} - exec ${pkgs.rootston}/bin/rootston -C ${cfg.configFile} - fi - ''; -in { - options.programs.rootston = { - enable = mkEnableOption '' - rootston, the reference compositor for wlroots. The purpose of rootston - is to test and demonstrate the features of wlroots (if you want a real - Wayland compositor you should e.g. use Sway instead). You can manually - start the compositor by running "rootston" from a terminal''; - - extraSessionCommands = mkOption { - type = types.lines; - default = ""; - example = '' - # Define a keymap (US QWERTY is the default) - export XKB_DEFAULT_LAYOUT=de,us - export XKB_DEFAULT_VARIANT=nodeadkeys - export XKB_DEFAULT_OPTIONS=grp:alt_shift_toggle,caps:escape - ''; - description = '' - Shell commands executed just before rootston is started. - ''; - }; - - extraPackages = mkOption { - type = with types; listOf package; - default = with pkgs; [ - westonLite xwayland rofi - ]; - defaultText = literalExample '' - with pkgs; [ - westonLite xwayland rofi - ] - ''; - example = literalExample "[ ]"; - description = '' - Extra packages to be installed system wide. - ''; - }; - - config = mkOption { - type = types.str; - default = '' - [keyboard] - meta-key = Logo - - # Sway/i3 like Keybindings - # Maps key combinations with commands to execute - # Commands include: - # - "exit" to stop the compositor - # - "exec" to execute a shell command - # - "close" to close the current view - # - "next_window" to cycle through windows - [bindings] - Logo+Shift+e = exit - Logo+q = close - Logo+m = maximize - Alt+Tab = next_window - Logo+Return = exec weston-terminal - Logo+d = exec rofi -show run - ''; - description = '' - Default configuration for rootston (used when called without any - parameters). - ''; - }; - - configFile = mkOption { - type = types.path; - default = "/etc/rootston.ini"; - example = literalExample "${pkgs.rootston}/etc/rootston.ini"; - description = '' - Path to the default rootston configuration file (the "config" option - will have no effect if you change the path). - ''; - }; - }; - - config = mkIf cfg.enable { - environment.etc."rootston.ini".text = cfg.config; - environment.systemPackages = [ rootstonWrapped ] ++ cfg.extraPackages; - - hardware.opengl.enable = mkDefault true; - fonts.enableDefaultFonts = mkDefault true; - programs.dconf.enable = mkDefault true; - }; - - meta.maintainers = with lib.maintainers; [ primeos gnidorah ]; -} diff --git a/nixos/modules/programs/shell.nix b/nixos/modules/programs/shell.nix index 6aa0262e3a4c..9842e2bef643 100644 --- a/nixos/modules/programs/shell.nix +++ b/nixos/modules/programs/shell.nix @@ -13,7 +13,7 @@ with lib; # Set up the per-user profile. mkdir -m 0755 -p "$NIX_USER_PROFILE_DIR" if [ "$(stat --printf '%u' "$NIX_USER_PROFILE_DIR")" != "$(id -u)" ]; then - echo "WARNING: bad ownership on $NIX_USER_PROFILE_DIR, should be $(id -u)" >&2 + echo "WARNING: the per-user profile dir $NIX_USER_PROFILE_DIR should belong to user id $(id -u)" >&2 fi if [ -w "$HOME" ]; then @@ -35,7 +35,7 @@ with lib; NIX_USER_GCROOTS_DIR="/nix/var/nix/gcroots/per-user/$USER" mkdir -m 0755 -p "$NIX_USER_GCROOTS_DIR" if [ "$(stat --printf '%u' "$NIX_USER_GCROOTS_DIR")" != "$(id -u)" ]; then - echo "WARNING: bad ownership on $NIX_USER_GCROOTS_DIR, should be $(id -u)" >&2 + echo "WARNING: the per-user gcroots dir $NIX_USER_GCROOTS_DIR should belong to user id $(id -u)" >&2 fi # Set up a default Nix expression from which to install stuff. diff --git a/nixos/modules/programs/sway-beta.nix b/nixos/modules/programs/sway-beta.nix new file mode 100644 index 000000000000..04f2e0662b86 --- /dev/null +++ b/nixos/modules/programs/sway-beta.nix @@ -0,0 +1,54 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.programs.sway-beta; + swayPackage = cfg.package; +in { + options.programs.sway-beta = { + enable = mkEnableOption '' + Sway, the i3-compatible tiling Wayland compositor. This module will be removed after the final release of Sway 1.0 + ''; + + package = mkOption { + type = types.package; + default = pkgs.sway-beta; + defaultText = "pkgs.sway-beta"; + description = '' + The package to be used for `sway`. + ''; + }; + + extraPackages = mkOption { + type = with types; listOf package; + default = with pkgs; [ + xwayland dmenu + ]; + defaultText = literalExample '' + with pkgs; [ xwayland dmenu ]; + ''; + example = literalExample '' + with pkgs; [ + xwayland + i3status i3status-rust + termite rofi light + ] + ''; + description = '' + Extra packages to be installed system wide. + ''; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ swayPackage ] ++ cfg.extraPackages; + security.pam.services.swaylock = {}; + hardware.opengl.enable = mkDefault true; + fonts.enableDefaultFonts = mkDefault true; + programs.dconf.enable = mkDefault true; + }; + + meta.maintainers = with lib.maintainers; [ gnidorah primeos colemickens ]; +} + diff --git a/nixos/modules/programs/wavemon.nix b/nixos/modules/programs/wavemon.nix new file mode 100644 index 000000000000..ac665fe4a023 --- /dev/null +++ b/nixos/modules/programs/wavemon.nix @@ -0,0 +1,28 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.wavemon; +in { + options = { + programs.wavemon = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to add wavemon to the global environment and configure a + setcap wrapper for it. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = with pkgs; [ wavemon ]; + security.wrappers.wavemon = { + source = "${pkgs.wavemon}/bin/wavemon"; + capabilities = "cap_net_admin+ep"; + }; + }; +} diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix index eb74b9bcac12..aa2b5c0b2dfb 100644 --- a/nixos/modules/rename.nix +++ b/nixos/modules/rename.nix @@ -28,7 +28,10 @@ with lib; (config: let enabled = getAttrFromPath [ "services" "printing" "gutenprint" ] config; in if enabled then [ pkgs.gutenprint ] else [ ])) - (mkRenamedOptionModule [ "services" "ddclient" "domain" ] [ "services" "ddclient" "domains" ]) + (mkChangedOptionModule [ "services" "ddclient" "domain" ] [ "services" "ddclient" "domains" ] + (config: + let value = getAttrFromPath [ "services" "ddclient" "domain" ] config; + in if value != "" then [ value ] else [])) (mkRemovedOptionModule [ "services" "ddclient" "homeDir" ] "") (mkRenamedOptionModule [ "services" "elasticsearch" "host" ] [ "services" "elasticsearch" "listenAddress" ]) (mkRenamedOptionModule [ "services" "graphite" "api" "host" ] [ "services" "graphite" "api" "listenAddress" ]) diff --git a/nixos/modules/security/apparmor-suid.nix b/nixos/modules/security/apparmor-suid.nix index dfbf5d859ba9..498c2f25d1c0 100644 --- a/nixos/modules/security/apparmor-suid.nix +++ b/nixos/modules/security/apparmor-suid.nix @@ -28,7 +28,7 @@ with lib; capability setuid, network inet raw, - ${pkgs.glibc.out}/lib/*.so mr, + ${pkgs.stdenv.cc.libc.out}/lib/*.so mr, ${pkgs.libcap.lib}/lib/libcap.so* mr, ${pkgs.attr.out}/lib/libattr.so* mr, diff --git a/nixos/modules/security/dhparams.nix b/nixos/modules/security/dhparams.nix index e2b84c3e3b38..62a499ea624d 100644 --- a/nixos/modules/security/dhparams.nix +++ b/nixos/modules/security/dhparams.nix @@ -170,4 +170,6 @@ in { ''; }) cfg.params; }; + + meta.maintainers = with lib.maintainers; [ ekleog ]; } diff --git a/nixos/modules/security/misc.nix b/nixos/modules/security/misc.nix new file mode 100644 index 000000000000..42f872b7b088 --- /dev/null +++ b/nixos/modules/security/misc.nix @@ -0,0 +1,39 @@ +{ config, lib, ... }: + +with lib; + +{ + meta = { + maintainers = [ maintainers.joachifm ]; + }; + + options = { + security.allowUserNamespaces = mkOption { + type = types.bool; + default = true; + description = '' + Whether to allow creation of user namespaces. A recurring problem + with user namespaces is the presence of code paths where the kernel's + permission checking logic fails to account for namespacing, instead + permitting a namespaced process to act outside the namespace with the + same privileges as it would have inside it. This is particularly + damaging in the common case of running as root within the namespace. + When user namespace creation is disallowed, attempting to create + a user namespace fails with "no space left on device" (ENOSPC). + ''; + }; + }; + + config = mkIf (!config.security.allowUserNamespaces) { + # Setting the number of allowed user namespaces to 0 effectively disables + # the feature at runtime. Note that root may raise the limit again + # at any time. + boot.kernel.sysctl."user.max_user_namespaces" = 0; + + assertions = [ + { assertion = config.nix.useSandbox -> config.security.allowUserNamespaces; + message = "`nix.useSandbox = true` conflicts with `!security.allowUserNamespaces`."; + } + ]; + }; +} diff --git a/nixos/modules/security/rngd.nix b/nixos/modules/security/rngd.nix index 3a1ffc55e5fe..63e00b548120 100644 --- a/nixos/modules/security/rngd.nix +++ b/nixos/modules/security/rngd.nix @@ -20,7 +20,6 @@ with lib; KERNEL=="random", TAG+="systemd" SUBSYSTEM=="cpu", ENV{MODALIAS}=="cpu:type:x86,*feature:*009E*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="rngd.service" KERNEL=="hw_random", TAG+="systemd", ENV{SYSTEMD_WANTS}+="rngd.service" - ${if config.services.tcsd.enable then "" else ''KERNEL=="tpm0", TAG+="systemd", ENV{SYSTEMD_WANTS}+="rngd.service"''} ''; systemd.services.rngd = { @@ -30,8 +29,7 @@ with lib; description = "Hardware RNG Entropy Gatherer Daemon"; - serviceConfig.ExecStart = "${pkgs.rng_tools}/sbin/rngd -f -v" + - (if config.services.tcsd.enable then " --no-tpm=1" else ""); + serviceConfig.ExecStart = "${pkgs.rng-tools}/sbin/rngd -f -v"; }; }; } diff --git a/nixos/modules/security/wrappers/default.nix b/nixos/modules/security/wrappers/default.nix index 77e4b2a616d8..dcb9c8d4ed5f 100644 --- a/nixos/modules/security/wrappers/default.nix +++ b/nixos/modules/security/wrappers/default.nix @@ -180,35 +180,6 @@ in # programs to be wrapped. WRAPPER_PATH=${config.system.path}/bin:${config.system.path}/sbin - # Remove the old /var/setuid-wrappers path from the system... - # - # TODO: this is only necessary for upgrades 16.09 => 17.x; - # this conditional removal block needs to be removed after - # the release. - if [ -d /var/setuid-wrappers ]; then - rm -rf /var/setuid-wrappers - ln -s /run/wrappers/bin /var/setuid-wrappers - fi - - # Remove the old /run/setuid-wrappers-dir path from the - # system as well... - # - # TODO: this is only necessary for upgrades 16.09 => 17.x; - # this conditional removal block needs to be removed after - # the release. - if [ -d /run/setuid-wrapper-dirs ]; then - rm -rf /run/setuid-wrapper-dirs - ln -s /run/wrappers/bin /run/setuid-wrapper-dirs - fi - - # TODO: this is only necessary for upgrades 16.09 => 17.x; - # this conditional removal block needs to be removed after - # the release. - if readlink -f /run/booted-system | grep nixos-17 > /dev/null; then - rm -rf /run/setuid-wrapper-dirs - rm -rf /var/setuid-wrappers - fi - # We want to place the tmpdirs for the wrappers to the parent dir. wrapperDir=$(mktemp --directory --tmpdir="${parentWrapperDir}" wrappers.XXXXXXXXXX) chmod a+rx $wrapperDir diff --git a/nixos/modules/services/admin/salt/master.nix b/nixos/modules/services/admin/salt/master.nix index 165580b97837..c6b1b0cc0bd8 100644 --- a/nixos/modules/services/admin/salt/master.nix +++ b/nixos/modules/services/admin/salt/master.nix @@ -53,6 +53,9 @@ in Type = "notify"; NotifyAccess = "all"; }; + restartTriggers = [ + config.environment.etc."salt/master".source + ]; }; }; diff --git a/nixos/modules/services/admin/salt/minion.nix b/nixos/modules/services/admin/salt/minion.nix index 9ecefb32cfa8..c8fa9461a209 100644 --- a/nixos/modules/services/admin/salt/minion.nix +++ b/nixos/modules/services/admin/salt/minion.nix @@ -15,7 +15,6 @@ let # Default is in /etc/salt/pki/minion pki_dir = "/var/lib/salt/pki/minion"; } cfg.configuration; - configDir = pkgs.writeTextDir "minion" (builtins.toJSON fullConfig); in @@ -28,15 +27,24 @@ in default = {}; description = '' Salt minion configuration as Nix attribute set. - See <link xlink:href="https://docs.saltstack.com/en/latest/ref/configuration/minion.html"/> - for details. + See <link xlink:href="https://docs.saltstack.com/en/latest/ref/configuration/minion.html"/> + for details. ''; }; }; }; config = mkIf cfg.enable { - environment.systemPackages = with pkgs; [ salt ]; + environment = { + # Set this up in /etc/salt/minion so `salt-call`, etc. work. + # The alternatives are + # - passing --config-dir to all salt commands, not just the minion unit, + # - setting aglobal environment variable. + etc."salt/minion".source = pkgs.writeText "minion" ( + builtins.toJSON fullConfig + ); + systemPackages = with pkgs; [ salt ]; + }; systemd.services.salt-minion = { description = "Salt Minion"; wantedBy = [ "multi-user.target" ]; @@ -45,11 +53,14 @@ in utillinux ]; serviceConfig = { - ExecStart = "${pkgs.salt}/bin/salt-minion --config-dir=${configDir}"; + ExecStart = "${pkgs.salt}/bin/salt-minion"; LimitNOFILE = 8192; Type = "notify"; NotifyAccess = "all"; }; + restartTriggers = [ + config.environment.etc."salt/minion".source + ]; }; }; } diff --git a/nixos/modules/services/computing/slurm/slurm.nix b/nixos/modules/services/computing/slurm/slurm.nix index 09174ed39f5e..cd481212db2d 100644 --- a/nixos/modules/services/computing/slurm/slurm.nix +++ b/nixos/modules/services/computing/slurm/slurm.nix @@ -6,13 +6,18 @@ let cfg = config.services.slurm; # configuration file can be generated by http://slurm.schedmd.com/configurator.html + + defaultUser = "slurm"; + configFile = pkgs.writeTextDir "slurm.conf" '' ClusterName=${cfg.clusterName} + StateSaveLocation=${cfg.stateSaveLocation} + SlurmUser=${cfg.user} ${optionalString (cfg.controlMachine != null) ''controlMachine=${cfg.controlMachine}''} ${optionalString (cfg.controlAddr != null) ''controlAddr=${cfg.controlAddr}''} - ${optionalString (cfg.nodeName != null) ''nodeName=${cfg.nodeName}''} - ${optionalString (cfg.partitionName != null) ''partitionName=${cfg.partitionName}''} + ${toString (map (x: "NodeName=${x}\n") cfg.nodeName)} + ${toString (map (x: "PartitionName=${x}\n") cfg.partitionName)} PlugStackConfig=${plugStackConfig} ProctrackType=${cfg.procTrackType} ${cfg.extraConfig} @@ -24,12 +29,19 @@ let ${cfg.extraPlugstackConfig} ''; - cgroupConfig = pkgs.writeTextDir "cgroup.conf" '' ${cfg.extraCgroupConfig} ''; + slurmdbdConf = pkgs.writeTextDir "slurmdbd.conf" + '' + DbdHost=${cfg.dbdserver.dbdHost} + SlurmUser=${cfg.user} + StorageType=accounting_storage/mysql + ${cfg.dbdserver.extraConfig} + ''; + # slurm expects some additional config files to be # in the same directory as slurm.conf etcSlurm = pkgs.symlinkJoin { @@ -43,6 +55,8 @@ in ###### interface + meta.maintainers = [ maintainers.markuskowa ]; + options = { services.slurm = { @@ -60,6 +74,27 @@ in }; }; + dbdserver = { + enable = mkEnableOption "SlurmDBD service"; + + dbdHost = mkOption { + type = types.str; + default = config.networking.hostName; + description = '' + Hostname of the machine where <literal>slurmdbd</literal> + is running (i.e. name returned by <literal>hostname -s</literal>). + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra configuration for <literal>slurmdbd.conf</literal> + ''; + }; + }; + client = { enable = mkEnableOption "slurm client daemon"; }; @@ -116,9 +151,9 @@ in }; nodeName = mkOption { - type = types.nullOr types.str; - default = null; - example = "linux[1-32] CPUs=1 State=UNKNOWN"; + type = types.listOf types.str; + default = []; + example = literalExample ''[ "linux[1-32] CPUs=1 State=UNKNOWN" ];''; description = '' Name that SLURM uses to refer to a node (or base partition for BlueGene systems). Typically this would be the string that "/bin/hostname -s" @@ -127,9 +162,9 @@ in }; partitionName = mkOption { - type = types.nullOr types.str; - default = null; - example = "debug Nodes=linux[1-32] Default=YES MaxTime=INFINITE State=UP"; + type = types.listOf types.str; + default = []; + example = literalExample ''[ "debug Nodes=linux[1-32] Default=YES MaxTime=INFINITE State=UP" ];''; description = '' Name by which the partition may be referenced. Note that now you have to write the partition's parameters after the name. @@ -150,7 +185,7 @@ in }; procTrackType = mkOption { - type = types.string; + type = types.str; default = "proctrack/linuxproc"; description = '' Plugin to be used for process tracking on a job step basis. @@ -159,6 +194,25 @@ in ''; }; + stateSaveLocation = mkOption { + type = types.str; + default = "/var/spool/slurmctld"; + description = '' + Directory into which the Slurm controller, slurmctld, saves its state. + ''; + }; + + user = mkOption { + type = types.str; + default = defaultUser; + description = '' + Set this option when you want to run the slurmctld daemon + as something else than the default slurm user "slurm". + Note that the UID of this user needs to be the same + on all nodes. + ''; + }; + extraConfig = mkOption { default = ""; type = types.lines; @@ -184,6 +238,8 @@ in used when <literal>procTrackType=proctrack/cgroup</literal>. ''; }; + + }; }; @@ -220,12 +276,24 @@ in ''; }; - in mkIf (cfg.enableStools || cfg.client.enable || cfg.server.enable) { + in mkIf ( cfg.enableStools || + cfg.client.enable || + cfg.server.enable || + cfg.dbdserver.enable ) { environment.systemPackages = [ wrappedSlurm ]; services.munge.enable = mkDefault true; + # use a static uid as default to ensure it is the same on all nodes + users.users.slurm = mkIf (cfg.user == defaultUser) { + name = defaultUser; + group = "slurm"; + uid = config.ids.uids.slurm; + }; + + users.groups.slurm.gid = config.ids.uids.slurm; + systemd.services.slurmd = mkIf (cfg.client.enable) { path = with pkgs; [ wrappedSlurm coreutils ] ++ lib.optional cfg.enableSrunX11 slurm-spank-x11; @@ -261,6 +329,29 @@ in PIDFile = "/run/slurmctld.pid"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; }; + + preStart = '' + mkdir -p ${cfg.stateSaveLocation} + chown -R ${cfg.user}:slurm ${cfg.stateSaveLocation} + ''; + }; + + systemd.services.slurmdbd = mkIf (cfg.dbdserver.enable) { + path = with pkgs; [ wrappedSlurm munge coreutils ]; + + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" "munged.service" "mysql.service" ]; + requires = [ "munged.service" "mysql.service" ]; + + # slurm strips the last component off the path + environment.SLURM_CONF = "${slurmdbdConf}/slurm.conf"; + + serviceConfig = { + Type = "forking"; + ExecStart = "${cfg.package}/bin/slurmdbd"; + PIDFile = "/run/slurmdbd.pid"; + ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + }; }; }; diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix index de2a757196a5..6edb1503c233 100644 --- a/nixos/modules/services/databases/postgresql.nix +++ b/nixos/modules/services/databases/postgresql.nix @@ -55,7 +55,7 @@ in package = mkOption { type = types.package; - example = literalExample "pkgs.postgresql96"; + example = literalExample "pkgs.postgresql_9_6"; description = '' PostgreSQL package to use. ''; @@ -118,7 +118,7 @@ in extraPlugins = mkOption { type = types.listOf types.path; default = []; - example = literalExample "[ (pkgs.postgis.override { postgresql = pkgs.postgresql94; }) ]"; + example = literalExample "[ (pkgs.postgis.override { postgresql = pkgs.postgresql_9_4; }) ]"; description = '' When this list contains elements a new store path is created. PostgreSQL and the elements are symlinked into it. Then pg_config, @@ -167,9 +167,9 @@ in # Note: when changing the default, make it conditional on # ‘system.stateVersion’ to maintain compatibility with existing # systems! - mkDefault (if versionAtLeast config.system.stateVersion "17.09" then pkgs.postgresql96 - else if versionAtLeast config.system.stateVersion "16.03" then pkgs.postgresql95 - else pkgs.postgresql94); + mkDefault (if versionAtLeast config.system.stateVersion "17.09" then pkgs.postgresql_9_6 + else if versionAtLeast config.system.stateVersion "16.03" then pkgs.postgresql_9_5 + else pkgs.postgresql_9_4); services.postgresql.dataDir = mkDefault (if versionAtLeast config.system.stateVersion "17.09" then "/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}" diff --git a/nixos/modules/services/databases/postgresql.xml b/nixos/modules/services/databases/postgresql.xml index f89f0d653164..14f4d4909bc0 100644 --- a/nixos/modules/services/databases/postgresql.xml +++ b/nixos/modules/services/databases/postgresql.xml @@ -27,12 +27,12 @@ <filename>configuration.nix</filename>: <programlisting> <xref linkend="opt-services.postgresql.enable"/> = true; -<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql94; +<xref linkend="opt-services.postgresql.package"/> = pkgs.postgresql_9_4; </programlisting> Note that you are required to specify the desired version of PostgreSQL - (e.g. <literal>pkgs.postgresql94</literal>). Since upgrading your PostgreSQL - version requires a database dump and reload (see below), NixOS cannot - provide a default value for + (e.g. <literal>pkgs.postgresql_9_4</literal>). Since upgrading your + PostgreSQL version requires a database dump and reload (see below), NixOS + cannot provide a default value for <xref linkend="opt-services.postgresql.package"/> such as the most recent release of PostgreSQL. </para> diff --git a/nixos/modules/services/desktops/gsignond.nix b/nixos/modules/services/desktops/gsignond.nix new file mode 100644 index 000000000000..cf26e05d5c18 --- /dev/null +++ b/nixos/modules/services/desktops/gsignond.nix @@ -0,0 +1,43 @@ +# Accounts-SSO gSignOn daemon + +{ config, lib, pkgs, ... }: + +with lib; + +let + package = pkgs.gsignond.override { plugins = config.services.gsignond.plugins; }; +in +{ + + ###### interface + + options = { + + services.gsignond = { + + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable gSignOn daemon, a DBus service + which performs user authentication on behalf of its clients. + ''; + }; + + plugins = mkOption { + type = types.listOf types.package; + default = []; + description = '' + What plugins to use with the gSignOn daemon. + ''; + }; + }; + }; + + ###### implementation + config = mkIf config.services.gsignond.enable { + environment.etc."gsignond.conf".source = "${package}/etc/gsignond.conf"; + services.dbus.packages = [ package ]; + }; + +} diff --git a/nixos/modules/services/hardware/lirc.nix b/nixos/modules/services/hardware/lirc.nix index a66a7fbf495f..5635d6f09715 100644 --- a/nixos/modules/services/hardware/lirc.nix +++ b/nixos/modules/services/hardware/lirc.nix @@ -65,6 +65,10 @@ in { serviceConfig = { RuntimeDirectory = "lirc"; + + # socket lives in runtime directory; we have to keep is available + RuntimeDirectoryPreserve = true; + ExecStart = '' ${pkgs.lirc}/bin/lircd --nodaemon \ ${escapeShellArgs cfg.extraArguments} \ diff --git a/nixos/modules/services/hardware/trezord.nix b/nixos/modules/services/hardware/trezord.nix index dfefc1171e62..c06a0665d02f 100644 --- a/nixos/modules/services/hardware/trezord.nix +++ b/nixos/modules/services/hardware/trezord.nix @@ -27,13 +27,13 @@ in { destination = "/etc/udev/rules.d/51-trezor.rules"; text = '' # TREZOR v1 (One) - SUBSYSTEM=="usb", ATTR{idVendor}=="534c", ATTR{idProduct}=="0001", MODE="0666", GROUP="dialout", TAG+="uaccess", TAG+="udev-acl", SYMLINK+="trezor%n" - KERNEL=="hidraw*", ATTRS{idVendor}=="534c", ATTRS{idProduct}=="0001", MODE="0666", GROUP="dialout", TAG+="uaccess", TAG+="udev-acl" + SUBSYSTEM=="usb", ATTR{idVendor}=="534c", ATTR{idProduct}=="0001", MODE="0660", GROUP="trezord", TAG+="uaccess", SYMLINK+="trezor%n" + KERNEL=="hidraw*", ATTRS{idVendor}=="534c", ATTRS{idProduct}=="0001", MODE="0660", GROUP="trezord", TAG+="uaccess" # TREZOR v2 (T) - SUBSYSTEM=="usb", ATTR{idVendor}=="1209", ATTR{idProduct}=="53c0", MODE="0661", GROUP="dialout", TAG+="uaccess", TAG+="udev-acl", SYMLINK+="trezor%n" - SUBSYSTEM=="usb", ATTR{idVendor}=="1209", ATTR{idProduct}=="53c1", MODE="0666", GROUP="dialout", TAG+="uaccess", TAG+="udev-acl", SYMLINK+="trezor%n" - KERNEL=="hidraw*", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="53c1", MODE="0666", GROUP="dialout", TAG+="uaccess", TAG+="udev-acl" + SUBSYSTEM=="usb", ATTR{idVendor}=="1209", ATTR{idProduct}=="53c0", MODE="0660", GROUP="trezord", TAG+="uaccess", SYMLINK+="trezor%n" + SUBSYSTEM=="usb", ATTR{idVendor}=="1209", ATTR{idProduct}=="53c1", MODE="0660", GROUP="trezord", TAG+="uaccess", SYMLINK+="trezor%n" + KERNEL=="hidraw*", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="53c1", MODE="0660", GROUP="trezord", TAG+="uaccess" ''; }); diff --git a/nixos/modules/services/hardware/upower.nix b/nixos/modules/services/hardware/upower.nix index 2198842a4511..1da47349c077 100644 --- a/nixos/modules/services/hardware/upower.nix +++ b/nixos/modules/services/hardware/upower.nix @@ -56,6 +56,32 @@ in { Type = "dbus"; BusName = "org.freedesktop.UPower"; ExecStart = "@${cfg.package}/libexec/upowerd upowerd"; + Restart = "on-failure"; + # Upstream lockdown: + # Filesystem lockdown + ProtectSystem = "strict"; + # Needed by keyboard backlight support + ProtectKernelTunables = false; + ProtectControlGroups = true; + ReadWritePaths = "/var/lib/upower"; + ProtectHome = true; + PrivateTmp = true; + + # Network + # PrivateNetwork=true would block udev's netlink socket + RestrictAddressFamilies = "AF_UNIX AF_NETLINK"; + + # Execute Mappings + MemoryDenyWriteExecute = true; + + # Modules + ProtectKernelModules = true; + + # Real-time + RestrictRealtime = true; + + # Privilege escalation + NoNewPrivileges = true; }; }; diff --git a/nixos/modules/services/mail/clamsmtp.nix b/nixos/modules/services/mail/clamsmtp.nix index 8f4f39aa7288..fc1267c5d280 100644 --- a/nixos/modules/services/mail/clamsmtp.nix +++ b/nixos/modules/services/mail/clamsmtp.nix @@ -176,4 +176,6 @@ in } ) cfg.instances); }; + + meta.maintainers = with lib.maintainers; [ ekleog ]; } diff --git a/nixos/modules/services/mail/dkimproxy-out.nix b/nixos/modules/services/mail/dkimproxy-out.nix index 894b88e25c1b..f4ac9e47007a 100644 --- a/nixos/modules/services/mail/dkimproxy-out.nix +++ b/nixos/modules/services/mail/dkimproxy-out.nix @@ -115,4 +115,6 @@ in }; }; }; + + meta.maintainers = with lib.maintainers; [ ekleog ]; } diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix index e6091182b2ab..30ad7d82fb80 100644 --- a/nixos/modules/services/mail/dovecot.nix +++ b/nixos/modules/services/mail/dovecot.nix @@ -311,7 +311,7 @@ in { name = "dovenull"; uid = config.ids.uids.dovenull2; description = "Dovecot user for untrusted logins"; - group = cfg.group; + group = "dovenull"; } ] ++ optional (cfg.user == "dovecot2") { name = "dovecot2"; @@ -332,6 +332,10 @@ in } ++ optional (cfg.createMailUser && cfg.mailGroup != null) { name = cfg.mailGroup; + } + ++ singleton + { name = "dovenull"; + gid = config.ids.gids.dovenull2; }; environment.etc."dovecot/modules".source = modulesDir; diff --git a/nixos/modules/services/mail/postfix.nix b/nixos/modules/services/mail/postfix.nix index 33249aa3e554..d43733484ffa 100644 --- a/nixos/modules/services/mail/postfix.nix +++ b/nixos/modules/services/mail/postfix.nix @@ -602,7 +602,7 @@ in target = "postfix"; }; - # This makes comfortable for root to run 'postqueue' for example. + # This makes it comfortable to run 'postqueue/postdrop' for example. systemPackages = [ pkgs.postfix ]; }; @@ -616,6 +616,22 @@ in setgid = true; }; + security.wrappers.postqueue = { + program = "postqueue"; + source = "${pkgs.postfix}/bin/postqueue"; + group = setgidGroup; + setuid = false; + setgid = true; + }; + + security.wrappers.postdrop = { + program = "postdrop"; + source = "${pkgs.postfix}/bin/postdrop"; + group = setgidGroup; + setuid = false; + setgid = true; + }; + users.users = optional (user == "postfix") { name = "postfix"; description = "Postfix mail server user"; diff --git a/nixos/modules/services/misc/home-assistant.nix b/nixos/modules/services/misc/home-assistant.nix index 0756e81612ac..2e9aa33aeeee 100644 --- a/nixos/modules/services/misc/home-assistant.nix +++ b/nixos/modules/services/misc/home-assistant.nix @@ -157,6 +157,7 @@ in { Restart = "on-failure"; ProtectSystem = "strict"; ReadWritePaths = "${cfg.configDir}"; + KillSignal = "SIGINT"; PrivateTmp = true; RemoveIPC = true; }; diff --git a/nixos/modules/services/misc/weechat.nix b/nixos/modules/services/misc/weechat.nix index 1fcfb440485d..c6ff540ea12f 100644 --- a/nixos/modules/services/misc/weechat.nix +++ b/nixos/modules/services/misc/weechat.nix @@ -46,10 +46,12 @@ in Group = "weechat"; RemainAfterExit = "yes"; }; - script = "exec ${pkgs.screen}/bin/screen -Dm -S ${cfg.sessionName} ${cfg.binary}"; + script = "exec ${config.security.wrapperDir}/screen -Dm -S ${cfg.sessionName} ${cfg.binary}"; wantedBy = [ "multi-user.target" ]; wants = [ "network.target" ]; }; + + security.wrappers.screen.source = "${pkgs.screen}/bin/screen"; }; meta.doc = ./weechat.xml; diff --git a/nixos/modules/services/misc/weechat.xml b/nixos/modules/services/misc/weechat.xml index 9c9ee0448c92..b7f755bbc5c7 100644 --- a/nixos/modules/services/misc/weechat.xml +++ b/nixos/modules/services/misc/weechat.xml @@ -54,7 +54,7 @@ </programlisting> Now, the session can be re-attached like this: <programlisting> -screen -r weechat-screen +screen -x weechat/weechat-screen </programlisting> </para> diff --git a/nixos/modules/services/monitoring/datadog-agent.nix b/nixos/modules/services/monitoring/datadog-agent.nix index 8fd3455a238f..5434fe99347d 100644 --- a/nixos/modules/services/monitoring/datadog-agent.nix +++ b/nixos/modules/services/monitoring/datadog-agent.nix @@ -7,7 +7,7 @@ let ddConf = { dd_url = "https://app.datadoghq.com"; - skip_ssl_validation = "no"; + skip_ssl_validation = false; confd_path = "/etc/datadog-agent/conf.d"; additional_checksd = "/etc/datadog-agent/checks.d"; use_dogstatsd = true; @@ -16,6 +16,7 @@ let // optionalAttrs (cfg.hostname != null) { inherit (cfg) hostname; } // optionalAttrs (cfg.tags != null ) { tags = concatStringsSep ", " cfg.tags; } // optionalAttrs (cfg.enableLiveProcessCollection) { process_config = { enabled = "true"; }; } + // optionalAttrs (cfg.enableTraceAgent) { apm_config = { enabled = true; }; } // cfg.extraConfig; # Generate Datadog configuration files for each configured checks. @@ -132,6 +133,15 @@ in { default = false; type = types.bool; }; + + enableTraceAgent = mkOption { + description = '' + Whether to enable the trace agent. + ''; + default = false; + type = types.bool; + }; + checks = mkOption { description = '' Configuration for all Datadog checks. Keys of this attribute @@ -244,6 +254,16 @@ in { ${pkgs.datadog-process-agent}/bin/agent --config /etc/datadog-agent/datadog.yaml ''; }); + + datadog-trace-agent = lib.mkIf cfg.enableTraceAgent (makeService { + description = "Datadog Trace Agent"; + path = [ ]; + script = '' + export DD_API_KEY=$(head -n 1 ${cfg.apiKeyFile}) + ${pkgs.datadog-trace-agent}/bin/trace-agent -config /etc/datadog-agent/datadog.yaml + ''; + }); + }; environment.etc = etcfiles; diff --git a/nixos/modules/services/monitoring/grafana.nix b/nixos/modules/services/monitoring/grafana.nix index c30647f5460b..c0c16a429d89 100644 --- a/nixos/modules/services/monitoring/grafana.nix +++ b/nixos/modules/services/monitoring/grafana.nix @@ -4,6 +4,7 @@ with lib; let cfg = config.services.grafana; + opt = options.services.grafana; envOptions = { PATHS_DATA = cfg.dataDir; @@ -41,6 +42,12 @@ let AUTH_ANONYMOUS_ORG_ROLE = cfg.auth.anonymous.org_role; ANALYTICS_REPORTING_ENABLED = boolToString cfg.analytics.reporting.enable; + + SMTP_ENABLE = boolToString cfg.smtp.enable; + SMTP_HOST = cfg.smtp.host; + SMTP_USER = cfg.smtp.user; + SMTP_PASSWORD = cfg.smtp.password; + SMTP_FROM_ADDRESS = cfg.smtp.fromAddress; } // cfg.extraOptions; in { @@ -134,11 +141,23 @@ in { }; password = mkOption { - description = "Database password."; + description = '' + Database password. + This option is mutual exclusive with the passwordFile option. + ''; default = ""; type = types.str; }; + passwordFile = mkOption { + description = '' + File that containts the database password. + This option is mutual exclusive with the password option. + ''; + default = null; + type = types.nullOr types.path; + }; + path = mkOption { description = "Database path."; default = "${cfg.dataDir}/data/grafana.db"; @@ -163,16 +182,69 @@ in { }; adminPassword = mkOption { - description = "Default admin password."; + description = '' + Default admin password. + This option is mutual exclusive with the adminPasswordFile option. + ''; default = "admin"; type = types.str; }; + adminPasswordFile = mkOption { + description = '' + Default admin password. + This option is mutual exclusive with the <literal>adminPassword</literal> option. + ''; + default = null; + type = types.nullOr types.path; + }; + secretKey = mkOption { description = "Secret key used for signing."; default = "SW2YcwTIb9zpOOhoPsMm"; type = types.str; }; + + secretKeyFile = mkOption { + description = "Secret key used for signing."; + default = null; + type = types.nullOr types.path; + }; + }; + + smtp = { + enable = mkEnableOption "smtp"; + host = mkOption { + description = "Host to connect to"; + default = "localhost:25"; + type = types.str; + }; + user = mkOption { + description = "User used for authentication"; + default = ""; + type = types.str; + }; + password = mkOption { + description = '' + Password used for authentication. + This option is mutual exclusive with the passwordFile option. + ''; + default = ""; + type = types.str; + }; + passwordFile = mkOption { + description = '' + Password used for authentication. + This option is mutual exclusive with the password option. + ''; + default = null; + type = types.nullOr types.path; + }; + fromAddress = mkOption { + description = "Email address used for sending"; + default = "admin@grafana.localhost"; + type = types.str; + }; }; users = { @@ -241,12 +313,31 @@ in { config = mkIf cfg.enable { warnings = optional ( - cfg.database.password != options.services.grafana.database.password.default || - cfg.security.adminPassword != options.services.grafana.security.adminPassword.default + cfg.database.password != opt.database.password.default || + cfg.security.adminPassword != opt.security.adminPassword.default ) "Grafana passwords will be stored as plaintext in the Nix store!"; environment.systemPackages = [ cfg.package ]; + assertions = [ + { + assertion = cfg.database.password != opt.database.password.default -> cfg.database.passwordFile == null; + message = "Cannot set both password and passwordFile"; + } + { + assertion = cfg.security.adminPassword != opt.security.adminPassword.default -> cfg.security.adminPasswordFile == null; + message = "Cannot set both adminPassword and adminPasswordFile"; + } + { + assertion = cfg.security.secretKeyFile != opt.security.secretKeyFile.default -> cfg.security.secretKeyFile == null; + message = "Cannot set both secretKey and secretKeyFile"; + } + { + assertion = cfg.smtp.password != opt.smtp.password.default -> cfg.smtp.passwordFile == null; + message = "Cannot set both password and secretKeyFile"; + } + ]; + systemd.services.grafana = { description = "Grafana Service Daemon"; wantedBy = ["multi-user.target"]; @@ -254,8 +345,22 @@ in { environment = { QT_QPA_PLATFORM = "offscreen"; } // mapAttrs' (n: v: nameValuePair "GF_${n}" (toString v)) envOptions; + script = '' + ${optionalString (cfg.database.passwordFile != null) '' + export GF_DATABASE_PASSWORD="$(cat ${escapeShellArg cfg.database.passwordFile})" + ''} + ${optionalString (cfg.security.adminPasswordFile != null) '' + export GF_SECURITY_ADMIN_PASSWORD="$(cat ${escapeShellArg cfg.security.adminPasswordFile})" + ''} + ${optionalString (cfg.security.secretKeyFile != null) '' + export GF_SECURITY_SECRET_KEY="$(cat ${escapeShellArg cfg.security.secretKeyFile})" + ''} + ${optionalString (cfg.smtp.passwordFile != null) '' + export GF_SMTP_PASSWORD="$(cat ${escapeShellArg cfg.smtp.passwordFile})" + ''} + exec ${cfg.package.bin}/bin/grafana-server -homepath ${cfg.dataDir} + ''; serviceConfig = { - ExecStart = "${cfg.package.bin}/bin/grafana-server -homepath ${cfg.dataDir}"; WorkingDirectory = cfg.dataDir; User = "grafana"; }; diff --git a/nixos/modules/services/monitoring/kapacitor.nix b/nixos/modules/services/monitoring/kapacitor.nix new file mode 100644 index 000000000000..1de0a8d5af2f --- /dev/null +++ b/nixos/modules/services/monitoring/kapacitor.nix @@ -0,0 +1,154 @@ +{ options, config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.kapacitor; + + kapacitorConf = pkgs.writeTextFile { + name = "kapacitord.conf"; + text = '' + hostname="${config.networking.hostName}" + data_dir="${cfg.dataDir}" + + [http] + bind-address = "${cfg.bind}:${toString cfg.port}" + log-enabled = false + auth-enabled = false + + [task] + dir = "${cfg.dataDir}/tasks" + snapshot-interval = "${cfg.taskSnapshotInterval}" + + [replay] + dir = "${cfg.dataDir}/replay" + + [storage] + boltdb = "${cfg.dataDir}/kapacitor.db" + + ${optionalString (cfg.loadDirectory != null) '' + [load] + enabled = true + dir = "${cfg.loadDirectory}" + ''} + + ${optionalString (cfg.defaultDatabase.enable) '' + [[influxdb]] + name = "default" + enabled = true + default = true + urls = [ "${cfg.defaultDatabase.url}" ] + username = "${cfg.defaultDatabase.username}" + password = "${cfg.defaultDatabase.password}" + ''} + + ${cfg.extraConfig} + ''; + }; +in +{ + options.services.kapacitor = { + enable = mkEnableOption "kapacitor"; + + dataDir = mkOption { + type = types.path; + example = "/var/lib/kapacitor"; + default = "/var/lib/kapacitor"; + description = "Location where Kapacitor stores its state"; + }; + + port = mkOption { + type = types.int; + default = 9092; + description = "Port of Kapacitor"; + }; + + bind = mkOption { + type = types.str; + default = ""; + example = literalExample "0.0.0.0"; + description = "Address to bind to. The default is to bind to all addresses"; + }; + + extraConfig = mkOption { + description = "These lines go into kapacitord.conf verbatim."; + default = ""; + type = types.lines; + }; + + user = mkOption { + type = types.str; + default = "kapacitor"; + description = "User account under which Kapacitor runs"; + }; + + group = mkOption { + type = types.str; + default = "kapacitor"; + description = "Group under which Kapacitor runs"; + }; + + taskSnapshotInterval = mkOption { + type = types.str; + description = "Specifies how often to snapshot the task state (in InfluxDB time units)"; + default = "1m0s"; + example = "1m0s"; + }; + + loadDirectory = mkOption { + type = types.nullOr types.path; + description = "Directory where to load services from, such as tasks, templates and handlers (or null to disable service loading on startup)"; + default = null; + }; + + defaultDatabase = { + enable = mkEnableOption "kapacitor.defaultDatabase"; + + url = mkOption { + description = "The URL to an InfluxDB server that serves as the default database"; + example = "http://localhost:8086"; + type = types.string; + }; + + username = mkOption { + description = "The username to connect to the remote InfluxDB server"; + type = types.string; + }; + + password = mkOption { + description = "The password to connect to the remote InfluxDB server"; + type = types.string; + }; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ pkgs.kapacitor ]; + + systemd.services.kapacitor = { + description = "Kapacitor Real-Time Stream Processing Engine"; + wantedBy = [ "multi-user.target" ]; + after = [ "networking.target" ]; + serviceConfig = { + ExecStart = "${pkgs.kapacitor}/bin/kapacitord -config ${kapacitorConf}"; + User = "kapacitor"; + Group = "kapacitor"; + PermissionsStartOnly = true; + }; + preStart = '' + mkdir -p ${cfg.dataDir} + chown ${cfg.user}:${cfg.group} ${cfg.dataDir} + ''; + }; + + users.users.kapacitor = { + uid = config.ids.uids.kapacitor; + description = "Kapacitor user"; + home = cfg.dataDir; + }; + + users.groups.kapacitor = { + gid = config.ids.gids.kapacitor; + }; + }; +} diff --git a/nixos/modules/services/monitoring/munin.nix b/nixos/modules/services/monitoring/munin.nix index ff9604c7dbcd..2b265d5b5a90 100644 --- a/nixos/modules/services/monitoring/munin.nix +++ b/nixos/modules/services/monitoring/munin.nix @@ -5,8 +5,8 @@ # TODO: support fastcgi # http://munin-monitoring.org/wiki/CgiHowto2 -# spawn-fcgi -s /var/run/munin/fastcgi-graph.sock -U www-data -u munin -g munin /usr/lib/munin/cgi/munin-cgi-graph -# spawn-fcgi -s /var/run/munin/fastcgi-html.sock -U www-data -u munin -g munin /usr/lib/munin/cgi/munin-cgi-html +# spawn-fcgi -s /run/munin/fastcgi-graph.sock -U www-data -u munin -g munin /usr/lib/munin/cgi/munin-cgi-graph +# spawn-fcgi -s /run/munin/fastcgi-html.sock -U www-data -u munin -g munin /usr/lib/munin/cgi/munin-cgi-html # https://paste.sh/vofcctHP#-KbDSXVeWoifYncZmLfZzgum # nginx http://munin.readthedocs.org/en/latest/example/webserver/nginx.html @@ -22,7 +22,7 @@ let dbdir /var/lib/munin htmldir /var/www/munin logdir /var/log/munin - rundir /var/run/munin + rundir /run/munin ${cronCfg.extraGlobalConfig} @@ -170,7 +170,7 @@ in wantedBy = [ "multi-user.target" ]; path = with pkgs; [ munin smartmontools "/run/current-system/sw" "/run/wrappers" ]; environment.MUNIN_LIBDIR = "${pkgs.munin}/lib"; - environment.MUNIN_PLUGSTATE = "/var/run/munin"; + environment.MUNIN_PLUGSTATE = "/run/munin"; environment.MUNIN_LOGDIR = "/var/log/munin"; preStart = '' echo "updating munin plugins..." @@ -188,7 +188,7 @@ in }; # munin_stats plugin breaks as of 2.0.33 when this doesn't exist - systemd.tmpfiles.rules = [ "d /var/run/munin 0755 munin munin -" ]; + systemd.tmpfiles.rules = [ "d /run/munin 0755 munin munin -" ]; }) (mkIf cronCfg.enable { @@ -210,7 +210,7 @@ in }; systemd.tmpfiles.rules = [ - "d /var/run/munin 0755 munin munin -" + "d /run/munin 0755 munin munin -" "d /var/log/munin 0755 munin munin -" "d /var/www/munin 0755 munin munin -" "d /var/lib/munin 0755 munin munin -" diff --git a/nixos/modules/services/monitoring/prometheus/default.nix b/nixos/modules/services/monitoring/prometheus/default.nix index 5dda763bd56b..e2ee995cea80 100644 --- a/nixos/modules/services/monitoring/prometheus/default.nix +++ b/nixos/modules/services/monitoring/prometheus/default.nix @@ -39,6 +39,7 @@ let "-alertmanager.notification-queue-capacity=${toString cfg.alertmanagerNotificationQueueCapacity}" "-alertmanager.timeout=${toString cfg.alertmanagerTimeout}s" (optionalString (cfg.alertmanagerURL != []) "-alertmanager.url=${concatStringsSep "," cfg.alertmanagerURL}") + (optionalString (cfg.webExternalUrl != null) "-web.external-url=${cfg.webExternalUrl}") ]; promTypes.globalConfig = types.submodule { @@ -467,6 +468,16 @@ in { Alert manager HTTP API timeout (in seconds). ''; }; + + webExternalUrl = mkOption { + type = types.nullOr types.str; + default = null; + example = "https://example.com/"; + description = '' + The URL under which Prometheus is externally reachable (for example, + if Prometheus is served via a reverse proxy). + ''; + }; }; }; diff --git a/nixos/modules/services/network-filesystems/openafs/client.nix b/nixos/modules/services/network-filesystems/openafs/client.nix index 52c0966e05bc..240c1392088f 100644 --- a/nixos/modules/services/network-filesystems/openafs/client.nix +++ b/nixos/modules/services/network-filesystems/openafs/client.nix @@ -149,11 +149,13 @@ in packages = { module = mkOption { default = config.boot.kernelPackages.openafs; + defaultText = "config.boot.kernelPackages.openafs"; type = types.package; description = "OpenAFS kernel module package. MUST match the userland package!"; }; programs = mkOption { default = getBin pkgs.openafs; + defaultText = "config.boot.kernelPackages.openafs"; type = types.package; description = "OpenAFS programs package. MUST match the kernel module package!"; }; diff --git a/nixos/modules/services/network-filesystems/openafs/server.nix b/nixos/modules/services/network-filesystems/openafs/server.nix index 4c80ed0839f7..095024d2c8af 100644 --- a/nixos/modules/services/network-filesystems/openafs/server.nix +++ b/nixos/modules/services/network-filesystems/openafs/server.nix @@ -80,6 +80,7 @@ in { package = mkOption { default = pkgs.openafs.server or pkgs.openafs; + defaultText = "pkgs.openafs.server or pkgs.openafs"; type = types.package; description = "OpenAFS package for the server binaries"; }; diff --git a/nixos/modules/services/networking/bitlbee.nix b/nixos/modules/services/networking/bitlbee.nix index 46e3b7457610..274b36171608 100644 --- a/nixos/modules/services/networking/bitlbee.nix +++ b/nixos/modules/services/networking/bitlbee.nix @@ -33,7 +33,7 @@ let purple_plugin_path = lib.concatMapStringsSep ":" - (plugin: "${plugin}/lib/pidgin/") + (plugin: "${plugin}/lib/pidgin/:${plugin}/lib/purple-2/") cfg.libpurple_plugins ; diff --git a/nixos/modules/services/networking/ddclient.nix b/nixos/modules/services/networking/ddclient.nix index 9a2e13e9553c..a70967820b32 100644 --- a/nixos/modules/services/networking/ddclient.nix +++ b/nixos/modules/services/networking/ddclient.nix @@ -182,9 +182,10 @@ with lib; serviceConfig = rec { DynamicUser = true; RuntimeDirectory = StateDirectory; + RuntimeDirectoryMode = "0750"; StateDirectory = builtins.baseNameOf dataDir; Type = "oneshot"; - ExecStartPre = "!${lib.getBin pkgs.coreutils}/bin/install -m666 ${cfg.configFile} /run/${RuntimeDirectory}/ddclient.conf"; + ExecStartPre = "!${lib.getBin pkgs.coreutils}/bin/install -m660 ${cfg.configFile} /run/${RuntimeDirectory}/ddclient.conf"; ExecStart = "${lib.getBin pkgs.ddclient}/bin/ddclient -file /run/${RuntimeDirectory}/ddclient.conf"; }; }; diff --git a/nixos/modules/services/networking/eternal-terminal.nix b/nixos/modules/services/networking/eternal-terminal.nix new file mode 100644 index 000000000000..be7337ece7e4 --- /dev/null +++ b/nixos/modules/services/networking/eternal-terminal.nix @@ -0,0 +1,89 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.eternal-terminal; + +in + +{ + + ###### interface + + options = { + + services.eternal-terminal = { + + enable = mkEnableOption "Eternal Terminal server"; + + port = mkOption { + default = 2022; + type = types.int; + description = '' + The port the server should listen on. Will use the server's default (2022) if not specified. + ''; + }; + + verbosity = mkOption { + default = 0; + type = types.enum (lib.range 0 9); + description = '' + The verbosity level (0-9). + ''; + }; + + silent = mkOption { + default = false; + type = types.bool; + description = '' + If enabled, disables all logging. + ''; + }; + + logSize = mkOption { + default = 20971520; + type = types.int; + description = '' + The maximum log size. + ''; + }; + }; + }; + + ###### implementation + + config = mkIf cfg.enable { + + # We need to ensure the et package is fully installed because + # the (remote) et client runs the `etterminal` binary when it + # connects. + environment.systemPackages = [ pkgs.eternal-terminal ]; + + systemd.services = { + eternal-terminal = { + description = "Eternal Terminal server."; + wantedBy = [ "multi-user.target" ]; + after = [ "syslog.target" "network.target" ]; + serviceConfig = { + Type = "forking"; + ExecStart = "${pkgs.eternal-terminal}/bin/etserver --daemon --cfgfile=${pkgs.writeText "et.cfg" '' + ; et.cfg : Config file for Eternal Terminal + ; + + [Networking] + port = ${toString cfg.port} + + [Debug] + verbose = ${toString cfg.verbosity} + silent = ${if cfg.silent then "1" else "0"} + logsize = ${toString cfg.logSize} + ''}"; + Restart = "on-failure"; + KillMode = "process"; + }; + }; + }; + }; +} diff --git a/nixos/modules/services/networking/hostapd.nix b/nixos/modules/services/networking/hostapd.nix index 3af0441a89d8..9f74e4963296 100644 --- a/nixos/modules/services/networking/hostapd.nix +++ b/nixos/modules/services/networking/hostapd.nix @@ -157,9 +157,9 @@ in { description = "hostapd wireless AP"; path = [ pkgs.hostapd ]; - wantedBy = [ "network.target" ]; - - after = [ "${cfg.interface}-cfg.service" "nat.service" "bind.service" "dhcpd.service" "sys-subsystem-net-devices-${cfg.interface}.device" ]; + after = [ "sys-subsystem-net-devices-${cfg.interface}.device" ]; + bindsTo = [ "sys-subsystem-net-devices-${cfg.interface}.device" ]; + requiredBy = [ "network-link-${cfg.interface}.service" ]; serviceConfig = { ExecStart = "${pkgs.hostapd}/bin/hostapd ${configFile}"; diff --git a/nixos/modules/services/networking/redsocks.nix b/nixos/modules/services/networking/redsocks.nix index a47a78f1005e..8481f9debf39 100644 --- a/nixos/modules/services/networking/redsocks.nix +++ b/nixos/modules/services/networking/redsocks.nix @@ -267,4 +267,6 @@ in "ip46tables -t nat -D OUTPUT -p tcp ${redCond block} -j ${chain} 2>/dev/null || true" ) cfg.redsocks; }; + + meta.maintainers = with lib.maintainers; [ ekleog ]; } diff --git a/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix b/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix index b16d299917fe..d4f7e95f859f 100644 --- a/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix +++ b/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix @@ -248,6 +248,14 @@ in { </itemizedlist> ''; + ppk_id = mkOptionalStrParam '' + String identifying the Postquantum Preshared Key (PPK) to be used. + ''; + + ppk_required = mkYesNoParam no '' + Whether a Postquantum Preshared Key (PPK) is required for this connection. + ''; + keyingtries = mkIntParam 1 '' Number of retransmission sequences to perform during initial connect. Instead of giving up initiation after the first retransmission @@ -922,6 +930,36 @@ in { <literal>0xffffffff</literal>. ''; + set_mark_in = mkStrParam "0/0x00000000" '' + Netfilter mark applied to packets after the inbound IPsec SA processed + them. This way it's not necessary to mark packets via Netfilter before + decryption or right afterwards to match policies or process them + differently (e.g. via policy routing). + + An additional mask may be appended to the mark, separated by + <literal>/</literal>. The default mask if omitted is 0xffffffff. The + special value <literal>%same</literal> uses the value (but not the mask) + from <option>mark_in</option> as mark value, which can be fixed, + <literal>%unique</literal> or <literal>%unique-dir</literal>. + + Setting marks in XFRM input requires Linux 4.19 or higher. + ''; + + set_mark_out = mkStrParam "0/0x00000000" '' + Netfilter mark applied to packets after the outbound IPsec SA processed + them. This allows processing ESP packets differently than the original + traffic (e.g. via policy routing). + + An additional mask may be appended to the mark, separated by + <literal>/</literal>. The default mask if omitted is 0xffffffff. The + special value <literal>%same</literal> uses the value (but not the mask) + from <option>mark_out</option> as mark value, which can be fixed, + <literal>%unique_</literal> or <literal>%unique-dir</literal>. + + Setting marks in XFRM output is supported since Linux 4.14. Setting a + mask requires at least Linux 4.19. + ''; + tfc_padding = mkParamOfType (with lib.types; either int (enum ["mtu"])) 0 '' Pads ESP packets with additional data to have a consistent ESP packet size for improved Traffic Flow Confidentiality. The padding defines the @@ -946,6 +984,33 @@ in { supported, but the installation does not fail otherwise. ''; + copy_df = mkYesNoParam yes '' + Whether to copy the DF bit to the outer IPv4 header in tunnel mode. This + effectively disables Path MTU discovery (PMTUD). Controlling this + behavior is not supported by all kernel interfaces. + ''; + + copy_ecn = mkYesNoParam yes '' + Whether to copy the ECN (Explicit Congestion Notification) header field + to/from the outer IP header in tunnel mode. Controlling this behavior is + not supported by all kernel interfaces. + ''; + + copy_dscp = mkEnumParam [ "out" "in" "yes" "no" ] "out" '' + Whether to copy the DSCP (Differentiated Services Field Codepoint) + header field to/from the outer IP header in tunnel mode. The value + <literal>out</literal> only copies the field from the inner to the outer + header, the value <literal>in</literal> does the opposite and only + copies the field from the outer to the inner header when decapsulating, + the value <literal>yes</literal> copies the field in both directions, + and the value <literal>no</literal> disables copying the field + altogether. Setting this to <literal>yes</literal> or + <literal>in</literal> could allow an attacker to adversely affect other + traffic at the receiver, which is why the default is + <literal>out</literal>. Controlling this behavior is not supported by + all kernel interfaces. + ''; + start_action = mkEnumParam ["none" "trap" "start"] "none" '' Action to perform after loading the configuration. <itemizedlist> @@ -1060,6 +1125,24 @@ in { defined in a unique section having the <literal>ike</literal> prefix. ''; + ppk = mkPrefixedAttrsOfParams { + secret = mkOptionalStrParam '' + Value of the PPK. It may either be an ASCII string, a hex encoded string + if it has a <literal>0x</literal> prefix or a Base64 encoded string if + it has a <literal>0s</literal> prefix in its value. Should have at least + 256 bits of entropy for 128-bit security. + ''; + + id = mkPrefixedAttrsOfParam (mkOptionalStrParam "") '' + PPK identity the PPK belongs to. Multiple unique identities may be + specified, each having an <literal>id</literal> prefix, if a secret is + shared between multiple peers. + ''; + } '' + Postquantum Preshared Key (PPK) section for a specific secret. Each PPK is + defined in a unique section having the <literal>ppk</literal> prefix. + ''; + private = mkPrefixedAttrsOfParams { file = mkOptionalStrParam '' File name in the private folder for which this passphrase should be used. diff --git a/nixos/modules/services/networking/tinc.nix b/nixos/modules/services/networking/tinc.nix index 35cdddc590b8..3379efd1afce 100644 --- a/nixos/modules/services/networking/tinc.nix +++ b/nixos/modules/services/networking/tinc.nix @@ -148,14 +148,6 @@ in } )); - networking.interfaces = flip mapAttrs' cfg.networks (network: data: nameValuePair - ("tinc.${network}") - ({ - virtual = true; - virtualType = "${data.interfaceType}"; - }) - ); - systemd.services = flip mapAttrs' cfg.networks (network: data: nameValuePair ("tinc.${network}") ({ diff --git a/nixos/modules/services/networking/zerotierone.nix b/nixos/modules/services/networking/zerotierone.nix index a4cd368397e7..764af3846fe5 100644 --- a/nixos/modules/services/networking/zerotierone.nix +++ b/nixos/modules/services/networking/zerotierone.nix @@ -39,7 +39,8 @@ in systemd.services.zerotierone = { description = "ZeroTierOne"; path = [ cfg.package ]; - after = [ "network.target" ]; + bindsTo = [ "network-online.target" ]; + after = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; preStart = '' mkdir -p /var/lib/zerotier-one/networks.d diff --git a/nixos/modules/services/networking/znc.nix b/nixos/modules/services/networking/znc.nix deleted file mode 100644 index f817db2ad000..000000000000 --- a/nixos/modules/services/networking/znc.nix +++ /dev/null @@ -1,431 +0,0 @@ -{ config, lib, pkgs, ...}: - -with lib; - -let - cfg = config.services.znc; - - defaultUser = "znc"; # Default user to own process. - - # Default user and pass: - # un=znc - # pw=nixospass - - defaultUserName = "znc"; - defaultPassBlock = " - <Pass password> - Method = sha256 - Hash = e2ce303c7ea75c571d80d8540a8699b46535be6a085be3414947d638e48d9e93 - Salt = l5Xryew4g*!oa(ECfX2o - </Pass> - "; - - modules = pkgs.buildEnv { - name = "znc-modules"; - paths = cfg.modulePackages; - }; - - # Keep znc.conf in nix store, then symlink or copy into `dataDir`, depending on `mutable`. - mkZncConf = confOpts: '' - Version = 1.6.3 - ${concatMapStrings (n: "LoadModule = ${n}\n") confOpts.modules} - - <Listener l> - Port = ${toString confOpts.port} - IPv4 = true - IPv6 = true - SSL = ${boolToString confOpts.useSSL} - ${lib.optionalString (confOpts.uriPrefix != null) "URIPrefix = ${confOpts.uriPrefix}"} - </Listener> - - <User ${confOpts.userName}> - ${confOpts.passBlock} - Admin = true - Nick = ${confOpts.nick} - AltNick = ${confOpts.nick}_ - Ident = ${confOpts.nick} - RealName = ${confOpts.nick} - ${concatMapStrings (n: "LoadModule = ${n}\n") confOpts.userModules} - - ${ lib.concatStringsSep "\n" (lib.mapAttrsToList (name: net: '' - <Network ${name}> - ${concatMapStrings (m: "LoadModule = ${m}\n") net.modules} - Server = ${net.server} ${lib.optionalString net.useSSL "+"}${toString net.port} ${net.password} - ${concatMapStrings (c: "<Chan #${c}>\n</Chan>\n") net.channels} - ${lib.optionalString net.hasBitlbeeControlChannel '' - <Chan &bitlbee> - </Chan> - ''} - ${net.extraConf} - </Network> - '') confOpts.networks) } - </User> - ${confOpts.extraZncConf} - ''; - - zncConfFile = pkgs.writeTextFile { - name = "znc.conf"; - text = if cfg.zncConf != "" - then cfg.zncConf - else mkZncConf cfg.confOptions; - }; - - networkOpts = { ... }: { - options = { - server = mkOption { - type = types.str; - example = "chat.freenode.net"; - description = '' - IRC server address. - ''; - }; - - port = mkOption { - type = types.int; - default = 6697; - example = 6697; - description = '' - IRC server port. - ''; - }; - - userName = mkOption { - default = ""; - example = "johntron"; - type = types.string; - description = '' - A nick identity specific to the IRC server. - ''; - }; - - password = mkOption { - type = types.str; - default = ""; - description = '' - IRC server password, such as for a Slack gateway. - ''; - }; - - useSSL = mkOption { - type = types.bool; - default = true; - description = '' - Whether to use SSL to connect to the IRC server. - ''; - }; - - modulePackages = mkOption { - type = types.listOf types.package; - default = []; - example = [ "pkgs.zncModules.push" "pkgs.zncModules.fish" ]; - description = '' - External ZNC modules to build. - ''; - }; - - modules = mkOption { - type = types.listOf types.str; - default = [ "simple_away" ]; - example = literalExample "[ simple_away sasl ]"; - description = '' - ZNC modules to load. - ''; - }; - - channels = mkOption { - type = types.listOf types.str; - default = []; - example = [ "nixos" ]; - description = '' - IRC channels to join. - ''; - }; - - hasBitlbeeControlChannel = mkOption { - type = types.bool; - default = false; - description = '' - Whether to add the special Bitlbee operations channel. - ''; - }; - - extraConf = mkOption { - default = ""; - type = types.lines; - example = '' - Encoding = ^UTF-8 - FloodBurst = 4 - FloodRate = 1.00 - IRCConnectEnabled = true - Ident = johntron - JoinDelay = 0 - Nick = johntron - ''; - description = '' - Extra config for the network. - ''; - }; - }; - }; - -in - -{ - - ###### Interface - - options = { - services.znc = { - enable = mkOption { - default = false; - type = types.bool; - description = '' - Enable a ZNC service for a user. - ''; - }; - - user = mkOption { - default = "znc"; - example = "john"; - type = types.string; - description = '' - The name of an existing user account to use to own the ZNC server process. - If not specified, a default user will be created to own the process. - ''; - }; - - group = mkOption { - default = ""; - example = "users"; - type = types.string; - description = '' - Group to own the ZNCserver process. - ''; - }; - - dataDir = mkOption { - default = "/var/lib/znc/"; - example = "/home/john/.znc/"; - type = types.path; - description = '' - The data directory. Used for configuration files and modules. - ''; - }; - - openFirewall = mkOption { - type = types.bool; - default = false; - description = '' - Whether to open ports in the firewall for ZNC. - ''; - }; - - zncConf = mkOption { - default = ""; - example = "See: http://wiki.znc.in/Configuration"; - type = types.lines; - description = '' - Config file as generated with `znc --makeconf` to use for the whole ZNC configuration. - If specified, `confOptions` will be ignored, and this value, as-is, will be used. - If left empty, a conf file with default values will be used. - ''; - }; - - confOptions = { - modules = mkOption { - type = types.listOf types.str; - default = [ "webadmin" "adminlog" ]; - example = [ "partyline" "webadmin" "adminlog" "log" ]; - description = '' - A list of modules to include in the `znc.conf` file. - ''; - }; - - userModules = mkOption { - type = types.listOf types.str; - default = [ "chansaver" "controlpanel" ]; - example = [ "chansaver" "controlpanel" "fish" "push" ]; - description = '' - A list of user modules to include in the `znc.conf` file. - ''; - }; - - userName = mkOption { - default = defaultUserName; - example = "johntron"; - type = types.string; - description = '' - The user name used to log in to the ZNC web admin interface. - ''; - }; - - networks = mkOption { - default = { }; - type = with types; attrsOf (submodule networkOpts); - description = '' - IRC networks to connect the user to. - ''; - example = { - "freenode" = { - server = "chat.freenode.net"; - port = 6697; - useSSL = true; - modules = [ "simple_away" ]; - }; - }; - }; - - nick = mkOption { - default = "znc-user"; - example = "john"; - type = types.string; - description = '' - The IRC nick. - ''; - }; - - passBlock = mkOption { - example = defaultPassBlock; - type = types.string; - description = '' - Generate with `nix-shell -p znc --command "znc --makepass"`. - This is the password used to log in to the ZNC web admin interface. - ''; - }; - - port = mkOption { - default = 5000; - example = 5000; - type = types.int; - description = '' - Specifies the port on which to listen. - ''; - }; - - useSSL = mkOption { - default = true; - type = types.bool; - description = '' - Indicates whether the ZNC server should use SSL when listening on the specified port. A self-signed certificate will be generated. - ''; - }; - - uriPrefix = mkOption { - type = types.nullOr types.str; - default = null; - example = "/znc/"; - description = '' - An optional URI prefix for the ZNC web interface. Can be - used to make ZNC available behind a reverse proxy. - ''; - }; - - extraZncConf = mkOption { - default = ""; - type = types.lines; - description = '' - Extra config to `znc.conf` file. - ''; - }; - }; - - modulePackages = mkOption { - type = types.listOf types.package; - default = [ ]; - example = literalExample "[ pkgs.zncModules.fish pkgs.zncModules.push ]"; - description = '' - A list of global znc module packages to add to znc. - ''; - }; - - mutable = mkOption { - default = true; - type = types.bool; - description = '' - Indicates whether to allow the contents of the `dataDir` directory to be changed - by the user at run-time. - If true, modifications to the ZNC configuration after its initial creation are not - overwritten by a NixOS system rebuild. - If false, the ZNC configuration is rebuilt by every system rebuild. - If the user wants to manage the ZNC service using the web admin interface, this value - should be set to true. - ''; - }; - - extraFlags = mkOption { - default = [ ]; - example = [ "--debug" ]; - type = types.listOf types.str; - description = '' - Extra flags to use when executing znc command. - ''; - }; - }; - }; - - - ###### Implementation - - config = mkIf cfg.enable { - - networking.firewall = mkIf cfg.openFirewall { - allowedTCPPorts = [ cfg.confOptions.port ]; - }; - - systemd.services.znc = { - description = "ZNC Server"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.service" ]; - serviceConfig = { - User = cfg.user; - Group = cfg.group; - Restart = "always"; - ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; - ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID"; - }; - preStart = '' - ${pkgs.coreutils}/bin/mkdir -p ${cfg.dataDir}/configs - - # If mutable, regenerate conf file every time. - ${optionalString (!cfg.mutable) '' - ${pkgs.coreutils}/bin/echo "znc is set to be system-managed. Now deleting old znc.conf file to be regenerated." - ${pkgs.coreutils}/bin/rm -f ${cfg.dataDir}/configs/znc.conf - ''} - - # Ensure essential files exist. - if [[ ! -f ${cfg.dataDir}/configs/znc.conf ]]; then - ${pkgs.coreutils}/bin/echo "No znc.conf file found in ${cfg.dataDir}. Creating one now." - ${pkgs.coreutils}/bin/cp --no-clobber ${zncConfFile} ${cfg.dataDir}/configs/znc.conf - ${pkgs.coreutils}/bin/chmod u+rw ${cfg.dataDir}/configs/znc.conf - ${pkgs.coreutils}/bin/chown ${cfg.user} ${cfg.dataDir}/configs/znc.conf - fi - - if [[ ! -f ${cfg.dataDir}/znc.pem ]]; then - ${pkgs.coreutils}/bin/echo "No znc.pem file found in ${cfg.dataDir}. Creating one now." - ${pkgs.znc}/bin/znc --makepem --datadir ${cfg.dataDir} - fi - - # Symlink modules - rm ${cfg.dataDir}/modules || true - ln -fs ${modules}/lib/znc ${cfg.dataDir}/modules - ''; - script = "${pkgs.znc}/bin/znc --foreground --datadir ${cfg.dataDir} ${toString cfg.extraFlags}"; - }; - - users.users = optional (cfg.user == defaultUser) - { name = defaultUser; - description = "ZNC server daemon owner"; - group = defaultUser; - uid = config.ids.uids.znc; - home = cfg.dataDir; - createHome = true; - }; - - users.groups = optional (cfg.user == defaultUser) - { name = defaultUser; - gid = config.ids.gids.znc; - members = [ defaultUser ]; - }; - - }; -} diff --git a/nixos/modules/services/networking/znc/default.nix b/nixos/modules/services/networking/znc/default.nix new file mode 100644 index 000000000000..bce5b15a19ec --- /dev/null +++ b/nixos/modules/services/networking/znc/default.nix @@ -0,0 +1,306 @@ +{ config, lib, pkgs, ...}: + +with lib; + +let + + cfg = config.services.znc; + + defaultUser = "znc"; + + modules = pkgs.buildEnv { + name = "znc-modules"; + paths = cfg.modulePackages; + }; + + listenerPorts = concatMap (l: optional (l ? Port) l.Port) + (attrValues (cfg.config.Listener or {})); + + # Converts the config option to a string + semanticString = let + + sortedAttrs = set: sort (l: r: + if l == "extraConfig" then false # Always put extraConfig last + else if isAttrs set.${l} == isAttrs set.${r} then l < r + else isAttrs set.${r} # Attrsets should be last, makes for a nice config + # This last case occurs when any side (but not both) is an attrset + # The order of these is correct when the attrset is on the right + # which we're just returning + ) (attrNames set); + + # Specifies an attrset that encodes the value according to its type + encode = name: value: { + null = []; + bool = [ "${name} = ${boolToString value}" ]; + int = [ "${name} = ${toString value}" ]; + + # extraConfig should be inserted verbatim + string = [ (if name == "extraConfig" then value else "${name} = ${value}") ]; + + # Values like `Foo = [ "bar" "baz" ];` should be transformed into + # Foo=bar + # Foo=baz + list = concatMap (encode name) value; + + # Values like `Foo = { bar = { Baz = "baz"; Qux = "qux"; Florps = null; }; };` should be transmed into + # <Foo bar> + # Baz=baz + # Qux=qux + # </Foo> + set = concatMap (subname: [ + "<${name} ${subname}>" + ] ++ map (line: "\t${line}") (toLines value.${subname}) ++ [ + "</${name}>" + ]) (filter (v: v != null) (attrNames value)); + + }.${builtins.typeOf value}; + + # One level "above" encode, acts upon a set and uses encode on each name,value pair + toLines = set: concatMap (name: encode name set.${name}) (sortedAttrs set); + + in + concatStringsSep "\n" (toLines cfg.config); + + semanticTypes = with types; rec { + zncAtom = nullOr (either (either int bool) str); + zncAttr = attrsOf (nullOr zncConf); + zncAll = either (either zncAtom (listOf zncAtom)) zncAttr; + zncConf = attrsOf (zncAll // { + # Since this is a recursive type and the description by default contains + # the description of its subtypes, infinite recursion would occur without + # explicitly breaking this cycle + description = "znc values (null, atoms (str, int, bool), list of atoms, or attrsets of znc values)"; + }); + }; + +in + +{ + + imports = [ ./options.nix ]; + + options = { + services.znc = { + enable = mkEnableOption "ZNC"; + + user = mkOption { + default = "znc"; + example = "john"; + type = types.str; + description = '' + The name of an existing user account to use to own the ZNC server + process. If not specified, a default user will be created. + ''; + }; + + group = mkOption { + default = defaultUser; + example = "users"; + type = types.str; + description = '' + Group to own the ZNC process. + ''; + }; + + dataDir = mkOption { + default = "/var/lib/znc/"; + example = "/home/john/.znc/"; + type = types.path; + description = '' + The state directory for ZNC. The config and the modules will be linked + to from this directory as well. + ''; + }; + + openFirewall = mkOption { + type = types.bool; + default = false; + description = '' + Whether to open ports in the firewall for ZNC. Does work with + ports for listeners specified in + <option>services.znc.config.Listener</option>. + ''; + }; + + config = mkOption { + type = semanticTypes.zncConf; + default = {}; + example = literalExample '' + { + LoadModule = [ "webadmin" "adminlog" ]; + User.paul = { + Admin = true; + Nick = "paul"; + AltNick = "paul1"; + LoadModule = [ "chansaver" "controlpanel" ]; + Network.freenode = { + Server = "chat.freenode.net +6697"; + LoadModule = [ "simple_away" ]; + Chan = { + "#nixos" = { Detached = false; }; + "##linux" = { Disabled = true; }; + }; + }; + Pass.password = { + Method = "sha256"; + Hash = "e2ce303c7ea75c571d80d8540a8699b46535be6a085be3414947d638e48d9e93"; + Salt = "l5Xryew4g*!oa(ECfX2o"; + }; + }; + } + ''; + description = '' + Configuration for ZNC, see + <literal>https://wiki.znc.in/Configuration</literal> for details. The + Nix value declared here will be translated directly to the xml-like + format ZNC expects. This is much more flexible than the legacy options + under <option>services.znc.confOptions.*</option>, but also can't do + any type checking. + </para> + <para> + You can use <command>nix-instantiate --eval --strict '<nixpkgs/nixos>' -A config.services.znc.config</command> + to view the current value. By default it contains a listener for port + 5000 with SSL enabled. + </para> + <para> + Nix attributes called <literal>extraConfig</literal> will be inserted + verbatim into the resulting config file. + </para> + <para> + If <option>services.znc.useLegacyConfig</option> is turned on, the + option values in <option>services.znc.confOptions.*</option> will be + gracefully be applied to this option. + </para> + <para> + If you intend to update the configuration through this option, be sure + to enable <option>services.znc.mutable</option>, otherwise none of the + changes here will be applied after the initial deploy. + ''; + }; + + configFile = mkOption { + type = types.path; + example = "~/.znc/configs/znc.conf"; + description = '' + Configuration file for ZNC. It is recommended to use the + <option>config</option> option instead. + </para> + <para> + Setting this option will override any auto-generated config file + through the <option>confOptions</option> or <option>config</option> + options. + ''; + }; + + modulePackages = mkOption { + type = types.listOf types.package; + default = [ ]; + example = literalExample "[ pkgs.zncModules.fish pkgs.zncModules.push ]"; + description = '' + A list of global znc module packages to add to znc. + ''; + }; + + mutable = mkOption { + default = true; # TODO: Default to true when config is set, make sure to not delete the old config if present + type = types.bool; + description = '' + Indicates whether to allow the contents of the + <literal>dataDir</literal> directory to be changed by the user at + run-time. + </para> + <para> + If enabled, modifications to the ZNC configuration after its initial + creation are not overwritten by a NixOS rebuild. If disabled, the + ZNC configuration is rebuilt on every NixOS rebuild. + </para> + <para> + If the user wants to manage the ZNC service using the web admin + interface, this option should be enabled. + ''; + }; + + extraFlags = mkOption { + default = [ ]; + example = [ "--debug" ]; + type = types.listOf types.str; + description = '' + Extra arguments to use for executing znc. + ''; + }; + }; + }; + + + ###### Implementation + + config = mkIf cfg.enable { + + services.znc = { + configFile = mkDefault (pkgs.writeText "znc-generated.conf" semanticString); + config = { + Version = (builtins.parseDrvName pkgs.znc.name).version; + Listener.l.Port = mkDefault 5000; + Listener.l.SSL = mkDefault true; + }; + }; + + networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall listenerPorts; + + systemd.services.znc = { + description = "ZNC Server"; + wantedBy = [ "multi-user.target" ]; + after = [ "network-online.target" ]; + serviceConfig = { + User = cfg.user; + Group = cfg.group; + Restart = "always"; + ExecStart = "${pkgs.znc}/bin/znc --foreground --datadir ${cfg.dataDir} ${escapeShellArgs cfg.extraFlags}"; + ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID"; + }; + preStart = '' + mkdir -p ${cfg.dataDir}/configs + + # If mutable, regenerate conf file every time. + ${optionalString (!cfg.mutable) '' + echo "znc is set to be system-managed. Now deleting old znc.conf file to be regenerated." + rm -f ${cfg.dataDir}/configs/znc.conf + ''} + + # Ensure essential files exist. + if [[ ! -f ${cfg.dataDir}/configs/znc.conf ]]; then + echo "No znc.conf file found in ${cfg.dataDir}. Creating one now." + cp --no-clobber ${cfg.configFile} ${cfg.dataDir}/configs/znc.conf + chmod u+rw ${cfg.dataDir}/configs/znc.conf + chown ${cfg.user} ${cfg.dataDir}/configs/znc.conf + fi + + if [[ ! -f ${cfg.dataDir}/znc.pem ]]; then + echo "No znc.pem file found in ${cfg.dataDir}. Creating one now." + ${pkgs.znc}/bin/znc --makepem --datadir ${cfg.dataDir} + fi + + # Symlink modules + rm ${cfg.dataDir}/modules || true + ln -fs ${modules}/lib/znc ${cfg.dataDir}/modules + ''; + }; + + users.users = optional (cfg.user == defaultUser) + { name = defaultUser; + description = "ZNC server daemon owner"; + group = defaultUser; + uid = config.ids.uids.znc; + home = cfg.dataDir; + createHome = true; + }; + + users.groups = optional (cfg.user == defaultUser) + { name = defaultUser; + gid = config.ids.gids.znc; + members = [ defaultUser ]; + }; + + }; +} diff --git a/nixos/modules/services/networking/znc/options.nix b/nixos/modules/services/networking/znc/options.nix new file mode 100644 index 000000000000..048dbd738630 --- /dev/null +++ b/nixos/modules/services/networking/znc/options.nix @@ -0,0 +1,270 @@ +{ lib, config, ... }: + +with lib; + +let + + cfg = config.services.znc; + + networkOpts = { + options = { + + server = mkOption { + type = types.str; + example = "chat.freenode.net"; + description = '' + IRC server address. + ''; + }; + + port = mkOption { + type = types.ints.u16; + default = 6697; + description = '' + IRC server port. + ''; + }; + + password = mkOption { + type = types.str; + default = ""; + description = '' + IRC server password, such as for a Slack gateway. + ''; + }; + + useSSL = mkOption { + type = types.bool; + default = true; + description = '' + Whether to use SSL to connect to the IRC server. + ''; + }; + + modules = mkOption { + type = types.listOf types.str; + default = [ "simple_away" ]; + example = literalExample "[ simple_away sasl ]"; + description = '' + ZNC network modules to load. + ''; + }; + + channels = mkOption { + type = types.listOf types.str; + default = []; + example = [ "nixos" ]; + description = '' + IRC channels to join. + ''; + }; + + hasBitlbeeControlChannel = mkOption { + type = types.bool; + default = false; + description = '' + Whether to add the special Bitlbee operations channel. + ''; + }; + + extraConf = mkOption { + default = ""; + type = types.lines; + example = '' + Encoding = ^UTF-8 + FloodBurst = 4 + FloodRate = 1.00 + IRCConnectEnabled = true + Ident = johntron + JoinDelay = 0 + Nick = johntron + ''; + description = '' + Extra config for the network. Consider using + <option>services.znc.config</option> instead. + ''; + }; + }; + }; + +in + +{ + + options = { + services.znc = { + + useLegacyConfig = mkOption { + default = true; + type = types.bool; + description = '' + Whether to propagate the legacy options under + <option>services.znc.confOptions.*</option> to the znc config. If this + is turned on, the znc config will contain a user with the default name + "znc", global modules "webadmin" and "adminlog" will be enabled by + default, and more, all controlled through the + <option>services.znc.confOptions.*</option> options. + You can use <command>nix-instantiate --eval --strict '<nixpkgs/nixos>' -A config.services.znc.config</command> + to view the current value of the config. + </para> + <para> + In any case, if you need more flexibility, + <option>services.znc.config</option> can be used to override/add to + all of the legacy options. + ''; + }; + + confOptions = { + modules = mkOption { + type = types.listOf types.str; + default = [ "webadmin" "adminlog" ]; + example = [ "partyline" "webadmin" "adminlog" "log" ]; + description = '' + A list of modules to include in the `znc.conf` file. + ''; + }; + + userModules = mkOption { + type = types.listOf types.str; + default = [ "chansaver" "controlpanel" ]; + example = [ "chansaver" "controlpanel" "fish" "push" ]; + description = '' + A list of user modules to include in the `znc.conf` file. + ''; + }; + + userName = mkOption { + default = "znc"; + example = "johntron"; + type = types.str; + description = '' + The user name used to log in to the ZNC web admin interface. + ''; + }; + + networks = mkOption { + default = { }; + type = with types; attrsOf (submodule networkOpts); + description = '' + IRC networks to connect the user to. + ''; + example = literalExample '' + { + "freenode" = { + server = "chat.freenode.net"; + port = 6697; + useSSL = true; + modules = [ "simple_away" ]; + }; + }; + ''; + }; + + nick = mkOption { + default = "znc-user"; + example = "john"; + type = types.str; + description = '' + The IRC nick. + ''; + }; + + passBlock = mkOption { + example = literalExample '' + <Pass password> + Method = sha256 + Hash = e2ce303c7ea75c571d80d8540a8699b46535be6a085be3414947d638e48d9e93 + Salt = l5Xryew4g*!oa(ECfX2o + </Pass> + ''; + type = types.str; + description = '' + Generate with `nix-shell -p znc --command "znc --makepass"`. + This is the password used to log in to the ZNC web admin interface. + You can also set this through + <option>services.znc.config.User.<username>.Pass.Method</option> + and co. + ''; + }; + + port = mkOption { + default = 5000; + type = types.int; + description = '' + Specifies the port on which to listen. + ''; + }; + + useSSL = mkOption { + default = true; + type = types.bool; + description = '' + Indicates whether the ZNC server should use SSL when listening on + the specified port. A self-signed certificate will be generated. + ''; + }; + + uriPrefix = mkOption { + type = types.nullOr types.str; + default = null; + example = "/znc/"; + description = '' + An optional URI prefix for the ZNC web interface. Can be + used to make ZNC available behind a reverse proxy. + ''; + }; + + extraZncConf = mkOption { + default = ""; + type = types.lines; + description = '' + Extra config to `znc.conf` file. + ''; + }; + }; + + }; + }; + + config = mkIf cfg.useLegacyConfig { + + services.znc.config = let + c = cfg.confOptions; + # defaults here should override defaults set in the non-legacy part + mkDefault = mkOverride 900; + in { + LoadModule = mkDefault c.modules; + Listener.l = { + Port = mkDefault c.port; + IPv4 = mkDefault true; + IPv6 = mkDefault true; + SSL = mkDefault c.useSSL; + URIPrefix = c.uriPrefix; + }; + User.${c.userName} = { + Admin = mkDefault true; + Nick = mkDefault c.nick; + AltNick = mkDefault "${c.nick}_"; + Ident = mkDefault c.nick; + RealName = mkDefault c.nick; + LoadModule = mkDefault c.userModules; + Network = mapAttrs (name: net: { + LoadModule = mkDefault net.modules; + Server = mkDefault "${net.server} ${optionalString net.useSSL "+"}${toString net.port} ${net.password}"; + Chan = optionalAttrs net.hasBitlbeeControlChannel { "&bitlbee" = mkDefault {}; } // + listToAttrs (map (n: nameValuePair "#${n}" (mkDefault {})) net.channels); + extraConfig = if net.extraConf == "" then mkDefault null else net.extraConf; + }) c.networks; + extraConfig = [ c.passBlock ]; + }; + extraConfig = optional (c.extraZncConf != "") c.extraZncConf; + }; + }; + + imports = [ + (mkRemovedOptionModule ["services" "znc" "zncConf"] '' + Instead of `services.znc.zncConf = "... foo ...";`, use + `services.znc.configFile = pkgs.writeText "znc.conf" "... foo ...";`. + '') + ]; +} diff --git a/nixos/modules/services/security/munge.nix b/nixos/modules/services/security/munge.nix index 5bca15833544..fda864f2c30a 100644 --- a/nixos/modules/services/security/munge.nix +++ b/nixos/modules/services/security/munge.nix @@ -53,8 +53,6 @@ in chmod 0700 ${cfg.password} mkdir -p /var/lib/munge -m 0711 chown -R munge:munge /var/lib/munge - mkdir -p /var/log/munge -m 0700 - chown -R munge:munge /var/log/munge mkdir -p /run/munge -m 0755 chown -R munge:munge /run/munge ''; diff --git a/nixos/modules/services/security/tor.nix b/nixos/modules/services/security/tor.nix index 9b6d4be9bda8..aca2cf8cdeaa 100644 --- a/nixos/modules/services/security/tor.nix +++ b/nixos/modules/services/security/tor.nix @@ -57,6 +57,11 @@ let AutomapHostsSuffixes ${concatStringsSep "," cfg.client.dns.automapHostsSuffixes} ''} '' + # Explicitly disable the SOCKS server if the client is disabled. In + # particular, this makes non-anonymous hidden services possible. + + optionalString (! cfg.client.enable) '' + SOCKSPort 0 + '' # Relay config + optionalString cfg.relay.enable '' ORPort ${toString cfg.relay.port} diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix index db4c8e1a3d85..c7e97bbeba9a 100644 --- a/nixos/modules/services/web-apps/nextcloud.nix +++ b/nixos/modules/services/web-apps/nextcloud.nix @@ -70,7 +70,15 @@ in { ''; }; - nginx.enable = mkEnableOption "nginx vhost management"; + nginx.enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable nginx virtual host management. + Further nginx configuration can be done by adapting <literal>services.nginx.virtualHosts.<name></literal>. + See <xref linkend="opt-services.nginx.virtualHosts"/> for further information. + ''; + }; webfinger = mkOption { type = types.bool; @@ -184,7 +192,7 @@ in { type = types.nullOr types.str; default = null; description = '' - Database password. Use <literal>adminpassFile</literal> to avoid this + Admin password. Use <literal>adminpassFile</literal> to avoid this being world-readable in the <literal>/nix/store</literal>. ''; }; diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index 508398f03ace..6c733f093ba8 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -46,7 +46,7 @@ let configFile = pkgs.writeText "nginx.conf" '' user ${cfg.user} ${cfg.group}; - error_log stderr; + error_log ${cfg.logError}; daemon off; ${cfg.config} @@ -341,6 +341,35 @@ in "; }; + logError = mkOption { + default = "stderr"; + description = " + Configures logging. + The first parameter defines a file that will store the log. The + special value stderr selects the standard error file. Logging to + syslog can be configured by specifying the “syslog:” prefix. + The second parameter determines the level of logging, and can be + one of the following: debug, info, notice, warn, error, crit, + alert, or emerg. Log levels above are listed in the order of + increasing severity. Setting a certain log level will cause all + messages of the specified and more severe log levels to be logged. + If this parameter is omitted then error is used. + "; + }; + + preStart = mkOption { + type = types.lines; + default = '' + test -d ${cfg.stateDir}/logs || mkdir -m 750 -p ${cfg.stateDir}/logs + test `stat -c %a ${cfg.stateDir}` = "750" || chmod 750 ${cfg.stateDir} + test `stat -c %a ${cfg.stateDir}/logs` = "750" || chmod 750 ${cfg.stateDir}/logs + chown -R ${cfg.user}:${cfg.group} ${cfg.stateDir} + ''; + description = " + Shell commands executed before the service's nginx is started. + "; + }; + config = mkOption { default = ""; description = " @@ -608,9 +637,7 @@ in stopIfChanged = false; preStart = '' - mkdir -p ${cfg.stateDir}/logs - chmod 700 ${cfg.stateDir} - chown -R ${cfg.user}:${cfg.group} ${cfg.stateDir} + ${cfg.preStart} ${cfg.package}/bin/nginx -c ${configFile} -p ${cfg.stateDir} -t ''; serviceConfig = { diff --git a/nixos/modules/services/web-servers/tomcat.nix b/nixos/modules/services/web-servers/tomcat.nix index d92ba72a8336..be54e9255c78 100644 --- a/nixos/modules/services/web-servers/tomcat.nix +++ b/nixos/modules/services/web-servers/tomcat.nix @@ -121,6 +121,11 @@ in type = types.str; description = "name of the virtualhost"; }; + aliases = mkOption { + type = types.listOf types.str; + description = "aliases of the virtualhost"; + default = []; + }; webapps = mkOption { type = types.listOf types.path; description = '' @@ -220,10 +225,28 @@ in ${if cfg.serverXml != "" then '' cp -f ${pkgs.writeTextDir "server.xml" cfg.serverXml}/* ${cfg.baseDir}/conf/ - '' else '' - # Create a modified server.xml which also includes all virtual hosts - sed -e "/<Engine name=\"Catalina\" defaultHost=\"localhost\">/a\ ${toString (map (virtualHost: ''<Host name=\"${virtualHost.name}\" appBase=\"virtualhosts/${virtualHost.name}/webapps\" unpackWARs=\"true\" autoDeploy=\"true\" xmlValidation=\"false\" xmlNamespaceAware=\"false\" >${if cfg.logPerVirtualHost then ''<Valve className=\"org.apache.catalina.valves.AccessLogValve\" directory=\"logs/${virtualHost.name}\" prefix=\"${virtualHost.name}_access_log.\" pattern=\"combined\" resolveHosts=\"false\"/>'' else ""}</Host>'') cfg.virtualHosts)}" \ - ${tomcat}/conf/server.xml > ${cfg.baseDir}/conf/server.xml + '' else + let + hostElementForVirtualHost = virtualHost: '' + <Host name="${virtualHost.name}" appBase="virtualhosts/${virtualHost.name}/webapps" + unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false"> + '' + concatStrings (innerElementsForVirtualHost virtualHost) + '' + </Host> + ''; + innerElementsForVirtualHost = virtualHost: + (map (alias: '' + <Alias>${alias}</Alias> + '') virtualHost.aliases) + ++ (optional cfg.logPerVirtualHost '' + <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs/${virtualHost.name}" + prefix="${virtualHost.name}_access_log." pattern="combined" resolveHosts="false"/> + ''); + hostElementsString = concatMapStringsSep "\n" hostElementForVirtualHost cfg.virtualHosts; + hostElementsSedString = replaceStrings ["\n"] ["\\\n"] hostElementsString; + in '' + # Create a modified server.xml which also includes all virtual hosts + sed -e "/<Engine name=\"Catalina\" defaultHost=\"localhost\">/a\\"${escapeShellArg hostElementsSedString} \ + ${tomcat}/conf/server.xml > ${cfg.baseDir}/conf/server.xml '' } ${optionalString (cfg.logDirs != []) '' diff --git a/nixos/modules/services/x11/compton.nix b/nixos/modules/services/x11/compton.nix index 8641c05de52e..cafd8d88ec4d 100644 --- a/nixos/modules/services/x11/compton.nix +++ b/nixos/modules/services/x11/compton.nix @@ -238,6 +238,12 @@ in { description = "Compton composite manager"; wantedBy = [ "graphical-session.target" ]; partOf = [ "graphical-session.target" ]; + + # Temporarily fixes corrupt colours with Mesa 18 + environment = mkIf (cfg.backend == "glx") { + allow_rgb10_configs = "false"; + }; + serviceConfig = { ExecStart = "${cfg.package}/bin/compton --config ${configFile}"; RestartSec = 3; diff --git a/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix b/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix index 013956c05466..d1ee076e9185 100644 --- a/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix +++ b/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix @@ -22,7 +22,7 @@ let # This wrapper ensures that we actually get themes makeWrapper ${pkgs.lightdm_gtk_greeter}/sbin/lightdm-gtk-greeter \ $out/greeter \ - --prefix PATH : "${pkgs.glibc.bin}/bin" \ + --prefix PATH : "${lib.getBin pkgs.stdenv.cc.libc}/bin" \ --set GDK_PIXBUF_MODULE_FILE "${pkgs.librsvg.out}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache" \ --set GTK_PATH "${theme}:${pkgs.gtk3.out}" \ --set GTK_EXE_PREFIX "${theme}" \ diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix index 297e36311656..070a02473437 100644 --- a/nixos/modules/services/x11/xserver.nix +++ b/nixos/modules/services/x11/xserver.nix @@ -631,6 +631,8 @@ in ] ++ optional (elem "virtualbox" cfg.videoDrivers) xorg.xrefresh; + environment.pathsToLink = [ "/share/X11" ]; + xdg = { autostart.enable = true; menus.enable = true; diff --git a/nixos/modules/system/activation/activation-script.nix b/nixos/modules/system/activation/activation-script.nix index b1eaf0189562..74c150a848d1 100644 --- a/nixos/modules/system/activation/activation-script.nix +++ b/nixos/modules/system/activation/activation-script.nix @@ -21,7 +21,8 @@ let [ coreutils gnugrep findutils - glibc # needed for getent + getent + stdenv.cc.libc # nscd in update-users-groups.pl shadow nettools # needed for hostname utillinux # needed for mount and mountpoint diff --git a/nixos/modules/system/boot/loader/raspberrypi/builder_uboot.sh b/nixos/modules/system/boot/loader/raspberrypi/builder_uboot.sh deleted file mode 100644 index 36bf15066274..000000000000 --- a/nixos/modules/system/boot/loader/raspberrypi/builder_uboot.sh +++ /dev/null @@ -1,29 +0,0 @@ -#! @bash@/bin/sh -e - -copyForced() { - local src="$1" - local dst="$2" - cp $src $dst.tmp - mv $dst.tmp $dst -} - -# Call the extlinux builder -"@extlinuxConfBuilder@" "$@" - -# Add the firmware files -fwdir=@firmware@/share/raspberrypi/boot/ -copyForced $fwdir/bootcode.bin /boot/bootcode.bin -copyForced $fwdir/fixup.dat /boot/fixup.dat -copyForced $fwdir/fixup_cd.dat /boot/fixup_cd.dat -copyForced $fwdir/fixup_db.dat /boot/fixup_db.dat -copyForced $fwdir/fixup_x.dat /boot/fixup_x.dat -copyForced $fwdir/start.elf /boot/start.elf -copyForced $fwdir/start_cd.elf /boot/start_cd.elf -copyForced $fwdir/start_db.elf /boot/start_db.elf -copyForced $fwdir/start_x.elf /boot/start_x.elf - -# Add the uboot file -copyForced @uboot@/u-boot.bin /boot/u-boot-rpi.bin - -# Add the config.txt -copyForced @configTxt@ /boot/config.txt diff --git a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.nix b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.nix new file mode 100644 index 000000000000..7eb52e3d021f --- /dev/null +++ b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.nix @@ -0,0 +1,10 @@ +{ pkgs, configTxt }: + +pkgs.substituteAll { + src = ./raspberrypi-builder.sh; + isExecutable = true; + inherit (pkgs) bash; + path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep]; + firmware = pkgs.raspberrypifw; + inherit configTxt; +} diff --git a/nixos/modules/system/boot/loader/raspberrypi/builder.sh b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.sh index 8adc8a6a7e11..0fb07de10c04 100644 --- a/nixos/modules/system/boot/loader/raspberrypi/builder.sh +++ b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.sh @@ -5,15 +5,25 @@ shopt -s nullglob export PATH=/empty for i in @path@; do PATH=$PATH:$i/bin; done -default=$1 -if test -z "$1"; then - echo "Syntax: builder.sh <DEFAULT-CONFIG>" +usage() { + echo "usage: $0 -c <path-to-default-configuration> [-d <boot-dir>]" >&2 exit 1 -fi +} + +default= # Default configuration +target=/boot # Target directory + +while getopts "c:d:" opt; do + case "$opt" in + c) default="$OPTARG" ;; + d) target="$OPTARG" ;; + \?) usage ;; + esac +done echo "updating the boot generations directory..." -mkdir -p /boot/old +mkdir -p $target/old # Convert a path to a file in the Nix store such as # /nix/store/<hash>-<name>/file to <hash>-<name>-<file>. @@ -22,12 +32,12 @@ cleanName() { echo "$path" | sed 's|^/nix/store/||' | sed 's|/|-|g' } -# Copy a file from the Nix store to /boot/kernels. +# Copy a file from the Nix store to $target/kernels. declare -A filesCopied copyToKernelsDir() { local src="$1" - local dst="/boot/old/$(cleanName $src)" + local dst="$target/old/$(cleanName $src)" # Don't copy the file if $dst already exists. This means that we # have to create $dst atomically to prevent partially copied # kernels or initrd if this script is ever interrupted. @@ -47,10 +57,10 @@ copyForced() { mv $dst.tmp $dst } -outdir=/boot/old +outdir=$target/old mkdir -p $outdir || true -# Copy its kernel and initrd to /boot/kernels. +# Copy its kernel and initrd to $target/old. addEntry() { local path="$1" local generation="$2" @@ -74,25 +84,21 @@ addEntry() { echo $initrd > $outdir/$generation-initrd echo $kernel > $outdir/$generation-kernel - if test $(readlink -f "$path") = "$default"; then - if [ @version@ -eq 1 ]; then - copyForced $kernel /boot/kernel.img - else - copyForced $kernel /boot/kernel7.img - fi - copyForced $initrd /boot/initrd - for dtb in $dtb_path/bcm*.dtb; do - dst="/boot/$(basename $dtb)" + if test "$generation" = "default"; then + copyForced $kernel $target/kernel.img + copyForced $initrd $target/initrd + for dtb in $dtb_path/{broadcom,}/bcm*.dtb; do + dst="$target/$(basename $dtb)" copyForced $dtb "$dst" filesCopied[$dst]=1 done - cp "$(readlink -f "$path/init")" /boot/nixos-init - echo "`cat $path/kernel-params` init=$path/init" >/boot/cmdline.txt - - echo "$2" > /boot/defaultgeneration + cp "$(readlink -f "$path/init")" $target/nixos-init + echo "`cat $path/kernel-params` init=$path/init" >$target/cmdline.txt fi } +addEntry $default default + # Add all generations of the system profile to the menu, in reverse # (most recent to least recent) order. for generation in $( @@ -105,21 +111,21 @@ done # Add the firmware files fwdir=@firmware@/share/raspberrypi/boot/ -copyForced $fwdir/bootcode.bin /boot/bootcode.bin -copyForced $fwdir/fixup.dat /boot/fixup.dat -copyForced $fwdir/fixup_cd.dat /boot/fixup_cd.dat -copyForced $fwdir/fixup_db.dat /boot/fixup_db.dat -copyForced $fwdir/fixup_x.dat /boot/fixup_x.dat -copyForced $fwdir/start.elf /boot/start.elf -copyForced $fwdir/start_cd.elf /boot/start_cd.elf -copyForced $fwdir/start_db.elf /boot/start_db.elf -copyForced $fwdir/start_x.elf /boot/start_x.elf +copyForced $fwdir/bootcode.bin $target/bootcode.bin +copyForced $fwdir/fixup.dat $target/fixup.dat +copyForced $fwdir/fixup_cd.dat $target/fixup_cd.dat +copyForced $fwdir/fixup_db.dat $target/fixup_db.dat +copyForced $fwdir/fixup_x.dat $target/fixup_x.dat +copyForced $fwdir/start.elf $target/start.elf +copyForced $fwdir/start_cd.elf $target/start_cd.elf +copyForced $fwdir/start_db.elf $target/start_db.elf +copyForced $fwdir/start_x.elf $target/start_x.elf # Add the config.txt -copyForced @configTxt@ /boot/config.txt +copyForced @configTxt@ $target/config.txt -# Remove obsolete files from /boot and /boot/old. -for fn in /boot/old/*linux* /boot/old/*initrd-initrd* /boot/bcm*.dtb; do +# Remove obsolete files from $target and $target/old. +for fn in $target/old/*linux* $target/old/*initrd-initrd* $target/bcm*.dtb; do if ! test "${filesCopied[$fn]}" = 1; then rm -vf -- "$fn" fi diff --git a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix index 9bec24c53f5b..7e089507ff20 100644 --- a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix +++ b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix @@ -5,25 +5,16 @@ with lib; let cfg = config.boot.loader.raspberryPi; - builderGeneric = pkgs.substituteAll { - src = ./builder.sh; - isExecutable = true; - inherit (pkgs) bash; - path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep]; - firmware = pkgs.raspberrypifw; - version = cfg.version; - inherit configTxt; - }; - inherit (pkgs.stdenv.hostPlatform) platform; - builderUboot = import ./builder_uboot.nix { inherit config; inherit pkgs; inherit configTxt; }; + builderUboot = import ./uboot-builder.nix { inherit pkgs configTxt; inherit (cfg) version; }; + builderGeneric = import ./raspberrypi-builder.nix { inherit pkgs configTxt; }; builder = if cfg.uboot.enable then "${builderUboot} -g ${toString cfg.uboot.configurationLimit} -t ${timeoutStr} -c" else - builderGeneric; + "${builderGeneric} -c"; blCfg = config.boot.loader; timeoutStr = if blCfg.timeout == null then "-1" else toString blCfg.timeout; @@ -43,9 +34,12 @@ let '' + optional isAarch64 '' # Boot in 64-bit mode. arm_control=0x200 - '' + optional cfg.uboot.enable '' + '' + (if cfg.uboot.enable then '' kernel=u-boot-rpi.bin - '' + optional (cfg.firmwareConfig != null) cfg.firmwareConfig); + '' else '' + kernel=kernel.img + initramfs initrd followkernel + '') + optional (cfg.firmwareConfig != null) cfg.firmwareConfig); in @@ -65,7 +59,7 @@ in version = mkOption { default = 2; - type = types.enum [ 1 2 3 ]; + type = types.enum [ 0 1 2 3 ]; description = '' ''; }; diff --git a/nixos/modules/system/boot/loader/raspberrypi/builder_uboot.nix b/nixos/modules/system/boot/loader/raspberrypi/uboot-builder.nix index 47f25a9c2b1b..e929c33c6ee3 100644 --- a/nixos/modules/system/boot/loader/raspberrypi/builder_uboot.nix +++ b/nixos/modules/system/boot/loader/raspberrypi/uboot-builder.nix @@ -1,13 +1,14 @@ -{ config, pkgs, configTxt }: +{ pkgs, version, configTxt }: let - cfg = config.boot.loader.raspberryPi; isAarch64 = pkgs.stdenv.isAarch64; uboot = - if cfg.version == 1 then + if version == 0 then + pkgs.ubootRaspberryPiZero + else if version == 1 then pkgs.ubootRaspberryPi - else if cfg.version == 2 then + else if version == 2 then pkgs.ubootRaspberryPi2 else if isAarch64 then @@ -21,7 +22,7 @@ let }; in pkgs.substituteAll { - src = ./builder_uboot.sh; + src = ./uboot-builder.sh; isExecutable = true; inherit (pkgs) bash; path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep]; @@ -29,6 +30,6 @@ pkgs.substituteAll { inherit uboot; inherit configTxt; inherit extlinuxConfBuilder; - version = cfg.version; + inherit version; } diff --git a/nixos/modules/system/boot/loader/raspberrypi/uboot-builder.sh b/nixos/modules/system/boot/loader/raspberrypi/uboot-builder.sh new file mode 100644 index 000000000000..ea591427179f --- /dev/null +++ b/nixos/modules/system/boot/loader/raspberrypi/uboot-builder.sh @@ -0,0 +1,38 @@ +#! @bash@/bin/sh -e + +target=/boot # Target directory + +while getopts "t:c:d:g:" opt; do + case "$opt" in + d) target="$OPTARG" ;; + *) ;; + esac +done + +copyForced() { + local src="$1" + local dst="$2" + cp $src $dst.tmp + mv $dst.tmp $dst +} + +# Call the extlinux builder +"@extlinuxConfBuilder@" "$@" + +# Add the firmware files +fwdir=@firmware@/share/raspberrypi/boot/ +copyForced $fwdir/bootcode.bin $target/bootcode.bin +copyForced $fwdir/fixup.dat $target/fixup.dat +copyForced $fwdir/fixup_cd.dat $target/fixup_cd.dat +copyForced $fwdir/fixup_db.dat $target/fixup_db.dat +copyForced $fwdir/fixup_x.dat $target/fixup_x.dat +copyForced $fwdir/start.elf $target/start.elf +copyForced $fwdir/start_cd.elf $target/start_cd.elf +copyForced $fwdir/start_db.elf $target/start_db.elf +copyForced $fwdir/start_x.elf $target/start_x.elf + +# Add the uboot file +copyForced @uboot@/u-boot.bin $target/u-boot-rpi.bin + +# Add the config.txt +copyForced @configTxt@ $target/config.txt diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix index f4cf9753c0a1..e7167999a6f8 100644 --- a/nixos/modules/system/boot/stage-1.nix +++ b/nixos/modules/system/boot/stage-1.nix @@ -147,7 +147,7 @@ let ${config.boot.initrd.extraUtilsCommands} # Copy ld manually since it isn't detected correctly - cp -pv ${pkgs.glibc.out}/lib/ld*.so.? $out/lib + cp -pv ${pkgs.stdenv.cc.libc.out}/lib/ld*.so.? $out/lib # Copy all of the needed libraries find $out/bin $out/lib -type f | while read BIN; do diff --git a/nixos/modules/system/boot/systemd-nspawn.nix b/nixos/modules/system/boot/systemd-nspawn.nix index 83fef8354360..4f538ccdbbe1 100644 --- a/nixos/modules/system/boot/systemd-nspawn.nix +++ b/nixos/modules/system/boot/systemd-nspawn.nix @@ -112,9 +112,7 @@ in { environment.etc."systemd/nspawn".source = generateUnits "nspawn" units [] []; - systemd.services."systemd-nspawn@" = { - wantedBy = [ "machine.target" ]; - }; + systemd.targets."multi-user".wants = [ "machines.target "]; }; } diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index a1412bc32904..89f8e8153550 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -387,7 +387,7 @@ let logindHandlerType = types.enum [ "ignore" "poweroff" "reboot" "halt" "kexec" "suspend" - "hibernate" "hybrid-sleep" "lock" + "hibernate" "hybrid-sleep" "suspend-then-hibernate" "lock" ]; in @@ -587,6 +587,15 @@ in ''; }; + services.journald.forwardToSyslog = mkOption { + default = config.services.rsyslogd.enable || config.services.syslog-ng.enable; + defaultText = "config.services.rsyslogd.enable || config.services.syslog-ng.enable"; + type = types.bool; + description = '' + Whether to forward log messages to syslog. + ''; + }; + services.logind.extraConfig = mkOption { default = ""; type = types.lines; @@ -754,6 +763,9 @@ in ForwardToConsole=yes TTYPath=${config.services.journald.console} ''} + ${optionalString (config.services.journald.forwardToSyslog) '' + ForwardToSyslog=yes + ''} ${config.services.journald.extraConfig} ''; diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix index 2b3b09d725c7..8f8c9e23e13e 100644 --- a/nixos/modules/tasks/filesystems/zfs.nix +++ b/nixos/modules/tasks/filesystems/zfs.nix @@ -74,7 +74,7 @@ let importLib = {zpoolCmd, awkCmd, cfgZfs}: '' poolReady() { pool="$1" - state="$("${zpoolCmd}" import | "${awkCmd}" "/pool: $pool/ { found = 1 }; /state:/ { if (found == 1) { print \$2; exit } }; END { if (found == 0) { print \"MISSING\" } }")" + state="$("${zpoolCmd}" import 2>/dev/null | "${awkCmd}" "/pool: $pool/ { found = 1 }; /state:/ { if (found == 1) { print \$2; exit } }; END { if (found == 0) { print \"MISSING\" } }")" if [[ "$state" = "ONLINE" ]]; then return 0 else diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix index e9e935e90202..c92570582f20 100644 --- a/nixos/modules/virtualisation/amazon-image.nix +++ b/nixos/modules/virtualisation/amazon-image.nix @@ -145,8 +145,12 @@ let cfg = config.ec2; in environment.systemPackages = [ pkgs.cryptsetup ]; boot.initrd.supportedFilesystems = [ "unionfs-fuse" ]; - + # EC2 has its own NTP server provided by the hypervisor networking.timeServers = [ "169.254.169.123" ]; + + # udisks has become too bloated to have in a headless system + # (e.g. it depends on GTK+). + services.udisks2.enable = false; }; } diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix index b91165ce3b82..2fcc0f254256 100644 --- a/nixos/modules/virtualisation/containers.nix +++ b/nixos/modules/virtualisation/containers.nix @@ -130,6 +130,7 @@ let --bind-ro=/nix/var/nix/daemon-socket \ --bind="/nix/var/nix/profiles/per-container/$INSTANCE:/nix/var/nix/profiles" \ --bind="/nix/var/nix/gcroots/per-container/$INSTANCE:/nix/var/nix/gcroots" \ + --link-journal=try-guest \ --setenv PRIVATE_NETWORK="$PRIVATE_NETWORK" \ --setenv HOST_BRIDGE="$HOST_BRIDGE" \ --setenv HOST_ADDRESS="$HOST_ADDRESS" \ @@ -242,6 +243,9 @@ let Restart = "on-failure"; + Slice = "machine.slice"; + Delegate = true; + # Hack: we don't want to kill systemd-nspawn, since we call # "machinectl poweroff" in preStop to shut down the # container cleanly. But systemd requires sending a signal @@ -605,7 +609,7 @@ in { config = { config, pkgs, ... }: { services.postgresql.enable = true; - services.postgresql.package = pkgs.postgresql96; + services.postgresql.package = pkgs.postgresql_9_6; system.stateVersion = "17.03"; }; @@ -656,6 +660,8 @@ in serviceConfig = serviceDirectives dummyConfig; }; in { + systemd.targets."multi-user".wants = [ "machines.target" ]; + systemd.services = listToAttrs (filter (x: x.value != null) ( # The generic container template used by imperative containers [{ name = "container@"; value = unit; }] @@ -679,7 +685,7 @@ in } // ( if config.autoStart then { - wantedBy = [ "multi-user.target" ]; + wantedBy = [ "machines.target" ]; wants = [ "network.target" ]; after = [ "network.target" ]; restartTriggers = [ config.path ]; diff --git a/nixos/modules/virtualisation/ec2-amis.nix b/nixos/modules/virtualisation/ec2-amis.nix index 76facac39fc6..aaea06bb9a63 100644 --- a/nixos/modules/virtualisation/ec2-amis.nix +++ b/nixos/modules/virtualisation/ec2-amis.nix @@ -257,5 +257,22 @@ let self = { "18.03".sa-east-1.hvm-ebs = "ami-163e1f7a"; "18.03".ap-south-1.hvm-ebs = "ami-6a390b05"; - latest = self."18.03"; + # 18.09.910.c15e342304a + "18.09".eu-west-1.hvm-ebs = "ami-0f412186fb8a0ec97"; + "18.09".eu-west-2.hvm-ebs = "ami-0dada3805ce43c55e"; + "18.09".eu-west-3.hvm-ebs = "ami-074df85565f2e02e2"; + "18.09".eu-central-1.hvm-ebs = "ami-07c9b884e679df4f8"; + "18.09".us-east-1.hvm-ebs = "ami-009c9c3f1af480ff3"; + "18.09".us-east-2.hvm-ebs = "ami-08199961085ea8bc6"; + "18.09".us-west-1.hvm-ebs = "ami-07aa7f56d612ddd38"; + "18.09".us-west-2.hvm-ebs = "ami-01c84b7c368ac24d1"; + "18.09".ca-central-1.hvm-ebs = "ami-04f66113f76198f6c"; + "18.09".ap-southeast-1.hvm-ebs = "ami-0892c7e24ebf2194f"; + "18.09".ap-southeast-2.hvm-ebs = "ami-010730f36424b0a2c"; + "18.09".ap-northeast-1.hvm-ebs = "ami-0cdba8e998f076547"; + "18.09".ap-northeast-2.hvm-ebs = "ami-0400a698e6a9f4a15"; + "18.09".sa-east-1.hvm-ebs = "ami-0e4a8a47fd6db6112"; + "18.09".ap-south-1.hvm-ebs = "ami-0880a678d3f555313"; + + latest = self."18.09"; }; in self diff --git a/nixos/modules/virtualisation/kvmgt.nix b/nixos/modules/virtualisation/kvmgt.nix index fc0bedb68bd0..132815a0ad63 100644 --- a/nixos/modules/virtualisation/kvmgt.nix +++ b/nixos/modules/virtualisation/kvmgt.nix @@ -50,11 +50,17 @@ in { nameValuePair "kvmgt-${name}" { description = "KVMGT VGPU ${name}"; serviceConfig = { - Type = "oneshot"; + Type = "forking"; RemainAfterExit = true; + Restart = "on-failure"; + RestartSec = 5; ExecStart = "${pkgs.runtimeShell} -c 'echo ${value.uuid} > /sys/bus/pci/devices/${cfg.device}/mdev_supported_types/${name}/create'"; ExecStop = "${pkgs.runtimeShell} -c 'echo 1 > /sys/bus/pci/devices/${cfg.device}/${value.uuid}/remove'"; }; + unitConfig = { + StartLimitBurst = 5; + StartLimitIntervalSec = 30; + }; wantedBy = [ "multi-user.target" ]; } ) cfg.vgpus; diff --git a/nixos/modules/virtualisation/libvirtd.nix b/nixos/modules/virtualisation/libvirtd.nix index 3e38662f5b0f..f4d7af1664af 100644 --- a/nixos/modules/virtualisation/libvirtd.nix +++ b/nixos/modules/virtualisation/libvirtd.nix @@ -196,6 +196,8 @@ in { wantedBy = [ "multi-user.target" ]; path = with pkgs; [ coreutils libvirt gawk ]; restartIfChanged = false; + + environment.ON_SHUTDOWN = "${cfg.onShutdown}"; }; systemd.sockets.virtlogd = { diff --git a/nixos/modules/virtualisation/virtualbox-image.nix b/nixos/modules/virtualisation/virtualbox-image.nix index 60048911658c..037c0d2f0d82 100644 --- a/nixos/modules/virtualisation/virtualbox-image.nix +++ b/nixos/modules/virtualisation/virtualbox-image.nix @@ -12,7 +12,7 @@ in { virtualbox = { baseImageSize = mkOption { type = types.int; - default = 10 * 1024; + default = 50 * 1024; description = '' The size of the VirtualBox base image in MiB. ''; @@ -61,7 +61,7 @@ in { export HOME=$PWD export PATH=${pkgs.virtualbox}/bin:$PATH - echo "creating VirtualBox pass-through disk wrapper (no copying invovled)..." + echo "creating VirtualBox pass-through disk wrapper (no copying involved)..." VBoxManage internalcommands createrawvmdk -filename disk.vmdk -rawdisk $diskImage echo "creating VirtualBox VM..." @@ -72,9 +72,9 @@ in { --memory ${toString cfg.memorySize} --acpi on --vram 32 \ ${optionalString (pkgs.stdenv.hostPlatform.system == "i686-linux") "--pae on"} \ --nictype1 virtio --nic1 nat \ - --audiocontroller ac97 --audio alsa \ + --audiocontroller ac97 --audio alsa --audioout on \ --rtcuseutc on \ - --usb on --mouse usbtablet + --usb on --usbehci on --mouse usbtablet VBoxManage storagectl "$vmName" --name SATA --add sata --portcount 4 --bootable on --hostiocache on VBoxManage storageattach "$vmName" --storagectl SATA --port 0 --device 0 --type hdd \ --medium disk.vmdk @@ -82,7 +82,7 @@ in { echo "exporting VirtualBox VM..." mkdir -p $out fn="$out/${cfg.vmFileName}" - VBoxManage export "$vmName" --output "$fn" + VBoxManage export "$vmName" --output "$fn" --options manifest rm -v $diskImage diff --git a/nixos/release.nix b/nixos/release.nix index 5412080cca18..51505d6aab9d 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -399,6 +399,7 @@ in rec { tests.radicale = callTest tests/radicale.nix {}; tests.redmine = callTest tests/redmine.nix {}; tests.rspamd = callSubTests tests/rspamd.nix {}; + tests.rsyslogd = callSubTests tests/rsyslogd.nix {}; tests.runInMachine = callTest tests/run-in-machine.nix {}; tests.rxe = callTest tests/rxe.nix {}; tests.samba = callTest tests/samba.nix {}; @@ -467,7 +468,7 @@ in rec { { services.httpd.enable = true; services.httpd.adminAddr = "foo@example.org"; services.postgresql.enable = true; - services.postgresql.package = pkgs.postgresql93; + services.postgresql.package = pkgs.postgresql_9_3; environment.systemPackages = [ pkgs.php ]; }); }; diff --git a/nixos/tests/ceph.nix b/nixos/tests/ceph.nix index dd45f0157b01..7408029c460e 100644 --- a/nixos/tests/ceph.nix +++ b/nixos/tests/ceph.nix @@ -10,9 +10,8 @@ import ./make-test.nix ({pkgs, ...}: rec { emptyDiskImages = [ 20480 20480 ]; vlans = [ 1 ]; }; - + networking = { - firewall.allowPing = true; useDHCP = false; interfaces.eth1.ipv4.addresses = pkgs.lib.mkOverride 0 [ { address = "192.168.1.1"; prefixLength = 24; } @@ -54,7 +53,7 @@ import ./make-test.nix ({pkgs, ...}: rec { }; }; }; - + testScript = { ... }: '' startAll; @@ -83,7 +82,7 @@ import ./make-test.nix ({pkgs, ...}: rec { # Can't check ceph status until a mon is up $aio->succeed("ceph -s | grep 'mon: 1 daemons'"); - + # Start the ceph-mgr daemon, it has no deps and hardly any setup $aio->mustSucceed( "ceph auth get-or-create mgr.aio mon 'allow profile mgr' osd 'allow *' mds 'allow *' > /var/lib/ceph/mgr/ceph-aio/keyring", diff --git a/nixos/tests/chromium.nix b/nixos/tests/chromium.nix index c341e83961a8..e5097609fb27 100644 --- a/nixos/tests/chromium.nix +++ b/nixos/tests/chromium.nix @@ -12,8 +12,10 @@ with pkgs.lib; mapAttrs (channel: chromiumPkg: makeTest rec { name = "chromium-${channel}"; - meta = with pkgs.stdenv.lib.maintainers; { - maintainers = [ aszlig ]; + meta = { + maintainers = with maintainers; [ aszlig ]; + # https://github.com/NixOS/hydra/issues/591#issuecomment-435125621 + inherit (chromiumPkg.meta) timeout; }; enableOCR = true; @@ -166,7 +168,7 @@ mapAttrs (channel: chromiumPkg: makeTest rec { my $clipboard = $machine->succeed(ru "${pkgs.xclip}/bin/xclip -o"); die "sandbox not working properly: $clipboard" - unless $clipboard =~ /namespace sandbox.*yes/mi + unless $clipboard =~ /layer 1 sandbox.*namespace/mi && $clipboard =~ /pid namespaces.*yes/mi && $clipboard =~ /network namespaces.*yes/mi && $clipboard =~ /seccomp.*sandbox.*yes/mi @@ -184,7 +186,7 @@ mapAttrs (channel: chromiumPkg: makeTest rec { my $clipboard = $machine->succeed(ru "${pkgs.xclip}/bin/xclip -o"); die "copying twice in a row does not work properly: $clipboard" - unless $clipboard =~ /namespace sandbox.*yes/mi + unless $clipboard =~ /layer 1 sandbox.*namespace/mi && $clipboard =~ /pid namespaces.*yes/mi && $clipboard =~ /network namespaces.*yes/mi && $clipboard =~ /seccomp.*sandbox.*yes/mi diff --git a/nixos/tests/cjdns.nix b/nixos/tests/cjdns.nix index ab5f8e0bcf3e..e03bb9882540 100644 --- a/nixos/tests/cjdns.nix +++ b/nixos/tests/cjdns.nix @@ -13,9 +13,6 @@ let # CJDNS output is incompatible with the XML log. systemd.services.cjdns.serviceConfig.StandardOutput = "null"; - #networking.firewall.enable = true; - networking.firewall.allowPing = true; - #networking.firewall.rejectPackets = true; }; in diff --git a/nixos/tests/containers-bridge.nix b/nixos/tests/containers-bridge.nix index bd8bd5dee9c8..777cf9a7e7f9 100644 --- a/nixos/tests/containers-bridge.nix +++ b/nixos/tests/containers-bridge.nix @@ -42,7 +42,6 @@ import ./make-test.nix ({ pkgs, ...} : { { services.httpd.enable = true; services.httpd.adminAddr = "foo@example.org"; networking.firewall.allowedTCPPorts = [ 80 ]; - networking.firewall.allowPing = true; }; }; diff --git a/nixos/tests/containers-extra_veth.nix b/nixos/tests/containers-extra_veth.nix index 8f874b3585dc..b4c48afe48ba 100644 --- a/nixos/tests/containers-extra_veth.nix +++ b/nixos/tests/containers-extra_veth.nix @@ -43,7 +43,6 @@ import ./make-test.nix ({ pkgs, ...} : { config = { networking.firewall.allowedTCPPorts = [ 80 ]; - networking.firewall.allowPing = true; }; }; diff --git a/nixos/tests/containers-ipv4.nix b/nixos/tests/containers-ipv4.nix index 4affe3d9d56d..5f83a33b1079 100644 --- a/nixos/tests/containers-ipv4.nix +++ b/nixos/tests/containers-ipv4.nix @@ -20,7 +20,6 @@ import ./make-test.nix ({ pkgs, ...} : { { services.httpd.enable = true; services.httpd.adminAddr = "foo@example.org"; networking.firewall.allowedTCPPorts = [ 80 ]; - networking.firewall.allowPing = true; system.stateVersion = "18.03"; }; }; diff --git a/nixos/tests/containers-ipv6.nix b/nixos/tests/containers-ipv6.nix index 7db389a18e72..5866e51b731d 100644 --- a/nixos/tests/containers-ipv6.nix +++ b/nixos/tests/containers-ipv6.nix @@ -25,7 +25,6 @@ import ./make-test.nix ({ pkgs, ...} : { { services.httpd.enable = true; services.httpd.adminAddr = "foo@example.org"; networking.firewall.allowedTCPPorts = [ 80 ]; - networking.firewall.allowPing = true; }; }; diff --git a/nixos/tests/containers-portforward.nix b/nixos/tests/containers-portforward.nix index be83f82445ed..d2dda926fc0e 100644 --- a/nixos/tests/containers-portforward.nix +++ b/nixos/tests/containers-portforward.nix @@ -28,7 +28,6 @@ import ./make-test.nix ({ pkgs, ...} : { { services.httpd.enable = true; services.httpd.adminAddr = "foo@example.org"; networking.firewall.allowedTCPPorts = [ 80 ]; - networking.firewall.allowPing = true; }; }; diff --git a/nixos/tests/containers-restart_networking.nix b/nixos/tests/containers-restart_networking.nix index aeb0a6e68e21..0fb3b591e9f9 100644 --- a/nixos/tests/containers-restart_networking.nix +++ b/nixos/tests/containers-restart_networking.nix @@ -10,7 +10,6 @@ let hostBridge = "br0"; config = { networking.firewall.enable = false; - networking.firewall.allowPing = true; networking.interfaces.eth0.ipv4.addresses = [ { address = "192.168.1.122"; prefixLength = 24; } ]; diff --git a/nixos/tests/home-assistant.nix b/nixos/tests/home-assistant.nix index 2d74b59bca46..0b3da0d59c68 100644 --- a/nixos/tests/home-assistant.nix +++ b/nixos/tests/home-assistant.nix @@ -74,7 +74,6 @@ in { print "$log\n"; # Check that no errors were logged - # The timer can get out of sync due to Hydra's load, so this error is ignored - $hass->fail("cat ${configDir}/home-assistant.log | grep -vF 'Timer got out of sync' | grep -qF ERROR"); + $hass->fail("cat ${configDir}/home-assistant.log | grep -qF ERROR"); ''; }) diff --git a/nixos/tests/nat.nix b/nixos/tests/nat.nix index 9c280fe8b5b6..04b4f0f045f0 100644 --- a/nixos/tests/nat.nix +++ b/nixos/tests/nat.nix @@ -11,7 +11,6 @@ import ./make-test.nix ({ pkgs, lib, withFirewall, withConntrackHelpers ? false, lib.mkMerge [ { virtualisation.vlans = [ 2 1 ]; networking.firewall.enable = withFirewall; - networking.firewall.allowPing = true; networking.nat.internalIPs = [ "192.168.1.0/24" ]; networking.nat.externalInterface = "eth1"; } @@ -33,7 +32,6 @@ import ./make-test.nix ({ pkgs, lib, withFirewall, withConntrackHelpers ? false, { pkgs, nodes, ... }: lib.mkMerge [ { virtualisation.vlans = [ 1 ]; - networking.firewall.allowPing = true; networking.defaultGateway = (pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ipv4.addresses).address; } diff --git a/nixos/tests/networking.nix b/nixos/tests/networking.nix index 87a8c4c0e196..d1d4fd41dda6 100644 --- a/nixos/tests/networking.nix +++ b/nixos/tests/networking.nix @@ -17,7 +17,6 @@ let networking = { useDHCP = false; useNetworkd = networkd; - firewall.allowPing = true; firewall.checkReversePath = true; firewall.allowedUDPPorts = [ 547 ]; interfaces = mkOverride 0 (listToAttrs (flip map vlanIfs (n: @@ -86,7 +85,6 @@ let virtualisation.vlans = [ 1 2 ]; networking = { useNetworkd = networkd; - firewall.allowPing = true; useDHCP = false; defaultGateway = "192.168.1.1"; interfaces.eth1.ipv4.addresses = mkOverride 0 [ @@ -139,7 +137,6 @@ let virtualisation.vlans = [ 1 2 ]; networking = { useNetworkd = networkd; - firewall.allowPing = true; useDHCP = true; interfaces.eth1 = { ipv4.addresses = mkOverride 0 [ ]; @@ -194,7 +191,6 @@ let virtualisation.vlans = [ 1 2 ]; networking = { useNetworkd = networkd; - firewall.allowPing = true; useDHCP = false; interfaces.eth1 = { ipv4.addresses = mkOverride 0 [ ]; @@ -234,7 +230,6 @@ let virtualisation.vlans = [ 1 2 ]; networking = { useNetworkd = networkd; - firewall.allowPing = true; useDHCP = false; bonds.bond = { interfaces = [ "eth1" "eth2" ]; @@ -271,7 +266,6 @@ let virtualisation.vlans = [ vlan ]; networking = { useNetworkd = networkd; - firewall.allowPing = true; useDHCP = false; interfaces.eth1.ipv4.addresses = mkOverride 0 [ { inherit address; prefixLength = 24; } ]; @@ -285,7 +279,6 @@ let virtualisation.vlans = [ 1 2 ]; networking = { useNetworkd = networkd; - firewall.allowPing = true; useDHCP = false; bridges.bridge.interfaces = [ "eth1" "eth2" ]; interfaces.eth1.ipv4.addresses = mkOverride 0 [ ]; @@ -329,7 +322,6 @@ let # reverse path filtering rules for the macvlan interface seem # to be incorrect, causing the test to fail. Disable temporarily. firewall.checkReversePath = false; - firewall.allowPing = true; useDHCP = true; macvlans.macvlan.interface = "eth1"; interfaces.eth1.ipv4.addresses = mkOverride 0 [ ]; @@ -415,7 +407,6 @@ let #virtualisation.vlans = [ 1 ]; networking = { useNetworkd = networkd; - firewall.allowPing = true; useDHCP = false; vlans.vlan = { id = 1; diff --git a/nixos/tests/opensmtpd.nix b/nixos/tests/opensmtpd.nix index 4c0cbca21010..4d3479168f70 100644 --- a/nixos/tests/opensmtpd.nix +++ b/nixos/tests/opensmtpd.nix @@ -17,11 +17,12 @@ import ./make-test.nix { extraServerArgs = [ "-v" ]; serverConfiguration = '' listen on 0.0.0.0 + action do_relay relay # DO NOT DO THIS IN PRODUCTION! # Setting up authentication requires a certificate which is painful in # a test environment, but THIS WOULD BE DANGEROUS OUTSIDE OF A # WELL-CONTROLLED ENVIRONMENT! - accept from any for any relay + match from any for any action do_relay ''; }; }; @@ -41,8 +42,9 @@ import ./make-test.nix { extraServerArgs = [ "-v" ]; serverConfiguration = '' listen on 0.0.0.0 - accept from any for local deliver to mda \ + action dovecot_deliver mda \ "${pkgs.dovecot}/libexec/dovecot/deliver -d %{user.username}" + match from any for local action dovecot_deliver ''; }; services.dovecot2 = { diff --git a/nixos/tests/plasma5.nix b/nixos/tests/plasma5.nix index eb705536827e..788c8719c8d2 100644 --- a/nixos/tests/plasma5.nix +++ b/nixos/tests/plasma5.nix @@ -26,31 +26,20 @@ import ./make-test.nix ({ pkgs, ...} : services.xserver.displayManager.sddm.theme = "breeze-ocr-theme"; services.xserver.desktopManager.plasma5.enable = true; services.xserver.desktopManager.default = "plasma5"; + services.xserver.displayManager.sddm.autoLogin = { + enable = true; + user = "alice"; + }; virtualisation.memorySize = 1024; environment.systemPackages = [ sddm_theme ]; - - # fontconfig-penultimate-0.3.3 -> 0.3.4 broke OCR apparently, but no idea why. - nixpkgs.config.packageOverrides = superPkgs: { - fontconfig-penultimate = superPkgs.fontconfig-penultimate.override { - version = "0.3.3"; - sha256 = "1z76jbkb0nhf4w7fy647yyayqr4q02fgk6w58k0yi700p0m3h4c9"; - }; - }; }; - enableOCR = true; - testScript = { nodes, ... }: let user = nodes.machine.config.users.users.alice; xdo = "${pkgs.xdotool}/bin/xdotool"; in '' startAll; - # Wait for display manager to start - $machine->waitForText(qr/${user.description}/); - $machine->screenshot("sddm"); - - # Log in - $machine->sendChars("${user.password}\n"); + # wait for log in $machine->waitForFile("/home/alice/.Xauthority"); $machine->succeed("xauth merge ~alice/.Xauthority"); diff --git a/nixos/tests/postgis.nix b/nixos/tests/postgis.nix index f8b63c5b6a27..49be0672a8e5 100644 --- a/nixos/tests/postgis.nix +++ b/nixos/tests/postgis.nix @@ -9,7 +9,7 @@ import ./make-test.nix ({ pkgs, ...} : { { pkgs, ... }: { - services.postgresql = let mypg = pkgs.postgresql100; in { + services.postgresql = let mypg = pkgs.postgresql_11; in { enable = true; package = mypg; extraPlugins = [ (pkgs.postgis.override { postgresql = mypg; }) ]; diff --git a/nixos/tests/quagga.nix b/nixos/tests/quagga.nix index 0ff14a21584a..6aee7ea57f03 100644 --- a/nixos/tests/quagga.nix +++ b/nixos/tests/quagga.nix @@ -66,7 +66,6 @@ import ./make-test.nix ({ pkgs, ... }: virtualisation.vlans = [ 3 ]; networking.defaultGateway = ifAddr nodes.router2 "eth1"; networking.firewall.allowedTCPPorts = [ 80 ]; - networking.firewall.allowPing = true; services.httpd.enable = true; services.httpd.adminAddr = "foo@example.com"; }; diff --git a/nixos/tests/rsyslogd.nix b/nixos/tests/rsyslogd.nix new file mode 100644 index 000000000000..969d59e0f2c2 --- /dev/null +++ b/nixos/tests/rsyslogd.nix @@ -0,0 +1,38 @@ +{ system ? builtins.currentSystem }: + +with import ../lib/testing.nix { inherit system; }; +with pkgs.lib; +{ + test1 = makeTest { + name = "rsyslogd-test1"; + meta.maintainers = [ maintainers.aanderse ]; + + machine = + { config, pkgs, ... }: + { services.rsyslogd.enable = true; + services.journald.forwardToSyslog = false; + }; + + # ensure rsyslogd isn't receiving messages from journald if explicitly disabled + testScript = '' + $machine->waitForUnit("default.target"); + $machine->fail("test -f /var/log/messages"); + ''; + }; + + test2 = makeTest { + name = "rsyslogd-test2"; + meta.maintainers = [ maintainers.aanderse ]; + + machine = + { config, pkgs, ... }: + { services.rsyslogd.enable = true; + }; + + # ensure rsyslogd is receiving messages from journald + testScript = '' + $machine->waitForUnit("default.target"); + $machine->succeed("test -f /var/log/messages"); + ''; + }; +} diff --git a/nixos/tests/slurm.nix b/nixos/tests/slurm.nix index 60f44c3c8459..7f9c266cbff6 100644 --- a/nixos/tests/slurm.nix +++ b/nixos/tests/slurm.nix @@ -1,22 +1,27 @@ -import ./make-test.nix ({ ... }: -let mungekey = "mungeverryweakkeybuteasytointegratoinatest"; +import ./make-test.nix ({ lib, ... }: +let + mungekey = "mungeverryweakkeybuteasytointegratoinatest"; + slurmconfig = { controlMachine = "control"; - nodeName = '' - control - NodeName=node[1-3] CPUs=1 State=UNKNOWN + nodeName = [ "node[1-3] CPUs=1 State=UNKNOWN" ]; + partitionName = [ "debug Nodes=node[1-3] Default=YES MaxTime=INFINITE State=UP" ]; + extraConfig = '' + AccountingStorageHost=dbd + AccountingStorageType=accounting_storage/slurmdbd ''; - partitionName = "debug Nodes=node[1-3] Default=YES MaxTime=INFINITE State=UP"; }; in { name = "slurm"; + meta.maintainers = [ lib.maintainers.markuskowa ]; + nodes = let computeNode = { ...}: { - # TODO slrumd port and slurmctld port should be configurations and + # TODO slurmd port and slurmctld port should be configurations and # automatically allowed by the firewall. networking.firewall.enable = false; services.slurm = { @@ -43,6 +48,24 @@ in { } // slurmconfig; }; + dbd = + { pkgs, ... } : + { + networking.firewall.enable = false; + services.slurm.dbdserver = { + enable = true; + }; + services.mysql = { + enable = true; + package = pkgs.mysql; + ensureDatabases = [ "slurm_acct_db" ]; + ensureUsers = [{ + ensurePermissions = { "slurm_acct_db.*" = "ALL PRIVILEGES"; }; + name = "slurm"; + }]; + }; + }; + node1 = computeNode; node2 = computeNode; node3 = computeNode; @@ -54,7 +77,7 @@ in { startAll; # Set up authentification across the cluster - foreach my $node (($submit,$control,$node1,$node2,$node3)) + foreach my $node (($submit,$control,$dbd,$node1,$node2,$node3)) { $node->waitForUnit("default.target"); @@ -63,10 +86,22 @@ in { $node->succeed("chmod 0400 /etc/munge/munge.key"); $node->succeed("chown munge:munge /etc/munge/munge.key"); $node->succeed("systemctl restart munged"); - } + + $node->waitForUnit("munged"); + }; # Restart the services since they have probably failed due to the munge init # failure + subtest "can_start_slurmdbd", sub { + $dbd->succeed("systemctl restart slurmdbd"); + $dbd->waitForUnit("slurmdbd.service"); + }; + + # there needs to be an entry for the current + # cluster in the database before slurmctld is restarted + subtest "add_account", sub { + $control->succeed("sacctmgr -i add cluster default"); + }; subtest "can_start_slurmctld", sub { $control->succeed("systemctl restart slurmctld"); @@ -81,12 +116,17 @@ in { } }; - # Test that the cluster work and can distribute jobs; + # Test that the cluster works and can distribute jobs; subtest "run_distributed_command", sub { # Run `hostname` on 3 nodes of the partition (so on all the 3 nodes). # The output must contain the 3 different names $submit->succeed("srun -N 3 hostname | sort | uniq | wc -l | xargs test 3 -eq"); }; + + subtest "check_slurm_dbd", sub { + # find the srun job from above in the database + $submit->succeed("sacct | grep hostname"); + }; ''; }) |