diff options
Diffstat (limited to 'nixos/modules')
87 files changed, 2134 insertions, 492 deletions
diff --git a/nixos/modules/config/ldap.nix b/nixos/modules/config/ldap.nix index 7fcb1aaf63dd..1a01533c585b 100644 --- a/nixos/modules/config/ldap.nix +++ b/nixos/modules/config/ldap.nix @@ -217,9 +217,7 @@ in systemd.services = mkIf cfg.daemon.enable { nslcd = { - wantedBy = [ "nss-user-lookup.target" ]; - before = [ "nss-user-lookup.target" ]; - after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; preStart = '' mkdir -p /run/nslcd diff --git a/nixos/modules/config/pulseaudio.nix b/nixos/modules/config/pulseaudio.nix index 67e536f4fd93..96593885e5b7 100644 --- a/nixos/modules/config/pulseaudio.nix +++ b/nixos/modules/config/pulseaudio.nix @@ -80,12 +80,12 @@ in { package = mkOption { type = types.package; - default = pulseaudio; - example = literalExample "pulseaudio.override { jackaudioSupport = true; }"; + default = pulseaudioFull; + example = literalExample "pulseaudioFull"; description = '' - The PulseAudio derivation to use. This can be used to enable - features (such as JACK support) that are not enabled in the - default PulseAudio in Nixpkgs. + The PulseAudio derivation to use. This can be used to disable + features (such as JACK support, Bluetooth) that are enabled in the + pulseaudioFull package in Nixpkgs. ''; }; diff --git a/nixos/modules/config/system-path.nix b/nixos/modules/config/system-path.nix index 2ea998bbb635..6b4c38172e95 100644 --- a/nixos/modules/config/system-path.nix +++ b/nixos/modules/config/system-path.nix @@ -110,6 +110,7 @@ in "/man" "/sbin" "/share/emacs" + "/share/vim-plugins" "/share/org" "/share/info" "/share/terminfo" diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix index 5de81a773424..7783f13b14b1 100644 --- a/nixos/modules/config/users-groups.nix +++ b/nixos/modules/config/users-groups.nix @@ -404,7 +404,7 @@ in { uid = ids.uids.root; description = "System administrator"; home = "/root"; - shell = cfg.defaultUserShell; + shell = mkDefault cfg.defaultUserShell; group = "root"; extraGroups = [ "grsecurity" ]; hashedPassword = mkDefault config.security.initialRootPassword; diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix index 28c42d64f6fb..d43fa2203818 100644 --- a/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixos/modules/installer/cd-dvd/iso-image.nix @@ -179,7 +179,6 @@ in fileSystems."/" = { fsType = "tmpfs"; - device = "none"; options = "mode=0755"; }; @@ -192,6 +191,8 @@ in noCheck = true; }; + # In stage 1, mount a tmpfs on top of /nix/store (the squashfs + # image) to make this a live CD. fileSystems."/nix/.ro-store" = { fsType = "squashfs"; device = "/iso/nix-store.squashfs"; @@ -201,23 +202,20 @@ in fileSystems."/nix/.rw-store" = { fsType = "tmpfs"; - device = "none"; options = "mode=0755"; neededForBoot = true; }; + fileSystems."/nix/store" = + { fsType = "unionfs-fuse"; + device = "unionfs"; + options = "allow_other,cow,nonempty,chroot=/mnt-root,max_files=32768,hide_meta_files,dirs=/nix/.rw-store=rw:/nix/.ro-store=ro"; + }; + boot.initrd.availableKernelModules = [ "squashfs" "iso9660" ]; boot.initrd.kernelModules = [ "loop" ]; - # In stage 1, mount a tmpfs on top of /nix/store (the squashfs - # image) to make this a live CD. - boot.initrd.postMountCommands = - '' - mkdir -p $targetRoot/nix/store - unionfs -o allow_other,cow,nonempty,chroot=$targetRoot,max_files=32768 /nix/.rw-store=RW:/nix/.ro-store=RO $targetRoot/nix/store - ''; - # Closures to be copied to the Nix store on the CD, namely the init # script and the top-level system configuration directory. isoImage.storeContents = @@ -313,8 +311,8 @@ in ''; # Add vfat support to the initrd to enable people to copy the - # contents of the CD to a bootable USB stick. Need unionfs-fuse for union mounts - boot.initrd.supportedFilesystems = [ "vfat" "unionfs-fuse" ]; + # contents of the CD to a bootable USB stick. + boot.initrd.supportedFilesystems = [ "vfat" ]; }; diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh index 9d62ba131dc7..a55eda1cb8fd 100644 --- a/nixos/modules/installer/tools/nixos-install.sh +++ b/nixos/modules/installer/tools/nixos-install.sh @@ -81,7 +81,7 @@ mount -t tmpfs -o "mode=0755" none $mountPoint/var/setuid-wrappers rm -rf $mountPoint/var/run ln -s /run $mountPoint/var/run rm -f $mountPoint/etc/{resolv.conf,hosts} -cp -f /etc/resolv.conf /etc/hosts $mountPoint/etc/ +cp -Lf /etc/resolv.conf /etc/hosts $mountPoint/etc/ if [ -n "$runChroot" ]; then diff --git a/nixos/modules/installer/tools/nixos-rebuild.sh b/nixos/modules/installer/tools/nixos-rebuild.sh index be37e61151aa..52b64c37578e 100644 --- a/nixos/modules/installer/tools/nixos-rebuild.sh +++ b/nixos/modules/installer/tools/nixos-rebuild.sh @@ -225,7 +225,10 @@ fi # If we're not just building, then make the new configuration the boot # default and/or activate it now. if [ "$action" = switch -o "$action" = boot -o "$action" = test ]; then - $pathToConfig/bin/switch-to-configuration "$action" + if ! $pathToConfig/bin/switch-to-configuration "$action"; then + echo "warning: there were error switching to the new configuration" >&2 + exit 1 + fi fi diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index 31de680514e6..9f509ba8cb94 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -136,6 +136,12 @@ nsd = 126; gitolite = 127; znc = 128; + polipo = 129; + mopidy = 130; + unifi = 131; + gdm = 132; + dhcpd = 133; + siproxd = 134; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -246,6 +252,12 @@ nsd = 126; firebird = 127; znc = 128; + polipo = 129; + mopidy = 130; + docker = 131; + gdm = 132; + tss = 133; + siproxd = 134; # When adding a gid, make sure it doesn't match an existing uid. And don't use gids above 399! diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index a9039eea71d4..1fc2959bd8a0 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -14,17 +14,17 @@ ./config/power-management.nix ./config/pulseaudio.nix ./config/shells-environment.nix - ./config/system-environment.nix ./config/swap.nix ./config/sysctl.nix + ./config/system-environment.nix ./config/system-path.nix ./config/timezone.nix ./config/unix-odbc-drivers.nix ./config/users-groups.nix ./config/zram.nix ./hardware/all-firmware.nix - ./hardware/cpu/intel-microcode.nix ./hardware/cpu/amd-microcode.nix + ./hardware/cpu/intel-microcode.nix ./hardware/network/b43.nix ./hardware/network/intel-2100bg.nix ./hardware/network/intel-2200bg.nix @@ -50,8 +50,11 @@ ./programs/bash/bash.nix ./programs/bash/command-not-found.nix ./programs/blcr.nix + ./programs/dconf.nix ./programs/environment.nix ./programs/info.nix + ./programs/nano.nix + ./programs/screen.nix ./programs/shadow.nix ./programs/shell.nix ./programs/ssh.nix @@ -59,7 +62,6 @@ ./programs/venus.nix ./programs/wvdial.nix ./programs/zsh/zsh.nix - ./programs/screen.nix ./rename.nix ./security/apparmor.nix ./security/apparmor-suid.nix @@ -79,6 +81,7 @@ ./services/audio/alsa.nix ./services/audio/fuppes.nix ./services/audio/mpd.nix + ./services/audio/mopidy.nix ./services/backup/almir.nix ./services/backup/bacula.nix ./services/backup/mysql-backup.nix @@ -92,15 +95,15 @@ ./services/databases/4store.nix ./services/databases/couchdb.nix ./services/databases/firebird.nix + ./services/databases/influxdb.nix ./services/databases/memcached.nix + ./services/databases/monetdb.nix ./services/databases/mongodb.nix - ./services/databases/redis.nix ./services/databases/mysql.nix ./services/databases/openldap.nix ./services/databases/postgresql.nix + ./services/databases/redis.nix ./services/databases/virtuoso.nix - ./services/databases/monetdb.nix - ./services/databases/influxdb.nix ./services/desktops/accountsservice.nix ./services/desktops/geoclue2.nix ./services/desktops/gnome3/at-spi2-core.nix @@ -124,16 +127,18 @@ ./services/hardware/pcscd.nix ./services/hardware/pommed.nix ./services/hardware/sane.nix + ./services/hardware/tcsd.nix + ./services/hardware/thinkfan.nix ./services/hardware/udev.nix ./services/hardware/udisks2.nix ./services/hardware/upower.nix - ./services/hardware/thinkfan.nix ./services/logging/klogd.nix ./services/logging/logcheck.nix ./services/logging/logrotate.nix ./services/logging/logstash.nix - ./services/logging/syslogd.nix ./services/logging/rsyslogd.nix + ./services/logging/syslogd.nix + ./services/logging/syslog-ng.nix ./services/mail/dovecot.nix ./services/mail/freepops.nix ./services/mail/mail.nix @@ -146,14 +151,15 @@ ./services/misc/disnix.nix ./services/misc/felix.nix ./services/misc/folding-at-home.nix - ./services/misc/gpsd.nix ./services/misc/gitolite.nix + ./services/misc/gpsd.nix ./services/misc/nix-daemon.nix ./services/misc/nix-gc.nix - ./services/misc/nix-ssh-serve.nix ./services/misc/nixos-manual.nix + ./services/misc/nix-ssh-serve.nix ./services/misc/rippled.nix ./services/misc/rogue.nix + ./services/misc/siproxd.nix ./services/misc/svnserve.nix ./services/misc/synergy.nix ./services/monitoring/apcupsd.nix @@ -179,24 +185,23 @@ ./services/networking/bind.nix ./services/networking/bitlbee.nix ./services/networking/btsync.nix + ./services/networking/chrony.nix ./services/networking/cjdns.nix - ./services/networking/connman.nix ./services/networking/cntlm.nix - ./services/networking/chrony.nix + ./services/networking/connman.nix ./services/networking/ddclient.nix ./services/networking/dhcpcd.nix ./services/networking/dhcpd.nix ./services/networking/dnsmasq.nix ./services/networking/ejabberd.nix ./services/networking/firewall.nix - ./services/networking/haproxy.nix - ./services/networking/tcpcrypt.nix ./services/networking/flashpolicyd.nix ./services/networking/freenet.nix ./services/networking/git-daemon.nix ./services/networking/gnunet.nix ./services/networking/gogoclient.nix ./services/networking/gvpe.nix + ./services/networking/haproxy.nix ./services/networking/hostapd.nix ./services/networking/ifplugd.nix ./services/networking/iodined.nix @@ -214,6 +219,7 @@ ./services/networking/oidentd.nix ./services/networking/openfire.nix ./services/networking/openvpn.nix + ./services/networking/polipo.nix ./services/networking/prayer.nix ./services/networking/privoxy.nix ./services/networking/quassel.nix @@ -224,13 +230,15 @@ ./services/networking/sabnzbd.nix ./services/networking/searx.nix ./services/networking/spiped.nix - ./services/networking/supybot.nix - ./services/networking/syncthing.nix ./services/networking/ssh/lshd.nix ./services/networking/ssh/sshd.nix + ./services/networking/supybot.nix + ./services/networking/syncthing.nix + ./services/networking/tcpcrypt.nix ./services/networking/teamspeak3.nix ./services/networking/tftpd.nix ./services/networking/unbound.nix + ./services/networking/unifi.nix ./services/networking/vsftpd.nix ./services/networking/wakeonlan.nix ./services/networking/websockify.nix @@ -245,11 +253,11 @@ ./services/search/elasticsearch.nix ./services/search/solr.nix ./services/security/clamav.nix - ./services/security/haveged.nix ./services/security/fprot.nix ./services/security/frandom.nix - ./services/security/tor.nix + ./services/security/haveged.nix ./services/security/torify.nix + ./services/security/tor.nix ./services/security/torsocks.nix ./services/system/dbus.nix ./services/system/kerberos.nix @@ -257,14 +265,14 @@ ./services/system/uptimed.nix ./services/torrent/deluge.nix ./services/torrent/transmission.nix - ./services/ttys/gpm.nix ./services/ttys/agetty.nix + ./services/ttys/gpm.nix ./services/ttys/kmscon.nix ./services/web-servers/apache-httpd/default.nix ./services/web-servers/fcgiwrap.nix ./services/web-servers/jboss/default.nix - ./services/web-servers/lighttpd/default.nix ./services/web-servers/lighttpd/cgit.nix + ./services/web-servers/lighttpd/default.nix ./services/web-servers/lighttpd/gitweb.nix ./services/web-servers/nginx/default.nix ./services/web-servers/phpfpm.nix @@ -275,26 +283,29 @@ ./services/x11/desktop-managers/default.nix ./services/x11/display-managers/auto.nix ./services/x11/display-managers/default.nix + ./services/x11/display-managers/gdm.nix ./services/x11/display-managers/kdm.nix - ./services/x11/display-managers/slim.nix ./services/x11/display-managers/lightdm.nix + ./services/x11/display-managers/slim.nix ./services/x11/hardware/multitouch.nix ./services/x11/hardware/synaptics.nix ./services/x11/hardware/wacom.nix + ./services/x11/redshift.nix ./services/x11/window-managers/awesome.nix #./services/x11/window-managers/compiz.nix ./services/x11/window-managers/default.nix ./services/x11/window-managers/icewm.nix + ./services/x11/window-managers/bspwm.nix ./services/x11/window-managers/metacity.nix ./services/x11/window-managers/none.nix ./services/x11/window-managers/twm.nix ./services/x11/window-managers/wmii.nix ./services/x11/window-managers/xmonad.nix - ./services/x11/redshift.nix ./services/x11/xfs.nix ./services/x11/xserver.nix ./system/activation/activation-script.nix ./system/activation/top-level.nix + ./system/boot/emergency-mode.nix ./system/boot/kernel.nix ./system/boot/kexec.nix ./system/boot/loader/efi.nix @@ -310,11 +321,14 @@ ./system/boot/stage-1.nix ./system/boot/stage-2.nix ./system/boot/systemd.nix + ./system/boot/tmp.nix ./system/etc/etc.nix ./system/upstart/upstart.nix ./tasks/cpu-freq.nix + ./tasks/encrypted-devices.nix ./tasks/filesystems.nix ./tasks/filesystems/btrfs.nix + ./tasks/filesystems/cifs.nix ./tasks/filesystems/ext.nix ./tasks/filesystems/f2fs.nix ./tasks/filesystems/nfs.nix @@ -323,7 +337,6 @@ ./tasks/filesystems/vfat.nix ./tasks/filesystems/xfs.nix ./tasks/filesystems/zfs.nix - ./tasks/encrypted-devices.nix ./tasks/kbd.nix ./tasks/lvm.nix ./tasks/network-interfaces.nix @@ -333,6 +346,7 @@ ./testing/service-runner.nix ./virtualisation/container-config.nix ./virtualisation/containers.nix + ./virtualisation/docker.nix ./virtualisation/libvirtd.nix #./virtualisation/nova.nix ./virtualisation/virtualbox-guest.nix diff --git a/nixos/modules/profiles/base.nix b/nixos/modules/profiles/base.nix index 562419b3facb..6f9e3002f299 100644 --- a/nixos/modules/profiles/base.nix +++ b/nixos/modules/profiles/base.nix @@ -7,7 +7,6 @@ # Include some utilities that are useful for installing or repairing # the system. environment.systemPackages = [ - pkgs.subversion # for nixos-checkout pkgs.w3m # needed for the manual anyway pkgs.testdisk # useful for repairing boot problems pkgs.mssys # for writing Microsoft boot sectors / MBRs diff --git a/nixos/modules/programs/dconf.nix b/nixos/modules/programs/dconf.nix new file mode 100644 index 000000000000..1b7e20799819 --- /dev/null +++ b/nixos/modules/programs/dconf.nix @@ -0,0 +1,34 @@ +{ config, lib, ... }: + +let + inherit (lib) mkOption mkIf types mapAttrsToList; + cfg = config.programs.dconf; + + mkDconfProfile = name: path: + { source = path; target = "dconf/profile/${name}"; }; + +in +{ + ###### interface + + options = { + programs.dconf = { + + profiles = mkOption { + type = types.attrsOf types.path; + default = {}; + description = "Set of dconf profile files."; + internal = true; + }; + + }; + }; + + ###### implementation + + config = mkIf (cfg.profiles != {}) { + environment.etc = + (mapAttrsToList mkDconfProfile cfg.profiles); + }; + +} diff --git a/nixos/modules/programs/nano.nix b/nixos/modules/programs/nano.nix new file mode 100644 index 000000000000..b8803eec7be1 --- /dev/null +++ b/nixos/modules/programs/nano.nix @@ -0,0 +1,35 @@ +{ config, lib, ... }: + +let + cfg = config.programs.nano; +in + +{ + ###### interface + + options = { + programs.nano = { + + nanorc = lib.mkOption { + type = lib.types.lines; + default = ""; + description = '' + The system-wide nano configuration. + See <citerefentry><refentrytitle>nanorc</refentrytitle><manvolnum>5</manvolnum></citerefentry>. + ''; + example = '' + set nowrap + set tabstospaces + set tabsize 4 + ''; + }; + }; + }; + + ###### implementation + + config = lib.mkIf (cfg.nanorc != "") { + environment.etc."nanorc".text = cfg.nanorc; + }; + +} diff --git a/nixos/modules/security/ca.nix b/nixos/modules/security/ca.nix index dd4b0c529e5d..8e653cd42847 100644 --- a/nixos/modules/security/ca.nix +++ b/nixos/modules/security/ca.nix @@ -13,8 +13,9 @@ with lib; ]; environment.sessionVariables = - { OPENSSL_X509_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt"; - CURL_CA_BUNDLE = "/etc/ssl/certs/ca-bundle.crt"; + { SSL_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt"; + # FIXME: unneeded - remove eventually. + OPENSSL_X509_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt"; GIT_SSL_CAINFO = "/etc/ssl/certs/ca-bundle.crt"; }; diff --git a/nixos/modules/security/grsecurity.nix b/nixos/modules/security/grsecurity.nix index 3bd58218c99d..9e5983691370 100644 --- a/nixos/modules/security/grsecurity.nix +++ b/nixos/modules/security/grsecurity.nix @@ -50,7 +50,7 @@ in description = '' grsecurity configuration mode. This specifies whether grsecurity is auto-configured or otherwise completely - manually configured. Can either by + manually configured. Can either be <literal>custom</literal> or <literal>auto</literal>. <literal>auto</literal> is recommended. @@ -64,7 +64,7 @@ in description = '' grsecurity configuration priority. This specifies whether the kernel configuration should emphasize speed or - security. Can either by <literal>security</literal> or + security. Can either be <literal>security</literal> or <literal>performance</literal>. ''; }; @@ -76,7 +76,7 @@ in description = '' grsecurity system configuration. This specifies whether the kernel configuration should be suitable for a Desktop - or a Server. Can either by <literal>server</literal> or + or a Server. Can either be <literal>server</literal> or <literal>desktop</literal>. ''; }; diff --git a/nixos/modules/security/rngd.nix b/nixos/modules/security/rngd.nix index c31e57e6f6f8..4d8fabc7696e 100644 --- a/nixos/modules/security/rngd.nix +++ b/nixos/modules/security/rngd.nix @@ -30,7 +30,8 @@ with lib; description = "Hardware RNG Entropy Gatherer Daemon"; - serviceConfig.ExecStart = "${pkgs.rng_tools}/sbin/rngd -f"; + serviceConfig.ExecStart = "${pkgs.rng_tools}/sbin/rngd -f -v" + + (if config.services.tcsd.enable then " --no-tpm=1" else ""); restartTriggers = [ pkgs.rng_tools ]; }; diff --git a/nixos/modules/security/setuid-wrappers.nix b/nixos/modules/security/setuid-wrappers.nix index 4cdc1023baab..373afffd3fb5 100644 --- a/nixos/modules/security/setuid-wrappers.nix +++ b/nixos/modules/security/setuid-wrappers.nix @@ -97,8 +97,7 @@ in }: '' - source=${if source != "" then source else "$(PATH=$SETUID_PATH type -tP ${program})"} - if test -z "$source"; then + if ! source=${if source != "" then source else "$(PATH=$SETUID_PATH type -tP ${program})"}; then # If we can't find the program, fall back to the # system profile. source=/nix/var/nix/profiles/default/bin/${program} diff --git a/nixos/modules/services/amqp/activemq/default.nix b/nixos/modules/services/amqp/activemq/default.nix index f731900070e4..261f97617664 100644 --- a/nixos/modules/services/amqp/activemq/default.nix +++ b/nixos/modules/services/amqp/activemq/default.nix @@ -12,7 +12,7 @@ let phases = [ "installPhase" ]; buildInputs = [ jdk ]; installPhase = '' - ensureDir $out/lib + mkdir -p $out/lib source ${activemq}/lib/classpath.env export CLASSPATH ln -s "${./ActiveMQBroker.java}" ActiveMQBroker.java diff --git a/nixos/modules/services/amqp/rabbitmq.nix b/nixos/modules/services/amqp/rabbitmq.nix index bef15fb64b7f..a930098bfeec 100644 --- a/nixos/modules/services/amqp/rabbitmq.nix +++ b/nixos/modules/services/amqp/rabbitmq.nix @@ -4,6 +4,8 @@ with lib; let cfg = config.services.rabbitmq; + config_file = pkgs.writeText "rabbitmq.config" cfg.config; + config_file_wo_suffix = builtins.substring 0 ((builtins.stringLength config_file) - 7) config_file; in { ###### interface @@ -31,7 +33,6 @@ in { ''; }; - dataDir = mkOption { type = types.path; default = "/var/lib/rabbitmq"; @@ -40,6 +41,30 @@ in { ''; }; + cookie = mkOption { + default = ""; + type = types.str; + description = '' + Erlang cookie is a string of arbitrary length which must + be the same for several nodes to be allowed to communicate. + Leave empty to generate automatically. + ''; + }; + + config = mkOption { + default = ""; + type = types.str; + description = '' + Verbatim configuration file contents. + See http://www.rabbitmq.com/configure.htm + ''; + }; + + plugins = mkOption { + default = []; + type = types.listOf types.str; + description = "The names of plugins to enable"; + }; }; }; @@ -69,7 +94,10 @@ in { RABBITMQ_NODE_IP_ADDRESS = cfg.listenAddress; RABBITMQ_SERVER_START_ARGS = "-rabbit error_logger tty -rabbit sasl_error_logger false"; SYS_PREFIX = ""; - }; + RABBITMQ_ENABLED_PLUGINS_FILE = pkgs.writeText "enabled_plugins" '' + [ ${concatStringsSep "," cfg.plugins} ]. + ''; + } // optionalAttrs (cfg.config != "") { RABBITMQ_CONFIG_FILE = config_file_wo_suffix; }; serviceConfig = { ExecStart = "${pkgs.rabbitmq_server}/sbin/rabbitmq-server"; @@ -81,6 +109,15 @@ in { preStart = '' mkdir -p ${cfg.dataDir} && chmod 0700 ${cfg.dataDir} if [ "$(id -u)" = 0 ]; then chown rabbitmq:rabbitmq ${cfg.dataDir}; fi + + ${optionalString (cfg.cookie != "") '' + echo -n ${cfg.cookie} > ${cfg.dataDir}/.erlang.cookie + chmod 400 ${cfg.dataDir}/.erlang.cookie + chown rabbitmq:rabbitmq ${cfg.dataDir}/.erlang.cookie + ''} + + mkdir -p /var/log/rabbitmq && chmod 0700 /var/log/rabbitmq + chown rabbitmq:rabbitmq /var/log/rabbitmq ''; }; diff --git a/nixos/modules/services/audio/mopidy.nix b/nixos/modules/services/audio/mopidy.nix new file mode 100644 index 000000000000..5b865cf4c1be --- /dev/null +++ b/nixos/modules/services/audio/mopidy.nix @@ -0,0 +1,118 @@ +{ config, lib, pkgs, ... }: + +with pkgs; +with lib; + +let + + uid = config.ids.uids.mopidy; + gid = config.ids.gids.mopidy; + cfg = config.services.mopidy; + + mopidyConf = writeText "mopidy.conf" cfg.configuration; + + mopidyLauncher = stdenv.mkDerivation { + name = "mopidy-launcher"; + phases = [ "installPhase" ]; + buildInputs = [ makeWrapper python ]; + installPhase = '' + mkdir -p $out/bin + ln -s ${mopidy}/bin/mopidy $out/bin/mopidy + wrapProgram $out/bin/mopidy \ + --prefix PYTHONPATH : \ + "${concatStringsSep ":" (map (p: "$(toPythonPath ${p})") cfg.extensionPackages)}" + ''; + }; + +in { + + options = { + + services.mopidy = { + + enable = mkOption { + default = false; + type = types.bool; + description = '' + Whether to enable Mopidy, a music player daemon. + ''; + }; + + dataDir = mkOption { + default = "/var/lib/mopidy"; + type = types.str; + description = '' + The directory where Mopidy stores its state. + ''; + }; + + extensionPackages = mkOption { + default = []; + type = types.listOf types.package; + example = [ mopidy-spotify ]; + description = '' + Mopidy extensions that should be loaded by the service. + ''; + }; + + configuration = mkOption { + type = types.lines; + description = '' + The configuration that Mopidy should use. + ''; + }; + + extraConfigFiles = mkOption { + default = []; + type = types.listOf types.str; + description = '' + Extra config file read by Mopidy when the service starts. + Later files in the list overrides earlier configuration. + ''; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + systemd.services.mopidy = { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" "sound.target" ]; + description = "mopidy music player daemon"; + preStart = "mkdir -p ${cfg.dataDir} && chown -R mopidy:mopidy ${cfg.dataDir}"; + serviceConfig = { + ExecStart = "${mopidyLauncher}/bin/mopidy --config ${concatStringsSep ":" ([mopidyConf] ++ cfg.extraConfigFiles)}"; + User = "mopidy"; + PermissionsStartOnly = true; + }; + }; + + systemd.services.mopidy-scan = { + description = "mopidy local files scanner"; + preStart = "mkdir -p ${cfg.dataDir} && chown -R mopidy:mopidy ${cfg.dataDir}"; + serviceConfig = { + ExecStart = "${mopidyLauncher}/bin/mopidy --config ${concatStringsSep ":" ([mopidyConf] ++ cfg.extraConfigFiles)} local scan"; + User = "mopidy"; + PermissionsStartOnly = true; + Type = "oneshot"; + }; + }; + + users.extraUsers.mopidy = { + inherit uid; + group = "mopidy"; + extraGroups = [ "audio" ]; + description = "Mopidy daemon user"; + home = "${cfg.dataDir}"; + }; + + users.extraGroups.mopidy.gid = gid; + + }; + +} diff --git a/nixos/modules/services/databases/redis.nix b/nixos/modules/services/databases/redis.nix index 2521e356bf39..b91c389e90a2 100644 --- a/nixos/modules/services/databases/redis.nix +++ b/nixos/modules/services/databases/redis.nix @@ -38,86 +38,92 @@ in services.redis = { enable = mkOption { + type = types.bool; default = false; description = "Whether to enable the Redis server."; }; package = mkOption { + type = types.package; default = pkgs.redis; description = "Which Redis derivation to use."; - type = types.package; }; user = mkOption { + type = types.str; default = "redis"; description = "User account under which Redis runs."; }; pidFile = mkOption { + type = types.path; default = "/var/lib/redis/redis.pid"; description = ""; }; port = mkOption { + type = types.int; default = 6379; description = "The port for Redis to listen to."; - type = with types; int; }; bind = mkOption { + type = with types; nullOr str; default = null; # All interfaces description = "The IP interface to bind to."; example = "127.0.0.1"; }; unixSocket = mkOption { + type = with types; nullOr path; default = null; description = "The path to the socket to bind to."; example = "/var/run/redis.sock"; }; logLevel = mkOption { + type = types.str; default = "notice"; # debug, verbose, notice, warning example = "debug"; description = "Specify the server verbosity level, options: debug, verbose, notice, warning."; - type = with types; string; }; logfile = mkOption { + type = types.str; default = "/dev/null"; description = "Specify the log file name. Also 'stdout' can be used to force Redis to log on the standard output."; example = "/var/log/redis.log"; - type = with types; string; }; syslog = mkOption { + type = types.bool; default = true; description = "Enable logging to the system logger."; - type = with types; bool; }; databases = mkOption { + type = types.int; default = 16; description = "Set the number of databases."; - type = with types; int; }; save = mkOption { + type = with types; listOf (listOf int); default = [ [900 1] [300 10] [60 10000] ]; description = "The schedule in which data is persisted to disk, represented as a list of lists where the first element represent the amount of seconds and the second the number of changes."; example = [ [900 1] [300 10] [60 10000] ]; }; dbFilename = mkOption { + type = types.str; default = "dump.rdb"; description = "The filename where to dump the DB."; - type = with types; string; }; dbpath = mkOption { + type = types.path; default = "/var/lib/redis"; description = "The DB will be written inside this directory, with the filename specified using the 'dbFilename' configuration."; - type = with types; string; }; slaveOf = mkOption { @@ -135,46 +141,47 @@ in }; requirePass = mkOption { + type = with types; nullOr str; default = null; description = "Password for database (STORED PLAIN TEXT, WORLD-READABLE IN NIX STORE)"; example = "letmein!"; }; appendOnly = mkOption { + type = types.bool; default = false; description = "By default data is only periodically persisted to disk, enable this option to use an append-only file for improved persistence."; - type = with types; bool; }; appendOnlyFilename = mkOption { + type = types.str; default = "appendonly.aof"; description = "Filename for the append-only file (stored inside of dbpath)"; - type = with types; string; }; appendFsync = mkOption { + type = types.str; default = "everysec"; # no, always, everysec description = "How often to fsync the append-only log, options: no, always, everysec."; - type = with types; string; }; slowLogLogSlowerThan = mkOption { + type = types.int; default = 10000; description = "Log queries whose execution take longer than X in milliseconds."; example = 1000; - type = with types; int; }; slowLogMaxLen = mkOption { + type = types.int; default = 128; description = "Maximum number of items to keep in slow log."; - type = with types; int; }; extraConfig = mkOption { + type = types.lines; default = ""; description = "Extra configuration options for redis.conf."; - type = with types; string; }; }; diff --git a/nixos/modules/services/desktops/gnome3/at-spi2-core.nix b/nixos/modules/services/desktops/gnome3/at-spi2-core.nix index 615f272e7b9a..6e4c59f4bb37 100644 --- a/nixos/modules/services/desktops/gnome3/at-spi2-core.nix +++ b/nixos/modules/services/desktops/gnome3/at-spi2-core.nix @@ -4,9 +4,6 @@ with lib; -let - gnome3 = config.environment.gnome3.packageSet; -in { ###### interface @@ -33,9 +30,9 @@ in config = mkIf config.services.gnome3.at-spi2-core.enable { - environment.systemPackages = [ gnome3.at_spi2_core ]; + environment.systemPackages = [ pkgs.at_spi2_core ]; - services.dbus.packages = [ gnome3.at_spi2_core ]; + services.dbus.packages = [ pkgs.at_spi2_core ]; }; diff --git a/nixos/modules/services/hardware/acpid.nix b/nixos/modules/services/hardware/acpid.nix index b87899e45983..a20b1a1ee3ad 100644 --- a/nixos/modules/services/hardware/acpid.nix +++ b/nixos/modules/services/hardware/acpid.nix @@ -6,7 +6,7 @@ let acpiConfDir = pkgs.runCommand "acpi-events" {} '' - ensureDir $out + mkdir -p $out ${ # Generate a configuration file for each event. (You can't have # multiple events in one config file...) diff --git a/nixos/modules/services/hardware/tcsd.nix b/nixos/modules/services/hardware/tcsd.nix new file mode 100644 index 000000000000..26b2c884b8f1 --- /dev/null +++ b/nixos/modules/services/hardware/tcsd.nix @@ -0,0 +1,139 @@ +# tcsd daemon. + +{ config, pkgs, ... }: + +with pkgs.lib; +let + + cfg = config.services.tcsd; + + tcsdConf = pkgs.writeText "tcsd.conf" '' + port = 30003 + num_threads = 10 + system_ps_file = ${cfg.stateDir}/system.data + # This is the log of each individual measurement done by the system. + # By re-calculating the PCR registers based on this information, even + # finer details about the measured environment can be inferred than + # what is available directly from the PCR registers. + firmware_log_file = /sys/kernel/security/tpm0/binary_bios_measurements + kernel_log_file = /sys/kernel/security/ima/binary_runtime_measurements + #firmware_pcrs = 0,1,2,3,4,5,6,7 + #kernel_pcrs = 10,11 + platform_cred = ${cfg.platformCred} + conformance_cred = ${cfg.conformanceCred} + endorsement_cred = ${cfg.endorsementCred} + #remote_ops = create_key,random + #host_platform_class = server_12 + #all_platform_classes = pc_11,pc_12,mobile_12 + ''; + +in +{ + + ###### interface + + options = { + + services.tcsd = { + + enable = mkOption { + default = false; + type = types.bool; + description = '' + Whether to enable tcsd, a Trusted Computing management service + that provides TCG Software Stack (TSS). The tcsd daemon is + the only portal to the Trusted Platform Module (TPM), a hardware + chip on the motherboard. + ''; + }; + + user = mkOption { + default = "tss"; + type = types.string; + description = "User account under which tcsd runs."; + }; + + group = mkOption { + default = "tss"; + type = types.string; + description = "Group account under which tcsd runs."; + }; + + stateDir = mkOption { + default = "/var/lib/tpm"; + type = types.path; + description = '' + The location of the system persistent storage file. + The system persistent storage file holds keys and data across + restarts of the TCSD and system reboots. + ''; + }; + + platformCred = mkOption { + default = "${cfg.stateDir}/platform.cert"; + type = types.path; + description = '' + Path to the platform credential for your TPM. Your TPM + manufacturer may have provided you with a set of credentials + (certificates) that should be used when creating identities + using your TPM. When a user of your TPM makes an identity, + this credential will be encrypted as part of that process. + See the 1.1b TPM Main specification section 9.3 for information + on this process. ''; + }; + + conformanceCred = mkOption { + default = "${cfg.stateDir}/conformance.cert"; + type = types.path; + description = '' + Path to the conformance credential for your TPM. + See also the platformCred option''; + }; + + endorsementCred = mkOption { + default = "${cfg.stateDir}/endorsement.cert"; + type = types.path; + description = '' + Path to the endorsement credential for your TPM. + See also the platformCred option''; + }; + }; + + }; + + ###### implementation + + config = mkIf cfg.enable { + + environment.systemPackages = [ pkgs.trousers ]; + +# system.activationScripts.tcsd = +# '' +# chown ${cfg.user}:${cfg.group} ${tcsdConf} +# ''; + + systemd.services.tcsd = { + description = "TCSD"; + after = [ "systemd-udev-settle.service" ]; + wantedBy = [ "multi-user.target" ]; + path = [ pkgs.trousers ]; + preStart = + '' + mkdir -m 0700 -p ${cfg.stateDir} + chown -R ${cfg.user}:${cfg.group} ${cfg.stateDir} + ''; + serviceConfig.ExecStart = "${pkgs.trousers}/sbin/tcsd -f -c ${tcsdConf}"; + }; + + users.extraUsers = optionalAttrs (cfg.user == "tss") (singleton + { name = "tss"; + group = "tss"; + uid = config.ids.uids.nginx; + }); + + users.extraGroups = optionalAttrs (cfg.group == "tss") (singleton + { name = "tss"; + gid = config.ids.gids.nginx; + }); + }; +} diff --git a/nixos/modules/services/logging/logrotate.nix b/nixos/modules/services/logging/logrotate.nix index 804f9a0847ff..6887ab1e8052 100644 --- a/nixos/modules/services/logging/logrotate.nix +++ b/nixos/modules/services/logging/logrotate.nix @@ -8,10 +8,6 @@ let configFile = pkgs.writeText "logrotate.conf" cfg.config; - cronJob = '' - 5 * * * * root ${pkgs.logrotate}/sbin/logrotate ${configFile} - ''; - in { options = { @@ -33,6 +29,16 @@ in }; config = mkIf cfg.enable { - services.cron.systemCronJobs = [ cronJob ]; + systemd.services.logrotate = { + description = "Logrotate Service"; + wantedBy = [ "multi-user.target" ]; + startAt = "*-*-* *:05:00"; + + serviceConfig.Restart = "no"; + serviceConfig.User = "root"; + script = '' + exec ${pkgs.logrotate}/sbin/logrotate ${configFile} + ''; + }; }; } diff --git a/nixos/modules/services/logging/logstash.nix b/nixos/modules/services/logging/logstash.nix index c92c81135704..802dd454878b 100644 --- a/nixos/modules/services/logging/logstash.nix +++ b/nixos/modules/services/logging/logstash.nix @@ -69,9 +69,9 @@ in systemd.services.logstash = with pkgs; { description = "Logstash Daemon"; wantedBy = [ "multi-user.target" ]; - + environment = { JAVA_HOME = jre; }; serviceConfig = { - ExecStart = "${jre}/bin/java -jar ${logstash} agent -f ${writeText "logstash.conf" '' + ExecStart = "${logstash}/bin/logstash agent -f ${writeText "logstash.conf" '' input { ${cfg.inputConfig} } diff --git a/nixos/modules/services/logging/syslog-ng.nix b/nixos/modules/services/logging/syslog-ng.nix new file mode 100644 index 000000000000..8b892a33bb7d --- /dev/null +++ b/nixos/modules/services/logging/syslog-ng.nix @@ -0,0 +1,83 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + + cfg = config.services.syslog-ng; + + syslogngConfig = pkgs.writeText "syslog-ng.conf" '' + @version: 3.5 + @include "scl.conf" + ${cfg.extraConfig} + ''; + + ctrlSocket = "/run/syslog-ng/syslog-ng.ctl"; + pidFile = "/run/syslog-ng/syslog-ng.pid"; + persistFile = "/var/syslog-ng/syslog-ng.persist"; + + syslogngOptions = [ + "--foreground" + "--module-path=${concatStringsSep ":" (["${pkgs.syslogng}/lib/syslog-ng"] ++ cfg.extraModulePaths)}" + "--cfgfile=${syslogngConfig}" + "--control=${ctrlSocket}" + "--persist-file=${persistFile}" + "--pidfile=${pidFile}" + ]; + +in { + + options = { + + services.syslog-ng = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable the syslog-ng daemon. + ''; + }; + serviceName = mkOption { + type = types.str; + default = "syslog-ng"; + description = '' + The name of the systemd service that runs syslog-ng. Set this to + <literal>syslog</literal> if you want journald to automatically + forward all logs to syslog-ng. + ''; + }; + extraModulePaths = mkOption { + type = types.listOf types.str; + default = []; + example = [ "${pkgs.syslogng_incubator}/lib/syslog-ng" ]; + description = '' + A list of paths that should be included in syslog-ng's + <literal>--module-path</literal> option. They should usually + end in <literal>/lib/syslog-ng</literal> + ''; + }; + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Configuration added to the end of <literal>syslog-ng.conf</literal>. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + systemd.services."${cfg.serviceName}" = { + wantedBy = [ "multi-user.target" ]; + preStart = "mkdir -p /{var,run}/syslog-ng"; + serviceConfig = { + Type = "notify"; + Sockets = "syslog.socket"; + StandardOutput = "null"; + Restart = "on-failure"; + ExecStart = "${pkgs.syslogng}/sbin/syslog-ng ${concatStringsSep " " syslogngOptions}"; + }; + }; + }; + +} diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix index 1ebd3c3643df..c98c0511b566 100644 --- a/nixos/modules/services/misc/nix-daemon.nix +++ b/nixos/modules/services/misc/nix-daemon.nix @@ -22,14 +22,11 @@ let nixConf = let - # Tricky: if we're using a chroot for builds, then we need - # /bin/sh in the chroot (our own compromise to purity). - # However, since /bin/sh is a symlink to some path in the - # Nix store, which furthermore has runtime dependencies on - # other paths in the store, we need the closure of /bin/sh - # in `build-chroot-dirs' - otherwise any builder that uses - # /bin/sh won't work. - binshDeps = pkgs.writeReferencesToFile config.system.build.binsh; + # If we're using a chroot for builds, then provide /bin/sh in + # the chroot as a bind-mount to bash. This means we also need to + # include the entire closure of bash. + sh = pkgs.stdenv.shell; + binshDeps = pkgs.writeReferencesToFile sh; in pkgs.runCommand "nix.conf" {extraOptions = cfg.extraOptions; } '' extraPaths=$(for i in $(cat ${binshDeps}); do if test -d $i; then echo $i; fi; done) @@ -40,7 +37,7 @@ let build-users-group = nixbld build-max-jobs = ${toString (cfg.maxJobs)} build-use-chroot = ${if cfg.useChroot then "true" else "false"} - build-chroot-dirs = ${toString cfg.chrootDirs} $(echo $extraPaths) + build-chroot-dirs = ${toString cfg.chrootDirs} /bin/sh=${sh} $(echo $extraPaths) binary-caches = ${toString cfg.binaryCaches} trusted-binary-caches = ${toString cfg.trustedBinaryCaches} $extraOptions @@ -253,8 +250,6 @@ in config = { - nix.chrootDirs = [ "/bin" ]; - environment.etc."nix/nix.conf".source = nixConf; # List of machines for distributed Nix builds in the format diff --git a/nixos/modules/services/misc/nix-ssh-serve.nix b/nixos/modules/services/misc/nix-ssh-serve.nix index 80e7961b1f82..d70bd855c7ff 100644 --- a/nixos/modules/services/misc/nix-ssh-serve.nix +++ b/nixos/modules/services/misc/nix-ssh-serve.nix @@ -1,32 +1,35 @@ { config, lib, pkgs, ... }: -let - serveOnly = pkgs.writeScript "nix-store-serve" '' - #!${pkgs.stdenv.shell} - if [ "$SSH_ORIGINAL_COMMAND" != "nix-store --serve" ]; then - echo 'Error: You are only allowed to run `nix-store --serve'\'''!' >&2 - exit 1 - fi - exec /run/current-system/sw/bin/nix-store --serve - ''; - - inherit (lib) mkIf mkOption types; -in { +with lib; + +{ options = { + nix.sshServe = { + enable = mkOption { - description = "Whether to enable serving the nix store over ssh."; - default = false; type = types.bool; + default = false; + description = "Whether to enable serving the Nix store as a binary cache via SSH."; + }; + + keys = mkOption { + type = types.listOf types.str; + default = []; + example = [ "ssh-dss AAAAB3NzaC1k... alice@example.org" ]; + description = "A list of SSH public keys allowed to access the binary cache via SSH."; }; + }; + }; config = mkIf config.nix.sshServe.enable { + users.extraUsers.nix-ssh = { - description = "User for running nix-store --serve."; + description = "Nix SSH substituter user"; uid = config.ids.uids.nix-ssh; - shell = pkgs.stdenv.shell; + useDefaultShell = true; }; services.openssh.enable = true; @@ -38,8 +41,11 @@ in { PermitTTY no PermitTunnel no X11Forwarding no - ForceCommand ${serveOnly} + ForceCommand ${config.nix.package}/bin/nix-store --serve Match All ''; + + users.extraUsers.nix-ssh.openssh.authorizedKeys.keys = config.nix.sshServe.keys; + }; } diff --git a/nixos/modules/services/misc/siproxd.nix b/nixos/modules/services/misc/siproxd.nix new file mode 100644 index 000000000000..9e8fb6c228f2 --- /dev/null +++ b/nixos/modules/services/misc/siproxd.nix @@ -0,0 +1,180 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.siproxd; + + conf = '' + daemonize = 0 + rtp_proxy_enable = 1 + user = siproxd + if_inbound = ${cfg.ifInbound} + if_outbound = ${cfg.ifOutbound} + sip_listen_port = ${toString cfg.sipListenPort} + rtp_port_low = ${toString cfg.rtpPortLow} + rtp_port_high = ${toString cfg.rtpPortHigh} + rtp_dscp = ${toString cfg.rtpDscp} + sip_dscp = ${toString cfg.sipDscp} + ${optionalString (cfg.hostsAllowReg != []) "hosts_allow_reg = ${concatStringsSep "," cfg.hostsAllowReg}"} + ${optionalString (cfg.hostsAllowSip != []) "hosts_allow_sip = ${concatStringsSep "," cfg.hostsAllowSip}"} + ${optionalString (cfg.hostsDenySip != []) "hosts_deny_sip = ${concatStringsSep "," cfg.hostsDenySip}"} + ${if (cfg.passwordFile != "") then "proxy_auth_pwfile = ${cfg.passwordFile}" else ""} + ${cfg.extraConfig} + ''; + + confFile = builtins.toFile "siproxd.conf" conf; + +in +{ + ##### interface + + options = { + + services.siproxd = { + + enable = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable the Siproxd SIP + proxy/masquerading daemon. + ''; + }; + + ifInbound = mkOption { + type = types.str; + example = "eth0"; + description = "Local network interface"; + }; + + ifOutbound = mkOption { + type = types.str; + example = "ppp0"; + description = "Public network interface"; + }; + + hostsAllowReg = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "192.168.1.0/24" "192.168.2.0/24" ]; + description = '' + Acess control list for incoming SIP registrations. + ''; + }; + + hostsAllowSip = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "123.45.0.0/16" "123.46.0.0/16" ]; + description = '' + Acess control list for incoming SIP traffic. + ''; + }; + + hostsDenySip = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "10.0.0.0/8" "11.0.0.0/8" ]; + description = '' + Acess control list for denying incoming + SIP registrations and traffic. + ''; + }; + + sipListenPort = mkOption { + type = types.int; + default = 5060; + description = '' + Port to listen for incoming SIP messages. + ''; + }; + + rtpPortLow = mkOption { + type = types.int; + default = 7070; + description = '' + Bottom of UDP port range for incoming and outgoing RTP traffic + ''; + }; + + rtpPortHigh = mkOption { + type = types.int; + default = 7089; + description = '' + Top of UDP port range for incoming and outgoing RTP traffic + ''; + }; + + rtpTimeout = mkOption { + type = types.int; + default = 300; + description = '' + Timeout for an RTP stream. If for the specified + number of seconds no data is relayed on an active + stream, it is considered dead and will be killed. + ''; + }; + + rtpDscp = mkOption { + type = types.int; + default = 46; + description = '' + DSCP (differentiated services) value to be assigned + to RTP packets. Allows QOS aware routers to handle + different types traffic with different priorities. + ''; + }; + + sipDscp = mkOption { + type = types.int; + default = 0; + description = '' + DSCP (differentiated services) value to be assigned + to SIP packets. Allows QOS aware routers to handle + different types traffic with different priorities. + ''; + }; + + passwordFile = mkOption { + type = types.str; + default = ""; + description = '' + Path to per-user password file. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra configuration to add to siproxd configuration. + ''; + }; + + }; + + }; + + ##### implementation + + config = mkIf cfg.enable { + + users.extraUsers = singleton { + name = "siproxyd"; + uid = config.ids.uids.siproxd; + }; + + systemd.services.siproxd = { + description = "SIP proxy/masquerading daemon"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + serviceConfig = { + ExecStart = "${pkgs.siproxd}/sbin/siproxd -c ${confFile}"; + }; + }; + + }; + +} diff --git a/nixos/modules/services/monitoring/munin.nix b/nixos/modules/services/monitoring/munin.nix index 966c2eca282a..21840bc67e8f 100644 --- a/nixos/modules/services/monitoring/munin.nix +++ b/nixos/modules/services/monitoring/munin.nix @@ -189,19 +189,18 @@ in wantedBy = [ "multi-user.target" ]; path = [ pkgs.munin ]; environment.MUNIN_PLUGSTATE = "/var/run/munin"; + preStart = '' + echo "updating munin plugins..." + + mkdir -p /etc/munin/plugins + rm -rf /etc/munin/plugins/* + PATH="/run/current-system/sw/bin:/run/current-system/sw/sbin" ${pkgs.munin}/sbin/munin-node-configure --shell --families contrib,auto,manual --config ${nodeConf} --libdir=${muninPlugins} --servicedir=/etc/munin/plugins 2>/dev/null | ${pkgs.bash}/bin/bash + ''; serviceConfig = { ExecStart = "${pkgs.munin}/sbin/munin-node --config ${nodeConf} --servicedir /etc/munin/plugins/"; }; }; - system.activationScripts.munin-node = '' - echo "updating munin plugins..." - - mkdir -p /etc/munin/plugins - rm -rf /etc/munin/plugins/* - PATH="/run/current-system/sw/bin:/run/current-system/sw/sbin" ${pkgs.munin}/sbin/munin-node-configure --shell --families contrib,auto,manual --config ${nodeConf} --libdir=${muninPlugins} --servicedir=/etc/munin/plugins 2>/dev/null | ${pkgs.bash}/bin/bash - ''; - }) (mkIf cronCfg.enable { services.cron.systemCronJobs = [ diff --git a/nixos/modules/services/monitoring/nagios.nix b/nixos/modules/services/monitoring/nagios.nix index 97d153153a55..c1f7ba0eca74 100644 --- a/nixos/modules/services/monitoring/nagios.nix +++ b/nixos/modules/services/monitoring/nagios.nix @@ -12,7 +12,7 @@ let nagiosObjectDefs = cfg.objectDefs; nagiosObjectDefsDir = pkgs.runCommand "nagios-objects" {inherit nagiosObjectDefs;} - "ensureDir $out; ln -s $nagiosObjectDefs $out/"; + "mkdir -p $out; ln -s $nagiosObjectDefs $out/"; nagiosCfgFile = pkgs.writeText "nagios.cfg" '' diff --git a/nixos/modules/services/monitoring/systemhealth.nix b/nixos/modules/services/monitoring/systemhealth.nix index b0e59595e133..20d1dadd3bf2 100644 --- a/nixos/modules/services/monitoring/systemhealth.nix +++ b/nixos/modules/services/monitoring/systemhealth.nix @@ -13,7 +13,7 @@ let }; buildInputs = [ python ]; installPhase = '' - ensureDir $out/bin + mkdir -p $out/bin # Make it work for kernels 3.x, not so different than 2.6 sed -i 's/2\.6/4.0/' system_health.py cp system_health.py $out/bin diff --git a/nixos/modules/services/network-filesystems/openafs-client/default.nix b/nixos/modules/services/network-filesystems/openafs-client/default.nix index 23ab39eb05f3..0297da9e865f 100644 --- a/nixos/modules/services/network-filesystems/openafs-client/default.nix +++ b/nixos/modules/services/network-filesystems/openafs-client/default.nix @@ -11,7 +11,7 @@ let }; afsConfig = pkgs.runCommand "afsconfig" {} '' - ensureDir $out + mkdir -p $out echo ${cfg.cellName} > $out/ThisCell cp ${cellServDB} $out/CellServDB echo "/afs:${cfg.cacheDirectory}:${cfg.cacheSize}" > $out/cacheinfo diff --git a/nixos/modules/services/networking/dhcpcd.nix b/nixos/modules/services/networking/dhcpcd.nix index 5a353fc0942a..866707c3a913 100644 --- a/nixos/modules/services/networking/dhcpcd.nix +++ b/nixos/modules/services/networking/dhcpcd.nix @@ -7,9 +7,10 @@ let dhcpcd = if !config.boot.isContainer then pkgs.dhcpcd else pkgs.dhcpcd.override { udev = null; }; # Don't start dhcpcd on explicitly configured interfaces or on - # interfaces that are part of a bridge. + # interfaces that are part of a bridge, bond or sit device. ignoredInterfaces = map (i: i.name) (filter (i: i.ipAddress != null) (attrValues config.networking.interfaces)) + ++ mapAttrsToList (i: _: i) config.networking.sits ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bridges)) ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bonds)) ++ config.networking.dhcpcd.denyInterfaces; @@ -35,7 +36,7 @@ let # Ignore peth* devices; on Xen, they're renamed physical # Ethernet cards used for bridging. Likewise for vif* and tap* # (Xen) and virbr* and vnet* (libvirt). - denyinterfaces ${toString ignoredInterfaces} lo peth* vif* tap* tun* virbr* vnet* vboxnet* + denyinterfaces ${toString ignoredInterfaces} lo peth* vif* tap* tun* virbr* vnet* vboxnet* sit* ${config.networking.dhcpcd.extraConfig} ''; diff --git a/nixos/modules/services/networking/dhcpd.nix b/nixos/modules/services/networking/dhcpd.nix index e5e1c103c686..900df67b53aa 100644 --- a/nixos/modules/services/networking/dhcpd.nix +++ b/nixos/modules/services/networking/dhcpd.nix @@ -13,7 +13,7 @@ let default-lease-time 600; max-lease-time 7200; authoritative; - ddns-update-style ad-hoc; + ddns-update-style interim; log-facility local1; # see dhcpd.nix ${cfg.extraConfig} @@ -108,22 +108,41 @@ in config = mkIf config.services.dhcpd.enable { - jobs.dhcpd = + users = { + extraUsers.dhcpd = { + uid = config.ids.uids.dhcpd; + description = "DHCP daemon user"; + }; + }; + + systemd.services.dhcpd = { description = "DHCP server"; - startOn = "started network-interfaces"; - stopOn = "stopping network-interfaces"; + wantedBy = [ "multi-user.target" ]; - script = + after = [ "network.target" ]; + + path = [ pkgs.dhcp ]; + + preStart = '' mkdir -m 755 -p ${stateDir} touch ${stateDir}/dhcpd.leases - exec ${pkgs.dhcp}/sbin/dhcpd -f -cf ${configFile} \ - -lf ${stateDir}/dhcpd.leases \ - ${toString cfg.interfaces} + mkdir -m 755 -p /run/dhcpd + chown dhcpd /run/dhcpd ''; + + serviceConfig = + { ExecStart = "@${pkgs.dhcp}/sbin/dhcpd dhcpd" + + " -pf /run/dhcpd/dhcpd.pid -cf ${configFile}" + + " -lf ${stateDir}/dhcpd.leases -user dhcpd -group nogroup" + + " ${toString cfg.interfaces}"; + Restart = "always"; + Type = "forking"; + PIDFile = "/run/dhcpd/dhcpd.pid"; + }; }; }; diff --git a/nixos/modules/services/networking/ircd-hybrid/builder.sh b/nixos/modules/services/networking/ircd-hybrid/builder.sh index b8cb836db95e..f2c92878a4dc 100644 --- a/nixos/modules/services/networking/ircd-hybrid/builder.sh +++ b/nixos/modules/services/networking/ircd-hybrid/builder.sh @@ -3,7 +3,7 @@ source $stdenv/setup doSub() { local src=$1 local dst=$2 - ensureDir $(dirname $dst) + mkdir -p $(dirname $dst) substituteAll $src $dst } @@ -28,4 +28,4 @@ for i in $substFiles; do fi done -ensureDir $out/bin +mkdir -p $out/bin diff --git a/nixos/modules/services/networking/polipo.nix b/nixos/modules/services/networking/polipo.nix new file mode 100644 index 000000000000..05ded84625d0 --- /dev/null +++ b/nixos/modules/services/networking/polipo.nix @@ -0,0 +1,118 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.polipo; + + polipoConfig = pkgs.writeText "polipo.conf" '' + proxyAddress = ${cfg.proxyAddress} + proxyPort = ${toString cfg.proxyPort} + allowedClients = ${concatStringsSep ", " cfg.allowedClients} + ${optionalString (cfg.parentProxy != "") "parentProxy = ${cfg.parentProxy}" } + ${optionalString (cfg.socksParentProxy != "") "socksParentProxy = ${cfg.socksParentProxy}" } + ${config.services.polipo.extraConfig} + ''; + +in + +{ + + options = { + + services.polipo = { + + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to run the polipo caching web proxy."; + }; + + proxyAddress = mkOption { + type = types.string; + default = "127.0.0.1"; + description = "IP address on which Polipo will listen."; + }; + + proxyPort = mkOption { + type = types.int; + default = 8123; + description = "TCP port on which Polipo will listen."; + }; + + allowedClients = mkOption { + type = types.listOf types.string; + default = [ "127.0.0.1" "::1" ]; + example = [ "127.0.0.1" "::1" "134.157.168.0/24" "2001:660:116::/48" ]; + description = '' + List of IP addresses or network addresses that may connect to Polipo. + ''; + }; + + parentProxy = mkOption { + type = types.string; + default = ""; + example = "localhost:8124"; + description = '' + Hostname and port number of an HTTP parent proxy; + it should have the form ‘host:port’. + ''; + }; + + socksParentProxy = mkOption { + type = types.string; + default = ""; + example = "localhost:9050"; + description = '' + Hostname and port number of an SOCKS parent proxy; + it should have the form ‘host:port’. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Polio configuration. Contents will be added + verbatim to the configuration file. + ''; + }; + + }; + + }; + + config = mkIf cfg.enable { + + users.extraUsers = singleton + { name = "polipo"; + uid = config.ids.uids.polipo; + description = "Polipo caching proxy user"; + home = "/var/cache/polipo"; + createHome = true; + }; + + users.extraGroups = singleton + { name = "polipo"; + gid = config.ids.gids.polipo; + members = [ "polipo" ]; + }; + + systemd.services.polipo = { + description = "caching web proxy"; + after = [ "network.target" "nss-lookup.target" ]; + wantedBy = [ "multi-user.target"]; + preStart = '' + ${pkgs.coreutils}/bin/chown polipo:polipo /var/cache/polipo -R + ''; + serviceConfig = { + ExecStart = "${pkgs.polipo}/bin/polipo -c ${polipoConfig}"; + ExecReload = "${pkgs.coreutils}/bin/kill -USR1 $MAINPID"; + User = "polipo"; + }; + }; + + }; + +} \ No newline at end of file diff --git a/nixos/modules/services/networking/ssh/lshd.nix b/nixos/modules/services/networking/ssh/lshd.nix index fca30a1fe49c..81e523fd2a51 100644 --- a/nixos/modules/services/networking/ssh/lshd.nix +++ b/nixos/modules/services/networking/ssh/lshd.nix @@ -99,7 +99,6 @@ in }; subsystems = mkOption { - default = [ ["sftp" "${pkgs.lsh}/sbin/sftp-server"] ]; description = '' List of subsystem-path pairs, where the head of the pair denotes the subsystem name, and the tail denotes the path to @@ -116,6 +115,8 @@ in config = mkIf cfg.enable { + services.lshd.subsystems = [ ["sftp" "${pkgs.lsh}/sbin/sftp-server"] ]; + jobs.lshd = { description = "GNU lshd SSH2 daemon"; diff --git a/nixos/modules/services/networking/unifi.nix b/nixos/modules/services/networking/unifi.nix new file mode 100644 index 000000000000..634f760328f7 --- /dev/null +++ b/nixos/modules/services/networking/unifi.nix @@ -0,0 +1,88 @@ +{ config, lib, pkgs, ... }: +with lib; +let + cfg = config.services.unifi; + stateDir = "/var/lib/unifi"; + cmd = "@${pkgs.icedtea7_jre}/bin/java java -jar ${stateDir}/lib/ace.jar"; +in +{ + + options = { + + services.unifi.enable = mkOption { + type = types.uniq types.bool; + default = false; + description = '' + Whether or not to enable the unifi controller service. + ''; + }; + + }; + + config = mkIf cfg.enable { + + users.extraUsers.unifi = { + uid = config.ids.uids.unifi; + description = "UniFi controller daemon user"; + home = "${stateDir}"; + }; + + # We must create the binary directories as bind mounts instead of symlinks + # This is because the controller resolves all symlinks to absolute paths + # to be used as the working directory. + systemd.mounts = map ({ what, where }: { + bindsTo = [ "unifi.service" ]; + requiredBy = [ "unifi.service" ]; + before = [ "unifi.service" ]; + options = "bind"; + what = what; + where = where; + }) [ + { + what = "${pkgs.unifi}/dl"; + where = "${stateDir}/dl"; + } + { + what = "${pkgs.unifi}/lib"; + where = "${stateDir}/lib"; + } + { + what = "${pkgs.mongodb}/bin"; + where = "${stateDir}/bin"; + } + ]; + + systemd.services.unifi = { + description = "UniFi controller daemon"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + preStart = '' + # Ensure privacy of state + chown unifi "${stateDir}" + chmod 0700 "${stateDir}" + + # Create the volatile webapps + mkdir -p "${stateDir}/webapps" + chown unifi "${stateDir}/webapps" + ln -s "${pkgs.unifi}/webapps/ROOT.war" "${stateDir}/webapps/ROOT.war" + ''; + + postStop = '' + rm "${stateDir}/webapps/ROOT.war" + ''; + + serviceConfig = { + Type = "simple"; + ExecStart = "${cmd} start"; + ExecStop = "${cmd} stop"; + User = "unifi"; + PermissionsStartOnly = true; + UMask = "0077"; + WorkingDirectory = "${stateDir}"; + }; + }; + + }; + +} diff --git a/nixos/modules/services/networking/znc.nix b/nixos/modules/services/networking/znc.nix index a40fd924741b..4d53cd0750fb 100644 --- a/nixos/modules/services/networking/znc.nix +++ b/nixos/modules/services/networking/znc.nix @@ -20,6 +20,11 @@ let </Pass> "; + modules = pkgs.buildEnv { + name = "znc-modules"; + paths = cfg.modulePackages; + }; + confOptions = { ... }: { options = { modules = mkOption { @@ -31,6 +36,15 @@ let ''; }; + userModules = mkOption { + type = types.listOf types.string; + default = [ ]; + example = [ "fish" "push" ]; + description = '' + A list of user modules to include in the `znc.conf` file. + ''; + }; + userName = mkOption { default = defaultUserName; example = "johntron"; @@ -63,9 +77,9 @@ let }; port = mkOption { - default = "5000"; - example = "5000"; - type = types.string; + default = 5000; + example = 5000; + type = types.int; description = '' Specifies the port on which to listen. ''; @@ -80,6 +94,13 @@ let ''; }; + extraZncConf = mkOption { + default = ""; + type = types.lines; + description = '' + Extra config to `znc.conf` file + ''; + }; }; }; @@ -104,7 +125,7 @@ let AllowWeb = true IPv4 = true IPv6 = false - Port = ${if confOpts.useSSL then "+" else ""}${confOpts.port} + Port = ${if confOpts.useSSL then "+" else ""}${toString confOpts.port} SSL = ${if confOpts.useSSL then "true" else "false"} </Listener> @@ -128,9 +149,11 @@ let QuitMsg = Quit RealName = ${confOpts.nick} TimestampFormat = [%H:%M:%S] + ${concatMapStrings (n: "LoadModule = ${n}\n") confOpts.userModules} ${confOpts.passBlock} </User> + ${confOpts.extraZncConf} ''; zncConfFile = pkgs.writeTextFile { @@ -168,9 +191,9 @@ in }; dataDir = mkOption { - default = "/home/${cfg.user}/.znc"; - example = "/home/john/.znc"; - type = types.string; + default = "/var/lib/znc/"; + example = "/home/john/.znc/"; + type = types.path; description = '' The data directory. Used for configuration files and modules. ''; @@ -179,7 +202,7 @@ in zncConf = mkOption { default = ""; example = "See: http://wiki.znc.in/Configuration"; - type = types.string; + type = types.lines; description = '' The contents of the `znc.conf` file to use when creating it. If specified, `confOptions` will be ignored, and this value, as-is, will be used. @@ -201,6 +224,15 @@ in ''; options = confOptions; }; + + modulePackages = mkOption { + type = types.listOf types.package; + default = [ ]; + example = [ pkgs.zncModules.fish pkgs.zncModules.push ]; + description = '' + A list of global znc module packages to add to znc. + ''; + }; mutable = mkOption { default = false; @@ -218,9 +250,9 @@ in }; extraFlags = mkOption { - default = ""; - example = "--debug"; - type = types.string; + default = [ ]; + example = [ "--debug" ]; + type = types.listOf types.str; description = '' Extra flags to use when executing znc command. ''; @@ -233,25 +265,22 @@ in config = mkIf cfg.enable { - systemd.services."znc-${cfg.user}" = { - description = "ZNC Server of ${cfg.user}."; + systemd.services.znc = { + description = "ZNC Server"; wantedBy = [ "multi-user.target" ]; after = [ "network.service" ]; - path = [ pkgs.znc ]; serviceConfig = { - User = "${cfg.user}"; + User = cfg.user; Restart = "always"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID"; }; preStart = '' - ${pkgs.coreutils}/bin/mkdir -p ${cfg.dataDir} - ${pkgs.coreutils}/bin/chown ${cfg.user} ${cfg.dataDir} -R ${pkgs.coreutils}/bin/mkdir -p ${cfg.dataDir}/configs # If mutable, regenerate conf file every time. ${optionalString (!cfg.mutable) '' - ${pkgs.coreutils}/echo "znc-${cfg.user} is set to be system-managed. Now deleting old znc.conf file to be regenerated." + ${pkgs.coreutils}/echo "znc is set to be system-managed. Now deleting old znc.conf file to be regenerated." ${pkgs.coreutils}/rm -f ${cfg.dataDir}/configs/znc.conf ''} @@ -259,7 +288,7 @@ in if [[ ! -f ${cfg.dataDir}/configs/znc.conf ]]; then ${pkgs.coreutils}/bin/echo "No znc.conf file found in ${cfg.dataDir}. Creating one now." ${if (!cfg.mutable) - then "${pkgs.coreutils}/bin/ln --force -s ${zncConfFile} ${cfg.dataDir}/configs/znc.conf" + then "${pkgs.coreutils}/bin/ln --force -s ${zncConfFile} ${cfg.dataDir}/.znc/configs/znc.conf" else '' ${pkgs.coreutils}/bin/cp --no-clobber ${zncConfFile} ${cfg.dataDir}/configs/znc.conf ${pkgs.coreutils}/bin/chmod u+rw ${cfg.dataDir}/configs/znc.conf @@ -269,10 +298,14 @@ in if [[ ! -f ${cfg.dataDir}/znc.pem ]]; then ${pkgs.coreutils}/bin/echo "No znc.pem file found in ${cfg.dataDir}. Creating one now." - ${pkgs.znc}/bin/znc --makepem + ${pkgs.znc}/bin/znc --makepem --datadir ${cfg.dataDir} fi + + # Symlink modules + rm ${cfg.dataDir}/modules || true + ln -fs ${modules}/lib/znc ${cfg.dataDir}/modules ''; - script = "${pkgs.znc}/bin/znc --foreground --datadir ${cfg.dataDir} ${cfg.extraFlags}"; + script = "${pkgs.znc}/bin/znc --foreground --datadir ${cfg.dataDir} ${toString cfg.extraFlags}"; }; users.extraUsers = optional (cfg.user == defaultUser) @@ -280,6 +313,7 @@ in description = "ZNC server daemon owner"; group = defaultUser; uid = config.ids.uids.znc; + home = cfg.dataDir; createHome = true; createUser = true; }; diff --git a/nixos/modules/services/search/elasticsearch.nix b/nixos/modules/services/search/elasticsearch.nix index eeae11dc4ff3..b74ef4370d76 100644 --- a/nixos/modules/services/search/elasticsearch.nix +++ b/nixos/modules/services/search/elasticsearch.nix @@ -21,6 +21,11 @@ let ]; }; + esPlugins = pkgs.buildEnv { + name = "elasticsearch-plugins"; + paths = cfg.plugins; + }; + in { ###### interface @@ -101,6 +106,12 @@ in { example = [ "-Djava.net.preferIPv4Stack=true" ]; }; + plugins = mkOption { + description = "Extra elasticsearch plugins"; + default = []; + type = types.listOf types.package; + }; + }; ###### implementation @@ -119,6 +130,10 @@ in { preStart = '' mkdir -m 0700 -p ${cfg.dataDir} if [ "$(id -u)" = 0 ]; then chown -R elasticsearch ${cfg.dataDir}; fi + + # Install plugins + rm ${cfg.dataDir}/plugins || true + ln -s ${esPlugins}/plugins ${cfg.dataDir}/plugins ''; }; diff --git a/nixos/modules/services/security/fail2ban.nix b/nixos/modules/services/security/fail2ban.nix index af5450166379..3758652ebddf 100644 --- a/nixos/modules/services/security/fail2ban.nix +++ b/nixos/modules/services/security/fail2ban.nix @@ -25,12 +25,17 @@ in options = { services.fail2ban = { + enable = mkOption { + default = false; + type = types.bool; + description = "Whether to enable the fail2ban service."; + }; daemonConfig = mkOption { default = '' [Definition] - loglevel = 3 + loglevel = INFO logtarget = SYSLOG socket = /run/fail2ban/fail2ban.sock pidfile = /run/fail2ban/fail2ban.pid @@ -80,7 +85,7 @@ in ###### implementation - config = { + config = mkIf cfg.enable { environment.systemPackages = [ pkgs.fail2ban ]; @@ -101,12 +106,13 @@ in preStart = '' mkdir -p /run/fail2ban -m 0755 + mkdir -p /var/lib/fail2ban ''; serviceConfig = { ExecStart = "${pkgs.fail2ban}/bin/fail2ban-server -f"; ReadOnlyDirectories = "/"; - ReadWriteDirectories = "/run /var/tmp"; + ReadWriteDirectories = "/run /var/tmp /var/lib"; CapabilityBoundingSet = "CAP_DAC_READ_SEARCH CAP_NET_ADMIN CAP_NET_RAW"; }; @@ -131,15 +137,14 @@ in bantime = 600 findtime = 600 maxretry = 3 - backend = auto - ''; + backend = systemd + ''; # Block SSH if there are too many failing connection attempts. services.fail2ban.jails.ssh-iptables = '' filter = sshd action = iptables[name=SSH, port=ssh, protocol=tcp] - logpath = /var/log/warn maxretry = 5 ''; diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix index 8d02a6404ac1..928f16c94489 100644 --- a/nixos/modules/services/system/dbus.nix +++ b/nixos/modules/services/system/dbus.nix @@ -14,7 +14,7 @@ let name = "dbus-conf"; preferLocalBuild = true; buildCommand = '' - ensureDir $out + mkdir -p $out cp -v ${pkgs.dbus.daemon}/etc/dbus-1/system.conf $out/system.conf diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix index b1a247163a47..b83cf276ed52 100644 --- a/nixos/modules/services/web-servers/apache-httpd/default.nix +++ b/nixos/modules/services/web-servers/apache-httpd/default.nix @@ -80,7 +80,7 @@ let # !!! should be in lib writeTextInDir = name: text: - pkgs.runCommand name {inherit text;} "ensureDir $out; echo -n \"$text\" > $out/$name"; + pkgs.runCommand name {inherit text;} "mkdir -p $out; echo -n \"$text\" > $out/$name"; enableSSL = any (vhost: vhost.enableSSL) allHosts; @@ -196,7 +196,7 @@ let ) null ([ cfg ] ++ subservices); documentRoot = if maybeDocumentRoot != null then maybeDocumentRoot else - pkgs.runCommand "empty" {} "ensureDir $out"; + pkgs.runCommand "empty" {} "mkdir -p $out"; documentRootConf = '' DocumentRoot "${documentRoot}" @@ -389,7 +389,7 @@ let ''; - enablePHP = any (svc: svc.enablePHP) allSubservices; + enablePHP = mainCfg.enablePHP || any (svc: svc.enablePHP) allSubservices; # Generate the PHP configuration file. Should probably be factored @@ -533,6 +533,12 @@ in ''; }; + enablePHP = mkOption { + type = types.bool; + default = false; + description = "Whether to enable the PHP module."; + }; + phpOptions = mkOption { type = types.lines; default = ""; diff --git a/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix b/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix index fa65ec0ef700..aa9aec87f0c4 100644 --- a/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix +++ b/nixos/modules/services/web-servers/apache-httpd/mediawiki.nix @@ -92,7 +92,7 @@ let installPhase = '' - ensureDir $out + mkdir -p $out cp -r * $out cp ${mediawikiConfig} $out/LocalSettings.php sed -i \ @@ -106,7 +106,7 @@ let mediawikiScripts = pkgs.runCommand "mediawiki-${config.id}-scripts" { buildInputs = [ pkgs.makeWrapper ]; } '' - ensureDir $out/bin + mkdir -p $out/bin for i in changePassword.php createAndPromote.php userOptions.php edit.php nukePage.php update.php; do makeWrapper ${php}/bin/php $out/bin/mediawiki-${config.id}-$(basename $i .php) \ --add-flags ${mediawikiRoot}/maintenance/$i diff --git a/nixos/modules/services/web-servers/apache-httpd/mercurial.nix b/nixos/modules/services/web-servers/apache-httpd/mercurial.nix index 1d4303b75b35..6dd91be00a73 100644 --- a/nixos/modules/services/web-servers/apache-httpd/mercurial.nix +++ b/nixos/modules/services/web-servers/apache-httpd/mercurial.nix @@ -9,7 +9,7 @@ let cgi = pkgs.stdenv.mkDerivation { name = "mercurial-cgi"; buildCommand = '' - ensureDir $out + mkdir -p $out cp -v ${mercurial}/share/cgi-bin/hgweb.cgi $out sed -i "s|/path/to/repo/or/config|$out/hgweb.config|" $out/hgweb.cgi echo " diff --git a/nixos/modules/services/web-servers/apache-httpd/tomcat-connector.nix b/nixos/modules/services/web-servers/apache-httpd/tomcat-connector.nix index b2cd53ae55cd..a883bb2b3433 100644 --- a/nixos/modules/services/web-servers/apache-httpd/tomcat-connector.nix +++ b/nixos/modules/services/web-servers/apache-httpd/tomcat-connector.nix @@ -29,6 +29,14 @@ ${extraWorkersProperties} ''; in { + + options = { + extraWorkersProperties = lib.mkOption { + default = ""; + description = "Additional configuration for the workers.properties file."; + }; + }; + extraModules = [ { name = "jk"; path = "${pkgs.tomcat_connectors}/modules/mod_jk.so"; } ]; diff --git a/nixos/modules/services/web-servers/lighttpd/cgit.nix b/nixos/modules/services/web-servers/lighttpd/cgit.nix index dbff565bd8a3..d4663781fd84 100644 --- a/nixos/modules/services/web-servers/lighttpd/cgit.nix +++ b/nixos/modules/services/web-servers/lighttpd/cgit.nix @@ -29,7 +29,7 @@ in cache-size=1000 scan-path=/srv/git ''; - type = types.string; + type = types.lines; description = '' Verbatim contents of the cgit runtime configuration file. Documentation (with cgitrc example file) is available in "man cgitrc". Or online: diff --git a/nixos/modules/services/web-servers/lighttpd/default.nix b/nixos/modules/services/web-servers/lighttpd/default.nix index 3ba934c72bf8..fc9487ab4859 100644 --- a/nixos/modules/services/web-servers/lighttpd/default.nix +++ b/nixos/modules/services/web-servers/lighttpd/default.nix @@ -9,9 +9,9 @@ let cfg = config.services.lighttpd; needModRedirect = cfg.gitweb.enable; - needModAlias = cfg.cgit.enable or cfg.gitweb.enable; - needModSetenv = cfg.cgit.enable or cfg.gitweb.enable; - needModCgi = cfg.cgit.enable or cfg.gitweb.enable; + needModAlias = cfg.cgit.enable || cfg.gitweb.enable; + needModSetenv = cfg.cgit.enable || cfg.gitweb.enable; + needModCgi = cfg.cgit.enable || cfg.gitweb.enable; needModStatus = cfg.mod_status; needModUserdir = cfg.mod_userdir; @@ -102,7 +102,7 @@ in document-root = mkOption { default = "/srv/www"; - type = types.str; + type = types.path; description = '' Document-root of the web server. Must be readable by the "lighttpd" user. ''; @@ -128,7 +128,7 @@ in configText = mkOption { default = ""; - type = types.string; + type = types.lines; example = ''...verbatim config file contents...''; description = '' Overridable config file contents to use for lighttpd. By default, use @@ -138,7 +138,7 @@ in extraConfig = mkOption { default = ""; - type = types.string; + type = types.lines; description = '' These configuration lines will be appended to the generated lighttpd config file. Note that this mechanism does not work when the manual diff --git a/nixos/modules/services/web-servers/lighttpd/gitweb.nix b/nixos/modules/services/web-servers/lighttpd/gitweb.nix index d49278be09a8..c407a1d89778 100644 --- a/nixos/modules/services/web-servers/lighttpd/gitweb.nix +++ b/nixos/modules/services/web-servers/lighttpd/gitweb.nix @@ -25,7 +25,7 @@ in projectroot = mkOption { default = "/srv/git"; - type = types.str; + type = types.path; description = '' Path to git projects (bare repositories) that should be served by gitweb. Must not end with a slash. @@ -34,7 +34,7 @@ in extraConfig = mkOption { default = ""; - type = types.str; + type = types.lines; description = '' Verbatim configuration text appended to the generated gitweb.conf file. ''; diff --git a/nixos/modules/services/web-servers/tomcat.nix b/nixos/modules/services/web-servers/tomcat.nix index 1de3d40165e9..c2f464014ae6 100644 --- a/nixos/modules/services/web-servers/tomcat.nix +++ b/nixos/modules/services/web-servers/tomcat.nix @@ -77,6 +77,11 @@ in description = "Whether to enable logging per virtual host."; }; + jdk = mkOption { + default = pkgs.jdk; + description = "Which JDK to use."; + }; + axis2 = { enable = mkOption { @@ -332,13 +337,13 @@ in ''; script = '' - ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c 'CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${pkgs.jdk} JAVA_OPTS="${cfg.javaOpts}" CATALINA_OPTS="${cfg.catalinaOpts}" ${tomcat}/bin/startup.sh' + ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c 'CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${cfg.jdk} JAVA_OPTS="${cfg.javaOpts}" CATALINA_OPTS="${cfg.catalinaOpts}" ${tomcat}/bin/startup.sh' ''; postStop = '' echo "Stopping tomcat..." - CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${pkgs.jdk} ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c ${tomcat}/bin/shutdown.sh + CATALINA_BASE=${cfg.baseDir} JAVA_HOME=${cfg.jdk} ${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${cfg.user} -c ${tomcat}/bin/shutdown.sh ''; }; diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix index b82398ccf9dd..c62beca60d84 100644 --- a/nixos/modules/services/x11/desktop-managers/default.nix +++ b/nixos/modules/services/x11/desktop-managers/default.nix @@ -17,7 +17,10 @@ in # Note: the order in which desktop manager modules are imported here # determines the default: later modules (if enabled) are preferred. # E.g., if KDE is enabled, it supersedes xterm. - imports = [ ./none.nix ./xterm.nix ./xfce.nix ./kde4.nix ./e17.nix ./gnome3.nix ./xbmc.nix ]; + imports = [ + ./none.nix ./xterm.nix ./xfce.nix ./kde4.nix + ./e17.nix ./e18.nix ./gnome3.nix ./xbmc.nix + ]; options = { diff --git a/nixos/modules/services/x11/desktop-managers/e18.nix b/nixos/modules/services/x11/desktop-managers/e18.nix new file mode 100644 index 000000000000..faafd21b07dd --- /dev/null +++ b/nixos/modules/services/x11/desktop-managers/e18.nix @@ -0,0 +1,43 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + + xcfg = config.services.xserver; + cfg = xcfg.desktopManager.e18; + e18_enlightenment = pkgs.e18.enlightenment.override { set_freqset_setuid = true; }; + +in + +{ + options = { + + services.xserver.desktopManager.e18.enable = mkOption { + default = false; + example = true; + description = "Enable the E18 desktop environment."; + }; + + }; + + config = mkIf (xcfg.enable && cfg.enable) { + + environment.systemPackages = [ + pkgs.e18.efl pkgs.e18.evas pkgs.e18.emotion pkgs.e18.elementary e18_enlightenment + pkgs.e18.terminology pkgs.e18.econnman + ]; + + services.xserver.desktopManager.session = [ + { name = "E18"; + start = '' + ${e18_enlightenment}/bin/enlightenment_start + waitPID=$! + ''; + }]; + + security.setuidPrograms = [ "e18_freqset" ]; + + }; + +} diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix index df50ca8c905c..06bcb6dbb8be 100644 --- a/nixos/modules/services/x11/desktop-managers/gnome3.nix +++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix @@ -35,6 +35,14 @@ in { description = "Enable Gnome 3 desktop manager."; }; + services.xserver.desktopManager.gnome3.sessionPath = mkOption { + default = []; + example = "[ pkgs.gnome3.gpaste ]"; + description = "Additional list of packages to be added to the session search path. + Useful for gnome shell extensions or gsettings-conditionated autostart."; + apply = list: list ++ [ gnome3.gnome_shell ]; + }; + environment.gnome3.packageSet = mkOption { default = pkgs.gnome3; example = literalExample "pkgs.gnome3_12"; @@ -86,10 +94,19 @@ in { export XDG_MENU_PREFIX=gnome - # Don't let epiphany depend upon gnome-shell - # Don't let gnome-session depend upon vino (for .desktop autostart condition) + ${concatMapStrings (p: '' + if [ -d "${p}/share/gsettings-schemas/${p.name}" ]; then + export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${p}/share/gsettings-schemas/${p.name} + fi + + if [ -d "${p}/lib/girepository-1.0" ]; then + export GI_TYPELIB_PATH=$GI_TYPELIB_PATH''${GI_TYPELIB_PATH:+:}${p}/lib/girepository-1.0 + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}${p}/lib + fi + '') cfg.sessionPath} + # Override default mimeapps - export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${gnome3.gnome_shell}/share/gsettings-schemas/${gnome3.gnome_shell.name}:${gnome3.vino}/share/gsettings-schemas/${gnome3.vino.name}:${mimeAppsList}/share + export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${mimeAppsList}/share # Let gnome-control-center find gnome-shell search providers export GNOME_SEARCH_PROVIDERS_DIR=${config.system.path}/share/gnome-shell/search-providers/ @@ -123,7 +140,7 @@ in { gnome3.gnome_settings_daemon gnome3.gnome_shell gnome3.gnome_themes_standard - ] ++ (removePackagesByName [ + ] ++ cfg.sessionPath ++ (removePackagesByName [ gnome3.baobab gnome3.empathy gnome3.eog diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix new file mode 100644 index 000000000000..9d14fc2e137c --- /dev/null +++ b/nixos/modules/services/x11/display-managers/gdm.nix @@ -0,0 +1,151 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.xserver.displayManager; + gdm = pkgs.gnome3_12.gdm; # gdm 3.10 not supported + gnome3 = config.environment.gnome3.packageSet; + +in + +{ + + ###### interface + + options = { + + services.xserver.displayManager.gdm = { + + enable = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + Whether to enable GDM as the display manager. + <emphasis>GDM is very experimental and may render system unusable.</emphasis> + ''; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.gdm.enable { + + services.xserver.displayManager.slim.enable = false; + + users.extraUsers.gdm = + { name = "gdm"; + uid = config.ids.uids.gdm; + group = "gdm"; + home = "/run/gdm"; + description = "GDM user"; + }; + + users.extraGroups.gdm.gid = config.ids.gids.gdm; + + services.xserver.displayManager.job = + { + environment = { + GDM_X_SERVER = "${cfg.xserverBin} ${cfg.xserverArgs}"; + GDM_SESSIONS_DIR = "${cfg.session.desktops}"; + XDG_CONFIG_DIRS = "${gnome3.gnome_settings_daemon}/etc/xdg"; + }; + execCmd = "exec ${gdm}/sbin/gdm"; + }; + + # Because sd_login_monitor_new requires /run/systemd/machines + systemd.services.display-manager.wants = [ "systemd-machined.service" ]; + systemd.services.display-manager.after = [ "systemd-machined.service" ]; + + systemd.services.display-manager.path = [ gnome3.gnome_shell gnome3.caribou ]; + + services.dbus.packages = [ gdm ]; + + programs.dconf.profiles.gdm = "${gdm}/share/dconf/profile/gdm"; + + # GDM LFS PAM modules, adapted somehow to NixOS + security.pam.services = { + gdm-launch-environment.text = '' + auth required pam_succeed_if.so audit quiet_success user = gdm + auth optional pam_permit.so + + account required pam_succeed_if.so audit quiet_success user = gdm + account sufficient pam_unix.so + + password required pam_deny.so + + session required pam_succeed_if.so audit quiet_success user = gdm + session required pam_env.so envfile=${config.system.build.pamEnvironment} + session optional ${pkgs.systemd}/lib/security/pam_systemd.so + session optional pam_keyinit.so force revoke + session optional pam_permit.so + ''; + + gdm.text = '' + auth requisite pam_nologin.so + auth required pam_env.so + + auth required pam_succeed_if.so uid >= 1000 quiet + auth optional ${gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so + auth sufficient pam_unix.so nullok likeauth + auth required pam_deny.so + + account sufficient pam_unix.so + + password requisite pam_unix.so nullok sha512 + + session required pam_env.so envfile=${config.system.build.pamEnvironment} + session required pam_unix.so + session required pam_loginuid.so + session optional ${pkgs.systemd}/lib/security/pam_systemd.so + session optional ${gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so auto_start + ''; + + gdm-password.text = '' + auth requisite pam_nologin.so + auth required pam_env.so envfile=${config.system.build.pamEnvironment} + + auth required pam_succeed_if.so uid >= 1000 quiet + auth optional ${gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so + auth sufficient pam_unix.so nullok likeauth + auth required pam_deny.so + + account sufficient pam_unix.so + + password requisite pam_unix.so nullok sha512 + + session required pam_env.so envfile=${config.system.build.pamEnvironment} + session required pam_unix.so + session required pam_loginuid.so + session optional ${pkgs.systemd}/lib/security/pam_systemd.so + session optional ${gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so auto_start + ''; + + gdm-autologin.text = '' + auth requisite pam_nologin.so + + auth required pam_succeed_if.so uid >= 1000 quiet + auth required pam_permit.so + + account sufficient pam_unix.so + + password requisite pam_unix.so nullok sha512 + + session optional pam_keyinit.so revoke + session required pam_env.so envfile=${config.system.build.pamEnvironment} + session required pam_unix.so + session required pam_loginuid.so + session optional ${pkgs.systemd}/lib/security/pam_systemd.so + ''; + + }; + + }; + +} diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix index d459c59b0483..f8ce06738fee 100644 --- a/nixos/modules/services/x11/display-managers/lightdm.nix +++ b/nixos/modules/services/x11/display-managers/lightdm.nix @@ -26,7 +26,7 @@ let buildInputs = [ pkgs.makeWrapper ]; buildCommand = '' - ensureDir $out/gtk-3.0/ + mkdir -p $out/gtk-3.0/ # This wrapper ensures that we actually get fonts makeWrapper ${pkgs.lightdm_gtk_greeter}/sbin/lightdm-gtk-greeter \ diff --git a/nixos/modules/services/x11/display-managers/slim.nix b/nixos/modules/services/x11/display-managers/slim.nix index 48feb12d044c..9ee4e0dc7cb0 100644 --- a/nixos/modules/services/x11/display-managers/slim.nix +++ b/nixos/modules/services/x11/display-managers/slim.nix @@ -27,7 +27,7 @@ let unpackedTheme = pkgs.stdenv.mkDerivation { name = "slim-theme"; buildCommand = '' - ensureDir $out + mkdir -p $out cd $out unpackFile ${cfg.theme} ln -s * default diff --git a/nixos/modules/services/x11/hardware/synaptics.nix b/nixos/modules/services/x11/hardware/synaptics.nix index f2227a34a20c..f5b394b6d98b 100644 --- a/nixos/modules/services/x11/hardware/synaptics.nix +++ b/nixos/modules/services/x11/hardware/synaptics.nix @@ -41,16 +41,19 @@ in { }; accelFactor = mkOption { + type = types.nullOr types.string; default = "0.001"; description = "Cursor acceleration (how fast speed increases from minSpeed to maxSpeed)."; }; minSpeed = mkOption { + type = types.nullOr types.string; default = "0.6"; description = "Cursor speed factor for precision finger motion."; }; maxSpeed = mkOption { + type = types.nullOr types.string; default = "1.0"; description = "Cursor speed factor for highest-speed finger motion."; }; @@ -120,9 +123,9 @@ in { MatchIsTouchpad "on" ${optionalString (cfg.dev != null) ''MatchDevicePath "${cfg.dev}"''} Driver "synaptics" - Option "MinSpeed" "${cfg.minSpeed}" - Option "MaxSpeed" "${cfg.maxSpeed}" - Option "AccelFactor" "${cfg.accelFactor}" + ${optionalString (cfg.minSpeed != null) ''Option "MinSpeed" "${cfg.minSpeed}"''} + ${optionalString (cfg.maxSpeed != null) ''Option "MaxSpeed" "${cfg.maxSpeed}"''} + ${optionalString (cfg.accelFactor != null) ''Option "AccelFactor" "${cfg.accelFactor}"''} ${optionalString cfg.tapButtons tapConfig} Option "ClickFinger1" "${builtins.elemAt cfg.buttonsMap 0}" Option "ClickFinger2" "${builtins.elemAt cfg.buttonsMap 1}" diff --git a/nixos/modules/services/x11/window-managers/bspwm.nix b/nixos/modules/services/x11/window-managers/bspwm.nix new file mode 100644 index 000000000000..d234a432e9a9 --- /dev/null +++ b/nixos/modules/services/x11/window-managers/bspwm.nix @@ -0,0 +1,29 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.xserver.windowManager.bspwm; +in + +{ + options = { + services.xserver.windowManager.bspwm.enable = mkOption { + type = types.bool; + default = false; + example = true; + description = "Enable the bspwm window manager."; + }; + }; + + config = mkIf cfg.enable { + services.xserver.windowManager.session = singleton { + name = "bspwm"; + start = " + ${pkgs.sxhkd}/bin/sxhkd & + ${pkgs.bspwm}/bin/bspwm + "; + }; + environment.systemPackages = [ pkgs.bspwm ]; + }; +} diff --git a/nixos/modules/services/x11/window-managers/default.nix b/nixos/modules/services/x11/window-managers/default.nix index f27ba3661413..45a4e947e0aa 100644 --- a/nixos/modules/services/x11/window-managers/default.nix +++ b/nixos/modules/services/x11/window-managers/default.nix @@ -17,6 +17,7 @@ in ./xmonad.nix ./i3.nix ./herbstluftwm.nix + ./bspwm.nix ]; options = { diff --git a/nixos/modules/system/activation/activation-script.nix b/nixos/modules/system/activation/activation-script.nix index b1bad956b4bb..2e5a70b3aa54 100644 --- a/nixos/modules/system/activation/activation-script.nix +++ b/nixos/modules/system/activation/activation-script.nix @@ -66,6 +66,9 @@ in PATH=$PATH:$i/bin:$i/sbin done + _status=0 + trap "_status=1" ERR + # Ensure a consistent umask. umask 0022 @@ -84,6 +87,8 @@ in # Prevent the current configuration from being garbage-collected. ln -sfn /run/current-system /nix/var/nix/gcroots/current-system + + exit $_status ''; }; diff --git a/nixos/modules/system/boot/emergency-mode.nix b/nixos/modules/system/boot/emergency-mode.nix new file mode 100644 index 000000000000..9cdab8416192 --- /dev/null +++ b/nixos/modules/system/boot/emergency-mode.nix @@ -0,0 +1,37 @@ +{ config, lib, ... }: + +with lib; + +{ + + ###### interface + + options = { + + systemd.enableEmergencyMode = mkOption { + default = true; + type = types.bool; + description = '' + Whether to enable emergency mode, which is an + <command>sulogin</command> shell started on the console if + mounting a filesystem fails. Since some machines (like EC2 + instances) have no console of any kind, emergency mode doesn't + make sense, and it's better to continue with the boot insofar + as possible. + ''; + }; + + }; + + ###### implementation + + config = { + + systemd.additionalUpstreamSystemUnits = optionals + config.systemd.enableEmergencyMode [ + "emergency.target" "emergency.service" + ]; + + }; + +} \ No newline at end of file diff --git a/nixos/modules/system/boot/modprobe.nix b/nixos/modules/system/boot/modprobe.nix index 7b214cd1e1f5..652eb046f50a 100644 --- a/nixos/modules/system/boot/modprobe.nix +++ b/nixos/modules/system/boot/modprobe.nix @@ -68,20 +68,15 @@ with lib; config = mkIf (!config.boot.isContainer) { - environment.etc = [ - { source = "${pkgs.kmod-blacklist-ubuntu}/modprobe.conf"; - target = "modprobe.d/ubuntu.conf"; - } - { source = pkgs.writeText "modprobe.conf" - '' - ${flip concatMapStrings config.boot.blacklistedKernelModules (name: '' - blacklist ${name} - '')} - ${config.boot.extraModprobeConfig} - ''; - target = "modprobe.d/nixos.conf"; - } - ]; + environment.etc."modprobe.d/ubuntu.conf".source = "${pkgs.kmod-blacklist-ubuntu}/modprobe.conf"; + + environment.etc."modprobe.d/nixos.conf".text = + '' + ${flip concatMapStrings config.boot.blacklistedKernelModules (name: '' + blacklist ${name} + '')} + ${config.boot.extraModprobeConfig} + ''; environment.systemPackages = [ config.system.sbin.modprobe pkgs.kmod ]; diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh index 7adb932aba7f..73fc6ce543cf 100644 --- a/nixos/modules/system/boot/stage-1-init.sh +++ b/nixos/modules/system/boot/stage-1-init.sh @@ -4,7 +4,8 @@ targetRoot=/mnt-root console=tty1 export LD_LIBRARY_PATH=@extraUtils@/lib -export PATH=@extraUtils@/bin:@extraUtils@/sbin +export PATH=@extraUtils@/bin +ln -s @extraUtils@/bin /bin fail() { @@ -193,6 +194,9 @@ checkFS() { # Don't check ROM filesystems. if [ "$fsType" = iso9660 -o "$fsType" = udf ]; then return 0; fi + # Don't check resilient COWs as they validate the fs structures at mount time + if [ "$fsType" = btrfs -o "$fsType" = zfs ]; then return 0; fi + # If we couldn't figure out the FS type, then skip fsck. if [ "$fsType" = auto ]; then echo 'cannot check filesystem with type "auto"!' @@ -262,6 +266,13 @@ mountFS() { checkFS "$device" "$fsType" + # Create backing directories for unionfs-fuse. + if [ "$fsType" = unionfs-fuse ]; then + for i in $(IFS=:; echo ${options##*,dirs=}); do + mkdir -m 0700 -p /mnt-root"${i%=*}" + done + fi + echo "mounting $device on $mountPoint..." mkdir -p "/mnt-root$mountPoint" || true diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix index b6249b6c0915..6a069c5d0540 100644 --- a/nixos/modules/system/boot/stage-1.nix +++ b/nixos/modules/system/boot/stage-1.nix @@ -23,22 +23,6 @@ let }; - needsCifsUtils = kernelPackages.kernel ? features - && kernelPackages.kernel.features ? needsCifsUtils - && kernelPackages.kernel.features.needsCifsUtils - && any (fs: fs.fsType == "cifs") fileSystems; - - busybox = - if needsCifsUtils - then pkgs.busybox.override { - extraConfig = '' - CONFIG_FEATURE_MOUNT_CIFS n - CONFIG_FEATURE_MOUNT_HELPERS y - ''; - } - else pkgs.busybox; - - # Some additional utilities needed in stage 1, like mount, lvm, fsck # etc. We don't want to bring in all of those packages, so we just # copy what we need. Instead of using statically linked binaries, @@ -51,6 +35,7 @@ let } '' mkdir -p $out/bin $out/lib + ln -s $out/bin $out/sbin # Copy what we need from Glibc. cp -pv ${pkgs.glibc}/lib/ld*.so.? $out/lib @@ -62,11 +47,10 @@ let cp -pv ${pkgs.gcc.gcc}/lib*/libgcc_s.so.* $out/lib # Copy BusyBox. - cp -rvd ${busybox}/{bin,sbin} $out/ - chmod -R u+w $out + cp -pvd ${pkgs.busybox}/bin/* ${pkgs.busybox}/sbin/* $out/bin/ # Copy some utillinux stuff. - cp -v ${pkgs.utillinux}/sbin/blkid $out/bin + cp -vf ${pkgs.utillinux}/sbin/blkid $out/bin cp -pdv ${pkgs.utillinux}/lib/libblkid*.so.* $out/lib cp -pdv ${pkgs.utillinux}/lib/libuuid*.so.* $out/lib @@ -89,12 +73,7 @@ let # Copy modprobe. cp -v ${pkgs.kmod}/bin/kmod $out/bin/ - ln -s kmod $out/bin/modprobe - - # Maybe copy cifs utils - ${optionalString needsCifsUtils '' - cp -v ${pkgs.cifs_utils}/sbin/mount.cifs $out/bin - ''} + ln -sf kmod $out/bin/modprobe ${config.boot.initrd.extraUtilsCommands} @@ -140,7 +119,7 @@ let udevRules = pkgs.stdenv.mkDerivation { name = "udev-rules"; buildCommand = '' - ensureDir $out + mkdir -p $out echo 'ENV{LD_LIBRARY_PATH}="${extraUtils}/lib"' > $out/00-env.rules @@ -313,6 +292,13 @@ in example = "xz"; }; + boot.initrd.supportedFilesystems = mkOption { + default = [ ]; + example = [ "btrfs" ]; + type = types.listOf types.string; + description = "Names of supported filesystem types in the initial ramdisk."; + }; + fileSystems = mkOption { options.neededForBoot = mkOption { default = false; @@ -347,5 +333,7 @@ in # Prevent systemd from waiting for the /dev/root symlink. systemd.units."dev-root.device".text = ""; + boot.initrd.supportedFilesystems = map (fs: fs.fsType) fileSystems; + }; } diff --git a/nixos/modules/system/boot/stage-2-init.sh b/nixos/modules/system/boot/stage-2-init.sh index eff2fb583bab..6fff776f8581 100644 --- a/nixos/modules/system/boot/stage-2-init.sh +++ b/nixos/modules/system/boot/stage-2-init.sh @@ -29,7 +29,9 @@ setPath "@path@" # Normally, stage 1 mounts the root filesystem read/writable. # However, in some environments, stage 2 is executed directly, and the # root is read-only. So make it writable here. -mount -n -o remount,rw / +if [ "$container" != systemd-nspawn ]; then + mount -n -o remount,rw none / +fi # Likewise, stage 1 mounts /proc, /dev and /sys, so if we don't have a @@ -98,12 +100,6 @@ mkdir -m 0755 -p /etc/nixos rm -rf /var/run /var/lock rm -f /etc/{group,passwd,shadow}.lock -if test -n "@cleanTmpDir@"; then - echo -n "cleaning \`/tmp'..." - find /tmp -maxdepth 1 -mindepth 1 -print0 | xargs -0r rm -rf --one-file-system - echo " done" -fi - # Also get rid of temporary GC roots. rm -rf /nix/var/nix/gcroots/tmp /nix/var/nix/temproots @@ -186,4 +182,4 @@ echo "starting systemd..." PATH=/run/current-system/systemd/lib/systemd \ MODULE_DIR=/run/booted-system/kernel-modules/lib/modules \ LOCALE_ARCHIVE=/run/current-system/sw/lib/locale/locale-archive \ - exec systemd --log-target=journal # --log-level=debug --log-target=console --crash-shell + exec systemd diff --git a/nixos/modules/system/boot/stage-2.nix b/nixos/modules/system/boot/stage-2.nix index f53c3b8b8e70..6155bb37cc52 100644 --- a/nixos/modules/system/boot/stage-2.nix +++ b/nixos/modules/system/boot/stage-2.nix @@ -17,7 +17,7 @@ let src = ./stage-2-init.sh; shellDebug = "${pkgs.bashInteractive}/bin/bash"; isExecutable = true; - inherit (config.boot) devShmSize runSize cleanTmpDir; + inherit (config.boot) devShmSize runSize; inherit (config.nix) readOnlyStore; inherit (config.networking) useHostResolvConf; ttyGid = config.ids.gids.tty; @@ -26,8 +26,7 @@ let pkgs.utillinux pkgs.sysvtools pkgs.openresolv - ] ++ (optional config.boot.cleanTmpDir pkgs.findutils) - ++ optional config.nix.readOnlyStore readonlyMountpoint; + ] ++ optional config.nix.readOnlyStore readonlyMountpoint; postBootCommands = pkgs.writeText "local-cmds" '' ${config.boot.postBootCommands} @@ -81,15 +80,6 @@ in ''; }; - # FIXME: should replace this with something that uses systemd-tmpfiles. - cleanTmpDir = mkOption { - type = types.bool; - default = false; - description = '' - Whether to delete all files in <filename>/tmp</filename> during boot. - ''; - }; - }; }; diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index 51ebca7dd43c..e353e9246b0e 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -162,10 +162,7 @@ let "systemd-sysctl.service" ] - ++ optionals cfg.enableEmergencyMode [ - "emergency.target" - "emergency.service" - ]; + ++ cfg.additionalUpstreamSystemUnits; upstreamSystemWants = [ #"basic.target.wants" @@ -317,7 +314,9 @@ let '' [Service] ${let env = cfg.globalEnvironment // def.environment; - in concatMapStrings (n: "Environment=\"${n}=${getAttr n env}\"\n") (attrNames env)} + in concatMapStrings (n: + let s = "Environment=\"${n}=${getAttr n env}\"\n"; + in if stringLength s >= 2048 then throw "The value of the environment variable ‘${n}’ in systemd service ‘${name}.service’ is too long." else s) (attrNames env)} ${if def.reloadIfChanged then '' X-ReloadIfChanged=true '' else if !def.restartIfChanged then '' @@ -635,19 +634,6 @@ in ''; }; - systemd.enableEmergencyMode = mkOption { - default = true; - type = types.bool; - description = '' - Whether to enable emergency mode, which is an - <command>sulogin</command> shell started on the console if - mounting a filesystem fails. Since some machines (like EC2 - instances) have no console of any kind, emergency mode doesn't - make sense, and it's better to continue with the boot insofar - as possible. - ''; - }; - systemd.tmpfiles.rules = mkOption { type = types.listOf types.str; default = []; @@ -690,6 +676,15 @@ in description = "Definition of systemd per-user socket units."; }; + systemd.additionalUpstreamSystemUnits = mkOption { + default = [ ]; + type = types.listOf types.str; + example = [ "debug-shell.service" "systemd-quotacheck.service" ]; + description = '' + Additional units shipped with systemd that shall be enabled. + ''; + }; + }; @@ -749,7 +744,7 @@ in # Make all journals readable to users in the wheel and adm # groups, in addition to those in the systemd-journal group. # Users can always read their own journals. - ${pkgs.acl}/bin/setfacl -nm g:wheel:rx,d:g:wheel:rx,g:adm:rx,d:g:adm:rx /var/log/journal + ${pkgs.acl}/bin/setfacl -nm g:wheel:rx,d:g:wheel:rx,g:adm:rx,d:g:adm:rx /var/log/journal || true ''; # Target for ‘charon send-keys’ to hook into. @@ -824,5 +819,8 @@ in systemd.services."user@".restartIfChanged = false; + systemd.services.systemd-remount-fs.restartIfChanged = false; + systemd.services.systemd-journal-flush.restartIfChanged = false; + }; } diff --git a/nixos/modules/system/boot/tmp.nix b/nixos/modules/system/boot/tmp.nix new file mode 100644 index 000000000000..5bf5e2eb2ec5 --- /dev/null +++ b/nixos/modules/system/boot/tmp.nix @@ -0,0 +1,39 @@ +{ config, lib, ... }: + +with lib; + +{ + + ###### interface + + options = { + + boot.cleanTmpDir = mkOption { + type = types.bool; + default = false; + description = '' + Whether to delete all files in <filename>/tmp</filename> during boot. + ''; + }; + + boot.tmpOnTmpfs = mkOption { + type = types.bool; + default = false; + description = '' + Whether to mount a tmpfs on <filename>/tmp</filename> during boot. + ''; + }; + + }; + + ###### implementation + + config = { + + systemd.additionalUpstreamSystemUnits = optional config.boot.tmpOnTmpfs "tmp.mount"; + + systemd.tmpfiles.rules = optional config.boot.cleanTmpDir "D! /tmp 1777 root root"; + + }; + +} \ No newline at end of file diff --git a/nixos/modules/system/etc/etc.nix b/nixos/modules/system/etc/etc.nix index 22d55a9e246c..b57b03bcf962 100644 --- a/nixos/modules/system/etc/etc.nix +++ b/nixos/modules/system/etc/etc.nix @@ -132,7 +132,7 @@ in '' # Set up the statically computed bits of /etc. echo "setting up /etc..." - ${pkgs.perl}/bin/perl ${./setup-etc.pl} ${etc}/etc + ${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl ${./setup-etc.pl} ${etc}/etc ''; }; diff --git a/nixos/modules/system/etc/setup-etc.pl b/nixos/modules/system/etc/setup-etc.pl index 8ba9a370b27a..d7e15eccefcd 100644 --- a/nixos/modules/system/etc/setup-etc.pl +++ b/nixos/modules/system/etc/setup-etc.pl @@ -3,6 +3,7 @@ use File::Find; use File::Copy; use File::Path; use File::Basename; +use File::Slurp; my $etc = $ARGV[0] or die; my $static = "/etc/static"; @@ -46,35 +47,55 @@ sub cleanup { find(\&cleanup, "/etc"); +# Use /etc/.clean to keep track of copied files. +my @oldCopied = read_file("/etc/.clean", chomp => 1, err_mode => 'quiet'); +open CLEAN, ">>/etc/.clean"; + + # For every file in the etc tree, create a corresponding symlink in # /etc to /etc/static. The indirection through /etc/static is to make # switching to a new configuration somewhat more atomic. +my %created; +my @copied; + sub link { my $fn = substr $File::Find::name, length($etc) + 1 or next; my $target = "/etc/$fn"; File::Path::make_path(dirname $target); + $created{$fn} = 1; if (-e "$_.mode") { - open MODE, "<$_.mode"; - my $mode = <MODE>; chomp $mode; - close MODE; + my $mode = read_file("$_.mode"); chomp $mode; if ($mode eq "direct-symlink") { atomicSymlink readlink("$static/$fn"), $target or warn; } else { - open UID, "<$_.uid"; - my $uid = <UID>; chomp $uid; - close UID; - open GID, "<$_.gid"; - my $gid = <GID>; chomp $gid; - close GID; - + my $uid = read_file("$_.uid"); chomp $uid; + my $gid = read_file("$_.gid"); chomp $gid; copy "$static/$fn", "$target.tmp" or warn; chown int($uid), int($gid), "$target.tmp" or warn; chmod oct($mode), "$target.tmp" or warn; rename "$target.tmp", $target or warn; } + push @copied, $fn; + print CLEAN "$fn\n"; } elsif (-l "$_") { atomicSymlink "$static/$fn", $target or warn; } } find(\&link, $etc); + + +# Delete files that were copied in a previous version but not in the +# current. +foreach my $fn (@oldCopied) { + if (!defined $created{$fn}) { + $fn = "/etc/$fn"; + print STDERR "removing obsolete file ‘$fn’...\n"; + unlink "$fn"; + } +} + + +# Rewrite /etc/.clean. +close CLEAN; +write_file("/etc/.clean", map { "$_\n" } @copied); diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix index d350bc1b5d0e..64a20034f3cc 100644 --- a/nixos/modules/tasks/filesystems.nix +++ b/nixos/modules/tasks/filesystems.nix @@ -9,7 +9,7 @@ let prioOption = prio: optionalString (prio !=null) " pri=${toString prio}"; - fileSystemOpts = { name, ... }: { + fileSystemOpts = { name, config, ... }: { options = { @@ -68,6 +68,7 @@ let config = { mountPoint = mkDefault name; + device = mkIf (config.fsType == "tmpfs") (mkDefault config.fsType); }; }; @@ -124,13 +125,6 @@ in description = "Names of supported filesystem types."; }; - boot.initrd.supportedFilesystems = mkOption { - default = [ ]; - example = [ "btrfs" ]; - type = types.listOf types.string; - description = "Names of supported filesystem types in the initial ramdisk."; - }; - }; @@ -140,15 +134,11 @@ in boot.supportedFilesystems = map (fs: fs.fsType) fileSystems; - boot.initrd.supportedFilesystems = - map (fs: fs.fsType) - (filter (fs: fs.mountPoint == "/" || fs.neededForBoot) fileSystems); - # Add the mount helpers to the system path so that `mount' can find them. system.fsPackages = [ pkgs.dosfstools ]; environment.systemPackages = - [ pkgs.ntfs3g pkgs.cifs_utils pkgs.fuse ] + [ pkgs.ntfs3g pkgs.fuse ] ++ config.system.fsPackages; environment.etc.fstab.text = @@ -157,7 +147,9 @@ in # Filesystems. ${flip concatMapStrings fileSystems (fs: - (if fs.device != null then fs.device else "/dev/disk/by-label/${fs.label}") + (if fs.device != null then fs.device + else if fs.label != null then "/dev/disk/by-label/${fs.label}" + else throw "No device specified for mount point ‘${fs.mountPoint}’.") + " " + fs.mountPoint + " " + fs.fsType + " " + fs.options diff --git a/nixos/modules/tasks/filesystems/cifs.nix b/nixos/modules/tasks/filesystems/cifs.nix new file mode 100644 index 000000000000..c60f175db841 --- /dev/null +++ b/nixos/modules/tasks/filesystems/cifs.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + inInitrd = any (fs: fs == "cifs") config.boot.initrd.supportedFilesystems; + +in + +{ + config = { + + system.fsPackages = [ pkgs.cifs_utils ]; + + boot.initrd.availableKernelModules = mkIf inInitrd + [ "cifs" "nls_utf8" "hmac" "md4" "ecb" "des_generic" "sha256" ]; + + boot.initrd.extraUtilsCommands = mkIf inInitrd + '' + cp -v ${pkgs.cifs_utils}/sbin/mount.cifs $out/bin + ''; + + }; +} diff --git a/nixos/modules/tasks/filesystems/unionfs-fuse.nix b/nixos/modules/tasks/filesystems/unionfs-fuse.nix index 5b7777180568..fe195e0db0b6 100644 --- a/nixos/modules/tasks/filesystems/unionfs-fuse.nix +++ b/nixos/modules/tasks/filesystems/unionfs-fuse.nix @@ -2,14 +2,21 @@ { config = lib.mkMerge [ + (lib.mkIf (lib.any (fs: fs == "unionfs-fuse") config.boot.initrd.supportedFilesystems) { boot.initrd.kernelModules = [ "fuse" ]; - + boot.initrd.extraUtilsCommands = '' cp -v ${pkgs.fuse}/lib/libfuse* $out/lib + cp -v ${pkgs.fuse}/sbin/mount.fuse $out/bin cp -v ${pkgs.unionfs-fuse}/bin/unionfs $out/bin + substitute ${pkgs.unionfs-fuse}/sbin/mount.unionfs-fuse $out/bin/mount.unionfs-fuse \ + --replace '${pkgs.bash}/bin/bash' /bin/sh \ + --replace '${pkgs.fuse}/sbin' /bin \ + --replace '${pkgs.unionfs-fuse}/bin' /bin + chmod +x $out/bin/mount.unionfs-fuse ''; - + boot.initrd.postDeviceCommands = '' # Hacky!!! fuse hard-codes the path to mount mkdir -p /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${pkgs.utillinux.name}/bin @@ -17,8 +24,10 @@ ln -s $(which umount) /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${pkgs.utillinux.name}/bin ''; }) + (lib.mkIf (lib.any (fs: fs == "unionfs-fuse") config.boot.supportedFilesystems) { system.fsPackages = [ pkgs.unionfs-fuse ]; }) + ]; } diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index 991f9f261450..7dabe70f00c4 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -7,6 +7,7 @@ let cfg = config.networking; interfaces = attrValues cfg.interfaces; hasVirtuals = any (i: i.virtual) interfaces; + hasSits = cfg.sits != { }; hasBonds = cfg.bonds != { }; interfaceOpts = { name, ... }: { @@ -321,6 +322,66 @@ in }; }; + networking.sits = mkOption { + type = types.attrsOf types.optionSet; + default = { }; + example = { + hurricane = { + remote = "10.0.0.1"; + local = "10.0.0.22"; + ttl = 255; + }; + msipv6 = { + remote = "192.168.0.1"; + dev = "enp3s0"; + ttl = 127; + }; + }; + description = '' + This option allows you to define 6-to-4 interfaces which should be automatically created. + ''; + options = { + + remote = mkOption { + type = types.nullOr types.str; + default = null; + example = "10.0.0.1"; + description = '' + The address of the remote endpoint to forward traffic over. + ''; + }; + + local = mkOption { + type = types.nullOr types.str; + default = null; + example = "10.0.0.22"; + description = '' + The address of the local endpoint which the remote + side should send packets to. + ''; + }; + + ttl = mkOption { + type = types.nullOr types.int; + default = null; + example = 255; + description = '' + The time-to-live of the connection to the remote tunnel endpoint. + ''; + }; + + dev = mkOption { + type = types.nullOr types.str; + default = null; + example = "enp4s0f0"; + description = '' + The underlying network device on which the tunnel resides. + ''; + }; + + }; + }; + networking.vlans = mkOption { default = { }; example = { @@ -380,6 +441,7 @@ in boot.kernelModules = [ ] ++ optional cfg.enableIPv6 "ipv6" ++ optional hasVirtuals "tun" + ++ optional hasSits "sit" ++ optional hasBonds "bonding"; boot.extraModprobeConfig = @@ -641,6 +703,32 @@ in ''; }; + createSitDevice = n: v: + let + deps = optional (v.dev != null) "sys-subsystem-net-devices-${v.dev}.device"; + in + { description = "6-to-4 Tunnel Interface ${n}"; + wantedBy = [ "network.target" "sys-subsystem-net-devices-${n}.device" ]; + bindsTo = deps; + after = deps; + serviceConfig.Type = "oneshot"; + serviceConfig.RemainAfterExit = true; + path = [ pkgs.iproute ]; + script = '' + # Remove Dead Interfaces + ip link show "${n}" >/dev/null 2>&1 && ip link delete "${n}" + ip link add "${n}" type sit \ + ${optionalString (v.remote != null) "remote \"${v.remote}\""} \ + ${optionalString (v.local != null) "local \"${v.local}\""} \ + ${optionalString (v.ttl != null) "ttl ${toString v.ttl}"} \ + ${optionalString (v.dev != null) "dev \"${v.dev}\""} + ip link set "${n}" up + ''; + postStop = '' + ip link delete "${n}" + ''; + }; + createVlanDevice = n: v: let deps = [ "sys-subsystem-net-devices-${v.interface}.device" ]; @@ -668,6 +756,7 @@ in map createTunDevice (filter (i: i.virtual) interfaces)) // mapAttrs createBridgeDevice cfg.bridges // mapAttrs createBondDevice cfg.bonds + // mapAttrs createSitDevice cfg.sits // mapAttrs createVlanDevice cfg.vlans // { "network-setup" = networkSetup; }; diff --git a/nixos/modules/tasks/trackpoint.nix b/nixos/modules/tasks/trackpoint.nix index 4be2c3eb4c47..d1c6f8ac1565 100644 --- a/nixos/modules/tasks/trackpoint.nix +++ b/nixos/modules/tasks/trackpoint.nix @@ -46,21 +46,15 @@ with lib; config = mkIf config.hardware.trackpoint.enable { - jobs.trackpoint = - { description = "Initialize trackpoint"; - - startOn = "started udev"; - - task = true; - - script = '' - echo -n ${toString config.hardware.trackpoint.sensitivity} \ - > /sys/devices/platform/i8042/serio1/sensitivity - echo -n ${toString config.hardware.trackpoint.speed} \ - > /sys/devices/platform/i8042/serio1/speed - ''; - }; - + services.udev.extraRules = + '' + ACTION=="add|change", SUBSYSTEM=="input", ATTR{name}=="TPPS/2 IBM TrackPoint", ATTR{device/speed}="${toString config.hardware.trackpoint.speed}", ATTR{device/sensitivity}="${toString config.hardware.trackpoint.sensitivity}" + ''; + + system.activationScripts.trackpoint = + '' + ${config.systemd.package}/bin/udevadm trigger --attr-match=name="TPPS/2 IBM TrackPoint" + ''; }; } diff --git a/nixos/modules/tasks/tty-backgrounds-combine.sh b/nixos/modules/tasks/tty-backgrounds-combine.sh index 1e0d8758a6ee..55c3a1ebfa8a 100644 --- a/nixos/modules/tasks/tty-backgrounds-combine.sh +++ b/nixos/modules/tasks/tty-backgrounds-combine.sh @@ -3,7 +3,7 @@ source $stdenv/setup ttys=($ttys) themes=($themes) -ensureDir $out +mkdir -p $out defaultName=$(cd $default && ls | grep -v default) echo $defaultName diff --git a/nixos/modules/testing/test-instrumentation.nix b/nixos/modules/testing/test-instrumentation.nix index 9100a433cd63..54a376c9560e 100644 --- a/nixos/modules/testing/test-instrumentation.nix +++ b/nixos/modules/testing/test-instrumentation.nix @@ -66,13 +66,22 @@ let kernel = config.boot.kernelPackages.kernel; in # Panic if an error occurs in stage 1 (rather than waiting for # user intervention). boot.kernelParams = - [ "console=tty1" "console=ttyS0" "panic=1" "boot.panic_on_fail" ]; + [ "console=ttyS0" "panic=1" "boot.panic_on_fail" ]; # `xwininfo' is used by the test driver to query open windows. environment.systemPackages = [ pkgs.xorg.xwininfo ]; # Log everything to the serial console. - services.journald.console = "/dev/console"; + services.journald.extraConfig = + '' + ForwardToConsole=yes + MaxLevelConsole=debug + ''; + + # Don't clobber the console with duplicate systemd messages. + systemd.extraConfig = "ShowStatus=no"; + + boot.consoleLogLevel = 7; # Prevent tests from accessing the Internet. networking.defaultGateway = mkOverride 150 ""; @@ -88,6 +97,9 @@ let kernel = config.boot.kernelPackages.kernel; in networking.usePredictableInterfaceNames = false; + # Make it easy to log in as root when running the test interactively. + security.initialRootPassword = mkDefault ""; + }; } diff --git a/nixos/modules/virtualisation/amazon-image.nix b/nixos/modules/virtualisation/amazon-image.nix index 7d6109f212ac..e129e496fe36 100644 --- a/nixos/modules/virtualisation/amazon-image.nix +++ b/nixos/modules/virtualisation/amazon-image.nix @@ -172,7 +172,7 @@ in boot.initrd.extraUtilsCommands = '' # We need swapon in the initrd. - cp ${pkgs.utillinux}/sbin/swapon $out/bin + cp --remove-destination ${pkgs.utillinux}/sbin/swapon $out/bin ''; # Don't put old configurations in the GRUB menu. The user has no diff --git a/nixos/modules/virtualisation/container-config.nix b/nixos/modules/virtualisation/container-config.nix index b81f97f2b4ec..84e3aa283520 100644 --- a/nixos/modules/virtualisation/container-config.nix +++ b/nixos/modules/virtualisation/container-config.nix @@ -89,6 +89,8 @@ with lib; restartIfChanged = false; }; + systemd.services.systemd-remount-fs.enable = false; + }; } diff --git a/nixos/modules/virtualisation/containers.nix b/nixos/modules/virtualisation/containers.nix index d0d04d9a1e5d..292b96e6eb24 100644 --- a/nixos/modules/virtualisation/containers.nix +++ b/nixos/modules/virtualisation/containers.nix @@ -32,7 +32,10 @@ let fi fi - exec "$1" + # 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" ''; system = config.nixpkgs.system; @@ -168,17 +171,18 @@ in preStart = '' - mkdir -p -m 0755 $root/var/lib + # Clean up existing machined registration and interfaces. + machinectl terminate "$INSTANCE" 2> /dev/null || true - # Create a named pipe to get a signal when the container - # has finished booting. - rm -f $root/var/lib/startup-done - mkfifo -m 0600 $root/var/lib/startup-done + if [ "$PRIVATE_NETWORK" = 1 ]; then + ip link del dev "ve-$INSTANCE" 2> /dev/null || true + fi ''; script = '' mkdir -p -m 0755 "$root/etc" "$root/var/lib" + mkdir -p -m 0700 "$root/var/lib/private" if ! [ -e "$root/etc/os-release" ]; then touch "$root/etc/os-release" fi @@ -187,6 +191,8 @@ in "/nix/var/nix/profiles/per-container/$INSTANCE" \ "/nix/var/nix/gcroots/per-container/$INSTANCE" + cp -f /etc/resolv.conf "$root/etc/resolv.conf" + if [ "$PRIVATE_NETWORK" = 1 ]; then extraFlags+=" --network-veth" fi @@ -203,12 +209,16 @@ in fi ''} + # 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 \ --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" \ @@ -220,12 +230,6 @@ in postStart = '' - # This blocks until the container-startup-done service - # writes something to this pipe. FIXME: it also hangs - # until the start timeout expires if systemd-nspawn exits. - read x < $root/var/lib/startup-done - rm -f $root/var/lib/startup-done - if [ "$PRIVATE_NETWORK" = 1 ]; then ifaceHost=ve-$INSTANCE ip link set dev $ifaceHost up @@ -240,23 +244,42 @@ in preStop = '' - machinectl poweroff "$INSTANCE" + machinectl poweroff "$INSTANCE" || true ''; restartIfChanged = false; #reloadIfChanged = true; # FIXME - serviceConfig.ExecReload = pkgs.writeScript "reload-container" - '' - #! ${pkgs.stdenv.shell} -e - SYSTEM_PATH=/nix/var/nix/profiles/system - echo $SYSTEM_PATH/bin/switch-to-configuration test | \ - ${pkgs.socat}/bin/socat unix:$root/var/lib/run-command.socket - - ''; + serviceConfig = { + ExecReload = pkgs.writeScript "reload-container" + '' + #! ${pkgs.stdenv.shell} -e + SYSTEM_PATH=/nix/var/nix/profiles/system + echo $SYSTEM_PATH/bin/switch-to-configuration test | \ + ${pkgs.socat}/bin/socat unix:$root/var/lib/run-command.socket - + ''; + + SyslogIdentifier = "container %i"; + + EnvironmentFile = "-/etc/containers/%i.conf"; + + Type = "notify"; + + NotifyAccess = "all"; - serviceConfig.SyslogIdentifier = "container %i"; + # Note that on reboot, systemd-nspawn returns 10, so this + # unit will be restarted. On poweroff, it returns 0, so the + # unit won't be restarted. + Restart = "on-failure"; - serviceConfig.EnvironmentFile = "-/etc/containers/%i.conf"; + # Hack: we don't want to kill systemd-nspawn, since we call + # "machinectl poweroff" in preStop to shut down the + # container cleanly. But systemd requires sending a signal + # (at least if we want remaining processes to be killed + # after the timeout). So send an ignored signal. + KillMode = "mixed"; + KillSignal = "WINCH"; + }; }; # Generate a configuration file in /etc/containers for each @@ -290,5 +313,30 @@ in environment.systemPackages = [ nixos-container ]; + # Start containers at boot time. + systemd.services.all-containers = + { description = "All Containers"; + + wantedBy = [ "multi-user.target" ]; + + unitConfig.ConditionDirectoryNotEmpty = "/etc/containers"; + + serviceConfig.Type = "oneshot"; + + script = + '' + res=0 + shopt -s nullglob + for i in /etc/containers/*.conf; do + AUTO_START= + source "$i" + if [ "$AUTO_START" = 1 ]; then + systemctl start "container@$(basename "$i" .conf).service" || res=1 + fi + done + exit $res + ''; # */ + }; + }; } diff --git a/nixos/modules/virtualisation/docker.nix b/nixos/modules/virtualisation/docker.nix new file mode 100644 index 000000000000..a0aa61353269 --- /dev/null +++ b/nixos/modules/virtualisation/docker.nix @@ -0,0 +1,109 @@ +# Systemd services for docker. + +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.virtualisation.docker; + +in + +{ + ###### interface + + options.virtualisation.docker = { + enable = + mkOption { + type = types.bool; + default = false; + description = + '' + This option enables docker, a daemon that manages + linux containers. Users in the "docker" group can interact with + the daemon (e.g. to start or stop containers) using the + <command>docker</command> command line tool. + ''; + }; + socketActivation = + mkOption { + type = types.bool; + default = false; + description = + '' + This option enables docker with socket activation. I.e. docker will + start when first called by client. + + Note: This is false by default because systemd lower than 214 that + nixos uses so far, doesn't support SocketGroup option, so socket + created by docker has root group now. This will likely be changed + in future. So set this option explicitly to false if you wish. + ''; + }; + extraOptions = + mkOption { + type = types.str; + default = ""; + description = + '' + The extra command-line options to pass to + <command>docker</command> daemon. + ''; + }; + + + }; + + ###### implementation + + config = mkIf cfg.enable (mkMerge [ + { environment.systemPackages = [ pkgs.docker ]; + } + (mkIf cfg.socketActivation { + + systemd.services.docker = { + description = "Docker Application Container Engine"; + after = [ "network.target" "docker.socket" ]; + requires = [ "docker.socket" ]; + serviceConfig = { + ExecStart = "${pkgs.docker}/bin/docker --daemon=true --host=fd:// --group=docker ${cfg.extraOptions}"; + # I'm not sure if that limits aren't too high, but it's what + # goes in config bundled with docker itself + LimitNOFILE = 1048576; + LimitNPROC = 1048576; + }; + }; + + systemd.sockets.docker = { + description = "Docker Socket for the API"; + wantedBy = [ "sockets.target" ]; + socketConfig = { + ListenStream = "/var/run/docker.sock"; + SocketMode = "0660"; + SocketUser = "root"; + SocketGroup = "docker"; + }; + }; + }) + (mkIf (!cfg.socketActivation) { + + systemd.services.docker = { + description = "Docker Application Container Engine"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + serviceConfig = { + ExecStart = "${pkgs.docker}/bin/docker --daemon=true --group=docker ${cfg.extraOptions}"; + # I'm not sure if that limits aren't too high, but it's what + # goes in config bundled with docker itself + LimitNOFILE = 1048576; + LimitNPROC = 1048576; + }; + + # Presumably some containers are running we don't want to interrupt + restartIfChanged = false; + }; + }) + ]); + +} diff --git a/nixos/modules/virtualisation/ec2-data.nix b/nixos/modules/virtualisation/ec2-data.nix index 246d35065317..93a83a3e42af 100644 --- a/nixos/modules/virtualisation/ec2-data.nix +++ b/nixos/modules/virtualisation/ec2-data.nix @@ -22,21 +22,22 @@ with lib; systemd.services."fetch-ec2-data" = { description = "Fetch EC2 Data"; - wantedBy = [ "multi-user.target" ]; + wantedBy = [ "multi-user.target" "sshd.service" ]; before = [ "sshd.service" ]; - after = [ "network.target" ]; + wants = [ "ip-up.target" ]; + after = [ "ip-up.target" ]; - path = [ pkgs.curl pkgs.iproute ]; + path = [ pkgs.wget pkgs.iproute ]; script = '' ip route del blackhole 169.254.169.254/32 || true - curl="curl --retry 3 --retry-delay 0 --fail" + wget="wget -q --retry-connrefused -O -" echo "setting host name..." ${optionalString (config.networking.hostName == "") '' - ${pkgs.nettools}/bin/hostname $($curl http://169.254.169.254/1.0/meta-data/hostname) + ${pkgs.nettools}/bin/hostname $($wget http://169.254.169.254/1.0/meta-data/hostname) ''} # Don't download the SSH key if it has already been injected @@ -44,7 +45,7 @@ with lib; if ! [ -e /root/.ssh/authorized_keys ]; then echo "obtaining SSH key..." mkdir -p /root/.ssh - $curl -o /root/key.pub http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key + $wget http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key > /root/key.pub if [ $? -eq 0 -a -e /root/key.pub ]; then if ! grep -q -f /root/key.pub /root/.ssh/authorized_keys; then cat /root/key.pub >> /root/.ssh/authorized_keys @@ -58,7 +59,7 @@ with lib; # Extract the intended SSH host key for this machine from # the supplied user data, if available. Otherwise sshd will # generate one normally. - $curl http://169.254.169.254/2011-01-01/user-data > /root/user-data || true + $wget http://169.254.169.254/2011-01-01/user-data > /root/user-data || true key="$(sed 's/|/\n/g; s/SSH_HOST_DSA_KEY://; t; d' /root/user-data)" key_pub="$(sed 's/SSH_HOST_DSA_KEY_PUB://; t; d' /root/user-data)" if [ -n "$key" -a -n "$key_pub" -a ! -e /etc/ssh/ssh_host_dsa_key ]; then diff --git a/nixos/modules/virtualisation/google-compute-image.nix b/nixos/modules/virtualisation/google-compute-image.nix index d55b74202436..697423ac60be 100644 --- a/nixos/modules/virtualisation/google-compute-image.nix +++ b/nixos/modules/virtualisation/google-compute-image.nix @@ -119,21 +119,25 @@ in 169.254.169.254 metadata.google.internal metadata ''; - systemd.services.fetch-root-authorized-keys = - { description = "Fetch authorized_keys for root user"; + networking.usePredictableInterfaceNames = false; - wantedBy = [ "multi-user.target" ]; + systemd.services.fetch-ssh-keys = + { description = "Fetch host keys and authorized_keys for root user"; + + wantedBy = [ "sshd.service" ]; before = [ "sshd.service" ]; - after = [ "network.target" ]; + after = [ "network-online.target" ]; + wants = [ "network-online.target" ]; - path = [ pkgs.curl ]; + path = [ pkgs.wget ]; script = '' + wget="wget --retry-connrefused -t 6 --waitretry=10" # Don't download the SSH key if it has already been downloaded if ! [ -e /root/.ssh/authorized_keys ]; then echo "obtaining SSH key..." mkdir -p /root/.ssh - curl -o /root/authorized-keys-metadata http://metadata/0.1/meta-data/authorized-keys + $wget -O /root/authorized-keys-metadata http://metadata/0.1/meta-data/authorized-keys if [ $? -eq 0 -a -e /root/authorized-keys-metadata ]; then cat /root/authorized-keys-metadata | cut -d: -f2- > /root/key.pub if ! grep -q -f /root/key.pub /root/.ssh/authorized_keys; then @@ -144,10 +148,26 @@ in rm -f /root/key.pub /root/authorized-keys-metadata fi fi + + echo "obtaining SSH private host key..." + $wget -O /root/ssh_host_ecdsa_key http://metadata/0.1/meta-data/attributes/ssh_host_ecdsa_key + if [ $? -eq 0 -a -e /root/ssh_host_ecdsa_key ]; then + mv -f /root/ssh_host_ecdsa_key /etc/ssh/ssh_host_ecdsa_key + echo "downloaded ssh_host_ecdsa_key" + chmod 600 /etc/ssh/ssh_host_ecdsa_key + fi + + echo "obtaining SSH public host key..." + $wget -O /root/ssh_host_ecdsa_key.pub http://metadata/0.1/meta-data/attributes/ssh_host_ecdsa_key_pub + if [ $? -eq 0 -a -e /root/ssh_host_ecdsa_key.pub ]; then + mv -f /root/ssh_host_ecdsa_key.pub /etc/ssh/ssh_host_ecdsa_key.pub + echo "downloaded ssh_host_ecdsa_key.pub" + chmod 644 /etc/ssh/ssh_host_ecdsa_key.pub + fi ''; serviceConfig.Type = "oneshot"; serviceConfig.RemainAfterExit = true; + serviceConfig.StandardError = "journal+console"; + serviceConfig.StandardOutput = "journal+console"; }; - - } diff --git a/nixos/modules/virtualisation/nixos-container.pl b/nixos/modules/virtualisation/nixos-container.pl index 5083abd84489..bf6f16fc6c77 100644 --- a/nixos/modules/virtualisation/nixos-container.pl +++ b/nixos/modules/virtualisation/nixos-container.pl @@ -17,25 +17,31 @@ umask 0022; sub showHelp { print <<EOF; Usage: nixos-container list - nixos-container create <container-name> [--config <string>] [--ensure-unique-name] + nixos-container create <container-name> [--system-path <path>] [--config <string>] [--ensure-unique-name] [--auto-start] nixos-container destroy <container-name> nixos-container start <container-name> nixos-container stop <container-name> + nixos-container status <container-name> nixos-container login <container-name> nixos-container root-login <container-name> nixos-container run <container-name> -- args... nixos-container set-root-password <container-name> <password> nixos-container show-ip <container-name> + nixos-container show-host-key <container-name> EOF exit 0; } +my $systemPath; my $ensureUniqueName = 0; +my $autoStart = 0; my $extraConfig; GetOptions( "help" => sub { showHelp() }, "ensure-unique-name" => \$ensureUniqueName, + "auto-start" => \$autoStart, + "system-path=s" => \$systemPath, "config=s" => \$extraConfig ) or exit 1; @@ -122,17 +128,13 @@ if ($action eq "create") { push @conf, "PRIVATE_NETWORK=1\n"; push @conf, "HOST_ADDRESS=$hostAddress\n"; push @conf, "LOCAL_ADDRESS=$localAddress\n"; + push @conf, "AUTO_START=$autoStart\n"; write_file($confFile, \@conf); close($lock); print STDERR "host IP is $hostAddress, container IP is $localAddress\n"; - mkpath("$root/etc/nixos", 0, 0755); - - my $nixosConfigFile = "$root/etc/nixos/configuration.nix"; - writeNixOSConfig $nixosConfigFile; - # The per-container directory is restricted to prevent users on # the host from messing with guest users who happen to have the # same uid. @@ -141,10 +143,21 @@ if ($action eq "create") { $profileDir = "$profileDir/$containerName"; mkpath($profileDir, 0, 0755); - system("nix-env", "-p", "$profileDir/system", - "-I", "nixos-config=$nixosConfigFile", "-f", "<nixpkgs/nixos>", - "--set", "-A", "system") == 0 - or die "$0: failed to build initial container configuration\n"; + # Build/set the initial configuration. + if (defined $systemPath) { + system("nix-env", "-p", "$profileDir/system", "--set", $systemPath) == 0 + or die "$0: failed to set initial container configuration\n"; + } else { + mkpath("$root/etc/nixos", 0, 0755); + + my $nixosConfigFile = "$root/etc/nixos/configuration.nix"; + writeNixOSConfig $nixosConfigFile; + + system("nix-env", "-p", "$profileDir/system", + "-I", "nixos-config=$nixosConfigFile", "-f", "<nixpkgs/nixos>", + "--set", "-A", "system") == 0 + or die "$0: failed to build initial container configuration\n"; + } print "$containerName\n" if $ensureUniqueName; exit 0; @@ -152,8 +165,16 @@ if ($action eq "create") { my $root = "/var/lib/containers/$containerName"; my $profileDir = "/nix/var/nix/profiles/per-container/$containerName"; +my $gcRootsDir = "/nix/var/nix/gcroots/per-container/$containerName"; my $confFile = "/etc/containers/$containerName.conf"; -die "$0: container ‘$containerName’ does not exist\n" if !-e $confFile; +if (!-e $confFile) { + if ($action eq "destroy") { + exit 0; + } elsif ($action eq "status") { + print "gone\n"; + } + die "$0: container ‘$containerName’ does not exist\n" ; +} sub isContainerRunning { my $status = `systemctl show 'container\@$containerName'`; @@ -172,6 +193,7 @@ if ($action eq "destroy") { stopContainer if isContainerRunning; rmtree($profileDir) if -e $profileDir; + rmtree($gcRootsDir) if -e $gcRootsDir; rmtree($root) if -e $root; unlink($confFile) or die; } @@ -185,6 +207,10 @@ elsif ($action eq "stop") { stopContainer; } +elsif ($action eq "status") { + print isContainerRunning() ? "up" : "down", "\n"; +} + elsif ($action eq "update") { my $nixosConfigFile = "$root/etc/nixos/configuration.nix"; @@ -239,6 +265,12 @@ elsif ($action eq "show-ip") { print "$1\n"; } +elsif ($action eq "show-host-key") { + my $fn = "$root/etc/ssh/ssh_host_ecdsa_key.pub"; + exit 1 if ! -f $fn; + print read_file($fn); +} + else { die "$0: unknown action ‘$action’\n"; } diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix index bccf6583e47d..58386ce5cf56 100644 --- a/nixos/modules/virtualisation/qemu-vm.nix +++ b/nixos/modules/virtualisation/qemu-vm.nix @@ -275,12 +275,10 @@ in boot.loader.grub.device = mkVMOverride "/dev/vda"; - boot.initrd.supportedFilesystems = optional cfg.writableStore "unionfs-fuse"; - boot.initrd.extraUtilsCommands = '' # We need mke2fs in the initrd. - cp ${pkgs.e2fsprogs}/sbin/mke2fs $out/bin + cp -f ${pkgs.e2fsprogs}/sbin/mke2fs $out/bin ''; boot.initrd.postDeviceCommands = @@ -303,20 +301,6 @@ in chmod 1777 $targetRoot/tmp mkdir -p $targetRoot/boot - ${optionalString cfg.writableStore '' - mkdir -p /unionfs-chroot/ro-store - mount --rbind $targetRoot/nix/store /unionfs-chroot/ro-store - - mkdir /unionfs-chroot/rw-store - ${if cfg.writableStoreUseTmpfs then '' - mount -t tmpfs -o "mode=755" none /unionfs-chroot/rw-store - '' else '' - mkdir $targetRoot/.nix-rw-store - mount --bind $targetRoot/.nix-rw-store /unionfs-chroot/rw-store - ''} - - unionfs -o allow_other,cow,nonempty,chroot=/unionfs-chroot,max_files=32768,hide_meta_files /rw-store=RW:/ro-store=RO $targetRoot/nix/store - ''} ''; # After booting, register the closure of the paths in @@ -343,12 +327,13 @@ in # configuration, where the regular value for the `fileSystems' # attribute should be disregarded for the purpose of building a VM # test image (since those filesystems don't exist in the VM). - fileSystems = mkVMOverride + fileSystems = mkVMOverride ( { "/".device = "/dev/vda"; - "/nix/store" = + ${if cfg.writableStore then "/nix/.ro-store" else "/nix/store"} = { device = "store"; fsType = "9p"; options = "trans=virtio,version=9p2000.L,msize=1048576,cache=loose"; + neededForBoot = true; }; "/tmp/xchg" = { device = "xchg"; @@ -362,6 +347,18 @@ in options = "trans=virtio,version=9p2000.L,msize=1048576"; neededForBoot = true; }; + } // optionalAttrs cfg.writableStore + { "/nix/store" = + { fsType = "unionfs-fuse"; + device = "unionfs"; + options = "allow_other,cow,nonempty,chroot=/mnt-root,max_files=32768,hide_meta_files,dirs=/nix/.rw-store=rw:/nix/.ro-store=ro"; + }; + } // optionalAttrs (cfg.writableStore && cfg.writableStoreUseTmpfs) + { "/nix/.rw-store" = + { fsType = "tmpfs"; + options = "mode=0755"; + neededForBoot = true; + }; } // optionalAttrs cfg.useBootLoader { "/boot" = { device = "/dev/disk/by-label/boot"; @@ -369,7 +366,7 @@ in options = "ro"; noCheck = true; # fsck fails on a r/o filesystem }; - }; + }); swapDevices = mkVMOverride [ ]; boot.initrd.luks.devices = mkVMOverride []; @@ -379,7 +376,7 @@ in system.build.vm = pkgs.runCommand "nixos-vm" { preferLocalBuild = true; } '' - ensureDir $out/bin + mkdir -p $out/bin ln -s ${config.system.build.toplevel} $out/system ln -s ${pkgs.writeScript "run-nixos-vm" startVM} $out/bin/run-${vmName}-vm ''; diff --git a/nixos/modules/virtualisation/virtualbox-image.nix b/nixos/modules/virtualisation/virtualbox-image.nix index 594b3e93ffeb..106b269d9e1f 100644 --- a/nixos/modules/virtualisation/virtualbox-image.nix +++ b/nixos/modules/virtualisation/virtualbox-image.nix @@ -2,109 +2,132 @@ with lib; -{ - system.build.virtualBoxImage = - pkgs.vmTools.runInLinuxVM ( - pkgs.runCommand "virtualbox-image" - { memSize = 768; - preVM = - '' - mkdir $out - diskImage=$out/image - ${pkgs.vmTools.qemu}/bin/qemu-img create -f raw $diskImage "10G" - mv closure xchg/ - ''; - postVM = - '' - echo "creating VirtualBox disk image..." - ${pkgs.vmTools.qemu}/bin/qemu-img convert -f raw -O vdi $diskImage $out/disk.vdi - rm $diskImage - ''; - buildInputs = [ pkgs.utillinux pkgs.perl ]; - exportReferencesGraph = - [ "closure" config.system.build.toplevel ]; - } - '' - # Create a single / partition. - ${pkgs.parted}/sbin/parted /dev/vda mklabel msdos - ${pkgs.parted}/sbin/parted /dev/vda -- mkpart primary ext2 1M -1s - . /sys/class/block/vda1/uevent - mknod /dev/vda1 b $MAJOR $MINOR - - # Create an empty filesystem and mount it. - ${pkgs.e2fsprogs}/sbin/mkfs.ext4 -L nixos /dev/vda1 - ${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda1 - mkdir /mnt - mount /dev/vda1 /mnt - - # The initrd expects these directories to exist. - mkdir /mnt/dev /mnt/proc /mnt/sys - mount --bind /proc /mnt/proc - mount --bind /dev /mnt/dev - mount --bind /sys /mnt/sys - - # Copy all paths in the closure to the filesystem. - storePaths=$(perl ${pkgs.pathsFromGraph} /tmp/xchg/closure) - - echo "filling Nix store..." - mkdir -p /mnt/nix/store - set -f - cp -prd $storePaths /mnt/nix/store/ - - # Register the paths in the Nix database. - printRegistration=1 perl ${pkgs.pathsFromGraph} /tmp/xchg/closure | \ - chroot /mnt ${config.nix.package}/bin/nix-store --load-db - - # Create the system profile to allow nixos-rebuild to work. - chroot /mnt ${config.nix.package}/bin/nix-env \ - -p /nix/var/nix/profiles/system --set ${config.system.build.toplevel} - - # `nixos-rebuild' requires an /etc/NIXOS. - mkdir -p /mnt/etc/nixos - touch /mnt/etc/NIXOS - - # `switch-to-configuration' requires a /bin/sh - mkdir -p /mnt/bin - ln -s ${config.system.build.binsh}/bin/sh /mnt/bin/sh - - # Generate the GRUB menu. - ln -s vda /dev/sda - chroot /mnt ${config.system.build.toplevel}/bin/switch-to-configuration boot - - umount /mnt/proc /mnt/dev /mnt/sys - umount /mnt - '' - ); - - system.build.virtualBoxOVA = pkgs.runCommand "virtualbox-ova" - { buildInputs = [ pkgs.linuxPackages.virtualbox ]; - vmName = "NixOS ${config.system.nixosVersion} (${pkgs.stdenv.system})"; - fileName = "nixos-${config.system.nixosVersion}-${pkgs.stdenv.system}.ova"; - } - '' - echo "creating VirtualBox VM..." - export HOME=$PWD - VBoxManage createvm --name "$vmName" --register \ - --ostype ${if pkgs.stdenv.system == "x86_64-linux" then "Linux26_64" else "Linux26"} - VBoxManage modifyvm "$vmName" \ - --memory 1536 --acpi on --vram 10 \ - --nictype1 virtio --nic1 nat \ - --audiocontroller ac97 --audio alsa \ - --rtcuseutc on \ - --usb on --mouse usbtablet - VBoxManage storagectl "$vmName" --name SATA --add sata --portcount 4 --bootable on --hostiocache on - VBoxManage storageattach "$vmName" --storagectl SATA --port 0 --device 0 --type hdd \ - --medium ${config.system.build.virtualBoxImage}/disk.vdi - - echo "exporting VirtualBox VM..." - mkdir -p $out - VBoxManage export "$vmName" --output "$out/$fileName" - ''; - - fileSystems."/".device = "/dev/disk/by-label/nixos"; - - boot.loader.grub.version = 2; - boot.loader.grub.device = "/dev/sda"; - - services.virtualbox.enable = true; +let + + cfg = config.virtualbox; + +in { + + options = { + virtualbox = { + baseImageSize = mkOption { + type = types.str; + default = "10G"; + description = '' + The size of the VirtualBox base image. The size string should be on + a format the qemu-img command accepts. + ''; + }; + }; + }; + + config = { + system.build.virtualBoxImage = + pkgs.vmTools.runInLinuxVM ( + pkgs.runCommand "virtualbox-image" + { memSize = 768; + preVM = + '' + mkdir $out + diskImage=$out/image + ${pkgs.vmTools.qemu}/bin/qemu-img create -f raw $diskImage "${cfg.baseImageSize}" + mv closure xchg/ + ''; + postVM = + '' + echo "creating VirtualBox disk image..." + ${pkgs.vmTools.qemu}/bin/qemu-img convert -f raw -O vdi $diskImage $out/disk.vdi + rm $diskImage + ''; + buildInputs = [ pkgs.utillinux pkgs.perl ]; + exportReferencesGraph = + [ "closure" config.system.build.toplevel ]; + } + '' + # Create a single / partition. + ${pkgs.parted}/sbin/parted /dev/vda mklabel msdos + ${pkgs.parted}/sbin/parted /dev/vda -- mkpart primary ext2 1M -1s + . /sys/class/block/vda1/uevent + mknod /dev/vda1 b $MAJOR $MINOR + + # Create an empty filesystem and mount it. + ${pkgs.e2fsprogs}/sbin/mkfs.ext4 -L nixos /dev/vda1 + ${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda1 + mkdir /mnt + mount /dev/vda1 /mnt + + # The initrd expects these directories to exist. + mkdir /mnt/dev /mnt/proc /mnt/sys + mount --bind /proc /mnt/proc + mount --bind /dev /mnt/dev + mount --bind /sys /mnt/sys + + # Copy all paths in the closure to the filesystem. + storePaths=$(perl ${pkgs.pathsFromGraph} /tmp/xchg/closure) + + echo "filling Nix store..." + mkdir -p /mnt/nix/store + set -f + cp -prd $storePaths /mnt/nix/store/ + + mkdir -p /mnt/etc/nix + echo 'build-users-group = ' > /mnt/etc/nix/nix.conf + + # Register the paths in the Nix database. + printRegistration=1 perl ${pkgs.pathsFromGraph} /tmp/xchg/closure | \ + chroot /mnt ${config.nix.package}/bin/nix-store --load-db + + # Create the system profile to allow nixos-rebuild to work. + chroot /mnt ${config.nix.package}/bin/nix-env \ + -p /nix/var/nix/profiles/system --set ${config.system.build.toplevel} + + # `nixos-rebuild' requires an /etc/NIXOS. + mkdir -p /mnt/etc/nixos + touch /mnt/etc/NIXOS + + # `switch-to-configuration' requires a /bin/sh + mkdir -p /mnt/bin + ln -s ${config.system.build.binsh}/bin/sh /mnt/bin/sh + + # Generate the GRUB menu. + ln -s vda /dev/sda + chroot /mnt ${config.system.build.toplevel}/bin/switch-to-configuration boot + + umount /mnt/proc /mnt/dev /mnt/sys + umount /mnt + '' + ); + + system.build.virtualBoxOVA = pkgs.runCommand "virtualbox-ova" + { buildInputs = [ pkgs.linuxPackages.virtualbox ]; + vmName = "NixOS ${config.system.nixosVersion} (${pkgs.stdenv.system})"; + fileName = "nixos-${config.system.nixosVersion}-${pkgs.stdenv.system}.ova"; + } + '' + echo "creating VirtualBox VM..." + export HOME=$PWD + VBoxManage createvm --name "$vmName" --register \ + --ostype ${if pkgs.stdenv.system == "x86_64-linux" then "Linux26_64" else "Linux26"} + VBoxManage modifyvm "$vmName" \ + --memory 1536 --acpi on --vram 10 \ + --nictype1 virtio --nic1 nat \ + --audiocontroller ac97 --audio alsa \ + --rtcuseutc on \ + --usb on --mouse usbtablet + VBoxManage storagectl "$vmName" --name SATA --add sata --portcount 4 --bootable on --hostiocache on + VBoxManage storageattach "$vmName" --storagectl SATA --port 0 --device 0 --type hdd \ + --medium ${config.system.build.virtualBoxImage}/disk.vdi + + echo "exporting VirtualBox VM..." + mkdir -p $out + VBoxManage export "$vmName" --output "$out/$fileName" + ''; + + fileSystems."/".device = "/dev/disk/by-label/nixos"; + + boot.loader.grub.version = 2; + boot.loader.grub.device = "/dev/sda"; + + services.virtualbox.enable = true; + }; } |