diff options
author | Robin Gloster <mail@glob.in> | 2016-07-31 20:51:34 +0000 |
---|---|---|
committer | Robin Gloster <mail@glob.in> | 2016-07-31 20:51:34 +0000 |
commit | 63c7b4f9a7844f0bc84d008b810375eb0fba6b2f (patch) | |
tree | e351ecd702d87ab1c4fd03246383162ec19d6de2 /nixos/modules | |
parent | 43ba8d295f414ab985bd3fc5d5125421bd8bd0ad (diff) | |
parent | a629cd3f02c2ad071e58d5898c5f48fb0336a705 (diff) | |
download | nixlib-63c7b4f9a7844f0bc84d008b810375eb0fba6b2f.tar nixlib-63c7b4f9a7844f0bc84d008b810375eb0fba6b2f.tar.gz nixlib-63c7b4f9a7844f0bc84d008b810375eb0fba6b2f.tar.bz2 nixlib-63c7b4f9a7844f0bc84d008b810375eb0fba6b2f.tar.lz nixlib-63c7b4f9a7844f0bc84d008b810375eb0fba6b2f.tar.xz nixlib-63c7b4f9a7844f0bc84d008b810375eb0fba6b2f.tar.zst nixlib-63c7b4f9a7844f0bc84d008b810375eb0fba6b2f.zip |
Merge remote-tracking branch 'upstream/master' into hardened-stdenv
Diffstat (limited to 'nixos/modules')
26 files changed, 582 insertions, 327 deletions
diff --git a/nixos/modules/config/pulseaudio.nix b/nixos/modules/config/pulseaudio.nix index 7acf050a9a40..71ac3f9a72c4 100644 --- a/nixos/modules/config/pulseaudio.nix +++ b/nixos/modules/config/pulseaudio.nix @@ -9,11 +9,36 @@ let systemWide = cfg.enable && cfg.systemWide; nonSystemWide = cfg.enable && !cfg.systemWide; + hasZeroconf = let z = cfg.zeroconf; in z.publish.enable || z.discovery.enable; + + overriddenPackage = cfg.package.override + (optionalAttrs hasZeroconf { zeroconfSupport = true; }); + binary = "${getBin overriddenPackage}/bin/pulseaudio"; + binaryNoDaemon = "${binary} --daemonize=no"; # Forces 32bit pulseaudio and alsaPlugins to be built/supported for apps # using 32bit alsa on 64bit linux. enable32BitAlsaPlugins = cfg.support32Bit && stdenv.isx86_64 && (pkgs_i686.alsaLib != null && pkgs_i686.libpulseaudio != null); + + myConfigFile = + let + addModuleIf = cond: mod: optionalString cond "load-module ${mod}"; + allAnon = optional cfg.tcp.anonymousClients.allowAll "auth-anonymous=1"; + ipAnon = let a = cfg.tcp.anonymousClients.allowedIpRanges; + in optional (a != []) ''auth-ip-acl=${concatStringsSep ";" a}''; + in writeTextFile { + name = "default.pa"; + text = '' + .include ${cfg.configFile} + ${addModuleIf cfg.zeroconf.publish.enable "module-zeroconf-publish"} + ${addModuleIf cfg.zeroconf.discovery.enable "module-zeroconf-discover"} + ${addModuleIf cfg.tcp.enable (concatStringsSep " " + ([ "load-module module-native-protocol-tcp" ] ++ allAnon ++ ipAnon))} + ${cfg.extraConfig} + ''; + }; + ids = config.ids; uid = ids.uids.pulseaudio; @@ -26,7 +51,7 @@ let # are built with PulseAudio support (like KDE). clientConf = writeText "client.conf" '' autospawn=${if nonSystemWide then "yes" else "no"} - ${optionalString nonSystemWide "daemon-binary=${cfg.package.out}/bin/pulseaudio"} + ${optionalString nonSystemWide "daemon-binary=${binary}"} ${cfg.extraClientConf} ''; @@ -44,7 +69,7 @@ let hint.description "Default Audio Device (via PulseAudio)" } ctl_type.pulse { - libs.native = ${alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so ; + libs.native = ${pkgs.alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so ; ${lib.optionalString enable32BitAlsaPlugins "libs.32Bit = ${pkgs_i686.alsaPlugins}/lib/alsa-lib/libasound_module_ctl_pulse.so ;"} } @@ -89,16 +114,25 @@ in { }; configFile = mkOption { - type = types.path; + type = types.nullOr types.path; description = '' - The path to the configuration the PulseAudio server + The path to the default configuration options the PulseAudio server should use. By default, the "default.pa" configuration from the PulseAudio distribution is used. ''; }; + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Literal string to append to <literal>configFile</literal> + and the config file generated by the pulseaudio module. + ''; + }; + extraClientConf = mkOption { - type = types.str; + type = types.lines; default = ""; description = '' Extra configuration appended to pulse/client.conf file. @@ -127,6 +161,31 @@ in { ''; }; }; + + zeroconf = { + discovery.enable = + mkEnableOption "discovery of pulseaudio sinks in the local network"; + publish.enable = + mkEnableOption "publishing the pulseaudio sink in the local network"; + }; + + # TODO: enable by default? + tcp = { + enable = mkEnableOption "tcp streaming support"; + + anonymousClients = { + allowAll = mkEnableOption "all anonymous clients to stream to the server"; + allowedIpRanges = mkOption { + type = types.listOf types.str; + default = []; + example = literalExample ''[ "127.0.0.1" "192.168.1.0/24" ]''; + description = '' + A list of IP subnets that are allowed to stream to the server. + ''; + }; + }; + }; + }; }; @@ -139,11 +198,11 @@ in { source = clientConf; }; - hardware.pulseaudio.configFile = mkDefault "${getBin cfg.package}/etc/pulse/default.pa"; + hardware.pulseaudio.configFile = mkDefault "${getBin overriddenPackage}/etc/pulse/default.pa"; } (mkIf cfg.enable { - environment.systemPackages = [ cfg.package ]; + environment.systemPackages = [ overriddenPackage ]; environment.etc = singleton { target = "asound.conf"; @@ -152,12 +211,21 @@ in { # Allow PulseAudio to get realtime priority using rtkit. security.rtkit.enable = true; + + }) + + (mkIf hasZeroconf { + services.avahi.enable = true; + }) + (mkIf cfg.zeroconf.publish.enable { + services.avahi.publish.enable = true; + services.avahi.publish.userServices = true; }) (mkIf nonSystemWide { environment.etc = singleton { target = "pulse/default.pa"; - source = cfg.configFile; + source = myConfigFile; }; systemd.user = { @@ -167,10 +235,12 @@ in { wantedBy = [ "default.target" ]; serviceConfig = { Type = "notify"; - ExecStart = "${getBin cfg.package}/bin/pulseaudio --daemonize=no"; + ExecStart = binaryNoDaemon; Restart = "on-failure"; + RestartSec = "500ms"; }; environment = { DISPLAY = ":${toString config.services.xserver.display}"; }; + restartIfChanged = true; }; sockets.pulseaudio = { @@ -205,8 +275,9 @@ in { environment.PULSE_RUNTIME_PATH = stateDir; serviceConfig = { Type = "notify"; - ExecStart = "${getBin cfg.package}/bin/pulseaudio --daemonize=no --log-level=${cfg.daemon.logLevel} --system -n --file=${cfg.configFile}"; + ExecStart = "${binaryNoDaemon} --log-level=${cfg.daemon.logLevel} --system -n --file=${myConfigFile}"; Restart = "on-failure"; + RestartSec = "500ms"; }; }; }) diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 6c696987f89e..9f1ca0f69232 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -473,7 +473,7 @@ ./services/web-servers/lighttpd/gitweb.nix ./services/web-servers/lighttpd/inginious.nix ./services/web-servers/nginx/default.nix - ./services/web-servers/phpfpm/default.nix + ./services/web-servers/phpfpm.nix ./services/web-servers/shellinabox.nix ./services/web-servers/tomcat.nix ./services/web-servers/uwsgi.nix diff --git a/nixos/modules/programs/ssmtp.nix b/nixos/modules/programs/ssmtp.nix index 7b00efbb4686..f5d1873cc5c8 100644 --- a/nixos/modules/programs/ssmtp.nix +++ b/nixos/modules/programs/ssmtp.nix @@ -100,6 +100,12 @@ in Password used for SMTP auth. (STORED PLAIN TEXT, WORLD-READABLE IN NIX STORE) ''; }; + + setSendmail = mkOption { + type = types.bool; + default = true; + description = "Whether to set the system sendmail to ssmtp's."; + }; }; @@ -122,6 +128,13 @@ in ''; environment.systemPackages = [pkgs.ssmtp]; + + services.mail.sendmailSetuidWrapper = mkIf cfg.setSendmail { + program = "sendmail"; + source = "${pkgs.ssmtp}/bin/sendmail"; + setuid = false; + setgid = false; + }; }; diff --git a/nixos/modules/programs/tmux.nix b/nixos/modules/programs/tmux.nix index cadf8d4ae105..f0f8d03505ac 100644 --- a/nixos/modules/programs/tmux.nix +++ b/nixos/modules/programs/tmux.nix @@ -27,7 +27,7 @@ let set -g status-keys ${cfg.keyMode} set -g mode-keys ${cfg.keyMode} - ${if cfg.keyMode == "vi" then '' + ${if cfg.keyMode == "vi" && cfg.customPaneNavigationAndResize then '' bind h select-pane -L bind j select-pane -D bind k select-pane -U @@ -86,6 +86,13 @@ in { description = "Use 24 hour clock."; }; + customPaneNavigationAndResize = mkOption { + default = false; + example = true; + type = types.bool; + description = "Override the hjkl and HJKL bindings for pane navigation and resizing in VI mode."; + }; + escapeTime = mkOption { default = 500; example = 0; diff --git a/nixos/modules/services/audio/mopidy.nix b/nixos/modules/services/audio/mopidy.nix index 9981b065f28d..029b14ab4726 100644 --- a/nixos/modules/services/audio/mopidy.nix +++ b/nixos/modules/services/audio/mopidy.nix @@ -47,6 +47,7 @@ in { }; configuration = mkOption { + default = ""; type = types.lines; description = '' The configuration that Mopidy should use. diff --git a/nixos/modules/services/continuous-integration/gocd-server/default.nix b/nixos/modules/services/continuous-integration/gocd-server/default.nix index f0d9d6f53c83..2d1986301216 100644 --- a/nixos/modules/services/continuous-integration/gocd-server/default.nix +++ b/nixos/modules/services/continuous-integration/gocd-server/default.nix @@ -67,33 +67,33 @@ in { }; packages = mkOption { - default = [ pkgs.stdenv pkgs.jre config.programs.ssh.package pkgs.nix ]; + default = [ pkgs.stdenv pkgs.jre pkgs.git config.programs.ssh.package pkgs.nix ]; type = types.listOf types.package; description = '' Packages to add to PATH for the Go.CD server's process. ''; }; - heapSize = mkOption { + initialJavaHeapSize = mkOption { default = "512m"; type = types.str; description = '' - Specifies the java heap memory size for the Go.CD server's java process. + Specifies the initial java heap memory size for the Go.CD server's java process. ''; }; - maxMemory = mkOption { + maxJavaHeapMemory = mkOption { default = "1024m"; type = types.str; description = '' - Specifies the java maximum memory size for the Go.CD server's java process. + Specifies the java maximum heap memory size for the Go.CD server's java process. ''; }; extraOptions = mkOption { default = [ - "-Xms${cfg.heapSize}" - "-Xmx${cfg.maxMemory}" + "-Xms${cfg.initialJavaHeapSize}" + "-Xmx${cfg.maxJavaHeapMemory}" "-Dcruise.listen.host=${cfg.listenAddress}" "-Duser.language=en" "-Djruby.rack.request.size.threshold.bytes=30000000" diff --git a/nixos/modules/services/logging/logstash.nix b/nixos/modules/services/logging/logstash.nix index 2c3016d27df8..62f6e187ea07 100644 --- a/nixos/modules/services/logging/logstash.nix +++ b/nixos/modules/services/logging/logstash.nix @@ -51,12 +51,6 @@ in description = "Logging verbosity level."; }; - watchdogTimeout = mkOption { - type = types.int; - default = 10; - description = "Set watchdog timeout value in seconds."; - }; - filterWorkers = mkOption { type = types.int; default = 1; @@ -140,7 +134,6 @@ in "-w ${toString cfg.filterWorkers} " + ops havePluginPath "--pluginpath ${pluginPath} " + "${verbosityFlag} " + - "--watchdog-timeout ${toString cfg.watchdogTimeout} " + "-f ${writeText "logstash.conf" '' input { ${cfg.inputConfig} diff --git a/nixos/modules/services/mail/rmilter.nix b/nixos/modules/services/mail/rmilter.nix index d1f7cd2e173e..e27b38bc0e2e 100644 --- a/nixos/modules/services/mail/rmilter.nix +++ b/nixos/modules/services/mail/rmilter.nix @@ -75,7 +75,7 @@ in bindUnixSockets = mkOption { type = types.listOf types.str; - default = ["/run/rmilter.sock"]; + default = ["/run/rmilter/rmilter.sock"]; description = '' Unix domain sockets to listen for MTA requests. ''; @@ -114,7 +114,7 @@ in servers = mkOption { type = types.listOf types.str; - default = ["r:/run/rspamd.sock"]; + default = ["r:/run/rspamd/rspamd.sock"]; description = '' Spamd socket definitions. Is server name is prefixed with r: it is rspamd server. @@ -197,7 +197,7 @@ milter_default_action = accept serviceConfig = { ExecStart = "${pkgs.rmilter}/bin/rmilter ${optionalString cfg.debug "-d"} -n -c ${rmilterConfigFile}"; - ExecReload = "/bin/kill -USR1 $MAINPID"; + ExecReload = "${pkgs.coreutils}/bin/kill -USR1 $MAINPID"; User = cfg.user; Group = cfg.group; PermissionsStartOnly = true; @@ -212,10 +212,10 @@ milter_default_action = accept description = "Rmilter service socket"; wantedBy = [ "sockets.target" ]; socketConfig = { - ListenStream = cfg.bindUnixSockets ++ cfg.bindInetSockets; - SocketUser = cfg.user; - SocketGroup = cfg.group; - SocketMode = "0660"; + ListenStream = cfg.bindUnixSockets ++ cfg.bindInetSockets; + SocketUser = cfg.user; + SocketGroup = cfg.group; + SocketMode = "0666"; }; }; diff --git a/nixos/modules/services/mail/rspamd.nix b/nixos/modules/services/mail/rspamd.nix index 412b99ccc570..98489df78517 100644 --- a/nixos/modules/services/mail/rspamd.nix +++ b/nixos/modules/services/mail/rspamd.nix @@ -8,7 +8,7 @@ let mkBindSockets = socks: concatStringsSep "\n" (map (each: " bind_socket = \"${each}\"") socks); - rspamdConf = + rspamdConfFile = pkgs.writeText "rspamd.conf" '' .include "$CONFDIR/common.conf" @@ -18,8 +18,7 @@ let } logging { - type = "file"; - filename = "$LOGDIR/rspamd.log"; + type = "syslog"; .include "$CONFDIR/logging.inc" } @@ -33,7 +32,6 @@ let .include "$CONFDIR/worker-controller.inc" } ''; - rspamdConfFile = pkgs.writeText "rspamd.conf" rspamdConf; in @@ -45,10 +43,7 @@ in services.rspamd = { - enable = mkOption { - default = false; - description = "Whether to run the rspamd daemon."; - }; + enable = mkEnableOption "Whether to run the rspamd daemon."; debug = mkOption { default = false; @@ -58,7 +53,7 @@ in bindSocket = mkOption { type = types.listOf types.str; default = [ - "/run/rspamd.sock mode=0666 owner=${cfg.user}" + "/run/rspamd/rspamd.sock mode=0666 owner=${cfg.user}" ]; description = '' List of sockets to listen, in format acceptable by rspamd @@ -97,7 +92,6 @@ in ''; }; }; - }; @@ -128,18 +122,15 @@ in serviceConfig = { ExecStart = "${pkgs.rspamd}/bin/rspamd ${optionalString cfg.debug "-d"} --user=${cfg.user} --group=${cfg.group} --pid=/run/rspamd.pid -c ${rspamdConfFile} -f"; - RuntimeDirectory = "/var/lib/rspamd"; - PermissionsStartOnly = true; Restart = "always"; + RuntimeDirectory = "rspamd"; + PrivateTmp = true; }; preStart = '' - ${pkgs.coreutils}/bin/mkdir -p /var/{lib,log}/rspamd + ${pkgs.coreutils}/bin/mkdir -p /var/lib/rspamd ${pkgs.coreutils}/bin/chown ${cfg.user}:${cfg.group} /var/lib/rspamd ''; - }; - }; - } diff --git a/nixos/modules/services/misc/matrix-synapse.nix b/nixos/modules/services/misc/matrix-synapse.nix index 1a95e2d9367d..bb8dc640f981 100644 --- a/nixos/modules/services/misc/matrix-synapse.nix +++ b/nixos/modules/services/misc/matrix-synapse.nix @@ -522,10 +522,12 @@ in { after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; preStart = '' - mkdir -p /var/lib/matrix-synapse - chmod 700 /var/lib/matrix-synapse - chown -R matrix-synapse:matrix-synapse /var/lib/matrix-synapse - ${cfg.package}/bin/homeserver --config-path ${configFile} --keys-directory /var/lib/matrix-synapse/ --generate-keys + if ! test -e /var/lib/matrix-synapse; then + mkdir -p /var/lib/matrix-synapse + chmod 700 /var/lib/matrix-synapse + chown -R matrix-synapse:matrix-synapse /var/lib/matrix-synapse + ${cfg.package}/bin/homeserver --config-path ${configFile} --keys-directory /var/lib/matrix-synapse/ --generate-keys + fi ''; serviceConfig = { Type = "simple"; diff --git a/nixos/modules/services/monitoring/dd-agent.nix b/nixos/modules/services/monitoring/dd-agent.nix index bd8d9950f77c..a98b0f2f0f85 100644 --- a/nixos/modules/services/monitoring/dd-agent.nix +++ b/nixos/modules/services/monitoring/dd-agent.nix @@ -72,6 +72,7 @@ let postgresqlConfig = pkgs.writeText "postgres.yaml" cfg.postgresqlConfig; nginxConfig = pkgs.writeText "nginx.yaml" cfg.nginxConfig; mongoConfig = pkgs.writeText "mongo.yaml" cfg.mongoConfig; + jmxConfig = pkgs.writeText "jmx.yaml" cfg.jmxConfig; etcfiles = [ { source = ddConf; @@ -94,6 +95,10 @@ let (optional (cfg.mongoConfig != null) { source = mongoConfig; target = "dd-agent/conf.d/mongo.yaml"; + }) ++ + (optional (cfg.jmxConfig != null) + { source = jmxConfig; + target = "dd-agent/conf.d/jmx.yaml"; }); in { @@ -141,6 +146,13 @@ in { default = null; type = types.uniq (types.nullOr types.string); }; + + jmxConfig = mkOption { + description = "JMX integration configuration"; + default = null; + type = types.uniq (types.nullOr types.string); + }; + }; config = mkIf cfg.enable { @@ -167,7 +179,7 @@ in { Restart = "always"; RestartSec = 2; }; - restartTriggers = [ pkgs.dd-agent ddConf diskConfig networkConfig postgresqlConfig nginxConfig mongoConfig ]; + restartTriggers = [ pkgs.dd-agent ddConf diskConfig networkConfig postgresqlConfig nginxConfig mongoConfig jmxConfig ]; }; systemd.services.dogstatsd = { @@ -183,7 +195,21 @@ in { Restart = "always"; RestartSec = 2; }; - restartTriggers = [ pkgs.dd-agent ddConf diskConfig networkConfig postgresqlConfig nginxConfig mongoConfig ]; + restartTriggers = [ pkgs.dd-agent ddConf diskConfig networkConfig postgresqlConfig nginxConfig mongoConfig jmxConfig ]; + }; + + systemd.services.dd-jmxfetch = lib.mkIf (cfg.jmxConfig != null) { + description = "Datadog JMX Fetcher"; + path = [ pkgs."dd-agent" pkgs.python pkgs.sysstat pkgs.procps pkgs.jdk ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = "${pkgs.dd-agent}/bin/dd-jmxfetch"; + User = "datadog"; + Group = "datadog"; + Restart = "always"; + RestartSec = 2; + }; + restartTriggers = [ pkgs.dd-agent ddConf diskConfig networkConfig postgresqlConfig nginxConfig mongoConfig jmxConfig ]; }; environment.etc = etcfiles; diff --git a/nixos/modules/services/networking/firewall.nix b/nixos/modules/services/networking/firewall.nix index 9221fe155777..138153306dd8 100644 --- a/nixos/modules/services/networking/firewall.nix +++ b/nixos/modules/services/networking/firewall.nix @@ -101,9 +101,22 @@ let # Perform a reverse-path test to refuse spoofers # For now, we just drop, as the raw table doesn't have a log-refuse yet ${optionalString (kernelHasRPFilter && cfg.checkReversePath) '' - if ! ip46tables -A PREROUTING -t raw -m rpfilter --invert -j DROP; then - echo "<2>failed to initialise rpfilter support" >&2 - fi + # Clean up rpfilter rules + ip46tables -t raw -D PREROUTING -j nixos-fw-rpfilter 2> /dev/null || true + ip46tables -t raw -F nixos-fw-rpfilter 2> /dev/null || true + ip46tables -t raw -N nixos-fw-rpfilter 2> /dev/null || true + + ip46tables -t raw -A nixos-fw-rpfilter -m rpfilter -j RETURN + + # Allows this host to act as a DHCPv4 server + iptables -t raw -A nixos-fw-rpfilter -s 0.0.0.0 -d 255.255.255.255 -p udp --sport 68 --dport 67 -j RETURN + + ${optionalString cfg.logReversePathDrops '' + ip46tables -t raw -A nixos-fw-rpfilter -j LOG --log-level info --log-prefix "rpfilter drop: " + ''} + ip46tables -t raw -A nixos-fw-rpfilter -j DROP + + ip46tables -t raw -A PREROUTING -j nixos-fw-rpfilter ''} # Accept all traffic on the trusted interfaces. @@ -188,9 +201,7 @@ let ip46tables -D INPUT -j nixos-fw 2>/dev/null || true ${optionalString (kernelHasRPFilter && cfg.checkReversePath) '' - if ! ip46tables -D PREROUTING -t raw -m rpfilter --invert -j DROP; then - echo "<2>failed to stop rpfilter support" >&2 - fi + ip46tables -t raw -D PREROUTING -j nixos-fw-rpfilter 2>/dev/null || true ''} ${cfg.extraStopCommands} @@ -376,6 +387,16 @@ in ''; }; + networking.firewall.logReversePathDrops = mkOption { + default = false; + type = types.bool; + description = + '' + Logs dropped packets failing the reverse path filter test if + the option networking.firewall.checkReversePath is enabled. + ''; + }; + networking.firewall.connectionTrackingModules = mkOption { default = [ "ftp" ]; example = [ "ftp" "irc" "sane" "sip" "tftp" "amanda" "h323" "netbios_sn" "pptp" "snmp" ]; diff --git a/nixos/modules/services/networking/syncthing.nix b/nixos/modules/services/networking/syncthing.nix index 98f4faabba26..b44b03dc0bf3 100644 --- a/nixos/modules/services/networking/syncthing.nix +++ b/nixos/modules/services/networking/syncthing.nix @@ -114,8 +114,8 @@ in environment.systemPackages = [ cfg.package ]; - systemd.services.syncthing = mkIf cfg.systemService - header // { + systemd.services = mkIf cfg.systemService { + syncthing = header // { wantedBy = [ "multi-user.target" ]; serviceConfig = service // { User = cfg.user; @@ -124,6 +124,7 @@ in ExecStart = "${cfg.package}/bin/syncthing -no-browser -home=${cfg.dataDir}"; }; }; + }; systemd.user.services.syncthing = header // { diff --git a/nixos/modules/services/networking/tinc.nix b/nixos/modules/services/networking/tinc.nix index 9330e6c92ba8..8da0f817ae2a 100644 --- a/nixos/modules/services/networking/tinc.nix +++ b/nixos/modules/services/networking/tinc.nix @@ -157,6 +157,7 @@ in serviceConfig = { Type = "simple"; PIDFile = "/run/tinc.${network}.pid"; + Restart = "on-failure"; }; preStart = '' mkdir -p /etc/tinc/${network}/hosts diff --git a/nixos/modules/services/web-apps/tt-rss.nix b/nixos/modules/services/web-apps/tt-rss.nix index 541aac1d0ef1..b08070f1e366 100644 --- a/nixos/modules/services/web-apps/tt-rss.nix +++ b/nixos/modules/services/web-apps/tt-rss.nix @@ -17,6 +17,7 @@ let else cfg.database.port; poolName = "tt-rss"; + phpfpmSocketName = "/var/run/phpfpm/${poolName}.sock"; virtualHostName = "tt-rss"; tt-rss-config = pkgs.writeText "config.php" '' @@ -448,23 +449,21 @@ let root = "/var/lib/tt-rss"; in mkIf cfg.enable { - services.phpfpm.pools = if cfg.pool == "${poolName}" then { - "${poolName}" = { - listen = "/var/run/phpfpm/${poolName}.sock"; - extraConfig = '' - listen.owner = nginx - listen.group = nginx - listen.mode = 0600 - user = nginx - pm = dynamic - pm.max_children = 75 - pm.start_servers = 10 - pm.min_spare_servers = 5 - pm.max_spare_servers = 20 - pm.max_requests = 500 - catch_workers_output = 1 - ''; - }; + services.phpfpm.poolConfigs = if cfg.pool == "${poolName}" then { + "${poolName}" = '' + listen = "${phpfpmSocketName}"; + listen.owner = nginx + listen.group = nginx + listen.mode = 0600 + user = nginx + pm = dynamic + pm.max_children = 75 + pm.start_servers = 10 + pm.min_spare_servers = 5 + pm.max_spare_servers = 20 + pm.max_requests = 500 + catch_workers_output = 1 + ''; } else {}; # TODO: Re-enable after https://github.com/NixOS/nixpkgs/pull/15862 is merged @@ -486,7 +485,7 @@ let # locations."~ \.php$" = { # extraConfig = '' # fastcgi_split_path_info ^(.+\.php)(/.+)$; - # fastcgi_pass unix:${config.services.phpfpm.pools."${cfg.pool}".listen}; + # fastcgi_pass unix:${phpfpmSocketName}; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME ${root}/$fastcgi_script_name; diff --git a/nixos/modules/services/web-servers/lighttpd/cgit.nix b/nixos/modules/services/web-servers/lighttpd/cgit.nix index c8590e6a54e1..710fecc0c05c 100644 --- a/nixos/modules/services/web-servers/lighttpd/cgit.nix +++ b/nixos/modules/services/web-servers/lighttpd/cgit.nix @@ -63,6 +63,11 @@ in } ''; + systemd.services.lighttpd.preStart = '' + mkdir -p /var/cache/cgit + chown lighttpd:lighttpd /var/cache/cgit + ''; + }; } diff --git a/nixos/modules/services/web-servers/lighttpd/default.nix b/nixos/modules/services/web-servers/lighttpd/default.nix index 171503db4eec..84cd0a4095d9 100644 --- a/nixos/modules/services/web-servers/lighttpd/default.nix +++ b/nixos/modules/services/web-servers/lighttpd/default.nix @@ -224,12 +224,6 @@ in description = "Lighttpd Web Server"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; - preStart = '' - ${if cfg.cgit.enable then '' - mkdir -p /var/cache/cgit - chown lighttpd:lighttpd /var/cache/cgit - '' else ""} - ''; serviceConfig.ExecStart = "${pkgs.lighttpd}/sbin/lighttpd -D -f ${configFile}"; # SIGINT => graceful shutdown serviceConfig.KillSignal = "SIGINT"; diff --git a/nixos/modules/services/web-servers/phpfpm/default.nix b/nixos/modules/services/web-servers/phpfpm.nix index 6befddf9f522..2658d7117e37 100644 --- a/nixos/modules/services/web-servers/phpfpm/default.nix +++ b/nixos/modules/services/web-servers/phpfpm.nix @@ -9,12 +9,6 @@ let pidFile = "${stateDir}/phpfpm.pid"; - mkPool = n: p: '' - [${n}] - listen = ${p.listen} - ${p.extraConfig} - ''; - cfgFile = pkgs.writeText "phpfpm.conf" '' [global] pid = ${pidFile} @@ -22,7 +16,7 @@ let daemonize = yes ${cfg.extraConfig} - ${concatStringsSep "\n" (mapAttrsToList mkPool cfg.pools)} + ${concatStringsSep "\n" (mapAttrsToList (n: v: "[${n}]\n${v}") cfg.poolConfigs)} ''; phpIni = pkgs.writeText "php.ini" '' @@ -67,19 +61,33 @@ in { "Options appended to the PHP configuration file <filename>php.ini</filename>."; }; - pools = mkOption { - type = types.attrsOf (types.submodule (import ./pool-options.nix { - inherit lib; - })); + poolConfigs = mkOption { + type = types.attrsOf types.lines; default = {}; + example = literalExample '' + { mypool = ''' + listen = /run/phpfpm/mypool + user = nobody + pm = dynamic + pm.max_children = 75 + pm.start_servers = 10 + pm.min_spare_servers = 5 + pm.max_spare_servers = 20 + pm.max_requests = 500 + '''; + } + ''; description = '' - If no pools are defined, the phpfpm service is disabled. + A mapping between PHP FPM pool names and their configurations. + See the documentation on <literal>php-fpm.conf</literal> for + details on configuration directives. If no pools are defined, + the phpfpm service is disabled. ''; }; }; }; - config = mkIf (cfg.pools != {}) { + config = mkIf (cfg.poolConfigs != {}) { systemd.services.phpfpm = { wantedBy = [ "multi-user.target" ]; diff --git a/nixos/modules/services/web-servers/phpfpm/pool-options.nix b/nixos/modules/services/web-servers/phpfpm/pool-options.nix deleted file mode 100644 index cc688c2c48a2..000000000000 --- a/nixos/modules/services/web-servers/phpfpm/pool-options.nix +++ /dev/null @@ -1,35 +0,0 @@ -{ lib }: - -with lib; { - - options = { - - listen = mkOption { - type = types.str; - example = "/path/to/unix/socket"; - description = '' - The address on which to accept FastCGI requests. - ''; - }; - - extraConfig = mkOption { - type = types.lines; - example = '' - user = nobody - pm = dynamic - pm.max_children = 75 - pm.start_servers = 10 - pm.min_spare_servers = 5 - pm.max_spare_servers = 20 - pm.max_requests = 500 - ''; - - description = '' - Extra lines that go into the pool configuration. - See the documentation on <literal>php-fpm.conf</literal> for - details on configuration directives. - ''; - }; - }; -} - diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix index 44c87c0760cb..b3da25448029 100644 --- a/nixos/modules/services/x11/desktop-managers/gnome3.nix +++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix @@ -84,7 +84,7 @@ in { environment.gnome3.packageSet = mkOption { default = null; - example = literalExample "pkgs.gnome3_18"; + example = literalExample "pkgs.gnome3_20"; description = "Which GNOME 3 package set to use."; apply = p: if p == null then pkgs.gnome3 else p; }; diff --git a/nixos/modules/services/x11/desktop-managers/kde5.nix b/nixos/modules/services/x11/desktop-managers/kde5.nix index 9f9bbe246234..86b98c2b6601 100644 --- a/nixos/modules/services/x11/desktop-managers/kde5.nix +++ b/nixos/modules/services/x11/desktop-managers/kde5.nix @@ -148,7 +148,7 @@ in kde5.kde-gtk-config pkgs.phonon-backend-gstreamer - pkgs.kde5.phonon-backend-gstreamer + pkgs.qt5.phonon-backend-gstreamer ] # Plasma 5.5 and later has a Breeze GTK theme. @@ -214,7 +214,7 @@ in services.xserver.displayManager.sddm = { theme = "breeze"; themes = [ - kde5.extra-cmake-modules # for the setup-hook + kde5.ecm # for the setup-hook kde5.plasma-workspace kde5.breeze-icons (kde5.oxygen-icons or kde5.oxygen-icons5) diff --git a/nixos/modules/services/x11/window-managers/default.nix b/nixos/modules/services/x11/window-managers/default.nix index 94f1aa3add7e..f005decfa33c 100644 --- a/nixos/modules/services/x11/window-managers/default.nix +++ b/nixos/modules/services/x11/window-managers/default.nix @@ -18,6 +18,7 @@ in ./i3.nix ./jwm.nix ./metacity.nix + ./mwm.nix ./openbox.nix ./pekwm.nix ./notion.nix diff --git a/nixos/modules/services/x11/window-managers/mwm.nix b/nixos/modules/services/x11/window-managers/mwm.nix new file mode 100644 index 000000000000..31f7b725f747 --- /dev/null +++ b/nixos/modules/services/x11/window-managers/mwm.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.xserver.windowManager.mwm; +in +{ + ###### interface + options = { + services.xserver.windowManager.mwm.enable = mkEnableOption "mwm"; + }; + + ###### implementation + config = mkIf cfg.enable { + services.xserver.windowManager.session = singleton { + name = "mwm"; + start = '' + ${pkgs.motif}/bin/mwm & + waitPID=$! + ''; + }; + environment.systemPackages = [ pkgs.motif ]; + }; +} diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix index 35816c3a16dd..e7df2e6b4690 100644 --- a/nixos/modules/services/x11/xserver.nix +++ b/nixos/modules/services/x11/xserver.nix @@ -14,9 +14,6 @@ let # Map video driver names to driver packages. FIXME: move into card-specific modules. knownVideoDrivers = { virtualbox = { modules = [ kernelPackages.virtualboxGuestAdditions ]; driverName = "vboxvideo"; }; - ati = { modules = with pkgs.xorg; [ xf86videoati glamoregl ]; }; - intel = { modules = with pkgs.xorg; [ xf86videointel glamoregl ]; }; - modesetting = { modules = []; }; }; fontsForXServer = @@ -512,7 +509,7 @@ in XKB_BINDIR = "${xorg.xkbcomp}/bin"; # Needed for the Xkb extension. XORG_DRI_DRIVER_PATH = "/run/opengl-driver/lib/dri"; # !!! Depends on the driver selected at runtime. LD_LIBRARY_PATH = concatStringsSep ":" ( - [ "${xorg.libX11.out}/lib" "${xorg.libXext.out}/lib" ] + [ "${xorg.libX11.out}/lib" "${xorg.libXext.out}/lib" "/run/opengl-driver/lib" ] ++ concatLists (catAttrs "libPath" cfg.drivers)); } // cfg.displayManager.job.environment; diff --git a/nixos/modules/system/etc/setup-etc.pl b/nixos/modules/system/etc/setup-etc.pl index 89a49b972ff9..efda74161ff8 100644 --- a/nixos/modules/system/etc/setup-etc.pl +++ b/nixos/modules/system/etc/setup-etc.pl @@ -22,6 +22,33 @@ sub atomicSymlink { # current configuration. atomicSymlink $etc, $static or die; +# Returns 1 if the argument points to the files in /etc/static. That +# means either argument is a symlink to a file in /etc/static or a +# directory with all children being static. +sub isStatic { + my $path = shift; + + if (-l $path) { + my $target = readlink $path; + return substr($target, 0, length "/etc/static/") eq "/etc/static/"; + } + + if (-d $path) { + opendir DIR, "$path" or return 0; + my @names = readdir DIR or die; + closedir DIR; + + foreach my $name (@names) { + next if $name eq "." || $name eq ".."; + unless (isStatic("$path/$name")) { + return 0; + } + } + return 1; + } + + return 0; +} # Remove dangling symlinks that point to /etc/static. These are # configuration files that existed in a previous configuration but not @@ -63,6 +90,16 @@ sub link { my $target = "/etc/$fn"; File::Path::make_path(dirname $target); $created{$fn} = 1; + + # Rename doesn't work if target is directory. + if (-l $_ && -d $target) { + if (isStatic $target) { + rmtree $target or warn; + } else { + warn "$target directory contains user files. Symlinking may fail."; + } + } + if (-e "$_.mode") { my $mode = read_file("$_.mode"); chomp $mode; if ($mode eq "direct-symlink") { diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix index b3870caece0c..d83841452f95 100644 --- a/nixos/modules/virtualisation/containers.nix +++ b/nixos/modules/virtualisation/containers.nix @@ -6,37 +6,212 @@ let # The container's init script, a small wrapper around the regular # NixOS stage-2 init script. - containerInit = pkgs.writeScript "container-init" - '' - #! ${pkgs.stdenv.shell} -e + containerInit = (cfg: + let + renderExtraVeth = (name: cfg: + '' + echo "Bringing ${name} up" + ip link set dev ${name} up + ${optionalString (cfg . "localAddress" or null != null) '' + echo "Setting ip for ${name}" + ip addr add ${cfg . "localAddress"} dev ${name} + ''} + ${optionalString (cfg . "localAddress6" or null != null) '' + echo "Setting ip6 for ${name}" + ip -6 addr add ${cfg . "localAddress6"} dev ${name} + ''} + ${optionalString (cfg . "hostAddress" or null != null) '' + echo "Setting route to host for ${name}" + ip route add ${cfg . "hostAddress"} dev ${name} + ''} + ${optionalString (cfg . "hostAddress6" or null != null) '' + echo "Setting route6 to host for ${name}" + ip -6 route add ${cfg . "hostAddress6"} dev ${name} + ''} + '' + ); + in + pkgs.writeScript "container-init" + '' + #! ${pkgs.stdenv.shell} -e - # Initialise the container side of the veth pair. - if [ "$PRIVATE_NETWORK" = 1 ]; then + # Initialise the container side of the veth pair. + if [ "$PRIVATE_NETWORK" = 1 ]; then - ip link set host0 name eth0 - ip link set dev eth0 up + ip link set host0 name eth0 + ip link set dev eth0 up - if [ -n "$LOCAL_ADDRESS" ]; then - ip addr add $LOCAL_ADDRESS dev eth0 - fi - if [ -n "$LOCAL_ADDRESS6" ]; then - ip -6 addr add $LOCAL_ADDRESS6 dev eth0 + if [ -n "$LOCAL_ADDRESS" ]; then + ip addr add $LOCAL_ADDRESS dev eth0 + fi + if [ -n "$LOCAL_ADDRESS6" ]; then + ip -6 addr add $LOCAL_ADDRESS6 dev eth0 + fi + if [ -n "$HOST_ADDRESS" ]; then + ip route add $HOST_ADDRESS dev eth0 + ip route add default via $HOST_ADDRESS + fi + if [ -n "$HOST_ADDRESS6" ]; then + ip -6 route add $HOST_ADDRESS6 dev eth0 + ip -6 route add default via $HOST_ADDRESS6 + fi + + ${concatStringsSep "\n" (mapAttrsToList renderExtraVeth cfg . "extraVeths" or {})} + ip a + ip r fi - if [ -n "$HOST_ADDRESS" ]; then - ip route add $HOST_ADDRESS dev eth0 - ip route add default via $HOST_ADDRESS + + # Start the regular stage 1 script. + exec "$1" + '' + ); + + nspawnExtraVethArgs = (name: cfg: "--network-veth-extra=${name}"); + startScript = (cfg: + '' + mkdir -p -m 0755 "$root/etc" "$root/var/lib" + mkdir -p -m 0700 "$root/var/lib/private" "$root/root" /run/containers + if ! [ -e "$root/etc/os-release" ]; then + touch "$root/etc/os-release" + fi + + if ! [ -e "$root/etc/machine-id" ]; then + touch "$root/etc/machine-id" + fi + + mkdir -p -m 0755 \ + "/nix/var/nix/profiles/per-container/$INSTANCE" \ + "/nix/var/nix/gcroots/per-container/$INSTANCE" + + cp --remove-destination /etc/resolv.conf "$root/etc/resolv.conf" + + if [ "$PRIVATE_NETWORK" = 1 ]; then + extraFlags+=" --network-veth" + if [ -n "$HOST_BRIDGE" ]; then + extraFlags+=" --network-bridge=$HOST_BRIDGE" fi - if [ -n "$HOST_ADDRESS6" ]; then - ip -6 route add $HOST_ADDRESS6 dev eth0 - ip -6 route add default via $HOST_ADDRESS6 + fi + + ${if cfg . "extraVeths" or null != null then + ''extraFlags+=" ${concatStringsSep " " (mapAttrsToList nspawnExtraVethArgs cfg . "extraVeths" or {})}"'' + else + ''# No extra veth pairs to create'' + } + + for iface in $INTERFACES; do + extraFlags+=" --network-interface=$iface" + done + + for iface in $MACVLANS; do + extraFlags+=" --network-macvlan=$iface" + done + + # If the host is 64-bit and the container is 32-bit, add a + # --personality flag. + ${optionalString (config.nixpkgs.system == "x86_64-linux") '' + if [ "$(< ''${SYSTEM_PATH:-/nix/var/nix/profiles/per-container/$INSTANCE/system}/system)" = i686-linux ]; then + extraFlags+=" --personality=x86" fi + ''} + + # Run systemd-nspawn without startup notification (we'll + # wait for the container systemd to signal readiness). + EXIT_ON_REBOOT=1 \ + exec ${config.systemd.package}/bin/systemd-nspawn \ + --keep-unit \ + -M "$INSTANCE" -D "$root" $extraFlags \ + $EXTRA_NSPAWN_FLAGS \ + --notify-ready=yes \ + --bind-ro=/nix/store \ + --bind-ro=/nix/var/nix/db \ + --bind-ro=/nix/var/nix/daemon-socket \ + --bind="/nix/var/nix/profiles/per-container/$INSTANCE:/nix/var/nix/profiles" \ + --bind="/nix/var/nix/gcroots/per-container/$INSTANCE:/nix/var/nix/gcroots" \ + --setenv PRIVATE_NETWORK="$PRIVATE_NETWORK" \ + --setenv HOST_BRIDGE="$HOST_BRIDGE" \ + --setenv HOST_ADDRESS="$HOST_ADDRESS" \ + --setenv LOCAL_ADDRESS="$LOCAL_ADDRESS" \ + --setenv HOST_ADDRESS6="$HOST_ADDRESS6" \ + --setenv LOCAL_ADDRESS6="$LOCAL_ADDRESS6" \ + --setenv PATH="$PATH" \ + ${containerInit cfg} "''${SYSTEM_PATH:-/nix/var/nix/profiles/system}/init" + '' + ); + + preStartScript = (cfg: + '' + # Clean up existing machined registration and interfaces. + machinectl terminate "$INSTANCE" 2> /dev/null || true + + if [ "$PRIVATE_NETWORK" = 1 ]; then + ip link del dev "ve-$INSTANCE" 2> /dev/null || true + ip link del dev "vb-$INSTANCE" 2> /dev/null || true fi - # Start the regular stage 1 script, passing the bind-mounted - # notification socket from the host to allow the container - # systemd to signal readiness to the host systemd. - NOTIFY_SOCKET=/var/lib/private/host-notify exec "$1" - ''; + ${concatStringsSep "\n" ( + mapAttrsToList (name: cfg: + ''ip link del dev ${name} 2> /dev/null || true '' + ) cfg . "extraVeths" or {} + )} + '' + ); + postStartScript = (cfg: + let + ipcall = (cfg: ipcmd: variable: attribute: + if cfg . attribute or null == null then + '' + if [ -n "${variable}" ]; then + ${ipcmd} add ${variable} dev $ifaceHost + fi + '' + else + ''${ipcmd} add ${cfg . attribute} dev $ifaceHost'' + ); + renderExtraVeth = (name: cfg: + if cfg . "hostBridge" or null != null then + '' + # Add ${name} to bridge ${cfg.hostBridge} + ip link set dev ${name} master ${cfg.hostBridge} up + '' + else + '' + # Set IPs and routes for ${name} + ${optionalString (cfg . "hostAddress" or null != null) '' + ip addr add ${cfg . "hostAddress"} dev ${name} + ''} + ${optionalString (cfg . "hostAddress6" or null != null) '' + ip -6 addr add ${cfg . "hostAddress6"} dev ${name} + ''} + ${optionalString (cfg . "localAddress" or null != null) '' + ip route add ${cfg . "localAddress"} dev ${name} + ''} + ${optionalString (cfg . "localAddress6" or null != null) '' + ip -6 route add ${cfg . "localAddress6"} dev ${name} + ''} + '' + ); + in + '' + if [ "$PRIVATE_NETWORK" = 1 ]; then + if [ -z "$HOST_BRIDGE" ]; then + ifaceHost=ve-$INSTANCE + ip link set dev $ifaceHost up + + ${ipcall cfg "ip addr" "$HOST_ADDRESS" "hostAddress"} + ${ipcall cfg "ip -6 addr" "$HOST_ADDRESS6" "hostAddress6"} + ${ipcall cfg "ip route" "$LOCAL_ADDRESS" "localAddress"} + ${ipcall cfg "ip -6 route" "$LOCAL_ADDRESS6" "localAddress6"} + fi + ${concatStringsSep "\n" (mapAttrsToList renderExtraVeth cfg . "extraVeths" or {})} + fi + + # Get the leader PID so that we can signal it in + # preStop. We can't use machinectl there because D-Bus + # might be shutting down. FIXME: in systemd 219 we can + # just signal systemd-nspawn to do a clean shutdown. + machinectl show "$INSTANCE" | sed 's/Leader=\(.*\)/\1/;t;d' > "/run/containers/$INSTANCE.pid" + '' + ); system = config.nixpkgs.system; @@ -75,6 +250,63 @@ let mkBindFlags = bs: concatMapStrings mkBindFlag (lib.attrValues bs); + networkOptions = { + hostBridge = mkOption { + type = types.nullOr types.string; + default = null; + example = "br0"; + description = '' + Put the host-side of the veth-pair into the named bridge. + Only one of hostAddress* or hostBridge can be given. + ''; + }; + + hostAddress = mkOption { + type = types.nullOr types.str; + default = null; + example = "10.231.136.1"; + description = '' + The IPv4 address assigned to the host interface. + (Not used when hostBridge is set.) + ''; + }; + + hostAddress6 = mkOption { + type = types.nullOr types.string; + default = null; + example = "fc00::1"; + description = '' + The IPv6 address assigned to the host interface. + (Not used when hostBridge is set.) + ''; + }; + + localAddress = mkOption { + type = types.nullOr types.str; + default = null; + example = "10.231.136.2"; + description = '' + The IPv4 address assigned to the interface in the container. + If a hostBridge is used, this should be given with netmask to access + the whole network. Otherwise the default netmask is /32 and routing is + set up from localAddress to hostAddress and back. + ''; + }; + + localAddress6 = mkOption { + type = types.nullOr types.string; + default = null; + example = "fc00::2"; + description = '' + The IPv6 address assigned to the interface in the container. + If a hostBridge is used, this should be given with netmask to access + the whole network. Otherwise the default netmask is /128 and routing is + set up from localAddress6 to hostAddress6 and back. + ''; + }; + + }; + in { @@ -135,56 +367,6 @@ in ''; }; - hostBridge = mkOption { - type = types.nullOr types.string; - default = null; - example = "br0"; - description = '' - Put the host-side of the veth-pair into the named bridge. - Only one of hostAddress* or hostBridge can be given. - ''; - }; - - hostAddress = mkOption { - type = types.nullOr types.str; - default = null; - example = "10.231.136.1"; - description = '' - The IPv4 address assigned to the host interface. - (Not used when hostBridge is set.) - ''; - }; - - hostAddress6 = mkOption { - type = types.nullOr types.string; - default = null; - example = "fc00::1"; - description = '' - The IPv6 address assigned to the host interface. - (Not used when hostBridge is set.) - ''; - }; - - localAddress = mkOption { - type = types.nullOr types.str; - default = null; - example = "10.231.136.2"; - description = '' - The IPv4 address assigned to <literal>eth0</literal> - in the container. - ''; - }; - - localAddress6 = mkOption { - type = types.nullOr types.string; - default = null; - example = "fc00::2"; - description = '' - The IPv6 address assigned to <literal>eth0</literal> - in the container. - ''; - }; - interfaces = mkOption { type = types.listOf types.string; default = []; @@ -194,6 +376,15 @@ in ''; }; + extraVeths = mkOption { + type = types.attrsOf types.optionSet; + default = {}; + options = networkOptions; + description = '' + Extra veth-pairs to be created for the container + ''; + }; + autoStart = mkOption { type = types.bool; default = false; @@ -216,7 +407,7 @@ in ''; }; - }; + } // networkOptions; config = mkMerge [ (mkIf options.config.isDefined { @@ -274,110 +465,11 @@ in environment.INSTANCE = "%i"; environment.root = "/var/lib/containers/%i"; - preStart = - '' - # Clean up existing machined registration and interfaces. - machinectl terminate "$INSTANCE" 2> /dev/null || true - - if [ "$PRIVATE_NETWORK" = 1 ]; then - ip link del dev "ve-$INSTANCE" 2> /dev/null || true - ip link del dev "vb-$INSTANCE" 2> /dev/null || true - fi - ''; - - script = - '' - mkdir -p -m 0755 "$root/etc" "$root/var/lib" - mkdir -p -m 0700 "$root/var/lib/private" "$root/root" /run/containers - if ! [ -e "$root/etc/os-release" ]; then - touch "$root/etc/os-release" - fi - - if ! [ -e "$root/etc/machine-id" ]; then - touch "$root/etc/machine-id" - fi - - mkdir -p -m 0755 \ - "/nix/var/nix/profiles/per-container/$INSTANCE" \ - "/nix/var/nix/gcroots/per-container/$INSTANCE" - - cp --remove-destination /etc/resolv.conf "$root/etc/resolv.conf" - - if [ "$PRIVATE_NETWORK" = 1 ]; then - extraFlags+=" --network-veth" - if [ -n "$HOST_BRIDGE" ]; then - extraFlags+=" --network-bridge=$HOST_BRIDGE" - fi - fi + preStart = preStartScript {}; - for iface in $INTERFACES; do - extraFlags+=" --network-interface=$iface" - done + script = startScript {}; - for iface in $MACVLANS; do - extraFlags+=" --network-macvlan=$iface" - done - - # If the host is 64-bit and the container is 32-bit, add a - # --personality flag. - ${optionalString (config.nixpkgs.system == "x86_64-linux") '' - if [ "$(< ''${SYSTEM_PATH:-/nix/var/nix/profiles/per-container/$INSTANCE/system}/system)" = i686-linux ]; then - extraFlags+=" --personality=x86" - fi - ''} - - rm -f $root/var/lib/private/host-notify - - # Run systemd-nspawn without startup notification (we'll - # wait for the container systemd to signal readiness). - EXIT_ON_REBOOT=1 NOTIFY_SOCKET= \ - exec ${config.systemd.package}/bin/systemd-nspawn \ - --keep-unit \ - -M "$INSTANCE" -D "$root" $extraFlags \ - $EXTRA_NSPAWN_FLAGS \ - --bind-ro=/nix/store \ - --bind-ro=/nix/var/nix/db \ - --bind-ro=/nix/var/nix/daemon-socket \ - --bind=/run/systemd/notify:/var/lib/private/host-notify \ - --bind="/nix/var/nix/profiles/per-container/$INSTANCE:/nix/var/nix/profiles" \ - --bind="/nix/var/nix/gcroots/per-container/$INSTANCE:/nix/var/nix/gcroots" \ - --setenv PRIVATE_NETWORK="$PRIVATE_NETWORK" \ - --setenv HOST_BRIDGE="$HOST_BRIDGE" \ - --setenv HOST_ADDRESS="$HOST_ADDRESS" \ - --setenv LOCAL_ADDRESS="$LOCAL_ADDRESS" \ - --setenv HOST_ADDRESS6="$HOST_ADDRESS6" \ - --setenv LOCAL_ADDRESS6="$LOCAL_ADDRESS6" \ - --setenv PATH="$PATH" \ - ${containerInit} "''${SYSTEM_PATH:-/nix/var/nix/profiles/system}/init" - ''; - - postStart = - '' - if [ "$PRIVATE_NETWORK" = 1 ]; then - if [ -z "$HOST_BRIDGE" ]; then - ifaceHost=ve-$INSTANCE - ip link set dev $ifaceHost up - if [ -n "$HOST_ADDRESS" ]; then - ip addr add $HOST_ADDRESS dev $ifaceHost - fi - if [ -n "$HOST_ADDRESS6" ]; then - ip -6 addr add $HOST_ADDRESS6 dev $ifaceHost - fi - if [ -n "$LOCAL_ADDRESS" ]; then - ip route add $LOCAL_ADDRESS dev $ifaceHost - fi - if [ -n "$LOCAL_ADDRESS6" ]; then - ip -6 route add $LOCAL_ADDRESS6 dev $ifaceHost - fi - fi - fi - - # Get the leader PID so that we can signal it in - # preStop. We can't use machinectl there because D-Bus - # might be shutting down. FIXME: in systemd 219 we can - # just signal systemd-nspawn to do a clean shutdown. - machinectl show "$INSTANCE" | sed 's/Leader=\(.*\)/\1/;t;d' > "/run/containers/$INSTANCE.pid" - ''; + postStart = postStartScript {}; preStop = '' @@ -404,8 +496,6 @@ in Type = "notify"; - NotifyAccess = "all"; - # Note that on reboot, systemd-nspawn returns 133, so this # unit will be restarted. On poweroff, it returns 0, so the # unit won't be restarted. @@ -421,6 +511,8 @@ in # after the timeout). So send an ignored signal. KillMode = "mixed"; KillSignal = "WINCH"; + + DevicePolicy = "closed"; }; }; in { @@ -429,15 +521,20 @@ in [{ name = "container@"; value = unit; }] # declarative containers ++ (mapAttrsToList (name: cfg: nameValuePair "container@${name}" ( + unit // { + preStart = preStartScript cfg; + script = startScript cfg; + postStart = postStartScript cfg; + } // ( if cfg.autoStart then - unit // { + { wantedBy = [ "multi-user.target" ]; wants = [ "network.target" ]; after = [ "network.target" ]; restartTriggers = [ cfg.path ]; reloadIfChanged = true; } - else null + else {}) )) config.containers) )); @@ -466,11 +563,11 @@ in LOCAL_ADDRESS6=${cfg.localAddress6} ''} ''} - INTERFACES="${toString cfg.interfaces}" - ${optionalString cfg.autoStart '' - AUTO_START=1 - ''} - EXTRA_NSPAWN_FLAGS="${mkBindFlags cfg.bindMounts}" + INTERFACES="${toString cfg.interfaces}" + ${optionalString cfg.autoStart '' + AUTO_START=1 + ''} + EXTRA_NSPAWN_FLAGS="${mkBindFlags cfg.bindMounts}" ''; }) config.containers; |