diff options
34 files changed, 723 insertions, 608 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..b25c15b81fae --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*~ diff --git a/modules/config/networking.nix b/modules/config/networking.nix index 2b4be69cc51f..a91ce9c59e26 100644 --- a/modules/config/networking.nix +++ b/modules/config/networking.nix @@ -67,7 +67,7 @@ in '' + optionalString config.services.nscd.enable '' # Invalidate the nscd cache whenever resolv.conf is # regenerated. - libc_restart='${pkgs.upstart}/sbin/start invalidate-nscd' + libc_restart='${pkgs.systemd}/bin/systemctl start invalidate-nscd.service' '' + optionalString config.services.bind.enable '' # This hosts runs a full-blown DNS resolver. name_servers='127.0.0.1' diff --git a/modules/config/system-path.nix b/modules/config/system-path.nix index 38e5f076bcfd..3969be680980 100644 --- a/modules/config/system-path.nix +++ b/modules/config/system-path.nix @@ -16,9 +16,7 @@ let ''; requiredPackages = - [ config.system.sbin.modprobe # must take precedence over module_init_tools - config.system.build.upstart - config.environment.nix + [ config.environment.nix pkgs.acl pkgs.attr pkgs.bashInteractive # bash with ncurses support @@ -39,7 +37,6 @@ let pkgs.less pkgs.libcap pkgs.man - pkgs.module_init_tools pkgs.nano pkgs.ncurses pkgs.netcat @@ -50,10 +47,8 @@ let pkgs.procps pkgs.rsync pkgs.strace - pkgs.sysklogd pkgs.sysvtools pkgs.time - pkgs.udev pkgs.usbutils pkgs.utillinux extraManpages diff --git a/modules/module-list.nix b/modules/module-list.nix index 1e5ec300df5d..1046233c9839 100644 --- a/modules/module-list.nix +++ b/modules/module-list.nix @@ -48,7 +48,6 @@ ./programs/wvdial.nix ./rename.nix ./security/ca.nix - ./security/consolekit.nix ./security/pam.nix ./security/pam_usb.nix ./security/policykit.nix @@ -83,7 +82,7 @@ ./services/hardware/udev.nix ./services/hardware/udisks.nix ./services/hardware/upower.nix - ./services/logging/klogd.nix + #./services/logging/klogd.nix ./services/logging/logrotate.nix ./services/logging/logstash.nix ./services/logging/syslogd.nix @@ -169,7 +168,7 @@ ./services/system/nscd.nix ./services/system/uptimed.nix ./services/ttys/gpm.nix - ./services/ttys/mingetty.nix + ./services/ttys/agetty.nix ./services/web-servers/apache-httpd/default.nix ./services/web-servers/jboss/default.nix ./services/web-servers/tomcat.nix @@ -198,12 +197,11 @@ ./system/boot/kernel.nix ./system/boot/luksroot.nix ./system/boot/modprobe.nix + ./system/boot/shutdown.nix ./system/boot/stage-1.nix ./system/boot/stage-2.nix + ./system/boot/systemd.nix ./system/etc/etc.nix - ./system/upstart-events/control-alt-delete.nix - ./system/upstart-events/runlevel.nix - ./system/upstart-events/shutdown.nix ./system/upstart/upstart.nix ./tasks/cpu-freq.nix ./tasks/filesystems.nix diff --git a/modules/security/consolekit.nix b/modules/security/consolekit.nix deleted file mode 100644 index 28e1fec06010..000000000000 --- a/modules/security/consolekit.nix +++ /dev/null @@ -1,60 +0,0 @@ -{ config, pkgs, ... }: - -with pkgs.lib; - -let - - # `pam_console' maintains the set of locally logged in users in - # /var/run/console. This is obsolete, but D-Bus still uses it for - # its `at_console' feature. So maintain it using a ConsoleKit - # session script. Borrowed from - # http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/sys-auth/consolekit/files/pam-foreground-compat.ck - updateVarRunConsole = pkgs.writeTextFile { - name = "var-run-console.ck"; - destination = "/etc/ConsoleKit/run-session.d/var-run-console.ck"; - executable = true; - - text = - '' - #! ${pkgs.stdenv.shell} -e - PATH=${pkgs.coreutils}/bin:${pkgs.gnused}/bin:${pkgs.glibc}/bin - TAGDIR=/var/run/console - - [ -n "$CK_SESSION_USER_UID" ] || exit 1 - - TAGFILE="$TAGDIR/`getent passwd $CK_SESSION_USER_UID | cut -f 1 -d:`" - - if [ "$1" = "session_added" ]; then - mkdir -p "$TAGDIR" - echo "$CK_SESSION_ID" >> "$TAGFILE" - fi - - if [ "$1" = "session_removed" ] && [ -e "$TAGFILE" ]; then - sed -i "\%^$CK_SESSION_ID\$%d" "$TAGFILE" - [ -s "$TAGFILE" ] || rm -f "$TAGFILE" - fi - ''; - }; - -in - -{ - - config = { - - environment.systemPackages = [ pkgs.consolekit ]; - - services.dbus.packages = [ pkgs.consolekit ]; - - environment.etc = singleton - { source = (pkgs.buildEnv { - name = "consolekit-config"; - pathsToLink = [ "/etc/ConsoleKit" ]; - paths = [ pkgs.consolekit pkgs.udev updateVarRunConsole ]; - }) + "/etc/ConsoleKit"; - target = "ConsoleKit"; - }; - - }; - -} diff --git a/modules/security/pam.nix b/modules/security/pam.nix index 4fab7febc710..09803598db90 100644 --- a/modules/security/pam.nix +++ b/modules/security/pam.nix @@ -41,7 +41,7 @@ let # against the keys in the calling user's ~/.ssh/authorized_keys. # This is useful for "sudo" on password-less remote systems. sshAgentAuth ? false - , # If set, use ConsoleKit's PAM connector module to claim + , # If set, use systemd's PAM connector module to claim # ownership of audio devices etc. ownDevices ? false , # Whether to forward XAuth keys between users. Mostly useful @@ -104,7 +104,7 @@ let ${optionalString config.krb5.enable "session optional ${pam_krb5}/lib/security/pam_krb5.so"} ${optionalString ownDevices - "session optional ${pkgs.consolekit}/lib/security/pam_ck_connector.so"} + "session optional ${pkgs.systemd}/lib/security/pam_systemd.so"} ${optionalString forwardXAuth "session optional pam_xauth.so xauthpath=${pkgs.xorg.xauth}/bin/xauth systemuser=99"} ${optionalString (limits != []) diff --git a/modules/services/hardware/udev.nix b/modules/services/hardware/udev.nix index 3bbf24bb3791..8d66982fb5cb 100644 --- a/modules/services/hardware/udev.nix +++ b/modules/services/hardware/udev.nix @@ -4,7 +4,9 @@ with pkgs.lib; let - inherit (pkgs) stdenv writeText udev procps; + inherit (pkgs) stdenv writeText procps; + + udev = config.system.build.systemd; cfg = config.services.udev; @@ -24,20 +26,16 @@ let udevRules = stdenv.mkDerivation { name = "udev-rules"; buildCommand = '' - ensureDir $out + mkdir -p $out shopt -s nullglob # Set a reasonable $PATH for programs called by udev rules. echo 'ENV{PATH}="${udevPath}/bin:${udevPath}/sbin"' > $out/00-path.rules - # Set the firmware search path so that the firmware.sh helper - # called by 50-firmware.rules works properly. - echo 'ENV{FIRMWARE_DIRS}="/root/test-firmware ${toString config.hardware.firmware}"' >> $out/00-path.rules - # Add the udev rules from other packages. for i in ${toString cfg.packages}; do echo "Adding rules for package $i" - for j in $i/*/udev/rules.d/*; do + for j in $i/{etc,lib}/udev/rules.d/*; do echo "Copying $j to $out/$(basename $j)" echo "# Copied from $j" > $out/$(basename $j) cat $j >> $out/$(basename $j) @@ -53,12 +51,7 @@ let --replace \"/bin/mount \"${pkgs.utillinux}/bin/mount done - # If auto-configuration is disabled, then remove - # udev's 80-drivers.rules file, which contains rules for - # automatically calling modprobe. - ${if !config.boot.hardwareScan then "rm $out/80-drivers.rules" else ""} - - echo -n "Checking that all programs called by relative paths in udev rules exist in ${udev}/lib/udev ... " + echo -n "Checking that all programs called by relative paths in udev rules exist in ${udev}/lib/udev... " import_progs=$(grep 'IMPORT{program}="[^/$]' $out/* | sed -e 's/.*IMPORT{program}="\([^ "]*\)[ "].*/\1/' | uniq) run_progs=$(grep -v '^[[:space:]]*#' $out/* | grep 'RUN+="[^/$]' | @@ -72,7 +65,7 @@ let done echo "OK" - echo -n "Checking that all programs call by absolute paths in udev rules exist ... " + echo -n "Checking that all programs called by absolute paths in udev rules exist... " import_progs=$(grep 'IMPORT{program}="\/' $out/* | sed -e 's/.*IMPORT{program}="\([^ "]*\)[ "].*/\1/' | uniq) run_progs=$(grep -v '^[[:space:]]*#' $out/* | grep 'RUN+="/' | @@ -90,24 +83,9 @@ let for i in ${toString cfg.packages}; do grep -l '\(RUN+\|IMPORT{program}\)="\(/usr\)\?/s\?bin' $i/*/udev/rules.d/* || true done - - # Use the persistent device rules (naming for CD/DVD and - # network devices) stored in - # /var/lib/udev/rules.d/70-persistent-{cd,net}.rules. These are - # modified by the write_{cd,net}_rules helpers called from - # 75-cd-aliases-generator.rules and - # 75-persistent-net-generator.rules. - ln -sv /var/lib/udev/rules.d/70-persistent-cd.rules $out/ - ln -sv /var/lib/udev/rules.d/70-persistent-net.rules $out/ ''; # */ }; - # The udev configuration file. - conf = writeText "udev.conf" '' - udev_rules="${udevRules}" - #udev_log="debug" - ''; - # Udev has a 512-character limit for ENV{PATH}, so create a symlink # tree to work around this. udevPath = pkgs.buildEnv { @@ -207,61 +185,15 @@ in services.udev.extraRules = nixosRules; - services.udev.packages = [ pkgs.udev extraUdevRules ]; - - services.udev.path = [ pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.utillinux pkgs.udev ]; - - jobs.udev = - { startOn = "startup"; - - environment = { UDEV_CONFIG_FILE = conf; }; - - path = [ udev ]; - - preStart = - '' - echo "" > /proc/sys/kernel/hotplug || true + services.udev.packages = [ extraUdevRules ]; - mkdir -p /var/lib/udev/rules.d - touch /var/lib/udev/rules.d/70-persistent-cd.rules /var/lib/udev/rules.d/70-persistent-net.rules + services.udev.path = [ pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.utillinux udev ]; - mkdir -p /dev/.udev # !!! bug in udev? - ''; - - daemonType = "fork"; - - exec = "udevd --daemon"; - - postStart = - '' - # Do the loading of additional stage 2 kernel modules. - # This needs to be done while udevd is running, because - # the modules may call upon udev's firmware loading rule. - for i in ${toString config.boot.kernelModules}; do - echo "loading kernel module ‘$i’..." - ${config.system.sbin.modprobe}/sbin/modprobe $i || true - done - ''; - }; - - jobs.udevtrigger = - { startOn = "started udev"; - - task = true; - - path = [ udev ]; - - script = - '' - # Let udev create device nodes for all modules that have already - # been loaded into the kernel (or for which support is built into - # the kernel). - udevadm trigger --action=add - udevadm settle || true # wait for udev to finish - - initctl emit -n new-devices - ''; - }; + environment.etc = + [ { source = udevRules; + target = "udev/rules.d"; + } + ]; }; diff --git a/modules/services/logging/syslogd.nix b/modules/services/logging/syslogd.nix index 715cfc0f9e6f..bfe7352122c0 100644 --- a/modules/services/logging/syslogd.nix +++ b/modules/services/logging/syslogd.nix @@ -96,7 +96,7 @@ in jobs.syslogd = { description = "Syslog daemon"; - startOn = "started udev"; + #startOn = "started udev"; environment = { TZ = config.time.timeZone; }; diff --git a/modules/services/misc/nix-daemon.nix b/modules/services/misc/nix-daemon.nix index 31b81a13e363..ea13def39d60 100644 --- a/modules/services/misc/nix-daemon.nix +++ b/modules/services/misc/nix-daemon.nix @@ -4,6 +4,8 @@ with pkgs.lib; let + cfg = config.nix; + inherit (config.environment) nix; makeNixBuildUser = nr: @@ -74,9 +76,7 @@ in gc-keep-outputs = true gc-keep-derivations = true "; - description = " - This option allows to append lines to nix.conf. - "; + description = "Additional text appended to <filename>nix.conf<filename>."; }; distributedBuilds = mkOption { @@ -169,11 +169,9 @@ in # actually a shell script. envVars = mkOption { internal = true; - default = ""; - type = types.string; - description = " - Environment variables used by Nix. - "; + default = {}; + type = types.attrs; + description = "Environment variables used by Nix."; }; nrBuildUsers = mkOption { @@ -208,14 +206,14 @@ in # /bin/sh won't work. binshDeps = pkgs.writeReferencesToFile config.system.build.binsh; in - pkgs.runCommand "nix.conf" {extraOptions = config.nix.extraOptions; } '' + pkgs.runCommand "nix.conf" {extraOptions = cfg.extraOptions; } '' extraPaths=$(for i in $(cat ${binshDeps}); do if test -d $i; then echo $i; fi; done) cat > $out <<END # WARNING: this file is generated. build-users-group = nixbld - build-max-jobs = ${toString (config.nix.maxJobs)} - build-use-chroot = ${if config.nix.useChroot then "true" else "false"} - build-chroot-dirs = ${toString config.nix.chrootDirs} $(echo $extraPaths) + build-max-jobs = ${toString (cfg.maxJobs)} + build-use-chroot = ${if cfg.useChroot then "true" else "false"} + build-chroot-dirs = ${toString cfg.chrootDirs} $(echo $extraPaths) $extraOptions END ''; @@ -223,7 +221,7 @@ in } ] - ++ optional (config.nix.distributedBuilds && !config.nix.manualNixMachines) + ++ optional (cfg.distributedBuilds && !cfg.manualNixMachines) { # List of machines for distributed Nix builds in the format expected # by build-remote.pl. source = pkgs.writeText "nix.machines" @@ -233,37 +231,69 @@ in + " ${machine.sshKey} ${toString machine.maxJobs} " + (if machine ? speedFactor then toString machine.speedFactor else "1" ) + "\n" - ) config.nix.buildMachines)); + ) cfg.buildMachines)); target = "nix.machines"; }; - jobs.nixDaemon = - { name = "nix-daemon"; + boot.systemd.units."nix-daemon.socket" = + { wantedBy = [ "sockets.target" ]; + text = + '' + [Unit] + Description=Nix Daemon Socket + Before=multi-user.target - startOn = "startup"; + [Socket] + ListenStream=/nix/var/nix/daemon-socket/socket + ''; + }; + + boot.systemd.services."nix-daemon.service" = + { description = "Nix Daemon"; path = [ nix pkgs.openssl pkgs.utillinux ] - ++ optionals config.nix.distributedBuilds [ pkgs.openssh pkgs.gzip ]; + ++ optionals cfg.distributedBuilds [ pkgs.openssh pkgs.gzip ]; - script = - '' - ${config.nix.envVars} - exec \ - nice -n ${builtins.toString config.nix.daemonNiceLevel} \ - ionice -n ${builtins.toString config.nix.daemonIONiceLevel} \ - nix-worker --daemon > /dev/null 2>&1 - ''; + environment = cfg.envVars; - extraConfig = + serviceConfig = '' - limit nofile 4096 4096 + ExecStart=${nix}/bin/nix-worker --daemon + KillMode=process + PIDFile=/run/sshd.pid + Nice=${toString cfg.daemonNiceLevel} + IOSchedulingPriority=${toString cfg.daemonIONiceLevel} + LimitNOFILE=4096 ''; }; + + nix.envVars = + { NIX_CONF_DIR = "/etc/nix"; + + # Enable the copy-from-other-stores substituter, which allows builds + # to be sped up by copying build results from remote Nix stores. To + # do this, mount the remote file system on a subdirectory of + # /var/run/nix/remote-stores. + NIX_OTHER_STORES = "/var/run/nix/remote-stores/*/nix"; + } + + // optionalAttrs cfg.distributedBuilds { + NIX_BUILD_HOOK = "${config.environment.nix}/libexec/nix/build-remote.pl"; + NIX_REMOTE_SYSTEMS = "/etc/nix.machines"; + NIX_CURRENT_LOAD = "/var/run/nix/current-load"; + } + + # !!! These should not be defined here, but in some general proxy configuration module! + // optionalAttrs (cfg.proxy != "") { + http_proxy = cfg.proxy; + https_proxy = cfg.proxy; + ftp_proxy = cfg.proxy; + }; environment.shellInit = '' # Set up the environment variables for running Nix. - ${config.nix.envVars} + ${concatMapStrings (n: "export ${n}=\"${getAttr n cfg.envVars}\"\n") (attrNames cfg.envVars)} # Set up secure multi-user builds: non-root users build through the # Nix daemon. @@ -274,29 +304,7 @@ in fi ''; - nix.envVars = - '' - export NIX_CONF_DIR=/etc/nix - - # Enable the copy-from-other-stores substituter, which allows builds - # to be sped up by copying build results from remote Nix stores. To - # do this, mount the remote file system on a subdirectory of - # /var/run/nix/remote-stores. - export NIX_OTHER_STORES=/var/run/nix/remote-stores/*/nix - '' # */ - + optionalString config.nix.distributedBuilds '' - export NIX_BUILD_HOOK=${config.environment.nix}/libexec/nix/build-remote.pl - export NIX_REMOTE_SYSTEMS=/etc/nix.machines - export NIX_CURRENT_LOAD=/var/run/nix/current-load - '' - # !!! These should not be defined here, but in some general proxy configuration module! - + optionalString (config.nix.proxy != "") '' - export http_proxy=${config.nix.proxy} - export https_proxy=${config.nix.proxy} - export ftp_proxy=${config.nix.proxy} - ''; - - users.extraUsers = map makeNixBuildUser (range 1 config.nix.nrBuildUsers); + users.extraUsers = map makeNixBuildUser (range 1 cfg.nrBuildUsers); system.activationScripts.nix = stringAfter [ "etc" "users" ] '' diff --git a/modules/services/monitoring/nagios/default.nix b/modules/services/monitoring/nagios/default.nix index 6d2fe3f2acec..3c32a3c25ec9 100644 --- a/modules/services/monitoring/nagios/default.nix +++ b/modules/services/monitoring/nagios/default.nix @@ -159,12 +159,7 @@ in environment.systemPackages = [ pkgs.nagios ]; jobs.nagios = - { # Run `nagios -v' to check the validity of the configuration file so - # that a nixos-rebuild fails *before* we kill the running Nagios - # daemon. - buildHook = "${pkgs.nagios}/bin/nagios -v ${nagiosCfgFile}"; - - description = "Nagios monitoring daemon"; + { description = "Nagios monitoring daemon"; startOn = "started network-interfaces"; stopOn = "stopping network-interfaces"; diff --git a/modules/services/networking/ssh/sshd.nix b/modules/services/networking/ssh/sshd.nix index ea60e591c14e..d89978a852c0 100644 --- a/modules/services/networking/ssh/sshd.nix +++ b/modules/services/networking/ssh/sshd.nix @@ -39,6 +39,7 @@ let ); userOptions = { + openssh.authorizedKeys = { preserveExistingKeys = mkOption { @@ -77,6 +78,7 @@ let }; }; + }; mkAuthkeyScript = @@ -136,7 +138,6 @@ let ${userLoop} ''; - in { @@ -314,24 +315,33 @@ in } ]; - jobs.sshd = { + boot.systemd.services."set-ssh-keys.service" = + { description = "Update authorized SSH keys"; - description = "OpenSSH server"; + wantedBy = [ "multi-user.target" ]; - startOn = "started network-interfaces"; + script = mkAuthkeyScript; - environment = { - LD_LIBRARY_PATH = nssModulesPath; - # Duplicated from bashrc. OpenSSH needs a patch for this. - LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive"; - }; + serviceConfig = + '' + Type=oneshot + RemainAfterExit=true + ''; + }; + + boot.systemd.services."sshd.service" = + { description = "SSH daemon"; + + wantedBy = [ "multi-user.target" ]; + after = [ "set-ssh-keys.service" ]; - path = [ pkgs.openssh pkgs.gnused ]; + path = [ pkgs.openssh ]; + + environment.LD_LIBRARY_PATH = nssModulesPath; + environment.LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive"; preStart = '' - ${mkAuthkeyScript} - mkdir -m 0755 -p /etc/ssh if ! test -f ${cfg.hostKeyPath}; then @@ -339,12 +349,15 @@ in fi ''; - daemonType = "fork"; - - exec = + serviceConfig = '' - ${pkgs.openssh}/sbin/sshd -h ${cfg.hostKeyPath} \ - -f ${pkgs.writeText "sshd_config" cfg.extraConfig} + ExecStart=\ + ${pkgs.openssh}/sbin/sshd -h ${cfg.hostKeyPath} \ + -f ${pkgs.writeText "sshd_config" cfg.extraConfig} + Restart=always + Type=forking + KillMode=process + PIDFile=/run/sshd.pid ''; }; @@ -352,6 +365,8 @@ in services.openssh.extraConfig = '' + PidFile /run/sshd.pid + Protocol 2 UsePAM ${if cfg.usePAM then "yes" else "no"} diff --git a/modules/services/system/dbus.nix b/modules/services/system/dbus.nix index f7fbb23d0a78..bd5c290d5826 100644 --- a/modules/services/system/dbus.nix +++ b/modules/services/system/dbus.nix @@ -116,6 +116,33 @@ in gid = config.ids.gids.messagebus; }; + # FIXME: these are copied verbatim from the dbus source tree. We + # should install and use the originals. + boot.systemd.units."dbus.socket".text = + '' + [Unit] + Description=D-Bus System Message Bus Socket + + [Socket] + ListenStream=/var/run/dbus/system_bus_socket + ''; + + boot.systemd.units."dbus.service".text = + '' + [Unit] + Description=D-Bus System Message Bus + Requires=dbus.socket + After=syslog.target + + [Service] + ExecStartPre=${pkgs.dbus_tools}/bin/dbus-uuidgen --ensure + ExecStartPre=-${pkgs.coreutils}/bin/rm -f /var/run/dbus/pid + ExecStart=${pkgs.dbus_daemon}/bin/dbus-daemon --system --address=systemd: --nofork --systemd-activation + ExecReload=${pkgs.dbus_tools}/dbus-send --print-reply --system --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig + OOMScoreAdjust=-900 + ''; + + /* jobs.dbus = { startOn = "started udev and started syslogd"; @@ -138,15 +165,6 @@ in exec = "dbus-daemon --system"; - /* - postStart = - '' - # Signal Upstart to connect to the system bus. This - # allows ‘initctl’ to work for non-root users. - kill -USR1 1 - ''; - */ - postStop = '' # !!! Hack: doesn't belong here. @@ -157,6 +175,7 @@ in fi ''; }; + */ security.setuidOwners = singleton { program = "dbus-daemon-launch-helper"; diff --git a/modules/services/system/nscd.nix b/modules/services/system/nscd.nix index 6f35cd30f582..b2596dbb4139 100644 --- a/modules/services/system/nscd.nix +++ b/modules/services/system/nscd.nix @@ -20,15 +20,14 @@ in enable = mkOption { default = true; - description = " - Whether to enable the Name Service Cache Daemon. - "; + description = "Whether to enable the Name Service Cache Daemon."; }; }; }; + ###### implementation config = mkIf config.services.nscd.enable { diff --git a/modules/services/ttys/mingetty.nix b/modules/services/ttys/agetty.nix index e5dbc07aeb0f..42d276c96664 100644 --- a/modules/services/ttys/mingetty.nix +++ b/modules/services/ttys/agetty.nix @@ -10,6 +10,7 @@ with pkgs.lib; services.mingetty = { + # FIXME ttys = mkOption { default = if pkgs.stdenv.isArm @@ -56,23 +57,39 @@ with pkgs.lib; config = { # Generate a separate job for each tty. - jobs = listToAttrs (map (tty: nameValuePair tty { - - startOn = - # On tty1 we should always wait for mountall, since it may - # start an emergency-shell job. - if config.services.mingetty.waitOnMounts || tty == "tty1" - then "stopped udevtrigger and filesystem" - else "stopped udevtrigger"; # !!! should start as soon as the tty device is created - - path = [ pkgs.mingetty ]; - - exec = "mingetty --loginprog=${pkgs.shadow}/bin/login --noclear ${tty}"; - - environment.LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive"; - - }) config.services.mingetty.ttys); - + boot.systemd.units."getty@.service".text = + '' + [Unit] + Description=Getty on %I + Documentation=man:agetty(8) + After=systemd-user-sessions.service plymouth-quit-wait.service + + # If additional gettys are spawned during boot then we should make + # sure that this is synchronized before getty.target, even though + # getty.target didn't actually pull it in. + Before=getty.target + IgnoreOnIsolate=yes + + [Service] + Environment=TERM=linux + Environment=LOCALE_ARCHIVE=/run/current-system/sw/lib/locale/locale-archive + ExecStart=@${pkgs.utillinux}/sbin/agetty agetty --noclear --login-program ${pkgs.shadow}/bin/login %I 38400 + Type=idle + Restart=always + RestartSec=0 + UtmpIdentifier=%I + TTYPath=/dev/%I + TTYReset=yes + TTYVHangup=yes + TTYVTDisallocate=yes + KillMode=process + IgnoreSIGPIPE=no + + # Some login implementations ignore SIGTERM, so we send SIGHUP + # instead, to ensure that login terminates cleanly. + KillSignal=SIGHUP + ''; + environment.etc = singleton { # Friendly greeting on the virtual consoles. source = pkgs.writeText "issue" '' @@ -83,6 +100,7 @@ with pkgs.lib; ''; target = "issue"; }; + }; } diff --git a/modules/services/web-servers/apache-httpd/default.nix b/modules/services/web-servers/apache-httpd/default.nix index ba02c6ead43f..ceb93cd8b016 100644 --- a/modules/services/web-servers/apache-httpd/default.nix +++ b/modules/services/web-servers/apache-httpd/default.nix @@ -557,18 +557,7 @@ in ''; jobs.httpd = - { # Statically verify the syntactic correctness of the generated - # httpd.conf. !!! this is impure! It doesn't just check for - # syntax, but also whether the Apache user/group exist, - # whether SSL keys exist, etc. - buildHook = - '' - echo - echo '=== Checking the generated Apache configuration file ===' - ${httpd}/bin/httpd -f ${httpdConf} -t || true - ''; - - description = "Apache HTTPD"; + { description = "Apache HTTPD"; startOn = "started networking and filesystem" # Hacky. Some subservices depend on Postgres diff --git a/modules/services/x11/display-managers/default.nix b/modules/services/x11/display-managers/default.nix index cdfd271ee65c..528b3a6f7276 100644 --- a/modules/services/x11/display-managers/default.nix +++ b/modules/services/x11/display-managers/default.nix @@ -53,12 +53,6 @@ let fi ''} - # Start a ConsoleKit session so that we get ownership of various - # devices. - if test -z "$XDG_SESSION_COOKIE"; then - exec ${pkgs.consolekit}/bin/ck-launch-session "$0" "$sessionType" - fi - # Handle being called by kdm. if test "''${1:0:1}" = /; then eval exec "$1"; fi diff --git a/modules/services/x11/display-managers/kdm.nix b/modules/services/x11/display-managers/kdm.nix index 838a4ed90330..ec4d033a597f 100644 --- a/modules/services/x11/display-managers/kdm.nix +++ b/modules/services/x11/display-managers/kdm.nix @@ -111,7 +111,7 @@ in logsXsession = true; }; - security.pam.services = [ { name = "kde"; allowNullPassword = true; } ]; + security.pam.services = [ { name = "kde"; allowNullPassword = true; ownDevices = true; } ]; users.extraUsers = singleton { name = "kdm"; diff --git a/modules/services/x11/display-managers/slim.nix b/modules/services/x11/display-managers/slim.nix index 97c5f1d1b2b8..fc4df80d810a 100644 --- a/modules/services/x11/display-managers/slim.nix +++ b/modules/services/x11/display-managers/slim.nix @@ -115,7 +115,7 @@ in # Allow null passwords so that the user can login as root on the # installation CD. - security.pam.services = [ { name = "slim"; allowNullPassword = true; } ]; + security.pam.services = [ { name = "slim"; allowNullPassword = true; ownDevices = true; } ]; }; diff --git a/modules/services/x11/xserver.nix b/modules/services/x11/xserver.nix index 97424308c273..5d795e5d57dc 100644 --- a/modules/services/x11/xserver.nix +++ b/modules/services/x11/xserver.nix @@ -377,15 +377,13 @@ in environment.pathsToLink = [ "/etc/xdg" "/share/xdg" "/share/applications" "/share/icons" "/share/pixmaps" ]; - jobs."xserver-start-check" = - { startOn = if cfg.autorun then "filesystem and stopped udevtrigger" else ""; - stopOn = ""; - task = true; - script = "grep -qv noX11 /proc/cmdline && start xserver || true"; - }; + boot.systemd.defaultUnit = mkIf cfg.autorun "graphical.target"; + + boot.systemd.services."xserver.service" = + { wantedBy = [ "graphical.target" ]; + after = [ "systemd-udev-settle.service" ]; - jobs.xserver = - { restartIfChanged = false; + #restartIfChanged = false; environment = { FONTCONFIG_FILE = "/etc/fonts/fonts.conf"; # !!! cleanup diff --git a/modules/system/activation/top-level.nix b/modules/system/activation/top-level.nix index 3edc92d502cc..ef32d991d9d6 100644 --- a/modules/system/activation/top-level.nix +++ b/modules/system/activation/top-level.nix @@ -117,12 +117,12 @@ let ln -s ${config.system.build.etc}/etc $out/etc ln -s ${config.system.path} $out/sw - ln -s ${config.system.build.upstart} $out/upstart + ln -s ${pkgs.systemd} $out/systemd ln -s ${config.hardware.firmware} $out/firmware echo -n "$kernelParams" > $out/kernel-params echo -n "$configurationName" > $out/configuration-name - echo -n "${toString config.system.build.upstart.interfaceVersion}" > $out/upstart-interface-version + #echo -n "${toString config.system.build.upstart.interfaceVersion}" > $out/upstart-interface-version echo -n "$nixosVersion" > $out/nixos-version mkdir $out/fine-tune @@ -173,7 +173,7 @@ let pkgs.gnugrep pkgs.findutils pkgs.diffutils - config.system.build.upstart # for initctl + pkgs.systemd ]; # Boot loaders diff --git a/modules/system/boot/modprobe.nix b/modules/system/boot/modprobe.nix index 41252e2ba0cd..03d9222af217 100644 --- a/modules/system/boot/modprobe.nix +++ b/modules/system/boot/modprobe.nix @@ -9,7 +9,6 @@ with pkgs.lib; options = { system.sbin.modprobe = mkOption { - # should be moved in module-init-tools internal = true; default = pkgs.writeTextFile { name = "modprobe"; @@ -18,8 +17,8 @@ with pkgs.lib; text = '' #! ${pkgs.stdenv.shell} - export MODULE_DIR=${config.system.modulesTree}/lib/modules/ - + export MODULE_DIR=/var/run/current-system/kernel-modules/lib/modules + # Fall back to the kernel modules used at boot time if the # modules in the current configuration don't match the # running kernel. @@ -27,7 +26,7 @@ with pkgs.lib; MODULE_DIR=/run/booted-system/kernel-modules/lib/modules/ fi - exec ${pkgs.module_init_tools}/sbin/modprobe "$@" + exec ${pkgs.kmod}/sbin/modprobe "$@" ''; }; description = '' @@ -78,6 +77,8 @@ with pkgs.lib; target = "modprobe.d/nixos.conf"; }; + environment.systemPackages = [ config.system.sbin.modprobe pkgs.kmod ]; + boot.blacklistedKernelModules = [ # This module is for debugging and generates gigantic amounts # of log output, so it should never be loaded automatically. @@ -104,7 +105,7 @@ with pkgs.lib; environment.shellInit = '' - export MODULE_DIR=${config.system.modulesTree}/lib/modules/ + export MODULE_DIR=/var/run/current-system/kernel-modules/lib/modules ''; }; diff --git a/modules/system/boot/shutdown.nix b/modules/system/boot/shutdown.nix new file mode 100644 index 000000000000..3af8e3e4b295 --- /dev/null +++ b/modules/system/boot/shutdown.nix @@ -0,0 +1,25 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +{ + + # This unit saves the value of the system clock to the hardware + # clock on shutdown. + boot.systemd.units."save-hwclock.service" = + { wantedBy = [ "shutdown.target" ]; + + text = + '' + [Unit] + Description=Save Hardware Clock + DefaultDependencies=no + Before=shutdown.target + + [Service] + Type=oneshot + ExecStart=${pkgs.utillinux}/sbin/hwclock --systohc --utc + ''; + }; + +} diff --git a/modules/system/boot/stage-1-init.sh b/modules/system/boot/stage-1-init.sh index cc12ccaa738f..a232151967fc 100644 --- a/modules/system/boot/stage-1-init.sh +++ b/modules/system/boot/stage-1-init.sh @@ -67,17 +67,10 @@ mkdir -p /proc mount -t proc none /proc mkdir -p /sys mount -t sysfs none /sys -mount -t tmpfs -o "mode=0755,size=@devSize@" none /dev +mount -t devtmpfs -o "size=@devSize@" none /dev mkdir -p /run mount -t tmpfs -o "mode=0755,size=@runSize@" none /run -# Some console devices, for the interactivity -mknod /dev/console c 5 1 -mknod /dev/tty c 5 0 -mknod /dev/tty1 c 4 1 -mknod /dev/ttyS0 c 4 64 -mknod /dev/ttyS1 c 4 65 - # Process the kernel command line. export stage2Init=/init for o in $(cat /proc/cmdline); do @@ -130,10 +123,6 @@ for i in @kernelModules@; do done -# Create /dev/null. -mknod /dev/null c 1 3 - - # Create device nodes in /dev. echo "running udev..." export UDEV_CONFIG_FILE=@udevConf@ diff --git a/modules/system/boot/stage-2-init.sh b/modules/system/boot/stage-2-init.sh index 0a42083144df..e8b01788900b 100644 --- a/modules/system/boot/stage-2-init.sh +++ b/modules/system/boot/stage-2-init.sh @@ -36,20 +36,8 @@ mount -n -o remount,rw none / if [ ! -e /proc/1 ]; then mkdir -m 0755 -p /proc mount -n -t proc none /proc - mkdir -m 0755 -p /sys - mount -t sysfs none /sys mkdir -m 0755 -p /dev - mount -t tmpfs -o "mode=0755" none /dev - - # Create the minimal device nodes needed for the activation scripts - # and Upstart. - mknod -m 0666 /dev/null c 1 3 - mknod -m 0644 /dev/urandom c 1 9 # needed for passwd - mknod -m 0644 /dev/console c 5 1 - mknod -m 0644 /dev/ptmx c 5 2 # required by upstart - mknod -m 0644 /dev/tty1 c 4 1 - mknod -m 0644 /dev/ttyS0 c 4 64 - mknod -m 0644 /dev/ttyS1 c 4 65 + mount -t devtmpfs none /dev fi @@ -57,7 +45,7 @@ fi mkdir -m 0755 -p /etc test -e /etc/fstab || touch /etc/fstab # to shut up mount rm -f /etc/mtab* # not that we care about stale locks -cat /proc/mounts > /etc/mtab +ln -s /proc/mounts /etc/mtab # Process the kernel command line. @@ -87,15 +75,15 @@ done mkdir -m 0755 /dev/shm mount -t tmpfs -o "rw,nosuid,nodev,size=@devShmSize@" tmpfs /dev/shm mkdir -m 0755 -p /dev/pts -mount -t devpts -o mode=0600,gid=@ttyGid@ none /dev/pts [ -e /proc/bus/usb ] && mount -t usbfs none /proc/bus/usb # UML doesn't have USB by default mkdir -m 01777 -p /tmp -mkdir -m 0755 -p /var +mkdir -m 0755 -p /var /var/log mkdir -m 0755 -p /nix/var mkdir -m 0700 -p /root mkdir -m 0755 -p /bin # for the /bin/sh symlink mkdir -m 0755 -p /home mkdir -m 0755 -p /etc/nixos +mkdir -m 0700 -p /var/log/journal # Miscellaneous boot time cleanup. @@ -187,6 +175,8 @@ if [ -n "$debug2" ]; then fi -# Start Upstart's init. -echo "starting Upstart..." -PATH=/run/current-system/upstart/sbin exec init --no-sessions ${debug2:+--verbose} +# Start systemd. +echo "starting systemd..." +PATH=/run/current-system/systemd/lib/systemd \ + MODULE_DIR=/run/current-system/kernel-modules/lib/modules \ + exec systemd --log-target journal # --log-level debug --crash-shell diff --git a/modules/system/boot/stage-2.nix b/modules/system/boot/stage-2.nix index 02c061dacde2..a5e96cc0f1cf 100644 --- a/modules/system/boot/stage-2.nix +++ b/modules/system/boot/stage-2.nix @@ -61,7 +61,6 @@ let isExecutable = true; inherit (config.boot) devShmSize runSize cleanTmpDir; ttyGid = config.ids.gids.tty; - upstart = config.system.build.upstart; path = [ pkgs.coreutils pkgs.utillinux diff --git a/modules/system/boot/systemd.nix b/modules/system/boot/systemd.nix new file mode 100644 index 000000000000..6976a204e7f2 --- /dev/null +++ b/modules/system/boot/systemd.nix @@ -0,0 +1,404 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + servicesOptions = { + + description = mkOption { + default = ""; + types = types.uniq types.string; + description = "Description of this unit used in systemd messages and progress indicators."; + }; + + requires = mkOption { + default = []; + types = types.listOf types.string; + description = '' + Start the specified units when this unit is started, and stop + this unit when the specified units are stopped or fail. + ''; + }; + + wants = mkOption { + default = []; + types = types.listOf types.string; + description = '' + Start the specified units when this unit is started. + ''; + }; + + after = mkOption { + default = []; + types = types.listOf types.string; + description = '' + If the specified units are started at the same time as + this unit, delay this unit until they have started. + ''; + }; + + before = mkOption { + default = []; + types = types.listOf types.string; + description = '' + If the specified units are started at the same time as + this unit, delay them until this unit has started. + ''; + }; + + wantedBy = mkOption { + default = []; + types = types.listOf types.string; + description = "Start this unit when the specified units are started."; + }; + + environment = mkOption { + default = {}; + type = types.attrs; + example = { PATH = "/foo/bar/bin"; LANG = "nl_NL.UTF-8"; }; + description = "Environment variables passed to the services's processes."; + }; + + path = mkOption { + default = []; + apply = ps: "${makeSearchPath "bin" ps}:${makeSearchPath "sbin" ps}"; + description = '' + Packages added to the service's <envar>PATH</envar> + environment variable. Both the <filename>bin</filename> + and <filename>sbin</filename> subdirectories of each + package are added. + ''; + }; + + serviceConfig = mkOption { + default = ""; + type = types.string; + description = '' + Contents of the <literal>[Service]</literal> section of the unit. + See <citerefentry><refentrytitle>systemd.unit</refentrytitle> + <manvolnum>5</manvolnum></citerefentry> for details. + ''; + }; + + script = mkOption { + type = types.uniq types.string; + default = ""; + description = "Shell commands executed as the service's main process."; + }; + + preStart = mkOption { + type = types.string; + default = ""; + description = '' + Shell commands executed before the service's main process + is started. + ''; + }; + + }; + + + servicesConfig = { name, config, ... }: { + + config = { + + # Default path for systemd services. Should be quite minimal. + path = + [ pkgs.coreutils + pkgs.findutils + pkgs.gnugrep + pkgs.gnused + systemd + ]; + + }; + + }; + + + cfg = config.boot.systemd; + + systemd = pkgs.systemd; + + makeUnit = name: unit: + pkgs.writeTextFile { name = "unit"; inherit (unit) text; destination = "/${name}"; }; + + upstreamUnits = + [ # Targets. + "basic.target" + "sysinit.target" + "sockets.target" + "graphical.target" + "multi-user.target" + "getty.target" + "rescue.target" + "network.target" + "nss-lookup.target" + "nss-user-lookup.target" + "syslog.target" + "time-sync.target" + + # Udev. + "systemd-udev-control.socket" + "systemd-udev-kernel.socket" + "systemd-udev.service" + "systemd-udev-settle.service" + "systemd-udev-trigger.service" + + # Login stuff. + "systemd-logind.service" + "autovt@.service" + "systemd-vconsole-setup.service" + "systemd-user-sessions.service" + "dbus-org.freedesktop.login1.service" + "user@.service" + + # Journal. + "systemd-journald.socket" + "systemd-journald.service" + + # SysV init compatibility. + "systemd-initctl.socket" + "systemd-initctl.service" + "runlevel0.target" + "runlevel1.target" + "runlevel2.target" + "runlevel3.target" + "runlevel4.target" + "runlevel5.target" + "runlevel6.target" + + # Random seed. + "systemd-random-seed-load.service" + "systemd-random-seed-save.service" + + # Utmp maintenance. + "systemd-update-utmp-runlevel.service" + "systemd-update-utmp-shutdown.service" + + # Filesystems. + "fsck@.service" + "fsck-root.service" + "systemd-remount-fs.service" + "local-fs.target" + "local-fs-pre.target" + "remote-fs.target" + "remote-fs-pre.target" + "swap.target" + "dev-hugepages.mount" + "dev-mqueue.mount" + "sys-fs-fuse-connections.mount" + "sys-kernel-config.mount" + "sys-kernel-debug.mount" + + # Hibernate / suspend. + "hibernate.target" + "hibernate.service" + "suspend.target" + "suspend.service" + "sleep.target" + + # Reboot stuff. + "reboot.target" + "reboot.service" + "poweroff.target" + "poweroff.service" + "halt.target" + "halt.service" + "ctrl-alt-del.target" + "shutdown.target" + "umount.target" + "final.target" + + # Password entry. + "systemd-ask-password-console.path" + "systemd-ask-password-console.service" + "systemd-ask-password-wall.path" + "systemd-ask-password-wall.service" + + # Misc. + "syslog.socket" + ]; + + upstreamWants = + [ "basic.target.wants" + "sysinit.target.wants" + "sockets.target.wants" + "local-fs.target.wants" + "multi-user.target.wants" + "shutdown.target.wants" + ]; + + rescueService = + '' + [Unit] + Description=Rescue Shell + DefaultDependencies=no + Conflicts=shutdown.target + After=sysinit.target + Before=shutdown.target + + [Service] + Environment=HOME=/root + WorkingDirectory=/root + ExecStartPre=-${pkgs.coreutils}/bin/echo 'Welcome to rescue mode. Use "systemctl default" or ^D to enter default mode.' + #ExecStart=-/sbin/sulogin + ExecStart=-${pkgs.bashInteractive}/bin/bash --login + ExecStopPost=-${systemd}/bin/systemctl --fail --no-block default + Type=idle + StandardInput=tty-force + StandardOutput=inherit + StandardError=inherit + KillMode=process + + # Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash + # terminates cleanly. + KillSignal=SIGHUP + ''; + + serviceToUnit = name: def: + { inherit (def) wantedBy; + + text = + '' + [Unit] + ${optionalString (def.description != "") '' + Description=${def.description} + ''} + Requires=${concatStringsSep " " def.requires} + Wants=${concatStringsSep " " def.wants} + Before=${concatStringsSep " " def.before} + After=${concatStringsSep " " def.after} + + [Service] + Environment=PATH=${def.path} + ${concatMapStrings (n: "Environment=${n}=${getAttr n def.environment}\n") (attrNames def.environment)} + + ${optionalString (def.preStart != "") '' + ExecStartPre=${pkgs.writeScript "${name}-prestart.sh" '' + #! ${pkgs.stdenv.shell} -e + ${def.preStart} + ''} + ''} + + ${optionalString (def.script != "") '' + ExecStart=${pkgs.writeScript "${name}.sh" '' + #! ${pkgs.stdenv.shell} -e + ${def.script} + ''} + ''} + + ${def.serviceConfig} + ''; + }; + + nixosUnits = mapAttrsToList makeUnit cfg.units; + + units = pkgs.runCommand "units" { preferLocalBuild = true; } + '' + mkdir -p $out/system + for i in ${toString upstreamUnits}; do + fn=${systemd}/example/systemd/system/$i + [ -e $fn ] + if [ -L $fn ]; then + cp -pd $fn $out/system/ + else + ln -s $fn $out/system + fi + done + + for i in ${toString upstreamWants}; do + fn=${systemd}/example/systemd/system/$i + [ -e $fn ] + x=$out/system/$(basename $fn) + mkdir $x + for i in $fn/*; do + y=$x/$(basename $i) + cp -pd $i $y + if ! [ -e $y ]; then rm -v $y; fi + done + done + + for i in ${toString nixosUnits}; do + cp $i/* $out/system + done + + ${concatStrings (mapAttrsToList (name: unit: + concatMapStrings (name2: '' + mkdir -p $out/system/${name2}.wants + ln -sfn ../${name} $out/system/${name2}.wants/ + '') unit.wantedBy) cfg.units)} + + ln -s ${cfg.defaultUnit} $out/system/default.target + ''; # */ + +in + +{ + + ###### interface + + options = { + + boot.systemd.units = mkOption { + description = "Definition of systemd units."; + default = {}; + type = types.attrsOf types.optionSet; + + options = { + + text = mkOption { + types = types.uniq types.string; + description = "Text of this systemd unit."; + }; + + wantedBy = mkOption { + default = []; + types = types.listOf types.string; + description = "Units that want (i.e. depend on) this unit."; + }; + + }; + + }; + + boot.systemd.services = mkOption { + description = "Definition of systemd services."; + default = {}; + type = types.attrsOf types.optionSet; + options = [ servicesOptions servicesConfig ]; + }; + + boot.systemd.defaultUnit = mkOption { + default = "multi-user.target"; + type = types.uniq types.string; + description = "Default unit started when the system boots."; + }; + + }; + + + ###### implementation + + config = { + + system.build.systemd = systemd; + + system.build.units = units; + + environment.systemPackages = [ systemd ]; + + environment.etc = + [ { source = units; + target = "systemd"; + } + ]; + + boot.systemd.units = + { "rescue.service".text = rescueService; } + // mapAttrs serviceToUnit cfg.services; + + }; + +} diff --git a/modules/system/upstart-events/control-alt-delete.nix b/modules/system/upstart-events/control-alt-delete.nix deleted file mode 100644 index f0f146160e58..000000000000 --- a/modules/system/upstart-events/control-alt-delete.nix +++ /dev/null @@ -1,26 +0,0 @@ -{ config, pkgs, ... }: - -###### implementation - -{ - jobs.control_alt_delete = - { name = "control-alt-delete"; - - startOn = "control-alt-delete"; - - task = true; - - script = - '' - shutdown -r now 'Ctrl-Alt-Delete pressed' - ''; - }; - - system.activationScripts.poweroff = - '' - # Allow the kernel to find the poweroff command. This is used - # (for instance) by Xen's "xm shutdown" command to signal a - # guest to shut down cleanly. - echo ${config.system.build.upstart}/sbin/poweroff > /proc/sys/kernel/poweroff_cmd - ''; -} diff --git a/modules/system/upstart-events/runlevel.nix b/modules/system/upstart-events/runlevel.nix deleted file mode 100644 index 016217ea3a67..000000000000 --- a/modules/system/upstart-events/runlevel.nix +++ /dev/null @@ -1,38 +0,0 @@ -{ config, pkgs, ... }: - -with pkgs.lib; - -{ - - # After booting, go to runlevel 2. (NixOS doesn't really use - # runlevels, but this keeps wtmp happy.) - jobs.boot = - { name = "boot"; - startOn = "startup"; - task = true; - restartIfChanged = false; - script = "telinit 2"; - }; - - jobs.runlevel = - { name = "runlevel"; - - startOn = "runlevel [0123456S]"; - - task = true; - - restartIfChanged = false; - - script = - '' - case "$RUNLEVEL" in - 0) initctl start shutdown --no-wait MODE=poweroff;; - 1) initctl start shutdown --no-wait MODE=maintenance;; - 2) true;; - 6) initctl start shutdown --no-wait MODE=reboot;; - *) echo "Unsupported runlevel: $RUNLEVEL";; - esac - ''; - }; - -} diff --git a/modules/system/upstart/upstart.nix b/modules/system/upstart/upstart.nix index 1bfde9fc60ee..de60f693e831 100644 --- a/modules/system/upstart/upstart.nix +++ b/modules/system/upstart/upstart.nix @@ -12,182 +12,92 @@ let groupExists = g: (g == "") || any (gg: gg.name == g) (attrValues config.users.extraGroups); - # From a job description, generate an Upstart job file. - makeJob = job: + # From a job description, generate an systemd unit file. + makeUnit = job: let hasMain = job.script != "" || job.exec != ""; env = config.system.upstartEnvironment // job.environment; - jobText = - let log = "/var/log/upstart/${job.name}"; in + preStartScript = pkgs.writeScript "${job.name}-pre-start.sh" '' - # Upstart job `${job.name}'. This is a generated file. Do not edit. + #! ${pkgs.stdenv.shell} -e + ${job.preStart} + ''; - ${optionalString (job.description != "") '' - description "${job.description}" + startScript = pkgs.writeScript "${job.name}-start.sh" + '' + #! ${pkgs.stdenv.shell} -e + ${if job.script != "" then job.script else '' + exec ${job.exec} ''} + ''; - ${if isList job.startOn then - "start on ${concatStringsSep " or " job.startOn}" - else if job.startOn != "" then - "start on ${job.startOn}" - else "" - } - - ${optionalString (job.stopOn != "") "stop on ${job.stopOn}"} - - env PATH=${job.path} - - ${concatMapStrings (n: "env ${n}=\"${getAttr n env}\"\n") (attrNames env)} - - ${optionalString (job.console != "") "console ${job.console}"} - - pre-start script - ${optionalString (job.console == "") '' - exec >> ${log} 2>&1 - ''} - ln -sfn "$(readlink -f "/etc/init/${job.name}.conf")" /var/run/upstart-jobs/${job.name} - ${optionalString (job.preStart != "") '' - source ${jobHelpers} - ${job.preStart} - ''} - end script - - ${if job.script != "" && job.exec != "" then - abort "Job ${job.name} has both a `script' and `exec' attribute." - else if job.script != "" then - '' - script - ${optionalString (job.console == "") '' - exec >> ${log} 2>&1 - ''} - source ${jobHelpers} - ${job.script} - end script - '' - else if job.exec != "" && job.console == "" then - '' - script - exec >> ${log} 2>&1 - exec ${job.exec} - end script - '' - else if job.exec != "" then - '' - exec ${job.exec} - '' - else "" - } + postStartScript = pkgs.writeScript "${job.name}-post-start.sh" + '' + #! ${pkgs.stdenv.shell} -e + ${job.postStart} + ''; - ${optionalString (job.postStart != "") '' - post-start script - ${optionalString (job.console == "") '' - exec >> ${log} 2>&1 - ''} - source ${jobHelpers} - ${job.postStart} - end script - ''} + preStopScript = pkgs.writeScript "${job.name}-pre-stop.sh" + '' + #! ${pkgs.stdenv.shell} -e + ${job.preStop} + ''; - ${optionalString job.task "task"} - ${optionalString (!job.task && job.respawn) "respawn"} - - ${ # preStop is run only if there is exec or script. - # (upstart 0.6.5, job.c:562) - optionalString (job.preStop != "") (assert hasMain; '' - pre-stop script - ${optionalString (job.console == "") '' - exec >> ${log} 2>&1 - ''} - source ${jobHelpers} - ${job.preStop} - end script - '')} + postStopScript = pkgs.writeScript "${job.name}-post-stop.sh" + '' + #! ${pkgs.stdenv.shell} -e + ${job.postStop} + ''; + in { - ${optionalString (job.postStop != "") '' - post-stop script - ${optionalString (job.console == "") '' - exec >> ${log} 2>&1 - ''} - source ${jobHelpers} - ${job.postStop} - end script + inherit (job) description path environment; + + after = + if job.startOn == "stopped udevtrigger" then [ "systemd-udev-settle.service" ] else + if job.startOn == "started udev" then [ "systemd-udev.service" ] else + []; + + wantedBy = if job.startOn == "" then [ ] else [ "multi-user.target" ]; + + serviceConfig = + '' + ${optionalString (job.preStart != "" && (job.script != "" || job.exec != "")) '' + ExecStartPre=${preStartScript} ''} - ${if job.daemonType == "fork" then "expect fork" else - if job.daemonType == "daemon" then "expect daemon" else - if job.daemonType == "stop" then "expect stop" else - if job.daemonType == "none" then "" else - throw "invalid daemon type `${job.daemonType}'"} + ${optionalString (job.preStart != "" && job.script == "" && job.exec == "") '' + ExecStart=${preStartScript} + ''} - ${optionalString (job.setuid != "") '' - setuid ${job.setuid} + ${optionalString (job.script != "" || job.exec != "") '' + ExecStart=${startScript} + ''} + + ${optionalString (job.postStart != "") '' + ExecStartPost=${postStartScript} ''} - ${optionalString (job.setgid != "") '' - setuid ${job.setgid} + ${optionalString (job.preStop != "") '' + ExecStop=${preStopScript} + ''} + + ${optionalString (job.postStop != "") '' + ExecStopPost=${postStopScript} ''} - ${job.extraConfig} - ''; + ${if job.script == "" && job.exec == "" then "Type=oneshot\nRemainAfterExit=true" else + if job.daemonType == "fork" then "Type=forking\nGuessMainPID=true" else + if job.daemonType == "none" then "" else + throw "invalid daemon type `${job.daemonType}'"} - in - pkgs.runCommand ("upstart-" + job.name + ".conf") - { inherit (job) buildHook; inherit jobText; preferLocalBuild = true; } - '' - eval "$buildHook" - echo "$jobText" > $out + ${optionalString (!job.task && job.respawn) "Restart=always"} ''; + }; - # Shell functions for use in Upstart jobs. - jobHelpers = pkgs.writeText "job-helpers.sh" - '' - # Ensure that an Upstart service is running. - ensure() { - local job="$1" - local status="$(status "$job")" - - # If it's already running, we're happy. - [[ "$status" =~ start/running ]] && return 0 - - # If its current goal is to stop, start it. - [[ "$status" =~ stop/ ]] && { status="$(start "$job")" || true; } - - # The "start" command is synchronous *if* the job is - # not already starting. So if somebody else started - # the job in parallel, the "start" above may return - # while the job is still starting. So wait until it - # is up or has failed. - while true; do - [[ "$status" =~ stop/ ]] && { echo "job $job failed to start"; return 1; } - [[ "$status" =~ start/running ]] && return 0 - echo "waiting for job $job to start..." - sleep 1 - status="$(status "$job")" - done - } - - # Check whether the current job has been stopped. Used in - # post-start jobs to determine if they should continue. - stop_check() { - local status="$(status)" - if [[ "$status" =~ stop/ ]]; then - echo "job asked to stop!" - return 1 - fi - if [[ "$status" =~ respawn/ ]]; then - echo "job respawning unexpectedly!" - stop - return 1 - fi - return 0 - } - ''; - - jobOptions = { name = mkOption { @@ -199,17 +109,6 @@ let ''; }; - buildHook = mkOption { - type = types.string; - default = "true"; - description = '' - Command run while building the Upstart job. Can be used - to perform simple regression tests (e.g., the Apache - Upstart job uses it to check the syntax of the generated - <filename>httpd.conf</filename>. - ''; - }; - description = mkOption { type = types.string; default = ""; @@ -373,8 +272,7 @@ let }; path = mkOption { - default = [ ]; - apply = ps: "${makeSearchPath "bin" ps}:${makeSearchPath "sbin" ps}"; + default = []; description = '' Packages added to the job's <envar>PATH</envar> environment variable. Both the <filename>bin</filename> and <filename>sbin</filename> @@ -401,13 +299,9 @@ let options = { - jobDrv = mkOption { - default = makeJob config; - type = types.uniq types.package; - description = '' - Derivation that builds the Upstart job file. The default - value is generated from other options. - ''; + unit = mkOption { + default = makeUnit config; + description = "Generated definition of the systemd unit corresponding to this job."; }; }; @@ -448,16 +342,6 @@ in options = [ jobOptions upstartJob ]; }; - tests.upstartJobs = mkOption { - internal = true; - default = {}; - description = '' - Make it easier to build individual Upstart jobs. (e.g., - <command>nix-build /etc/nixos/nixos -A - tests.upstartJobs.xserver</command>). - ''; - }; - system.upstartEnvironment = mkOption { type = types.attrs; default = {}; @@ -476,23 +360,10 @@ in system.build.upstart = upstart; - environment.etc = - flip map (attrValues config.jobs) (job: - { source = job.jobDrv; - target = "init/${job.name}.conf"; - } ); - - # Upstart can listen on the system bus, allowing normal users to - # do status queries. - services.dbus.packages = [ upstart ]; - - system.activationScripts.chownJobLogs = stringAfter ["var"] - (concatMapStrings (job: '' - touch /var/log/upstart/${job.name} - ${optionalString (job.setuid != "") "chown ${job.setuid} /var/log/upstart/${job.name}"} - ${optionalString (job.setgid != "") "chown :${job.setgid} /var/log/upstart/${job.name}"} - '') (attrValues config.jobs)); - + boot.systemd.services = + flip mapAttrs' config.jobs (name: job: + nameValuePair "${job.name}.service" job.unit); + }; } diff --git a/modules/tasks/filesystems.nix b/modules/tasks/filesystems.nix index 9495cac67855..8eaf77330a3d 100644 --- a/modules/tasks/filesystems.nix +++ b/modules/tasks/filesystems.nix @@ -174,7 +174,7 @@ in system.fsPackages = [ pkgs.dosfstools ]; environment.systemPackages = - [ pkgs.ntfs3g pkgs.cifs_utils pkgs.mountall ] + [ pkgs.ntfs3g pkgs.cifs_utils ] ++ config.system.fsPackages; environment.etc = singleton @@ -182,6 +182,7 @@ in target = "fstab"; }; + /* jobs.mountall = { startOn = "started udev or config-changed"; @@ -309,6 +310,7 @@ in initctl start --no-wait mountall ''; }; + */ }; diff --git a/modules/tasks/kbd.nix b/modules/tasks/kbd.nix index d9e820ef9e76..dd4b9f382c09 100644 --- a/modules/tasks/kbd.nix +++ b/modules/tasks/kbd.nix @@ -54,8 +54,10 @@ in inherit requiredTTYs; # pass it to ./modules/tasks/tty-backgrounds.nix - environment.systemPackages = [pkgs.kbd]; + environment.systemPackages = [ pkgs.kbd ]; + /* FIXME - remove; this is handled by systemd now. + jobs.kbd = { description = "Keyboard / console initialisation"; @@ -120,6 +122,7 @@ in ${pkgs.kbd}/bin/loadkeys '${consoleKeyMap}' ''; }; + */ }; diff --git a/modules/tasks/lvm.nix b/modules/tasks/lvm.nix index 635146ac889b..7773a2c79e31 100644 --- a/modules/tasks/lvm.nix +++ b/modules/tasks/lvm.nix @@ -14,8 +14,6 @@ # Make all logical volumes on all volume groups available, i.e., # make them appear in /dev. ${pkgs.lvm2}/sbin/vgchange --available y - - initctl emit -n new-devices ''; task = true; diff --git a/modules/tasks/network-interfaces.nix b/modules/tasks/network-interfaces.nix index c12f9b28ca91..611de13148a3 100644 --- a/modules/tasks/network-interfaces.nix +++ b/modules/tasks/network-interfaces.nix @@ -267,7 +267,8 @@ in ${optionalString (cfg.interfaces != [] || cfg.localCommands != "") '' # Emit the ip-up event (e.g. to start ntpd). - initctl emit -n ip-up + #FIXME + #initctl emit -n ip-up ''} ''; }; diff --git a/modules/testing/test-instrumentation.nix b/modules/testing/test-instrumentation.nix index 830f1744fa04..ce9c1cea7431 100644 --- a/modules/testing/test-instrumentation.nix +++ b/modules/testing/test-instrumentation.nix @@ -7,15 +7,12 @@ with pkgs.lib; { - config = - # Require a patch to the kernel to increase the 15s CIFS timeout. - mkAssert (config.boot.kernelPackages.kernel.features ? cifsTimeout) " - VM tests require that the kernel has the CIFS timeout patch. - " { + config = { - jobs.backdoor = - { startOn = "started udev"; - stopOn = ""; + boot.systemd.services."backdoor.service" = + { wantedBy = [ "multi-user.target" ]; + requires = [ "dev-hvc0.device" ]; + after = [ "dev-hvc0.device" ]; script = '' @@ -30,8 +27,6 @@ with pkgs.lib; echo PS1= /bin/sh ''; - - respawn = false; }; boot.initrd.postDeviceCommands = |