diff options
author | Vladimír Čunát <vcunat@gmail.com> | 2017-01-26 16:49:41 +0100 |
---|---|---|
committer | Vladimír Čunát <vcunat@gmail.com> | 2017-01-26 16:49:41 +0100 |
commit | 6973c7739ea1581595931e8c8b3b76241083b2df (patch) | |
tree | f56826492e0e260f24aeeedd2e47d36785ba3519 /nixos/modules | |
parent | 5dacc53af3f4537fab693952b5f13b6cafcde6d4 (diff) | |
parent | bca9bcb3c3dd3b2e46f8e07db9a8326de01697c7 (diff) | |
download | nixlib-6973c7739ea1581595931e8c8b3b76241083b2df.tar nixlib-6973c7739ea1581595931e8c8b3b76241083b2df.tar.gz nixlib-6973c7739ea1581595931e8c8b3b76241083b2df.tar.bz2 nixlib-6973c7739ea1581595931e8c8b3b76241083b2df.tar.lz nixlib-6973c7739ea1581595931e8c8b3b76241083b2df.tar.xz nixlib-6973c7739ea1581595931e8c8b3b76241083b2df.tar.zst nixlib-6973c7739ea1581595931e8c8b3b76241083b2df.zip |
Merge branch 'master' into staging
There were some larger rebuilds because of security.
Diffstat (limited to 'nixos/modules')
25 files changed, 838 insertions, 72 deletions
diff --git a/nixos/modules/i18n/input-method/ibus.nix b/nixos/modules/i18n/input-method/ibus.nix index 3eaf9e2ab370..a5bbe6bcb559 100644 --- a/nixos/modules/i18n/input-method/ibus.nix +++ b/nixos/modules/i18n/input-method/ibus.nix @@ -44,7 +44,7 @@ in panel = mkOption { type = with types; nullOr path; default = null; - example = literalExample "${pkgs.kde5.plasma-desktop}/lib/libexec/kimpanel-ibus-panel"; + example = literalExample "''${pkgs.kde5.plasma-desktop}/lib/libexec/kimpanel-ibus-panel"; description = "Replace the IBus panel with another panel."; }; }; diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index 5058d41bf753..2005f2518ba0 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -284,6 +284,8 @@ glance = 266; couchpotato = 267; gogs = 268; + pdns-recursor = 269; + kresd = 270; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -538,6 +540,7 @@ glance = 266; couchpotato = 267; gogs = 268; + kresd = 270; # 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/misc/locate.nix b/nixos/modules/misc/locate.nix index 3cb5bb1a351a..a9c84f6db243 100644 --- a/nixos/modules/misc/locate.nix +++ b/nixos/modules/misc/locate.nix @@ -4,10 +4,12 @@ with lib; let cfg = config.services.locate; + isMLocate = hasPrefix "mlocate" cfg.locate.name; + isFindutils = hasPrefix "findutils" cfg.locate.name; in { - options.services.locate = { + options.services.locate = with types; { enable = mkOption { - type = types.bool; + type = bool; default = false; description = '' If enabled, NixOS will periodically update the database of @@ -16,8 +18,9 @@ in { }; locate = mkOption { - type = types.package; + type = package; default = pkgs.findutils; + defaultText = "pkgs.findutils"; example = "pkgs.mlocate"; description = '' The locate implementation to use @@ -25,7 +28,7 @@ in { }; interval = mkOption { - type = types.str; + type = str; default = "02:15"; example = "hourly"; description = '' @@ -38,11 +41,8 @@ in { ''; }; - # This is no longer supported, but we keep it to give a better warning below - period = mkOption { visible = false; }; - extraFlags = mkOption { - type = types.listOf types.str; + type = listOf str; default = [ ]; description = '' Extra flags to pass to <command>updatedb</command>. @@ -50,7 +50,7 @@ in { }; output = mkOption { - type = types.path; + type = path; default = "/var/cache/locatedb"; description = '' The database file to build. @@ -58,7 +58,7 @@ in { }; localuser = mkOption { - type = types.str; + type = nullOr str; default = "nobody"; description = '' The user to search non-network directories as, using @@ -66,31 +66,81 @@ in { ''; }; - includeStore = mkOption { - type = types.bool; + pruneFS = mkOption { + type = listOf str; + default = ["afs" "anon_inodefs" "auto" "autofs" "bdev" "binfmt" "binfmt_misc" "cgroup" "cifs" "coda" "configfs" "cramfs" "cpuset" "debugfs" "devfs" "devpts" "devtmpfs" "ecryptfs" "eventpollfs" "exofs" "futexfs" "ftpfs" "fuse" "fusectl" "gfs" "gfs2" "hostfs" "hugetlbfs" "inotifyfs" "iso9660" "jffs2" "lustre" "misc" "mqueue" "ncpfs" "nnpfs" "ocfs" "ocfs2" "pipefs" "proc" "ramfs" "rpc_pipefs" "securityfs" "selinuxfs" "sfs" "shfs" "smbfs" "sockfs" "spufs" "nfs" "NFS" "nfs4" "nfsd" "sshfs" "subfs" "supermount" "sysfs" "tmpfs" "ubifs" "udf" "usbfs" "vboxsf" "vperfctrfs" ]; + description = '' + Which filesystem types to exclude from indexing + ''; + }; + + prunePaths = mkOption { + type = listOf path; + default = ["/tmp" "/var/tmp" "/var/cache" "/var/lock" "/var/run" "/var/spool" "/nix/store"]; + description = '' + Which paths to exclude from indexing + ''; + }; + + pruneNames = mkOption { + type = listOf str; + default = []; + description = '' + Directory components which should exclude paths containing them from indexing + ''; + }; + + pruneBindMounts = mkOption { + type = bool; default = false; description = '' - Whether to include <filename>/nix/store</filename> in the locate database. + Whether not to index bind mounts ''; }; + }; - config = { - warnings = - let opt = options.services.locate.period; in - optional opt.isDefined "The ‘services.locate.period’ option in ${showFiles opt.files} has been removed; please replace it with ‘services.locate.interval’, using the systemd.time(7) calendar event format."; + config = mkIf cfg.enable { + users.extraGroups = mkIf isMLocate { mlocate = {}; }; + + security.setuidOwners = mkIf isMLocate + [ { group = "mlocate"; + owner = "root"; + permissions = "u+rx,g+x,o+x"; + setgid = true; + setuid = false; + program = "locate"; + } + ]; + + nixpkgs.config = { locate.dbfile = cfg.output; }; + + environment.systemPackages = [ cfg.locate ]; + + environment.variables = mkIf (!isMLocate) + { LOCATE_PATH = cfg.output; + }; + warnings = optional (isMLocate && cfg.localuser != null) "mlocate does not support searching as user other than root" + ++ optional (isFindutils && cfg.pruneNames != []) "findutils locate does not support pruning by directory component" + ++ optional (isFindutils && cfg.pruneBindMounts) "findutils locate does not support skipping bind mounts"; + systemd.services.update-locatedb = { description = "Update Locate Database"; - path = [ pkgs.su ]; + path = mkIf (!isMLocate) [ pkgs.su ]; script = '' - mkdir -m 0755 -p $(dirname ${toString cfg.output}) + install -m ${if isMLocate then "0750" else "0755"} -o root -g ${if isMLocate then "mlocate" else "root"} -d $(dirname ${cfg.output}) exec ${cfg.locate}/bin/updatedb \ - --localuser=${cfg.localuser} \ - ${optionalString (!cfg.includeStore) "--prunepaths='/nix/store'"} \ + ${optionalString (cfg.localuser != null) ''--localuser=${cfg.localuser}''} \ --output=${toString cfg.output} ${concatStringsSep " " cfg.extraFlags} ''; + environment = { + PRUNEFS = concatStringsSep " " cfg.pruneFS; + PRUNEPATHS = concatStringsSep " " cfg.prunePaths; + PRUNENAMES = concatStringsSep " " cfg.pruneNames; + PRUNE_BIND_MOUNTS = if cfg.pruneBindMounts then "yes" else "no"; + }; serviceConfig.Nice = 19; serviceConfig.IOSchedulingClass = "idle"; serviceConfig.PrivateTmp = "yes"; @@ -100,7 +150,7 @@ in { serviceConfig.ReadWriteDirectories = dirOf cfg.output; }; - systemd.timers.update-locatedb = mkIf cfg.enable + systemd.timers.update-locatedb = { description = "Update timer for locate database"; partOf = [ "update-locatedb.service" ]; wantedBy = [ "timers.target" ]; diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index e99e344b932d..9100f5b27a04 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -212,6 +212,7 @@ ./services/logging/awstats.nix ./services/logging/fluentd.nix ./services/logging/graylog.nix + ./services/logging/journalbeat.nix ./services/logging/klogd.nix ./services/logging/logcheck.nix ./services/logging/logrotate.nix @@ -332,6 +333,7 @@ ./services/monitoring/telegraf.nix ./services/monitoring/ups.nix ./services/monitoring/uptime.nix + ./services/monitoring/vnstat.nix ./services/monitoring/zabbix-agent.nix ./services/monitoring/zabbix-server.nix ./services/network-filesystems/cachefilesd.nix @@ -370,6 +372,7 @@ ./services/networking/dhcpd.nix ./services/networking/dnschain.nix ./services/networking/dnscrypt-proxy.nix + ./services/networking/dnscrypt-wrapper.nix ./services/networking/dnsmasq.nix ./services/networking/ejabberd.nix ./services/networking/fan.nix @@ -396,6 +399,7 @@ ./services/networking/iodine.nix ./services/networking/ircd-hybrid/default.nix ./services/networking/kippo.nix + ./services/networking/kresd.nix ./services/networking/lambdabot.nix ./services/networking/libreswan.nix ./services/networking/logmein-hamachi.nix @@ -426,6 +430,7 @@ ./services/networking/pdnsd.nix ./services/networking/polipo.nix ./services/networking/powerdns.nix + ./services/networking/pdns-recursor.nix ./services/networking/pptpd.nix ./services/networking/prayer.nix ./services/networking/privoxy.nix diff --git a/nixos/modules/profiles/installation-device.nix b/nixos/modules/profiles/installation-device.nix index b2973d88b157..a24fa75e01db 100644 --- a/nixos/modules/profiles/installation-device.nix +++ b/nixos/modules/profiles/installation-device.nix @@ -45,8 +45,13 @@ with lib; "Type `systemctl start display-manager' to\nstart the graphical user interface."} ''; - # Allow sshd to be started manually through "start sshd". - services.openssh.enable = true; + # Allow sshd to be started manually through "systemctl start sshd". + services.openssh = { + enable = true; + # Allow password login to the installation, if the user sets a password via "passwd" + # It is safe as root doesn't have a password by default and SSH is disabled by default + permitRootLogin = "yes"; + }; systemd.services.sshd.wantedBy = mkOverride 50 []; # Enable wpa_supplicant, but don't start it by default. @@ -66,9 +71,8 @@ with lib; boot.kernel.sysctl."vm.overcommit_memory" = "1"; # To speed up installation a little bit, include the complete - # stdenv in the Nix store on the CD. Archive::Cpio is needed for - # the initrd builder. - system.extraDependencies = [ pkgs.stdenv pkgs.busybox pkgs.perlPackages.ArchiveCpio ]; + # stdenv in the Nix store on the CD. + system.extraDependencies = with pkgs; [ stdenv stdenvNoCC busybox ]; # Show all debug messages from the kernel but don't log refused packets # because we have the firewall enabled. This makes installs from the diff --git a/nixos/modules/programs/environment.nix b/nixos/modules/programs/environment.nix index a35b5cc9513e..a1615c920c02 100644 --- a/nixos/modules/programs/environment.nix +++ b/nixos/modules/programs/environment.nix @@ -17,8 +17,7 @@ in config = { environment.variables = - { LOCATE_PATH = "/var/cache/locatedb"; - NIXPKGS_CONFIG = "/etc/nix/nixpkgs-config.nix"; + { NIXPKGS_CONFIG = "/etc/nix/nixpkgs-config.nix"; PAGER = mkDefault "less -R"; EDITOR = mkDefault "nano"; }; diff --git a/nixos/modules/programs/man.nix b/nixos/modules/programs/man.nix index e59ffd6f936d..5b20a38d8856 100644 --- a/nixos/modules/programs/man.nix +++ b/nixos/modules/programs/man.nix @@ -11,6 +11,7 @@ with lib; default = true; description = '' Whether to enable manual pages and the <command>man</command> command. + This also includes "man" outputs of all <literal>systemPackages</literal>. ''; }; diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix index ad1ba86980d5..4e7f62fc8f5c 100644 --- a/nixos/modules/rename.nix +++ b/nixos/modules/rename.nix @@ -18,6 +18,7 @@ with lib; (mkRenamedOptionModule [ "services" "elasticsearch" "host" ] [ "services" "elasticsearch" "listenAddress" ]) (mkRenamedOptionModule [ "services" "graphite" "api" "host" ] [ "services" "graphite" "api" "listenAddress" ]) (mkRenamedOptionModule [ "services" "graphite" "web" "host" ] [ "services" "graphite" "web" "listenAddress" ]) + (mkRenamedOptionModule [ "services" "logstash" "address" ] [ "services" "logstash" "listenAddress" ]) (mkRenamedOptionModule [ "services" "kibana" "host" ] [ "services" "kibana" "listenAddress" ]) (mkRenamedOptionModule [ "services" "mpd" "network" "host" ] [ "services" "mpd" "network" "listenAddress" ]) (mkRenamedOptionModule [ "services" "neo4j" "host" ] [ "services" "neo4j" "listenAddress" ]) @@ -167,6 +168,10 @@ with lib; # dhcpd (mkRenamedOptionModule [ "services" "dhcpd" ] [ "services" "dhcpd4" ]) + # locate + (mkRenamedOptionModule [ "services" "locate" "period" ] [ "services" "locate" "interval" ]) + (mkRemovedOptionModule [ "services" "locate" "includeStore" ] "Use services.locate.prunePaths" ) + # Options that are obsolete and have no replacement. (mkRemovedOptionModule [ "boot" "initrd" "luks" "enable" ] "") (mkRemovedOptionModule [ "programs" "bash" "enable" ] "") diff --git a/nixos/modules/security/acme.nix b/nixos/modules/security/acme.nix index 726e54711410..4e7c966a463a 100644 --- a/nixos/modules/security/acme.nix +++ b/nixos/modules/security/acme.nix @@ -284,6 +284,8 @@ in OnCalendar = cfg.renewInterval; Unit = "acme-${cert}.service"; Persistent = "yes"; + AccuracySec = "5m"; + RandomizedDelaySec = "1h"; }; }) ); diff --git a/nixos/modules/services/games/factorio.nix b/nixos/modules/services/games/factorio.nix index 0369752997a7..e7f070d08773 100644 --- a/nixos/modules/services/games/factorio.nix +++ b/nixos/modules/services/games/factorio.nix @@ -14,6 +14,31 @@ let read-data=${factorio}/share/factorio/data write-data=${stateDir} ''; + serverSettings = { + name = cfg.game-name; + description = cfg.description; + visibility = { + public = cfg.public; + lan = cfg.lan; + }; + username = cfg.username; + password = cfg.password; + token = cfg.token; + game_password = cfg.game-password; + require_user_verification = true; + max_upload_in_kilobytes_per_second = 0; + minimum_latency_in_ticks = 0; + ignore_player_limit_for_returning_players = false; + allow_commands = "admins-only"; + autosave_interval = cfg.autosave-interval; + autosave_slots = 5; + afk_autokick_interval = 0; + auto_pause = true; + only_admins_can_pause_the_game = true; + autosave_only_on_server = true; + admins = []; + }; + serverSettingsFile = pkgs.writeText "server-settings.json" (builtins.toJSON (filterAttrsRecursive (n: v: v != null) serverSettings)); modDir = pkgs.factorio-mkModDirDrv cfg.mods; in { @@ -67,12 +92,68 @@ in derivations via nixos-channel. Until then, this is for experts only. ''; }; + game-name = mkOption { + type = types.nullOr types.string; + default = "Factorio Game"; + description = '' + Name of the game as it will appear in the game listing. + ''; + }; + description = mkOption { + type = types.nullOr types.string; + default = ""; + description = '' + Description of the game that will appear in the listing. + ''; + }; + public = mkOption { + type = types.bool; + default = false; + description = '' + Game will be published on the official Factorio matching server. + ''; + }; + lan = mkOption { + type = types.bool; + default = false; + description = '' + Game will be broadcast on LAN. + ''; + }; + username = mkOption { + type = types.nullOr types.string; + default = null; + description = '' + Your factorio.com login credentials. Required for games with visibility public. + ''; + }; + password = mkOption { + type = types.nullOr types.string; + default = null; + description = '' + Your factorio.com login credentials. Required for games with visibility public. + ''; + }; + token = mkOption { + type = types.nullOr types.string; + default = null; + description = '' + Authentication token. May be used instead of 'password' above. + ''; + }; + game-password = mkOption { + type = types.nullOr types.string; + default = null; + description = '' + Game password. + ''; + }; autosave-interval = mkOption { type = types.nullOr types.int; default = null; - example = 2; + example = 10; description = '' - The time, in minutes, between autosaves. + Autosave interval in minutes. ''; }; }; @@ -120,8 +201,8 @@ in "--config=${cfg.configFile}" "--port=${toString cfg.port}" "--start-server=${mkSavePath cfg.saveName}" + "--server-settings=${serverSettingsFile}" (optionalString (cfg.mods != []) "--mod-directory=${modDir}") - (optionalString (cfg.autosave-interval != null) "--autosave-interval ${toString cfg.autosave-interval}") ]; }; }; diff --git a/nixos/modules/services/logging/journalbeat.nix b/nixos/modules/services/logging/journalbeat.nix new file mode 100644 index 000000000000..8186a3b02c37 --- /dev/null +++ b/nixos/modules/services/logging/journalbeat.nix @@ -0,0 +1,76 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.journalbeat; + + journalbeatYml = pkgs.writeText "journalbeat.yml" '' + name: ${cfg.name} + tags: ${builtins.toJSON cfg.tags} + + journalbeat.cursor_state_file: ${cfg.stateDir}/cursor-state + + ${cfg.extraConfig} + ''; + +in +{ + options = { + + services.journalbeat = { + + enable = mkEnableOption "journalbeat"; + + name = mkOption { + type = types.str; + default = "journalbeat"; + description = "Name of the beat"; + }; + + tags = mkOption { + type = types.listOf types.str; + default = []; + description = "Tags to place on the shipped log messages"; + }; + + stateDir = mkOption { + type = types.str; + default = "/var/lib/journalbeat"; + description = "The state directory. Journalbeat's own logs and other data are stored here."; + }; + + extraConfig = mkOption { + type = types.lines; + default = '' + journalbeat: + seek_position: cursor + cursor_seek_fallback: tail + write_cursor_state: true + cursor_flush_period: 5s + clean_field_names: true + convert_to_numbers: false + move_metadata_to_field: journal + default_type: journal + ''; + description = "Any other configuration options you want to add"; + }; + + }; + }; + + config = mkIf cfg.enable { + + systemd.services.journalbeat = with pkgs; { + description = "Journalbeat log shipper"; + wantedBy = [ "multi-user.target" ]; + preStart = '' + mkdir -p ${cfg.stateDir}/data + mkdir -p ${cfg.stateDir}/logs + ''; + serviceConfig = { + ExecStart = "${pkgs.journalbeat}/bin/journalbeat -c ${journalbeatYml} -path.data ${cfg.stateDir}/data -path.logs ${cfg.stateDir}/logs"; + }; + }; + }; +} diff --git a/nixos/modules/services/logging/logstash.nix b/nixos/modules/services/logging/logstash.nix index 62f6e187ea07..c9477b9e3ab0 100644 --- a/nixos/modules/services/logging/logstash.nix +++ b/nixos/modules/services/logging/logstash.nix @@ -63,7 +63,7 @@ in description = "Enable the logstash web interface."; }; - address = mkOption { + listenAddress = mkOption { type = types.str; default = "0.0.0.0"; description = "Address on which to start webserver."; @@ -77,7 +77,7 @@ in inputConfig = mkOption { type = types.lines; - default = ''stdin { type => "example" }''; + default = ''generator { }''; description = "Logstash input configuration."; example = '' # Read from journal @@ -90,7 +90,7 @@ in filterConfig = mkOption { type = types.lines; - default = ''noop {}''; + default = ""; description = "logstash filter configuration."; example = '' if [type] == "syslog" { @@ -108,11 +108,11 @@ in outputConfig = mkOption { type = types.lines; - default = ''stdout { debug => true debug_format => "json"}''; + default = ''stdout { codec => rubydebug }''; description = "Logstash output configuration."; example = '' - redis { host => "localhost" data_type => "list" key => "logstash" codec => json } - elasticsearch { embedded => true } + redis { host => ["localhost"] data_type => "list" key => "logstash" codec => json } + elasticsearch { } ''; }; @@ -147,7 +147,7 @@ in ${cfg.outputConfig} } ''} " + - ops cfg.enableWeb "-- web -a ${cfg.address} -p ${cfg.port}"; + ops cfg.enableWeb "-- web -a ${cfg.listenAddress} -p ${cfg.port}"; }; }; }; diff --git a/nixos/modules/services/misc/apache-kafka.nix b/nixos/modules/services/misc/apache-kafka.nix index c856d3294c01..cff053396885 100644 --- a/nixos/modules/services/misc/apache-kafka.nix +++ b/nixos/modules/services/misc/apache-kafka.nix @@ -38,7 +38,7 @@ in { brokerId = mkOption { description = "Broker ID."; - default = 0; + default = -1; type = types.int; }; diff --git a/nixos/modules/services/monitoring/vnstat.nix b/nixos/modules/services/monitoring/vnstat.nix new file mode 100644 index 000000000000..f6be7c7fd34a --- /dev/null +++ b/nixos/modules/services/monitoring/vnstat.nix @@ -0,0 +1,43 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.vnstat; +in { + options.services.vnstat = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable update of network usage statistics via vnstatd. + ''; + }; + }; + + config = mkIf cfg.enable { + users.extraUsers.vnstatd = { + isSystemUser = true; + description = "vnstat daemon user"; + home = "/var/lib/vnstat"; + createHome = true; + }; + + systemd.services.vnstat = { + description = "vnStat network traffic monitor"; + path = [ pkgs.coreutils ]; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + unitConfig.documentation = "man:vnstatd(1) man:vnstat(1) man:vnstat.conf(5)"; + preStart = "chmod 755 /var/lib/vnstat"; + serviceConfig = { + ExecStart = "${pkgs.vnstat}/bin/vnstatd -n"; + ExecReload = "kill -HUP $MAINPID"; + ProtectHome = true; + PrivateDevices = true; + PrivateTmp = true; + User = "vnstatd"; + }; + }; + }; +} diff --git a/nixos/modules/services/network-filesystems/tahoe.nix b/nixos/modules/services/network-filesystems/tahoe.nix index ab9eac3829fb..f63f641d00be 100644 --- a/nixos/modules/services/network-filesystems/tahoe.nix +++ b/nixos/modules/services/network-filesystems/tahoe.nix @@ -343,7 +343,7 @@ in preStart = '' if [ \! -d ${nodedir} ]; then mkdir -p /var/db/tahoe-lafs - tahoe create-node ${nodedir} + tahoe create-node --hostname=localhost ${nodedir} fi # Tahoe has created a predefined tahoe.cfg which we must now diff --git a/nixos/modules/services/networking/dnscrypt-wrapper.nix b/nixos/modules/services/networking/dnscrypt-wrapper.nix new file mode 100644 index 000000000000..85fac660d52e --- /dev/null +++ b/nixos/modules/services/networking/dnscrypt-wrapper.nix @@ -0,0 +1,187 @@ +{ config, lib, pkgs, ... }: +with lib; + +let + cfg = config.services.dnscrypt-wrapper; + dataDir = "/var/lib/dnscrypt-wrapper"; + + daemonArgs = with cfg; [ + "--listen-address=${address}:${toString port}" + "--resolver-address=${upstream.address}:${toString upstream.port}" + "--provider-name=${providerName}" + "--provider-publickey-file=public.key" + "--provider-secretkey-file=secret.key" + "--provider-cert-file=${providerName}.crt" + "--crypt-secretkey-file=${providerName}.key" + ]; + + genKeys = '' + # generates time-limited keypairs + keyGen() { + dnscrypt-wrapper --gen-crypt-keypair \ + --crypt-secretkey-file=${cfg.providerName}.key + + dnscrypt-wrapper --gen-cert-file \ + --crypt-secretkey-file=${cfg.providerName}.key \ + --provider-cert-file=${cfg.providerName}.crt \ + --provider-publickey-file=public.key \ + --provider-secretkey-file=secret.key \ + --cert-file-expire-days=${toString cfg.keys.expiration} + } + + cd ${dataDir} + + # generate provider keypair (first run only) + if [ ! -f public.key ] || [ ! -f secret.key ]; then + dnscrypt-wrapper --gen-provider-keypair + fi + + # generate new keys for rotation + if [ ! -f ${cfg.providerName}.key ] || [ ! -f ${cfg.providerName}.crt ]; then + keyGen + fi + ''; + + rotateKeys = '' + # check if keys are not expired + keyValid() { + fingerprint=$(dnscrypt-wrapper --show-provider-publickey-fingerprint | awk '{print $(NF)}') + dnscrypt-proxy --test=${toString (cfg.keys.checkInterval + 1)} \ + --resolver-address=127.0.0.1:${toString cfg.port} \ + --provider-name=${cfg.providerName} \ + --provider-key=$fingerprint + } + + cd ${dataDir} + + # archive old keys and restart the service + if ! keyValid; then + mkdir -p oldkeys + mv ${cfg.providerName}.key oldkeys/${cfg.providerName}-$(date +%F-%T).key + mv ${cfg.providerName}.crt oldkeys/${cfg.providerName}-$(date +%F-%T).crt + systemctl restart dnscrypt-wrapper + fi + ''; + +in { + + + ###### interface + + options.services.dnscrypt-wrapper = { + enable = mkEnableOption "DNSCrypt wrapper"; + + address = mkOption { + type = types.str; + default = "127.0.0.1"; + description = '' + The DNSCrypt wrapper will bind to this IP address. + ''; + }; + + port = mkOption { + type = types.int; + default = 5353; + description = '' + The DNSCrypt wrapper will listen for DNS queries on this port. + ''; + }; + + providerName = mkOption { + type = types.str; + default = "2.dnscrypt-cert.${config.networking.hostName}"; + example = "2.dnscrypt-cert.myresolver"; + description = '' + The name that will be given to this DNSCrypt resolver. + Note: the resolver name must start with <literal>2.dnscrypt-cert.</literal>. + ''; + }; + + upstream.address = mkOption { + type = types.str; + default = "127.0.0.1"; + description = '' + The IP address of the upstream DNS server DNSCrypt will "wrap". + ''; + }; + + upstream.port = mkOption { + type = types.int; + default = 53; + description = '' + The port of the upstream DNS server DNSCrypt will "wrap". + ''; + }; + + keys.expiration = mkOption { + type = types.int; + default = 30; + description = '' + The duration (in days) of the time-limited secret key. + This will be automatically rotated before expiration. + ''; + }; + + keys.checkInterval = mkOption { + type = types.int; + default = 1440; + description = '' + The time interval (in minutes) between key expiration checks. + ''; + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + users.users.dnscrypt-wrapper = { + description = "dnscrypt-wrapper daemon user"; + home = "${dataDir}"; + createHome = true; + }; + users.groups.dnscrypt-wrapper = { }; + + + systemd.services.dnscrypt-wrapper = { + description = "dnscrypt-wrapper daemon"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + path = [ pkgs.dnscrypt-wrapper ]; + + serviceConfig = { + User = "dnscrypt-wrapper"; + WorkingDirectory = dataDir; + Restart = "on-failure"; + ExecStart = "${pkgs.dnscrypt-wrapper}/bin/dnscrypt-wrapper ${toString daemonArgs}"; + }; + + preStart = genKeys; + }; + + + systemd.services.dnscrypt-wrapper-rotate = { + after = [ "network.target" ]; + requires = [ "dnscrypt-wrapper.service" ]; + description = "Rotates DNSCrypt wrapper keys if soon to expire"; + + path = with pkgs; [ dnscrypt-wrapper dnscrypt-proxy gawk ]; + script = rotateKeys; + }; + + + systemd.timers.dnscrypt-wrapper-rotate = { + description = "Periodically check DNSCrypt wrapper keys for expiration"; + wantedBy = [ "multi-user.target" ]; + + timerConfig = { + Unit = "dnscrypt-wrapper-rotate.service"; + OnBootSec = "1min"; + OnUnitActiveSec = cfg.keys.checkInterval * 60; + }; + }; + + }; +} diff --git a/nixos/modules/services/networking/firewall.nix b/nixos/modules/services/networking/firewall.nix index c251b52e03fd..34b731ad35c9 100644 --- a/nixos/modules/services/networking/firewall.nix +++ b/nixos/modules/services/networking/firewall.nix @@ -41,7 +41,6 @@ let kernelPackages = config.boot.kernelPackages; kernelHasRPFilter = kernelPackages.kernel.features.netfilterRPFilter or false; - kernelCanDisableHelpers = kernelPackages.kernel.features.canDisableNetfilterConntrackHelpers or false; helpers = '' @@ -426,7 +425,7 @@ in networking.firewall.connectionTrackingModules = mkOption { type = types.listOf types.str; - default = [ "ftp" ]; + default = [ ]; example = [ "ftp" "irc" "sane" "sip" "tftp" "amanda" "h323" "netbios_sn" "pptp" "snmp" ]; description = '' @@ -435,9 +434,11 @@ in As helpers can pose as a security risk, it is advised to set this to an empty list and disable the setting - networking.firewall.autoLoadConntrackHelpers + networking.firewall.autoLoadConntrackHelpers unless you + know what you are doing. Connection tracking is disabled + by default. - Loading of helpers is recommended to be done through the new + Loading of helpers is recommended to be done through the CT target. More info: https://home.regit.org/netfilter-en/secure-use-of-helpers/ ''; @@ -445,7 +446,7 @@ in networking.firewall.autoLoadConntrackHelpers = mkOption { type = types.bool; - default = true; + default = false; description = '' Whether to auto-load connection-tracking helpers. @@ -505,15 +506,14 @@ in environment.systemPackages = [ pkgs.iptables ] ++ cfg.extraPackages; - boot.kernelModules = map (x: "nf_conntrack_${x}") cfg.connectionTrackingModules; - boot.extraModprobeConfig = optionalString (!cfg.autoLoadConntrackHelpers) '' - options nf_conntrack nf_conntrack_helper=0 + boot.kernelModules = (optional cfg.autoLoadConntrackHelpers "nf_conntrack") + ++ map (x: "nf_conntrack_${x}") cfg.connectionTrackingModules; + boot.extraModprobeConfig = optionalString cfg.autoLoadConntrackHelpers '' + options nf_conntrack nf_conntrack_helper=1 ''; assertions = [ { assertion = (cfg.checkReversePath != false) || kernelHasRPFilter; message = "This kernel does not support rpfilter"; } - { assertion = cfg.autoLoadConntrackHelpers || kernelCanDisableHelpers; - message = "This kernel does not support disabling conntrack helpers"; } ]; systemd.services.firewall = { diff --git a/nixos/modules/services/networking/flannel.nix b/nixos/modules/services/networking/flannel.nix index ca47a18bc1f6..b93e28e34efd 100644 --- a/nixos/modules/services/networking/flannel.nix +++ b/nixos/modules/services/networking/flannel.nix @@ -149,6 +149,6 @@ in { serviceConfig.ExecStart = "${cfg.package}/bin/flannel"; }; - services.etcd.enable = mkDefault cfg.etcd.endpoints == ["http://127.0.0.1:2379"]; + services.etcd.enable = mkDefault (cfg.etcd.endpoints == ["http://127.0.0.1:2379"]); }; } diff --git a/nixos/modules/services/networking/kresd.nix b/nixos/modules/services/networking/kresd.nix new file mode 100644 index 000000000000..18e2ab9aebf1 --- /dev/null +++ b/nixos/modules/services/networking/kresd.nix @@ -0,0 +1,119 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.kresd; + package = pkgs.knot-resolver; + + configFile = pkgs.writeText "kresd.conf" cfg.extraConfig; +in + +{ + meta.maintainers = [ maintainers.vcunat /* upstream developer */ ]; + + ###### interface + options.services.kresd = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable knot-resolver domain name server. + DNSSEC validation is turned on by default. + You can run <literal>sudo nc -U /run/kresd/control</literal> + and give commands interactively to kresd. + ''; + }; + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra lines to be added verbatim to the generated configuration file. + ''; + }; + cacheDir = mkOption { + type = types.path; + default = "/var/cache/kresd"; + description = '' + Directory for caches. They are intended to survive reboots. + ''; + }; + interfaces = mkOption { + type = with types; listOf str; + default = [ "::1" "127.0.0.1" ]; + description = '' + What addresses the server should listen on. + ''; + }; + # TODO: perhaps options for more common stuff like cache size or forwarding + }; + + ###### implementation + config = mkIf cfg.enable { + environment.etc."kresd.conf".source = configFile; # not required + + users.extraUsers = singleton + { name = "kresd"; + uid = config.ids.uids.kresd; + group = "kresd"; + description = "Knot-resolver daemon user"; + }; + users.extraGroups = singleton + { name = "kresd"; + gid = config.ids.gids.kresd; + }; + + systemd.sockets.kresd = rec { + wantedBy = [ "sockets.target" ]; + before = wantedBy; + listenStreams = map + # Syntax depends on being IPv6 or IPv4. + (iface: if elem ":" (stringToCharacters iface) then "[${iface}]:53" else "${iface}:53") + cfg.interfaces; + socketConfig.ListenDatagram = listenStreams; + }; + + systemd.sockets.kresd-control = rec { + wantedBy = [ "sockets.target" ]; + before = wantedBy; + partOf = [ "kresd.socket" ]; + listenStreams = [ "/run/kresd/control" ]; + socketConfig = { + FileDescriptorName = "control"; + Service = "kresd.service"; + SocketMode = "0660"; # only root user/group may connect + }; + }; + + # Create the cacheDir; tmpfiles don't work on nixos-rebuild switch. + systemd.services.kresd-cachedir = { + serviceConfig.Type = "oneshot"; + script = '' + if [ ! -d '${cfg.cacheDir}' ]; then + mkdir -p '${cfg.cacheDir}' + chown kresd:kresd '${cfg.cacheDir}' + fi + ''; + }; + + systemd.services.kresd = { + description = "Knot-resolver daemon"; + + serviceConfig = { + User = "kresd"; + Type = "notify"; + WorkingDirectory = cfg.cacheDir; + }; + + script = '' + exec '${package}/bin/kresd' --config '${configFile}' \ + -k '${cfg.cacheDir}/root.key' + ''; + + after = [ "kresd-cachedir.service" ]; + requires = [ "kresd.socket" "kresd-cachedir.service" ]; + wantedBy = [ "sockets.target" ]; + }; + }; +} diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix index 8f353979d3fc..c11d4434c206 100644 --- a/nixos/modules/services/networking/networkmanager.nix +++ b/nixos/modules/services/networking/networkmanager.nix @@ -174,7 +174,7 @@ in { assertions = [{ assertion = config.networking.wireless.enable == false; - message = "You can not use networking.networkmanager with services.networking.wireless"; + message = "You can not use networking.networkmanager with networking.wireless"; }]; boot.kernelModules = [ "ppp_mppe" ]; # Needed for most (all?) PPTP VPN connections. @@ -239,7 +239,8 @@ in { # Turn off NixOS' network management networking = { useDHCP = false; - wireless.enable = false; + # use mkDefault to trigger the assertion about the conflict above + wireless.enable = lib.mkDefault false; }; powerManagement.resumeCommands = '' diff --git a/nixos/modules/services/networking/pdns-recursor.nix b/nixos/modules/services/networking/pdns-recursor.nix new file mode 100644 index 000000000000..26be72d2a61e --- /dev/null +++ b/nixos/modules/services/networking/pdns-recursor.nix @@ -0,0 +1,168 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + dataDir = "/var/lib/pdns-recursor"; + username = "pdns-recursor"; + + cfg = config.services.pdns-recursor; + zones = mapAttrsToList (zone: uri: "${zone}.=${uri}") cfg.forwardZones; + + configFile = pkgs.writeText "recursor.conf" '' + local-address=${cfg.dns.address} + local-port=${toString cfg.dns.port} + allow-from=${concatStringsSep "," cfg.dns.allowFrom} + + webserver-address=${cfg.api.address} + webserver-port=${toString cfg.api.port} + webserver-allow-from=${concatStringsSep "," cfg.api.allowFrom} + + forward-zones=${concatStringsSep "," zones} + export-etc-hosts=${if cfg.exportHosts then "yes" else "no"} + dnssec=${cfg.dnssecValidation} + serve-rfc1918=${if cfg.serveRFC1918 then "yes" else "no"} + + ${cfg.extraConfig} + ''; + +in { + options.services.pdns-recursor = { + enable = mkEnableOption "PowerDNS Recursor, a recursive DNS server"; + + dns.address = mkOption { + type = types.str; + default = "0.0.0.0"; + description = '' + IP address Recursor DNS server will bind to. + ''; + }; + + dns.port = mkOption { + type = types.int; + default = 53; + description = '' + Port number Recursor DNS server will bind to. + ''; + }; + + dns.allowFrom = mkOption { + type = types.listOf types.str; + default = [ "10.0.0.0/8" "172.16.0.0/12" "192.168.0.0/16" ]; + example = [ "0.0.0.0/0" ]; + description = '' + IP address ranges of clients allowed to make DNS queries. + ''; + }; + + api.address = mkOption { + type = types.str; + default = "0.0.0.0"; + description = '' + IP address Recursor REST API server will bind to. + ''; + }; + + api.port = mkOption { + type = types.int; + default = 8082; + description = '' + Port number Recursor REST API server will bind to. + ''; + }; + + api.allowFrom = mkOption { + type = types.listOf types.str; + default = [ "0.0.0.0/0" ]; + description = '' + IP address ranges of clients allowed to make API requests. + ''; + }; + + exportHosts = mkOption { + type = types.bool; + default = false; + description = '' + Whether to export names and IP addresses defined in /etc/hosts. + ''; + }; + + forwardZones = mkOption { + type = types.attrs; + example = { eth = "127.0.0.1:5353"; }; + default = {}; + description = '' + DNS zones to be forwarded to other servers. + ''; + }; + + dnssecValidation = mkOption { + type = types.enum ["off" "process-no-validate" "process" "log-fail" "validate"]; + default = "validate"; + description = '' + Controls the level of DNSSEC processing done by the PowerDNS Recursor. + See https://doc.powerdns.com/md/recursor/dnssec/ for a detailed explanation. + ''; + }; + + serveRFC1918 = mkOption { + type = types.bool; + default = true; + description = '' + Whether to directly resolve the RFC1918 reverse-mapping domains: + <literal>10.in-addr.arpa</literal>, + <literal>168.192.in-addr.arpa</literal>, + <literal>16-31.172.in-addr.arpa</literal> + This saves load on the AS112 servers. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra options to be appended to the configuration file. + ''; + }; + }; + + config = mkIf cfg.enable { + + users.extraUsers."${username}" = { + home = dataDir; + createHome = true; + uid = config.ids.uids.pdns-recursor; + description = "PowerDNS Recursor daemon user"; + }; + + systemd.services.pdns-recursor = { + unitConfig.Documentation = "man:pdns_recursor(1) man:rec_control(1)"; + description = "PowerDNS recursive server"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + serviceConfig = { + User = username; + Restart ="on-failure"; + RestartSec = "5"; + PrivateTmp = true; + PrivateDevices = true; + AmbientCapabilities = "cap_net_bind_service"; + ExecStart = ''${pkgs.pdns-recursor}/bin/pdns_recursor \ + --config-dir=${dataDir} \ + --socket-dir=${dataDir} \ + --disable-syslog + ''; + }; + + preStart = '' + # Link configuration file into recursor home directory + configPath=${dataDir}/recursor.conf + if [ "$(realpath $configPath)" != "${configFile}" ]; then + rm -f $configPath + ln -s ${configFile} $configPath + fi + ''; + }; + }; +} diff --git a/nixos/modules/services/networking/smokeping.nix b/nixos/modules/services/networking/smokeping.nix index 04312c39062f..6648ada0c0de 100644 --- a/nixos/modules/services/networking/smokeping.nix +++ b/nixos/modules/services/networking/smokeping.nix @@ -273,7 +273,7 @@ in message = "services.smokeping: sendmail and Mailhost cannot both be enabled."; } ]; - security.setuidPrograms = [ "fping" ]; + security.setuidPrograms = [ "fping" "fping6" ]; environment.systemPackages = [ pkgs.fping ]; users.extraUsers = singleton { name = cfg.user; diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index 68a672c42c90..c9eacdd85dcd 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -5,7 +5,11 @@ with lib; let cfg = config.services.nginx; virtualHosts = mapAttrs (vhostName: vhostConfig: - vhostConfig // (optionalAttrs vhostConfig.enableACME { + vhostConfig // { + serverName = if vhostConfig.serverName != null + then vhostConfig.serverName + else vhostName; + } // (optionalAttrs vhostConfig.enableACME { sslCertificate = "/var/lib/acme/${vhostName}/fullchain.pem"; sslCertificateKey = "/var/lib/acme/${vhostName}/key.pem"; }) @@ -112,8 +116,9 @@ let ${cfg.appendConfig} ''; - vhosts = concatStringsSep "\n" (mapAttrsToList (serverName: vhost: + vhosts = concatStringsSep "\n" (mapAttrsToList (vhostName: vhost: let + serverName = vhost.serverName; ssl = vhost.enableSSL || vhost.forceSSL; port = if vhost.port != null then vhost.port else (if ssl then 443 else 80); listenString = toString port + optionalString ssl " ssl http2" @@ -161,7 +166,7 @@ let ssl_certificate_key ${vhost.sslCertificateKey}; ''} - ${optionalString (vhost.basicAuth != {}) (mkBasicAuth serverName vhost.basicAuth)} + ${optionalString (vhost.basicAuth != {}) (mkBasicAuth vhostName vhost.basicAuth)} ${mkLocations vhost.locations} @@ -178,8 +183,8 @@ let ${config.extraConfig} } '') locations); - mkBasicAuth = serverName: authDef: let - htpasswdFile = pkgs.writeText "${serverName}.htpasswd" ( + mkBasicAuth = vhostName: authDef: let + htpasswdFile = pkgs.writeText "${vhostName}.htpasswd" ( concatStringsSep "\n" (mapAttrsToList (user: password: '' ${user}:{PLAIN}${password} '') authDef) @@ -393,17 +398,20 @@ in }; security.acme.certs = filterAttrs (n: v: v != {}) ( - mapAttrs (vhostName: vhostConfig: - optionalAttrs vhostConfig.enableACME { - user = cfg.user; - group = cfg.group; - webroot = vhostConfig.acmeRoot; - extraDomains = genAttrs vhostConfig.serverAliases (alias: null); - postRun = '' - systemctl reload nginx - ''; - } - ) virtualHosts + let + vhostsConfigs = mapAttrsToList (vhostName: vhostConfig: vhostConfig) virtualHosts; + acmeEnabledVhosts = filter (vhostConfig: vhostConfig.enableACME) vhostsConfigs; + acmePairs = map (vhostConfig: { name = vhostConfig.serverName; value = { + user = cfg.user; + group = cfg.group; + webroot = vhostConfig.acmeRoot; + extraDomains = genAttrs vhostConfig.serverAliases (alias: null); + postRun = '' + systemctl reload nginx + ''; + }; }) acmeEnabledVhosts; + in + listToAttrs acmePairs ); users.extraUsers = optionalAttrs (cfg.user == "nginx") (singleton diff --git a/nixos/modules/services/web-servers/nginx/vhost-options.nix b/nixos/modules/services/web-servers/nginx/vhost-options.nix index dcebbc9229fc..c0ea645b3dfe 100644 --- a/nixos/modules/services/web-servers/nginx/vhost-options.nix +++ b/nixos/modules/services/web-servers/nginx/vhost-options.nix @@ -8,6 +8,15 @@ with lib; { options = { + serverName = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Name of this virtual host. Defaults to attribute name in virtualHosts. + ''; + example = "example.org"; + }; + serverAliases = mkOption { type = types.listOf types.str; default = []; diff --git a/nixos/modules/services/x11/desktop-managers/kde5.nix b/nixos/modules/services/x11/desktop-managers/kde5.nix index ee4ec0fc819f..8f081a1e9d2a 100644 --- a/nixos/modules/services/x11/desktop-managers/kde5.nix +++ b/nixos/modules/services/x11/desktop-managers/kde5.nix @@ -249,6 +249,11 @@ in security.pam.services.kde = { allowNullPassword = true; }; + # use kimpanel as the default IBus panel + i18n.inputMethod.ibus.panel = + lib.mkDefault + "${pkgs.kde5.plasma-desktop}/lib/libexec/kimpanel-ibus-panel"; + }) ]; |