diff options
Diffstat (limited to 'nixos/modules')
23 files changed, 967 insertions, 231 deletions
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index 6ec3c1a112dd..859838182ed4 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -335,7 +335,7 @@ dialout = 27; #polkituser = 28; # currently unused, polkitd doesn't need a group utmp = 29; - #ddclient = 30; # unused + ddclient = 30; davfs2 = 31; disnix = 33; osgi = 34; diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 1da1ea5ae115..1bb950ca7d65 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -165,6 +165,7 @@ ./services/continuous-integration/buildbot/master.nix ./services/continuous-integration/buildbot/worker.nix ./services/continuous-integration/buildkite-agent.nix + ./services/continuous-integration/hail.nix ./services/continuous-integration/hydra/default.nix ./services/continuous-integration/gitlab-runner.nix ./services/continuous-integration/gocd-agent/default.nix @@ -185,6 +186,7 @@ ./services/databases/neo4j.nix ./services/databases/openldap.nix ./services/databases/opentsdb.nix + ./services/databases/postage.nix ./services/databases/postgresql.nix ./services/databases/redis.nix ./services/databases/riak.nix @@ -555,6 +557,7 @@ ./services/security/oauth2_proxy.nix ./services/security/physlock.nix ./services/security/shibboleth-sp.nix + ./services/security/sks.nix ./services/security/sshguard.nix ./services/security/tor.nix ./services/security/torify.nix @@ -582,6 +585,7 @@ ./services/web-apps/frab.nix ./services/web-apps/mattermost.nix ./services/web-apps/nixbot.nix + ./services/web-apps/pgpkeyserver-lite.nix ./services/web-apps/piwik.nix ./services/web-apps/pump.io.nix ./services/web-apps/tt-rss.nix diff --git a/nixos/modules/profiles/hardened.nix b/nixos/modules/profiles/hardened.nix index 0a0838431da7..0ab210cc4c39 100644 --- a/nixos/modules/profiles/hardened.nix +++ b/nixos/modules/profiles/hardened.nix @@ -59,4 +59,10 @@ with lib; # the feature at runtime. Attempting to create a user namespace # with unshare will then fail with "no space left on device". boot.kernel.sysctl."user.max_user_namespaces" = mkDefault 0; + + # Raise ASLR entropy for 64bit & 32bit, respectively. + # + # Note: mmap_rnd_compat_bits may not exist on 64bit. + boot.kernel.sysctl."vm.mmap_rnd_bits" = mkDefault 32; + boot.kernel.sysctl."vm.mmap_rnd_compat_bits" = mkDefault 16; } diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix index 08146d1f5687..2079ed544aee 100644 --- a/nixos/modules/rename.nix +++ b/nixos/modules/rename.nix @@ -25,6 +25,7 @@ with lib; (mkRenamedOptionModule [ "services" "sslh" "host" ] [ "services" "sslh" "listenAddress" ]) (mkRenamedOptionModule [ "services" "statsd" "host" ] [ "services" "statsd" "listenAddress" ]) (mkRenamedOptionModule [ "services" "subsonic" "host" ] [ "services" "subsonic" "listenAddress" ]) + (mkRenamedOptionModule [ "services" "tor" "relay" "portSpec" ] [ "services" "tor" "relay" "port" ]) (mkRenamedOptionModule [ "jobs" ] [ "systemd" "services" ]) (mkRenamedOptionModule [ "services" "gitlab" "stateDir" ] [ "services" "gitlab" "statePath" ]) @@ -195,6 +196,8 @@ with lib; (mkRemovedOptionModule [ "services" "openvpn" "enable" ] "") (mkRemovedOptionModule [ "services" "printing" "cupsFilesConf" ] "") (mkRemovedOptionModule [ "services" "printing" "cupsdConf" ] "") + (mkRemovedOptionModule [ "services" "tor" "relay" "isBridge" ] "Use services.tor.relay.role instead.") + (mkRemovedOptionModule [ "services" "tor" "relay" "isExit" ] "Use services.tor.relay.role instead.") (mkRemovedOptionModule [ "services" "xserver" "startGnuPGAgent" ] "See the 16.09 release notes for more information.") (mkRemovedOptionModule [ "services" "phpfpm" "phpIni" ] "") diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix index 5632500df2e0..ede4ace5ed03 100644 --- a/nixos/modules/security/pam.nix +++ b/nixos/modules/security/pam.nix @@ -281,7 +281,7 @@ let "auth optional ${pkgs.pam_mount}/lib/security/pam_mount.so"} ${optionalString cfg.enableKwallet ("auth optional ${pkgs.plasma5.kwallet-pam}/lib/security/pam_kwallet5.so" + - " kwalletd=${pkgs.libsForQt5.kwallet}/bin/kwalletd5")} + " kwalletd=${pkgs.libsForQt5.kwallet.bin}/bin/kwalletd5")} '') + '' ${optionalString cfg.unixAuth "auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} likeauth try_first_pass"} @@ -350,7 +350,7 @@ let "session optional ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so order=user,group,default debug"} ${optionalString (cfg.enableKwallet) ("session optional ${pkgs.plasma5.kwallet-pam}/lib/security/pam_kwallet5.so" + - " kwalletd=${pkgs.libsForQt5.kwallet}/bin/kwalletd5")} + " kwalletd=${pkgs.libsForQt5.kwallet.bin}/bin/kwalletd5")} ''); }; diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix index bd6c316243c8..5f379b392ea8 100644 --- a/nixos/modules/services/audio/mpd.nix +++ b/nixos/modules/services/audio/mpd.nix @@ -10,11 +10,9 @@ let gid = config.ids.gids.mpd; cfg = config.services.mpd; - playlistDir = "${cfg.dataDir}/playlists"; - mpdConf = pkgs.writeText "mpd.conf" '' music_directory "${cfg.musicDirectory}" - playlist_directory "${playlistDir}" + playlist_directory "${cfg.playlistDirectory}" db_file "${cfg.dbFile}" state_file "${cfg.dataDir}/state" sticker_file "${cfg.dataDir}/sticker.sql" @@ -57,11 +55,21 @@ in { musicDirectory = mkOption { type = types.path; default = "${cfg.dataDir}/music"; + defaultText = ''''${dataDir}/music''; description = '' The directory where mpd reads music from. ''; }; + playlistDirectory = mkOption { + type = types.path; + default = "${cfg.dataDir}/playlists"; + defaultText = ''''${dataDir}/playlists''; + description = '' + The directory where mpd stores playlists. + ''; + }; + extraConfig = mkOption { type = types.lines; default = ""; @@ -120,6 +128,7 @@ in { dbFile = mkOption { type = types.str; default = "${cfg.dataDir}/tag_cache"; + defaultText = ''''${dataDir}/tag_cache''; description = '' The path to MPD's database. ''; @@ -153,7 +162,7 @@ in { preStart = '' mkdir -p "${cfg.dataDir}" && chown -R ${cfg.user}:${cfg.group} "${cfg.dataDir}" - mkdir -p "${playlistDir}" && chown -R ${cfg.user}:${cfg.group} "${playlistDir}" + mkdir -p "${cfg.playlistDirectory}" && chown -R ${cfg.user}:${cfg.group} "${cfg.playlistDirectory}" ''; serviceConfig = { User = "${cfg.user}"; diff --git a/nixos/modules/services/continuous-integration/gitlab-runner.nix b/nixos/modules/services/continuous-integration/gitlab-runner.nix index b11bc031b3ff..ce0583dad54d 100644 --- a/nixos/modules/services/continuous-integration/gitlab-runner.nix +++ b/nixos/modules/services/continuous-integration/gitlab-runner.nix @@ -4,15 +4,65 @@ with lib; let cfg = config.services.gitlab-runner; - configFile = pkgs.writeText "config.toml" cfg.configText; + configFile = + if (cfg.configFile == null) then + (pkgs.runCommand "config.toml" { + buildInputs = [ pkgs.remarshal ]; + } '' + remarshal -if json -of toml \ + < ${pkgs.writeText "config.json" (builtins.toJSON cfg.configOptions)} \ + > $out + '') + else + cfg.configFile; hasDocker = config.virtualisation.docker.enable; in { options.services.gitlab-runner = { enable = mkEnableOption "Gitlab Runner"; - configText = mkOption { - description = "Verbatim config.toml to use"; + configFile = mkOption { + default = null; + description = '' + Configuration file for gitlab-runner. + Use this option in favor of configOptions to avoid placing CI tokens in the nix store. + + <option>configFile</option> takes precedence over <option>configOptions</option>. + + Warning: Not using <option>configFile</option> will potentially result in secrets + leaking into the WORLD-READABLE nix store. + ''; + type = types.nullOr types.path; + }; + + configOptions = mkOption { + description = '' + Configuration for gitlab-runner + <option>configFile</option> will take precedence over this option. + + Warning: all Configuration, especially CI token, will be stored in a + WORLD-READABLE file in the Nix Store. + + If you want to protect your CI token use <option>configFile</option> instead. + ''; + type = types.attrs; + example = { + concurrent = 2; + runners = [{ + name = "docker-nix-1.11"; + url = "https://CI/"; + token = "TOKEN"; + executor = "docker"; + builds_dir = ""; + docker = { + host = ""; + image = "nixos/nix:1.11"; + privileged = true; + disable_cache = true; + cache_dir = ""; + }; + }]; + }; }; gracefulTermination = mkOption { diff --git a/nixos/modules/services/continuous-integration/hail.nix b/nixos/modules/services/continuous-integration/hail.nix new file mode 100644 index 000000000000..5d0c3f7b4ab3 --- /dev/null +++ b/nixos/modules/services/continuous-integration/hail.nix @@ -0,0 +1,61 @@ +{ config, lib, pkgs, ...}: + +with lib; + +let + cfg = config.services.hail; +in { + + + ###### interface + + options.services.hail = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enables the Hail Auto Update Service. Hail can automatically deploy artifacts + built by a Hydra Continous Integration server. A common use case is to provide + continous deployment for single services or a full NixOS configuration.''; + }; + profile = mkOption { + type = types.str; + default = "hail-profile"; + description = "The name of the Nix profile used by Hail."; + }; + hydraJobUri = mkOption { + type = types.str; + description = "The URI of the Hydra Job."; + }; + netrc = mkOption { + type = types.nullOr types.path; + description = "The netrc file to use when fetching data from Hydra."; + default = null; + }; + package = mkOption { + type = types.package; + default = pkgs.haskellPackages.hail; + defaultText = "pkgs.haskellPackages.hail"; + description = "Hail package to use."; + }; + }; + + + ###### implementation + + config = mkIf cfg.enable { + systemd.services.hail = { + description = "Hail Auto Update Service"; + wants = [ "network-online.target" ]; + wantedBy = [ "multi-user.target" ]; + path = with pkgs; [ nix ]; + environment = { + HOME = "/var/lib/empty"; + }; + serviceConfig = { + ExecStart = "${cfg.package}/bin/hail --profile ${cfg.profile} --job-uri ${cfg.hydraJobUri}" + + lib.optionalString (cfg.netrc != null) " --netrc-file ${cfg.netrc}"; + }; + }; + }; +} diff --git a/nixos/modules/services/databases/postage.nix b/nixos/modules/services/databases/postage.nix new file mode 100644 index 000000000000..d49c9a83a46f --- /dev/null +++ b/nixos/modules/services/databases/postage.nix @@ -0,0 +1,205 @@ +{ lib, pkgs, config, ... } : + +with lib; + +let + cfg = config.services.postage; + + confFile = pkgs.writeTextFile { + name = "postage.conf"; + text = '' + connection_file = ${postageConnectionsFile} + + allow_custom_connections = ${builtins.toJSON cfg.allowCustomConnections} + + postage_port = ${toString cfg.port} + + super_only = ${builtins.toJSON cfg.superOnly} + + ${optionalString (!isNull cfg.loginGroup) "login_group = ${cfg.loginGroup}"} + + login_timeout = ${toString cfg.loginTimeout} + + web_root = ${cfg.package}/etc/postage/web_root + + data_root = ${cfg.dataRoot} + + ${optionalString (!isNull cfg.tls) '' + tls_cert = ${cfg.tls.cert} + tls_key = ${cfg.tls.key} + ''} + + log_level = ${cfg.logLevel} + ''; + }; + + postageConnectionsFile = pkgs.writeTextFile { + name = "postage-connections.conf"; + text = concatStringsSep "\n" + (mapAttrsToList (name : conn : "${name}: ${conn}") cfg.connections); + }; + + postage = "postage"; +in { + + options.services.postage = { + enable = mkEnableOption "PostgreSQL Administration for the web"; + + package = mkOption { + type = types.package; + default = pkgs.postage; + defaultText = "pkgs.postage"; + description = '' + The postage package to use. + ''; + }; + + connections = mkOption { + type = types.attrsOf types.str; + default = {}; + example = { + "nuc-server" = "hostaddr=192.168.0.100 port=5432 dbname=postgres"; + "mini-server" = "hostaddr=127.0.0.1 port=5432 dbname=postgres sslmode=require"; + }; + description = '' + Postage requires at least one PostgreSQL server be defined. + </para><para> + Detailed information about PostgreSQL connection strings is available at: + <link xlink:href="http://www.postgresql.org/docs/current/static/libpq-connect.html"/> + </para><para> + Note that you should not specify your user name or password. That + information will be entered on the login screen. If you specify a + username or password, it will be removed by Postage before attempting to + connect to a database. + ''; + }; + + allowCustomConnections = mkOption { + type = types.bool; + default = false; + description = '' + This tells Postage whether or not to allow anyone to use a custom + connection from the login screen. + ''; + }; + + port = mkOption { + type = types.int; + default = 8080; + description = '' + This tells Postage what port to listen on for browser requests. + ''; + }; + + localOnly = mkOption { + type = types.bool; + default = true; + description = '' + This tells Postage whether or not to set the listening socket to local + addresses only. + ''; + }; + + superOnly = mkOption { + type = types.bool; + default = true; + description = '' + This tells Postage whether or not to only allow super users to + login. The recommended value is true and will restrict users who are not + super users from logging in to any PostgreSQL instance through + Postage. Note that a connection will be made to PostgreSQL in order to + test if the user is a superuser. + ''; + }; + + loginGroup = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + This tells Postage to only allow users in a certain PostgreSQL group to + login to Postage. Note that a connection will be made to PostgreSQL in + order to test if the user is a member of the login group. + ''; + }; + + loginTimeout = mkOption { + type = types.int; + default = 3600; + description = '' + Number of seconds of inactivity before user is automatically logged + out. + ''; + }; + + dataRoot = mkOption { + type = types.str; + default = "/var/lib/postage"; + description = '' + This tells Postage where to put the SQL file history. All tabs are saved + to this location so that if you get disconnected from Postage you + don't lose your work. + ''; + }; + + tls = mkOption { + type = types.nullOr (types.submodule { + options = { + cert = mkOption { + type = types.str; + description = "TLS certificate"; + }; + key = mkOption { + type = types.str; + description = "TLS key"; + }; + }; + }); + default = null; + description = '' + These options tell Postage where the TLS Certificate and Key files + reside. If you use these options then you'll only be able to access + Postage through a secure TLS connection. These options are only + necessary if you wish to connect directly to Postage using a secure TLS + connection. As an alternative, you can set up Postage in a reverse proxy + configuration. This allows your web server to terminate the secure + connection and pass on the request to Postage. You can find help to set + up this configuration in: + <link xlink:href="https://github.com/workflowproducts/postage/blob/master/INSTALL_NGINX.md"/> + ''; + }; + + logLevel = mkOption { + type = types.enum ["error" "warn" "notice" "info"]; + default = "error"; + description = '' + Verbosity of logs + ''; + }; + }; + + config = mkIf cfg.enable { + systemd.services.postage = { + description = "postage - PostgreSQL Administration for the web"; + wants = [ "postgresql.service" ]; + after = [ "postgresql.service" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + User = postage; + Group = postage; + ExecStart = "${pkgs.postage}/sbin/postage -c ${confFile}" + + optionalString cfg.localOnly " --local-only=true"; + }; + }; + users = { + users."${postage}" = { + name = postage; + group = postage; + home = cfg.dataRoot; + createHome = true; + }; + groups."${postage}" = { + name = postage; + }; + }; + }; +} diff --git a/nixos/modules/services/editors/emacs.xml b/nixos/modules/services/editors/emacs.xml index 9d6395ebd74c..dd66bac442c6 100644 --- a/nixos/modules/services/editors/emacs.xml +++ b/nixos/modules/services/editors/emacs.xml @@ -24,7 +24,7 @@ <para> Emacs runs within a graphical desktop environment using the X Window System, but works equally well on a text terminal. Under - <productname>OS X</productname>, a "Mac port" edition is + <productname>macOS</productname>, a "Mac port" edition is available, which uses Apple's native GUI frameworks. </para> @@ -84,7 +84,7 @@ <listitem> <para> Emacs 25 with the "Mac port" patches, providing a more - native look and feel under OS X. + native look and feel under macOS. </para> </listitem> </varlistentry> diff --git a/nixos/modules/services/monitoring/munin.nix b/nixos/modules/services/monitoring/munin.nix index b26bcba64059..723b04dc0fe9 100644 --- a/nixos/modules/services/monitoring/munin.nix +++ b/nixos/modules/services/monitoring/munin.nix @@ -26,7 +26,9 @@ let for file in $out/*; do case "$file" in - plugin.sh) continue;; + */plugin.sh|*/plugins.history) + chmod +x "$file" + continue;; esac # read magic makers from the file diff --git a/nixos/modules/services/monitoring/prometheus/unifi-exporter.nix b/nixos/modules/services/monitoring/prometheus/unifi-exporter.nix index e3059e485098..0a56d6ae95a5 100644 --- a/nixos/modules/services/monitoring/prometheus/unifi-exporter.nix +++ b/nixos/modules/services/monitoring/prometheus/unifi-exporter.nix @@ -83,6 +83,7 @@ in { description = "Prometheus exporter for UniFi Controller metrics"; unitConfig.Documentation = "https://github.com/mdlayher/unifi_exporter"; wantedBy = [ "multi-user.target" ]; + after = optional config.services.unifi.enable "unifi.service"; serviceConfig = { User = "nobody"; Restart = "always"; diff --git a/nixos/modules/services/network-filesystems/ipfs.nix b/nixos/modules/services/network-filesystems/ipfs.nix index 10c1d751ac5d..60822b5b547f 100644 --- a/nixos/modules/services/network-filesystems/ipfs.nix +++ b/nixos/modules/services/network-filesystems/ipfs.nix @@ -49,6 +49,12 @@ in description = "The data dir for IPFS"; }; + defaultMode = mkOption { + description = "systemd service that is enabled by default"; + type = types.enum [ "online" "offline" "norouting" ]; + default = "online"; + }; + autoMigrate = mkOption { type = types.bool; default = false; @@ -147,10 +153,11 @@ in systemd.services.ipfs = { description = "IPFS Daemon"; - wantedBy = [ "multi-user.target" ]; + wantedBy = mkIf (cfg.defaultMode == "online") [ "multi-user.target" ]; + after = [ "network.target" "local-fs.target" "ipfs-init.service" ]; - conflicts = [ "ipfs-offline.service" ]; + conflicts = [ "ipfs-offline.service" "ipfs-norouting.service"]; wants = [ "ipfs-init.service" ]; environment.IPFS_PATH = cfg.dataDir; @@ -169,9 +176,11 @@ in systemd.services.ipfs-offline = { description = "IPFS Daemon (offline mode)"; + wantedBy = mkIf (cfg.defaultMode == "offline") [ "multi-user.target" ]; + after = [ "local-fs.target" "ipfs-init.service" ]; - conflicts = [ "ipfs.service" ]; + conflicts = [ "ipfs.service" "ipfs-norouting.service"]; wants = [ "ipfs-init.service" ]; environment.IPFS_PATH = cfg.dataDir; @@ -186,5 +195,29 @@ in RestartSec = 1; }; }; + + systemd.services.ipfs-norouting = { + description = "IPFS Daemon (no routing mode)"; + + wantedBy = mkIf (cfg.defaultMode == "norouting") [ "multi-user.target" ]; + + after = [ "local-fs.target" "ipfs-init.service" ]; + + conflicts = [ "ipfs.service" "ipfs-offline.service"]; + wants = [ "ipfs-init.service" ]; + + environment.IPFS_PATH = cfg.dataDir; + + path = [ pkgs.ipfs ]; + + serviceConfig = { + ExecStart = "${ipfs}/bin/ipfs daemon ${ipfsFlags} --routing=none"; + User = cfg.user; + Group = cfg.group; + Restart = "on-failure"; + RestartSec = 1; + }; + }; + }; } diff --git a/nixos/modules/services/networking/ddclient.nix b/nixos/modules/services/networking/ddclient.nix index 28c96a9baefc..9e56545f746c 100644 --- a/nixos/modules/services/networking/ddclient.nix +++ b/nixos/modules/services/networking/ddclient.nix @@ -1,17 +1,33 @@ { config, pkgs, lib, ... }: let - - inherit (lib) mkOption mkIf singleton; - inherit (pkgs) ddclient; - - stateDir = "/var/spool/ddclient"; - ddclientUser = "ddclient"; - ddclientFlags = "-foreground -file ${config.services.ddclient.configFile}"; - ddclientPIDFile = "${stateDir}/ddclient.pid"; + cfg = config.services.ddclient; + boolToStr = bool: if bool then "yes" else "no"; + + configText = '' + # This file can be used as a template for configFile or is automatically generated by Nix options. + daemon=${toString cfg.interval} + cache=${cfg.homeDir}/ddclient.cache + pid=/run/ddclient/ddclient.pid + foreground=NO + use=${cfg.use} + login=${cfg.username} + password=${cfg.password} + protocol=${cfg.protocol} + ${let server = cfg.server; in + lib.optionalString (server != "") "server=${server}"} + ssl=${boolToStr cfg.ssl} + wildcard=YES + quiet=${boolToStr cfg.quiet} + verbose=${boolToStr cfg.verbose} + ${cfg.domain} + ${cfg.extraConfig} + ''; in +with lib; + { ###### interface @@ -28,6 +44,12 @@ in ''; }; + homeDir = mkOption { + default = "/var/lib/ddclient"; + type = str; + description = "Home directory for the daemon user."; + }; + domain = mkOption { default = ""; type = str; @@ -52,6 +74,12 @@ in ''; }; + interval = mkOption { + default = 600; + type = int; + description = "The interval at which to run the check and update."; + }; + configFile = mkOption { default = "/etc/ddclient.conf"; type = path; @@ -126,37 +154,24 @@ in config = mkIf config.services.ddclient.enable { - environment.systemPackages = [ ddclient ]; + users = { + extraGroups.ddclient.gid = config.ids.gids.ddclient; - users.extraUsers = singleton { - name = ddclientUser; - uid = config.ids.uids.ddclient; - description = "ddclient daemon user"; - home = stateDir; + extraUsers.ddclient = { + uid = config.ids.uids.ddclient; + description = "ddclient daemon user"; + group = "ddclient"; + home = cfg.homeDir; + createHome = true; + }; }; environment.etc."ddclient.conf" = { - enable = config.services.ddclient.configFile == "/etc/ddclient.conf"; + enable = cfg.configFile == "/etc/ddclient.conf"; uid = config.ids.uids.ddclient; + gid = config.ids.gids.ddclient; mode = "0600"; - text = '' - # This file can be used as a template for configFile or is automatically generated by Nix options. - daemon=600 - cache=${stateDir}/ddclient.cache - pid=${ddclientPIDFile} - use=${config.services.ddclient.use} - login=${config.services.ddclient.username} - password=${config.services.ddclient.password} - protocol=${config.services.ddclient.protocol} - ${let server = config.services.ddclient.server; in - lib.optionalString (server != "") "server=${server}"} - ssl=${if config.services.ddclient.ssl then "yes" else "no"} - wildcard=YES - quiet=${if config.services.ddclient.quiet then "yes" else "no"} - verbose=${if config.services.ddclient.verbose then "yes" else "no"} - ${config.services.ddclient.domain} - ${config.services.ddclient.extraConfig} - ''; + text = configText; }; systemd.services.ddclient = { @@ -166,17 +181,14 @@ in restartTriggers = [ config.environment.etc."ddclient.conf".source ]; serviceConfig = { - # Uncomment this if too many problems occur: - # Type = "forking"; - User = ddclientUser; - Group = "nogroup"; #TODO get this to work - PermissionsStartOnly = "true"; - PIDFile = ddclientPIDFile; - ExecStartPre = '' - ${pkgs.stdenv.shell} -c "${pkgs.coreutils}/bin/mkdir -m 0755 -p ${stateDir} && ${pkgs.coreutils}/bin/chown ${ddclientUser} ${stateDir}" - ''; - ExecStart = "${ddclient}/bin/ddclient ${ddclientFlags}"; - #ExecStartPost = "${pkgs.coreutils}/bin/rm -r ${stateDir}"; # Should we have this? + RuntimeDirectory = "ddclient"; + # we cannot run in forking mode as it swallows all the program output + Type = "simple"; + User = "ddclient"; + Group = "ddclient"; + ExecStart = "${lib.getBin pkgs.ddclient}/bin/ddclient -foreground -file ${cfg.configFile}"; + ProtectSystem = "full"; + PrivateTmp = true; }; }; }; diff --git a/nixos/modules/services/security/sks.nix b/nixos/modules/services/security/sks.nix new file mode 100644 index 000000000000..62308428f326 --- /dev/null +++ b/nixos/modules/services/security/sks.nix @@ -0,0 +1,82 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.sks; + + sksPkg = cfg.package; + +in + +{ + + options = { + + services.sks = { + + enable = mkEnableOption "sks"; + + package = mkOption { + default = pkgs.sks; + defaultText = "pkgs.sks"; + type = types.package; + description = " + Which sks derivation to use. + "; + }; + + hkpAddress = mkOption { + default = [ "127.0.0.1" "::1" ]; + type = types.listOf types.str; + description = " + Wich ip addresses the sks-keyserver is listening on. + "; + }; + + hkpPort = mkOption { + default = 11371; + type = types.int; + description = " + Which port the sks-keyserver is listening on. + "; + }; + }; + }; + + config = mkIf cfg.enable { + + environment.systemPackages = [ sksPkg ]; + + users.users.sks = { + createHome = true; + home = "/var/db/sks"; + isSystemUser = true; + shell = "${pkgs.coreutils}/bin/true"; + }; + + systemd.services = let + hkpAddress = "'" + (builtins.concatStringsSep " " cfg.hkpAddress) + "'" ; + hkpPort = builtins.toString cfg.hkpPort; + home = config.users.users.sks.home; + user = config.users.users.sks.name; + in { + sks-keyserver = { + wantedBy = [ "multi-user.target" ]; + preStart = '' + mkdir -p ${home}/dump + ${pkgs.sks}/bin/sks build ${home}/dump/*.gpg -n 10 -cache 100 || true #*/ + ${pkgs.sks}/bin/sks cleandb || true + ${pkgs.sks}/bin/sks pbuild -cache 20 -ptree_cache 70 || true + ''; + serviceConfig = { + WorkingDirectory = home; + User = user; + Restart = "always"; + ExecStart = "${pkgs.sks}/bin/sks db -hkp_address ${hkpAddress} -hkp_port ${hkpPort}"; + }; + }; + }; + }; +} diff --git a/nixos/modules/services/security/tor.nix b/nixos/modules/services/security/tor.nix index 3f1450ebfbd7..04b065f6ae4b 100644 --- a/nixos/modules/services/security/tor.nix +++ b/nixos/modules/services/security/tor.nix @@ -7,7 +7,7 @@ let torDirectory = "/var/lib/tor"; opt = name: value: optionalString (value != null) "${name} ${value}"; - optint = name: value: optionalString (value != 0) "${name} ${toString value}"; + optint = name: value: optionalString (value != null && value != 0) "${name} ${toString value}"; torRc = '' User tor @@ -17,7 +17,7 @@ let GeoIPv6File ${pkgs.tor.geoip}/share/tor/geoip6 ''} - ${optint "ControlPort" cfg.controlPort} + ${optint "ControlPort" (toString cfg.controlPort)} '' # Client connection config + optionalString cfg.client.enable '' @@ -27,7 +27,8 @@ let '' # Relay config + optionalString cfg.relay.enable '' - ORPort ${cfg.relay.portSpec} + ORPort ${toString cfg.relay.port} + ${opt "Address" cfg.relay.address} ${opt "Nickname" cfg.relay.nickname} ${opt "ContactInfo" cfg.relay.contactInfo} @@ -36,31 +37,32 @@ let ${opt "AccountingMax" cfg.relay.accountingMax} ${opt "AccountingStart" cfg.relay.accountingStart} - ${if cfg.relay.isExit then + ${if (cfg.relay.role == "exit") then opt "ExitPolicy" cfg.relay.exitPolicy else "ExitPolicy reject *:*"} - ${optionalString cfg.relay.isBridge '' + ${optionalString (elem cfg.relay.role ["bridge" "private-bridge"]) '' BridgeRelay 1 ServerTransportPlugin obfs2,obfs3 exec ${pkgs.pythonPackages.obfsproxy}/bin/obfsproxy managed + ExtORPort auto + ${optionalString (cfg.relay.role == "private-bridge") '' + ExtraInfoStatistics 0 + PublishServerDescriptor 0 + ''} ''} '' - + hiddenServices + # Hidden services + + concatStrings (flip mapAttrsToList cfg.hiddenServices (n: v: '' + HiddenServiceDir ${torDirectory}/onion/${v.name} + ${flip concatMapStrings v.map (p: '' + HiddenServicePort ${toString p.port} ${p.destination} + '')} + '')) + cfg.extraConfig; - hiddenServices = concatStrings (mapAttrsToList (hiddenServiceDir: hs: - let - hsports = concatStringsSep "\n" (map mkHiddenServicePort hs.hiddenServicePorts); - in - "HiddenServiceDir ${hiddenServiceDir}\n${hsports}\n${hs.extraConfig}\n" - ) cfg.hiddenServices); - - mkHiddenServicePort = hsport: let - trgt = optionalString (hsport.target != null) (" " + hsport.target); - in "HiddenServicePort ${toString hsport.virtualPort}${trgt}"; - torRcFile = pkgs.writeText "torrc" torRc; + in { options = { @@ -96,8 +98,8 @@ in }; controlPort = mkOption { - type = types.int; - default = 0; + type = types.nullOr (types.either types.int types.str); + default = null; example = 9051; description = '' If set, Tor will accept connections on the specified port @@ -133,9 +135,10 @@ in example = "192.168.0.1:9101"; description = '' Bind to this address to listen for connections from - Socks-speaking applications. Same as socksListenAddress - but uses weaker circuit isolation to provide performance - suitable for a web browser. + Socks-speaking applications. Same as + <option>socksListenAddress</option> but uses weaker + circuit isolation to provide performance suitable for a + web browser. ''; }; @@ -145,9 +148,9 @@ in example = "accept 192.168.0.0/16, reject *"; description = '' Entry policies to allow/deny SOCKS requests based on IP - address. First entry that matches wins. If no SocksPolicy + address. First entry that matches wins. If no SocksPolicy is set, we accept all (and only) requests from - SocksListenAddress. + <option>socksListenAddress</option>. ''; }; @@ -176,45 +179,147 @@ in description = '' Whether to enable relaying TOR traffic for others. - See https://www.torproject.org/docs/tor-doc-relay for details. - ''; - }; - - isBridge = mkOption { - type = types.bool; - default = false; - description = '' - Bridge relays (or "bridges") are Tor relays that aren't - listed in the main directory. Since there is no complete - public list of them, even if an ISP is filtering - connections to all the known Tor relays, they probably - won't be able to block all the bridges. - - A bridge relay can't be an exit relay. - - You need to set relay.enable to true for this option to - take effect. + See <link xlink:href="https://www.torproject.org/docs/tor-doc-relay" /> + for details. - The bridge is set up with an obfuscated transport proxy. - - See https://www.torproject.org/bridges.html.en for more info. + Setting this to true requires setting + <option>services.tor.relay.role</option> + and + <option>services.tor.relay.port</option> + options. ''; }; - isExit = mkOption { - type = types.bool; - default = false; + role = mkOption { + type = types.enum [ "exit" "relay" "bridge" "private-bridge" ]; description = '' - An exit relay allows Tor users to access regular Internet - services. - - Unlike running a non-exit relay, running an exit relay may - expose you to abuse complaints. See - https://www.torproject.org/faq.html.en#ExitPolicies for - more info. - - You can specify which services Tor users may access via - your exit relay using exitPolicy option. + Your role in Tor network. There're several options: + + <variablelist> + <varlistentry> + <term><literal>exit</literal></term> + <listitem> + <para> + An exit relay. This allows Tor users to access regular + Internet services through your public IP. + </para> + + <important><para> + Running an exit relay may expose you to abuse + complaints. See + <link xlink:href="https://www.torproject.org/faq.html.en#ExitPolicies" /> + for more info. + </para></important> + + <para> + You can specify which services Tor users may access via + your exit relay using <option>exitPolicy</option> option. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>relay</literal></term> + <listitem> + <para> + Regular relay. This allows Tor users to relay onion + traffic to other Tor nodes, but not to public + Internet. + </para> + + <important><para> + Note that some misconfigured and/or disrespectful + towards privacy sites will block you even if your + relay is not an exit relay. That is, just being listed + in a public relay directory can have unwanted + consequences. + + Which means you might not want to use + this role if you browse public Internet from the same + network as your relay, unless you want to write + e-mails to those sites (you should!). + </para></important> + + <para> + See + <link xlink:href="https://www.torproject.org/docs/tor-doc-relay.html.en" /> + for more info. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>bridge</literal></term> + <listitem> + <para> + Regular bridge. Works like a regular relay, but + doesn't list you in the public relay directory and + hides your Tor node behind obfsproxy. + </para> + + <para> + Using this option will make Tor advertise your bridge + to users through various mechanisms like + <link xlink:href="https://bridges.torproject.org/" />, though. + </para> + + <important> + <para> + WARNING: THE FOLLOWING PARAGRAPH IS NOT LEGAL ADVISE. + Consult with your lawer when in doubt. + </para> + + <para> + This role should be safe to use in most situations + (unless the act of forwarding traffic for others is + a punishable offence under your local laws, which + would be pretty insane as it would make ISP + illegal). + </para> + </important> + + <para> + See <link xlink:href="https://www.torproject.org/docs/bridges.html.en" /> + for more info. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>private-bridge</literal></term> + <listitem> + <para> + Private bridge. Works like regular bridge, but does + not advertise your node in any way. + </para> + + <para> + Using this role means that you won't contribute to Tor + network in any way unless you advertise your node + yourself in some way. + </para> + + <para> + Use this if you want to run a private bridge, for + example because you'll give out your bridge address + manually to your friends. + </para> + + <para> + Switching to this role after measurable time in + "bridge" role is pretty useless as some Tor users + would have learned about your node already. In the + latter case you can still change + <option>port</option> option. + </para> + + <para> + See <link xlink:href="https://www.torproject.org/docs/bridges.html.en" /> + for more info. + </para> + </listitem> + </varlistentry> + </variablelist> ''; }; @@ -268,8 +373,8 @@ in }; bandwidthRate = mkOption { - type = types.int; - default = 0; + type = types.nullOr types.int; + default = null; example = 100; description = '' Specify this to limit the bandwidth usage of relayed (server) @@ -278,7 +383,7 @@ in }; bandwidthBurst = mkOption { - type = types.int; + type = types.nullOr types.int; default = cfg.relay.bandwidthRate; example = 200; description = '' @@ -288,9 +393,19 @@ in ''; }; - portSpec = mkOption { - type = types.str; - example = "143"; + address = mkOption { + type = types.nullOr types.str; + default = null; + example = "noname.example.com"; + description = '' + The IP address or full DNS name for advertised address of your relay. + Leave unset and Tor will guess. + ''; + }; + + port = mkOption { + type = types.either types.int types.str; + example = 143; description = '' What port to advertise for Tor connections. This corresponds to the <literal>ORPort</literal> section in the Tor manual; see @@ -313,13 +428,15 @@ in considered first to last, and the first match wins. If you want to _replace_ the default exit policy, end this with either a reject *:* or an accept *:*. Otherwise, you're - _augmenting_ (prepending to) the default exit - policy. Leave commented to just use the default, which is + _augmenting_ (prepending to) the default exit policy. + Leave commented to just use the default, which is available in the man page or at - https://www.torproject.org/documentation.html + <link xlink:href="https://www.torproject.org/documentation.html" />. - Look at https://www.torproject.org/faq-abuse.html#TypicalAbuses - for issues you might encounter if you use the default exit policy. + Look at + <link xlink:href="https://www.torproject.org/faq-abuse.html#TypicalAbuses" /> + for issues you might encounter if you use the default + exit policy. If certain IPs and ports are blocked externally, e.g. by your firewall, you should update your exit policy to @@ -330,79 +447,122 @@ in }; hiddenServices = mkOption { - type = types.attrsOf (types.submodule ({ - options = { - hiddenServicePorts = mkOption { - type = types.listOf (types.submodule { - options = { - virtualPort = mkOption { - type = types.int; - example = 80; - description = "Virtual port."; - }; - target = mkOption { - type = types.nullOr types.str; - default = null; - example = "127.0.0.1:8080"; - description = '' - Target virtual Port shall be mapped to. - - You may override the target port, address, or both by - specifying a target of addr, port, addr:port, or - unix:path. (You can specify an IPv6 target as - [addr]:port. Unix paths may be quoted, and may use - standard C escapes.) - ''; - }; - }; - }); - example = [ { virtualPort = 80; target = "127.0.0.1:8080"; } { virtualPort = 6667; } ]; - description = '' - If target is <literal>null</literal> the virtual port is mapped - to the same port on 127.0.0.1 over TCP. You may use - <literal>target</literal> to overwrite this behaviour (see - description of target). - - This corresponds to the <literal>HiddenServicePort VIRTPORT - [TARGET]</literal> option by looking at the tor manual - <citerefentry><refentrytitle>tor</refentrytitle> - <manvolnum>1</manvolnum></citerefentry> for more information. - ''; - }; - extraConfig = mkOption { - type = types.str; - default = ""; - description = '' - Extra configuration. Contents will be added in the current - hidden service context. - ''; - }; - }; - })); + description = '' + A set of static hidden services that terminate their Tor + circuits at this node. + + Every element in this set declares a virtual onion host. + + You can specify your onion address by putting corresponding + private key to an appropriate place in ${torDirectory}. + + For services without private keys in ${torDirectory} Tor + daemon will generate random key pairs (which implies random + onion addresses) on restart. The latter could take a while, + please be patient. + + <note><para> + Hidden services can be useful even if you don't intend to + actually <emphasis>hide</emphasis> them, since they can + also be seen as a kind of NAT traversal mechanism. + + E.g. the example will make your sshd, whatever runs on + "8080" and your mail server available from anywhere where + the Tor network is available (which, with the help from + bridges, is pretty much everywhere), even if both client + and server machines are behind NAT you have no control + over. + </para></note> + ''; default = {}; - example = { - "/var/lib/tor/webserver" = { - hiddenServicePorts = [ { virtualPort = 80; } ]; + example = literalExample '' + { "my-hidden-service-example".map = [ + { port = 22; } # map ssh port to this machine's ssh + { port = 80; toPort = 8080; } # map http port to whatever runs on 8080 + { port = "sip"; toHost = "mail.example.com"; toPort = "imap"; } # because we can + ]; + } + ''; + type = types.loaOf (types.submodule ({name, config, ...}: { + options = { + + name = mkOption { + type = types.str; + description = '' + Name of this tor hidden service. + + This is purely descriptive. + + After restarting Tor daemon you should be able to + find your .onion address in + <literal>${torDirectory}/onion/$name/hostname</literal>. + ''; + }; + + map = mkOption { + default = []; + description = "Port mapping for this hidden service."; + type = types.listOf (types.submodule ({config, ...}: { + options = { + + port = mkOption { + type = types.either types.int types.str; + example = 80; + description = '' + Hidden service port to "bind to". + ''; + }; + + destination = mkOption { + internal = true; + type = types.str; + description = "Forward these connections where?"; + }; + + toHost = mkOption { + type = types.str; + default = "127.0.0.1"; + description = "Mapping destination host."; + }; + + toPort = mkOption { + type = types.either types.int types.str; + example = 8080; + description = "Mapping destination port."; + }; + + }; + + config = { + toPort = mkDefault config.port; + destination = mkDefault "${config.toHost}:${toString config.toPort}"; + }; + })); + }; + }; - }; - description = '' - Configure hidden services. - Please consult the tor manual - <citerefentry><refentrytitle>tor</refentrytitle> - <manvolnum>1</manvolnum></citerefentry> for a more detailed - explanation. (search for 'HIDDEN'). - ''; + config = { + name = mkDefault name; + }; + })); }; }; }; config = mkIf cfg.enable { - assertions = singleton - { message = "Can't be both an exit and a bridge relay at the same time"; - assertion = - cfg.relay.enable -> !(cfg.relay.isBridge && cfg.relay.isExit); - }; + # Not sure if `cfg.relay.role == "private-bridge"` helps as tor + # sends a lot of stats + warnings = optional (cfg.relay.enable && cfg.hiddenServices != {}) + '' + Running Tor hidden services on a public relay makes the + presence of hidden services visible through simple statistical + analysis of publicly available data. + + You can safely ignore this warning if you don't intend to + actually hide your hidden services. In either case, you can + always create a container/VM with a separate Tor daemon instance. + ''; users.extraGroups.tor.gid = config.ids.gids.tor; users.extraUsers.tor = @@ -422,9 +582,13 @@ in restartTriggers = [ torRcFile ]; # Translated from the upstream contrib/dist/tor.service.in + preStart = '' + install -o tor -g tor -d ${torDirectory}/onion + ${pkgs.tor}/bin/tor -f ${torRcFile} --verify-config + ''; + serviceConfig = { Type = "simple"; - ExecStartPre = "${pkgs.tor}/bin/tor -f ${torRcFile} --verify-config"; ExecStart = "${pkgs.tor}/bin/tor -f ${torRcFile} --RunAsDaemon 0"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; KillSignal = "SIGINT"; diff --git a/nixos/modules/services/ttys/agetty.nix b/nixos/modules/services/ttys/agetty.nix index f8dd75ea2c46..3429397d2cc2 100644 --- a/nixos/modules/services/ttys/agetty.nix +++ b/nixos/modules/services/ttys/agetty.nix @@ -85,12 +85,18 @@ in }; systemd.services."container-getty@" = - { serviceConfig.ExecStart = gettyCmd "--noclear --keep-baud pts/%I 115200,38400,9600 $TERM"; + { serviceConfig.ExecStart = [ + "" # override upstream default with an empty ExecStart + (gettyCmd "--noclear --keep-baud pts/%I 115200,38400,9600 $TERM") + ]; restartIfChanged = false; }; systemd.services."console-getty" = - { serviceConfig.ExecStart = gettyCmd "--noclear --keep-baud console 115200,38400,9600 $TERM"; + { serviceConfig.ExecStart = [ + "" # override upstream default with an empty ExecStart + (gettyCmd "--noclear --keep-baud console 115200,38400,9600 $TERM") + ]; serviceConfig.Restart = "always"; restartIfChanged = false; enable = mkDefault config.boot.isContainer; diff --git a/nixos/modules/services/web-apps/pgpkeyserver-lite.nix b/nixos/modules/services/web-apps/pgpkeyserver-lite.nix new file mode 100644 index 000000000000..93f69bd12651 --- /dev/null +++ b/nixos/modules/services/web-apps/pgpkeyserver-lite.nix @@ -0,0 +1,75 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.pgpkeyserver-lite; + sksCfg = config.services.sks; + + webPkg = cfg.package; + +in + +{ + + options = { + + services.pgpkeyserver-lite = { + + enable = mkEnableOption "pgpkeyserver-lite on a nginx vHost proxying to a gpg keyserver"; + + package = mkOption { + default = pkgs.pgpkeyserver-lite; + defaultText = "pkgs.pgpkeyserver-lite"; + type = types.package; + description = " + Which webgui derivation to use. + "; + }; + + hostname = mkOption { + type = types.str; + description = " + Which hostname to set the vHost to that is proxying to sks. + "; + }; + + hkpAddress = mkOption { + default = builtins.head sksCfg.hkpAddress; + type = types.str; + description = " + Wich ip address the sks-keyserver is listening on. + "; + }; + + hkpPort = mkOption { + default = sksCfg.hkpPort; + type = types.int; + description = " + Which port the sks-keyserver is listening on. + "; + }; + }; + }; + + config = mkIf cfg.enable { + + services.nginx.enable = true; + + services.nginx.virtualHosts = let + hkpPort = builtins.toString cfg.hkpPort; + in { + "${cfg.hostname}" = { + root = webPkg; + locations = { + "/pks".extraConfig = '' + proxy_pass http://${cfg.hkpAddress}:${hkpPort}; + proxy_pass_header Server; + add_header Via "1.1 ${cfg.hostname}"; + ''; + }; + }; + }; + }; +} diff --git a/nixos/modules/services/web-servers/phpfpm/default.nix b/nixos/modules/services/web-servers/phpfpm/default.nix index 26f546022035..f9febbfbacdf 100644 --- a/nixos/modules/services/web-servers/phpfpm/default.nix +++ b/nixos/modules/services/web-servers/phpfpm/default.nix @@ -150,7 +150,6 @@ in { PrivateDevices = true; ProtectSystem = "full"; ProtectHome = true; - NoNewPrivileges = true; RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; Type = "notify"; ExecStart = "${cfg.phpPackage}/bin/php-fpm -y ${cfgFile} -c ${phpIni}"; diff --git a/nixos/modules/services/web-servers/varnish/default.nix b/nixos/modules/services/web-servers/varnish/default.nix index 5433db3b91c8..c3bc065d4651 100644 --- a/nixos/modules/services/web-servers/varnish/default.nix +++ b/nixos/modules/services/web-servers/varnish/default.nix @@ -7,14 +7,10 @@ with lib; { options = { services.varnish = { - enable = mkOption { - default = false; - description = " - Enable the Varnish Server. - "; - }; + enable = mkEnableOption "Varnish Server"; http_address = mkOption { + type = types.str; default = "*:6081"; description = " HTTP listen address and port. @@ -22,17 +18,37 @@ with lib; }; config = mkOption { + type = types.lines; description = " Verbatim default.vcl configuration. "; }; stateDir = mkOption { + type = types.path; default = "/var/spool/varnish/${config.networking.hostName}"; description = " Directory holding all state for Varnish to run. "; }; + + extraModules = mkOption { + type = types.listOf types.package; + default = []; + example = literalExample "[ pkgs.varnish-geoip ]"; + description = " + Varnish modules (except 'std'). + "; + }; + + extraCommandLine = mkOption { + type = types.str; + default = ""; + example = "-s malloc,256M"; + description = " + Command line switches for varnishd (run 'varnishd -?' to get list of options) + "; + }; }; }; @@ -42,6 +58,7 @@ with lib; systemd.services.varnish = { description = "Varnish"; wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; preStart = '' mkdir -p ${cfg.stateDir} chown -R varnish:varnish ${cfg.stateDir} @@ -49,8 +66,19 @@ with lib; postStop = '' rm -rf ${cfg.stateDir} ''; - serviceConfig.ExecStart = "${pkgs.varnish}/sbin/varnishd -a ${cfg.http_address} -f ${pkgs.writeText "default.vcl" cfg.config} -n ${cfg.stateDir} -u varnish"; - serviceConfig.Type = "forking"; + serviceConfig = { + Type = "simple"; + PermissionsStartOnly = true; + ExecStart = "${pkgs.varnish}/sbin/varnishd -a ${cfg.http_address} -f ${pkgs.writeText "default.vcl" cfg.config} -n ${cfg.stateDir} -F ${cfg.extraCommandLine}" + + optionalString (cfg.extraModules != []) " -p vmod_path='${makeSearchPathOutput "lib" "lib/varnish/vmods" ([pkgs.varnish] ++ cfg.extraModules)}' -r vmod_path"; + Restart = "always"; + RestartSec = "5s"; + User = "varnish"; + Group = "varnish"; + AmbientCapabilities = "cap_net_bind_service"; + NoNewPrivileges = true; + LimitNOFILE = 131072; + }; }; environment.systemPackages = [ pkgs.varnish ]; diff --git a/nixos/modules/testing/minimal-kernel.nix b/nixos/modules/testing/minimal-kernel.nix index a463cb803ade..7c2b9c05cf9a 100644 --- a/nixos/modules/testing/minimal-kernel.nix +++ b/nixos/modules/testing/minimal-kernel.nix @@ -6,7 +6,7 @@ let ); origKernel = pkgs.buildLinux { - inherit (pkgs.linux) src version; + inherit (pkgs.linux) src version stdenv; inherit configfile; allowImportFromDerivation = true; kernelPatches = [ pkgs.kernelPatches.cifs_timeout_2_6_38 ]; diff --git a/nixos/modules/virtualisation/libvirtd.nix b/nixos/modules/virtualisation/libvirtd.nix index b24ea0f33c9e..ade0ba531cfa 100644 --- a/nixos/modules/virtualisation/libvirtd.nix +++ b/nixos/modules/virtualisation/libvirtd.nix @@ -15,7 +15,7 @@ let ''; qemuConfigFile = pkgs.writeText "qemu.conf" '' ${optionalString cfg.qemuOvmf '' - nvram = ["${pkgs.OVMF.fd}/FV/OVMF_CODE.fd:${pkgs.OVMF.fd}/FV/OVMF_VARS.fd"] + nvram = ["/run/libvirt/nix-ovmf/OVMF_CODE.fd:/run/libvirt/nix-ovmf/OVMF_VARS.fd"] ''} ${cfg.qemuVerbatimConfig} ''; @@ -102,9 +102,7 @@ in { config = mkIf cfg.enable { - environment.systemPackages = with pkgs; - [ libvirt netcat-openbsd ] - ++ optional cfg.enableKVM qemu_kvm; + environment.systemPackages = with pkgs; [ libvirt netcat-openbsd ]; boot.kernelModules = [ "tun" ]; @@ -129,7 +127,6 @@ in { dnsmasq ebtables ] - ++ optional cfg.enableKVM qemu_kvm ++ optional vswitch.enable vswitch.package; preStart = '' @@ -155,34 +152,31 @@ in { # Copy generated qemu config to libvirt directory cp -f ${qemuConfigFile} /var/lib/libvirt/qemu.conf - # libvirtd puts the full path of the emulator binary in the machine - # config file. But this path can unfortunately be garbage collected - # while still being used by the virtual machine. So update the - # emulator path on each startup to something valid (re-scan $PATH). - for file in /var/lib/libvirt/qemu/*.xml /var/lib/libvirt/lxc/*.xml; do - test -f "$file" || continue - # get (old) emulator path from config file - emulator=$("${pkgs.xmlstarlet}/bin/xmlstarlet" select --template --value-of "/domain/devices/emulator" "$file") - # get a (definitely) working emulator path by re-scanning $PATH - new_emulator=$(PATH=${pkgs.libvirt}/libexec:$PATH command -v $(basename "$emulator")) - # write back - "${pkgs.xmlstarlet}/bin/xmlstarlet" edit --inplace --update "/domain/devices/emulator" -v "$new_emulator" "$file" - - # Also refresh the OVMF path. Files with no matches are ignored. - "${pkgs.xmlstarlet}/bin/xmlstarlet" edit --inplace --update "/domain/os/loader" -v "${pkgs.OVMF.fd}/FV/OVMF_CODE.fd" "$file" - done - ''; # */ + # stable (not GC'able as in /nix/store) paths for using in <emulator> section of xml configs + mkdir -p /run/libvirt/nix-emulators + ln -s --force ${pkgs.libvirt}/libexec/libvirt_lxc /run/libvirt/nix-emulators/ + ${optionalString pkgs.stdenv.isAarch64 "ln -s --force ${pkgs.qemu}/bin/qemu-system-aarch64 /run/libvirt/nix-emulators/"} + ${optionalString cfg.enableKVM "ln -s --force ${pkgs.qemu_kvm}/bin/qemu-kvm /run/libvirt/nix-emulators/"} + + ${optionalString cfg.qemuOvmf '' + mkdir -p /run/libvirt/nix-ovmf + ln -s --force ${pkgs.OVMF.fd}/FV/OVMF_CODE.fd /run/libvirt/nix-ovmf/ + ln -s --force ${pkgs.OVMF.fd}/FV/OVMF_VARS.fd /run/libvirt/nix-ovmf/ + ''} + ''; serviceConfig = { Type = "notify"; KillMode = "process"; # when stopping, leave the VMs alone - Restart = "on-failure"; + Restart = "no"; }; + restartIfChanged = false; }; systemd.services.libvirt-guests = { wantedBy = [ "multi-user.target" ]; path = with pkgs; [ coreutils libvirt gawk ]; + restartIfChanged = false; }; systemd.sockets.virtlogd = { @@ -194,6 +188,7 @@ in { systemd.services.virtlogd = { description = "Virtual machine log manager"; serviceConfig.ExecStart = "@${pkgs.libvirt}/sbin/virtlogd virtlogd"; + restartIfChanged = false; }; systemd.sockets.virtlockd = { @@ -205,6 +200,7 @@ in { systemd.services.virtlockd = { description = "Virtual machine lock manager"; serviceConfig.ExecStart = "@${pkgs.libvirt}/sbin/virtlockd virtlockd"; + restartIfChanged = false; }; }; } diff --git a/nixos/modules/virtualisation/vmware-guest.nix b/nixos/modules/virtualisation/vmware-guest.nix index ce1224a8f131..68930a0e3254 100644 --- a/nixos/modules/virtualisation/vmware-guest.nix +++ b/nixos/modules/virtualisation/vmware-guest.nix @@ -33,7 +33,7 @@ in serviceConfig.ExecStart = "${open-vm-tools}/bin/vmtoolsd"; }; - environment.etc."vmware-tools".source = "${pkgs.open-vm-tools}/etc/vmware-tools/*"; + environment.etc."vmware-tools".source = "${open-vm-tools}/etc/vmware-tools/*"; services.xserver = mkIf (!cfg.headless) { videoDrivers = mkOverride 50 [ "vmware" ]; |