diff options
Diffstat (limited to 'nixos/modules')
43 files changed, 1264 insertions, 262 deletions
diff --git a/nixos/modules/config/i18n.nix b/nixos/modules/config/i18n.nix index 8182b8ae808..d3f24e280c7 100644 --- a/nixos/modules/config/i18n.nix +++ b/nixos/modules/config/i18n.nix @@ -76,7 +76,7 @@ in environment.systemPackages = [ glibcLocales ]; - environment.variables = + environment.sessionVariables = { LANG = config.i18n.defaultLocale; LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive"; }; diff --git a/nixos/modules/config/shells-environment.nix b/nixos/modules/config/shells-environment.nix index 9e212847e48..cc079cdc585 100644 --- a/nixos/modules/config/shells-environment.nix +++ b/nixos/modules/config/shells-environment.nix @@ -19,6 +19,7 @@ in default = {}; description = '' A set of environment variables used in the global environment. + These variables will be set on shell initialisation. The value of each variable can be either a string or a list of strings. The latter is concatenated, interspersed with colon characters. @@ -148,6 +149,12 @@ in system.build.binsh = pkgs.bashInteractive; + # Set session variables in the shell as well. This is usually + # unnecessary, but it allows changes to session variables to take + # effect without restarting the session (e.g. by opening a new + # terminal instead of logging out of X11). + environment.variables = config.environment.sessionVariables; + environment.etc."shells".text = '' ${concatStringsSep "\n" cfg.shells} diff --git a/nixos/modules/config/system-environment.nix b/nixos/modules/config/system-environment.nix new file mode 100644 index 00000000000..3ab32f00fd1 --- /dev/null +++ b/nixos/modules/config/system-environment.nix @@ -0,0 +1,56 @@ +# This module defines a system-wide environment that will be +# initialised by pam_env (that is, not only in shells). +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.environment; + +in + +{ + + options = { + + environment.sessionVariables = mkOption { + default = {}; + description = '' + A set of environment variables used in the global environment. + These variables will be set by PAM. + The value of each variable can be either a string or a list of + strings. The latter is concatenated, interspersed with colon + characters. + ''; + type = types.attrsOf (mkOptionType { + name = "a string or a list of strings"; + merge = loc: defs: + let + defs' = filterOverrides defs; + res = (head defs').value; + in + if isList res then concatLists (getValues defs') + else if lessThan 1 (length defs') then + throw "The option `${showOption loc}' is defined multiple times, in ${showFiles (getFiles defs)}." + else if !isString res then + throw "The option `${showOption loc}' does not have a string value, in ${showFiles (getFiles defs)}." + else res; + }); + apply = mapAttrs (n: v: if isList v then concatStringsSep ":" v else v); + }; + + }; + + config = { + + system.build.pamEnvironment = pkgs.writeText "pam-environment" + '' + ${concatStringsSep "\n" ( + (mapAttrsToList (n: v: ''${n}="${concatStringsSep ":" v}"'') + (zipAttrsWith (const concatLists) ([ (mapAttrs (n: v: [ v ]) cfg.sessionVariables) ]))))} + ''; + + }; + +} diff --git a/nixos/modules/config/timezone.nix b/nixos/modules/config/timezone.nix index 65703d8bb08..c8592284077 100644 --- a/nixos/modules/config/timezone.nix +++ b/nixos/modules/config/timezone.nix @@ -30,7 +30,7 @@ in config = { - environment.variables.TZDIR = "/etc/zoneinfo"; + environment.sessionVariables.TZDIR = "/etc/zoneinfo"; systemd.globalEnvironment.TZDIR = tzdir; diff --git a/nixos/modules/config/zram.nix b/nixos/modules/config/zram.nix new file mode 100644 index 00000000000..22b74847f87 --- /dev/null +++ b/nixos/modules/config/zram.nix @@ -0,0 +1,138 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.zramSwap; + + devices = map (nr: "zram${toString nr}") (range 0 (cfg.numDevices - 1)); + + modprobe = "${config.system.sbin.modprobe}/sbin/modprobe"; + +in + +{ + + ###### interface + + options = { + + zramSwap = { + + enable = mkOption { + default = false; + type = types.bool; + description = '' + Enable in-memory compressed swap space provided by the zram kernel + module. It is recommended to enable only for kernel 3.14 or higher. + ''; + }; + + numDevices = mkOption { + default = 4; + type = types.int; + description = '' + Number of zram swap devices to create. It should be equal to the + number of CPU cores your system has. + ''; + }; + + memoryPercent = mkOption { + default = 50; + type = types.int; + description = '' + Maximum amount of memory that can be used by the zram swap devices + (as a percentage of your total memory). Defaults to 1/2 of your total + RAM. + ''; + }; + + priority = mkOption { + default = 5; + type = types.int; + description = '' + Priority of the zram swap devices. It should be a number higher than + the priority of your disk-based swap devices (so that the system will + fill the zram swap devices before falling back to disk swap). + ''; + }; + + }; + + }; + + config = mkIf cfg.enable { + + system.requiredKernelConfig = with config.lib.kernelConfig; [ + (isModule "ZRAM") + ]; + + # Disabling this for the moment, as it would create and mkswap devices twice, + # once in stage 2 boot, and again when the zram-reloader service starts. + # boot.kernelModules = [ "zram" ]; + + boot.extraModprobeConfig = '' + options zram num_devices=${toString cfg.numDevices} + ''; + + services.udev.extraRules = '' + KERNEL=="zram[0-9]*", ENV{SYSTEMD_WANTS}="zram-init-%k.service", TAG+="systemd" + ''; + + systemd.services = + let + createZramInitService = dev: + nameValuePair "zram-init-${dev}" { + description = "Init swap on zram-based device ${dev}"; + bindsTo = [ "dev-${dev}.swap" ]; + after = [ "dev-${dev}.device" "zram-reloader.service" ]; + requires = [ "dev-${dev}.device" "zram-reloader.service" ]; + before = [ "dev-${dev}.swap" ]; + requiredBy = [ "dev-${dev}.swap" ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStop = "${pkgs.stdenv.shell} -c 'echo 1 > /sys/class/block/${dev}/reset'"; + }; + script = '' + set -u + set -o pipefail + + PATH=${pkgs.procps}/bin:${pkgs.gnugrep}/bin:${pkgs.gnused}/bin + + # Calculate memory to use for zram + totalmem=$(free | grep -e "^Mem:" | sed -e 's/^Mem: *//' -e 's/ *.*//') + mem=$(((totalmem * ${toString cfg.memoryPercent} / 100 / ${toString cfg.numDevices}) * 1024)) + + echo $mem > /sys/class/block/${dev}/disksize + ${pkgs.utillinux}/sbin/mkswap /dev/${dev} + ''; + restartIfChanged = false; + }; + in listToAttrs ((map createZramInitService devices) ++ [(nameValuePair "zram-reloader" + { + description = "Reload zram kernel module when number of devices changes"; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStartPre = "${modprobe} -r zram"; + ExecStart = "${modprobe} zram"; + ExecStop = "${modprobe} -r zram"; + }; + restartTriggers = [ cfg.numDevices ]; + restartIfChanged = true; + })]); + + swapDevices = + let + useZramSwap = dev: + { + device = "/dev/${dev}"; + priority = cfg.priority; + }; + in map useZramSwap devices; + + }; + +} diff --git a/nixos/modules/hardware/opengl.nix b/nixos/modules/hardware/opengl.nix index 096f7e2c097..ab5c309bd42 100644 --- a/nixos/modules/hardware/opengl.nix +++ b/nixos/modules/hardware/opengl.nix @@ -16,7 +16,7 @@ let [ p.mesa_drivers p.mesa_noglu # mainly for libGL (if cfg.s3tcSupport then p.libtxc_dxtn else p.libtxc_dxtn_s2tc) - p.udev + p.udev ]; }; @@ -101,7 +101,7 @@ in ''} ''; - environment.variables.LD_LIBRARY_PATH = + environment.sessionVariables.LD_LIBRARY_PATH = [ "/run/opengl-driver/lib" "/run/opengl-driver-32/lib" ]; # FIXME: move this into card-specific modules. diff --git a/nixos/modules/installer/cd-dvd/installation-cd-base.nix b/nixos/modules/installer/cd-dvd/installation-cd-base.nix index eb7c4026857..4d87c20559d 100644 --- a/nixos/modules/installer/cd-dvd/installation-cd-base.nix +++ b/nixos/modules/installer/cd-dvd/installation-cd-base.nix @@ -19,7 +19,7 @@ with lib; # ISO naming. isoImage.isoName = "${config.isoImage.isoBaseName}-${config.system.nixosVersion}-${pkgs.stdenv.system}.iso"; - isoImage.volumeID = substring 0 11 "NIXOS_${config.system.nixosVersion}"; + isoImage.volumeID = substring 0 11 "NIXOS_ISO"; # Make the installer more likely to succeed in low memory # environments. The kernel's overcommit heustistics bite us diff --git a/nixos/modules/installer/cd-dvd/installation-cd-new-kernel.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-new-kernel.nix index 93bcbf00b25..506b9292b01 100644 --- a/nixos/modules/installer/cd-dvd/installation-cd-new-kernel.nix +++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-new-kernel.nix @@ -3,6 +3,5 @@ { imports = [ ./installation-cd-graphical.nix ]; - boot.kernelPackages = pkgs.linuxPackages_3_10; - boot.vesa = false; + boot.kernelPackages = pkgs.linuxPackages_latest; } diff --git a/nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix b/nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix index 38d02ffd162..4363c8e6c93 100644 --- a/nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix +++ b/nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix @@ -3,6 +3,5 @@ { imports = [ ./installation-cd-minimal.nix ]; - boot.kernelPackages = pkgs.linuxPackages_3_10; - boot.vesa = false; + boot.kernelPackages = pkgs.linuxPackages_latest; } diff --git a/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix b/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix index 5e77b701ff5..4372d196261 100644 --- a/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix +++ b/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix @@ -6,4 +6,4 @@ let nodes = import networkExpr; in with import ../../../../lib/testing.nix { inherit system; }; -(complete { inherit nodes; testScript = ""; }).driver +(makeTest { inherit nodes; testScript = ""; }).driver diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl index ab058efc709..66a8152a3a6 100644 --- a/nixos/modules/installer/tools/nixos-generate-config.pl +++ b/nixos/modules/installer/tools/nixos-generate-config.pl @@ -466,7 +466,7 @@ $bootLoaderConfig # }; # List packages installed in system profile. To search by name, run: - # $ nix-env -qaP | grep wget + # \$ nix-env -qaP | grep wget # environment.systemPackages = with pkgs; [ # wget # ]; diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index db50a010e7d..f1028a479df 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -133,6 +133,7 @@ spiped = 123; teamspeak = 124; influxdb = 125; + nsd = 126; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -240,6 +241,7 @@ spiped = 123; teamspeak = 124; influxdb = 125; + nsd = 126; # When adding a gid, make sure it doesn't match an existing uid. And don't use gids above 399! diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 7fa705a5ae3..13f2656c287 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -14,12 +14,14 @@ ./config/power-management.nix ./config/pulseaudio.nix ./config/shells-environment.nix + ./config/system-environment.nix ./config/swap.nix ./config/sysctl.nix ./config/system-path.nix ./config/timezone.nix ./config/unix-odbc-drivers.nix ./config/users-groups.nix + ./config/zram.nix ./hardware/all-firmware.nix ./hardware/cpu/intel-microcode.nix ./hardware/cpu/amd-microcode.nix @@ -99,7 +101,7 @@ ./services/databases/virtuoso.nix ./services/databases/monetdb.nix ./services/databases/influxdb.nix - ./services/desktops/accountservice.nix + ./services/desktops/accountsservice.nix ./services/desktops/geoclue2.nix ./services/desktops/gnome3/at-spi2-core.nix ./services/desktops/gnome3/evolution-data-server.nix @@ -158,7 +160,7 @@ ./services/monitoring/graphite.nix ./services/monitoring/monit.nix ./services/monitoring/munin.nix - ./services/monitoring/nagios/default.nix + ./services/monitoring/nagios.nix ./services/monitoring/smartd.nix ./services/monitoring/statsd.nix ./services/monitoring/systemhealth.nix @@ -205,6 +207,7 @@ ./services/networking/networkmanager.nix ./services/networking/ngircd.nix ./services/networking/notbit.nix + ./services/networking/nsd.nix ./services/networking/ntopng.nix ./services/networking/ntpd.nix ./services/networking/oidentd.nix @@ -323,6 +326,7 @@ ./tasks/network-interfaces.nix ./tasks/scsi-link-power-management.nix ./tasks/swraid.nix + ./tasks/trackpoint.nix ./testing/service-runner.nix ./virtualisation/container-config.nix ./virtualisation/containers.nix diff --git a/nixos/modules/programs/environment.nix b/nixos/modules/programs/environment.nix index aa9aec07834..2ff1db48757 100644 --- a/nixos/modules/programs/environment.nix +++ b/nixos/modules/programs/environment.nix @@ -19,13 +19,16 @@ in environment.variables = { LOCATE_PATH = "/var/cache/locatedb"; NIXPKGS_CONFIG = "/etc/nix/nixpkgs-config.nix"; - NIX_PATH = + PAGER = "less -R"; + EDITOR = "nano"; + }; + + environment.sessionVariables = + { NIX_PATH = [ "/nix/var/nix/profiles/per-user/root/channels/nixos" "nixpkgs=/etc/nixos/nixpkgs" "nixos-config=/etc/nixos/configuration.nix" ]; - PAGER = "less -R"; - EDITOR = "nano"; }; environment.profiles = diff --git a/nixos/modules/programs/shadow.nix b/nixos/modules/programs/shadow.nix index 27a18c726a3..5fcd2133a7e 100644 --- a/nixos/modules/programs/shadow.nix +++ b/nixos/modules/programs/shadow.nix @@ -48,6 +48,7 @@ in Rather, it should be the path of a symlink that points to the actual shell in the Nix store. ''; + example = "/run/current-system/sw/bin/zsh"; type = types.path; }; diff --git a/nixos/modules/security/ca.nix b/nixos/modules/security/ca.nix index f159e359f96..dd4b0c529e5 100644 --- a/nixos/modules/security/ca.nix +++ b/nixos/modules/security/ca.nix @@ -12,9 +12,11 @@ with lib; } ]; - environment.variables.OPENSSL_X509_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt"; - environment.variables.CURL_CA_BUNDLE = "/etc/ssl/certs/ca-bundle.crt"; - environment.variables.GIT_SSL_CAINFO = "/etc/ssl/certs/ca-bundle.crt"; + environment.sessionVariables = + { OPENSSL_X509_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt"; + CURL_CA_BUNDLE = "/etc/ssl/certs/ca-bundle.crt"; + GIT_SSL_CAINFO = "/etc/ssl/certs/ca-bundle.crt"; + }; }; diff --git a/nixos/modules/security/grsecurity.nix b/nixos/modules/security/grsecurity.nix index f4af04247fe..3bd58218c99 100644 --- a/nixos/modules/security/grsecurity.nix +++ b/nixos/modules/security/grsecurity.nix @@ -6,12 +6,10 @@ let cfg = config.security.grsecurity; customGrsecPkg = - (import ../../../pkgs/build-support/grsecurity - { - inherit lib pkgs; - grsecOptions = cfg; - } - ).grsecPackage; + (import ../../../pkgs/build-support/grsecurity { + grsecOptions = cfg; + inherit pkgs lib; + }).grsecPackage; in { options = { @@ -36,14 +34,6 @@ in ''; }; - vserver = mkOption { - type = types.bool; - default = false; - description = '' - Enable the stable grsecurity/vserver patches, based on Linux 3.2. - ''; - }; - testing = mkOption { type = types.bool; default = false; @@ -246,9 +236,6 @@ in both. ''; } - { assertion = (cfg.testing -> !cfg.vserver); - message = "The vserver patches are only supported in the stable kernel."; - } { assertion = (cfg.config.restrictProc -> !cfg.config.restrictProcWithGroup) || (cfg.config.restrictProcWithGroup -> !cfg.config.restrictProc); message = "You cannot enable both restrictProc and restrictProcWithGroup"; diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix index 6a5eb4c720f..02340fd78e8 100644 --- a/nixos/modules/security/pam.nix +++ b/nixos/modules/security/pam.nix @@ -186,6 +186,7 @@ let "password optional ${pkgs.samba}/lib/security/pam_smbpass.so nullok use_authtok try_first_pass"} # Session management. + session required pam_env.so envfile=${config.system.build.pamEnvironment} session required pam_unix.so ${optionalString cfg.setLoginUid "session required pam_loginuid.so"} diff --git a/nixos/modules/security/sudo.nix b/nixos/modules/security/sudo.nix index 6cfeac0d7dc..cbd1628caae 100644 --- a/nixos/modules/security/sudo.nix +++ b/nixos/modules/security/sudo.nix @@ -58,9 +58,6 @@ in # Don't edit this file. Set the NixOS option ‘security.sudo.configFile’ instead. # Environment variables to keep for root and %wheel. - Defaults:root,%wheel env_keep+=LOCALE_ARCHIVE - Defaults:root,%wheel env_keep+=NIX_CONF_DIR - Defaults:root,%wheel env_keep+=NIX_PATH Defaults:root,%wheel env_keep+=TERMINFO_DIRS Defaults:root,%wheel env_keep+=TERMINFO @@ -81,10 +78,13 @@ in security.pam.services.sudo = { sshAgentAuth = true; }; environment.etc = singleton - { source = pkgs.writeText "sudoers-in" cfg.configFile; + { source = + pkgs.runCommand "sudoers" + {src = pkgs.writeText "sudoers-in" cfg.configFile; } # Make sure that the sudoers file is syntactically valid. # (currently disabled - NIXOS-66) - #"${pkgs.sudo}/sbin/visudo -f $src -c && cp $src $out"; + "${pkgs.sudo}/sbin/visudo -f $src -c && + cp $src $out"; target = "sudoers"; mode = "0440"; }; diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix index 1b50f06bf30..53542e34b14 100644 --- a/nixos/modules/services/audio/mpd.nix +++ b/nixos/modules/services/audio/mpd.nix @@ -52,7 +52,7 @@ in { }; dataDir = mkOption { - default = "/var/lib/mpd/"; + default = "/var/lib/mpd"; description = '' The directory where MPD stores its state, tag cache, playlists etc. diff --git a/nixos/modules/services/desktops/accountservice.nix b/nixos/modules/services/desktops/accountsservice.nix index 386dfe98bd2..c28c2729576 100644 --- a/nixos/modules/services/desktops/accountservice.nix +++ b/nixos/modules/services/desktops/accountsservice.nix @@ -30,11 +30,11 @@ with lib; config = mkIf config.services.accounts-daemon.enable { - environment.systemPackages = [ pkgs.accountservice ]; + environment.systemPackages = [ pkgs.accountsservice ]; - services.dbus.packages = [ pkgs.accountservice ]; + services.dbus.packages = [ pkgs.accountsservice ]; - systemd.packages = [ pkgs.accountservice ]; + systemd.packages = [ pkgs.accountsservice ]; }; } diff --git a/nixos/modules/services/hardware/sane.nix b/nixos/modules/services/hardware/sane.nix index f7b25c18787..3bf765c6f99 100644 --- a/nixos/modules/services/hardware/sane.nix +++ b/nixos/modules/services/hardware/sane.nix @@ -34,6 +34,12 @@ in description = "Packages providing extra SANE backends to enable."; }; + hardware.sane.configDir = mkOption { + type = types.string; + default = "${saneConfig}/etc/sane.d"; + description = "The value of SANE_CONFIG_DIR."; + }; + }; @@ -42,8 +48,8 @@ in config = mkIf config.hardware.sane.enable { environment.systemPackages = backends; - environment.variables = { - SANE_CONFIG_DIR = mkDefault "${saneConfig}/etc/sane.d"; + environment.sessionVariables = { + SANE_CONFIG_DIR = config.hardware.sane.configDir; LD_LIBRARY_PATH = [ "${saneConfig}/lib/sane" ]; }; services.udev.packages = backends; diff --git a/nixos/modules/services/misc/disnix.nix b/nixos/modules/services/misc/disnix.nix index 94d0caaa76b..219c7ed9587 100644 --- a/nixos/modules/services/misc/disnix.nix +++ b/nixos/modules/services/misc/disnix.nix @@ -125,13 +125,14 @@ in after = [ "dbus.service" ] ++ optional config.services.httpd.enable "httpd.service" ++ optional config.services.mysql.enable "mysql.service" + ++ optional config.services.postgresql.enable "postgresql.service" ++ optional config.services.tomcat.enable "tomcat.service" ++ optional config.services.svnserve.enable "svnserve.service" ++ optional config.services.mongodb.enable "mongodb.service"; restartIfChanged = false; - path = [ pkgs.nix pkgs.disnix pkgs.dysnomia ]; + path = [ pkgs.nix pkgs.disnix dysnomia ]; environment = { HOME = "/root"; diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix index 4bfd6268234..1ebd3c3643d 100644 --- a/nixos/modules/services/misc/nix-daemon.nix +++ b/nixos/modules/services/misc/nix-daemon.nix @@ -318,7 +318,7 @@ in }; # Set up the environment variables for running Nix. - environment.variables = cfg.envVars; + environment.sessionVariables = cfg.envVars; environment.extraInit = '' diff --git a/nixos/modules/services/misc/synergy.nix b/nixos/modules/services/misc/synergy.nix index ec8ff426f0a..5338b25715c 100644 --- a/nixos/modules/services/misc/synergy.nix +++ b/nixos/modules/services/misc/synergy.nix @@ -83,7 +83,8 @@ in config = { - systemd.services."synergy-client" = mkIf cfgC.enable { + systemd.services."synergy-client" = { + enable = cfgC.enable; after = [ "network.target" ]; description = "Synergy client"; wantedBy = optional cfgC.autoStart "multi-user.target"; @@ -91,7 +92,8 @@ in serviceConfig.ExecStart = ''${pkgs.synergy}/bin/synergyc -f ${optionalString (cfgC.screenName != "") "-n ${cfgC.screenName}"} ${cfgC.serverAddress}''; }; - systemd.services."synergy-server" = mkIf cfgS.enable { + systemd.services."synergy-server" = { + enable = cfgS.enable; after = [ "network.target" ]; description = "Synergy server"; wantedBy = optional cfgS.autoStart "multi-user.target"; diff --git a/nixos/modules/services/monitoring/graphite.nix b/nixos/modules/services/monitoring/graphite.nix index d543d15b34e..dbfe0ee182a 100644 --- a/nixos/modules/services/monitoring/graphite.nix +++ b/nixos/modules/services/monitoring/graphite.nix @@ -12,7 +12,7 @@ let name = "graphite-config"; paths = lists.filter (el: el != null) [ (writeTextOrNull "carbon.conf" cfg.carbon.config) - (writeTextOrNull "storage-agregation.conf" cfg.carbon.storageAggregation) + (writeTextOrNull "storage-aggregation.conf" cfg.carbon.storageAggregation) (writeTextOrNull "storage-schemas.conf" cfg.carbon.storageSchemas) (writeTextOrNull "blacklist.conf" cfg.carbon.blacklist) (writeTextOrNull "whitelist.conf" cfg.carbon.whitelist) @@ -47,19 +47,19 @@ in { web = { enable = mkOption { - description = "Whether to enable graphite web frontend"; + description = "Whether to enable graphite web frontend."; default = false; type = types.uniq types.bool; }; host = mkOption { - description = "Graphite web frontend listen address"; + description = "Graphite web frontend listen address."; default = "127.0.0.1"; type = types.str; }; port = mkOption { - description = "Graphite web frontend port"; + description = "Graphite web frontend port."; default = 8080; type = types.int; }; @@ -67,7 +67,7 @@ in { carbon = { config = mkOption { - description = "Content of carbon configuration file"; + description = "Content of carbon configuration file."; default = '' [cache] # Listen on localhost by default for security reasons @@ -83,13 +83,13 @@ in { }; enableCache = mkOption { - description = "Whether to enable carbon cache, the graphite storage daemon"; + description = "Whether to enable carbon cache, the graphite storage daemon."; default = false; type = types.uniq types.bool; }; storageAggregation = mkOption { - description = "Defines how to aggregate data to lower-precision retentions"; + description = "Defines how to aggregate data to lower-precision retentions."; default = null; type = types.uniq (types.nullOr types.string); example = '' @@ -101,7 +101,7 @@ in { }; storageSchemas = mkOption { - description = "Defines retention rates for storing metrics"; + description = "Defines retention rates for storing metrics."; default = ""; type = types.uniq (types.nullOr types.string); example = '' @@ -112,21 +112,24 @@ in { }; blacklist = mkOption { - description = "Any metrics received which match one of the experssions will be dropped"; + description = "Any metrics received which match one of the experssions will be dropped."; default = null; type = types.uniq (types.nullOr types.string); example = "^some\.noisy\.metric\.prefix\..*"; }; whitelist = mkOption { - description = "Only metrics received which match one of the experssions will be persisted"; + description = "Only metrics received which match one of the experssions will be persisted."; default = null; type = types.uniq (types.nullOr types.string); example = ".*"; }; rewriteRules = mkOption { - description = "Regular expression patterns that can be used to rewrite metric names in a search and replace fashion"; + description = '' + Regular expression patterns that can be used to rewrite metric names + in a search and replace fashion. + ''; default = null; type = types.uniq (types.nullOr types.string); example = '' @@ -137,7 +140,7 @@ in { }; enableRelay = mkOption { - description = "Whether to enable carbon relay, the carbon replication and sharding service"; + description = "Whether to enable carbon relay, the carbon replication and sharding service."; default = false; type = types.uniq types.bool; }; @@ -154,13 +157,13 @@ in { }; enableAggregator = mkOption { - description = "Whether to enable carbon agregator, the carbon buffering service"; + description = "Whether to enable carbon agregator, the carbon buffering service."; default = false; type = types.uniq types.bool; }; aggregationRules = mkOption { - description = "Defines if and how received metrics will be agregated"; + description = "Defines if and how received metrics will be agregated."; default = null; type = types.uniq (types.nullOr types.string); example = '' @@ -188,10 +191,7 @@ in { }; restartTriggers = [ pkgs.pythonPackages.carbon - cfg.carbon.config - cfg.carbon.storageAggregation - cfg.carbon.storageSchemas - cfg.carbon.rewriteRules + configDir ]; preStart = '' mkdir -p ${cfg.dataDir}/whisper @@ -212,7 +212,8 @@ in { Group = "graphite"; }; restartTriggers = [ - pkgs.pythonPackages.carbon cfg.carbon.config cfg.carbon.aggregationRules + pkgs.pythonPackages.carbon + configDir ]; }; @@ -228,7 +229,8 @@ in { Group = "graphite"; }; restartTriggers = [ - pkgs.pythonPackages.carbon cfg.carbon.config cfg.carbon.relayRules + pkgs.pythonPackages.carbon + configDir ]; }; @@ -271,7 +273,6 @@ in { ''; restartTriggers = [ pkgs.python27Packages.graphite_web - pkgs.python27Packages.waitress ]; }; diff --git a/nixos/modules/services/monitoring/nagios/default.nix b/nixos/modules/services/monitoring/nagios.nix index 2eeddf78250..97d153153a5 100644 --- a/nixos/modules/services/monitoring/nagios/default.nix +++ b/nixos/modules/services/monitoring/nagios.nix @@ -4,21 +4,12 @@ with lib; let - cfg = config.services.nagios; - nagiosUser = "nagios"; - nagiosGroup = "nogroup"; - nagiosState = "/var/lib/nagios"; nagiosLogDir = "/var/log/nagios"; - nagiosObjectDefs = - [ ./timeperiods.cfg - ./host-templates.cfg - ./service-templates.cfg - ./commands.cfg - ] ++ cfg.objectDefs; + nagiosObjectDefs = cfg.objectDefs; nagiosObjectDefsDir = pkgs.runCommand "nagios-objects" {inherit nagiosObjectDefs;} "ensureDir $out; ln -s $nagiosObjectDefs $out/"; @@ -30,19 +21,20 @@ let log_archive_path=${nagiosLogDir}/archive status_file=${nagiosState}/status.dat object_cache_file=${nagiosState}/objects.cache - comment_file=${nagiosState}/comment.dat - downtime_file=${nagiosState}/downtime.dat temp_file=${nagiosState}/nagios.tmp lock_file=/var/run/nagios.lock # Not used I think. state_retention_file=${nagiosState}/retention.dat + query_socket=${nagiosState}/nagios.qh + check_result_path=${nagiosState} + command_file=${nagiosState}/nagios.cmd # Configuration files. #resource_file=resource.cfg cfg_dir=${nagiosObjectDefsDir} # Uid/gid that the daemon runs under. - nagios_user=${nagiosUser} - nagios_group=${nagiosGroup} + nagios_user=nagios + nagios_group=nogroup # Misc. options. illegal_macro_output_chars=`~$&|'"<> @@ -53,26 +45,24 @@ let # authentication. nagiosCGICfgFile = pkgs.writeText "nagios.cgi.conf" '' - main_config_file=${nagiosCfgFile} + main_config_file=${cfg.mainConfigFile} use_authentication=0 - url_html_path=/nagios + url_html_path=${cfg.urlPath} ''; - urlPath = cfg.urlPath; - extraHttpdConfig = '' - ScriptAlias ${urlPath}/cgi-bin ${pkgs.nagios}/sbin + ScriptAlias ${cfg.urlPath}/cgi-bin ${pkgs.nagios}/sbin <Directory "${pkgs.nagios}/sbin"> Options ExecCGI AllowOverride None Order allow,deny Allow from all - SetEnv NAGIOS_CGI_CONFIG ${nagiosCGICfgFile} + SetEnv NAGIOS_CGI_CONFIG ${cfg.cgiConfigFile} </Directory> - Alias ${urlPath} ${pkgs.nagios}/share + Alias ${cfg.urlPath} ${pkgs.nagios}/share <Directory "${pkgs.nagios}/share"> Options None @@ -83,14 +73,9 @@ let ''; in - { - ###### interface - options = { - services.nagios = { - enable = mkOption { default = false; description = " @@ -116,6 +101,21 @@ in "; }; + mainConfigFile = mkOption { + default = nagiosCfgFile; + description = " + Derivation for the main configuration file of Nagios. + "; + }; + + cgiConfigFile = mkOption { + default = nagiosCGICfgFile; + description = " + Derivation for the configuration file of Nagios CGI scripts + that can be used in web servers for running the Nagios web interface. + "; + }; + enableWebInterface = mkOption { default = false; description = " @@ -132,55 +132,53 @@ in <literal>http://<replaceable>server</replaceable>/<replaceable>urlPath</replaceable></literal>. "; }; - }; - }; - ###### implementation - config = mkIf cfg.enable { - - users.extraUsers = singleton - { name = nagiosUser; - uid = config.ids.uids.nagios; - description = "Nagios monitoring daemon"; - home = nagiosState; - }; + users.extraUsers.nagios = { + description = "Nagios user "; + uid = config.ids.uids.nagios; + home = nagiosState; + createHome = true; + }; # This isn't needed, it's just so that the user can type "nagiostats # -c /etc/nagios.cfg". - environment.etc = singleton - { source = nagiosCfgFile; + environment.etc = [ + { source = cfg.mainConfigFile; target = "nagios.cfg"; - }; + } + ]; environment.systemPackages = [ pkgs.nagios ]; - - jobs.nagios = - { description = "Nagios monitoring daemon"; - - startOn = "started network-interfaces"; - stopOn = "stopping network-interfaces"; - - preStart = - '' - mkdir -m 0755 -p ${nagiosState} ${nagiosLogDir} - chown ${nagiosUser} ${nagiosState} ${nagiosLogDir} - ''; - - script = - '' - for i in ${toString config.services.nagios.plugins}; do - export PATH=$i/bin:$i/sbin:$i/libexec:$PATH - done - exec ${pkgs.nagios}/bin/nagios ${nagiosCfgFile} - ''; + systemd.services.nagios = { + description = "Nagios monitoring daemon"; + path = [ pkgs.nagios ]; + wantedBy = [ "multi-user.target" ]; + after = [ "network-interfaces.target" ]; + + serviceConfig = { + User = "nagios"; + Restart = "always"; + RestartSec = 2; + PermissionsStartOnly = true; }; - services.httpd.extraConfig = optionalString cfg.enableWebInterface extraHttpdConfig; + preStart = '' + mkdir -m 0755 -p ${nagiosState} ${nagiosLogDir} + chown nagios ${nagiosState} ${nagiosLogDir} + ''; + + script = '' + for i in ${toString cfg.plugins}; do + export PATH=$i/bin:$i/sbin:$i/libexec:$PATH + done + exec ${pkgs.nagios}/bin/nagios ${cfg.mainConfigFile} + ''; + }; + services.httpd.extraConfig = optionalString cfg.enableWebInterface extraHttpdConfig; }; - } diff --git a/nixos/modules/services/monitoring/nagios/commands.cfg b/nixos/modules/services/monitoring/nagios/commands.cfg deleted file mode 100644 index 6efdefcd37d..00000000000 --- a/nixos/modules/services/monitoring/nagios/commands.cfg +++ /dev/null @@ -1,34 +0,0 @@ -define command { - command_name host-notify-by-email - command_line printf "%b" "To: $CONTACTEMAIL$\nSubject: [Nagios] Host $HOSTSTATE$ alert for $HOSTNAME$\n\n***** Nagios *****\n\nNotification Type: $NOTIFICATIONTYPE$\nHost: $HOSTNAME$\nState: $HOSTSTATE$\nAddress: $HOSTADDRESS$\nInfo: $HOSTOUTPUT$\n\nDate/Time: $LONGDATETIME$\n" | sendmail $CONTACTEMAIL$ -} - - -define command { - command_name notify-by-email - command_line printf "%b" "To: $CONTACTEMAIL$\nSubject: [Nagios] $NOTIFICATIONTYPE$ alert - $HOSTALIAS$/$SERVICEDESC$ is $SERVICESTATE$\n\n***** Nagios *****\n\nNotification Type: $NOTIFICATIONTYPE$\nService: $SERVICEDESC$\nHost: $HOSTALIAS$\nAddress: $HOSTADDRESS$\nState: $SERVICESTATE$\n\nDate/Time: $LONGDATETIME$\n\nAdditional Info:\n\n$SERVICEOUTPUT$" | sendmail $CONTACTEMAIL$ -} - - -define command { - command_name dummy-ok - command_line true -} - - -define command { - command_name check-host-alive - command_line check_ping -H $HOSTADDRESS$ -w 3000.0,80% -c 5000.0,100% -p 1 -} - - -define command { - command_name check_local_disk - command_line check_disk -w $ARG1$ -c $ARG2$ -p $ARG3$ -} - - -define command { - command_name check_ssh - command_line check_ssh $HOSTADDRESS$ -} diff --git a/nixos/modules/services/monitoring/nagios/host-templates.cfg b/nixos/modules/services/monitoring/nagios/host-templates.cfg deleted file mode 100644 index 3a4c269e257..00000000000 --- a/nixos/modules/services/monitoring/nagios/host-templates.cfg +++ /dev/null @@ -1,27 +0,0 @@ -define host { - name generic-host - notifications_enabled 1 - event_handler_enabled 1 - flap_detection_enabled 1 - failure_prediction_enabled 1 - process_perf_data 1 - retain_status_information 1 - retain_nonstatus_information 1 - notification_period 24x7 - register 0 -} - - -define host { - name generic-server - use generic-host - check_period 24x7 - max_check_attempts 10 - check_command check-host-alive - notification_period 24x7 - notification_interval 120 - notification_options d,u,r - contact_groups admins - register 0 - #check_interval 1 -} diff --git a/nixos/modules/services/monitoring/nagios/service-templates.cfg b/nixos/modules/services/monitoring/nagios/service-templates.cfg deleted file mode 100644 index e729ea77675..00000000000 --- a/nixos/modules/services/monitoring/nagios/service-templates.cfg +++ /dev/null @@ -1,32 +0,0 @@ -define service { - name generic-service - active_checks_enabled 1 - passive_checks_enabled 1 - parallelize_check 1 - obsess_over_service 1 - check_freshness 0 - notifications_enabled 1 - event_handler_enabled 1 - flap_detection_enabled 1 - failure_prediction_enabled 1 - process_perf_data 1 - retain_status_information 1 - retain_nonstatus_information 1 - is_volatile 0 - register 0 -} - - -define service { - name local-service - use generic-service - check_period 24x7 - max_check_attempts 4 - normal_check_interval 5 - retry_check_interval 1 - contact_groups admins - notification_options w,u,c,r - notification_interval 0 # notify only once - notification_period 24x7 - register 0 -} diff --git a/nixos/modules/services/monitoring/nagios/timeperiods.cfg b/nixos/modules/services/monitoring/nagios/timeperiods.cfg deleted file mode 100644 index 2669be54d3d..00000000000 --- a/nixos/modules/services/monitoring/nagios/timeperiods.cfg +++ /dev/null @@ -1,11 +0,0 @@ -define timeperiod { - timeperiod_name 24x7 - alias 24 Hours A Day, 7 Days A Week - sunday 00:00-24:00 - monday 00:00-24:00 - tuesday 00:00-24:00 - wednesday 00:00-24:00 - thursday 00:00-24:00 - friday 00:00-24:00 - saturday 00:00-24:00 -} diff --git a/nixos/modules/services/monitoring/statsd.nix b/nixos/modules/services/monitoring/statsd.nix index 05950639c1e..74f3deb4c29 100644 --- a/nixos/modules/services/monitoring/statsd.nix +++ b/nixos/modules/services/monitoring/statsd.nix @@ -69,8 +69,8 @@ in }; graphitePort = mkOption { - description = "Port of Graphite server"; - default = config.services.graphite.web.port; + description = "Port of Graphite server (i.e. carbon-cache)."; + default = 2003; type = types.uniq types.int; }; diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix index 51a4d193d50..4218b965cd9 100644 --- a/nixos/modules/services/network-filesystems/samba.nix +++ b/nixos/modules/services/network-filesystems/samba.nix @@ -59,7 +59,7 @@ let daemonService = appName: args: { description = "Samba Service Daemon ${appName}"; - wantedBy = [ "samba.target" ]; + requiredBy = [ "samba.target" ]; partOf = [ "samba.target" ]; environment = { diff --git a/nixos/modules/services/networking/nsd.nix b/nixos/modules/services/networking/nsd.nix new file mode 100644 index 00000000000..adfee1caec5 --- /dev/null +++ b/nixos/modules/services/networking/nsd.nix @@ -0,0 +1,751 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + cfg = config.services.nsd; + + username = "nsd"; + stateDir = "/var/lib/nsd"; + pidFile = stateDir + "/var/nsd.pid"; + + zoneFiles = pkgs.stdenv.mkDerivation { + preferLocalBuild = true; + name = "nsd-env"; + buildCommand = concatStringsSep "\n" + [ "mkdir -p $out" + (concatStrings (mapAttrsToList (zoneName: zoneOptions: '' + cat > "$out/${zoneName}" <<_EOF_ + ${zoneOptions.data} + _EOF_ + '') zoneConfigs)) + ]; + }; + + configFile = pkgs.writeText "nsd.conf" '' + server: + username: ${username} + chroot: "${stateDir}" + + # The directory for zonefile: files. The daemon chdirs here. + zonesdir: "${stateDir}" + + # the list of dynamically added zones. + zonelistfile: "${stateDir}/var/zone.list" + database: "${stateDir}/var/nsd.db" + logfile: "${stateDir}/var/nsd.log" + pidfile: "${pidFile}" + xfrdfile: "${stateDir}/var/xfrd.state" + xfrdir: "${stateDir}/tmp" + + # interfaces + ${forEach " ip-address: " cfg.interfaces} + + server-count: ${toString cfg.serverCount} + ip-transparent: ${yesOrNo cfg.ipTransparent} + do-ip4: ${yesOrNo cfg.ipv4} + do-ip6: ${yesOrNo cfg.ipv6} + port: ${toString cfg.port} + verbosity: ${toString cfg.verbosity} + hide-version: ${yesOrNo cfg.hideVersion} + identity: "${cfg.identity}" + ${maybeString "nsid: " cfg.nsid} + tcp-count: ${toString cfg.tcpCount} + tcp-query-count: ${toString cfg.tcpQueryCount} + tcp-timeout: ${toString cfg.tcpTimeout} + ipv4-edns-size: ${toString cfg.ipv4EDNSSize} + ipv6-edns-size: ${toString cfg.ipv6EDNSSize} + ${if cfg.statistics == null then "" else "statistics: ${toString cfg.statistics}"} + xfrd-reload-timeout: ${toString cfg.xfrdReloadTimeout} + zonefiles-check: ${yesOrNo cfg.zonefilesCheck} + + rrl-size: ${toString cfg.ratelimit.size} + rrl-ratelimit: ${toString cfg.ratelimit.ratelimit} + rrl-whitelist-ratelimit: ${toString cfg.ratelimit.whitelistRatelimit} + ${maybeString "rrl-slip: " cfg.ratelimit.slip} + ${maybeString "rrl-ipv4-prefix-length: " cfg.ratelimit.ipv4PrefixLength} + ${maybeString "rrl-ipv6-prefix-length: " cfg.ratelimit.ipv6PrefixLength} + + ${keyConfigFile} + + remote-control: + control-enable: ${yesOrNo cfg.remoteControl.enable} + ${forEach " control-interface: " cfg.remoteControl.interfaces} + control-port: ${toString cfg.port} + server-key-file: "${cfg.remoteControl.serverKeyFile}" + server-cert-file: "${cfg.remoteControl.serverCertFile}" + control-key-file: "${cfg.remoteControl.controlKeyFile}" + control-cert-file: "${cfg.remoteControl.controlCertFile}" + + # zone files reside in "${zoneFiles}" linked to "${stateDir}/zones" + ${concatStrings (mapAttrsToList zoneConfigFile zoneConfigs)} + + ${cfg.extraConfig} + ''; + + yesOrNo = b: if b then "yes" else "no"; + maybeString = pre: s: if s == null then "" else ''${pre} "${s}"''; + forEach = pre: l: concatMapStrings (x: pre + x + "\n") l; + + + keyConfigFile = concatStrings (mapAttrsToList (keyName: keyOptions: '' + key: + name: "${keyName}" + algorithm: "${keyOptions.algorithm}" + include: "${stateDir}/private/${keyName}" + '') cfg.keys); + + copyKeys = concatStrings (mapAttrsToList (keyName: keyOptions: '' + secret=$(cat "${keyOptions.keyFile}") + dest="${stateDir}/private/${keyName}" + echo " secret: \"$secret\"" > "$dest" + ${pkgs.coreutils}/bin/chown ${username}:${username} "$dest" + ${pkgs.coreutils}/bin/chmod 0400 "$dest" + '') cfg.keys); + + + zoneConfigFile = name: zone: '' + zone: + name: "${name}" + zonefile: "${stateDir}/zones/${name}" + ${maybeString "outgoing-interface: " zone.outgoingInterface} + ${forEach " rrl-whitelist: " zone.rrlWhitelist} + + ${forEach " allow-notify: " zone.allowNotify} + ${forEach " request-xfr: " zone.requestXFR} + allow-axfr-fallback: ${yesOrNo zone.allowAXFRFallback} + + ${forEach " notify: " zone.notify} + notify-retry: ${toString zone.notifyRetry} + ${forEach " provide-xfr: " zone.provideXFR} + + ''; + + zoneConfigs = zoneConfigs' {} "" { children = cfg.zones; }; + + zoneConfigs' = parent: name: zone: + if !(zone ? children) || zone.children == null || zone.children == { } + # leaf -> actual zone + then listToAttrs [ (nameValuePair name (parent // zone)) ] + + # fork -> pattern + else zipAttrsWith (name: head) ( + mapAttrsToList (name: child: zoneConfigs' (parent // zone // { children = {}; }) name child) + zone.children + ); + + # fighting infinite recursion + zoneOptions = zoneOptionsRaw // childConfig zoneOptions1 true; + zoneOptions1 = zoneOptionsRaw // childConfig zoneOptions2 false; + zoneOptions2 = zoneOptionsRaw // childConfig zoneOptions3 false; + zoneOptions3 = zoneOptionsRaw // childConfig zoneOptions4 false; + zoneOptions4 = zoneOptionsRaw // childConfig zoneOptions5 false; + zoneOptions5 = zoneOptionsRaw // childConfig zoneOptions6 false; + zoneOptions6 = zoneOptionsRaw // childConfig null false; + + childConfig = x: v: { options.children = { type = types.attrsOf x; visible = v; }; }; + + zoneOptionsRaw = types.submodule ( + { options, ... }: + { options = { + children = mkOption { + default = {}; + description = '' + Children zones inherit all options of their parents. Attributes + defined in a child will overwrite the ones of its parent. Only + leaf zones will be actually served. This way it's possible to + define maybe zones which share most attributes without + duplicating everything. This mechanism replaces nsd's patterns + in a save and functional way. + ''; + }; + + allowNotify = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "192.0.2.0/24 NOKEY" "10.0.0.1-10.0.0.5 my_tsig_key_name" + "10.0.3.4&255.255.0.0 BLOCKED" + ]; + description = '' + Listed primary servers are allowed to notify this secondary server. + <screen><![CDATA[ + Format: <ip> <key-name | NOKEY | BLOCKED> + + <ip> either a plain IPv4/IPv6 address or range. Valid patters for ranges: + * 10.0.0.0/24 # via subnet size + * 10.0.0.0&255.255.255.0 # via subnet mask + * 10.0.0.1-10.0.0.254 # via range + + A optional port number could be added with a '@': + * 2001:1234::1@1234 + + <key-name | NOKEY | BLOCKED> + * <key-name> will use the specified TSIG key + * NOKEY no TSIG signature is required + * BLOCKED notifies from non-listed or blocked IPs will be ignored + * ]]></screen> + ''; + }; + + requestXFR = mkOption { + type = types.listOf types.str; + default = []; + example = []; + description = '' + Format: <code>[AXFR|UDP] <ip-address> <key-name | NOKEY></code> + ''; + }; + + allowAXFRFallback = mkOption { + type = types.bool; + default = true; + description = '' + If NSD as secondary server should be allowed to AXFR if the primary + server does not allow IXFR. + ''; + }; + + notify = mkOption { + type = types.listOf types.str; + default = []; + example = [ "10.0.0.1@3721 my_key" "::5 NOKEY" ]; + description = '' + This primary server will notify all given secondary servers about + zone changes. + <screen><![CDATA[ + Format: <ip> <key-name | NOKEY> + + <ip> a plain IPv4/IPv6 address with on optional port number (ip@port) + + <key-name | NOKEY> + * <key-name> sign notifies with the specified key + * NOKEY don't sign notifies + ]]></screen> + ''; + }; + + notifyRetry = mkOption { + type = types.int; + default = 5; + description = '' + Specifies the number of retries for failed notifies. Set this along with notify. + ''; + }; + + provideXFR = mkOption { + type = types.listOf types.str; + default = []; + example = [ "192.0.2.0/24 NOKEY" "192.0.2.0/24 my_tsig_key_name" ]; + description = '' + Allow these IPs and TSIG to transfer zones, addr TSIG|NOKEY|BLOCKED + address range 192.0.2.0/24, 1.2.3.4&255.255.0.0, 3.0.2.20-3.0.2.40 + ''; + }; + + outgoingInterface = mkOption { + type = types.nullOr types.str; + default = null; + example = "2000::1@1234"; + description = '' + This address will be used for zone-transfere requests if configured + as a secondary server or notifications in case of a primary server. + Supply either a plain IPv4 or IPv6 address with an optional port + number (ip@port). + ''; + }; + + rrlWhitelist = mkOption { + type = types.listOf types.str; + default = []; + description = '' + Whitelists the given rrl-types. + The RRL classification types are: nxdomain, error, referral, any, + rrsig, wildcard, nodata, dnskey, positive, all + ''; + }; + + data = mkOption { + type = types.str; + default = ""; + example = ""; + description = '' + The actual zone data. This is the content of your zone file. + Use imports or pkgs.lib.readFile if you don't want this data in your config file. + ''; + }; + + }; + } + ); + +in +{ + options = { + services.nsd = { + + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable the NSD authoritative domain name server. + ''; + }; + + rootServer = mkOption { + type = types.bool; + default = false; + description = '' + Wheter if this server will be a root server (a DNS root server, you + usually don't want that). + ''; + }; + + interfaces = mkOption { + type = types.listOf types.str; + default = [ "127.0.0.0" "::1" ]; + description = '' + What addresses the server should listen to. + ''; + }; + + serverCount = mkOption { + type = types.int; + default = 1; + description = '' + Number of NSD servers to fork. Put the number of CPUs to use here. + ''; + }; + + ipTransparent = mkOption { + type = types.bool; + default = false; + description = '' + Allow binding to non local addresses. + ''; + }; + + ipv4 = mkOption { + type = types.bool; + default = true; + description = '' + Wheter to listen on IPv4 connections. + ''; + }; + + ipv6 = mkOption { + type = types.bool; + default = true; + description = '' + Wheter to listen on IPv6 connections. + ''; + }; + + port = mkOption { + type = types.int; + default = 53; + description = '' + Port the service should bind do. + ''; + }; + + verbosity = mkOption { + type = types.int; + default = 0; + description = '' + Verbosity level. + ''; + }; + + hideVersion = mkOption { + type = types.bool; + default = true; + description = '' + Wheter NSD should answer VERSION.BIND and VERSION.SERVER CHAOS class queries. + ''; + }; + + identity = mkOption { + type = types.str; + default = "unidentified server"; + description = '' + Identify the server (CH TXT ID.SERVER entry). + ''; + }; + + nsid = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + NSID identity (hex string, or "ascii_somestring"). + ''; + }; + + tcpCount = mkOption { + type = types.int; + default = 100; + description = '' + Maximum number of concurrent TCP connections per server. + ''; + }; + + tcpQueryCount = mkOption { + type = types.int; + default = 0; + description = '' + Maximum number of queries served on a single TCP connection. + 0 means no maximum. + ''; + }; + + tcpTimeout = mkOption { + type = types.int; + default = 120; + description = '' + TCP timeout in seconds. + ''; + }; + + ipv4EDNSSize = mkOption { + type = types.int; + default = 4096; + description = '' + Preferred EDNS buffer size for IPv4. + ''; + }; + + ipv6EDNSSize = mkOption { + type = types.int; + default = 4096; + description = '' + Preferred EDNS buffer size for IPv6. + ''; + }; + + statistics = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + Statistics are produced every number of seconds. Prints to log. + If null no statistics are logged. + ''; + }; + + xfrdReloadTimeout = mkOption { + type = types.int; + default = 1; + description = '' + Number of seconds between reloads triggered by xfrd. + ''; + }; + + zonefilesCheck = mkOption { + type = types.bool; + default = true; + description = '' + Wheter to check mtime of all zone files on start and sighup. + ''; + }; + + + extraConfig = mkOption { + type = types.str; + default = ""; + description = '' + Extra nsd config. + ''; + }; + + + ratelimit = mkOption { + type = types.submodule ( + { options, ... }: + { options = { + + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enable ratelimit capabilities. + ''; + }; + + size = mkOption { + type = types.int; + default = 1000000; + description = '' + Size of the hashtable. More buckets use more memory but lower + the chance of hash hash collisions. + ''; + }; + + ratelimit = mkOption { + type = types.int; + default = 200; + description = '' + Max qps allowed from any query source. + 0 means unlimited. With an verbosity of 2 blocked and + unblocked subnets will be logged. + ''; + }; + + whitelistRatelimit = mkOption { + type = types.int; + default = 2000; + description = '' + Max qps allowed from whitelisted sources. + 0 means unlimited. Set the rrl-whitelist option for specific + queries to apply this limit instead of the default to them. + ''; + }; + + slip = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + Number of packets that get discarded before replying a SLIP response. + 0 disables SLIP responses. 1 will make every response a SLIP response. + ''; + }; + + ipv4PrefixLength = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + IPv4 prefix length. Addresses are grouped by netblock. + ''; + }; + + ipv6PrefixLength = mkOption { + type = types.nullOr types.int; + default = null; + description = '' + IPv6 prefix length. Addresses are grouped by netblock. + ''; + }; + + }; + }); + default = { + }; + example = {}; + description = '' + ''; + }; + + + remoteControl = mkOption { + type = types.submodule ( + { config, options, ... }: + { options = { + + enable = mkOption { + type = types.bool; + default = false; + description = '' + Wheter to enable remote control via nsd-control(8). + ''; + }; + + interfaces = mkOption { + type = types.listOf types.str; + default = [ "127.0.0.1" "::1" ]; + description = '' + Which interfaces NSD should bind to for remote control. + ''; + }; + + port = mkOption { + type = types.int; + default = 8952; + description = '' + Port number for remote control operations (uses TLS over TCP). + ''; + }; + + serverKeyFile = mkOption { + type = types.path; + default = "/etc/nsd/nsd_server.key"; + description = '' + Path to the server private key, which is used by the server + but not by nsd-control. This file is generated by nsd-control-setup. + ''; + }; + + serverCertFile = mkOption { + type = types.path; + default = "/etc/nsd/nsd_server.pem"; + description = '' + Path to the server self signed certificate, which is used by the server + but and by nsd-control. This file is generated by nsd-control-setup. + ''; + }; + + controlKeyFile = mkOption { + type = types.path; + default = "/etc/nsd/nsd_control.key"; + description = '' + Path to the client private key, which is used by nsd-control + but not by the server. This file is generated by nsd-control-setup. + ''; + }; + + controlCertFile = mkOption { + type = types.path; + default = "/etc/nsd/nsd_control.pem"; + description = '' + Path to the client certificate signed with the server certificate. + This file is used by nsd-control and generated by nsd-control-setup. + ''; + }; + + }; + + }); + default = { + }; + example = {}; + description = '' + ''; + }; + + + keys = mkOption { + type = types.attrsOf (types.submodule ( + { options, ... }: + { options = { + + algorithm = mkOption { + type = types.str; + default = "hmac-sha256"; + description = '' + Authentication algorithm for this key. + ''; + }; + + keyFile = mkOption { + type = types.path; + description = '' + Path to the file which contains the actual base64 encoded + key. The key will be copied into "${stateDir}/private" before + NSD starts. The copied file is only accessibly by the NSD + user. + ''; + }; + + }; + })); + default = { + }; + example = { + "tsig.example.org" = { + algorithm = "hmac-md5"; + secret = "aaaaaabbbbbbccccccdddddd"; + }; + }; + description = '' + Define your TSIG keys here. + ''; + }; + + zones = mkOption { + type = types.attrsOf zoneOptions; + default = {}; + example = { + "serverGroup1" = { + provideXFR = [ "10.1.2.3 NOKEY" ]; + children = { + "example.com." = { + data = '' + $ORIGIN example.com. + $TTL 86400 + @ IN SOA a.ns.example.com. admin.example.com. ( + ... + ''; + }; + "example.org." = { + data = '' + $ORIGIN example.org. + $TTL 86400 + @ IN SOA a.ns.example.com. admin.example.com. ( + ... + ''; + }; + }; + }; + + "example.net." = { + provideXFR = [ "10.3.2.1 NOKEY" ]; + data = ''...''; + }; + }; + description = '' + Define your zones here. Zones can cascade other zones and therefore + inherit settings from parent zones. Look at the definition of + children to learn about inheritance and child zones. + The given example will define 3 zones (example.(com|org|net).). Both + example.com. and example.org. inherit their configuration from + serverGroup1. + ''; + }; + + }; + }; + + config = mkIf cfg.enable { + + # this is not working :( + nixpkgs.config.nsd = { + ipv6 = cfg.ipv6; + ratelimit = cfg.ratelimit.enable; + rootServer = cfg.rootServer; + }; + + users.extraGroups = singleton { + name = username; + gid = config.ids.gids.nsd; + }; + + users.extraUsers = singleton { + name = username; + description = "NSD service user"; + home = stateDir; + createHome = true; + uid = config.ids.uids.nsd; + group = username; + }; + + systemd.services.nsd = { + description = "NSD authoritative only domain name service"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + serviceConfig = { + Type = "forking"; + PIDFile = pidFile; + Restart = "always"; + ExecStart = "${pkgs.nsd}/sbin/nsd -c ${configFile}"; + }; + + preStart = '' + ${pkgs.coreutils}/bin/mkdir -m 0700 -p "${stateDir}/private" + ${pkgs.coreutils}/bin/mkdir -m 0700 -p "${stateDir}/tmp" + ${pkgs.coreutils}/bin/mkdir -m 0700 -p "${stateDir}/var" + + ${pkgs.coreutils}/bin/touch "${stateDir}/don't touch anything in here" + + ${pkgs.coreutils}/bin/rm -f "${stateDir}/private/"* + ${pkgs.coreutils}/bin/rm -f "${stateDir}/tmp/"* + + ${pkgs.coreutils}/bin/chown nsd:nsd -R "${stateDir}/private" + ${pkgs.coreutils}/bin/chown nsd:nsd -R "${stateDir}/tmp" + ${pkgs.coreutils}/bin/chown nsd:nsd -R "${stateDir}/var" + + ${pkgs.coreutils}/bin/rm -rf "${stateDir}/zones" + ${pkgs.coreutils}/bin/cp -r "${zoneFiles}" "${stateDir}/zones" + + ${copyKeys} + ''; + }; + + }; +} diff --git a/nixos/modules/services/search/elasticsearch.nix b/nixos/modules/services/search/elasticsearch.nix index b7a3566f95d..3c32e4a3dfe 100644 --- a/nixos/modules/services/search/elasticsearch.nix +++ b/nixos/modules/services/search/elasticsearch.nix @@ -93,6 +93,14 @@ in { Data directory for elasticsearch. ''; }; + + extraCmdLineOptions = mkOption { + description = "Extra command line options for the elasticsearch launcher"; + default = []; + type = types.listOf types.string; + example = [ "-Djava.net.preferIPv4Stack=true" ]; + }; + }; ###### implementation @@ -104,8 +112,9 @@ in { after = [ "network-interfaces.target" ]; environment = { ES_HOME = cfg.dataDir; }; serviceConfig = { - ExecStart = "${pkgs.elasticsearch}/bin/elasticsearch -f -Des.path.conf=${configDir}"; + ExecStart = "${pkgs.elasticsearch}/bin/elasticsearch -Des.path.conf=${configDir} ${toString cfg.extraCmdLineOptions}"; User = "elasticsearch"; + PermissionsStartOnly = true; }; preStart = '' mkdir -m 0700 -p ${cfg.dataDir} diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix index 75ec6671d15..b8359d4756b 100644 --- a/nixos/modules/services/web-servers/apache-httpd/default.nix +++ b/nixos/modules/services/web-servers/apache-httpd/default.nix @@ -594,14 +594,14 @@ in message = "SSL is enabled for HTTPD, but sslServerCert and/or sslServerKey haven't been specified."; } ]; - users.extraUsers = optionalAttrs (mainCfg.user == "wwwrun") singleton + users.extraUsers = optional (mainCfg.user == "wwwrun") { name = "wwwrun"; group = "wwwrun"; description = "Apache httpd user"; uid = config.ids.uids.wwwrun; }; - users.extraGroups = optionalAttrs (mainCfg.group == "wwwrun") singleton + users.extraGroups = optional (mainCfg.group == "wwwrun") { name = "wwwrun"; gid = config.ids.gids.wwwrun; }; diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index ff94ee42d28..7c2d3a42973 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -84,8 +84,6 @@ in }; config = mkIf cfg.enable { - environment.systemPackages = [ nginx ]; - # TODO: test user supplied config file pases syntax test systemd.services.nginx = { @@ -96,6 +94,7 @@ in preStart = '' mkdir -p ${cfg.stateDir}/logs + chmod 700 ${cfg.stateDir} chown -R ${cfg.user}:${cfg.group} ${cfg.stateDir} ''; serviceConfig = { @@ -105,7 +104,7 @@ in users.extraUsers = optionalAttrs (cfg.user == "nginx") (singleton { name = "nginx"; - group = "nginx"; + group = cfg.group; uid = config.ids.uids.nginx; }); diff --git a/nixos/modules/services/web-servers/phpfpm.nix b/nixos/modules/services/web-servers/phpfpm.nix index 4a14f9b41a4..8551e3ccdeb 100644 --- a/nixos/modules/services/web-servers/phpfpm.nix +++ b/nixos/modules/services/web-servers/phpfpm.nix @@ -42,6 +42,12 @@ in { ''; }; + phpIni = mkOption { + type = types.path; + default = "${cfg.phpPackage}/etc/php-recommended.ini"; + description = "php.ini file to use."; + }; + poolConfigs = mkOption { type = types.attrsOf types.lines; default = {}; @@ -75,7 +81,7 @@ in { mkdir -p "${stateDir}" ''; serviceConfig = { - ExecStart = "${cfg.phpPackage}/sbin/php-fpm -y ${cfgFile}"; + ExecStart = "${cfg.phpPackage}/sbin/php-fpm -y ${cfgFile} -c ${cfg.phpIni}"; PIDFile = pidFile; }; }; diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix index b739ef693ce..62999dceee3 100644 --- a/nixos/modules/system/activation/top-level.nix +++ b/nixos/modules/system/activation/top-level.nix @@ -95,7 +95,7 @@ let # kernel, systemd units, init scripts, etc.) as well as a script # `switch-to-configuration' that activates the configuration and # makes it bootable. - system = showWarnings ( + baseSystem = showWarnings ( if [] == failed then pkgs.stdenv.mkDerivation { name = "nixos-${config.system.nixosVersion}"; preferLocalBuild = true; @@ -118,6 +118,10 @@ let perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl"; } else throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failed)}"); + # Replace runtime dependencies + system = fold ({ oldDependency, newDependency }: drv: + pkgs.replaceDependency { inherit oldDependency newDependency drv; } + ) baseSystem config.system.replaceRuntimeDependencies; in @@ -184,6 +188,33 @@ in ''; }; + system.replaceRuntimeDependencies = mkOption { + default = []; + example = lib.literalExample "[ ({ original = pkgs.openssl; replacement = pkgs.callPackage /path/to/openssl { ... }; }) ]"; + type = types.listOf (types.submodule ( + { options, ... }: { + options.original = mkOption { + type = types.package; + description = "The original package to override."; + }; + + options.replacement = mkOption { + type = types.package; + description = "The replacement package."; + }; + }) + ); + apply = map ({ original, replacement, ... }: { + oldDependency = original; + newDependency = replacement; + }); + description = '' + List of packages to override without doing a full rebuild. + The original derivation and replacement derivation must have the same + name length, and ideally should have close-to-identical directory layout. + ''; + }; + }; diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index 761600f9e55..51ebca7dd43 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -15,13 +15,13 @@ let pkgs.runCommand "unit" { preferLocalBuild = true; inherit (unit) text; } '' mkdir -p $out - echo -n "$text" > $out/${name} + echo -n "$text" > $out/${shellEscape name} '' else pkgs.runCommand "unit" { preferLocalBuild = true; } '' mkdir -p $out - ln -s /dev/null $out/${name} + ln -s /dev/null $out/${shellEscape name} ''; upstreamSystemUnits = @@ -187,9 +187,11 @@ let "timers.target" ]; + shellEscape = s: (replaceChars [ "\\" ] [ "\\\\" ] s); + makeJobScript = name: text: - let x = pkgs.writeTextFile { name = "unit-script"; executable = true; destination = "/bin/${name}"; inherit text; }; - in "${x}/bin/${name}"; + let x = pkgs.writeTextFile { name = "unit-script"; executable = true; destination = "/bin/${shellEscape name}"; inherit text; }; + in "${x}/bin/${shellEscape name}"; unitConfig = { name, config, ... }: { config = { @@ -681,6 +683,13 @@ in description = "Definition of systemd per-user service units."; }; + systemd.user.sockets = mkOption { + default = {}; + type = types.attrsOf types.optionSet; + options = [ socketOptions unitConfig ]; + description = "Definition of systemd per-user socket units."; + }; + }; @@ -765,7 +774,8 @@ in in nameValuePair "${n}.automount" (automountToUnit n v)) cfg.automounts); systemd.user.units = - mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.user.services; + mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.user.services + // mapAttrs' (n: v: nameValuePair "${n}.socket" (socketToUnit n v)) cfg.user.sockets; system.requiredKernelConfig = map config.lib.kernelConfig.isEnabled [ "DEVTMPFS" "CGROUPS" "INOTIFY_USER" "SIGNALFD" "TIMERFD" "EPOLL" "NET" diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index 9cc8b154324..991f9f26145 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -183,6 +183,15 @@ in ''; }; + networking.search = mkOption { + default = []; + example = [ "example.com" "local.domain" ]; + type = types.listOf types.str; + description = '' + The list of search paths used when resolving domain names. + ''; + }; + networking.domain = mkOption { default = ""; example = "home"; @@ -424,6 +433,7 @@ in ${optionalString (cfg.nameservers != [] && cfg.domain != "") '' domain ${cfg.domain} ''} + ${optionalString (cfg.search != []) ("search " + concatStringsSep " " cfg.search)} ${flip concatMapStrings cfg.nameservers (ns: '' nameserver ${ns} '')} diff --git a/nixos/modules/tasks/trackpoint.nix b/nixos/modules/tasks/trackpoint.nix new file mode 100644 index 00000000000..4be2c3eb4c4 --- /dev/null +++ b/nixos/modules/tasks/trackpoint.nix @@ -0,0 +1,66 @@ +{ config, lib, pkgs, ... }: + +with lib; + +{ + ###### interface + + options = { + + hardware.trackpoint = { + + enable = mkOption { + default = false; + type = types.bool; + description = '' + Enable sensitivity and speed configuration for trackpoints. + ''; + }; + + sensitivity = mkOption { + default = 128; + example = 255; + type = types.int; + description = '' + Configure the trackpoint sensitivity. By default, the kernel + configures 128. + ''; + }; + + speed = mkOption { + default = 97; + example = 255; + type = types.int; + description = '' + Configure the trackpoint sensitivity. By default, the kernel + configures 97. + ''; + }; + + }; + + }; + + + ###### implementation + + config = mkIf config.hardware.trackpoint.enable { + + jobs.trackpoint = + { description = "Initialize trackpoint"; + + startOn = "started udev"; + + task = true; + + script = '' + echo -n ${toString config.hardware.trackpoint.sensitivity} \ + > /sys/devices/platform/i8042/serio1/sensitivity + echo -n ${toString config.hardware.trackpoint.speed} \ + > /sys/devices/platform/i8042/serio1/speed + ''; + }; + + }; + +} diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix index 9e64327c3ab..7d6109f212a 100644 --- a/nixos/modules/virtualisation/amazon-image.nix +++ b/nixos/modules/virtualisation/amazon-image.nix @@ -26,7 +26,7 @@ in '' mkdir $out diskImage=$out/nixos.img - ${pkgs.vmTools.qemu}/bin/qemu-img create -f raw $diskImage "4G" + ${pkgs.vmTools.qemu}/bin/qemu-img create -f raw $diskImage "8G" mv closure xchg/ ''; buildInputs = [ pkgs.utillinux pkgs.perl ]; @@ -34,16 +34,32 @@ in [ "closure" config.system.build.toplevel ]; } '' - # Create an empty filesystem and mount it. - ${pkgs.e2fsprogs}/sbin/mkfs.ext4 -L nixos /dev/vda - ${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda - mkdir /mnt - mount /dev/vda /mnt + ${if cfg.hvm then '' + # Create a single / partition. + ${pkgs.parted}/sbin/parted /dev/vda mklabel msdos + ${pkgs.parted}/sbin/parted /dev/vda -- mkpart primary ext2 1M -1s + . /sys/class/block/vda1/uevent + mknod /dev/vda1 b $MAJOR $MINOR + + # Create an empty filesystem and mount it. + ${pkgs.e2fsprogs}/sbin/mkfs.ext4 -L nixos /dev/vda1 + ${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda1 + mkdir /mnt + mount /dev/vda1 /mnt + '' else '' + # Create an empty filesystem and mount it. + ${pkgs.e2fsprogs}/sbin/mkfs.ext4 -L nixos /dev/vda + ${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda + mkdir /mnt + mount /dev/vda /mnt + ''} # The initrd expects these directories to exist. mkdir /mnt/dev /mnt/proc /mnt/sys mount -o bind /proc /mnt/proc + mount -o bind /dev /mnt/dev + mount -o bind /sys /mnt/sys # Copy all paths in the closure to the filesystem. storePaths=$(perl ${pkgs.pathsFromGraph} /tmp/xchg/closure) @@ -73,9 +89,10 @@ in cp ${./amazon-config.nix} /mnt/etc/nixos/configuration.nix # Generate the GRUB menu. + ln -s vda /dev/xvda chroot /mnt ${config.system.build.toplevel}/bin/switch-to-configuration boot - umount /mnt/proc + umount /mnt/proc /mnt/dev /mnt/sys umount /mnt '' ); @@ -86,7 +103,7 @@ in boot.kernelModules = [ "xen-netfront" ]; # Generate a GRUB menu. Amazon's pv-grub uses this to boot our kernel/initrd. - boot.loader.grub.version = 1; + boot.loader.grub.version = if cfg.hvm then 2 else 1; boot.loader.grub.device = if cfg.hvm then "/dev/xvda" else "nodev"; boot.loader.grub.timeout = 0; boot.loader.grub.extraPerEntryConfig = "root (hd0${lib.optionalString cfg.hvm ",0"})"; |