diff options
Diffstat (limited to 'nixos')
63 files changed, 1486 insertions, 494 deletions
diff --git a/nixos/doc/manual/installation/installing.xml b/nixos/doc/manual/installation/installing.xml index 6066d025adbf..6f8e0f613b19 100644 --- a/nixos/doc/manual/installation/installing.xml +++ b/nixos/doc/manual/installation/installing.xml @@ -326,10 +326,9 @@ Retype new UNIX password: *** </screen> <note> <para> - To prevent the password prompt, set - <code><xref linkend="opt-users.mutableUsers"/> = false;</code> in - <filename>configuration.nix</filename>, which allows unattended - installation necessary in automation. + For unattended installations, it is possible to use + <command>nixos-install --no-root-passwd</command> + in order to disable the password prompt entirely. </para> </note> </para> diff --git a/nixos/doc/manual/manual.xml b/nixos/doc/manual/manual.xml index 61b21203f500..e9338efbc025 100644 --- a/nixos/doc/manual/manual.xml +++ b/nixos/doc/manual/manual.xml @@ -17,8 +17,8 @@ <para> If you encounter problems, please report them on the <literal - xlink:href="https://groups.google.com/forum/#!forum/nix-devel">nix-devel</literal> - mailing list or on the <link + xlink:href="https://discourse.nixos.org">Discourse</literal> + or on the <link xlink:href="irc://irc.freenode.net/#nixos"> <literal>#nixos</literal> channel on Freenode</link>. Bugs should be reported in diff --git a/nixos/doc/manual/release-notes/rl-1809.xml b/nixos/doc/manual/release-notes/rl-1809.xml index 0cb4874a1a21..db9e13da0654 100644 --- a/nixos/doc/manual/release-notes/rl-1809.xml +++ b/nixos/doc/manual/release-notes/rl-1809.xml @@ -111,6 +111,12 @@ $ nix-instantiate -E '(import <nixpkgsunstable> {}).gitFull' <link xlink:href="https://github.com/strongswan/strongswan/blob/master/README_LEGACY.md">stroke configuration interface</link>. </para> </listitem> + <listitem> + <para> + The new <varname>services.elasticsearch-curator</varname> service + periodically curates or manages, your Elasticsearch indices and snapshots. + </para> + </listitem> </itemizedlist> </section> @@ -192,6 +198,39 @@ $ nix-instantiate -E '(import <nixpkgsunstable> {}).gitFull' </listitem> <listitem> <para> + The ELK stack: <varname>elasticsearch</varname>, <varname>logstash</varname> and <varname>kibana</varname> + has been upgraded from 2.* to 6.3.*. + The 2.* versions have been <link xlink:href="https://www.elastic.co/support/eol">unsupported since last year</link> + so they have been removed. You can still use the 5.* versions under the names + <varname>elasticsearch5</varname>, <varname>logstash5</varname> and + <varname>kibana5</varname>. + </para> + <para> + The elastic beats: + <varname>filebeat</varname>, <varname>heartbeat</varname>, + <varname>metricbeat</varname> and <varname>packetbeat</varname> + have had the same treatment: they now target 6.3.* as well. + The 5.* versions are available under the names: + <varname>filebeat5</varname>, <varname>heartbeat5</varname>, + <varname>metricbeat5</varname> and <varname>packetbeat5</varname> + </para> + <para> + The ELK-6.3 stack now comes with + <link xlink:href="https://www.elastic.co/products/x-pack/open">X-Pack by default</link>. + Since X-Pack is licensed under the + <link xlink:href="https://github.com/elastic/elasticsearch/blob/master/licenses/ELASTIC-LICENSE.txt">Elastic License</link> + the ELK packages now have an unfree license. To use them you need to specify + <literal>allowUnfree = true;</literal> in your nixpkgs configuration. + </para> + <para> + Fortunately there is also a free variant of the ELK stack without X-Pack. + The packages are available under the names: + <varname>elasticsearch-oss</varname>, <varname>logstash-oss</varname> and + <varname>kibana-oss</varname>. + </para> + </listitem> + <listitem> + <para> Options <literal>boot.initrd.luks.devices.<replaceable>name</replaceable>.yubikey.ramfsMountPoint</literal> <literal>boot.initrd.luks.devices.<replaceable>name</replaceable>.yubikey.storage.mountPoint</literal> @@ -278,6 +317,8 @@ inherit (pkgs.nixos { <literal>lib.traceCallXml</literal> has been deprecated. Please complain if you use the function regularly. </para> + </listitem> + <listitem> <para> The attribute <literal>lib.nixpkgsVersion</literal> has been deprecated in favor of <literal>lib.version</literal>. Please refer to the discussion in @@ -287,6 +328,13 @@ inherit (pkgs.nixos { </listitem> <listitem> <para> + <literal>lib.recursiveUpdateUntil</literal> was not acting according to its + specification. It has been fixed to act according to the docstring, and a + test has been added. + </para> + </listitem> + <listitem> + <para> The module for <option>security.dhparams</option> has two new options now: </para> <variablelist> diff --git a/nixos/lib/make-ext4-fs.nix b/nixos/lib/make-ext4-fs.nix index 35a8afae4a7a..88be8b73ab37 100644 --- a/nixos/lib/make-ext4-fs.nix +++ b/nixos/lib/make-ext4-fs.nix @@ -6,16 +6,19 @@ , storePaths , volumeLabel , uuid ? "44444444-4444-4444-8888-888888888888" +, e2fsprogs +, libfaketime +, perl }: let - sdClosureInfo = pkgs.closureInfo { rootPaths = storePaths; }; + sdClosureInfo = pkgs.buildPackages.closureInfo { rootPaths = storePaths; }; in pkgs.stdenv.mkDerivation { name = "ext4-fs.img"; - nativeBuildInputs = with pkgs; [e2fsprogs.bin libfaketime perl]; + nativeBuildInputs = [e2fsprogs.bin libfaketime perl]; buildCommand = '' diff --git a/nixos/lib/qemu-flags.nix b/nixos/lib/qemu-flags.nix index 6f61c64a832e..f115ca5ac000 100644 --- a/nixos/lib/qemu-flags.nix +++ b/nixos/lib/qemu-flags.nix @@ -1,11 +1,15 @@ # QEMU flags shared between various Nix expressions. { pkgs }: +let + zeroPad = n: if n < 10 then "0${toString n}" else toString n; +in + { qemuNICFlags = nic: net: machine: - [ "-net nic,vlan=${toString nic},macaddr=52:54:00:12:${toString net}:${toString machine},model=virtio" - "-net vde,vlan=${toString nic},sock=$QEMU_VDE_SOCKET_${toString net}" + [ "-device virtio-net-pci,netdev=vlan${toString nic},mac=52:54:00:12:${zeroPad net}:${zeroPad machine}" + "-netdev vde,id=vlan${toString nic},sock=$QEMU_VDE_SOCKET_${toString net}" ]; qemuSerialDevice = if pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64 then "ttyS0" diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix index ddec21b5f6e5..426e1666a814 100644 --- a/nixos/modules/config/users-groups.nix +++ b/nixos/modules/config/users-groups.nix @@ -524,6 +524,8 @@ in { utmp.gid = ids.gids.utmp; adm.gid = ids.gids.adm; input.gid = ids.gids.input; + kvm.gid = ids.gids.kvm; + render.gid = ids.gids.render; }; system.activationScripts.users = stringAfter [ "stdio" ] diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix index 08923970cd38..1ac9e5c5c74b 100644 --- a/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixos/modules/installer/cd-dvd/iso-image.nix @@ -318,7 +318,7 @@ in options = [ "allow_other" "cow" "nonempty" "chroot=/mnt-root" "max_files=32768" "hide_meta_files" "dirs=/nix/.rw-store=rw:/nix/.ro-store=ro" ]; }; - boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "usb-storage" "uas" ]; + boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "uas" ]; boot.blacklistedKernelModules = [ "nouveau" ]; diff --git a/nixos/modules/installer/cd-dvd/sd-image.nix b/nixos/modules/installer/cd-dvd/sd-image.nix index 311a5ff69670..2371be9d89a1 100644 --- a/nixos/modules/installer/cd-dvd/sd-image.nix +++ b/nixos/modules/installer/cd-dvd/sd-image.nix @@ -12,13 +12,12 @@ with lib; let - rootfsImage = import ../../../lib/make-ext4-fs.nix { - inherit pkgs; + rootfsImage = pkgs.callPackage ../../../lib/make-ext4-fs.nix ({ inherit (config.sdImage) storePaths; volumeLabel = "NIXOS_SD"; } // optionalAttrs (config.sdImage.rootPartitionUUID != null) { uuid = config.sdImage.rootPartitionUUID; - }; + }); in { options.sdImage = { @@ -94,10 +93,10 @@ in sdImage.storePaths = [ config.system.build.toplevel ]; - system.build.sdImage = pkgs.stdenv.mkDerivation { + system.build.sdImage = pkgs.callPackage ({ stdenv, dosfstools, e2fsprogs, mtools, libfaketime, utillinux }: stdenv.mkDerivation { name = config.sdImage.imageName; - buildInputs = with pkgs; [ dosfstools e2fsprogs mtools libfaketime utillinux ]; + nativeBuildInputs = [ dosfstools e2fsprogs mtools libfaketime utillinux ]; buildCommand = '' mkdir -p $out/nix-support $out/sd-image @@ -138,7 +137,7 @@ in (cd boot; mcopy -bpsvm -i ../bootpart.img ./* ::) dd conv=notrunc if=bootpart.img of=$img seek=$START count=$SECTORS ''; - }; + }) {}; boot.postBootCommands = '' # On the first boot do some maintenance tasks diff --git a/nixos/modules/installer/netboot/netboot.nix b/nixos/modules/installer/netboot/netboot.nix index a4eda3c52dce..ea640173c6dd 100644 --- a/nixos/modules/installer/netboot/netboot.nix +++ b/nixos/modules/installer/netboot/netboot.nix @@ -28,7 +28,6 @@ with lib; ++ (if pkgs.stdenv.system == "aarch64-linux" then [] else [ pkgs.grub2 pkgs.syslinux ]); - system.boot.loader.kernelFile = pkgs.stdenv.platform.kernelTarget; fileSystems."/" = { fsType = "tmpfs"; @@ -86,7 +85,7 @@ with lib; system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" '' #!ipxe - kernel ${pkgs.stdenv.platform.kernelTarget} init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} + kernel ${pkgs.stdenv.hostPlatform.platform.kernelTarget} init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} initrd initrd boot ''; diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index bffd8aff78b9..0928e368d80f 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -326,6 +326,8 @@ cfssl = 299; cassandra = 300; qemu-libvirtd = 301; + # kvm = 302; # unused + # render = 303; # unused # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -612,6 +614,8 @@ cfssl = 299; cassandra = 300; qemu-libvirtd = 301; + kvm = 302; # default udev rules from systemd requires these + render = 303; # default udev rules from systemd requires these # 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 e19853efd73c..12944857af4e 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -247,8 +247,10 @@ ./services/desktops/gnome3/tracker-miners.nix ./services/desktops/profile-sync-daemon.nix ./services/desktops/telepathy.nix + ./services/desktops/zeitgeist.nix ./services/development/bloop.nix ./services/development/hoogle.nix + ./services/development/jupyter/default.nix ./services/editors/emacs.nix ./services/editors/infinoted.nix ./services/games/factorio.nix @@ -280,6 +282,7 @@ ./services/hardware/upower.nix ./services/hardware/usbmuxd.nix ./services/hardware/thermald.nix + ./services/hardware/undervolt.nix ./services/logging/SystemdJournal2Gelf.nix ./services/logging/awstats.nix ./services/logging/fluentd.nix @@ -407,6 +410,7 @@ ./services/monitoring/cadvisor.nix ./services/monitoring/collectd.nix ./services/monitoring/das_watchdog.nix + ./services/monitoring/datadog-agent.nix ./services/monitoring/dd-agent/dd-agent.nix ./services/monitoring/fusion-inventory.nix ./services/monitoring/grafana.nix @@ -620,6 +624,7 @@ ./services/scheduling/fcron.nix ./services/scheduling/marathon.nix ./services/search/elasticsearch.nix + ./services/search/elasticsearch-curator.nix ./services/search/hound.nix ./services/search/kibana.nix ./services/search/solr.nix diff --git a/nixos/modules/profiles/all-hardware.nix b/nixos/modules/profiles/all-hardware.nix index 0d7124be0a5c..19f821ae17f3 100644 --- a/nixos/modules/profiles/all-hardware.nix +++ b/nixos/modules/profiles/all-hardware.nix @@ -33,7 +33,7 @@ # USB support, especially for booting from USB CD-ROM # drives. - "usb_storage" + "uas" # Firewire support. Not tested. "ohci1394" "sbp2" diff --git a/nixos/modules/profiles/installation-device.nix b/nixos/modules/profiles/installation-device.nix index 57d947b52684..ff4a23a18d06 100644 --- a/nixos/modules/profiles/installation-device.nix +++ b/nixos/modules/profiles/installation-device.nix @@ -31,7 +31,8 @@ with lib; #services.rogue.enable = true; # Disable some other stuff we don't need. - security.sudo.enable = false; + security.sudo.enable = mkDefault false; + services.udisks2.enable = mkDefault false; # Automatically log in at the virtual consoles. services.mingetty.autologinUser = "root"; diff --git a/nixos/modules/programs/zsh/zsh.nix b/nixos/modules/programs/zsh/zsh.nix index 42d4e1d4ada0..d30b3415411f 100644 --- a/nixos/modules/programs/zsh/zsh.nix +++ b/nixos/modules/programs/zsh/zsh.nix @@ -87,6 +87,19 @@ in type = types.bool; }; + + enableGlobalCompInit = mkOption { + default = cfg.enableCompletion; + description = '' + Enable execution of compinit call for all interactive zsh shells. + + This option can be disabled if the user wants to extend its + <literal>fpath</literal> and a custom <literal>compinit</literal> + call in the local config is required. + ''; + type = types.bool; + }; + }; }; @@ -159,7 +172,7 @@ in fpath+=($p/share/zsh/site-functions $p/share/zsh/$ZSH_VERSION/functions $p/share/zsh/vendor-completions) done - ${optionalString cfg.enableCompletion "autoload -U compinit && compinit"} + ${optionalString cfg.enableGlobalCompInit "autoload -U compinit && compinit"} ${cfge.interactiveShellInit} diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix index 75f02ea78e64..b51dcd2976f4 100644 --- a/nixos/modules/rename.nix +++ b/nixos/modules/rename.nix @@ -256,6 +256,8 @@ with lib; (mkRemovedOptionModule [ "fonts" "fontconfig" "forceAutohint" ] "") (mkRemovedOptionModule [ "fonts" "fontconfig" "renderMonoTTFAsBitmap" ] "") (mkRemovedOptionModule [ "virtualisation" "xen" "qemu" ] "You don't need this option anymore, it will work without it.") + (mkRemovedOptionModule [ "services" "logstash" "enableWeb" ] "The web interface was removed from logstash") + (mkRemovedOptionModule [ "boot" "zfs" "enableLegacyCrypto" ] "The corresponding package was removed from nixpkgs.") # ZSH (mkRenamedOptionModule [ "programs" "zsh" "enableSyntaxHighlighting" ] [ "programs" "zsh" "syntaxHighlighting" "enable" ]) diff --git a/nixos/modules/services/desktops/accountsservice.nix b/nixos/modules/services/desktops/accountsservice.nix index 2a7450669ea0..933b9da2c83c 100644 --- a/nixos/modules/services/desktops/accountsservice.nix +++ b/nixos/modules/services/desktops/accountsservice.nix @@ -32,15 +32,21 @@ with lib; environment.systemPackages = [ pkgs.accountsservice ]; + # Accounts daemon looks for dbus interfaces in $XDG_DATA_DIRS/accountsservice + environment.pathsToLink = [ "/share/accountsservice" ]; + services.dbus.packages = [ pkgs.accountsservice ]; systemd.packages = [ pkgs.accountsservice ]; - systemd.services.accounts-daemon= { + systemd.services.accounts-daemon = { wantedBy = [ "graphical.target" ]; - } // (mkIf (!config.users.mutableUsers) { + # Accounts daemon looks for dbus interfaces in $XDG_DATA_DIRS/accountsservice + environment.XDG_DATA_DIRS = "${config.system.path}/share"; + + } // (optionalAttrs (!config.users.mutableUsers) { environment.NIXOS_USERS_PURE = "true"; }); }; diff --git a/nixos/modules/services/desktops/geoclue2.nix b/nixos/modules/services/desktops/geoclue2.nix index c5a000d5c6a7..dafb0af20756 100644 --- a/nixos/modules/services/desktops/geoclue2.nix +++ b/nixos/modules/services/desktops/geoclue2.nix @@ -4,6 +4,10 @@ with lib; +let + # the demo agent isn't built by default, but we need it here + package = pkgs.geoclue2.override { withDemoAgent = config.services.geoclue2.enableDemoAgent; }; +in { ###### interface @@ -21,21 +25,42 @@ with lib; ''; }; + enableDemoAgent = mkOption { + type = types.bool; + default = true; + description = '' + Whether to use the GeoClue demo agent. This should be + overridden by desktop environments that provide their own + agent. + ''; + }; + }; }; ###### implementation - config = mkIf config.services.geoclue2.enable { - environment.systemPackages = [ pkgs.geoclue2 ]; - - services.dbus.packages = [ pkgs.geoclue2 ]; - - systemd.packages = [ pkgs.geoclue2 ]; - + environment.systemPackages = [ package ]; + + services.dbus.packages = [ package ]; + + systemd.packages = [ package ]; + + # this needs to run as a user service, since it's associated with the + # user who is making the requests + systemd.user.services = mkIf config.services.geoclue2.enableDemoAgent { + "geoclue-agent" = { + description = "Geoclue agent"; + script = "${package}/libexec/geoclue-2.0/demos/agent"; + # this should really be `partOf = [ "geoclue.service" ]`, but + # we can't be part of a system service, and the agent should + # be okay with the main service coming and going + wantedBy = [ "default.target" ]; + }; + }; }; } diff --git a/nixos/modules/services/desktops/zeitgeist.nix b/nixos/modules/services/desktops/zeitgeist.nix new file mode 100644 index 000000000000..20c82ccdd56c --- /dev/null +++ b/nixos/modules/services/desktops/zeitgeist.nix @@ -0,0 +1,26 @@ +# Zeitgeist + +{ config, lib, pkgs, ... }: + +with lib; + +{ + ###### interface + + options = { + services.zeitgeist = { + enable = mkEnableOption "zeitgeist"; + }; + }; + + ###### implementation + + config = mkIf config.services.zeitgeist.enable { + + environment.systemPackages = [ pkgs.zeitgeist ]; + + services.dbus.packages = [ pkgs.zeitgeist ]; + + systemd.packages = [ pkgs.zeitgeist ]; + }; +} diff --git a/nixos/modules/services/development/jupyter/default.nix b/nixos/modules/services/development/jupyter/default.nix new file mode 100644 index 000000000000..9fcc00431865 --- /dev/null +++ b/nixos/modules/services/development/jupyter/default.nix @@ -0,0 +1,184 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.jupyter; + + # NOTE: We don't use top-level jupyter because we don't + # want to pass in JUPYTER_PATH but use .environment instead, + # saving a rebuild. + package = pkgs.python3.pkgs.notebook; + + kernels = (pkgs.jupyter-kernel.create { + definitions = if cfg.kernels != null + then cfg.kernels + else pkgs.jupyter-kernel.default; + }); + + notebookConfig = pkgs.writeText "jupyter_config.py" '' + ${cfg.notebookConfig} + + c.NotebookApp.password = ${cfg.password} + ''; + +in { + meta.maintainers = with maintainers; [ aborsu ]; + + options.services.jupyter = { + enable = mkEnableOption "Jupyter development server"; + + ip = mkOption { + type = types.str; + default = "localhost"; + description = '' + IP address Jupyter will be listening on. + ''; + }; + + port = mkOption { + type = types.int; + default = 8888; + description = '' + Port number Jupyter will be listening on. + ''; + }; + + notebookDir = mkOption { + type = types.str; + default = "~/"; + description = '' + Root directory for notebooks. + ''; + }; + + user = mkOption { + type = types.str; + default = "jupyter"; + description = '' + Name of the user used to run the jupyter service. + For security reason, jupyter should really not be run as root. + If not set (jupyter), the service will create a jupyter user with appropriate settings. + ''; + example = "aborsu"; + }; + + group = mkOption { + type = types.str; + default = "jupyter"; + description = '' + Name of the group used to run the jupyter service. + Use this if you want to create a group of users that are able to view the notebook directory's content. + ''; + example = "users"; + }; + + password = mkOption { + type = types.str; + description = '' + Password to use with notebook. + Can be generated using: + In [1]: from notebook.auth import passwd + In [2]: passwd('test') + Out[2]: 'sha1:1b961dc713fb:88483270a63e57d18d43cf337e629539de1436ba' + NOTE: you need to keep the single quote inside the nix string. + Or you can use a python oneliner: + "open('/path/secret_file', 'r', encoding='utf8').read().strip()" + It will be interpreted at the end of the notebookConfig. + ''; + example = [ + "'sha1:1b961dc713fb:88483270a63e57d18d43cf337e629539de1436ba'" + "open('/path/secret_file', 'r', encoding='utf8').read().strip()" + ]; + }; + + notebookConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Raw jupyter config. + ''; + }; + + kernels = mkOption { + type = types.nullOr (types.attrsOf(types.submodule (import ./kernel-options.nix { + inherit lib; + }))); + + default = null; + example = literalExample '' + { + python3 = let + env = (pkgs.python3.withPackages (pythonPackages: with pythonPackages; [ + ipykernel + pandas + scikitlearn + ])); + in { + displayName = "Python 3 for machine learning"; + argv = [ + "$ {env.interpreter}" + "-m" + "ipykernel_launcher" + "-f" + "{connection_file}" + ]; + language = "python"; + logo32 = "$ {env.sitePackages}/ipykernel/resources/logo-32x32.png"; + logo64 = "$ {env.sitePackages}/ipykernel/resources/logo-64x64.png"; + }; + } + ''; + description = "Declarative kernel config + + Kernels can be declared in any language that supports and has the required + dependencies to communicate with a jupyter server. + In python's case, it means that ipykernel package must always be included in + the list of packages of the targeted environment. + "; + }; + }; + + config = mkMerge [ + (mkIf cfg.enable { + systemd.services.jupyter = { + description = "Jupyter development server"; + + wantedBy = [ "multi-user.target" ]; + + # TODO: Patch notebook so we can explicitly pass in a shell + path = [ pkgs.bash ]; # needed for sh in cell magic to work + + environment = { + JUPYTER_PATH = toString kernels; + }; + + serviceConfig = { + Restart = "always"; + ExecStart = ''${package}/bin/jupyter-notebook \ + --no-browser \ + --ip=${cfg.ip} \ + --port=${toString cfg.port} --port-retries 0 \ + --notebook-dir=${cfg.notebookDir} \ + --NotebookApp.config_file=${notebookConfig} + ''; + User = cfg.user; + Group = cfg.group; + WorkingDirectory = "~"; + }; + }; + }) + (mkIf (cfg.enable && (cfg.group == "jupyter")) { + users.groups.jupyter = {}; + }) + (mkIf (cfg.enable && (cfg.user == "jupyter")) { + users.extraUsers.jupyter = { + extraGroups = [ cfg.group ]; + home = "/var/lib/jupyter"; + createHome = true; + useDefaultShell = true; # needed so that the user can start a terminal. + }; + }) + ]; +} diff --git a/nixos/modules/services/development/jupyter/kernel-options.nix b/nixos/modules/services/development/jupyter/kernel-options.nix new file mode 100644 index 000000000000..03547637449a --- /dev/null +++ b/nixos/modules/services/development/jupyter/kernel-options.nix @@ -0,0 +1,60 @@ +# Options that can be used for creating a jupyter kernel. +{lib }: + +with lib; + +{ + options = { + + displayName = mkOption { + type = types.str; + default = ""; + example = [ + "Python 3" + "Python 3 for Data Science" + ]; + description = '' + Name that will be shown to the user. + ''; + }; + + argv = mkOption { + type = types.listOf types.str; + example = [ + "{customEnv.interpreter}" + "-m" + "ipykernel_launcher" + "-f" + "{connection_file}" + ]; + description = '' + Command and arguments to start the kernel. + ''; + }; + + language = mkOption { + type = types.str; + example = "python"; + description = '' + Language of the environment. Typically the name of the binary. + ''; + }; + + logo32 = mkOption { + type = types.nullOr types.path; + default = null; + example = "{env.sitePackages}/ipykernel/resources/logo-32x32.png"; + description = '' + Path to 32x32 logo png. + ''; + }; + logo64 = mkOption { + type = types.nullOr types.path; + default = null; + example = "{env.sitePackages}/ipykernel/resources/logo-64x64.png"; + description = '' + Path to 64x64 logo png. + ''; + }; + }; +} diff --git a/nixos/modules/services/games/terraria.nix b/nixos/modules/services/games/terraria.nix index ddf17599296a..31f8edca20ce 100644 --- a/nixos/modules/services/games/terraria.nix +++ b/nixos/modules/services/games/terraria.nix @@ -18,6 +18,16 @@ let (boolFlag "secure" cfg.secure) (boolFlag "noupnp" cfg.noUPnP) ]; + stopScript = pkgs.writeScript "terraria-stop" '' + #!${pkgs.runtimeShell} + + if ! [ -d "/proc/$1" ]; then + exit 0 + fi + + ${getBin pkgs.tmux}/bin/tmux -S /var/lib/terraria/terraria.sock send-keys Enter exit Enter + ${getBin pkgs.coreutils}/bin/tail --pid="$1" -f /dev/null + ''; in { options = { @@ -124,10 +134,10 @@ in serviceConfig = { User = "terraria"; - Type = "oneshot"; - RemainAfterExit = true; + Type = "forking"; + GuessMainPID = true; ExecStart = "${getBin pkgs.tmux}/bin/tmux -S /var/lib/terraria/terraria.sock new -d ${pkgs.terraria-server}/bin/TerrariaServer ${concatStringsSep " " flags}"; - ExecStop = "${getBin pkgs.tmux}/bin/tmux -S /var/lib/terraria/terraria.sock send-keys Enter \"exit\" Enter"; + ExecStop = "${stopScript} $MAINPID"; }; postStart = '' diff --git a/nixos/modules/services/hardware/thermald.nix b/nixos/modules/services/hardware/thermald.nix index 88c3f99aed4e..69577bbe0181 100644 --- a/nixos/modules/services/hardware/thermald.nix +++ b/nixos/modules/services/hardware/thermald.nix @@ -6,16 +6,30 @@ let cfg = config.services.thermald; in { ###### interface - options = { - services.thermald = { + options = { + services.thermald = { enable = mkOption { default = false; description = '' Whether to enable thermald, the temperature management daemon. - ''; - }; - }; - }; + ''; + }; + + debug = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable debug logging. + ''; + }; + + configFile = mkOption { + type = types.nullOr types.path; + default = null; + description = "the thermald manual configuration file."; + }; + }; + }; ###### implementation config = mkIf cfg.enable { @@ -24,7 +38,15 @@ in { systemd.services.thermald = { description = "Thermal Daemon Service"; wantedBy = [ "multi-user.target" ]; - script = "exec ${pkgs.thermald}/sbin/thermald --no-daemon --dbus-enable"; + serviceConfig = { + ExecStart = '' + ${pkgs.thermald}/sbin/thermald \ + --no-daemon \ + ${optionalString cfg.debug "--loglevel=debug"} \ + ${optionalString (cfg.configFile != null) "--config-file ${cfg.configFile}"} \ + --dbus-enable + ''; + }; }; }; } diff --git a/nixos/modules/services/hardware/undervolt.nix b/nixos/modules/services/hardware/undervolt.nix new file mode 100644 index 000000000000..e5ef0601de3c --- /dev/null +++ b/nixos/modules/services/hardware/undervolt.nix @@ -0,0 +1,134 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + cfg = config.services.undervolt; +in { + options.services.undervolt = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to undervolt intel cpus. + ''; + }; + + verbose = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable verbose logging. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.undervolt; + defaultText = "pkgs.undervolt"; + description = '' + undervolt derivation to use. + ''; + }; + + coreOffset = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The amount of voltage to offset the CPU cores by. Accepts a floating point number. + ''; + }; + + gpuOffset = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The amount of voltage to offset the GPU by. Accepts a floating point number. + ''; + }; + + uncoreOffset = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The amount of voltage to offset uncore by. Accepts a floating point number. + ''; + }; + + analogioOffset = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The amount of voltage to offset analogio by. Accepts a floating point number. + ''; + }; + + temp = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The temperature target. Accepts a floating point number. + ''; + }; + + tempAc = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The temperature target on AC power. Accepts a floating point number. + ''; + }; + + tempBat = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The temperature target on battery power. Accepts a floating point number. + ''; + }; + }; + + config = mkIf cfg.enable { + boot.kernelModules = [ "msr" ]; + + environment.systemPackages = [ cfg.package ]; + + systemd.services.undervolt = { + path = [ pkgs.undervolt ]; + + description = "Intel Undervolting Service"; + serviceConfig = { + Type = "oneshot"; + Restart = "no"; + + # `core` and `cache` are both intentionally set to `cfg.coreOffset` as according to the undervolt docs: + # + # Core or Cache offsets have no effect. It is not possible to set different offsets for + # CPU Core and Cache. The CPU will take the smaller of the two offsets, and apply that to + # both CPU and Cache. A warning message will be displayed if you attempt to set different offsets. + ExecStart = '' + ${pkgs.undervolt}/bin/undervolt \ + ${optionalString cfg.verbose "--verbose"} \ + ${optionalString (cfg.coreOffset != null) "--core ${cfg.coreOffset}"} \ + ${optionalString (cfg.coreOffset != null) "--cache ${cfg.coreOffset}"} \ + ${optionalString (cfg.gpuOffset != null) "--gpu ${cfg.gpuOffset}"} \ + ${optionalString (cfg.uncoreOffset != null) "--uncore ${cfg.uncoreOffset}"} \ + ${optionalString (cfg.analogioOffset != null) "--analogio ${cfg.analogioOffset}"} \ + ${optionalString (cfg.temp != null) "--temp ${cfg.temp}"} \ + ${optionalString (cfg.tempAc != null) "--temp-ac ${cfg.tempAc}"} \ + ${optionalString (cfg.tempBat != null) "--temp-bat ${cfg.tempBat}"} + ''; + }; + }; + + systemd.timers.undervolt = { + description = "Undervolt timer to ensure voltage settings are always applied"; + partOf = [ "undervolt.service" ]; + wantedBy = [ "multi-user.target" ]; + timerConfig = { + OnBootSec = "2min"; + OnUnitActiveSec = "30"; + }; + }; + }; +} diff --git a/nixos/modules/services/logging/logstash.nix b/nixos/modules/services/logging/logstash.nix index 28d89a7463ab..aa019d855ea9 100644 --- a/nixos/modules/services/logging/logstash.nix +++ b/nixos/modules/services/logging/logstash.nix @@ -4,25 +4,12 @@ with lib; let cfg = config.services.logstash; - atLeast54 = versionAtLeast (builtins.parseDrvName cfg.package.name).version "5.4"; pluginPath = lib.concatStringsSep ":" cfg.plugins; havePluginPath = lib.length cfg.plugins > 0; ops = lib.optionalString; - verbosityFlag = - if atLeast54 - then "--log.level " + cfg.logLevel - else { - debug = "--debug"; - info = "--verbose"; - warn = ""; # intentionally empty - error = "--quiet"; - fatal = "--silent"; - }."${cfg.logLevel}"; - - pluginsPath = - if atLeast54 - then "--path.plugins ${pluginPath}" - else "--pluginpath ${pluginPath}"; + verbosityFlag = "--log.level " + cfg.logLevel; + + pluginsPath = "--path.plugins ${pluginPath}"; logstashConf = pkgs.writeText "logstash.conf" '' input { @@ -63,7 +50,7 @@ in type = types.package; default = pkgs.logstash; defaultText = "pkgs.logstash"; - example = literalExample "pkgs.logstash"; + example = literalExample "pkgs.logstash5"; description = "Logstash package to use."; }; @@ -95,12 +82,6 @@ in description = "The quantity of filter workers to run."; }; - enableWeb = mkOption { - type = types.bool; - default = false; - description = "Enable the logstash web interface."; - }; - listenAddress = mkOption { type = types.str; default = "127.0.0.1"; @@ -174,16 +155,6 @@ in ###### implementation config = mkIf cfg.enable { - assertions = [ - { assertion = atLeast54 -> !cfg.enableWeb; - message = '' - The logstash web interface is only available for versions older than 5.4. - So either set services.logstash.enableWeb = false, - or set services.logstash.package to an older logstash. - ''; - } - ]; - systemd.services.logstash = with pkgs; { description = "Logstash Daemon"; wantedBy = [ "multi-user.target" ]; @@ -193,14 +164,12 @@ in ExecStartPre = ''${pkgs.coreutils}/bin/mkdir -p "${cfg.dataDir}" ; ${pkgs.coreutils}/bin/chmod 700 "${cfg.dataDir}"''; ExecStart = concatStringsSep " " (filter (s: stringLength s != 0) [ "${cfg.package}/bin/logstash" - (ops (!atLeast54) "agent") "-w ${toString cfg.filterWorkers}" (ops havePluginPath pluginsPath) "${verbosityFlag}" "-f ${logstashConf}" - (ops atLeast54 "--path.settings ${logstashSettingsDir}") - (ops atLeast54 "--path.data ${cfg.dataDir}") - (ops cfg.enableWeb "-- web -a ${cfg.listenAddress} -p ${cfg.port}") + "--path.settings ${logstashSettingsDir}" + "--path.data ${cfg.dataDir}" ]); }; }; diff --git a/nixos/modules/services/logging/syslog-ng.nix b/nixos/modules/services/logging/syslog-ng.nix index 21be286a6e98..65e103ac2ba5 100644 --- a/nixos/modules/services/logging/syslog-ng.nix +++ b/nixos/modules/services/logging/syslog-ng.nix @@ -85,9 +85,11 @@ in { after = [ "multi-user.target" ]; # makes sure hostname etc is set serviceConfig = { Type = "notify"; + PIDFile = pidFile; StandardOutput = "null"; Restart = "on-failure"; ExecStart = "${cfg.package}/sbin/syslog-ng ${concatStringsSep " " syslogngOptions}"; + ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; }; }; }; diff --git a/nixos/modules/services/misc/gitea.nix b/nixos/modules/services/misc/gitea.nix index 5d664728e0b5..dc63f1a6c052 100644 --- a/nixos/modules/services/misc/gitea.nix +++ b/nixos/modules/services/misc/gitea.nix @@ -261,7 +261,8 @@ in runConfig = "${cfg.stateDir}/custom/conf/app.ini"; secretKey = "${cfg.stateDir}/custom/conf/secret_key"; in '' - mkdir -p ${cfg.stateDir} + # Make sure that the stateDir exists, as well as the conf dir in there + mkdir -p ${cfg.stateDir}/conf # copy custom configuration and generate a random secret key if needed ${optionalString (cfg.useWizard == false) '' @@ -290,11 +291,13 @@ in sed -ri 's,/nix/store/[a-z0-9.-]+/bin/bash,${pkgs.bash}/bin/bash,g' $HOOKS sed -ri 's,/nix/store/[a-z0-9.-]+/bin/perl,${pkgs.perl}/bin/perl,g' $HOOKS fi - if [ ! -d ${cfg.stateDir}/conf/locale ] + # If we have a folder or symlink with gitea locales, remove it + if [ -e ${cfg.stateDir}/conf/locale ] then - mkdir -p ${cfg.stateDir}/conf - cp -r ${gitea.out}/locale ${cfg.stateDir}/conf/locale + rm -r ${cfg.stateDir}/conf/locale fi + # And symlink the current gitea locales in place + ln -s ${gitea.out}/locale ${cfg.stateDir}/conf/locale # update command option in authorized_keys if [ -r ${cfg.stateDir}/.ssh/authorized_keys ] then diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix index 5ca879bf2664..c0eb882c58f3 100644 --- a/nixos/modules/services/misc/nix-daemon.nix +++ b/nixos/modules/services/misc/nix-daemon.nix @@ -88,7 +88,7 @@ in }; maxJobs = mkOption { - type = types.int; + type = types.either types.int (types.enum ["auto"]); default = 1; example = 64; description = '' diff --git a/nixos/modules/services/misc/redmine.nix b/nixos/modules/services/misc/redmine.nix index 9a9424449f80..f763ba21d0b2 100644 --- a/nixos/modules/services/misc/redmine.nix +++ b/nixos/modules/services/misc/redmine.nix @@ -1,121 +1,124 @@ { config, lib, pkgs, ... }: -# TODO: support non-postgresql - with lib; let cfg = config.services.redmine; - ruby = pkgs.ruby; + bundle = "${pkgs.redmine}/share/redmine/bin/bundle"; - databaseYml = '' + databaseYml = pkgs.writeText "database.yml" '' production: - adapter: postgresql - database: ${cfg.databaseName} - host: ${cfg.databaseHost} - password: ${cfg.databasePassword} - username: ${cfg.databaseUsername} - encoding: utf8 + adapter: ${cfg.database.type} + database: ${cfg.database.name} + host: ${cfg.database.host} + port: ${toString cfg.database.port} + username: ${cfg.database.user} + password: #dbpass# ''; - configurationYml = '' + configurationYml = pkgs.writeText "configuration.yml" '' default: - # Absolute path to the directory where attachments are stored. - # The default is the 'files' directory in your Redmine instance. - # Your Redmine instance needs to have write permission on this - # directory. - # Examples: - # attachments_storage_path: /var/redmine/files - # attachments_storage_path: D:/redmine/files - attachments_storage_path: ${cfg.stateDir}/files - - # Absolute path to the SCM commands errors (stderr) log file. - # The default is to log in the 'log' directory of your Redmine instance. - # Example: - # scm_stderr_log_file: /var/log/redmine_scm_stderr.log - scm_stderr_log_file: ${cfg.stateDir}/redmine_scm_stderr.log - - ${cfg.extraConfig} + scm_subversion_command: ${pkgs.subversion}/bin/svn + scm_mercurial_command: ${pkgs.mercurial}/bin/hg + scm_git_command: ${pkgs.gitAndTools.git}/bin/git + scm_cvs_command: ${pkgs.cvs}/bin/cvs + scm_bazaar_command: ${pkgs.bazaar}/bin/bzr + scm_darcs_command: ${pkgs.darcs}/bin/darcs + + ${cfg.extraConfig} ''; - unpackTheme = unpack "theme"; - unpackPlugin = unpack "plugin"; - unpack = id: (name: source: - pkgs.stdenv.mkDerivation { - name = "redmine-${id}-${name}"; - buildInputs = [ pkgs.unzip ]; - buildCommand = '' - mkdir -p $out - cd $out - unpackFile ${source} - ''; - }); - -in { +in +{ options = { services.redmine = { enable = mkOption { type = types.bool; default = false; - description = '' - Enable the redmine service. - ''; + description = "Enable the Redmine service."; }; - stateDir = mkOption { + user = mkOption { type = types.str; - default = "/var/redmine"; - description = "The state directory, logs and plugins are stored here"; - }; - - extraConfig = mkOption { - type = types.lines; - default = ""; - description = "Extra configuration in configuration.yml"; - }; - - themes = mkOption { - type = types.attrsOf types.path; - default = {}; - description = "Set of themes"; + default = "redmine"; + description = "User under which Redmine is ran."; }; - plugins = mkOption { - type = types.attrsOf types.path; - default = {}; - description = "Set of plugins"; + group = mkOption { + type = types.str; + default = "redmine"; + description = "Group under which Redmine is ran."; }; - #databaseType = mkOption { - # type = types.str; - # default = "postgresql"; - # description = "Type of database"; - #}; - - databaseHost = mkOption { + stateDir = mkOption { type = types.str; - default = "127.0.0.1"; - description = "Database hostname"; + default = "/var/lib/redmine"; + description = "The state directory, logs and plugins are stored here."; }; - databasePassword = mkOption { - type = types.str; + extraConfig = mkOption { + type = types.lines; default = ""; - description = "Database user password"; - }; + description = '' + Extra configuration in configuration.yml. - databaseName = mkOption { - type = types.str; - default = "redmine"; - description = "Database name"; + See https://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration + ''; }; - databaseUsername = mkOption { - type = types.str; - default = "redmine"; - description = "Database user"; + database = { + type = mkOption { + type = types.enum [ "mysql2" "postgresql" ]; + example = "postgresql"; + default = "mysql2"; + description = "Database engine to use."; + }; + + host = mkOption { + type = types.str; + default = "127.0.0.1"; + description = "Database host address."; + }; + + port = mkOption { + type = types.int; + default = 3306; + description = "Database host port."; + }; + + name = mkOption { + type = types.str; + default = "redmine"; + description = "Database name."; + }; + + user = mkOption { + type = types.str; + default = "redmine"; + description = "Database user."; + }; + + password = mkOption { + type = types.str; + default = ""; + description = '' + The password corresponding to <option>database.user</option>. + Warning: this is stored in cleartext in the Nix store! + Use <option>database.passwordFile</option> instead. + ''; + }; + + passwordFile = mkOption { + type = types.nullOr types.path; + default = null; + example = "/run/keys/redmine-dbpassword"; + description = '' + A file containing the password corresponding to + <option>database.user</option>. + ''; + }; }; }; }; @@ -123,99 +126,106 @@ in { config = mkIf cfg.enable { assertions = [ - { assertion = cfg.databasePassword != ""; - message = "services.redmine.databasePassword must be set"; + { assertion = cfg.database.passwordFile != null || cfg.database.password != ""; + message = "either services.redmine.database.passwordFile or services.redmine.database.password must be set"; } ]; - users.users = [ - { name = "redmine"; - group = "redmine"; - uid = config.ids.uids.redmine; - } ]; - - users.groups = [ - { name = "redmine"; - gid = config.ids.gids.redmine; - } ]; + environment.systemPackages = [ pkgs.redmine ]; systemd.services.redmine = { - after = [ "network.target" "postgresql.service" ]; + after = [ "network.target" (if cfg.database.type == "mysql2" then "mysql.service" else "postgresql.service") ]; wantedBy = [ "multi-user.target" ]; + environment.HOME = "${pkgs.redmine}/share/redmine"; environment.RAILS_ENV = "production"; - environment.RAILS_ETC = "${cfg.stateDir}/config"; - environment.RAILS_LOG = "${cfg.stateDir}/log"; - environment.RAILS_VAR = "${cfg.stateDir}/var"; environment.RAILS_CACHE = "${cfg.stateDir}/cache"; - environment.RAILS_PLUGINS = "${cfg.stateDir}/plugins"; - environment.RAILS_PUBLIC = "${cfg.stateDir}/public"; - environment.RAILS_TMP = "${cfg.stateDir}/tmp"; - environment.SCHEMA = "${cfg.stateDir}/cache/schema.db"; - environment.HOME = "${pkgs.redmine}/share/redmine"; environment.REDMINE_LANG = "en"; - environment.GEM_HOME = "${pkgs.redmine}/share/redmine/vendor/bundle/ruby/1.9.1"; - environment.GEM_PATH = "${pkgs.bundler}/${pkgs.bundler.ruby.gemPath}"; + environment.SCHEMA = "${cfg.stateDir}/cache/schema.db"; path = with pkgs; [ imagemagickBig - subversion - mercurial - cvs - config.services.postgresql.package bazaar + cvs + darcs gitAndTools.git - # once we build binaries for darc enable it - #darcs + mercurial + subversion ]; preStart = '' - # TODO: use env vars - for i in plugins public/plugin_assets db files log config cache var/files tmp; do + # start with a fresh config directory every time + rm -rf ${cfg.stateDir}/config + cp -r ${pkgs.redmine}/share/redmine/config.dist ${cfg.stateDir}/config + + # create the basic state directory layout pkgs.redmine expects + mkdir -p /run/redmine + + for i in config files log plugins tmp; do mkdir -p ${cfg.stateDir}/$i + ln -fs ${cfg.stateDir}/$i /run/redmine/$i done - chown -R redmine:redmine ${cfg.stateDir} - chmod -R 755 ${cfg.stateDir} + # ensure cache directory exists for db:migrate command + mkdir -p ${cfg.stateDir}/cache - rm -rf ${cfg.stateDir}/public/* - cp -R ${pkgs.redmine}/share/redmine/public/* ${cfg.stateDir}/public/ - for theme in ${concatStringsSep " " (mapAttrsToList unpackTheme cfg.themes)}; do - ln -fs $theme/* ${cfg.stateDir}/public/themes/ - done + # link in the application configuration + ln -fs ${configurationYml} ${cfg.stateDir}/config/configuration.yml - rm -rf ${cfg.stateDir}/plugins/* - for plugin in ${concatStringsSep " " (mapAttrsToList unpackPlugin cfg.plugins)}; do - ln -fs $plugin/* ${cfg.stateDir}/plugins/''${plugin##*-redmine-plugin-} - done + chmod -R ug+rwX,o-rwx+x ${cfg.stateDir}/ - ln -fs ${pkgs.writeText "database.yml" databaseYml} ${cfg.stateDir}/config/database.yml - ln -fs ${pkgs.writeText "configuration.yml" configurationYml} ${cfg.stateDir}/config/configuration.yml + # handle database.passwordFile + DBPASS=$(head -n1 ${cfg.database.passwordFile}) + cp -f ${databaseYml} ${cfg.stateDir}/config/database.yml + sed -e "s,#dbpass#,$DBPASS,g" -i ${cfg.stateDir}/config/database.yml + chmod 440 ${cfg.stateDir}/config/database.yml - if [ "${cfg.databaseHost}" = "127.0.0.1" ]; then - if ! test -e "${cfg.stateDir}/db-created"; then - psql postgres -c "CREATE ROLE redmine WITH LOGIN NOCREATEDB NOCREATEROLE ENCRYPTED PASSWORD '${cfg.databasePassword}'" - ${config.services.postgresql.package}/bin/createdb --owner redmine redmine || true - touch "${cfg.stateDir}/db-created" - fi + # generate a secret token if required + if ! test -e "${cfg.stateDir}/config/initializers/secret_token.rb"; then + ${bundle} exec rake generate_secret_token + chmod 440 ${cfg.stateDir}/config/initializers/secret_token.rb fi - cd ${pkgs.redmine}/share/redmine/ - ${ruby}/bin/rake db:migrate - ${ruby}/bin/rake redmine:plugins:migrate - ${ruby}/bin/rake redmine:load_default_data - ${ruby}/bin/rake generate_secret_token + # ensure everything is owned by ${cfg.user} + chown -R ${cfg.user}:${cfg.group} ${cfg.stateDir} + + ${bundle} exec rake db:migrate + ${bundle} exec rake redmine:load_default_data ''; serviceConfig = { PermissionsStartOnly = true; # preStart must be run as root Type = "simple"; - User = "redmine"; - Group = "redmine"; + User = cfg.user; + Group = cfg.group; TimeoutSec = "300"; WorkingDirectory = "${pkgs.redmine}/share/redmine"; - ExecStart="${ruby}/bin/ruby ${pkgs.redmine}/share/redmine/script/rails server webrick -e production -P ${cfg.stateDir}/redmine.pid"; + ExecStart="${bundle} exec rails server webrick -e production -P ${cfg.stateDir}/redmine.pid"; }; }; + users.extraUsers = optionalAttrs (cfg.user == "redmine") (singleton + { name = "redmine"; + group = cfg.group; + home = cfg.stateDir; + createHome = true; + uid = config.ids.uids.redmine; + }); + + users.extraGroups = optionalAttrs (cfg.group == "redmine") (singleton + { name = "redmine"; + gid = config.ids.gids.redmine; + }); + + warnings = optional (cfg.database.password != "") + ''config.services.redmine.database.password will be stored as plaintext + in the Nix store. Use database.passwordFile instead.''; + + # Create database passwordFile default when password is configured. + services.redmine.database.passwordFile = + (mkDefault (toString (pkgs.writeTextFile { + name = "redmine-database-password"; + text = cfg.database.password; + }))); + }; } diff --git a/nixos/modules/services/misc/synergy.nix b/nixos/modules/services/misc/synergy.nix index 7e8eadbe5f37..b89cb41ac3ad 100644 --- a/nixos/modules/services/misc/synergy.nix +++ b/nixos/modules/services/misc/synergy.nix @@ -83,20 +83,20 @@ in config = mkMerge [ (mkIf cfgC.enable { - systemd.services."synergy-client" = { - after = [ "network.target" ]; + systemd.user.services."synergy-client" = { + after = [ "network.target" "graphical-session.target" ]; description = "Synergy client"; - wantedBy = optional cfgC.autoStart "multi-user.target"; + wantedBy = optional cfgC.autoStart "graphical-session.target"; path = [ pkgs.synergy ]; serviceConfig.ExecStart = ''${pkgs.synergy}/bin/synergyc -f ${optionalString (cfgC.screenName != "") "-n ${cfgC.screenName}"} ${cfgC.serverAddress}''; serviceConfig.Restart = "on-failure"; }; }) (mkIf cfgS.enable { - systemd.services."synergy-server" = { - after = [ "network.target" ]; + systemd.user.services."synergy-server" = { + after = [ "network.target" "graphical-session.target" ]; description = "Synergy server"; - wantedBy = optional cfgS.autoStart "multi-user.target"; + wantedBy = optional cfgS.autoStart "graphical-session.target"; path = [ pkgs.synergy ]; serviceConfig.ExecStart = ''${pkgs.synergy}/bin/synergys -c ${cfgS.configFile} -f ${optionalString (cfgS.address != "") "-a ${cfgS.address}"} ${optionalString (cfgS.screenName != "") "-n ${cfgS.screenName}" }''; serviceConfig.Restart = "on-failure"; diff --git a/nixos/modules/services/monitoring/datadog-agent.nix b/nixos/modules/services/monitoring/datadog-agent.nix new file mode 100644 index 000000000000..e545e06b3495 --- /dev/null +++ b/nixos/modules/services/monitoring/datadog-agent.nix @@ -0,0 +1,236 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.datadog-agent; + + ddConf = { + dd_url = "https://app.datadoghq.com"; + skip_ssl_validation = "no"; + api_key = ""; + confd_path = "/etc/datadog-agent/conf.d"; + additional_checksd = "/etc/datadog-agent/checks.d"; + use_dogstatsd = true; + } + // optionalAttrs (cfg.logLevel != null) { log_level = cfg.logLevel; } + // optionalAttrs (cfg.hostname != null) { inherit (cfg) hostname; } + // optionalAttrs (cfg.tags != null ) { tags = concatStringsSep ", " cfg.tags; } + // cfg.extraConfig; + + # Generate Datadog configuration files for each configured checks. + # This works because check configurations have predictable paths, + # and because JSON is a valid subset of YAML. + makeCheckConfigs = entries: mapAttrsToList (name: conf: { + source = pkgs.writeText "${name}-check-conf.yaml" (builtins.toJSON conf); + target = "datadog-agent/conf.d/${name}.d/conf.yaml"; + }) entries; + + defaultChecks = { + disk = cfg.diskCheck; + network = cfg.networkCheck; + }; + + # Assemble all check configurations and the top-level agent + # configuration. + etcfiles = with pkgs; with builtins; [{ + source = writeText "datadog.yaml" (toJSON ddConf); + target = "datadog-agent/datadog.yaml"; + }] ++ makeCheckConfigs (cfg.checks // defaultChecks); + + # Apply the configured extraIntegrations to the provided agent + # package. See the documentation of `dd-agent/integrations-core.nix` + # for detailed information on this. + datadogPkg = cfg.package.overrideAttrs(_: { + python = (pkgs.datadog-integrations-core cfg.extraIntegrations).python; + }); +in { + options.services.datadog-agent = { + enable = mkOption { + description = '' + Whether to enable the datadog-agent v6 monitoring service + ''; + default = false; + type = types.bool; + }; + + package = mkOption { + default = pkgs.datadog-agent; + defaultText = "pkgs.datadog-agent"; + description = '' + Which DataDog v6 agent package to use. Note that the provided + package is expected to have an overridable `python`-attribute + which configures the Python environment with the Datadog + checks. + ''; + type = types.package; + }; + + apiKeyFile = mkOption { + description = '' + Path to a file containing the Datadog API key to associate the + agent with your account. + ''; + example = "/run/keys/datadog_api_key"; + type = types.path; + }; + + tags = mkOption { + description = "The tags to mark this Datadog agent"; + example = [ "test" "service" ]; + default = null; + type = types.nullOr (types.listOf types.str); + }; + + hostname = mkOption { + description = "The hostname to show in the Datadog dashboard (optional)"; + default = null; + example = "mymachine.mydomain"; + type = types.uniq (types.nullOr types.string); + }; + + logLevel = mkOption { + description = "Logging verbosity."; + default = null; + type = types.nullOr (types.enum ["DEBUG" "INFO" "WARN" "ERROR"]); + }; + + extraIntegrations = mkOption { + default = {}; + type = types.attrs; + + description = '' + Extra integrations from the Datadog core-integrations + repository that should be built and included. + + By default the included integrations are disk, mongo, network, + nginx and postgres. + + To include additional integrations the name of the derivation + and a function to filter its dependencies from the Python + package set must be provided. + ''; + + example = { + ntp = (pythonPackages: [ pythonPackages.ntplib ]); + }; + }; + + extraConfig = mkOption { + default = {}; + type = types.attrs; + description = '' + Extra configuration options that will be merged into the + main config file <filename>datadog.yaml</filename>. + ''; + }; + + checks = mkOption { + description = '' + Configuration for all Datadog checks. Keys of this attribute + set will be used as the name of the check to create the + appropriate configuration in `conf.d/$check.d/conf.yaml`. + + The configuration is converted into JSON from the plain Nix + language configuration, meaning that you should write + configuration adhering to Datadog's documentation - but in Nix + language. + + Refer to the implementation of this module (specifically the + definition of `defaultChecks`) for an example. + + Note: The 'disk' and 'network' check are configured in + separate options because they exist by default. Attempting to + override their configuration here will have no effect. + ''; + + example = { + http_check = { + init_config = null; # sic! + instances = [ + { + name = "some-service"; + url = "http://localhost:1337/healthz"; + tags = [ "some-service" ]; + } + ]; + }; + }; + + default = {}; + + # sic! The structure of the values is up to the check, so we can + # not usefully constrain the type further. + type = with types; attrsOf attrs; + }; + + diskCheck = mkOption { + description = "Disk check config"; + type = types.attrs; + default = { + init_config = {}; + instances = [ { use-mount = "no"; } ]; + }; + }; + + networkCheck = mkOption { + description = "Network check config"; + type = types.attrs; + default = { + init_config = {}; + # Network check only supports one configured instance + instances = [ { collect_connection_state = false; + excluded_interfaces = [ "lo" "lo0" ]; } ]; + }; + }; + }; + config = mkIf cfg.enable { + environment.systemPackages = [ datadogPkg pkgs.sysstat pkgs.procps ]; + + users.extraUsers.datadog = { + description = "Datadog Agent User"; + uid = config.ids.uids.datadog; + group = "datadog"; + home = "/var/log/datadog/"; + createHome = true; + }; + + users.extraGroups.datadog.gid = config.ids.gids.datadog; + + systemd.services = let + makeService = attrs: recursiveUpdate { + path = [ datadogPkg pkgs.python pkgs.sysstat pkgs.procps ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + User = "datadog"; + Group = "datadog"; + Restart = "always"; + RestartSec = 2; + PrivateTmp = true; + }; + restartTriggers = [ datadogPkg ] ++ map (etc: etc.source) etcfiles; + } attrs; + in { + datadog-agent = makeService { + description = "Datadog agent monitor"; + preStart = '' + chown -R datadog: /etc/datadog-agent + rm -f /etc/datadog-agent/auth_token + ''; + script = '' + export DD_API_KEY=$(head -n 1 ${cfg.apiKeyFile}) + exec ${datadogPkg}/bin/agent start -c /etc/datadog-agent/datadog.yaml + ''; + serviceConfig.PermissionsStartOnly = true; + }; + + dd-jmxfetch = lib.mkIf (lib.hasAttr "jmx" cfg.checks) (makeService { + description = "Datadog JMX Fetcher"; + path = [ datadogPkg pkgs.python pkgs.sysstat pkgs.procps pkgs.jdk ]; + serviceConfig.ExecStart = "${datadogPkg}/bin/dd-jmxfetch"; + }); + }; + + environment.etc = etcfiles; + }; +} diff --git a/nixos/modules/services/monitoring/dd-agent/dd-agent.nix b/nixos/modules/services/monitoring/dd-agent/dd-agent.nix index cf65b6c28cf2..abc8d65d58f2 100644 --- a/nixos/modules/services/monitoring/dd-agent/dd-agent.nix +++ b/nixos/modules/services/monitoring/dd-agent/dd-agent.nix @@ -114,13 +114,22 @@ let in { options.services.dd-agent = { enable = mkOption { - description = "Whether to enable the dd-agent montioring service"; + description = '' + Whether to enable the dd-agent v5 monitoring service. + For datadog-agent v6, see <option>services.datadog-agent.enable</option>. + ''; default = false; type = types.bool; }; api_key = mkOption { - description = "The Datadog API key to associate the agent with your account"; + description = '' + The Datadog API key to associate the agent with your account. + + Warning: this key is stored in cleartext within the world-readable + Nix store! Consider using the new v6 + <option>services.datadog-agent</option> module instead. + ''; example = "ae0aa6a8f08efa988ba0a17578f009ab"; type = types.str; }; @@ -188,48 +197,41 @@ in { users.groups.datadog.gid = config.ids.gids.datadog; - systemd.services.dd-agent = { - description = "Datadog agent monitor"; - path = [ pkgs."dd-agent" pkgs.python pkgs.sysstat pkgs.procps pkgs.gohai ]; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - ExecStart = "${pkgs.dd-agent}/bin/dd-agent foreground"; - User = "datadog"; - Group = "datadog"; - Restart = "always"; - RestartSec = 2; + systemd.services = let + makeService = attrs: recursiveUpdate { + path = [ pkgs.dd-agent pkgs.python pkgs.sysstat pkgs.procps pkgs.gohai ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + User = "datadog"; + Group = "datadog"; + Restart = "always"; + RestartSec = 2; + PrivateTmp = true; + }; + restartTriggers = [ pkgs.dd-agent ddConf diskConfig networkConfig postgresqlConfig nginxConfig mongoConfig jmxConfig processConfig ]; + } attrs; + in { + dd-agent = makeService { + description = "Datadog agent monitor"; + serviceConfig.ExecStart = "${pkgs.dd-agent}/bin/dd-agent foreground"; }; - restartTriggers = [ pkgs.dd-agent ddConf diskConfig networkConfig postgresqlConfig nginxConfig mongoConfig jmxConfig processConfig ]; - }; - systemd.services.dogstatsd = { - description = "Datadog statsd"; - path = [ pkgs."dd-agent" pkgs.python pkgs.procps ]; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - ExecStart = "${pkgs.dd-agent}/bin/dogstatsd start"; - User = "datadog"; - Group = "datadog"; - Type = "forking"; - PIDFile = "/tmp/dogstatsd.pid"; - Restart = "always"; - RestartSec = 2; + dogstatsd = makeService { + description = "Datadog statsd"; + environment.TMPDIR = "/run/dogstatsd"; + serviceConfig = { + ExecStart = "${pkgs.dd-agent}/bin/dogstatsd start"; + Type = "forking"; + PIDFile = "/run/dogstatsd/dogstatsd.pid"; + RuntimeDirectory = "dogstatsd"; + }; }; - restartTriggers = [ pkgs.dd-agent ddConf diskConfig networkConfig postgresqlConfig nginxConfig mongoConfig jmxConfig processConfig ]; - }; - systemd.services.dd-jmxfetch = lib.mkIf (cfg.jmxConfig != null) { - description = "Datadog JMX Fetcher"; - path = [ pkgs."dd-agent" pkgs.python pkgs.sysstat pkgs.procps pkgs.jdk ]; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - ExecStart = "${pkgs.dd-agent}/bin/dd-jmxfetch"; - User = "datadog"; - Group = "datadog"; - Restart = "always"; - RestartSec = 2; + dd-jmxfetch = lib.mkIf (cfg.jmxConfig != null) { + description = "Datadog JMX Fetcher"; + path = [ pkgs.dd-agent pkgs.python pkgs.sysstat pkgs.procps pkgs.jdk ]; + serviceConfig.ExecStart = "${pkgs.dd-agent}/bin/dd-jmxfetch"; }; - restartTriggers = [ pkgs.dd-agent ddConf diskConfig networkConfig postgresqlConfig nginxConfig mongoConfig jmxConfig ]; }; environment.etc = etcfiles; diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix index b23266e8d43a..10dc58311212 100644 --- a/nixos/modules/services/network-filesystems/samba.nix +++ b/nixos/modules/services/network-filesystems/samba.nix @@ -214,12 +214,10 @@ in } ]; # Always provide a smb.conf to shut up programs like smbclient and smbspool. - environment.etc = singleton - { source = - if cfg.enable then configFile - else pkgs.writeText "smb-dummy.conf" "# Samba is disabled."; - target = "samba/smb.conf"; - }; + environment.etc."samba/smb.conf".source = mkOptionDefault ( + if cfg.enable then configFile + else pkgs.writeText "smb-dummy.conf" "# Samba is disabled." + ); } (mkIf cfg.enable { diff --git a/nixos/modules/services/networking/dhcpcd.nix b/nixos/modules/services/networking/dhcpcd.nix index de0aa1a2c2c3..efdbca5d52e8 100644 --- a/nixos/modules/services/networking/dhcpcd.nix +++ b/nixos/modules/services/networking/dhcpcd.nix @@ -161,8 +161,9 @@ in { description = "DHCP Client"; wantedBy = [ "multi-user.target" ] ++ optional (!hasDefaultGatewaySet) "network-online.target"; - after = [ "network.target" ]; - wants = [ "network.target" ]; + wants = [ "network.target" "systemd-udev-settle.service" ]; + before = [ "network.target" ]; + after = [ "systemd-udev-settle.service" ]; # Stopping dhcpcd during a reconfiguration is undesirable # because it brings down the network interfaces configured by diff --git a/nixos/modules/services/networking/iwd.nix b/nixos/modules/services/networking/iwd.nix index cfc536fc5b5f..eb03d2e1d632 100644 --- a/nixos/modules/services/networking/iwd.nix +++ b/nixos/modules/services/networking/iwd.nix @@ -20,14 +20,7 @@ in { services.dbus.packages = [ pkgs.iwd ]; - systemd.services.iwd = { - description = "Wireless daemon"; - before = [ "network.target" ]; - wants = [ "network.target" ]; - wantedBy = [ "multi-user.target" ]; - - serviceConfig.ExecStart = "${pkgs.iwd}/libexec/iwd"; - }; + systemd.packages = [ pkgs.iwd ]; systemd.tmpfiles.rules = [ "d /var/lib/iwd 0700 root root -" diff --git a/nixos/modules/services/search/elasticsearch-curator.nix b/nixos/modules/services/search/elasticsearch-curator.nix new file mode 100644 index 000000000000..43785c392fee --- /dev/null +++ b/nixos/modules/services/search/elasticsearch-curator.nix @@ -0,0 +1,93 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.elasticsearch-curator; + curatorConfig = pkgs.writeTextFile { + name = "config.yaml"; + text = '' + --- + # Remember, leave a key empty if there is no value. None will be a string, + # not a Python "NoneType" + client: + hosts: ${builtins.toJSON cfg.hosts} + port: ${toString cfg.port} + url_prefix: + use_ssl: False + certificate: + client_cert: + client_key: + ssl_no_validate: False + http_auth: + timeout: 30 + master_only: False + logging: + loglevel: INFO + logfile: + logformat: default + blacklist: ['elasticsearch', 'urllib3'] + ''; + }; + curatorAction = pkgs.writeTextFile { + name = "action.yaml"; + text = cfg.actionYAML; + }; +in { + + options.services.elasticsearch-curator = { + + enable = mkEnableOption "elasticsearch curator"; + interval = mkOption { + description = "The frequency to run curator, a systemd.time such as 'hourly'"; + default = "hourly"; + type = types.str; + }; + hosts = mkOption { + description = "a list of elasticsearch hosts to connect to"; + type = types.listOf types.str; + default = ["localhost"]; + }; + port = mkOption { + description = "the port that elasticsearch is listening on"; + type = types.int; + default = 9200; + }; + actionYAML = mkOption { + description = "curator action.yaml file contents, alternatively use curator-cli which takes a simple action command"; + example = '' + --- + actions: + 1: + action: delete_indices + description: >- + Delete indices older than 45 days (based on index name), for logstash- + prefixed indices. Ignore the error if the filter does not result in an + actionable list of indices (ignore_empty_list) and exit cleanly. + options: + ignore_empty_list: True + disable_action: False + filters: + - filtertype: pattern + kind: prefix + value: logstash- + - filtertype: age + source: name + direction: older + timestring: '%Y.%m.%d' + unit: days + unit_count: 45 + ''; + }; + }; + + config = mkIf cfg.enable { + + systemd.services.elasticsearch-curator = { + startAt = cfg.interval; + serviceConfig = { + ExecStart = ''${pkgs.python36Packages.elasticsearch-curator}/bin/curator --config ${curatorConfig} ${curatorAction}''; + }; + }; + }; +} diff --git a/nixos/modules/services/search/elasticsearch.nix b/nixos/modules/services/search/elasticsearch.nix index b0831dcd1ca8..6b688c640d59 100644 --- a/nixos/modules/services/search/elasticsearch.nix +++ b/nixos/modules/services/search/elasticsearch.nix @@ -5,22 +5,14 @@ with lib; let cfg = config.services.elasticsearch; - es5 = builtins.compareVersions (builtins.parseDrvName cfg.package.name).version "5" >= 0; - es6 = builtins.compareVersions (builtins.parseDrvName cfg.package.name).version "6" >= 0; + es6 = builtins.compareVersions cfg.package.version "6" >= 0; esConfig = '' network.host: ${cfg.listenAddress} cluster.name: ${cfg.cluster_name} - ${if es5 then '' - http.port: ${toString cfg.port} - transport.tcp.port: ${toString cfg.tcp_port} - '' else '' - network.port: ${toString cfg.port} - network.tcp.port: ${toString cfg.tcp_port} - # TODO: find a way to enable security manager - security.manager.enabled: false - ''} + http.port: ${toString cfg.port} + transport.tcp.port: ${toString cfg.tcp_port} ${cfg.extraConf} ''; @@ -32,7 +24,7 @@ let text = esConfig; }; - loggingConfigFilename = if es5 then "log4j2.properties" else "logging.yml"; + loggingConfigFilename = "log4j2.properties"; loggingConfigFile = pkgs.writeTextFile { name = loggingConfigFilename; text = cfg.logging; @@ -41,8 +33,7 @@ let esPlugins = pkgs.buildEnv { name = "elasticsearch-plugins"; paths = cfg.plugins; - # Elasticsearch 5.x won't start when the plugins directory does not exist - postBuild = if es5 then "${pkgs.coreutils}/bin/mkdir -p $out/plugins" else ""; + postBuild = "${pkgs.coreutils}/bin/mkdir -p $out/plugins"; }; in { @@ -58,8 +49,8 @@ in { package = mkOption { description = "Elasticsearch package to use."; - default = pkgs.elasticsearch2; - defaultText = "pkgs.elasticsearch2"; + default = pkgs.elasticsearch; + defaultText = "pkgs.elasticsearch"; type = types.package; }; @@ -100,30 +91,18 @@ in { logging = mkOption { description = "Elasticsearch logging configuration."; - default = - if es5 then '' - logger.action.name = org.elasticsearch.action - logger.action.level = info - - appender.console.type = Console - appender.console.name = console - appender.console.layout.type = PatternLayout - appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%m%n - - rootLogger.level = info - rootLogger.appenderRef.console.ref = console - '' else '' - rootLogger: INFO, console - logger: - action: INFO - com.amazonaws: WARN - appender: - console: - type: console - layout: - type: consolePattern - conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n" - ''; + default = '' + logger.action.name = org.elasticsearch.action + logger.action.level = info + + appender.console.type = Console + appender.console.name = console + appender.console.layout.type = PatternLayout + appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%m%n + + rootLogger.level = info + rootLogger.appenderRef.console.ref = console + ''; type = types.str; }; @@ -204,9 +183,9 @@ in { cp ${elasticsearchYml} ${configDir}/elasticsearch.yml # Make sure the logging configuration for old elasticsearch versions is removed: - rm -f ${if es5 then "${configDir}/logging.yml" else "${configDir}/log4j2.properties"} + rm -f "${configDir}/logging.yml" cp ${loggingConfigFile} ${configDir}/${loggingConfigFilename} - ${optionalString es5 "mkdir -p ${configDir}/scripts"} + mkdir -p ${configDir}/scripts ${optionalString es6 "cp ${cfg.package}/config/jvm.options ${configDir}/jvm.options"} if [ "$(id -u)" = 0 ]; then chown -R elasticsearch:elasticsearch ${cfg.dataDir}; fi diff --git a/nixos/modules/services/search/kibana.nix b/nixos/modules/services/search/kibana.nix index 5885a72c6628..ca36bba58c02 100644 --- a/nixos/modules/services/search/kibana.nix +++ b/nixos/modules/services/search/kibana.nix @@ -5,43 +5,7 @@ with lib; let cfg = config.services.kibana; - atLeast54 = versionAtLeast (builtins.parseDrvName cfg.package.name).version "5.4"; - - cfgFile = if atLeast54 then cfgFile5 else cfgFile4; - - cfgFile4 = pkgs.writeText "kibana.json" (builtins.toJSON ( - (filterAttrsRecursive (n: v: v != null) ({ - host = cfg.listenAddress; - port = cfg.port; - ssl_cert_file = cfg.cert; - ssl_key_file = cfg.key; - - kibana_index = cfg.index; - default_app_id = cfg.defaultAppId; - - elasticsearch_url = cfg.elasticsearch.url; - kibana_elasticsearch_username = cfg.elasticsearch.username; - kibana_elasticsearch_password = cfg.elasticsearch.password; - kibana_elasticsearch_cert = cfg.elasticsearch.cert; - kibana_elasticsearch_key = cfg.elasticsearch.key; - ca = cfg.elasticsearch.ca; - - bundled_plugin_ids = [ - "plugins/dashboard/index" - "plugins/discover/index" - "plugins/doc/index" - "plugins/kibana/index" - "plugins/markdown_vis/index" - "plugins/metric_vis/index" - "plugins/settings/index" - "plugins/table_vis/index" - "plugins/vis_types/index" - "plugins/visualize/index" - ]; - } // cfg.extraConf) - ))); - - cfgFile5 = pkgs.writeText "kibana.json" (builtins.toJSON ( + cfgFile = pkgs.writeText "kibana.json" (builtins.toJSON ( (filterAttrsRecursive (n: v: v != null) ({ server.host = cfg.listenAddress; server.port = cfg.port; diff --git a/nixos/modules/services/security/cfssl.nix b/nixos/modules/services/security/cfssl.nix index 1eb2f65ba602..ee6d5d91fe15 100644 --- a/nixos/modules/services/security/cfssl.nix +++ b/nixos/modules/services/security/cfssl.nix @@ -146,7 +146,7 @@ in { }; }; - config = { + config = mkIf cfg.enable { users.extraGroups.cfssl = { gid = config.ids.gids.cfssl; }; @@ -159,7 +159,7 @@ in { uid = config.ids.uids.cfssl; }; - systemd.services.cfssl = mkIf cfg.enable { + systemd.services.cfssl = { description = "CFSSL CA API server"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; diff --git a/nixos/modules/services/system/localtime.nix b/nixos/modules/services/system/localtime.nix index b9355bbb9441..c7e897c96448 100644 --- a/nixos/modules/services/system/localtime.nix +++ b/nixos/modules/services/system/localtime.nix @@ -22,14 +22,8 @@ in { config = mkIf cfg.enable { services.geoclue2.enable = true; - security.polkit.extraConfig = '' - polkit.addRule(function(action, subject) { - if (action.id == "org.freedesktop.timedate1.set-timezone" - && subject.user == "localtimed") { - return polkit.Result.YES; - } - }); - ''; + # so polkit will pick up the rules + environment.systemPackages = [ pkgs.localtime ]; users.users = [{ name = "localtimed"; diff --git a/nixos/modules/services/web-servers/hydron.nix b/nixos/modules/services/web-servers/hydron.nix index c49efaede160..ed63230bc784 100644 --- a/nixos/modules/services/web-servers/hydron.nix +++ b/nixos/modules/services/web-servers/hydron.nix @@ -16,10 +16,10 @@ in with lib; { interval = mkOption { type = types.str; - default = "hourly"; + default = "weekly"; example = "06:00"; description = '' - How often we run hydron import and possibly fetch tags. Runs by default every hour. + How often we run hydron import and possibly fetch tags. Runs by default every week. The format is described in <citerefentry><refentrytitle>systemd.time</refentrytitle> @@ -137,9 +137,13 @@ in with lib; { systemd.timers.hydron-fetch = { description = "Automatically import paths into hydron and possibly fetch tags"; - after = [ "network.target" ]; + after = [ "network.target" "hydron.service" ]; wantedBy = [ "timers.target" ]; - timerConfig.OnCalendar = cfg.interval; + + timerConfig = { + Persistent = true; + OnCalendar = cfg.interval; + }; }; users = { diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix index ee9b11928ae1..c339d24b098a 100644 --- a/nixos/modules/services/x11/desktop-managers/gnome3.nix +++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix @@ -97,6 +97,8 @@ in { services.udisks2.enable = true; services.accounts-daemon.enable = true; services.geoclue2.enable = mkDefault true; + # GNOME should have its own geoclue agent + services.geoclue2.enableDemoAgent = false; services.dleyna-renderer.enable = mkDefault true; services.dleyna-server.enable = mkDefault true; services.gnome3.at-spi2-core.enable = true; diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix index 6be15d8cdf46..dc82f7086c82 100644 --- a/nixos/modules/services/x11/display-managers/lightdm.nix +++ b/nixos/modules/services/x11/display-managers/lightdm.nix @@ -15,7 +15,7 @@ let inherit (pkgs) lightdm writeScript writeText; - # lightdm runs with clearenv(), but we need a few things in the enviornment for X to startup + # lightdm runs with clearenv(), but we need a few things in the environment for X to startup xserverWrapper = writeScript "xserver-wrapper" '' #! ${pkgs.bash}/bin/bash @@ -209,9 +209,12 @@ in services.dbus.enable = true; services.dbus.packages = [ lightdm ]; - # lightdm uses the accounts daemon to rember language/window-manager per user + # lightdm uses the accounts daemon to remember language/window-manager per user services.accounts-daemon.enable = true; + # Enable the accounts daemon to find lightdm's dbus interface + environment.systemPackages = [ lightdm ]; + security.pam.services.lightdm = { allowNullPassword = true; startSession = true; diff --git a/nixos/modules/services/x11/redshift.nix b/nixos/modules/services/x11/redshift.nix index 30d853841ea4..b7dd7debcb63 100644 --- a/nixos/modules/services/x11/redshift.nix +++ b/nixos/modules/services/x11/redshift.nix @@ -116,6 +116,9 @@ in { } ]; + # needed so that .desktop files are installed, which geoclue cares about + environment.systemPackages = [ cfg.package ]; + services.geoclue2.enable = mkIf (cfg.provider == "geoclue2") true; systemd.user.services.redshift = diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix index da29e08b3691..9d410a8b9ca4 100644 --- a/nixos/modules/system/activation/top-level.nix +++ b/nixos/modules/system/activation/top-level.nix @@ -46,7 +46,7 @@ let ln -s ${kernelPath} $out/kernel ln -s ${config.system.modulesTree} $out/kernel-modules - ${optionalString (pkgs.stdenv.platform.kernelDTB or false) '' + ${optionalString (pkgs.stdenv.hostPlatform.platform.kernelDTB or false) '' ln -s ${config.boot.kernelPackages.kernel}/dtbs $out/dtbs ''} @@ -74,7 +74,7 @@ let echo -n "$configurationName" > $out/configuration-name echo -n "systemd ${toString config.systemd.package.interfaceVersion}" > $out/init-interface-version echo -n "$nixosLabel" > $out/nixos-version - echo -n "$system" > $out/system + echo -n "${pkgs.stdenv.hostPlatform.system}" > $out/system mkdir $out/fine-tune childCount=0 @@ -175,7 +175,7 @@ in system.boot.loader.kernelFile = mkOption { internal = true; - default = pkgs.stdenv.platform.kernelTarget; + default = pkgs.stdenv.hostPlatform.platform.kernelTarget; type = types.str; description = '' Name of the kernel file to be passed to the bootloader. diff --git a/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix b/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix index f8a00784034a..2d27611946e2 100644 --- a/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix +++ b/nixos/modules/system/boot/loader/generations-dir/generations-dir.nix @@ -13,7 +13,7 @@ let }; # Temporary check, for nixos to cope both with nixpkgs stdenv-updates and trunk - platform = pkgs.stdenv.platform; + inherit (pkgs.stdenv.hostPlatform) platform; in diff --git a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix index f974d07da9e5..9bec24c53f5b 100644 --- a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix +++ b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix @@ -15,7 +15,7 @@ let inherit configTxt; }; - platform = pkgs.stdenv.platform; + inherit (pkgs.stdenv.hostPlatform) platform; builderUboot = import ./builder_uboot.nix { inherit config; inherit pkgs; inherit configTxt; }; diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix index ce770d067608..c11aaeaeb6dc 100644 --- a/nixos/modules/system/boot/networkd.nix +++ b/nixos/modules/system/boot/networkd.nix @@ -11,17 +11,29 @@ let checkLink = checkUnitConfig "Link" [ (assertOnlyFields [ "Description" "Alias" "MACAddressPolicy" "MACAddress" "NamePolicy" "Name" - "MTUBytes" "BitsPerSecond" "Duplex" "WakeOnLan" + "MTUBytes" "BitsPerSecond" "Duplex" "AutoNegotiation" "WakeOnLan" "Port" + "TCPSegmentationOffload" "TCP6SegmentationOffload" "GenericSegmentationOffload" + "GenericReceiveOffload" "LargeReceiveOffload" "RxChannels" "TxChannels" + "OtherChannels" "CombinedChannels" ]) - (assertValueOneOf "MACAddressPolicy" ["persistent" "random"]) + (assertValueOneOf "MACAddressPolicy" ["persistent" "random" "none"]) (assertMacAddress "MACAddress") - (assertValueOneOf "NamePolicy" [ - "kernel" "database" "onboard" "slot" "path" "mac" - ]) (assertByteFormat "MTUBytes") (assertByteFormat "BitsPerSecond") (assertValueOneOf "Duplex" ["half" "full"]) - (assertValueOneOf "WakeOnLan" ["phy" "magic" "off"]) + (assertValueOneOf "AutoNegotiation" boolValues) + (assertValueOneOf "WakeOnLan" ["phy" "unicast" "multicast" "broadcast" "arp" "magic" "secureon" "off"]) + (assertValueOneOf "Port" ["tp" "aui" "bnc" "mii" "fibre"]) + (assertValueOneOf "TCPSegmentationOffload" boolValues) + (assertValueOneOf "TCP6SegmentationOffload" boolValues) + (assertValueOneOf "GenericSegmentationOffload" boolValues) + (assertValueOneOf "UDPSegmentationOffload" boolValues) + (assertValueOneOf "GenericReceiveOffload" boolValues) + (assertValueOneOf "LargeReceiveOffload" boolValues) + (assertRange "RxChannels" 1 4294967295) + (assertRange "TxChannels" 1 4294967295) + (assertRange "OtherChannels" 1 4294967295) + (assertRange "CombinedChannels" 1 4294967295) ]; checkNetdev = checkUnitConfig "Netdev" [ @@ -31,16 +43,21 @@ let (assertHasField "Name") (assertHasField "Kind") (assertValueOneOf "Kind" [ - "bridge" "bond" "vlan" "macvlan" "vxlan" "ipip" - "gre" "sit" "vti" "veth" "tun" "tap" "dummy" + "bond" "bridge" "dummy" "gre" "gretap" "ip6gre" "ip6tnl" "ip6gretap" "ipip" + "ipvlan" "macvlan" "macvtap" "sit" "tap" "tun" "veth" "vlan" "vti" "vti6" + "vxlan" "geneve" "vrf" "vcan" "vxcan" "wireguard" "netdevsim" ]) (assertByteFormat "MTUBytes") (assertMacAddress "MACAddress") ]; checkVlan = checkUnitConfig "VLAN" [ - (assertOnlyFields ["Id"]) + (assertOnlyFields ["Id" "GVRP" "MVRP" "LooseBinding" "ReorderHeader"]) (assertRange "Id" 0 4094) + (assertValueOneOf "GVRP" boolValues) + (assertValueOneOf "MVRP" boolValues) + (assertValueOneOf "LooseBinding" boolValues) + (assertValueOneOf "ReorderHeader" boolValues) ]; checkMacvlan = checkUnitConfig "MACVLAN" [ @@ -49,15 +66,41 @@ let ]; checkVxlan = checkUnitConfig "VXLAN" [ - (assertOnlyFields ["Id" "Group" "TOS" "TTL" "MacLearning"]) + (assertOnlyFields [ + "Id" "Remote" "Local" "TOS" "TTL" "MacLearning" "FDBAgeingSec" + "MaximumFDBEntries" "ReduceARPProxy" "L2MissNotification" + "L3MissNotification" "RouteShortCircuit" "UDPChecksum" + "UDP6ZeroChecksumTx" "UDP6ZeroChecksumRx" "RemoteChecksumTx" + "RemoteChecksumRx" "GroupPolicyExtension" "DestinationPort" "PortRange" + "FlowLabel" + ]) (assertRange "TTL" 0 255) (assertValueOneOf "MacLearning" boolValues) + (assertValueOneOf "ReduceARPProxy" boolValues) + (assertValueOneOf "L2MissNotification" boolValues) + (assertValueOneOf "L3MissNotification" boolValues) + (assertValueOneOf "RouteShortCircuit" boolValues) + (assertValueOneOf "UDPChecksum" boolValues) + (assertValueOneOf "UDP6ZeroChecksumTx" boolValues) + (assertValueOneOf "UDP6ZeroChecksumRx" boolValues) + (assertValueOneOf "RemoteChecksumTx" boolValues) + (assertValueOneOf "RemoteChecksumRx" boolValues) + (assertValueOneOf "GroupPolicyExtension" boolValues) + (assertRange "FlowLabel" 0 1048575) ]; checkTunnel = checkUnitConfig "Tunnel" [ - (assertOnlyFields ["Local" "Remote" "TOS" "TTL" "DiscoverPathMTU"]) + (assertOnlyFields [ + "Local" "Remote" "TOS" "TTL" "DiscoverPathMTU" "IPv6FlowLabel" "CopyDSCP" + "EncapsulationLimit" "Key" "InputKey" "OutputKey" "Mode" "Independent" + "AllowLocalRemote" + ]) (assertRange "TTL" 0 255) (assertValueOneOf "DiscoverPathMTU" boolValues) + (assertValueOneOf "CopyDSCP" boolValues) + (assertValueOneOf "Mode" ["ip6ip6" "ipip6" "any"]) + (assertValueOneOf "Independent" boolValues) + (assertValueOneOf "AllowLocalRemote" boolValues) ]; checkPeer = checkUnitConfig "Peer" [ @@ -66,10 +109,11 @@ let ]; tunTapChecks = [ - (assertOnlyFields ["OneQueue" "MultiQueue" "PacketInfo" "User" "Group"]) + (assertOnlyFields ["OneQueue" "MultiQueue" "PacketInfo" "VNetHeader" "User" "Group"]) (assertValueOneOf "OneQueue" boolValues) (assertValueOneOf "MultiQueue" boolValues) (assertValueOneOf "PacketInfo" boolValues) + (assertValueOneOf "VNetHeader" boolValues) ]; checkTun = checkUnitConfig "Tun" tunTapChecks; @@ -79,67 +123,121 @@ let checkBond = checkUnitConfig "Bond" [ (assertOnlyFields [ "Mode" "TransmitHashPolicy" "LACPTransmitRate" "MIIMonitorSec" - "UpDelaySec" "DownDelaySec" "GratuitousARP" + "UpDelaySec" "DownDelaySec" "LearnPacketIntervalSec" "AdSelect" + "FailOverMACPolicy" "ARPValidate" "ARPIntervalSec" "ARPIPTargets" + "ARPAllTargets" "PrimaryReselectPolicy" "ResendIGMP" "PacketsPerSlave" + "GratuitousARP" "AllSlavesActive" "MinLinks" ]) (assertValueOneOf "Mode" [ "balance-rr" "active-backup" "balance-xor" "broadcast" "802.3ad" "balance-tlb" "balance-alb" ]) (assertValueOneOf "TransmitHashPolicy" [ - "layer2" "layer3+4" "layer2+3" "encap2+3" "802.3ad" "encap3+4" + "layer2" "layer3+4" "layer2+3" "encap2+3" "encap3+4" ]) (assertValueOneOf "LACPTransmitRate" ["slow" "fast"]) + (assertValueOneOf "AdSelect" ["stable" "bandwidth" "count"]) + (assertValueOneOf "FailOverMACPolicy" ["none" "active" "follow"]) + (assertValueOneOf "ARPValidate" ["none" "active" "backup" "all"]) + (assertValueOneOf "ARPAllTargets" ["any" "all"]) + (assertValueOneOf "PrimaryReselectPolicy" ["always" "better" "failure"]) + (assertRange "ResendIGMP" 0 255) + (assertRange "PacketsPerSlave" 0 65535) + (assertRange "GratuitousARP" 0 255) + (assertValueOneOf "AllSlavesActive" boolValues) ]; checkNetwork = checkUnitConfig "Network" [ (assertOnlyFields [ - "Description" "DHCP" "DHCPServer" "IPForward" "IPMasquerade" "IPv4LL" "IPv4LLRoute" - "LLMNR" "MulticastDNS" "Domains" "Bridge" "Bond" "IPv6PrivacyExtensions" + "Description" "DHCP" "DHCPServer" "LinkLocalAddressing" "IPv4LLRoute" + "IPv6Token" "LLMNR" "MulticastDNS" "DNSOverTLS" "DNSSEC" + "DNSSECNegativeTrustAnchors" "LLDP" "EmitLLDP" "BindCarrier" "Address" + "Gateway" "DNS" "Domains" "NTP" "IPForward" "IPMasquerade" + "IPv6PrivacyExtensions" "IPv6AcceptRA" "IPv6DuplicateAddressDetection" + "IPv6HopLimit" "IPv4ProxyARP" "IPv6ProxyNDP" "IPv6ProxyNDPAddress" + "IPv6PrefixDelegation" "IPv6MTUBytes" "Bridge" "Bond" "VRF" "VLAN" + "IPVLAN" "MACVLAN" "VXLAN" "Tunnel" "ActiveSlave" "PrimarySlave" + "ConfigureWithoutCarrier" ]) - (assertValueOneOf "DHCP" ["both" "none" "v4" "v6"]) + # Note: For DHCP the values both, none, v4, v6 are deprecated + (assertValueOneOf "DHCP" ["yes" "no" "ipv4" "ipv6" "both" "none" "v4" "v6"]) (assertValueOneOf "DHCPServer" boolValues) + (assertValueOneOf "LinkLocalAddressing" ["yes" "no" "ipv4" "ipv6"]) + (assertValueOneOf "IPv4LLRoute" boolValues) + (assertValueOneOf "LLMNR" ["yes" "resolve" "no"]) + (assertValueOneOf "MulticastDNS" ["yes" "resolve" "no"]) + (assertValueOneOf "DNSOverTLS" ["opportunistic" "no"]) + (assertValueOneOf "DNSSEC" ["yes" "allow-downgrade" "no"]) + (assertValueOneOf "LLDP" ["yes" "routers-only" "no"]) + (assertValueOneOf "EmitLLDP" ["yes" "no" "nearest-bridge" "non-tpmr-bridge" "customer-bridge"]) (assertValueOneOf "IPForward" ["yes" "no" "ipv4" "ipv6"]) (assertValueOneOf "IPMasquerade" boolValues) - (assertValueOneOf "IPv4LL" boolValues) - (assertValueOneOf "IPv4LLRoute" boolValues) - (assertValueOneOf "LLMNR" boolValues) - (assertValueOneOf "MulticastDNS" boolValues) (assertValueOneOf "IPv6PrivacyExtensions" ["yes" "no" "prefer-public" "kernel"]) + (assertValueOneOf "IPv6AcceptRA" boolValues) + (assertValueOneOf "IPv4ProxyARP" boolValues) + (assertValueOneOf "IPv6ProxyNDP" boolValues) + (assertValueOneOf "IPv6PrefixDelegation" boolValues) + (assertValueOneOf "ActiveSlave" boolValues) + (assertValueOneOf "PrimarySlave" boolValues) + (assertValueOneOf "ConfigureWithoutCarrier" boolValues) ]; checkAddress = checkUnitConfig "Address" [ - (assertOnlyFields ["Address" "Peer" "Broadcast" "Label"]) + (assertOnlyFields [ + "Address" "Peer" "Broadcast" "Label" "PreferredLifetime" "Scope" + "HomeAddress" "DuplicateAddressDetection" "ManageTemporaryAddress" + "PrefixRoute" "AutoJoin" + ]) (assertHasField "Address") + (assertValueOneOf "PreferredLifetime" ["forever" "infinity" "0" 0]) + (assertValueOneOf "HomeAddress" boolValues) + (assertValueOneOf "DuplicateAddressDetection" boolValues) + (assertValueOneOf "ManageTemporaryAddress" boolValues) + (assertValueOneOf "PrefixRoute" boolValues) + (assertValueOneOf "AutoJoin" boolValues) ]; checkRoute = checkUnitConfig "Route" [ - (assertOnlyFields ["Gateway" "Destination" "Metric"]) + (assertOnlyFields [ + "Gateway" "GatewayOnlink" "Destination" "Source" "Metric" + "IPv6Preference" "Scope" "PreferredSource" "Table" "Protocol" "Type" + "InitialCongestionWindow" "InitialAdvertisedReceiveWindow" "QuickAck" + "MTUBytes" + ]) (assertHasField "Gateway") ]; checkDhcp = checkUnitConfig "DHCP" [ (assertOnlyFields [ - "UseDNS" "UseMTU" "SendHostname" "UseHostname" "UseDomains" "UseRoutes" - "CriticalConnections" "VendorClassIdentifier" "RequestBroadcast" - "RouteMetric" + "UseDNS" "UseNTP" "UseMTU" "Anonymize" "SendHostname" "UseHostname" + "Hostname" "UseDomains" "UseRoutes" "UseTimezone" "CriticalConnection" + "ClientIdentifier" "VendorClassIdentifier" "UserClass" "DUIDType" + "DUIDRawData" "IAID" "RequestBroadcast" "RouteMetric" "RouteTable" + "ListenPort" "RapidCommit" ]) (assertValueOneOf "UseDNS" boolValues) + (assertValueOneOf "UseNTP" boolValues) (assertValueOneOf "UseMTU" boolValues) + (assertValueOneOf "Anonymize" boolValues) (assertValueOneOf "SendHostname" boolValues) (assertValueOneOf "UseHostname" boolValues) - (assertValueOneOf "UseDomains" boolValues) + (assertValueOneOf "UseDomains" ["yes" "no" "route"]) (assertValueOneOf "UseRoutes" boolValues) - (assertValueOneOf "CriticalConnections" boolValues) + (assertValueOneOf "UseTimezone" boolValues) + (assertValueOneOf "CriticalConnection" boolValues) (assertValueOneOf "RequestBroadcast" boolValues) + (assertRange "RouteTable" 0 4294967295) + (assertValueOneOf "RapidCommit" boolValues) ]; checkDhcpServer = checkUnitConfig "DHCPServer" [ (assertOnlyFields [ "PoolOffset" "PoolSize" "DefaultLeaseTimeSec" "MaxLeaseTimeSec" - "EmitDNS" "DNS" "EmitNTP" "NTP" "EmitTimezone" "Timezone" + "EmitDNS" "DNS" "EmitNTP" "NTP" "EmitRouter" "EmitTimezone" "Timezone" ]) (assertValueOneOf "EmitDNS" boolValues) (assertValueOneOf "EmitNTP" boolValues) + (assertValueOneOf "EmitRouter" boolValues) (assertValueOneOf "EmitTimezone" boolValues) ]; @@ -461,6 +559,36 @@ let ''; }; + bridge = mkOption { + default = [ ]; + type = types.listOf types.str; + description = '' + A list of bridge interfaces to be added to the network section of the + unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle> + <manvolnum>5</manvolnum></citerefentry> for details. + ''; + }; + + bond = mkOption { + default = [ ]; + type = types.listOf types.str; + description = '' + A list of bond interfaces to be added to the network section of the + unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle> + <manvolnum>5</manvolnum></citerefentry> for details. + ''; + }; + + vrf = mkOption { + default = [ ]; + type = types.listOf types.str; + description = '' + A list of vrf interfaces to be added to the network section of the + unit. See <citerefentry><refentrytitle>systemd.network</refentrytitle> + <manvolnum>5</manvolnum></citerefentry> for details. + ''; + }; + vlan = mkOption { default = [ ]; type = types.listOf types.str; @@ -619,6 +747,9 @@ let ${concatStringsSep "\n" (map (s: "Gateway=${s}") def.gateway)} ${concatStringsSep "\n" (map (s: "DNS=${s}") def.dns)} ${concatStringsSep "\n" (map (s: "NTP=${s}") def.ntp)} + ${concatStringsSep "\n" (map (s: "Bridge=${s}") def.bridge)} + ${concatStringsSep "\n" (map (s: "Bond=${s}") def.bond)} + ${concatStringsSep "\n" (map (s: "VRF=${s}") def.vrf)} ${concatStringsSep "\n" (map (s: "VLAN=${s}") def.vlan)} ${concatStringsSep "\n" (map (s: "MACVLAN=${s}") def.macvlan)} ${concatStringsSep "\n" (map (s: "VXLAN=${s}") def.vxlan)} diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix index 2caab69cbb95..f58b68cb3353 100644 --- a/nixos/modules/system/boot/stage-1.nix +++ b/nixos/modules/system/boot/stage-1.nix @@ -179,7 +179,7 @@ let fi done - if [ -z "${toString pkgs.stdenv.isCross}" ]; then + if [ -z "${toString (pkgs.stdenv.hostPlatform != pkgs.stdenv.buildPlatform)}" ]; then # Make sure that the patchelf'ed binaries still work. echo "testing patched programs..." $out/bin/ash -c 'echo hello world' | grep "hello world" diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index 2d3d80a91bc6..12e029ae57f8 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -65,6 +65,7 @@ let "systemd-user-sessions.service" "dbus-org.freedesktop.machine1.service" "user@.service" + "user-runtime-dir@.service" # Journal. "systemd-journald.socket" diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix index 7120856387ef..2b3b09d725c7 100644 --- a/nixos/modules/tasks/filesystems/zfs.nix +++ b/nixos/modules/tasks/filesystems/zfs.nix @@ -23,12 +23,8 @@ let kernel = config.boot.kernelPackages; - packages = if config.boot.zfs.enableLegacyCrypto then { - spl = kernel.splLegacyCrypto; - zfs = kernel.zfsLegacyCrypto; - zfsUser = pkgs.zfsLegacyCrypto; - } else if config.boot.zfs.enableUnstable then { - spl = kernel.splUnstable; + packages = if config.boot.zfs.enableUnstable then { + spl = null; zfs = kernel.zfsUnstable; zfsUser = pkgs.zfsUnstable; } else { @@ -117,27 +113,6 @@ in ''; }; - enableLegacyCrypto = mkOption { - type = types.bool; - default = false; - description = '' - Enabling this option will allow you to continue to use the old format for - encrypted datasets. With the inclusion of stability patches the format of - encrypted datasets has changed. They can still be accessed and mounted but - in read-only mode mounted. It is highly recommended to convert them to - the new format. - - This option is only for convenience to people that cannot convert their - datasets to the new format yet and it will be removed in due time. - - For migration strategies from old format to this new one, check the Wiki: - https://nixos.wiki/wiki/NixOS_on_ZFS#Encrypted_Dataset_Format_Change - - See https://github.com/zfsonlinux/zfs/pull/6864 for more details about - the stability patches. - ''; - }; - extraPools = mkOption { type = types.listOf types.str; default = []; @@ -350,12 +325,12 @@ in virtualisation.lxd.zfsSupport = true; boot = { - kernelModules = [ "spl" "zfs" ] ; - extraModulePackages = with packages; [ spl zfs ]; + kernelModules = [ "zfs" ] ++ optional (!cfgZfs.enableUnstable) "spl"; + extraModulePackages = with packages; [ zfs ] ++ optional (!cfgZfs.enableUnstable) spl; }; boot.initrd = mkIf inInitrd { - kernelModules = [ "spl" "zfs" ]; + kernelModules = [ "zfs" ] ++ optional (!cfgZfs.enableUnstable) "spl"; extraUtilsCommands = '' copy_bin_and_libs ${packages.zfsUser}/sbin/zfs diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix index 0abf7b11703c..4e9c87222d0a 100644 --- a/nixos/modules/virtualisation/qemu-vm.nix +++ b/nixos/modules/virtualisation/qemu-vm.nix @@ -156,9 +156,6 @@ let --partition-guid=2:970C694F-AFD0-4B99-B750-CDB7A329AB6F \ --hybrid 2 \ --recompute-chs /dev/vda - . /sys/class/block/vda2/uevent - mknod /dev/vda2 b $MAJOR $MINOR - . /sys/class/block/vda/uevent ${pkgs.dosfstools}/bin/mkfs.fat -F16 /dev/vda2 export MTOOLS_SKIP_CHECK=1 ${pkgs.mtools}/bin/mlabel -i /dev/vda2 ::boot diff --git a/nixos/modules/virtualisation/virtualbox-host.nix b/nixos/modules/virtualisation/virtualbox-host.nix index b69860a199a2..60779579402c 100644 --- a/nixos/modules/virtualisation/virtualbox-host.nix +++ b/nixos/modules/virtualisation/virtualbox-host.nix @@ -6,7 +6,8 @@ let cfg = config.virtualisation.virtualbox.host; virtualbox = cfg.package.override { - inherit (cfg) enableExtensionPack enableHardening headless; + inherit (cfg) enableHardening headless; + extensionPack = if cfg.enableExtensionPack then pkgs.virtualboxExtpack else null; }; kernelModules = config.boot.kernelPackages.virtualbox.override { @@ -28,6 +29,17 @@ in ''; }; + enableExtensionPack = mkEnableOption "VirtualBox extension pack" // { + description = '' + Whether to install the Oracle Extension Pack for VirtualBox. + + <important><para> + You must set <literal>nixpkgs.config.allowUnfree = true</literal> in + order to use this. This requires you accept the VirtualBox PUEL. + </para></important> + ''; + }; + package = mkOption { type = types.package; default = pkgs.virtualbox; @@ -45,8 +57,6 @@ in ''; }; - enableExtensionPack = mkEnableOption "VirtualBox extension pack"; - enableHardening = mkOption { type = types.bool; default = true; diff --git a/nixos/release.nix b/nixos/release.nix index 1d1f8009f27c..b25c684ff47a 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -83,7 +83,7 @@ let in tarball // { meta = { - description = "NixOS system tarball for ${system} - ${stdenv.platform.name}"; + description = "NixOS system tarball for ${system} - ${stdenv.hostPlatform.platform.name}"; maintainers = map (x: lib.maintainers.${x}) maintainers; }; inherit config; @@ -106,7 +106,7 @@ let let configEvaled = import lib/eval-config.nix config; build = configEvaled.config.system.build; - kernelTarget = configEvaled.pkgs.stdenv.platform.kernelTarget; + kernelTarget = configEvaled.pkgs.stdenv.hostPlatform.platform.kernelTarget; in pkgs.symlinkJoin { name = "netboot"; diff --git a/nixos/tests/ec2.nix b/nixos/tests/ec2.nix index f585fa2ec237..8271747ccc63 100644 --- a/nixos/tests/ec2.nix +++ b/nixos/tests/ec2.nix @@ -68,7 +68,9 @@ let # again when it deletes link-local addresses.) Ideally we'd # turn off the DHCP server, but qemu does not have an option # to do that. - my $startCommand = "qemu-kvm -m 768 -net nic,vlan=0,model=virtio -net 'user,vlan=0,net=169.0.0.0/8,guestfwd=tcp:169.254.169.254:80-cmd:${pkgs.micro-httpd}/bin/micro_httpd ${metaData}'"; + my $startCommand = "qemu-kvm -m 768"; + $startCommand .= " -device virtio-net-pci,netdev=vlan0"; + $startCommand .= " -netdev 'user,id=vlan0,net=169.0.0.0/8,guestfwd=tcp:169.254.169.254:80-cmd:${pkgs.micro-httpd}/bin/micro_httpd ${metaData}'"; $startCommand .= " -drive file=$diskImage,if=virtio,werror=report"; $startCommand .= " \$QEMU_OPTS"; diff --git a/nixos/tests/elk.nix b/nixos/tests/elk.nix index 4c5c441ca265..15be72b80bba 100644 --- a/nixos/tests/elk.nix +++ b/nixos/tests/elk.nix @@ -63,6 +63,33 @@ let package = elk.kibana; elasticsearch.url = esUrl; }; + + elasticsearch-curator = { + enable = true; + actionYAML = '' + --- + actions: + 1: + action: delete_indices + description: >- + Delete indices older than 1 second (based on index name), for logstash- + prefixed indices. Ignore the error if the filter does not result in an + actionable list of indices (ignore_empty_list) and exit cleanly. + options: + ignore_empty_list: True + disable_action: False + filters: + - filtertype: pattern + kind: prefix + value: logstash- + - filtertype: age + source: name + direction: older + timestring: '%Y.%m.%d' + unit: seconds + unit_count: 1 + ''; + }; }; }; }; @@ -91,6 +118,11 @@ let # See if logstash messages arive in elasticsearch. $one->waitUntilSucceeds("curl --silent --show-error '${esUrl}/_search' -H 'Content-Type: application/json' -d '{\"query\" : { \"match\" : { \"message\" : \"flowers\"}}}' | jq .hits.total | grep -v 0"); $one->waitUntilSucceeds("curl --silent --show-error '${esUrl}/_search' -H 'Content-Type: application/json' -d '{\"query\" : { \"match\" : { \"message\" : \"dragons\"}}}' | jq .hits.total | grep 0"); + + # Test elasticsearch-curator. + $one->systemctl("stop logstash"); + $one->systemctl("start elasticsearch-curator"); + $one->waitUntilSucceeds("! curl --silent --show-error '${esUrl}/_cat/indices' | grep logstash | grep -q ^$1"); ''; }; in mapAttrs mkElkTest { diff --git a/nixos/tests/home-assistant.nix b/nixos/tests/home-assistant.nix index 0c027eaca619..2d74b59bca46 100644 --- a/nixos/tests/home-assistant.nix +++ b/nixos/tests/home-assistant.nix @@ -2,7 +2,8 @@ import ./make-test.nix ({ pkgs, ... }: let configDir = "/var/lib/foobar"; - apiPassword = "secret"; + apiPassword = "some_secret"; + mqttPassword = "another_secret"; in { name = "home-assistant"; @@ -33,7 +34,9 @@ in { }; frontend = { }; http.api_password = apiPassword; - mqtt = { }; # Use hbmqtt as broker + mqtt = { # Use hbmqtt as broker + password = mqttPassword; + }; binary_sensor = [ { platform = "mqtt"; @@ -62,7 +65,7 @@ in { # Toggle a binary sensor using MQTT $hass->succeed("curl http://localhost:8123/api/states/binary_sensor.mqtt_binary_sensor -H 'x-ha-access: ${apiPassword}' | grep -qF '\"state\": \"off\"'"); - $hass->waitUntilSucceeds("mosquitto_pub -V mqttv311 -t home-assistant/test -u homeassistant -P '${apiPassword}' -m let_there_be_light"); + $hass->waitUntilSucceeds("mosquitto_pub -V mqttv311 -t home-assistant/test -u homeassistant -P '${mqttPassword}' -m let_there_be_light"); $hass->succeed("curl http://localhost:8123/api/states/binary_sensor.mqtt_binary_sensor -H 'x-ha-access: ${apiPassword}' | grep -qF '\"state\": \"on\"'"); # Print log to ease debugging diff --git a/nixos/tests/hydra/default.nix b/nixos/tests/hydra/default.nix index 98d99811f3c0..db4e97e0039b 100644 --- a/nixos/tests/hydra/default.nix +++ b/nixos/tests/hydra/default.nix @@ -2,14 +2,11 @@ import ../make-test.nix ({ pkgs, ...} : let trivialJob = pkgs.writeTextDir "trivial.nix" '' - with import <nix/config.nix>; - { trivial = builtins.derivation { name = "trivial"; system = "x86_64-linux"; - PATH = coreutils; - builder = shell; - args = ["-c" "touch $out; exit 0"]; + builder = "/bin/sh"; + args = ["-c" "echo success > $out; exit 0"]; }; } ''; @@ -27,7 +24,7 @@ let in { name = "hydra-init-localdb"; meta = with pkgs.stdenv.lib.maintainers; { - maintainers = [ pstn lewo ]; + maintainers = [ pstn lewo ma27 ]; }; machine = @@ -50,6 +47,8 @@ in { hostName = "localhost"; systems = [ "x86_64-linux" ]; }]; + + binaryCaches = []; }; }; @@ -74,5 +73,5 @@ in { $machine->succeed("create-trivial-project.sh"); $machine->waitUntilSucceeds('curl -L -s http://localhost:3000/build/1 -H "Accept: application/json" | jq .buildstatus | xargs test 0 -eq'); - ''; + ''; }) diff --git a/nixos/tests/matrix-synapse.nix b/nixos/tests/matrix-synapse.nix index 113fb622588b..8504a7c0d057 100644 --- a/nixos/tests/matrix-synapse.nix +++ b/nixos/tests/matrix-synapse.nix @@ -6,12 +6,13 @@ import ./make-test.nix ({ pkgs, ... } : { }; nodes = { - server_postgres = args: { + # Since 0.33.0, matrix-synapse doesn't allow underscores in server names + serverpostgres = args: { services.matrix-synapse.enable = true; services.matrix-synapse.database_type = "psycopg2"; }; - server_sqlite = args: { + serversqlite = args: { services.matrix-synapse.enable = true; services.matrix-synapse.database_type = "sqlite3"; }; @@ -19,12 +20,12 @@ import ./make-test.nix ({ pkgs, ... } : { testScript = '' startAll; - $server_postgres->waitForUnit("matrix-synapse.service"); - $server_postgres->waitUntilSucceeds("curl -Lk https://localhost:8448/"); - $server_postgres->requireActiveUnit("postgresql.service"); - $server_sqlite->waitForUnit("matrix-synapse.service"); - $server_sqlite->waitUntilSucceeds("curl -Lk https://localhost:8448/"); - $server_sqlite->mustSucceed("[ -e /var/lib/matrix-synapse/homeserver.db ]"); + $serverpostgres->waitForUnit("matrix-synapse.service"); + $serverpostgres->waitUntilSucceeds("curl -Lk https://localhost:8448/"); + $serverpostgres->requireActiveUnit("postgresql.service"); + $serversqlite->waitForUnit("matrix-synapse.service"); + $serversqlite->waitUntilSucceeds("curl -Lk https://localhost:8448/"); + $serversqlite->mustSucceed("[ -e /var/lib/matrix-synapse/homeserver.db ]"); ''; }) diff --git a/nixos/tests/munin.nix b/nixos/tests/munin.nix index eb91d4d630bc..9f66005292ab 100644 --- a/nixos/tests/munin.nix +++ b/nixos/tests/munin.nix @@ -12,16 +12,23 @@ import ./make-test.nix ({ pkgs, ...} : { { config, ... }: { services = { - munin-node.enable = true; - munin-cron = { + munin-node = { enable = true; - hosts = '' - [${config.networking.hostName}] - address localhost + # disable a failing plugin to prevent irrelevant error message, see #23049 + extraConfig = '' + ignore_file ^apc_nis$ ''; }; + munin-cron = { + enable = true; + hosts = '' + [${config.networking.hostName}] + address localhost + ''; + }; }; - systemd.services.munin-node.serviceConfig.TimeoutStartSec = "3min"; + # long timeout to prevent hydra failure on high load + systemd.services.munin-node.serviceConfig.TimeoutStartSec = "10min"; }; }; @@ -29,7 +36,10 @@ import ./make-test.nix ({ pkgs, ...} : { startAll; $one->waitForUnit("munin-node.service"); + # make sure the node is actually listening + $one->waitForOpenPort(4949); $one->succeed('systemctl start munin-cron'); + # wait for munin-cron output $one->waitForFile("/var/lib/munin/one/one-uptime-uptime-g.rrd"); $one->waitForFile("/var/www/munin/one/index.html"); ''; diff --git a/nixos/tests/netdata.nix b/nixos/tests/netdata.nix index eb45db6f04c3..9bd147968e4b 100644 --- a/nixos/tests/netdata.nix +++ b/nixos/tests/netdata.nix @@ -20,6 +20,9 @@ import ./make-test.nix ({ pkgs, ...} : { $netdata->waitForUnit("netdata.service"); + # wait for the service to listen before sending a request + $netdata->waitForOpenPort(19999); + # check if the netdata main page loads. $netdata->succeed("curl --fail http://localhost:19999/"); diff --git a/nixos/tests/networking.nix b/nixos/tests/networking.nix index cd5d537a3be7..ff088ad2621b 100644 --- a/nixos/tests/networking.nix +++ b/nixos/tests/networking.nix @@ -448,8 +448,8 @@ let testScript = '' my $targetList = <<'END'; - tap0: tap UNKNOWN_FLAGS:800 user 0 - tun0: tun UNKNOWN_FLAGS:800 user 0 + tap0: tap persist user 0 + tun0: tun persist user 0 END # Wait for networking to come up @@ -552,15 +552,15 @@ let testScript = '' my $targetIPv4Table = <<'END'; - 10.0.0.0/16 scope link mtu 1500 + 10.0.0.0/16 proto static scope link mtu 1500 192.168.1.0/24 proto kernel scope link src 192.168.1.2 - 192.168.2.0/24 via 192.168.1.1 + 192.168.2.0/24 via 192.168.1.1 proto static END my $targetIPv6Table = <<'END'; 2001:1470:fffd:2097::/64 proto kernel metric 256 pref medium - 2001:1470:fffd:2098::/64 via fdfd:b3f0::1 metric 1024 pref medium - fdfd:b3f0::/48 metric 1024 pref medium + 2001:1470:fffd:2098::/64 via fdfd:b3f0::1 proto static metric 1024 pref medium + fdfd:b3f0::/48 proto static metric 1024 pref medium END $machine->start; diff --git a/nixos/tests/virtualbox.nix b/nixos/tests/virtualbox.nix index 008dab8459c8..4207112cf16a 100644 --- a/nixos/tests/virtualbox.nix +++ b/nixos/tests/virtualbox.nix @@ -293,6 +293,11 @@ let "--hostonlyadapter2 vboxnet0" ]; + # The VirtualBox Oracle Extension Pack lets you use USB 3.0 (xHCI). + enableExtensionPackVMFlags = [ + "--usbxhci on" + ]; + dhcpScript = pkgs: '' ${pkgs.dhcp}/bin/dhclient \ -lf /run/dhcp.leases \ @@ -323,13 +328,17 @@ let headless.services.xserver.enable = false; }; - mkVBoxTest = name: testScript: makeTest { + vboxVMsWithExtpack = mapAttrs createVM { + testExtensionPack.vmFlags = enableExtensionPackVMFlags; + }; + + mkVBoxTest = useExtensionPack: vms: name: testScript: makeTest { name = "virtualbox-${name}"; machine = { lib, config, ... }: { imports = let mkVMConf = name: val: val.machine // { key = "${name}-config"; }; - vmConfigs = mapAttrsToList mkVMConf vboxVMs; + vmConfigs = mapAttrsToList mkVMConf vms; in [ ./common/user-account.nix ./common/x11.nix ] ++ vmConfigs; virtualisation.memorySize = 2048; virtualisation.virtualbox.host.enable = true; @@ -337,6 +346,8 @@ let users.users.alice.extraGroups = let inherit (config.virtualisation.virtualbox.host) enableHardening; in lib.mkIf enableHardening (lib.singleton "vboxusers"); + virtualisation.virtualbox.host.enableExtensionPack = useExtensionPack; + nixpkgs.config.allowUnfree = useExtensionPack; }; testScript = '' @@ -353,7 +364,7 @@ let return join("\n", grep { $_ !~ /^UUID:/ } split(/\n/, $_[0]))."\n"; } - ${concatStrings (mapAttrsToList (_: getAttr "testSubs") vboxVMs)} + ${concatStrings (mapAttrsToList (_: getAttr "testSubs") vms)} $machine->waitForX; @@ -363,11 +374,11 @@ let ''; meta = with pkgs.stdenv.lib.maintainers; { - maintainers = [ aszlig wkennington ]; + maintainers = [ aszlig wkennington cdepillabout ]; }; }; -in mapAttrs mkVBoxTest { +in mapAttrs (mkVBoxTest false vboxVMs) { simple-gui = '' createVM_simple; $machine->succeed(ru "VirtualBox &"); @@ -473,4 +484,22 @@ in mapAttrs mkVBoxTest { destroyVM_test1; destroyVM_test2; ''; +} // mapAttrs (mkVBoxTest true vboxVMsWithExtpack) { + enable-extension-pack = '' + createVM_testExtensionPack; + vbm("startvm testExtensionPack"); + waitForStartup_testExtensionPack; + $machine->screenshot("cli_started"); + waitForVMBoot_testExtensionPack; + $machine->screenshot("cli_booted"); + + $machine->nest("Checking for privilege escalation", sub { + $machine->fail("test -e '/root/VirtualBox VMs'"); + $machine->fail("test -e '/root/.config/VirtualBox'"); + $machine->succeed("test -e '/home/alice/VirtualBox VMs'"); + }); + + shutdownVM_testExtensionPack; + destroyVM_testExtensionPack; + ''; } diff --git a/nixos/tests/wordpress.nix b/nixos/tests/wordpress.nix index 2c0bbbfd7161..5003e25a7d5b 100644 --- a/nixos/tests/wordpress.nix +++ b/nixos/tests/wordpress.nix @@ -18,9 +18,6 @@ import ./make-test.nix ({ pkgs, ... }: enable = true; logPerVirtualHost = true; adminAddr="js@lastlog.de"; - extraModules = [ - { name = "php7"; path = "${pkgs.php}/modules/libphp7.so"; } - ]; virtualHosts = [ { @@ -30,7 +27,7 @@ import ./make-test.nix ({ pkgs, ... }: { serviceType = "wordpress"; dbPassword = "wordpress"; - wordpressUploads = "/data/uploads"; + dbHost = "127.0.0.1"; languages = [ "de_DE" "en_GB" ]; } ]; |