diff --git a/default.nix b/default.nix index e63a76cd03f3..6b929537ee42 100644 --- a/default.nix +++ b/default.nix @@ -11,11 +11,22 @@ let inherit (eval) config pkgs; + # This is for `nixos-rebuild build-vm'. vmConfig = (import ./lib/eval-config.nix { inherit system; modules = [ configuration ./modules/virtualisation/qemu-vm.nix ]; }).config; - + + # This is for `nixos-rebuild build-vm-with-bootloader'. + vmWithBootLoaderConfig = (import ./lib/eval-config.nix { + inherit system; + modules = + [ configuration + ./modules/virtualisation/qemu-vm.nix + { virtualisation.useBootLoader = true; } + ]; + }).config; + in { @@ -25,6 +36,8 @@ in vm = vmConfig.system.build.vm; + vmWithBootLoader = vmWithBootLoaderConfig.system.build.vm; + # The following are used by nixos-rebuild. nixFallback = pkgs.nixUnstable; manifests = config.installer.manifests; diff --git a/doc/manual/installation.xml b/doc/manual/installation.xml index b2efbf2d5d5c..330ef14e0fd1 100644 --- a/doc/manual/installation.xml +++ b/doc/manual/installation.xml @@ -38,24 +38,14 @@ $ nix-channel --update xlink:href="https://svn.nixos.org/repos/nix/nixos/trunk"/> as nixos. - If you don’t already have Nixpkgs checkout, Check - out Nixpkgs from as + Check out Nixpkgs from + as nixpkgs. - In the directory nixos, make a - symbolic link pkgs to the pkgs - directory of the Nixpkgs tree, e.g., - - -$ ln -s nixpkgs/pkgs nixos/ - - - Build the ISO image: -$ nix-build configuration/rescue-cd.nix -A rescueCD +$ nix-build ./nixos/release.nix -A iso_minimal.iso If everything goes well, you’ll end up with an ISO image in ./result/iso/nixos-version-platform.iso @@ -63,7 +53,7 @@ $ nix-build configuration/rescue-cd.nix -A rescueCD your favourite virtual machine software. - + @@ -89,8 +79,8 @@ $ nix-build configuration/rescue-cd.nix -A rescueCD server on your network. Otherwise configure manually. - The NixOS manual is available on virtual console 7 - (press Alt+F7 to access). + The NixOS manual is available on virtual console 8 + (press Alt+F8 to access). Login as root, empty password. @@ -138,43 +128,37 @@ $ lvcreate --size 1G --name smalldisk MyVolGroup Mount the target file system on - /mnt. + /mnt on which NixOS would be installed. + - The installation is declarative; you need to write a - description of the configuration that you want to be built and - activated. The configuration is specified in a Nix expression and - must be stored on the target file system in - /mnt/etc/nixos/configuration.nix. See - /etc/nixos/nixos/doc/config-examples for - example machine configurations. You can copy and edit one of - those (e.g., copy - /etc/nixos/nixos/doc/config-examples/basic.nix - to /mnt/etc/nixos/configuration.nix). See - for a list of the available - configuration options. The text editors nano - and vim are available. + Generate a template configuration for the target system: - In particular you need to specify a root file system in - and the target device for the Grub - boot loader in . - - The command nixos-hardware-scan can + The command nixos-option can generate an initial configuration file for you, i.e., -$ mkdir -p /mnt/etc/nixos -$ nixos-hardware-scan > /mnt/etc/nixos/configuration.nix +$ nixos-option --install It tries to figure out the modules necessary for mounting the root device, as well as various other hardware characteristics. - However, it doesn’t try to figure out the + However, it doesn’t try to figure out the option yet. - More examples of NixOS configurations for some actual - machines can be found at . + Edit /mnt/etc/nixos/configuration.nix to + configure your system. The installation is declarative; you need to + write a description of the configuration that you want to be built and + activated. The configuration is specified in a Nix expression and must + be stored on the target file system. The text + editors nano and vim are + available. + + You need to specify a root file system in + and the target device for the Grub boot + loader in . See + for a list of the available configuration + options. It is very important that you specify in the option all kernel modules that @@ -187,6 +171,11 @@ $ nixos-hardware-scan > /mnt/etc/nixos/configuration.nix nixos-hardware-scan should figure out the required modules in most cases. + Examples are available in + /etc/nixos/nixos/doc/config-examples and some + actual NixOS configuration can be found at . + If your machine has a limited amount of memory, you @@ -268,8 +257,7 @@ $ fdisk /dev/sda (or whatever device you want to install on)(idem) $ mkswap -L swap /dev/sda2 (idem) $ mount LABEL=nixos /mnt -$ mkdir -p /mnt/etc/nixos -$ nixos-hardware-scan > /mnt/etc/nixos/configuration.nix +$ nixos-option --install $ nano /mnt/etc/nixos/configuration.nix (in particular, set the fileSystems and swapDevices options) $ nixos-install @@ -280,7 +268,8 @@ $ reboot { boot.initrd.kernelModules = [ "ata_piix" ]; - boot.grubDevice = "/dev/sda"; + boot.loader.grub.enable = true; + boot.loader.grub.device = "/dev/sda"; fileSystems = [ { mountPoint = "/"; diff --git a/doc/manual/man-nixos-option.xml b/doc/manual/man-nixos-option.xml new file mode 100644 index 000000000000..b88daa51db63 --- /dev/null +++ b/doc/manual/man-nixos-option.xml @@ -0,0 +1,186 @@ + + + + nixos-option + 8 + NixOS + + + + + nixos-option + inspect a NixOS configuration + + + + + nixos-option + + + + + + + option.name + + + nixos-option + + + + + +Description + +This command evaluates the configuration specified in +/etc/nixos/configuration.nix and returns the properties +of the option name given as argument. By default, it returns the value of +the option. + +When the option name is not an option, the command prints the list of +attributes in contained in the attribute set. This could used to provide +completion in some editors. + +When the option (or ) is +used with no option name, this command generates a template configuration +with a scan of the target system. It produces a template configuration +in /etc/nixos/configuration.nix, and a scan of the +machine in /etc/nixos/hardware-configuration.nix. The +scan of the machine is produced +by nixos-hardware-scan. + + + +Options + +This command accepts the following options: + + + + + , + + Use the installation configuration instead of current system + configuration. Generate a template configuration if no option name is + specified. + + + + + , + + Returns the value of the option. This is the default operation + if no other options are defined. + + + + + , + + Return the default value, the example and the description of the + option when available. + + + + + , + + Return the locations where the option is declared and where it + is defined. This is extremely useful to find sources of errors in + your configuration. + + + + + + + + +Environment + + + + + mountPoint + + Location of the target file system. Defaults to + /mnt. This environment variable is only used in + combinaison with option. + + + + + NIXOS + + Path to the NixOS source tree. Defaults to + /etc/nixos/nixos. + + + + + NIXPKGS + + Path to the Nixpkgs source tree. Defaults to + /etc/nixos/nixpkgs. + + + + + NIXOS_CONFIG + + Path to the main NixOS configuration module. Defaults to + /etc/nixos/configuration.nix. + + + + + + + + +Examples + +Investigate option values: + +$ nixos-option boot.loader +This attribute set contains: +generationsDir +grub +initScript + +$ nixos-option boot.loader.grub.enable +true + +Prints option information: + +$ nixos-option -d networking.hostName +Default: "nixos" +Description: +The name of the machine. Leave it empty if you want to obtain +it from a DHCP server (if using DHCP). + +Find the locations which are declaring and defining an option: + +$ nixos-option -l hardware.firmware +Declared by: + /mnt/data/nix-sources/nixos/modules/services/hardware/udev.nix + +Defined by: + /etc/nixos/nixos/modules/system/boot/kernel.nix + /etc/nixos/nixos/modules/hardware/network/rt73.nix + /etc/nixos/nixos/modules/hardware/network/intel-3945abg.nix + /etc/nixos/nixos/modules/hardware/network/intel-2200bg.nix + + + +Bugs + +The author listed in the following section is wrong. If there is any + other bug, please report to Nicolas Pierron. + + + + + diff --git a/doc/manual/man-nixos-rebuild.xml b/doc/manual/man-nixos-rebuild.xml index 0bdc925efd9e..6f888172d48a 100644 --- a/doc/manual/man-nixos-rebuild.xml +++ b/doc/manual/man-nixos-rebuild.xml @@ -24,6 +24,8 @@ + + @@ -151,6 +153,35 @@ $ ./result/bin/run-*-vm + + + + Like , but boots using the + regular boot loader of your configuration (e.g., GRUB 1 or 2), + rather than booting directly into the kernel and initial ramdisk + of the system. This allows you to test whether the boot loader + works correctly. However, it does not guarantee that your NixOS + configuration will boot successfully on the host hardware (i.e., + after running nixos-rebuild switch), because + the hardware and boot loader configuration in the VM are + different. The boot loader is installed on an automatically + generated virtual disk containing a /boot + partition, which is mounted read-only in the VM. + + + + + + + This operation merely fetches the latest manifest in the + Nixpkgs channel to speed up subsequent + nix-env operations. This is useful if you + are not using nix-channel but still want to + use pre-built binary packages. It doesn’t reconfigure the + system at all. + + + diff --git a/doc/manual/man-pages.xml b/doc/manual/man-pages.xml index e706574d8895..e3b3a5bc2899 100644 --- a/doc/manual/man-pages.xml +++ b/doc/manual/man-pages.xml @@ -25,5 +25,6 @@ + diff --git a/modules/config/nsswitch-mdns.conf b/modules/config/nsswitch-mdns.conf index eefbd0c4203e..61dd436682d3 100644 --- a/modules/config/nsswitch-mdns.conf +++ b/modules/config/nsswitch-mdns.conf @@ -4,7 +4,7 @@ passwd: ldap files group: ldap files shadow: ldap files -hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4 +hosts: files mdns_minimal [NOTFOUND=return] dns mdns networks: files dns services: files diff --git a/modules/config/users-groups.nix b/modules/config/users-groups.nix index 447dc96f818f..6d57209a4ac8 100644 --- a/modules/config/users-groups.nix +++ b/modules/config/users-groups.nix @@ -156,7 +156,23 @@ in config = { - system.activationScripts.users = fullDepEntry + system.activationScripts.rootPasswd = stringAfter [ "etc" ] + '' + # If there is no password file yet, create a root account with an + # empty password. + if ! test -e /etc/passwd; then + rootHome=/root + touch /etc/passwd; chmod 0644 /etc/passwd + touch /etc/group; chmod 0644 /etc/group + touch /etc/shadow; chmod 0600 /etc/shadow + # Can't use useradd, since it complains that it doesn't know us + # (bootstrap problem!). + echo "root:x:0:0:System administrator:$rootHome:${config.users.defaultUserShell}" >> /etc/passwd + echo "root::::::::" >> /etc/shadow + fi + ''; + + system.activationScripts.users = stringAfter [ "groups" ] '' echo "updating users..." @@ -206,9 +222,9 @@ in fi done - '' [ "groups" ]; + ''; - system.activationScripts.groups = fullDepEntry + system.activationScripts.groups = stringAfter [ "rootPasswd" "binsh" "etc" "var" ] '' echo "updating groups..." @@ -231,7 +247,7 @@ in done <installation-cd-graphical.nix add - packages to this list. - ''; - - default = - [ 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 - pkgs.parted - pkgs.ddrescue - pkgs.ccrypt - pkgs.cryptsetup # needed for dm-crypt volumes - - # Some networking tools. - pkgs.sshfsFuse - pkgs.socat - pkgs.screen - - # Hardware-related tools. - pkgs.sdparm - pkgs.hdparm - pkgs.dmraid - - # Tools to create / manipulate filesystems. - pkgs.ntfsprogs # for resizing NTFS partitions - pkgs.btrfsProgs - pkgs.dosfstools - pkgs.xfsprogs - pkgs.jfsutils - pkgs.jfsrec - - # Some compression/archiver tools. - pkgs.unrar - pkgs.unzip - pkgs.zip - pkgs.xz - pkgs.dar # disk archiver - - # Some editors. - pkgs.nvi - pkgs.bvi # binary editor - pkgs.joe - ]; - }; - }; - - # We need a copy of the Nix expressions for Nixpkgs and NixOS on the # CD. We put them in a tarball because accessing that many small # files from a slow device like a CD-ROM takes too long. !!! Once @@ -95,37 +25,17 @@ let nixpkgsTarball = makeTarball "nixpkgs.tar.bz2" (cleanSource pkgs.path); includeSources = true; - - - # A dummy /etc/nixos/configuration.nix in the booted CD that - # rebuilds the CD's configuration (and allows the configuration to - # be modified, of course, providing a true live CD). Problem is - # that we don't really know how the CD was built - the Nix - # expression language doesn't allow us to query the expression being - # evaluated. So we'll just hope for the best. - dummyConfiguration = pkgs.writeText "configuration.nix" - '' - {config, pkgs, ...}: - - { - require = [${config.installer.configModule}]; - - # Add your own options below and run "nixos-rebuild switch". - # E.g., - # services.openssh.enable = true; - } - ''; - in { require = - [ options - ./memtest.nix + [ ./memtest.nix ./iso-image.nix - ../../hardware/network/intel-3945abg.nix - ../../hardware/network/rt73.nix + + # Profiles of this basic installation CD. + ../../profiles/base.nix + ../../profiles/installation-device.nix ]; # ISO naming. @@ -133,79 +43,10 @@ in isoImage.volumeID = "NIXOS_INSTALL_CD_${config.system.nixosVersion}"; - # Show the manual. - services.nixosManual.showManual = true; - - # Let the user play Rogue on TTY 8 during the installation. - services.rogue.enable = true; - - # Disable some other stuff we don't need. - security.sudo.enable = false; - - # Include only the en_US locale. This saves 75 MiB or so compared to - # the full glibcLocales package. - i18n.supportedLocales = ["en_US.UTF-8/UTF-8" "en_US/ISO-8859-1"]; - - # Include some utilities that are useful for installing or repairing - # the system. - environment.systemPackages = config.installer.basePackages; - - # The initrd has to contain any module that might be necessary for - # mounting the CD/DVD. - boot.initrd.availableKernelModules = - [ # SATA/PATA support. - "ahci" - - "ata_piix" - - "sata_inic162x" "sata_nv" "sata_promise" "sata_qstor" - "sata_sil" "sata_sil24" "sata_sis" "sata_svw" "sata_sx4" - "sata_uli" "sata_via" "sata_vsc" - - "pata_ali" "pata_amd" "pata_artop" "pata_atiixp" - "pata_cs5520" "pata_cs5530" "pata_cs5535" "pata_efar" - "pata_hpt366" "pata_hpt37x" "pata_hpt3x2n" "pata_hpt3x3" - "pata_it8213" "pata_it821x" "pata_jmicron" "pata_marvell" - "pata_mpiix" "pata_netcell" "pata_ns87410" "pata_oldpiix" - "pata_pcmcia" "pata_pdc2027x" "pata_qdi" "pata_rz1000" - "pata_sc1200" "pata_serverworks" "pata_sil680" "pata_sis" - "pata_sl82c105" "pata_triflex" "pata_via" - "pata_winbond" - - # SCSI support (incomplete). - "3w-9xxx" "3w-xxxx" "aic79xx" "aic7xxx" "arcmsr" - - # USB support, especially for booting from USB CD-ROM - # drives. - "usb_storage" - - # Firewire support. Not tested. - "ohci1394" "sbp2" - - # Virtio (QEMU, KVM etc.) support. - "virtio_net" "virtio_pci" "virtio_blk" "virtio_balloon" - - # Add vfat to enable people to copy the contents of the CD to a - # bootable USB stick. - "vfat" "nls_cp437" "nls_iso8859-1" - ]; - - boot.initrd.kernelModules = - [ # Wait for SCSI devices to appear. - "scsi_wait_scan" - ]; - - # nixos-install will do a pull from this channel to speed up the - # installation. - installer.nixpkgsURL = http://nixos.org/releases/nixpkgs/channels/nixpkgs-unstable; - boot.postBootCommands = '' export PATH=${pkgs.gnutar}/bin:${pkgs.bzip2}/bin:$PATH - # Provide a mount point for nixos-install. - mkdir -p /mnt - # Provide the NixOS/Nixpkgs sources in /etc/nixos. This is required # for nixos-install. ${optionalString includeSources '' @@ -216,40 +57,9 @@ in tar xjf ${nixpkgsTarball}/nixpkgs.tar.bz2 -C /etc/nixos/nixpkgs chown -R root.root /etc/nixos ''} - - # Provide a configuration for the CD/DVD itself, to allow users - # to run nixos-rebuild to change the configuration of the - # running system on the CD/DVD. - cp ${dummyConfiguration} /etc/nixos/configuration.nix ''; - # Some more help text. - services.mingetty.helpLine = - '' - - Log in as "root" with an empty password. ${ - if config.services.xserver.enable then - "Type `start xserver' to start\nthe graphical user interface." - else "" - } - ''; - - # Include the firmware for various wireless cards. - networking.enableRT73Firmware = true; - networking.enableIntel2200BGFirmware = true; - networking.enableIntel3945ABGFirmware = true; - # To speed up installation a little bit, include the complete stdenv # in the Nix store on the CD. isoImage.storeContents = [ pkgs.stdenv pkgs.klibc pkgs.klibcShrunk ]; - - # Allow sshd to be started manually through "start sshd". It should - # not be started by default on the installation CD because the - # default root password is empty. - services.openssh.enable = true; - jobs.sshd.startOn = pkgs.lib.mkOverrideTemplate 50 {} ""; - - # Enable wpa_supplicant, but don't start it by default. - networking.enableWLAN = true; - jobs.wpa_supplicant.startOn = pkgs.lib.mkOverrideTemplate 50 {} ""; } diff --git a/modules/installer/cd-dvd/installation-cd-graphical.nix b/modules/installer/cd-dvd/installation-cd-graphical.nix index 5f600022dce7..a3c533bb7150 100644 --- a/modules/installer/cd-dvd/installation-cd-graphical.nix +++ b/modules/installer/cd-dvd/installation-cd-graphical.nix @@ -4,15 +4,8 @@ {config, pkgs, ...}: { - require = [./installation-cd-base.nix]; - - installer.configModule = "./nixos/modules/installer/cd-dvd/installation-cd-graphical.nix"; - - services.xserver = { - enable = true; - autorun = false; - defaultDepth = 16; - desktopManager.default = "kde4"; - desktopManager.kde4.enable = true; - }; + require = [ + ./installation-cd-base.nix + ../../profiles/graphical.nix + ]; } diff --git a/modules/installer/cd-dvd/installation-cd-minimal.nix b/modules/installer/cd-dvd/installation-cd-minimal.nix index 4d85b7c8a80c..c166e3f4ad03 100644 --- a/modules/installer/cd-dvd/installation-cd-minimal.nix +++ b/modules/installer/cd-dvd/installation-cd-minimal.nix @@ -4,14 +4,8 @@ {config, pkgs, ...}: { - require = [./installation-cd-base.nix]; - - installer.configModule = "./nixos/modules/installer/cd-dvd/installation-cd-minimal.nix"; - - # Don't include X libraries. - services.openssh.forwardX11 = false; - services.dbus.enable = false; # depends on libX11 - services.hal.enable = false; # depends on dbus - fonts.enableFontConfig = false; - fonts.enableCoreFonts = false; + require = [ + ./installation-cd-base.nix + ../../profiles/minimal.nix + ]; } diff --git a/modules/installer/cd-dvd/installation-cd-rescue.nix b/modules/installer/cd-dvd/installation-cd-rescue.nix index ed5184c69cb3..43b9c9e2b7c1 100644 --- a/modules/installer/cd-dvd/installation-cd-rescue.nix +++ b/modules/installer/cd-dvd/installation-cd-rescue.nix @@ -4,48 +4,8 @@ {config, pkgs, ...}: { - require = [./installation-cd-base.nix]; - - installer.configModule = "./nixos/modules/installer/cd-dvd/installation-cd-minimal.nix"; - - # Don't include X libraries. - services.openssh.forwardX11 = false; - services.dbus.enable = false; # depends on libX11 - services.hal.enable = false; # depends on dbus - fonts.enableFontConfig = false; - fonts.enableCoreFonts = false; - - # Useful for rescue.. - environment.systemPackages = with pkgs; [ - utillinuxCurses ddrescue - pciutils sdparm hdparm hddtemp usbutils - btrfsProgs xfsprogs jfsutils jfsrec - iproute - fuse ntfs3g smbfsFuse sshfsFuse - manpages irssi elinks mcabber mutt openssh lftp - openssl ncat socat - gnupg1 gnupg - patch which diffutils gcc binutils bc file - screen - bvi joe nvi - subversion16 monotone git darcs mercurial bazaar cvs - unrar unzip zip lzma cabextract cpio - lsof + require = [ + ./installation-cd-base.nix + ../../profiles/rescue.nix ]; - - boot.kernelPackages = pkgs.linuxPackages_2_6_32; - boot.initrd.kernelModules = ["evdev" "i8042" "pcips2" "serio" - "sd_mod" "libata" "unix" "usbhid" "uhci_hcd" "atkbd" "xtkbd" "fbdev" - "iso9660" "udf" "loop"]; - boot.kernelModules = ["fbcon" "radeonfb" "intelfb" "sisfb" "nvidiafb" - "cirrusfb"]; - boot.kernelParams = [ - "selinux=0" - "acpi=on" - "apm=off" - "console=tty1" - "splash=verbose" - ]; - - services.ttyBackgrounds.enable = false; } diff --git a/modules/installer/cd-dvd/iso-image.nix b/modules/installer/cd-dvd/iso-image.nix index 15ac34492075..8117d8631f5b 100644 --- a/modules/installer/cd-dvd/iso-image.nix +++ b/modules/installer/cd-dvd/iso-image.nix @@ -174,11 +174,9 @@ in # Closures to be copied to the Nix store on the CD, namely the init # script and the top-level system configuration directory. isoImage.storeContents = - [ config.system.build.bootStage2 - config.system.build.toplevel - ] ++ - (optional config.isoImage.includeSystemBuildDependencies - config.system.build.toplevel.drvPath); + [ config.system.build.toplevel ] ++ + optional config.isoImage.includeSystemBuildDependencies + config.system.build.toplevel.drvPath; # Create the squashfs image that contains the Nix store. system.build.squashfsStore = import ../../../lib/make-squashfs.nix { @@ -220,7 +218,7 @@ in boot.loader.grub.extraEntries = '' menuentry "NixOS Installer / Rescue" { - linux /boot/bzImage init=${config.system.build.bootStage2} systemConfig=${config.system.build.toplevel} ${toString config.boot.kernelParams} + linux /boot/bzImage init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} initrd /boot/initrd } diff --git a/modules/installer/cd-dvd/live-dvd.nix b/modules/installer/cd-dvd/live-dvd.nix index 70fa301ef1fd..4857900389c0 100644 --- a/modules/installer/cd-dvd/live-dvd.nix +++ b/modules/installer/cd-dvd/live-dvd.nix @@ -1,7 +1,7 @@ {config, pkgs, ...}: { - require = [./installation-cd.nix]; + require = [./installation-cd-base.nix]; # Build the build-time dependencies of this configuration on the DVD # to speed up installation. diff --git a/modules/installer/cd-dvd/system-tarball-pc.nix b/modules/installer/cd-dvd/system-tarball-pc.nix index b81b7d5d0a9a..62b32c48144e 100644 --- a/modules/installer/cd-dvd/system-tarball-pc.nix +++ b/modules/installer/cd-dvd/system-tarball-pc.nix @@ -7,164 +7,18 @@ with pkgs.lib; let - # A dummy /etc/nixos/configuration.nix in the booted CD that - # rebuilds the CD's configuration (and allows the configuration to - # be modified, of course, providing a true live CD). Problem is - # that we don't really know how the CD was built - the Nix - # expression language doesn't allow us to query the expression being - # evaluated. So we'll just hope for the best. - dummyConfiguration = pkgs.writeText "configuration.nix" - '' - {config, pkgs, ...}: - - { - require = [ ]; - - # Add your own options below and run "nixos-rebuild switch". - # E.g., - # services.openssh.enable = true; - } - ''; - - pkgs2storeContents = l : map (x: { object = x; symlink = "none"; }) l; - options = { - - system.nixosVersion = mkOption { - default = "${builtins.readFile ../../../VERSION}"; - description = '' - NixOS version number. - ''; - }; - }; - in { - require = - [ options - ./system-tarball.nix - ../../hardware/network/rt73.nix - ]; - - - # Disable some other stuff we don't need. - security.sudo.enable = false; - - # Include only the en_US locale. This saves 75 MiB or so compared to - # the full glibcLocales package. - i18n.supportedLocales = ["en_US.UTF-8/UTF-8" "en_US/ISO-8859-1"]; - - # 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 - pkgs.parted - pkgs.ddrescue - pkgs.ccrypt - pkgs.cryptsetup # needed for dm-crypt volumes - - # Some networking tools. - pkgs.sshfsFuse - pkgs.socat - pkgs.screen - pkgs.wpa_supplicant # !!! should use the wpa module - - # Hardware-related tools. - pkgs.sdparm - pkgs.hdparm - pkgs.dmraid - - # Tools to create / manipulate filesystems. - pkgs.ntfsprogs # for resizing NTFS partitions - pkgs.btrfsProgs - pkgs.xfsprogs - pkgs.jfsutils - pkgs.jfsrec - - # Some compression/archiver tools. - pkgs.unrar - pkgs.unzip - pkgs.zip - pkgs.xz - pkgs.dar # disk archiver - - # Some editors. - pkgs.nvi - pkgs.bvi # binary editor - pkgs.joe - ]; - - # The initrd has to contain any module that might be necessary for - # mounting the CD/DVD. - boot.initrd.availableKernelModules = - [ # SATA/PATA support. - "ahci" - - "ata_piix" - - "sata_inic162x" "sata_nv" "sata_promise" "sata_qstor" - "sata_sil" "sata_sil24" "sata_sis" "sata_svw" "sata_sx4" - "sata_uli" "sata_via" "sata_vsc" - - "pata_ali" "pata_amd" "pata_artop" "pata_atiixp" - "pata_cs5520" "pata_cs5530" "pata_cs5535" "pata_efar" - "pata_hpt366" "pata_hpt37x" "pata_hpt3x2n" "pata_hpt3x3" - "pata_it8213" "pata_it821x" "pata_jmicron" "pata_marvell" - "pata_mpiix" "pata_netcell" "pata_ns87410" "pata_oldpiix" - "pata_pcmcia" "pata_pdc2027x" "pata_qdi" "pata_rz1000" - "pata_sc1200" "pata_serverworks" "pata_sil680" "pata_sis" - "pata_sl82c105" "pata_triflex" "pata_via" - "pata_winbond" - - # SCSI support (incomplete). - "3w-9xxx" "3w-xxxx" "aic79xx" "aic7xxx" "arcmsr" - - # USB support, especially for booting from USB CD-ROM - # drives. - "usb_storage" - - # Firewire support. Not tested. - "ohci1394" "sbp2" - - # Virtio (QEMU, KVM etc.) support. - "virtio_net" "virtio_pci" "virtio_blk" "virtio_balloon" - - # Add vfat to enable people to copy the contents of the CD to a - # bootable USB stick. - "vfat" - ]; - - boot.initrd.kernelModules = - [ # Wait for SCSI devices to appear. - "scsi_wait_scan" - ]; - - boot.postBootCommands = - '' - mkdir -p /mnt - - cp ${dummyConfiguration} /etc/nixos/configuration.nix - ''; - - # Some more help text. - services.mingetty.helpLine = - '' - - Log in as "root" with an empty password. ${ - if config.services.xserver.enable then - "Type `start xserver' to start\nthe graphical user interface." - else "" - } - ''; - - # Include the firmware for various wireless cards. - networking.enableRT73Firmware = true; - networking.enableIntel2200BGFirmware = true; + require = [ + ./system-tarball.nix + + # Profiles of this basic installation. + ../../profiles/base.nix + ../../profiles/installation-device.nix + ]; # To speed up further installation of packages, include the complete stdenv # in the Nix store of the tarball. diff --git a/modules/installer/cd-dvd/system-tarball.nix b/modules/installer/cd-dvd/system-tarball.nix index 3418afc9c3d5..61290d6b4609 100644 --- a/modules/installer/cd-dvd/system-tarball.nix +++ b/modules/installer/cd-dvd/system-tarball.nix @@ -53,12 +53,7 @@ in # Closures to be copied to the Nix store on the CD, namely the init # script and the top-level system configuration directory. tarball.storeContents = - [ { - object = config.system.build.bootStage2; - symlink = "none"; - } - { - object = config.system.build.toplevel; + [ { object = config.system.build.toplevel; symlink = "/var/run/current-system"; } ]; diff --git a/modules/installer/grub/grub-menu-builder.sh b/modules/installer/grub/grub-menu-builder.sh index fc246847eed3..cc82665f2eef 100644 --- a/modules/installer/grub/grub-menu-builder.sh +++ b/modules/installer/grub/grub-menu-builder.sh @@ -52,8 +52,8 @@ default @default@ timeout @timeout@ GRUBEND if test -n "@splashImage@"; then - echo "splashimage $bootRoot/background.xpm.gz" >> "$1" - fi + echo "splashimage $bootRoot/background.xpm.gz" >> "$1" + fi ;; 2) cp -f @grub@/share/grub/unicode.pf2 /boot/grub/unicode.pf2 @@ -154,6 +154,7 @@ addEntry() { local kernel=$(readlink -f $path/kernel) local initrd=$(readlink -f $path/initrd) + local xen=$([ -f $path/xen.gz ] && readlink -f $path/xen.gz) if test "$path" = "$defaultConfig"; then cp "$kernel" /boot/nixos-kernel @@ -181,28 +182,34 @@ EOF if test -n "$copyKernels"; then copyToKernelsDir $kernel; kernel=$result copyToKernelsDir $initrd; initrd=$result + if [ -n "$xen" ]; then copyToKernelsDir $xen; xen=$result; fi fi - + local confName=$(cat $path/configuration-name 2>/dev/null || true) if test -n "$confName"; then name="$confName $3" fi + local kernelParams="systemConfig=$(readlink -f $path) init=$(readlink -f $path/init) $(cat $path/kernel-params)" + local xenParams="$([ -n "$xen" ] && cat $path/xen-params)" + case "$grubVersion" in 1) cat >> "$tmp" << GRUBEND title $name @extraPerEntryConfig@ - kernel $kernel systemConfig=$(readlink -f $path) init=$(readlink -f $path/init) $(cat $path/kernel-params) - initrd $initrd + ${xen:+kernel $xen $xenParams} + $(if [ -z "$xen" ]; then echo kernel; else echo module; fi) $kernel $kernelParams + $(if [ -z "$xen" ]; then echo initrd; else echo module; fi) $initrd GRUBEND ;; 2) cat >> "$tmp" << GRUBEND menuentry "$name" { @extraPerEntryConfig@ - linux $kernel systemConfig=$(readlink -f $path) init=$(readlink -f $path/init) $(cat $path/kernel-params) - initrd $initrd + ${xen:+multiboot $xen $xenParams} + $(if [ -z "$xen" ]; then echo linux; else echo module; fi) $kernel $kernelParams + $(if [ -z "$xen" ]; then echo initrd; else echo module; fi) $initrd } GRUBEND ;; @@ -243,7 +250,7 @@ for link in $((ls -d $defaultConfig/fine-tune/* ) | sort -n); do done for generation in $( - (cd /nix/var/nix/profiles && ls -d system-*-link) \ + (cd /nix/var/nix/profiles && for i in system-*-link; do echo $i; done) \ | sed 's/system-\([0-9]\+\)-link/\1/' \ | sort -n -r); do link=/nix/var/nix/profiles/system-$generation-link diff --git a/modules/installer/scan/detected.nix b/modules/installer/scan/detected.nix new file mode 100644 index 000000000000..09d04608e685 --- /dev/null +++ b/modules/installer/scan/detected.nix @@ -0,0 +1,13 @@ +# List all devices which are detected by nixos-hardware-scan. +# Common devices are enabled by default. +{config, pkgs, ...}: + +with pkgs.lib; + +{ + config = mkDefault { + # Wireless card firmware + networking.enableIntel2200BGFirmware = true; + networking.enableIntel3945ABGFirmware = true; + }; +} diff --git a/modules/installer/scan/not-detected.nix b/modules/installer/scan/not-detected.nix new file mode 100644 index 000000000000..3a4a7f40fc69 --- /dev/null +++ b/modules/installer/scan/not-detected.nix @@ -0,0 +1,12 @@ +# List all devices which are _not_ detected by nixos-hardware-scan. +# Common devices are enabled by default. +{config, pkgs, ...}: + +with pkgs.lib; + +{ + config = mkDefault { + # Wireless card firmware + networking.enableRT73Firmware = true; + }; +} diff --git a/modules/installer/tools/nixos-deploy-network/deploy.nix b/modules/installer/tools/nixos-deploy-network/deploy.nix new file mode 100644 index 000000000000..8d426780b100 --- /dev/null +++ b/modules/installer/tools/nixos-deploy-network/deploy.nix @@ -0,0 +1,61 @@ +{ nixos ? /etc/nixos/nixos +, nixpkgs ? /etc/nixos/nixpkgs +, networkExpr +, infrastructureExpr +}: + +let + pkgs = import nixpkgs {}; + + inherit (builtins) attrNames getAttr listToAttrs concatMapStrings; + + network = import networkExpr; + infrastructure = import infrastructureExpr; + + generateScript = network: infrastructure: configs: + concatMapStrings (configurationName: + let + infrastructureElement = getAttr configurationName infrastructure; + config = getAttr configurationName configs; + in + '' + echo "=== upgrading ${infrastructureElement.hostName} ===" + nix-copy-closure --to ${infrastructureElement.hostName} ${config.system.build.toplevel} \ + && ssh $NIX_SSHOPTS ${infrastructureElement.hostName} nix-env -p /nix/var/nix/profiles/system --set ${config.system.build.toplevel} \ + && ssh $NIX_SSHOPTS ${infrastructureElement.hostName} ${config.system.build.toplevel}/bin/switch-to-configuration switch \ + && { succeeded=$((succeeded + 1)); } \ + || { failed=$((failed + 1)); echo 'WARNING: upgrade of ${infrastructureElement.hostName} failed!'; } + '' + ) (attrNames network) + ; + + evaluateMachines = network: infrastructure: + listToAttrs (map (configurationName: + let + configuration = getAttr configurationName network; + system = (getAttr configurationName infrastructure).system; + in + { name = configurationName; + value = (import "${nixos}/lib/eval-config.nix" { + inherit nixpkgs system; + modules = [ configuration ]; + extraArgs = evaluateMachines network infrastructure; + }).config; } + ) (attrNames (network))) + ; + + configs = evaluateMachines network infrastructure; +in +pkgs.stdenv.mkDerivation { + name = "deploy-script"; + buildCommand = '' + ensureDir $out/bin + cat > $out/bin/deploy-systems << "EOF" + #! ${pkgs.stdenv.shell} -e + failed=0; succeeded=0 + ${generateScript network infrastructure configs} + echo "Upgrade of $failed machines failed, $succeeded machines succeeded."; + EOF + chmod +x $out/bin/deploy-systems + ''; +} diff --git a/modules/installer/tools/nixos-deploy-network/nixos-deploy-network.sh b/modules/installer/tools/nixos-deploy-network/nixos-deploy-network.sh new file mode 100644 index 000000000000..62463285f0fd --- /dev/null +++ b/modules/installer/tools/nixos-deploy-network/nixos-deploy-network.sh @@ -0,0 +1,73 @@ +#! @shell@ -e + +# Shows the usage of this command to the user + +showUsage() +{ + echo "Usage: $0 -n network_expr -i infrastructure_expr" + echo "Options:" + echo + echo "-n,--network Network Nix expression which captures properties of machines in the network" + echo "-i,--infrastructure Infrastructure Nix expression which captures properties of machines in the network" + echo "-h,--help Shows the usage of this command" +} + +# Parse valid argument options + +PARAMS=`getopt -n $0 -o n:i:h -l network:,infrastructure:,show-trace,help -- "$@"` + +if [ $? != 0 ] +then + showUsage + exit 1 +fi + +eval set -- "$PARAMS" + +# Evaluate valid options + +while [ "$1" != "--" ] +do + case "$1" in + -n|--network) + networkExpr=`readlink -f $2` + ;; + -i|--infrastructure) + infrastructureExpr=`readlink -f $2` + ;; + --show-trace) + showTraceArg="--show-trace" + ;; + -h|--help) + showUsage + exit 0 + ;; + esac + + shift +done + +# Validate the given options + +if [ "$infrastructureExpr" = "" ] +then + echo "ERROR: A infrastructure expression must be specified!" >&2 + exit 1 +fi + +if [ "$networkExpr" = "" ] +then + echo "ERROR: A network expression must be specified!" >&2 + exit 1 +fi + +if [ -z "$NIXOS" ] +then + NIXOS=/etc/nixos/nixos +fi + +# Deploy the network + +nix-build $NIXOS/deploy.nix --argstr networkExpr $networkExpr --argstr infrastructureExpr $infrastructureExpr $showTraceArg +./result/bin/deploy-systems +rm -f result diff --git a/modules/installer/tools/nixos-hardware-scan.pl b/modules/installer/tools/nixos-hardware-scan.pl index ce1085f8ebc5..56549f99235d 100644 --- a/modules/installer/tools/nixos-hardware-scan.pl +++ b/modules/installer/tools/nixos-hardware-scan.pl @@ -227,7 +227,14 @@ my $attrs = multiLineList(" ", removeDups @attrs); print <&2 " -Usage: $0 OPTION_NAME [-v] [-d] [-l] +Usage: $0 [--install] [-v] [-d] [-l] OPTION_NAME + $0 [--install] This program is used to explore NixOS options by looking at their values or -by looking at their description. It is helpful for understanding the how -your configuration is working. +by looking at their description. It is helpful for understanding how your +configuration is working. Options: + -i | --install Use the configuration on + ${mountPoint:+$mountPoint/}$NIXOS_CONFIG instead of + the current system configuration. Generate a + template configuration if no option name is + specified. -v | --value Display the current value, based on your configuration. - -d | --default Display the default value, the example and the + -d | --description Display the default value, the example and the description. -l | --lookup Display where the option is defined and where it is declared. --help Show this message. -Environment variables affecting nixos-option: +Environment variables affecting $0: - \$NIXOS_PATH Path where the NixOS repository is located. + \$mountPoint Path to the target file system. + \$NIXOS Path where the NixOS repository is located. \$NIXOS_CONFIG Path to your configuration file. \$NIXPKGS Path to Nix packages. @@ -44,6 +52,7 @@ Environment variables affecting nixos-option: desc=false defs=false value=false +install=false verbose=false option="" @@ -52,18 +61,39 @@ argfun="" for arg; do if test -z "$argfun"; then case $arg in - -d|--description) desc=true;; - -v|--value) value=true;; - -l|--lookup) defs=true;; - --verbose) verbose=true;; - --help) usage;; - -*) usage;; - *) if test -z "$option"; then - option="$arg" - else - usage - fi;; + -*) + longarg="" + sarg="$arg" + while test "$sarg" != "-"; do + case $sarg in + --*) longarg=$arg;; + -d*) longarg="$longarg --description";; + -v*) longarg="$longarg --value";; + -l*) longarg="$longarg --lookup";; + -i*) longarg="$longarg --install";; + -*) usage;; + esac + sarg="-${sarg#??}" + done + ;; + *) longarg=$arg;; esac + for larg in $longarg; do + case $larg in + --description) desc=true;; + --value) value=true;; + --lookup) defs=true;; + --install) install=true;; + --verbose) verbose=true;; + --help) usage;; + -*) usage;; + *) if test -z "$option"; then + option="$larg" + else + usage + fi;; + esac + done else case $argfun in set_*) @@ -75,6 +105,16 @@ for arg; do fi done +# --install cannot be used with -d -v -l without option name. +if $value || $desc || $defs && $install && test -z "$option"; then + usage +fi + +generate=false +if ! $defs && ! $desc && ! $value && $install && test -z "$option"; then + generate=true +fi + if ! $defs && ! $desc; then value=true fi @@ -93,7 +133,7 @@ evalAttr(){ local prefix=$1 local suffix=$2 local strict=$3 - echo "(import $NIXOS_PATH {}).$prefix${option:+.$option}${suffix:+.$suffix}" | + echo "(import $NIXOS {}).$prefix${option:+.$option}${suffix:+.$suffix}" | nix-instantiate - --eval-only ${strict:+--strict} } @@ -107,11 +147,134 @@ evalCfg(){ findSources(){ local suffix=$1 - echo "builtins.map (f: f.source) (import $NIXOS_PATH {}).eval.options${option:+.$option}.$suffix" | + echo "builtins.map (f: f.source) (import $NIXOS {}).eval.options${option:+.$option}.$suffix" | nix-instantiate - --eval-only --strict } +if $install; then + if test -e "$mountPoint$NIXOS"; then + export NIXOS="$mountPoint$NIXOS" + fi + if test -e "$mountPoint$NIXPKGS"; then + export NIXPKGS="$mountPoint$NIXPKGS" + fi + export NIXOS_CONFIG="$mountPoint$NIXOS_CONFIG" +fi +if $generate; then + mkdir -p $(dirname "$NIXOS_CONFIG") + + # Scan the hardware and add the result to /etc/nixos/hardware-scan.nix. + hardware_config="${NIXOS_CONFIG%/configuration.nix}/hardware-configuration.nix" + if test -e "$hardware_config"; then + echo "A hardware configuration file exists, generation skipped." + else + echo "Scan your hardware to generate a hardware configuration file." + nixos-hardware-scan > "$hardware_config" + fi + + if test -e "$NIXOS_CONFIG"; then + echo 1>&2 "error: Cannot generate a template configuration because a configuration file exists." + exit 1 + fi + + echo "Generate a template configuration that you should edit." + + # Generate a template configuration file where the user has to + # fill the gaps. + echo > "$NIXOS_CONFIG" \ +'# Edit this configuration file which defines what would be installed on the +# system. To Help while choosing option value, you can watch at the manual +# page of configuration.nix or at the last chapter of the manual available +# on the virtual console 8 (Alt+F8). + +{config, pkgs, ...}: + +{ + require = [ + # Include the configuration for part of your system which have been + # detected automatically. In addition, it includes the same + # configuration as the installation device that you used. + ./hardware-configuration.nix + ]; + + boot.initrd.kernelModules = [ + # Specify all kernel modules that are necessary for mounting the root + # file system. + # + # "ext4" "ata_piix" + ]; + + boot.loader.grub = { + # Use grub 2 as boot loader. + enable = true; + version = 2; + + # Define on which hard drive you want to install Grub. + # device = "/dev/sda"; + }; + + networking = { + # hostName = "nixos"; # Define your hostname. + interfaceMonitor.enable = true; # Watch for plugged cable. + enableWLAN = true; # Enables Wireless. + }; + + # Add file system entries for each partition that you want to see mounted + # at boot time. You can add filesystems which are not mounted at boot by + # adding the noauto option. + fileSystems = [ + # Mount the root file system + # + # { mountPoint = "/"; + # device = "/dev/sda2"; + # } + + # Copy & Paste & Uncomment & Modify to add any other file system. + # + # { mountPoint = "/data"; # where you want to mount the device + # device = "/dev/sdb"; # the device or the label of the device + # # label = "data"; + # fsType = "ext3"; # the type of the partition. + # options = "data=journal"; + # } + ]; + + swapDevices = [ + # List swap partitions that are mounted at boot time. + # + # { device = "/dev/sda1"; } + ]; + + # Select internationalisation properties. + # i18n = { + # consoleFont = "lat9w-16"; + # consoleKeyMap = "us"; + # defaultLocale = "en_US.UTF-8"; + # }; + + # List services that you want to enable: + + # Add an OpenSSH daemon. + # services.openssh.enable = true; + + # Add CUPS to print documents. + # services.printing.enable = true; + + # Add XServer (default if you have used a graphical iso) + # services.xserver = { + # enable = true; + # layout = "us"; + # xkbOptions = "eurosign:e"; + # }; + + # Add the NixOS Manual on virtual console 8 + services.nixosManual.showManual = true; +} +' + + exit 0 +fi; if test "$(evalOpt "_type" 2> /dev/null)" = '"option"'; then $value && evalCfg; diff --git a/modules/installer/tools/nixos-rebuild.sh b/modules/installer/tools/nixos-rebuild.sh index 4d01ff53f890..41b74494337d 100644 --- a/modules/installer/tools/nixos-rebuild.sh +++ b/modules/installer/tools/nixos-rebuild.sh @@ -22,6 +22,8 @@ The operation is one of the following: activate it build-vm: build a virtual machine containing the configuration (useful for testing) + build-vm-with-bootloader: + like build-vm, but include a boot loader in the VM dry-run: just show what store paths would be built/downloaded pull: just pull the Nixpkgs channel manifest and exit @@ -64,7 +66,7 @@ while test "$#" -gt 0; do --help) showSyntax ;; - switch|boot|test|build|dry-run|build-vm|pull) + switch|boot|test|build|dry-run|build-vm|build-vm-with-bootloader|pull) action="$i" ;; --install-grub) @@ -171,9 +173,12 @@ if test -z "$rollback"; then elif test "$action" = test -o "$action" = build -o "$action" = dry-run; then nix-build $NIXOS -A system -K -k $extraBuildFlags > /dev/null pathToConfig=./result - elif test "$action" = build-vm; then + elif [ "$action" = build-vm ]; then nix-build $NIXOS -A vm -K -k $extraBuildFlags > /dev/null pathToConfig=./result + elif [ "$action" = build-vm-with-bootloader ]; then + nix-build $NIXOS -A vmWithBootLoader -K -k $extraBuildFlags > /dev/null + pathToConfig=./result else showSyntax fi diff --git a/modules/installer/tools/tools.nix b/modules/installer/tools/tools.nix index d9ebb58a9f8f..8dd07c67f916 100644 --- a/modules/installer/tools/tools.nix +++ b/modules/installer/tools/tools.nix @@ -11,6 +11,11 @@ let isExecutable = true; }); + nixosDeployNetwork = makeProg { + name = "nixos-deploy-network"; + src = ./nixos-deploy-network/nixos-deploy-network.sh; + }; + nixosInstall = makeProg { name = "nixos-install"; src = ./nixos-install.sh; @@ -80,6 +85,7 @@ let name = "nixos-hardware-scan"; src = ./nixos-hardware-scan.pl; inherit (pkgs) perl; + profile = config.installer.installProfile; }; nixosOption = makeProg { @@ -112,12 +118,21 @@ in nixos-rebuild to speed up builds. ''; }; + + installer.installProfile = pkgs.lib.mkOption { + default = "base"; + example = "graphical"; + description = '' + Name of the profile used when generating the hardware-scan. + ''; + }; }; config = { environment.systemPackages = - [ nixosInstall + [ nixosDeployNetwork + nixosInstall nixosRebuild nixosHardwareScan nixosGenSeccureKeys @@ -128,7 +143,7 @@ in ]; system.build = { - inherit nixosInstall; + inherit nixosInstall nixosHardwareScan nixosOption; # expose scripts inherit (installer2) nixosPrepareInstall runInChroot nixosBootstrap minimalInstallArchive; diff --git a/modules/misc/ids.nix b/modules/misc/ids.nix index 11f41aa08276..f69ae2f3b9fe 100644 --- a/modules/misc/ids.nix +++ b/modules/misc/ids.nix @@ -56,6 +56,7 @@ in sabnzbd = 33; tor = 35; cups = 36; + foldingAtHome = 37; # When adding a uid, make sure it doesn't match an existing gid. nixbld = 30000; # start of range of uids diff --git a/modules/module-list.nix b/modules/module-list.nix index 5a1efdabf411..4bc46544d107 100644 --- a/modules/module-list.nix +++ b/modules/module-list.nix @@ -14,6 +14,7 @@ ./config/users-groups.nix ./hardware/network/intel-2200bg.nix ./hardware/network/intel-3945abg.nix + ./hardware/network/rt2870.nix ./hardware/network/rt73.nix ./hardware/pcmcia.nix ./installer/generations-dir/generations-dir.nix @@ -44,6 +45,7 @@ ./security/sudo.nix ./services/audio/alsa.nix ./services/audio/pulseaudio.nix + ./services/backup/hydra-mirror.nix ./services/backup/mysql-backup.nix ./services/backup/postgresql-backup.nix ./services/backup/sitecopy-backup.nix @@ -58,10 +60,12 @@ ./services/logging/logrotate.nix ./services/logging/syslogd.nix ./services/mail/dovecot.nix + ./services/mail/mail.nix ./services/mail/postfix.nix ./services/misc/autofs.nix ./services/misc/disnix.nix ./services/misc/felix.nix + ./services/misc/folding-at-home.nix ./services/misc/gpsd.nix ./services/misc/nix-daemon.nix ./services/misc/nix-gc.nix @@ -77,6 +81,7 @@ ./services/network-filesystems/nfs-kernel.nix ./services/network-filesystems/openafs-client/default.nix ./services/network-filesystems/samba.nix + ./services/networking/amuled.nix ./services/networking/avahi-daemon.nix ./services/networking/bind.nix ./services/networking/bitlbee.nix @@ -109,6 +114,7 @@ ./services/scheduling/cron.nix ./services/scheduling/fcron.nix ./services/security/tor.nix + ./services/security/torsocks.nix ./services/system/dbus.nix ./services/system/kerberos.nix ./services/system/nscd.nix @@ -154,4 +160,5 @@ ./tasks/network-interfaces.nix ./tasks/swraid.nix ./tasks/tty-backgrounds.nix + ./virtualisation/xen-dom0.nix ] diff --git a/modules/profiles/base.nix b/modules/profiles/base.nix new file mode 100644 index 000000000000..68456e81f546 --- /dev/null +++ b/modules/profiles/base.nix @@ -0,0 +1,92 @@ +{config, pkgs, ...}: + +{ + + # The initrd has to contain any module that might be necessary for + # mounting the CD/DVD. + boot.initrd.availableKernelModules = + [ # SATA/PATA support. + "ahci" + + "ata_piix" + + "sata_inic162x" "sata_nv" "sata_promise" "sata_qstor" + "sata_sil" "sata_sil24" "sata_sis" "sata_svw" "sata_sx4" + "sata_uli" "sata_via" "sata_vsc" + + "pata_ali" "pata_amd" "pata_artop" "pata_atiixp" + "pata_cs5520" "pata_cs5530" "pata_cs5535" "pata_efar" + "pata_hpt366" "pata_hpt37x" "pata_hpt3x2n" "pata_hpt3x3" + "pata_it8213" "pata_it821x" "pata_jmicron" "pata_marvell" + "pata_mpiix" "pata_netcell" "pata_ns87410" "pata_oldpiix" + "pata_pcmcia" "pata_pdc2027x" "pata_qdi" "pata_rz1000" + "pata_sc1200" "pata_serverworks" "pata_sil680" "pata_sis" + "pata_sl82c105" "pata_triflex" "pata_via" + "pata_winbond" + + # SCSI support (incomplete). + "3w-9xxx" "3w-xxxx" "aic79xx" "aic7xxx" "arcmsr" + + # USB support, especially for booting from USB CD-ROM + # drives. + "usb_storage" + + # Firewire support. Not tested. + "ohci1394" "sbp2" + + # Virtio (QEMU, KVM etc.) support. + "virtio_net" "virtio_pci" "virtio_blk" "virtio_balloon" + + # Add vfat to enable people to copy the contents of the CD to a + # bootable USB stick. + "vfat" "nls_cp437" "nls_iso8859-1" + ]; + + boot.initrd.kernelModules = + [ # Wait for SCSI devices to appear. + "scsi_wait_scan" + ]; + + # 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 + pkgs.parted + pkgs.ddrescue + pkgs.ccrypt + pkgs.cryptsetup # needed for dm-crypt volumes + + # Some networking tools. + pkgs.sshfsFuse + pkgs.socat + pkgs.screen + + # Hardware-related tools. + pkgs.sdparm + pkgs.hdparm + pkgs.dmraid + + # Tools to create / manipulate filesystems. + pkgs.ntfsprogs # for resizing NTFS partitions + pkgs.btrfsProgs + pkgs.dosfstools + pkgs.xfsprogs + pkgs.jfsutils + pkgs.jfsrec + + # Some compression/archiver tools. + pkgs.unrar + pkgs.unzip + pkgs.zip + pkgs.xz + pkgs.dar # disk archiver + + # Some editors. + pkgs.nvi + pkgs.bvi # binary editor + pkgs.joe + ]; +} diff --git a/modules/profiles/empty.nix b/modules/profiles/empty.nix new file mode 100644 index 000000000000..bb40a31470dd --- /dev/null +++ b/modules/profiles/empty.nix @@ -0,0 +1,8 @@ +# Empty profiles, used to avoid the case where no profiles are selected for +# nixos-hardware-scan. + +{ + imports = []; + options = {}; + config = {}; +} diff --git a/modules/profiles/graphical.nix b/modules/profiles/graphical.nix new file mode 100644 index 000000000000..58b4ffa7c1a1 --- /dev/null +++ b/modules/profiles/graphical.nix @@ -0,0 +1,17 @@ +# This module defines a NixOS configuration that contains X11 and +# KDE 4. +{config, pkgs, ...}: + +{ + require = [ + ./base.nix + ]; + + services.xserver = { + enable = true; + autorun = true; + defaultDepth = 24; + desktopManager.default = "kde4"; + desktopManager.kde4.enable = true; + }; +} diff --git a/modules/profiles/installation-device.nix b/modules/profiles/installation-device.nix new file mode 100644 index 000000000000..ccd982c9ce9f --- /dev/null +++ b/modules/profiles/installation-device.nix @@ -0,0 +1,166 @@ +# Provide a basic cponfiguration for installation devices like CDs. +{config, pkgs, modules, ...}: + +with pkgs.lib; + +let + # Location of the repository on the harddrive + nixosPath = toString ../../.; + + # Check if the path is from the NixOS repository + isNixOSFile = path: + let s = toString path; in + removePrefix nixosPath s != s; + + # Copy modules given as extra configuration files. Unfortunately, we + # cannot serialized attribute set given in the list of modules (that's why + # you should use files). + moduleFiles = + filter isPath modules; + + # Partition module files because between NixOS and non-NixOS files. NixOS + # files may change if the repository is updated. + partitionnedModuleFiles = + let p = partition isNixOSFile moduleFiles; in + { nixos = p.right; others = p.wrong; }; + + # Path transformed to be valid on the installation device. Thus the + # device configuration could be rebuild. + relocatedModuleFiles = + let + relocateNixOS = path: + "/etc/nixos/nixos" + removePrefix nixosPath (toString path); + relocateOthers = null; + in + { nixos = map relocateNixOS partitionnedModuleFiles.nixos; + others = []; # TODO: copy the modules to the install-device repository. + }; + + # A dummy /etc/nixos/configuration.nix in the booted CD that + # rebuilds the CD's configuration (and allows the configuration to + # be modified, of course, providing a true live CD). Problem is + # that we don't really know how the CD was built - the Nix + # expression language doesn't allow us to query the expression being + # evaluated. So we'll just hope for the best. + configClone = pkgs.writeText "configuration.nix" + '' + {config, pkgs, ...}: + + { + require = [ + ${toString config.installer.cloneConfigIncludes} + ]; + + # Add your own options below and run "nixos-rebuild switch". + # E.g., + # services.openssh.enable = true; + } + ''; +in + +{ + imports = [ + # Enable devices which are usually scanned, because we don't know the + # target system. + ../installer/scan/detected.nix + ../installer/scan/not-detected.nix + ]; + + options = { + system.nixosVersion = mkOption { + default = "${builtins.readFile ../../VERSION}"; + description = '' + NixOS version number. + ''; + }; + + installer.cloneConfig = mkOption { + default = true; + description = '' + Try to clone the installation-device configuration by re-using it's + profile from the list of imported modules. + ''; + }; + + installer.cloneConfigIncludes = mkOption { + default = []; + example = [ "./nixos/modules/hardware/network/rt73.nix" ]; + description = '' + List of modules used to re-build this installation device profile. + ''; + }; + + # Ignored. Kept for Backward compatibiliy. + # you can retrieve the profiles which have been used by looking at the + # list of modules use to configure the installation device. + installer.configModule = mkOption { + example = "./nixos/modules/installer/cd-dvd/installation-cd.nix"; + description = '' + Filename of the configuration module that builds the CD + configuration. Must be specified to support reconfiguration + in live CDs. + ''; + }; + }; + + config = { + installer.cloneConfigIncludes = + relocatedModuleFiles.nixos ++ relocatedModuleFiles.others; + + # Show the manual. + services.nixosManual.showManual = true; + + # Let the user play Rogue on TTY 8 during the installation. + services.rogue.enable = true; + + # Disable some other stuff we don't need. + security.sudo.enable = false; + + # Include only the en_US locale. This saves 75 MiB or so compared to + # the full glibcLocales package. + i18n.supportedLocales = ["en_US.UTF-8/UTF-8" "en_US/ISO-8859-1"]; + + # nixos-install will do a pull from this channel to speed up the + # installation. + installer.nixpkgsURL = http://nixos.org/releases/nixpkgs/channels/nixpkgs-unstable; + + boot.postBootCommands = + '' + # Provide a mount point for nixos-install. + mkdir -p /mnt + + ${optionalString config.installer.cloneConfig '' + # Provide a configuration for the CD/DVD itself, to allow users + # to run nixos-rebuild to change the configuration of the + # running system on the CD/DVD. + cp ${configClone} /etc/nixos/configuration.nix + ''} + ''; + + # Force the xserver autorun to false. + services.xserver.autorun = mkForce false; + services.xserver.defaultDepth = mkForce 16; + + # Some more help text. + services.mingetty.helpLine = + '' + + Log in as "root" with an empty password. ${ + if config.services.xserver.enable then + "Type `start xserver' to start\nthe graphical user interface." + else "" + } + ''; + + + # Allow sshd to be started manually through "start sshd". It should + # not be started by default on the installation CD because the + # default root password is empty. + services.openssh.enable = true; + jobs.sshd.startOn = pkgs.lib.mkOverride 50 ""; + + # Enable wpa_supplicant, but don't start it by default. + networking.enableWLAN = true; + jobs.wpa_supplicant.startOn = pkgs.lib.mkOverride 50 ""; + }; +} diff --git a/modules/profiles/minimal.nix b/modules/profiles/minimal.nix new file mode 100644 index 000000000000..acc56d94edc1 --- /dev/null +++ b/modules/profiles/minimal.nix @@ -0,0 +1,15 @@ +# This module defines a small NixOS configuration. It does not +# contain any graphical stuff. + +{config, pkgs, ...}: + +{ + require = [ ./base.nix ]; + + # Don't include X libraries. + services.openssh.forwardX11 = false; + services.dbus.enable = false; # depends on libX11 + services.hal.enable = false; # depends on dbus + fonts.enableFontConfig = false; + fonts.enableCoreFonts = false; +} diff --git a/modules/profiles/rescue.nix b/modules/profiles/rescue.nix new file mode 100644 index 000000000000..b3b830e6618f --- /dev/null +++ b/modules/profiles/rescue.nix @@ -0,0 +1,52 @@ +# This module defines a small NixOS configuration. It does not contain any +# graphical stuff but contains many tools useful for the rescue. + +{config, pkgs, ...}: + +{ + require = [ ./minimal.nix ]; + + # Useful for rescue.. + environment.systemPackages = with pkgs; [ + utillinuxCurses ddrescue + pciutils sdparm hdparm hddtemp usbutils + btrfsProgs xfsprogs jfsutils jfsrec + iproute + fuse ntfs3g smbfsFuse sshfsFuse + manpages irssi elinks mcabber mutt openssh lftp + openssl ncat socat + gnupg1 gnupg + patch which diffutils gcc binutils bc file + screen + bvi joe nvi + subversion16 monotone git darcs mercurial bazaar cvs + unrar unzip zip lzma cabextract cpio + lsof + ]; + + boot.kernelPackages = pkgs.linuxPackages_2_6_32; + + boot.initrd.kernelModules = [ + "evdev" "i8042" "pcips2" "serio" "sd_mod" "libata" "unix" "usbhid" + "uhci_hcd" "atkbd" "xtkbd" "fbdev" "iso9660" "udf" "loop" + ]; + + boot.kernelModules = [ + "fbcon" + "radeonfb" + "intelfb" + "sisfb" + "nvidiafb" + "cirrusfb" + ]; + + boot.kernelParams = [ + "selinux=0" + "acpi=on" + "apm=off" + "console=tty1" + "splash=verbose" + ]; + + services.ttyBackgrounds.enable = false; +} diff --git a/modules/programs/bash/bash.nix b/modules/programs/bash/bash.nix index 1e2730b04b97..f99d04e6335d 100644 --- a/modules/programs/bash/bash.nix +++ b/modules/programs/bash/bash.nix @@ -1,19 +1,21 @@ # This module defines global configuration for the Bash shell, in # particular /etc/bashrc and /etc/profile. -{config, pkgs, ...}: +{ config, pkgs, ... }: + +with pkgs.lib; let options = { - environment.shellInit = pkgs.lib.mkOption { + environment.shellInit = mkOption { default = ""; example = ''export PATH=/godi/bin/:$PATH''; description = " Script used to initialized user shell environments. "; - merge = pkgs.lib.mergeStringOption; + merge = mergeStringOption; }; }; @@ -57,4 +59,13 @@ in ]; system.build.binsh = pkgs.bashInteractive; + + system.activationScripts.binsh = stringAfter [ "stdio" ] + '' + # Create the required /bin/sh symlink; otherwise lots of things + # (notably the system() function) won't work. + mkdir -m 0755 -p /bin + ln -sfn ${config.system.build.binsh}/bin/sh /bin/sh + ''; + } diff --git a/modules/programs/bash/bashrc.sh b/modules/programs/bash/bashrc.sh index e43b716a0ce2..8d1e4833a2de 100644 --- a/modules/programs/bash/bashrc.sh +++ b/modules/programs/bash/bashrc.sh @@ -15,14 +15,14 @@ export LOCATE_PATH=/var/cache/locatedb # Include the various profiles in the appropriate environment variables. NIX_USER_PROFILE_DIR=/nix/var/nix/profiles/per-user/$USER -NIX_PROFILES="/var/run/current-system/sw /nix/var/nix/profiles/default $NIX_USER_PROFILE_DIR/profile" +NIX_PROFILES="/var/run/current-system/sw /nix/var/nix/profiles/default $HOME/.nix-profile" unset PATH INFOPATH PKG_CONFIG_PATH PERL5LIB GST_PLUGIN_PATH KDEDIRS unset XDG_CONFIG_DIRS XDG_DATA_DIRS for i in $NIX_PROFILES; do # !!! reverse # We have to care not leaving an empty PATH element, because that means '.' to Linux - export PATH=$i/bin:$i/sbin${PATH:+:}$PATH + export PATH=$i/bin:$i/sbin:$i/lib/kde4/libexec${PATH:+:}$PATH export INFOPATH=$i/info:$i/share/info${INFOPATH:+:}$INFOPATH export PKG_CONFIG_PATH="$i/lib/pkgconfig${PKG_CONFIG_PATH:+:}$PKG_CONFIG_PATH" @@ -30,12 +30,15 @@ for i in $NIX_PROFILES; do # !!! reverse # from Nixpkgs <= 0.12. export PERL5LIB="$i/lib/perl5/site_perl:$i/lib/site_perl${PERL5LIB:+:}$PERL5LIB" + # ALSA plugins + export ALSA_PLUGIN_DIRS="$i/lib/alsa-lib${ALSA_PLUGIN_DIRS:+:}$ALSA_PLUGIN_DIRS" + # GStreamer. export GST_PLUGIN_PATH="$i/lib/gstreamer-0.10${GST_PLUGIN_PATH:+:}$GST_PLUGIN_PATH" # KDE/Gnome stuff. export KDEDIRS=$i${KDEDIRS:+:}$KDEDIRS - export QT_PLUGIN_PATH=$i/plugins:$i/lib/qt4/plugins${QT_PLUGIN_PATH:+:}$QT_PLUGIN_PATH + export QT_PLUGIN_PATH=$i/lib/qt4/plugins:$i/lib/kde4/plugins${QT_PLUGIN_PATH:+:}$QT_PLUGIN_PATH export XDG_CONFIG_DIRS=$i/etc/xdg${XDG_CONFIG_DIRS:+:}$XDG_CONFIG_DIRS export XDG_DATA_DIRS=$i/share${XDG_DATA_DIRS:+:}$XDG_DATA_DIRS done @@ -43,7 +46,7 @@ done # Search directory for Aspell dictionaries. -export ASPELL_CONF="dict-dir $NIX_USER_PROFILE_DIR/profile/lib/aspell" +export ASPELL_CONF="dict-dir $HOME/.nix-profile/lib/aspell" # ~/bin and the setuid wrappers override other bin directories. diff --git a/modules/security/policykit.nix b/modules/security/policykit.nix index 6d7b507d0337..39075dd760f1 100644 --- a/modules/security/policykit.nix +++ b/modules/security/policykit.nix @@ -51,7 +51,7 @@ in } ]; - system.activationScripts.policyKit = fullDepEntry + system.activationScripts.policyKit = stringAfter [ "users" ] '' mkdir -m 0770 -p /var/run/PolicyKit chown root.polkituser /var/run/PolicyKit @@ -63,7 +63,7 @@ in touch /var/lib/misc/PolicyKit.reload chmod 0664 /var/lib/misc/PolicyKit.reload chown polkituser.polkituser /var/lib/misc/PolicyKit.reload - '' [ "users" ]; + ''; }; diff --git a/modules/security/polkit.nix b/modules/security/polkit.nix index 0a8ff4c7ea2c..3723a621827b 100644 --- a/modules/security/polkit.nix +++ b/modules/security/polkit.nix @@ -27,12 +27,10 @@ in environment = { systemPackages = [ pkWrapper ]; pathsToLink = [ "/share/polkit-1" "/etc/polkit-1" ]; - etc = [ - { - source = "${config.system.path}/etc/polkit-1"; + etc = singleton + { source = "${config.system.path}/etc/polkit-1"; target = "polkit-1"; - } - ]; + }; }; services.dbus.packages = [ pkWrapper ]; @@ -41,18 +39,16 @@ in pam.services = [ { name = "polkit-1"; } ]; setuidPrograms = [ "pkexec" ]; - setuidOwners = [ - { - program = "polkit-agent-helper-1"; + setuidOwners = singleton + { program = "polkit-agent-helper-1"; owner = "root"; group = "root"; setuid = true; source = pkgs.polkit + "/" + pkWrapper.helper; - } - ]; + }; }; - system.activationScripts.polikit = pkgs.stringsWithDeps.noDepEntry + system.activationScripts.polkit = '' mkdir -p /var/lib/polkit-1/localauthority chmod 700 /var/lib/polkit-1{/localauthority,} diff --git a/modules/security/setuid-wrappers.nix b/modules/security/setuid-wrappers.nix index 3c4a08c16b70..a7238b9add5c 100644 --- a/modules/security/setuid-wrappers.nix +++ b/modules/security/setuid-wrappers.nix @@ -75,7 +75,7 @@ in config = { security.setuidPrograms = - [ "crontab" "fusermount" "wodim" "cdrdao" "growisofs" ]; + [ "fusermount" "wodim" "cdrdao" "growisofs" ]; system.activationScripts.setuid = let @@ -110,7 +110,7 @@ in chmod "u${if setuid then "+" else "-"}s,g${if setgid then "+" else "-"}s,${permissions}" ${wrapperDir}/${program} ''; - in pkgs.stringsWithDeps.fullDepEntry + in stringAfter [ "users" ] '' # Look in the system path and in the default profile for # programs to be wrapped. @@ -120,7 +120,7 @@ in mkdir -p ${wrapperDir} ${concatMapStrings makeSetuidWrapper setuidPrograms} - '' [ "defaultPath" "users" ]; + ''; }; diff --git a/modules/services/backup/hydra-mirror.nix b/modules/services/backup/hydra-mirror.nix new file mode 100644 index 000000000000..a328a9a159a3 --- /dev/null +++ b/modules/services/backup/hydra-mirror.nix @@ -0,0 +1,87 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + cfg = config.services.hydraChannelMirror ; + mirrorChannel = pkgs.fetchsvn { + url = https://svn.nixos.org/repos/nix/release/trunk/channels/mirror-channel.pl; + rev = 24132; + sha256 = "02xvswbbr2sj9k1wfraa0j9053vf6w88nhk15qwzs8nkm180n820"; + }; + cronjob = jobset : '' + ${cfg.period} root ENABLE_PATCHES=1 PATH=${config.environment.nix}/libexec/nix:$PATH perl -I${config.environment.nix}/libexec/nix ${mirrorChannel} ${cfg.hydraURL}/jobset/${jobset.project}/${jobset.jobset}/channel/latest ${cfg.dataDir}/channels/${jobset.relURL} ${cfg.dataDir}/nars ${cfg.mirrorURL}/nars ${cfg.dataDir}/patches ${cfg.mirrorURL}/patches ${if jobset.nixexprs == "" then "" else "${cfg.hydraURL}/job/${jobset.project}/${jobset.jobset}/${jobset.nixexprs}/latest/download-by-type/file/source-dist"} >> ${cfg.dataDir}/logs/${jobset.name}.log + ''; +in +{ + options = { + + services.hydraChannelMirror = { + + enable = mkOption { + default = false; + description = '' + Whether to enable Hydra channel mirroring. + ''; + }; + + period = mkOption { + default = "15 * * * *"; + description = '' + This option defines (in the format used by cron) when the + mirroring should occur. + ''; + }; + + jobsets = mkOption { + default = [ rec { name = "nixpkgs-unstable"; project = "nixpkgs"; jobset = "trunk"; nixexprs = "tarball"; relURL = "nixpkgs/channels/${name}"; } ]; + description = '' + List of jobsets to mirror. + ''; + }; + + hydraURL = mkOption { + default = "http://hydra.nixos.org"; + description = '' + Location (URL) of Hydra instance + ''; + }; + + mirrorURL = mkOption { + default = "http://nixos.org/releases"; + description = '' + Location (URL) of Hydra mirror + ''; + }; + + dataDir = mkOption { + default = "/data/hydra-mirror"; + description = '' + Location of Hydra mirror data + ''; + }; + }; + + }; + + config = mkIf cfg.enable { + + services.cron.systemCronJobs = map cronjob cfg.jobsets ; + + system.activationScripts.hydraChannelMirror = stringAfter [ "stdio" "users" ] + '' + mkdir -m 0755 -p ${cfg.dataDir} + mkdir -m 0755 -p ${cfg.dataDir}/nars + mkdir -m 0755 -p ${cfg.dataDir}/patches + mkdir -m 0755 -p ${cfg.dataDir}/channels + ln -fs ${cfg.dataDir}/nars ${cfg.dataDir}/channels/nars + ln -fs ${cfg.dataDir}/patches ${cfg.dataDir}/channels/patches + mkdir -m 0755 -p ${cfg.dataDir}/logs + ${concatMapStrings (j : '' + mkdir -m 0755 -p ${cfg.dataDir}/channels/${j.relURL} + '') cfg.jobsets} + ''; + + }; + +} diff --git a/modules/services/backup/mysql-backup.nix b/modules/services/backup/mysql-backup.nix index e06f2bb581da..b6d42b8782a1 100644 --- a/modules/services/backup/mysql-backup.nix +++ b/modules/services/backup/mysql-backup.nix @@ -1,7 +1,9 @@ -{pkgs, config, ...}: +{ config, pkgs, ... }: + +with pkgs.lib; let - inherit (pkgs.lib) mkOption mkIf singleton concatStrings; + inherit (pkgs) mysql gzip; location = config.services.mysqlBackup.location ; @@ -58,14 +60,15 @@ in }; config = mkIf config.services.mysqlBackup.enable { - services.cron = { - systemCronJobs = map mysqlBackupCron config.services.mysqlBackup.databases; - }; + + services.cron.systemCronJobs = map mysqlBackupCron config.services.mysqlBackup.databases; - system.activationScripts.mysqlBackup = pkgs.stringsWithDeps.fullDepEntry '' - mkdir -m 0700 -p ${config.services.mysqlBackup.location} - chown ${config.services.mysqlBackup.user} ${config.services.mysqlBackup.location} - '' [ "stdio" "defaultPath" "systemConfig" "users" ]; + system.activationScripts.mysqlBackup = stringAfter [ "stdio" "defaultPath" "systemConfig" "users" ] + '' + mkdir -m 0700 -p ${config.services.mysqlBackup.location} + chown ${config.services.mysqlBackup.user} ${config.services.mysqlBackup.location} + ''; + }; } diff --git a/modules/services/backup/postgresql-backup.nix b/modules/services/backup/postgresql-backup.nix index 61bafed7bfa4..edbbbdac635a 100644 --- a/modules/services/backup/postgresql-backup.nix +++ b/modules/services/backup/postgresql-backup.nix @@ -1,14 +1,16 @@ -{pkgs, config, ...}: +{ config, pkgs, ... }: + +with pkgs.lib; let - inherit (pkgs.lib) mkOption mkIf singleton concatStrings; inherit (pkgs) postgresql gzip; location = config.services.postgresqlBackup.location ; - postgresqlBackupCron = db : '' - ${config.services.postgresqlBackup.period} root ${postgresql}/bin/pg_dump ${db} | ${gzip}/bin/gzip -c > ${location}/${db}.gz - ''; + postgresqlBackupCron = db: + '' + ${config.services.postgresqlBackup.period} root ${postgresql}/bin/pg_dump ${db} | ${gzip}/bin/gzip -c > ${location}/${db}.gz + ''; in @@ -52,14 +54,13 @@ in }; config = mkIf config.services.postgresqlBackup.enable { - services.cron = { - systemCronJobs = map postgresqlBackupCron config.services.postgresqlBackup.databases; - }; + services.cron.systemCronJobs = map postgresqlBackupCron config.services.postgresqlBackup.databases; - system.activationScripts.postgresqlBackup = pkgs.stringsWithDeps.fullDepEntry '' - mkdir -m 0700 -p ${config.services.postgresqlBackup.location} - chown root ${config.services.postgresqlBackup.location} - '' [ "stdio" "defaultPath" "systemConfig" "users" ]; + system.activationScripts.postgresqlBackup = stringAfter [ "stdio" "defaultPath" "systemConfig" "users" ] + '' + mkdir -m 0700 -p ${config.services.postgresqlBackup.location} + chown root ${config.services.postgresqlBackup.location} + ''; }; } diff --git a/modules/services/backup/sitecopy-backup.nix b/modules/services/backup/sitecopy-backup.nix index 310a5e78b080..f30002b6ee86 100644 --- a/modules/services/backup/sitecopy-backup.nix +++ b/modules/services/backup/sitecopy-backup.nix @@ -1,7 +1,8 @@ -{pkgs, config, ...}: +{ config, pkgs, ... }: + +with pkgs.lib; let - inherit (pkgs.lib) mkOption mkIf singleton concatStrings; inherit (pkgs) sitecopy; stateDir = "/var/spool/sitecopy"; @@ -63,45 +64,41 @@ in config = mkIf config.services.sitecopy.enable { environment.systemPackages = [ sitecopy ]; - services.cron = { - systemCronJobs = map sitecopyCron config.services.sitecopy.backups; - }; + services.cron.systemCronJobs = map sitecopyCron config.services.sitecopy.backups; + system.activationScripts.sitecopyBackup = stringAfter [ "stdio" "systemConfig" "users" ] + '' + mkdir -m 0700 -p ${stateDir} + chown root ${stateDir} + touch ${stateDir}/sitecopy.secrets + chown root ${stateDir}/sitecopy.secrets - system.activationScripts.sitecopyBackup = - pkgs.stringsWithDeps.fullDepEntry '' - mkdir -m 0700 -p ${stateDir} - chown root ${stateDir} - touch ${stateDir}/sitecopy.secrets - chown root ${stateDir}/sitecopy.secrets - - ${pkgs.lib.concatStrings (map ( b: '' - unset secrets - unset secret - secrets=`grep '^${b.server}' ${stateDir}/sitecopy.secrets | head -1` - secret=($secrets) - cat > ${stateDir}/${b.name}.conf << EOF - site ${b.name} - server ${b.server} - protocol ${b.protocol} - username ''${secret[1]} - password ''${secret[2]} - local ${b.local} - remote ${b.remote} - symlinks ${b.symlinks} - ${if b.https then "http secure" else ""} - EOF - chmod 0600 ${stateDir}/${b.name}.conf - if ! test -e ${stateDir}/${b.name} ; then - echo " * Initializing sitecopy '${b.name}'" - ${sitecopy}/bin/sitecopy --storepath=${stateDir} --rcfile=${stateDir}/${b.name}.conf --initialize ${b.name} - else - echo " * Sitecopy '${b.name}' already initialized" - fi - '' ) config.services.sitecopy.backups - )} - - '' [ "stdio" "defaultPath" "systemConfig" "users" ] ; + ${pkgs.lib.concatStrings (map ( b: '' + unset secrets + unset secret + secrets=`grep '^${b.server}' ${stateDir}/sitecopy.secrets | head -1` + secret=($secrets) + cat > ${stateDir}/${b.name}.conf << EOF + site ${b.name} + server ${b.server} + protocol ${b.protocol} + username ''${secret[1]} + password ''${secret[2]} + local ${b.local} + remote ${b.remote} + symlinks ${b.symlinks} + ${if b.https then "http secure" else ""} + EOF + chmod 0600 ${stateDir}/${b.name}.conf + if ! test -e ${stateDir}/${b.name} ; then + echo " * Initializing sitecopy '${b.name}'" + ${sitecopy}/bin/sitecopy --storepath=${stateDir} --rcfile=${stateDir}/${b.name}.conf --initialize ${b.name} + else + echo " * Sitecopy '${b.name}' already initialized" + fi + '' ) config.services.sitecopy.backups + )} + ''; }; } diff --git a/modules/services/hardware/udev.nix b/modules/services/hardware/udev.nix index c3661e0c0b55..e84150d24927 100644 --- a/modules/services/hardware/udev.nix +++ b/modules/services/hardware/udev.nix @@ -38,7 +38,7 @@ let cp -v ${udev}/libexec/rules.d/*.rules $out/ # Set a reasonable $PATH for programs called by udev rules. - echo 'ENV{PATH}="${pkgs.coreutils}/bin:${pkgs.gnused}/bin:${pkgs.utillinux}/bin"' > $out/00-path.rules + echo 'ENV{PATH}="${udevPath}/bin:${udevPath}/sbin"' > $out/00-path.rules # Set the firmware search path so that the firmware.sh helper # called by 50-firmware.rules works properly. @@ -84,6 +84,15 @@ let #udev_log="debug" ''; + # Udev has a 512-character limit for ENV{PATH}, so create a symlink + # tree to work around this. + udevPath = pkgs.buildEnv { + name = "udev-path"; + paths = cfg.path; + pathsToLink = [ "/bin" "/sbin" ]; + ignoreCollisions = true; + }; + in { @@ -118,6 +127,15 @@ in ''; }; + path = mkOption { + default = []; + merge = mergeListOption; + description = '' + Packages added to the PATH environment variable when + executing programs from Udev rules. + ''; + }; + extraRules = mkOption { default = ""; example = '' @@ -159,7 +177,9 @@ in services.udev.extraRules = nixosRules; - services.udev.packages = [extraUdevRules]; + services.udev.packages = [ extraUdevRules ]; + + services.udev.path = [ pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.utillinux ]; jobs.udev = { startOn = "startup"; @@ -207,7 +227,7 @@ in initctl emit -n new-devices ''; }; - + }; } diff --git a/modules/services/mail/mail.nix b/modules/services/mail/mail.nix new file mode 100644 index 000000000000..bdf6b28ffbc7 --- /dev/null +++ b/modules/services/mail/mail.nix @@ -0,0 +1,33 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +{ + + ###### interface + + options = { + + services.mail = { + + sendmailSetuidWrapper = mkOption { + default = null; + description = '' + Configuration for the sendmail setuid wrwapper (like an element of + security.setuidOwners)"; + ''; + }; + + }; + + }; + + ###### implementation + + config = mkIf (config.services.mail.sendmailSetuidWrapper != null) { + + security.setuidOwners = [ config.services.mail.sendmailSetuidWrapper ]; + + }; + +} diff --git a/modules/services/mail/postfix.nix b/modules/services/mail/postfix.nix index 03c77885d069..3eda558f1c50 100644 --- a/modules/services/mail/postfix.nix +++ b/modules/services/mail/postfix.nix @@ -111,6 +111,11 @@ in default = false; description = "Whether to run the Postfix mail server."; }; + + setSendmail = mkOption { + default = true; + description = "Whether to set the system sendmail to postfix's."; + }; user = mkOption { default = "postfix"; @@ -254,10 +259,24 @@ in config = mkIf config.services.postfix.enable { - environment.etc = singleton - { source = "/var/postfix/conf"; - target = "postfix"; - }; + environment = { + etc = singleton + { source = "/var/postfix/conf"; + target = "postfix"; + }; + + # This makes comfortable for root to run 'postqueue' for example. + systemPackages = [ pkgs.postfix ]; + }; + + services.mail.sendmailSetuidWrapper = mkIf config.services.postfix.setSendmail { + program = "sendmail"; + source = "${pkgs.postfix}/bin/sendmail"; + owner = "nobody"; + group = "postdrop"; + setuid = false; + setgid = true; + }; users.extraUsers = singleton { name = user; diff --git a/modules/services/misc/folding-at-home.nix b/modules/services/misc/folding-at-home.nix new file mode 100644 index 000000000000..06223bc56e03 --- /dev/null +++ b/modules/services/misc/folding-at-home.nix @@ -0,0 +1,74 @@ +{ config, pkgs, ... }: +with pkgs.lib; +let + stateDir = "/var/lib/foldingathome"; + cfg = config.services.foldingAtHome; + fahUser = "foldingathome"; +in { + + ###### interface + + options = { + + services.foldingAtHome = { + + enable = mkOption { + default = false; + description = '' + Whether to enable the Folding@Home to use idle CPU time. + ''; + }; + + nickname = mkOption { + default = "Anonymous"; + description = '' + A unique handle for statistics. + ''; + }; + + config = mkOption { + default = ""; + description = '' + Extra configuration. Contents will be added verbatim to the + configuration file. + ''; + }; + + }; + + }; + + ###### implementation + + config = mkIf cfg.enable { + + users.extraUsers = singleton + { name = fahUser; + uid = config.ids.uids.foldingAtHome; + description = "Folding@Home user"; + home = stateDir; + }; + + jobs.foldingAtHome = + { name = "foldingathome"; + + startOn = "started network-interfaces"; + stopOn = "stopping network-interfaces"; + + preStart = + '' + mkdir -m 0755 -p ${stateDir} + chown ${fahUser} ${stateDir} + cp -f ${pkgs.writeText "client.cfg" cfg.config} ${stateDir}/client.cfg + ''; + exec = "${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${fahUser} -c 'cd ${stateDir}; ${pkgs.foldingathome}/bin/fah6'"; + }; + + services.foldingAtHome.config = '' + [settings] + username=${cfg.nickname} + ''; + + }; + +} \ No newline at end of file diff --git a/modules/services/misc/nix-daemon.nix b/modules/services/misc/nix-daemon.nix index a9a0bc70f1ec..2be7789cc5fa 100644 --- a/modules/services/misc/nix-daemon.nix +++ b/modules/services/misc/nix-daemon.nix @@ -277,7 +277,7 @@ in # do this, mount the remote file system on a subdirectory of # /var/run/nix/remote-stores. export NIX_OTHER_STORES=/var/run/nix/remote-stores/*/nix - '' + '' # */ + optionalString config.nix.distributedBuilds '' export NIX_BUILD_HOOK=${config.environment.nix}/libexec/nix/build-remote.pl export NIX_REMOTE_SYSTEMS=/etc/nix.machines @@ -292,6 +292,33 @@ in users.extraUsers = map makeNixBuildUser (pkgs.lib.range 1 config.nix.nrBuildUsers); + system.activationScripts.nix = stringAfter [ "etc" "users" ] + '' + # Set up Nix. + mkdir -p /nix/etc/nix + ln -sfn /etc/nix.conf /nix/etc/nix/nix.conf + chown root.nixbld /nix/store + chmod 1775 /nix/store + + # Nix initialisation. + mkdir -m 0755 -p \ + /nix/var/nix/gcroots \ + /nix/var/nix/temproots \ + /nix/var/nix/manifests \ + /nix/var/nix/userpool \ + /nix/var/nix/profiles \ + /nix/var/nix/db \ + /nix/var/log/nix/drvs \ + /nix/var/nix/channel-cache \ + /nix/var/nix/chroots + mkdir -m 1777 -p /nix/var/nix/gcroots/per-user + mkdir -m 1777 -p /nix/var/nix/profiles/per-user + mkdir -m 1777 -p /nix/var/nix/gcroots/tmp + + ln -sf /nix/var/nix/profiles /nix/var/nix/gcroots/ + ln -sf /nix/var/nix/manifests /nix/var/nix/gcroots/ + ''; + }; } diff --git a/modules/services/monitoring/systemhealth.nix b/modules/services/monitoring/systemhealth.nix index 8d531b526f3a..85f297cfb71b 100644 --- a/modules/services/monitoring/systemhealth.nix +++ b/modules/services/monitoring/systemhealth.nix @@ -75,43 +75,44 @@ in config = mkIf cfg.enable { services.cron.systemCronJobs = [ cronJob ]; - system.activationScripts.systemhealth = fullDepEntry '' - mkdir -p ${rrdDir} ${htmlDir} - chown wwwrun.wwwrun ${rrdDir} ${htmlDir} + system.activationScripts.systemhealth = stringAfter [ "var" ] + '' + mkdir -p ${rrdDir} ${htmlDir} + chown wwwrun.wwwrun ${rrdDir} ${htmlDir} - cat >${configFile} << EOF - [paths] - rrdtool = ${pkgs.rrdtool}/bin/rrdtool - loadavg_rrd = loadavg - ps = /var/run/current-system/sw/bin/ps - df = /var/run/current-system/sw/bin/df - meminfo_rrd = meminfo - uptime_rrd = uptime - rrd_path = ${rrdDir} - png_path = ${htmlDir} + cat >${configFile} << EOF + [paths] + rrdtool = ${pkgs.rrdtool}/bin/rrdtool + loadavg_rrd = loadavg + ps = /var/run/current-system/sw/bin/ps + df = /var/run/current-system/sw/bin/df + meminfo_rrd = meminfo + uptime_rrd = uptime + rrd_path = ${rrdDir} + png_path = ${htmlDir} - [processes] + [processes] - [interfaces] - ${interfacesSection} + [interfaces] + ${interfacesSection} - [drives] - ${drivesSection} + [drives] + ${drivesSection} - [graphs] - width = 400 - time = ['-3hours', '-32hours', '-8days', '-5weeks', '-13months'] - height = 100 + [graphs] + width = 400 + time = ['-3hours', '-32hours', '-8days', '-5weeks', '-13months'] + height = 100 - [external] + [external] - EOF + EOF - chown wwwrun.wwwrun ${configFile} + chown wwwrun.wwwrun ${configFile} - ${pkgs.su}/bin/su -s "/bin/sh" -c "${command} --check" wwwrun - ${pkgs.su}/bin/su -s "/bin/sh" -c "${command} --html" wwwrun - '' [ "var" ]; + ${pkgs.su}/bin/su -s "/bin/sh" -c "${command} --check" wwwrun + ${pkgs.su}/bin/su -s "/bin/sh" -c "${command} --html" wwwrun + ''; services.httpd.extraSubservices = [ { function = f: { diff --git a/modules/services/networking/amuled.nix b/modules/services/networking/amuled.nix new file mode 100644 index 000000000000..f499e72c0d2b --- /dev/null +++ b/modules/services/networking/amuled.nix @@ -0,0 +1,71 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + cfg = config.services.amule; + user = if cfg.user != null then cfg.user else "amule"; +in + +{ + + ###### interface + + options = { + + services.amule = { + + enable = mkOption { + default = false; + description = '' + Whether to run the AMule daemon. You need to manually run "amuled --ec-config" to configure the service for the first time. + ''; + }; + + dataDir = mkOption { + default = ''/home/${user}/''; + description = '' + The directory holding configuration, incoming and temporary files. + ''; + }; + + user = mkOption { + default = null; + description = '' + The user the AMule daemon should run as. + ''; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + users.extraUsers = mkIf (cfg.user == null) [ + { name = "amule"; + description = "AMule daemon"; + } ]; + + jobs.amuled = + { description = "AMule daemon"; + + startOn = "ip-up"; + + preStart = '' + mkdir -p ${cfg.dataDir} + chown ${user} ${cfg.dataDir} + ''; + + exec = '' + ${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${user} \ + -c 'HOME="${cfg.dataDir}" ${pkgs.amuleDaemon}/bin/amuled' + ''; + }; + + }; + +} diff --git a/modules/services/networking/avahi-daemon.nix b/modules/services/networking/avahi-daemon.nix index 369b6d4f0fca..0ca9869db0b4 100644 --- a/modules/services/networking/avahi-daemon.nix +++ b/modules/services/networking/avahi-daemon.nix @@ -81,12 +81,6 @@ in Whether to enable the mDNS NSS (Name Service Switch) plug-in. Enabling it allows applications to resolve names in the `.local' domain by transparently querying the Avahi daemon. - - Warning: Currently, enabling this option breaks DNS lookups after - a `nixos-rebuild'. This is because `/etc/nsswitch.conf' is - updated to use `nss-mdns' but `libnss_mdns' is not in - applications' `LD_LIBRARY_PATH'. The next time `/etc/profile' is - sourced, it will set up an appropriate `LD_LIBRARY_PATH', though. ''; }; @@ -130,7 +124,7 @@ in mkdir -p /var/run/avahi-daemon - exec ${avahi}/sbin/avahi-daemon --daemonize -f "${avahiDaemonConf}" + exec ${avahi}/sbin/avahi-daemon --syslog -f "${avahiDaemonConf}" ''; }; diff --git a/modules/services/networking/dhclient.nix b/modules/services/networking/dhclient.nix index 7b334a8e51e2..bd3f781c19a5 100644 --- a/modules/services/networking/dhclient.nix +++ b/modules/services/networking/dhclient.nix @@ -78,9 +78,13 @@ in for i in $(cd /sys/class/net && ls -d *); do # Only run dhclient on interfaces of type ARPHRD_ETHER - # (1), i.e. Ethernet. - if [ "$(cat /sys/class/net/$i/type)" = 1 ]; then - if ! for j in ${toString ignoredInterfaces}; do echo $j; done | grep -F -x -q "$i"; then + # (1), i.e. Ethernet. Ignore peth* devices; on Xen, + # they're renamed physical Ethernet cards used for + # bridging. + if [ "$(cat /sys/class/net/$i/type)" = 1 ]; then + if ! for j in ${toString ignoredInterfaces}; do echo $j; done | grep -F -x -q "$i" && + ! echo "$i" | grep -x -q "peth.*"; + then echo "Running dhclient on $i" interfaces="$interfaces $i" fi diff --git a/modules/services/networking/ntpd.nix b/modules/services/networking/ntpd.nix index a50229125d19..f0b96951eb17 100644 --- a/modules/services/networking/ntpd.nix +++ b/modules/services/networking/ntpd.nix @@ -20,7 +20,7 @@ let # chroot to ${stateDir}, we have to specify it as /ntp.drift. driftfile /ntp.drift - ${toString (map (server: "server " + server + "\n") servers)} + ${toString (map (server: "server " + server + " iburst\n") servers)} ''; ntpFlags = "-c ${configFile} -u ${ntpUser}:nogroup -i ${stateDir}"; diff --git a/modules/services/networking/quassel.nix b/modules/services/networking/quassel.nix index d4795f3b57d2..916694c69109 100644 --- a/modules/services/networking/quassel.nix +++ b/modules/services/networking/quassel.nix @@ -3,8 +3,9 @@ with pkgs.lib; let - quassel = pkgs.quassel.override { daemon = true; monolithic = false; client = false; }; + quassel = pkgs.quasselDaemon; cfg = config.services.quassel; + user = if cfg.user != null then cfg.user else "quassel"; in { @@ -38,22 +39,17 @@ in ''; }; - logFile = mkOption { - default = "/var/log/quassel.log"; - description = "Location of the logfile of the Quassel daemon."; - }; - dataDir = mkOption { - default = ''/home/${cfg.user}/.config/quassel-irc.org''; + default = ''/home/${user}/.config/quassel-irc.org''; description = '' The directory holding configuration files, the SQlite database and the SSL Cert. ''; }; user = mkOption { - default = "quassel"; + default = null; description = '' - The user the Quassel daemon should run as. + The existing user the Quassel daemon should run as. If left empty, a default "quassel" user will be created. ''; }; @@ -66,10 +62,10 @@ in config = mkIf cfg.enable { - users.extraUsers = singleton - { name = cfg.user; + users.extraUsers = mkIf (cfg.user == null) [ + { name = "quassel"; description = "Quassel IRC client daemon"; - }; + }]; jobs.quassel = @@ -79,19 +75,16 @@ in preStart = '' mkdir -p ${cfg.dataDir} - chown ${cfg.user} ${cfg.dataDir} - touch ${cfg.logFile} && chown ${cfg.user} ${cfg.logFile} + chown ${user} ${cfg.dataDir} ''; exec = '' - ${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${cfg.user} \ + ${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${user} \ -c '${quassel}/bin/quasselcore --listen=${cfg.interface}\ - --port=${toString cfg.portNumber} --configdir=${cfg.dataDir} --logfile=${cfg.logFile}' + --port=${toString cfg.portNumber} --configdir=${cfg.dataDir}' ''; }; - environment.systemPackages = [ quassel ]; - }; } diff --git a/modules/services/printing/cupsd.nix b/modules/services/printing/cupsd.nix index 8599512a5f59..ebc0215d06de 100644 --- a/modules/services/printing/cupsd.nix +++ b/modules/services/printing/cupsd.nix @@ -134,10 +134,7 @@ in startOn = "started network-interfaces"; stopOn = "stopping network-interfaces"; - environment = { - # Cups scripts for printing (psto...) require awk, sed, grep, ... - PATH = "${config.system.path}/bin"; - }; + path = [ config.system.path ]; preStart = '' diff --git a/modules/services/scheduling/atd.nix b/modules/services/scheduling/atd.nix index 3c3aca6f5a24..8f6d1667bdb3 100644 --- a/modules/services/scheduling/atd.nix +++ b/modules/services/scheduling/atd.nix @@ -66,7 +66,7 @@ in jobs.atd = { description = "at daemon (atd)"; - startOn = "started udev"; + startOn = "stopped udevtrigger"; preStart = '' @@ -99,7 +99,9 @@ in fi ''; - exec = "${at}/sbin/atd -f"; + exec = "${at}/sbin/atd"; + + daemonType = "fork"; }; }; diff --git a/modules/services/scheduling/cron.nix b/modules/services/scheduling/cron.nix index e769caefdf59..555cde928760 100644 --- a/modules/services/scheduling/cron.nix +++ b/modules/services/scheduling/cron.nix @@ -15,6 +15,13 @@ let NIX_CONF_DIR=/nix/etc/nix ${pkgs.lib.concatStrings (map (job: job + "\n") config.services.cron.systemCronJobs)} ''; + + # Vixie cron requires build-time configuration for the sendmail path. + cronNixosPkg = pkgs.cron.override { + # The mail.nix nixos module, if there is any local mail system enabled, + # should have sendmail in this path. + sendmailPath = "/var/setuid-wrappers/sendmail"; + }; in @@ -26,6 +33,11 @@ in services.cron = { + enable = mkOption { + default = true; + description = "Whether to enable the `vixie cron' daemon."; + }; + mailto = mkOption { default = ""; description = " The job output will be mailed to this email address. "; @@ -46,6 +58,10 @@ in If neither /var/cron/cron.deny nor /var/cron/cron.allow exist only root will is allowed to have its own crontab file. The /var/cron/cron.deny file is created automatically for you. So every user can use a crontab. + + Many nixos modules set systemCronJobs, so if you decide to disable vixie cron + and enable another cron daemon, you may want it to get its system crontab + based on systemCronJobs. ''; }; @@ -56,7 +72,7 @@ in ###### implementation - config = { + config = mkIf config.services.cron.enable { environment.etc = singleton # The system-wide crontab. @@ -65,7 +81,9 @@ in mode = "0600"; # Cron requires this. }; - environment.systemPackages = [pkgs.cron]; + security.setuidPrograms = [ "crontab" ]; + + environment.systemPackages = [ cronNixosPkg ]; jobs.cron = { description = "Cron daemon"; @@ -86,7 +104,7 @@ in fi ''; - exec = "${pkgs.cron}/sbin/cron -n"; + exec = "${cronNixosPkg}/sbin/cron -n"; }; }; diff --git a/modules/services/scheduling/fcron.nix b/modules/services/scheduling/fcron.nix index f217449cf0c8..5bff33b3e274 100644 --- a/modules/services/scheduling/fcron.nix +++ b/modules/services/scheduling/fcron.nix @@ -4,20 +4,17 @@ with pkgs.lib; let - # Put all the system cronjobs together. - # TODO allow using fcron only.. - #systemCronJobs = - # config.services.cron.systemCronJobs; cfg = config.services.fcron; queuelen = if cfg.queuelen == "" then "" else "-q ${toString cfg.queuelen}"; - # shell is set to /sh in config.. - # ${pkgs.lib.concatStrings (map (job: job + "\n") systemCronJobs)} - systemCronJobsFile = pkgs.writeText "fcron-systab" + systemCronJobsFile = pkgs.writeText "system-crontab" '' - SHELL=${pkgs.bash}/bin/sh - PATH=${pkgs.coreutils}/bin:${pkgs.findutils}/bin:${pkgs.gnused}/bin + SHELL=${pkgs.bash}/bin/bash + PATH=${config.system.path}/bin:${config.system.path}/sbin + MAILTO="${config.services.cron.mailto}" + NIX_CONF_DIR=/nix/etc/nix + ${pkgs.lib.concatStrings (map (job: job + "\n") config.services.cron.systemCronJobs)} ''; allowdeny = target: users: @@ -42,7 +39,7 @@ in }; allow = mkOption { - default = []; + default = [ "all" ]; description = '' Users allowed to use fcrontab and fcrondyn (one name per line, "all" for everyone). ''; @@ -64,7 +61,7 @@ in }; systab = mkOption { - default = ""; + default = systemCronJobsFile; description = ''The "system" crontab contents.''; }; }; @@ -77,7 +74,7 @@ in config = mkIf cfg.enable { environment.etc = - [ (allowdeny "allow" (["root"] ++ cfg.allow)) + [ (allowdeny "allow" (cfg.allow)) (allowdeny "deny" cfg.deny) # see man 5 fcron.conf { source = pkgs.writeText "fcon.conf" '' @@ -97,6 +94,8 @@ in environment.systemPackages = [ pkgs.fcron ]; + security.setuidPrograms = [ "fcrontab" ]; + jobs.fcron = { description = "fcron daemon"; diff --git a/modules/services/security/tor.nix b/modules/services/security/tor.nix index d3fceae3608e..65b7abafd6a2 100644 --- a/modules/services/security/tor.nix +++ b/modules/services/security/tor.nix @@ -27,40 +27,6 @@ in services.tor = { - enable = mkOption { - default = false; - description = '' - Whether to enable the Tor anonymous routing daemon. - ''; - }; - - enableClient = mkOption { - default = true; - description = '' - Whether to enable Tor daemon to route application connections. - You might want to disable this if you plan running a dedicated Tor relay. - ''; - }; - - socksListenAddress = mkOption { - default = "127.0.0.1:9050"; - example = "127.0.0.1:9050, 192.168.0.1:9100"; - description = '' - Bind to this address(es) to listen for connections from Socks-speaking - applications. You can also specify a port. - ''; - }; - - socksPolicy = mkOption { - default = ""; - example = "accept 192.168.0.0/16, reject *"; - description = '' - Entry policies to allow/deny SOCKS requests based on IP address. - First entry that matches wins. If no SocksPolicy is set, we accept - all (and only) requests from SocksListenAddress. - ''; - }; - config = mkOption { default = ""; description = '' @@ -69,141 +35,180 @@ in ''; }; - enablePrivoxy = mkOption { - default = true; - description = '' - Whether to enable a special instance of privoxy dedicated to Tor. - To have anonymity, protocols need to be scrubbed of identifying - information. - Most people using Tor want to anonymize their web traffic, so by - default we enable an special instance of privoxy specifically for - Tor. - However, if you are only going to use Tor only as a relay then you - can disable this option. - ''; - }; - - privoxyListenAddress = mkOption { - default = "127.0.0.1:8118"; - description = '' - Address that Tor's instance of privoxy is listening to. - *This does not configure the standard NixOS instance of privoxy.* - This is for Tor connections only! - See services.privoxy.listenAddress to configure the standard NixOS - instace of privoxy. - ''; + client = { + + enable = mkOption { + default = false; + description = '' + Whether to enable Tor daemon to route application connections. + You might want to disable this if you plan running a dedicated Tor relay. + ''; + }; + + socksListenAddress = mkOption { + default = "127.0.0.1:9050"; + example = "192.168.0.1:9100"; + description = '' + Bind to this address to listen for connections from Socks-speaking + applications. + ''; + }; + + socksPolicy = mkOption { + default = ""; + example = "accept 192.168.0.0/16, reject *"; + description = '' + Entry policies to allow/deny SOCKS requests based on IP address. + First entry that matches wins. If no SocksPolicy is set, we accept + all (and only) requests from SocksListenAddress. + ''; + }; + + privoxy = { + + enable = mkOption { + default = true; + description = '' + Whether to enable a special instance of privoxy dedicated to Tor. + To have anonymity, protocols need to be scrubbed of identifying + information. + Most people using Tor want to anonymize their web traffic, so by + default we enable an special instance of privoxy specifically for + Tor. + However, if you are only going to use Tor only for other kinds of + traffic then you can disable this option. + ''; + }; + + listenAddress = mkOption { + default = "127.0.0.1:8118"; + description = '' + Address that Tor's instance of privoxy is listening to. + *This does not configure the standard NixOS instance of privoxy.* + This is for Tor connections only! + See services.privoxy.listenAddress to configure the standard NixOS + instace of privoxy. + ''; + }; + + config = mkOption { + default = ""; + description = '' + Extra configuration for Tor's instance of privoxy. Contents will be + added verbatim to the configuration file. + *This does not configure the standard NixOS instance of privoxy.* + This is for Tor connections only! + See services.privoxy.extraConfig to configure the standard NixOS + instace of privoxy. + ''; + }; + + }; + }; - privoxyConfig = mkOption { - default = ""; - description = '' - Extra configuration for Tor's instance of privoxy. Contents will be - added verbatim to the configuration file. - *This does not configure the standard NixOS instance of privoxy.* - This is for Tor connections only! - See services.privoxy.extraConfig to configure the standard NixOS - instace of privoxy. - ''; - }; + relay = { - enableRelay = mkOption { - default = false; - description = '' - Whether to enable relaying traffic for others. + enable = mkOption { + default = false; + description = '' + Whether to enable relaying TOR traffic for others. - See https://www.torproject.org/docs/tor-doc-relay for details. - ''; - }; + See https://www.torproject.org/docs/tor-doc-relay for details. + ''; + }; - isBridgeRelay = mkOption { - default = false; - description = '' - Bridge relays (or "bridges" ) are Tor relays that aren't listed in the - main directory. Since there is no complete public list of them, even if an - ISP is filtering connections to all the known Tor relays, they probably - won't be able to block all the bridges. + isBridge = mkOption { + default = false; + description = '' + Bridge relays (or "bridges" ) are Tor relays that aren't listed in the + main directory. Since there is no complete public list of them, even if an + ISP is filtering connections to all the known Tor relays, they probably + won't be able to block all the bridges. - A bridge relay can't be an exit relay. + A bridge relay can't be an exit relay. - You need to set enableRelay to true for this option to take effect. + You need to set enableRelay to true for this option to take effect. - See https://www.torproject.org/bridges.html.en for more info. - ''; - }; + See https://www.torproject.org/bridges.html.en for more info. + ''; + }; - isExitRelay = mkOption { - default = false; - description = '' - An exit relay allows Tor users to access regular Internet services. + isExit = mkOption { + default = false; + description = '' + An exit relay allows Tor users to access regular Internet services. - Unlike running a non-exit relay, running an exit relay may expose - you to abuse complaints. See https://www.torproject.org/faq.html.en#ExitPolicies for more info. + Unlike running a non-exit relay, running an exit relay may expose + you to abuse complaints. See https://www.torproject.org/faq.html.en#ExitPolicies for more info. - You can specify which services Tor users may access via your exit relay using exitPolicy option. - ''; - }; + You can specify which services Tor users may access via your exit relay using exitPolicy option. + ''; + }; - nickname = mkOption { - default = "anonymous"; - description = '' - A unique handle for your TOR relay. - ''; - }; + nickname = mkOption { + default = "anonymous"; + description = '' + A unique handle for your TOR relay. + ''; + }; - relayBandwidthRate = mkOption { - default = 0; - example = 100; - description = '' - Specify this to limit the bandwidth usage of relayed (server) - traffic. Your own traffic is still unthrottled. Units: kilobytes/second. - ''; - }; + bandwidthRate = mkOption { + default = 0; + example = 100; + description = '' + Specify this to limit the bandwidth usage of relayed (server) + traffic. Your own traffic is still unthrottled. Units: bytes/second. + ''; + }; - relayBandwidthBurst = mkOption { - default = 0; - example = 200; - description = '' - Specify this to allow bursts of the bandwidth usage of relayed (server) - traffic. The average usage will still be as specified in relayBandwidthRate. - Your own traffic is still unthrottled. Units: kilobytes/second. - ''; - }; + bandwidthBurst = mkOption { + default = cfg.relay.bandwidthRate; + example = 200; + description = '' + Specify this to allow bursts of the bandwidth usage of relayed (server) + traffic. The average usage will still be as specified in relayBandwidthRate. + Your own traffic is still unthrottled. Units: bytes/second. + ''; + }; - relayPort = mkOption { - default = 9001; - description = '' - What port to advertise for Tor connections. - ''; - }; + port = mkOption { + default = 9001; + description = '' + What port to advertise for Tor connections. + ''; + }; - relayListenAddress = mkOption { - default = ""; - example = "0.0.0.0:9090"; - description = '' - Set this if you need to listen on a port other than the one advertised - in relayPort (e.g. to advertise 443 but bind to 9090). You'll need to do - ipchains or other port forwarding yourself to make this work. - ''; - }; + listenAddress = mkOption { + default = ""; + example = "0.0.0.0:9090"; + description = '' + Set this if you need to listen on a port other than the one advertised + in relayPort (e.g. to advertise 443 but bind to 9090). You'll need to do + ipchains or other port forwsarding yourself to make this work. + ''; + }; - exitPolicy = mkOption { - default = ""; - example = "accept *:6660-6667,reject *:*"; - description = '' - A comma-separated list of exit policies. They're considered first - to last, and the first match wins. If you want to _replace_ - the default exit policy, end this with either a reject *:* or an - accept *:*. Otherwise, you're _augmenting_ (prepending to) the - default exit policy. Leave commented to just use the default, which is - available in the man page or at https://www.torproject.org/documentation.html + exitPolicy = mkOption { + default = ""; + example = "accept *:6660-6667,reject *:*"; + description = '' + A comma-separated list of exit policies. They're considered first + to last, and the first match wins. If you want to _replace_ + the default exit policy, end this with either a reject *:* or an + accept *:*. Otherwise, you're _augmenting_ (prepending to) the + default exit policy. Leave commented to just use the default, which is + available in the man page or at https://www.torproject.org/documentation.html - Look at https://www.torproject.org/faq-abuse.html#TypicalAbuses - for issues you might encounter if you use the default exit policy. + Look at https://www.torproject.org/faq-abuse.html#TypicalAbuses + for issues you might encounter if you use the default exit policy. + + If certain IPs and ports are blocked externally, e.g. by your firewall, + you should update your exit policy to reflect this -- otherwise Tor + users will be told that those destinations are down. + ''; + }; - If certain IPs and ports are blocked externally, e.g. by your firewall, - you should update your exit policy to reflect this -- otherwise Tor - users will be told that those destinations are down. - ''; }; }; @@ -213,14 +218,10 @@ in ###### implementation - config = mkIf cfg.enable { - environment.systemPackages = [ tor ]; # provides tor-resolve and torify + config = mkIf (cfg.client.enable || cfg.relay.enable) { - assertions = [{ - assertion = cfg.enableRelay || cfg.enableClient; - message = "Need to either enable TOR client or relay functionality"; - } { - assertion = cfg.enableRelay -> !(cfg.isBridgeRelay && cfg.isExitRelay); + assertions = [ { + assertion = cfg.relay.enable -> !(cfg.relay.isBridge && cfg.relay.isExit); message = "Can't be both an exit and a bridge relay at the same time"; } ]; @@ -231,60 +232,57 @@ in home = stateDir; }; - jobs.tor = - { name = "tor"; + jobs = { + tor = { name = "tor"; - startOn = "started network-interfaces"; - stopOn = "stopping network-interfaces"; + startOn = "started network-interfaces"; + stopOn = "stopping network-interfaces"; - preStart = - '' - mkdir -m 0755 -p ${stateDir} - chown ${torUser} ${stateDir} - ''; - exec = "${tor}/bin/tor -f ${pkgs.writeText "torrc" cfg.config}"; - }; + preStart = '' + mkdir -m 0755 -p ${stateDir} + chown ${torUser} ${stateDir} + ''; + exec = "${tor}/bin/tor -f ${pkgs.writeText "torrc" cfg.config}"; + }; } + // optionalAttrs (cfg.client.privoxy.enable && cfg.client.enable) { + torPrivoxy = { name = "tor-privoxy"; - jobs.torPrivoxy = mkIf (cfg.enablePrivoxy && cfg.enableClient) - { name = "tor-privoxy"; + startOn = "starting tor"; + stopOn = "stopping tor"; - startOn = "starting tor"; - stopOn = "stopping tor"; + preStart = '' + mkdir -m 0755 -p ${privoxyDir} + chown ${torUser} ${privoxyDir} - preStart = - '' - mkdir -m 0755 -p ${privoxyDir} - chown ${torUser} ${privoxyDir} - - # Needed to run privoxy as an unprivileged user? - ${modprobe}/sbin/modprobe capability || true - ''; - exec = "${privoxy}/sbin/privoxy --no-daemon --user ${torUser} ${pkgs.writeText "torPrivoxy.conf" cfg.privoxyConfig}"; - }; + # Needed to run privoxy as an unprivileged user? + ${modprobe}/sbin/modprobe capability || true + ''; + exec = "${privoxy}/sbin/privoxy --no-daemon --user ${torUser} ${pkgs.writeText "torPrivoxy.conf" cfg.client.privoxy.config}"; + }; }; services.tor.config = '' DataDirectory ${stateDir} User ${torUser} '' - + optionalString cfg.enableClient '' - SocksListenAddress ${cfg.socksListenAddress} - ${opt "SocksPolicy" cfg.socksPolicy} + + optionalString cfg.client.enable '' + SocksListenAddress ${cfg.client.socksListenAddress} + ${opt "SocksPolicy" cfg.client.socksPolicy} '' - + optionalString cfg.enableRelay '' - ORPort ${toString cfg.relayPort} - ${opt "ORListenAddress" cfg.relayListenAddress } - ${opt "Nickname" cfg.nickname} - ${optint "RelayBandwidthRate" cfg.relayBandwidthRate} - ${optint "RelayBandwidthBurst" cfg.relayBandwidthBurst} - ${if cfg.isExitRelay then opt "ExitPolicy" cfg.exitPolicy else "ExitPolicy reject *:*"} - ${if cfg.isBridgeRelay then "BridgeRelay 1" else ""} + + optionalString cfg.relay.enable '' + ORPort ${toString cfg.relay.port} + ${opt "ORListenAddress" cfg.relay.listenAddress } + ${opt "Nickname" cfg.relay.nickname} + ${optint "RelayBandwidthRate" cfg.relay.bandwidthRate} + ${optint "RelayBandwidthBurst" cfg.relay.bandwidthBurst} + ${if cfg.relay.isExit then opt "ExitPolicy" cfg.relay.exitPolicy else "ExitPolicy reject *:*"} + ${if cfg.relay.isBridge then "BridgeRelay 1" else ""} ''; - services.tor.privoxyConfig = '' + services.tor.client.privoxy.config = '' # Generally, this file goes in /etc/privoxy/config # # Tor listens as a SOCKS4a proxy here: - forward-socks4a / ${cfg.socksListenAddress} . + forward-socks4a / ${cfg.client.socksListenAddress} . confdir ${privoxy}/etc logdir ${privoxyDir} # actionsfile standard # Internal purpose, recommended @@ -300,7 +298,7 @@ in debug 8192 # Errors - *we highly recommended enabling this* user-manual ${privoxy}/doc/privoxy/user-manual - listen-address ${cfg.privoxyListenAddress} + listen-address ${cfg.client.privoxy.listenAddress} toggle 1 enable-remote-toggle 0 enable-edit-actions 0 diff --git a/modules/services/security/torsocks.nix b/modules/services/security/torsocks.nix new file mode 100644 index 000000000000..5257327b384e --- /dev/null +++ b/modules/services/security/torsocks.nix @@ -0,0 +1,72 @@ +{ config, pkgs, ... }: +with pkgs.lib; +let + + cfg = config.services.tor; + + torsocks = pkgs.writeTextFile { + name = "torsocks"; + text = '' + #!${pkgs.stdenv.shell} + TORSOCKS_CONF_FILE=${pkgs.writeText "torsocks.conf" cfg.torsocks.config} LD_PRELOAD="${pkgs.torsocks}/lib/torsocks/libtorsocks.so $LD_PRELOAD" $@ + ''; + executable = true; + destination = "/bin/torsocks"; + }; + +in + +{ + + ###### interface + + options = { + + services.tor.torsocks = { + + enable = mkOption { + default = cfg.client.enable; + description = '' + Whether to build torsocks scipt to relay application traffic via TOR. + ''; + }; + + server = mkOption { + default = cfg.client.socksListenAddress; + example = "192.168.0.20"; + description = '' + IP address of TOR client to use. + ''; + }; + + config = mkOption { + default = ""; + description = '' + Extra configuration. Contents will be added verbatim to torsocks + configuration file. + ''; + }; + + }; + + }; + + ###### implementation + + config = mkIf cfg.torsocks.enable { + + environment.systemPackages = [ torsocks ]; # expose it to the users + + services.tor.torsocks.config = '' + server = ${toString(head (splitString ":" cfg.torsocks.server))} + server_port = ${toString(tail (splitString ":" cfg.torsocks.server))} + + local = 127.0.0.0/255.128.0.0 + local = 127.128.0.0/255.192.0.0 + local = 169.254.0.0/255.255.0.0 + local = 172.16.0.0/255.240.0.0 + local = 192.168.0.0/255.255.0.0 + ''; + }; + +} diff --git a/modules/services/web-servers/apache-httpd/mercurial.nix b/modules/services/web-servers/apache-httpd/mercurial.nix new file mode 100644 index 000000000000..d2d9e66d4f84 --- /dev/null +++ b/modules/services/web-servers/apache-httpd/mercurial.nix @@ -0,0 +1,77 @@ +{ config, pkgs, serverInfo, servicesPath, ... }: + +let + inherit (pkgs) mercurial; + inherit (pkgs.lib) mkOption; + + urlPrefix = config.urlPrefix; + + cgi = pkgs.stdenv.mkDerivation { + name = "mercurial-cgi"; + buildCommand = '' + ensureDir $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 " + [collections] + ${config.dataDir} = ${config.dataDir} + [web] + style = gitweb + allow_push = * + " > $out/hgweb.config + ''; + }; + +in { + + extraConfig = '' + RewriteEngine on + RewriteRule /(.*) ${cgi}/hgweb.cgi/$1 + + + AuthType Basic + AuthName "Mercurial repositories" + AuthUserFile ${config.dataDir}/hgusers + + Require valid-user + + + + Order allow,deny + Allow from all + AllowOverride All + Options ExecCGI + AddHandler cgi-script .cgi + PassEnv PYTHONPATH + + ''; + + robotsEntries = '' + User-agent: * + Disallow: ${urlPrefix} + ''; + + extraServerPath = [ + (pkgs.python+"/bin") + ]; + + globalEnvVars = [ { name = "PYTHONPATH"; value = "${mercurial}/lib/${pkgs.python.libPrefix}/site-packages"; } ]; + + options = { + urlPrefix = mkOption { + default = "/hg"; + description = " + The URL prefix under which the Mercurial service appears. + Use the empty string to have it appear in the server root. + "; + }; + + dataDir = mkOption { + example = "/data/mercurial"; + description = " + Path to the directory that holds the repositories. + "; + }; + }; + +} diff --git a/modules/services/web-servers/apache-httpd/twiki.nix b/modules/services/web-servers/apache-httpd/twiki.nix index e55197ade67e..dca92062fa8a 100644 --- a/modules/services/web-servers/apache-httpd/twiki.nix +++ b/modules/services/web-servers/apache-httpd/twiki.nix @@ -20,7 +20,7 @@ let defaultUrlHost = ""; # Build the TWiki CGI and configuration files. - twikiRoot = (import /etc/nixos/services/twiki/twiki-instance.nix).twiki { + twikiRoot = (import /etc/nixos/services/twiki/twiki-instance.nix { inherit pkgs; }).twiki { name = "wiki-instance"; pubdir = pubDir; datadir = dataDir; @@ -143,4 +143,4 @@ in { }; -} \ No newline at end of file +} diff --git a/modules/services/web-servers/tomcat.nix b/modules/services/web-servers/tomcat.nix index baf05e06a09c..e63abfb15d27 100644 --- a/modules/services/web-servers/tomcat.nix +++ b/modules/services/web-servers/tomcat.nix @@ -282,7 +282,7 @@ in mkdir -p ${cfg.baseDir}/work chown ${cfg.user}:${cfg.group} ${cfg.baseDir}/work - ${if cfg.axis2.enable == true then + ${if cfg.axis2.enable then '' # Copy the Axis2 web application cp -av ${pkgs.axis2}/webapps/axis2 ${cfg.baseDir}/webapps diff --git a/modules/services/x11/desktop-managers/kde4.nix b/modules/services/x11/desktop-managers/kde4.nix index cf4faef223f5..5ed501e4b020 100644 --- a/modules/services/x11/desktop-managers/kde4.nix +++ b/modules/services/x11/desktop-managers/kde4.nix @@ -47,7 +47,13 @@ in ''; }; - security.setuidPrograms = [ "kcheckpass" ]; + security.setuidOwners = [ { + program = "kcheckpass"; + source = "${pkgs.kde4.kdebase_workspace}/lib/kde4/libexec/kcheckpass"; + owner = "root"; + group = "root"; + setuid = true; + } ]; environment = { kdePackages = [ diff --git a/modules/system/activation/activation-script.nix b/modules/system/activation/activation-script.nix index 8924041ae600..1aad1f37c2d5 100644 --- a/modules/system/activation/activation-script.nix +++ b/modules/system/activation/activation-script.nix @@ -1,220 +1,134 @@ # generate the script used to activate the configuration. -{pkgs, config, ...}: +{ config, pkgs, ... }: + +with pkgs.lib; let - inherit (pkgs.lib) mkOption mergeTypedOption mergeAttrs - mapAttrs addErrorContext fold id filter textClosureMap noDepEntry - fullDepEntry; - inherit (builtins) attrNames; addAttributeName = mapAttrs (a: v: v // { - text = '' - #### actionScripts snippet ${a} : - # ======================================== - ${v.text} - ''; - }); - - defaultScripts = { - - systemConfig = noDepEntry '' - systemConfig="$1" - if test -z "$systemConfig"; then - systemConfig="/system" # for the installation CD - fi + text = '' + #### Activation script snippet ${a}: + ${v.text} ''; + }); - defaultPath = - let path = [ - pkgs.coreutils pkgs.gnugrep pkgs.findutils - pkgs.glibc # needed for getent - pkgs.shadow - pkgs.nettools # needed for hostname - ]; in noDepEntry '' - export PATH=/empty - for i in ${toString path}; do - PATH=$PATH:$i/bin:$i/sbin; - done - ''; - - stdio = fullDepEntry '' - # Needed by some programs. - ln -sfn /proc/self/fd /dev/fd - ln -sfn /proc/self/fd/0 /dev/stdin - ln -sfn /proc/self/fd/1 /dev/stdout - ln -sfn /proc/self/fd/2 /dev/stderr - '' [ - "defaultPath" # path to ln + path = + [ pkgs.coreutils pkgs.gnugrep pkgs.findutils + pkgs.glibc # needed for getent + pkgs.shadow + pkgs.nettools # needed for hostname ]; - - binsh = fullDepEntry '' - # Create the required /bin/sh symlink; otherwise lots of things - # (notably the system() function) won't work. - mkdir -m 0755 -p $mountPoint/bin - ln -sfn ${config.system.build.binsh}/bin/sh $mountPoint/bin/sh - '' [ - "defaultPath" # path to ln & mkdir - "stdio" # ? - ]; - - modprobe = fullDepEntry '' - # Allow the kernel to find our wrapped modprobe (which searches - # in the right location in the Nix store for kernel modules). - # We need this when the kernel (or some module) auto-loads a - # module. - echo ${config.system.sbin.modprobe}/sbin/modprobe > /proc/sys/kernel/modprobe - '' [ - # ? - ]; - - var = fullDepEntry '' - # Various log/runtime directories. - - touch /var/run/utmp # must exist - chgrp ${toString config.ids.gids.utmp} /var/run/utmp - chmod 664 /var/run/utmp - - mkdir -m 0755 -p /var/run/nix/current-load # for distributed builds - mkdir -m 0700 -p /var/run/nix/remote-stores - - mkdir -m 0755 -p /var/log - mkdir -m 0755 -p /var/log/upstart - - touch /var/log/wtmp # must exist - chmod 644 /var/log/wtmp - - touch /var/log/lastlog - chmod 644 /var/log/lastlog - - mkdir -m 1777 -p /var/tmp - - # Empty, read-only home directory of many system accounts. - mkdir -m 0555 -p /var/empty - '' [ - "defaultPath" # path to mkdir & touch & chmod - ]; - - rootPasswd = fullDepEntry '' - # If there is no password file yet, create a root account with an - # empty password. - if ! test -e /etc/passwd; then - rootHome=/root - touch /etc/passwd; chmod 0644 /etc/passwd - touch /etc/group; chmod 0644 /etc/group - touch /etc/shadow; chmod 0600 /etc/shadow - # Can't use useradd, since it complains that it doesn't know us - # (bootstrap problem!). - echo "root:x:0:0:System administrator:$rootHome:${config.users.defaultUserShell}" >> /etc/passwd - echo "root::::::::" >> /etc/shadow - fi - '' [ - "defaultPath" # path to touch & passwd - "etc" # for /etc - # ? - ]; - - nix = fullDepEntry '' - # Set up Nix. - mkdir -p /nix/etc/nix - ln -sfn /etc/nix.conf /nix/etc/nix/nix.conf - chown root.nixbld /nix/store - chmod 1775 /nix/store - - # Nix initialisation. - mkdir -m 0755 -p \ - /nix/var/nix/gcroots \ - /nix/var/nix/temproots \ - /nix/var/nix/manifests \ - /nix/var/nix/userpool \ - /nix/var/nix/profiles \ - /nix/var/nix/db \ - /nix/var/log/nix/drvs \ - /nix/var/nix/channel-cache \ - /nix/var/nix/chroots - mkdir -m 1777 -p /nix/var/nix/gcroots/per-user - mkdir -m 1777 -p /nix/var/nix/profiles/per-user - mkdir -m 1777 -p /nix/var/nix/gcroots/tmp - - ln -sf /nix/var/nix/profiles /nix/var/nix/gcroots/ - ln -sf /nix/var/nix/manifests /nix/var/nix/gcroots/ - '' [ - "defaultPath" - "etc" # /etc/nix.conf - "users" # nixbld group - ]; - - hostname = fullDepEntry '' - # Set the host name. Don't clear it if it's not configured in the - # NixOS configuration, since it may have been set by dhclient in the - # meantime. - ${if config.networking.hostName != "" then - ''hostname "${config.networking.hostName}"'' - else '' - # dhclient won't do anything if the hostname isn't empty. - if test "$(hostname)" = "(none)"; then - hostname "" - fi - ''} - '' [ "defaultPath" ]; - - # The activation has to be done at the end. This is forced at the apply - # function of activationScripts option - activate = noDepEntry '' - # Make this configuration the current configuration. - # The readlink is there to ensure that when $systemConfig = /system - # (which is a symlink to the store), /var/run/current-system is still - # used as a garbage collection root. - ln -sfn "$(readlink -f "$systemConfig")" /var/run/current-system - - # Prevent the current configuration from being garbage-collected. - ln -sfn /var/run/current-system /nix/var/nix/gcroots/current-system - ''; - - media = noDepEntry '' - mkdir -p /media - ''; - - }; - in { - require = { - system = { - activationScripts = mkOption { - default = []; - example = { - stdio = { - text = " - # Needed by some programs. - ln -sfn /proc/self/fd /dev/fd - ln -sfn /proc/self/fd/0 /dev/stdin - ln -sfn /proc/self/fd/1 /dev/stdout - ln -sfn /proc/self/fd/2 /dev/stderr - "; - deps = []; - }; - }; - description = '' - Activate the new configuration (i.e., update /etc, make accounts, - and so on). - ''; - merge = mergeTypedOption "script" builtins.isAttrs (fold mergeAttrs {}); - apply = set: - let withHeadlines = addAttributeName set; - activateLib = removeAttrs withHeadlines ["activate"]; - activateLibNames = attrNames activateLib; - in { - script = pkgs.writeScript "nixos-activation-script" - ("#! ${pkgs.stdenv.shell}\n" - + textClosureMap id activateLib activateLibNames + "\n" - # make sure that the activate snippet is added last. - + withHeadlines.activate.text); + + ###### interface + + options = { + + system.activationScripts = mkOption { + default = {}; + + example = { + stdio = { + text = '' + # Needed by some programs. + ln -sfn /proc/self/fd /dev/fd + ln -sfn /proc/self/fd/0 /dev/stdin + ln -sfn /proc/self/fd/1 /dev/stdout + ln -sfn /proc/self/fd/2 /dev/stderr + ''; + deps = []; }; }; + + description = '' + Activate the new configuration (i.e., update /etc, make accounts, + and so on). + ''; + + merge = mergeTypedOption "script" builtins.isAttrs (fold mergeAttrs {}); + + apply = set: { + script = + '' + #! ${pkgs.stdenv.shell} + + systemConfig=@out@ + + export PATH=/empty + for i in ${toString path}; do + PATH=$PATH:$i/bin:$i/sbin; + done + + ${ + let + set' = mapAttrs (n: v: if builtins.isString v then noDepEntry v else v) set; + withHeadlines = addAttributeName set'; + in textClosureMap id (withHeadlines) (attrNames withHeadlines) + } + + # Make this configuration the current configuration. + # The readlink is there to ensure that when $systemConfig = /system + # (which is a symlink to the store), /var/run/current-system is still + # used as a garbage collection root. + ln -sfn "$(readlink -f "$systemConfig")" /var/run/current-system + + # Prevent the current configuration from being garbage-collected. + ln -sfn /var/run/current-system /nix/var/nix/gcroots/current-system + ''; + }; + }; + }; - system.activationScripts = defaultScripts; + + ###### implementation + + config = { + + system.activationScripts.stdio = + '' + # Needed by some programs. + ln -sfn /proc/self/fd /dev/fd + ln -sfn /proc/self/fd/0 /dev/stdin + ln -sfn /proc/self/fd/1 /dev/stdout + ln -sfn /proc/self/fd/2 /dev/stderr + ''; + + system.activationScripts.var = + '' + # Various log/runtime directories. + + touch /var/run/utmp # must exist + chgrp ${toString config.ids.gids.utmp} /var/run/utmp + chmod 664 /var/run/utmp + + mkdir -m 0755 -p /var/run/nix/current-load # for distributed builds + mkdir -m 0700 -p /var/run/nix/remote-stores + + mkdir -m 0755 -p /var/log + mkdir -m 0755 -p /var/log/upstart + + touch /var/log/wtmp # must exist + chmod 644 /var/log/wtmp + + touch /var/log/lastlog + chmod 644 /var/log/lastlog + + mkdir -m 1777 -p /var/tmp + + # Empty, read-only home directory of many system accounts. + mkdir -m 0555 -p /var/empty + ''; + + system.activationScripts.media = + '' + mkdir -p /media + ''; + + }; + } diff --git a/modules/system/activation/switch-to-configuration.sh b/modules/system/activation/switch-to-configuration.sh index 6aec8225fdfc..3249ee3ea347 100644 --- a/modules/system/activation/switch-to-configuration.sh +++ b/modules/system/activation/switch-to-configuration.sh @@ -38,7 +38,7 @@ if [ "$action" = "switch" -o "$action" = "boot" ]; then if [ "$NIXOS_INSTALL_GRUB" = 1 -o "$oldGrubVersion" != "$newGrubVersion" ]; then echo "installing the GRUB bootloader..." - @grub@/sbin/grub-install "@grubDevice@" --no-floppy --recheck + @grub@/sbin/grub-install "@grubDevice@" --no-floppy echo "$newGrubVersion" > /boot/grub/version fi fi @@ -110,7 +110,11 @@ EOF # forget about current sessions. # Idem for the emergeny-shell, because its `console owner' # line screws up the X server. - if echo "$job" | grep -q "^shutdown$\|^control-alt-delete$\|^xserver$\|^dbus$\|^disnix$\|^emergency-shell$"; then continue; fi + # Idem for xendomains because we don't want to save/restore + # Xen domains unless we have to. + # TODO: Jobs should be able to declare that they should not be + # auto-restarted. + if echo "$job" | grep -q "^shutdown$\|^control-alt-delete$\|^xserver$\|^dbus$\|^disnix$\|^emergency-shell$\|^xendomains$"; then continue; fi if ! test -e "$oldJobs/$job.conf"; then echo "starting $job..." diff --git a/modules/system/activation/top-level.nix b/modules/system/activation/top-level.nix index cb3c4e8941dc..92615c78f32b 100644 --- a/modules/system/activation/top-level.nix +++ b/modules/system/activation/top-level.nix @@ -43,30 +43,19 @@ let system.copySystemConfiguration = pkgs.lib.mkOption { default = false; description = '' - Unless set to false copies the nixos configuration file - $NIXOS_CONFIG defaulting to - /etc/nixos/configuration.nix + If enabled, copies the NixOS configuration file + $NIXOS_CONFIG (usually + /etc/nixos/configuration.nix) to the system store path. - See - if you want to do add more customized info - to your system storepath. ''; }; system.extraSystemBuilderCmds = pkgs.lib.mkOption { default = ""; + internal = true; merge = pkgs.lib.concatStringsSep "\n"; description = '' This code will be added to the builder creating the system store path. - This use case copies your configuration file into the system derivation: - - cp ${pkgs.lib.maybeEnv "NIXOS_CONFIG" "/etc/nixos/configuration.nix"} $out - - Of course you could add code saving a svn diff or svn revision number - of both nixos and nixpkgs repositories as well. Keep in mind that when - you build in chroots that you have do either copy sources to store or - add them to the chroot somehow. - You still should consider putting your configuration into a VCS. ''; }; @@ -107,14 +96,23 @@ let echo "(Expecting ${kernelPath})" false fi + ln -s ${kernelPath} $out/kernel ln -s ${config.system.modulesTree} $out/kernel-modules if [ -n "$grub" ]; then ln -s $grub $out/grub fi - ln -s ${config.system.build.bootStage2} $out/init + ln -s ${config.system.build.initialRamdisk}/initrd $out/initrd - ln -s ${config.system.activationScripts.script} $out/activate + + echo "$activationScript" > $out/activate + substituteInPlace $out/activate --subst-var out + chmod u+x $out/activate + unset activationScript + + cp ${config.system.build.bootStage2} $out/init + substituteInPlace $out/init --subst-var-by systemConfig $out + ln -s ${config.system.build.etc}/etc $out/etc ln -s ${config.system.path} $out/sw ln -s ${config.system.build.upstart} $out/upstart @@ -126,7 +124,7 @@ let mkdir $out/fine-tune childCount=0; - for i in $children; do + for i in $children; do childCount=$(( childCount + 1 )); ln -s $i $out/fine-tune/child-$childCount; done @@ -152,6 +150,7 @@ let config.boot.kernelParams ++ config.boot.extraKernelParams; menuBuilder = config.system.build.menuBuilder; initScriptBuilder = config.system.build.initScriptBuilder; + activationScript = config.system.activationScripts.script; # Most of these are needed by grub-install. path = [ pkgs.coreutils @@ -181,8 +180,9 @@ in { require = [options]; system.extraSystemBuilderCmds = - pkgs.lib.optionalString - config.system.copySystemConfiguration - "cp ${pkgs.lib.maybeEnv "NIXOS_CONFIG" "/etc/nixos/configuration.nix"} $out"; + pkgs.lib.optionalString + config.system.copySystemConfiguration + "cp ${pkgs.lib.maybeEnv "NIXOS_CONFIG" "/etc/nixos/configuration.nix"} $out"; + system.build.toplevel = system; } diff --git a/modules/system/boot/modprobe.nix b/modules/system/boot/modprobe.nix index 65b3f6fd292a..aa4d023a9f43 100644 --- a/modules/system/boot/modprobe.nix +++ b/modules/system/boot/modprobe.nix @@ -88,6 +88,15 @@ with pkgs.lib; # too? ]; + system.activationScripts.modprobe = + '' + # Allow the kernel to find our wrapped modprobe (which searches + # in the right location in the Nix store for kernel modules). + # We need this when the kernel (or some module) auto-loads a + # module. + echo ${config.system.sbin.modprobe}/sbin/modprobe > /proc/sys/kernel/modprobe + ''; + }; } diff --git a/modules/system/boot/stage-1.nix b/modules/system/boot/stage-1.nix index 7f8287e7e4ba..7a38883af576 100644 --- a/modules/system/boot/stage-1.nix +++ b/modules/system/boot/stage-1.nix @@ -199,7 +199,6 @@ let $out/bin/umount --version | grep "umount " $out/bin/e2fsck -V 2>&1 | grep "e2fsck " $out/bin/tune2fs 2> /dev/null | grep "tune2fs " - $out/bin/fsck -N | grep "fsck from" $out/bin/udevadm --version $out/bin/blkid -v 2>&1 | tee -a $out/log | grep "blkid from util-linux-ng" $out/bin/dmsetup --version 2>&1 | tee -a $out/log | grep "version:" diff --git a/modules/system/boot/stage-2-init.sh b/modules/system/boot/stage-2-init.sh index 834ad9548ed3..b00baf8a0758 100644 --- a/modules/system/boot/stage-2-init.sh +++ b/modules/system/boot/stage-2-init.sh @@ -1,6 +1,6 @@ #! @shell@ -# !!! copied from stage 1; remove duplication +systemConfig=@systemConfig@ # Print a greeting. @@ -56,11 +56,6 @@ rm -f /etc/mtab* # not that we care about stale locks cat /proc/mounts > /etc/mtab -# If no `systemConfig' parameter is specified on the kernel command -# line, use a fallback. -systemConfig=/nix/var/nix/profiles/system - - # Process the kernel command line. for o in $(cat /proc/cmdline); do case $o in @@ -79,10 +74,6 @@ for o in $(cat /proc/cmdline); do safemode) safeMode=1 ;; - systemConfig=*) - set -- $(IFS==; echo $o) - systemConfig=$2 - ;; resume=*) set -- $(IFS==; echo $o) resumeDevice=$2 @@ -90,8 +81,6 @@ for o in $(cat /proc/cmdline); do esac done -systemConfig="$(readlink -f "$systemConfig")" - # More special file systems, initialise required directories. mkdir -m 0777 /dev/shm @@ -153,19 +142,16 @@ fi # Run the script that performs all configuration activation that does # not have to be done at boot time. echo "running activation script..." -@activateConfiguration@ "$systemConfig" +$systemConfig/activate # Record the boot configuration. -if test -n "$systemConfig"; then - ln -sfn "$systemConfig" /var/run/booted-system +ln -sfn "$systemConfig" /var/run/booted-system - # Prevent the booted system form being garbage-collected - # If it weren't a gcroot, if we were running a different kernel, - # switched system, and garbage collected all, we could not load - # kernel modules anymore. - ln -sfn /var/run/booted-system /nix/var/nix/gcroots/booted-system -fi +# Prevent the booted system form being garbage-collected If it weren't +# a gcroot, if we were running a different kernel, switched system, +# and garbage collected all, we could not load kernel modules anymore. +ln -sfn /var/run/booted-system /nix/var/nix/gcroots/booted-system # Ensure that the module tools can find the kernel modules. diff --git a/modules/system/boot/stage-2.nix b/modules/system/boot/stage-2.nix index 279f454c5db8..8934a33cd04c 100644 --- a/modules/system/boot/stage-2.nix +++ b/modules/system/boot/stage-2.nix @@ -43,7 +43,7 @@ let bootStage2 = substituteAll { src = ./stage-2-init.sh; isExecutable = true; - inherit kernel activateConfiguration; + inherit kernel; inherit (config.boot) devShmSize; ttyGid = config.ids.gids.tty; upstart = config.system.build.upstart; diff --git a/modules/system/etc/etc.nix b/modules/system/etc/etc.nix index 4ae420017a57..7a764a8397b0 100644 --- a/modules/system/etc/etc.nix +++ b/modules/system/etc/etc.nix @@ -1,9 +1,10 @@ -# produce a script to generate /etc -{config, pkgs, ...}: +# Produce a script to generate /etc. +{ config, pkgs, ... }: + +with pkgs.lib; ###### interface let - inherit (pkgs.lib) mkOption; option = { environment.etc = mkOption { @@ -36,7 +37,7 @@ let chmod ${mode} "$target" ''; - makeEtc = pkgs.stdenv.mkDerivation { + etc = pkgs.stdenv.mkDerivation { name = "etc"; builder = ./make-etc.sh; @@ -52,47 +53,13 @@ in { require = [option]; - system = { - build = { - etc = makeEtc; - }; + system.build.etc = etc; - activationScripts = { - etc = pkgs.lib.fullDepEntry '' - # Set up the statically computed bits of /etc. - echo "setting up /etc..." - staticEtc=/etc/static - rm -f $staticEtc - ln -s ${makeEtc}/etc $staticEtc - for i in $(cd $staticEtc && find * -type l); do - mkdir -p /etc/$(dirname $i) - rm -f /etc/$i - if test -e "$staticEtc/$i.mode"; then - # Create a regular file in /etc. - cp $staticEtc/$i /etc/$i - chown 0.0 /etc/$i - chmod "$(cat "$staticEtc/$i.mode")" /etc/$i - else - # Create a symlink in /etc. - ln -s $staticEtc/$i /etc/$i - fi - done + system.activationScripts.etc = stringAfter [ "stdio" ] + '' + # Set up the statically computed bits of /etc. + echo "setting up /etc..." + ${pkgs.perl}/bin/perl ${./setup-etc.pl} ${etc}/etc + ''; - # Remove dangling symlinks that point to /etc/static. These are - # configuration files that existed in a previous configuration but not - # in the current one. For efficiency, don't look under /etc/nixos - # (where all the NixOS sources live). - for i in $(find /etc/ \( -path /etc/nixos -prune \) -o -type l); do - target=$(readlink "$i") - if test "''${target:0:''${#staticEtc}}" = "$staticEtc" -a ! -e "$i"; then - rm -f "$i" - fi - done - '' [ - "systemConfig" - "defaultPath" # path to cp, chmod, chown - "stdio" - ]; - }; - }; } diff --git a/modules/system/etc/setup-etc.pl b/modules/system/etc/setup-etc.pl new file mode 100644 index 000000000000..c6b932cf2022 --- /dev/null +++ b/modules/system/etc/setup-etc.pl @@ -0,0 +1,65 @@ +use strict; +use File::Find; +use File::Copy; +use File::Path; +use File::Basename; + +my $etc = $ARGV[0] or die; +my $static = "/etc/static"; + +sub atomicSymlink { + my ($source, $target) = @_; + my $tmp = "$target.tmp"; + unlink $tmp; + symlink $source, $tmp or return 1; + rename $tmp, $target or return 1; + return 1; +} + + +# Atomically update /etc/static to point at the etc files of the +# current configuration. +atomicSymlink $etc, $static or die; + + +# 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. +sub link { + my $fn = substr $File::Find::name, length($etc) + 1 or next; + my $target = "/etc/$fn"; + File::Path::make_path(dirname $target); + if (-e "$_.mode") { + open MODE, "<$_.mode"; + my $mode = ; chomp $mode; + close MODE; + copy "$static/$fn", "$target.tmp" or warn; + chmod oct($mode), "$target.tmp" or warn; + rename "$target.tmp", $target or warn; + } elsif (-l "$_") { + atomicSymlink "$static/$fn", $target or warn; + } +} + +find(\&link, $etc); + + +# Remove dangling symlinks that point to /etc/static. These are +# configuration files that existed in a previous configuration but not +# in the current one. For efficiency, don't look under /etc/nixos +# (where all the NixOS sources live). +sub cleanup { + if ($File::Find::name eq "/etc/nixos") { + $File::Find::prune = 1; + return; + } + if (-l $_) { + my $target = readlink $_; + if (substr($target, 0, length $static) eq $static) { + my $x = "/etc/static/" . substr($File::Find::name, length "/etc/"); + unlink "$_" unless -e "$x"; + } + } +} + +find(\&cleanup, "/etc"); diff --git a/modules/system/upstart-events/control-alt-delete.nix b/modules/system/upstart-events/control-alt-delete.nix index 5fa2bd87eb91..f0f146160e58 100644 --- a/modules/system/upstart-events/control-alt-delete.nix +++ b/modules/system/upstart-events/control-alt-delete.nix @@ -15,4 +15,12 @@ shutdown -r now 'Ctrl-Alt-Delete pressed' ''; }; + + system.activationScripts.poweroff = + '' + # Allow the kernel to find the poweroff command. This is used + # (for instance) by Xen's "xm shutdown" command to signal a + # guest to shut down cleanly. + echo ${config.system.build.upstart}/sbin/poweroff > /proc/sys/kernel/poweroff_cmd + ''; } diff --git a/modules/system/upstart/upstart.nix b/modules/system/upstart/upstart.nix index cb3975e694c3..535e612ed32c 100644 --- a/modules/system/upstart/upstart.nix +++ b/modules/system/upstart/upstart.nix @@ -39,7 +39,8 @@ let ${optionalString (job.stopOn != "") "stop on ${job.stopOn}"} - env PATH=${makeSearchPath "bin" upstartPath}:${makeSearchPath "sbin" upstartPath} + env PATH=${makeSearchPath "bin" (job.path ++ upstartPath)}:${makeSearchPath "sbin" (job.path ++ upstartPath)} + ${concatMapStrings (n: "env ${n}=\"${getAttr n job.environment}\"\n") (attrNames job.environment)} ${optionalString (job.preStart != "") '' @@ -271,6 +272,15 @@ let ''; }; + path = mkOption { + default = [ ]; + description = '' + Packages added to the job's PATH environment variable. + Both the bin and sbin + subdirectories of each package are added. + ''; + }; + }; diff --git a/modules/tasks/filesystems.nix b/modules/tasks/filesystems.nix index 5735d943c51e..699e9b3c33ca 100644 --- a/modules/tasks/filesystems.nix +++ b/modules/tasks/filesystems.nix @@ -94,9 +94,7 @@ in example = "data=journal"; type = types.string; merge = pkgs.lib.concatStringsSep ","; - description = " - Option used to mount the file system. - "; + description = "Options used to mount the file system."; }; autocreate = mkOption { @@ -107,6 +105,12 @@ in . "; }; + + noCheck = mkOption { + default = false; + type = types.bool; + description = "Disable running fsck on this filesystem."; + }; }; }; @@ -142,7 +146,8 @@ in + " " + fs.fsType + " " + fs.options + " 0" - + " " + (if fs.fsType == "none" then "0" else if fs.mountPoint == "/" then "1" else "2") + + " " + (if fs.fsType == "none" || fs.noCheck then "0" else + if fs.mountPoint == "/" then "1" else "2") + "\n" )} diff --git a/modules/tasks/network-interfaces.nix b/modules/tasks/network-interfaces.nix index 8c419810c573..562a945d832a 100644 --- a/modules/tasks/network-interfaces.nix +++ b/modules/tasks/network-interfaces.nix @@ -205,7 +205,15 @@ in # ${nettools}/sbin/ifconfig $i down || true #done ''; - }; + }; + + # Set the host name in the activation script. Don't clear it if + # it's not configured in the NixOS configuration, since it may + # have been set by dhclient in the meantime. + system.activationScripts.hostname = + optionalString (config.networking.hostName != "") '' + hostname "${config.networking.hostName}" + ''; }; diff --git a/modules/testing/test-instrumentation.nix b/modules/testing/test-instrumentation.nix index 6f47a6a9c39e..610d5fcc8321 100644 --- a/modules/testing/test-instrumentation.nix +++ b/modules/testing/test-instrumentation.nix @@ -77,9 +77,13 @@ in # Send all of /var/log/messages to the serial port. services.syslogd.extraConfig = "*.* /dev/ttyS0"; + # Clear the kernel log buffer before starting klogd to prevent it + # from printing messages that we have already seen. + jobs.klogd.preStart = "dmesg -c > /dev/null"; + # Prevent tests from accessing the Internet. - networking.defaultGateway = mkOverrideTemplate 150 {} ""; - networking.nameservers = mkOverrideTemplate 150 {} [ ]; + networking.defaultGateway = mkOverride 150 ""; + networking.nameservers = mkOverride 150 [ ]; # Require a patch to the kernel to increase the 15s CIFS timeout. assertions = diff --git a/modules/virtualisation/qemu-vm.nix b/modules/virtualisation/qemu-vm.nix index cf527391e2c5..005e4ebfb54b 100644 --- a/modules/virtualisation/qemu-vm.nix +++ b/modules/virtualisation/qemu-vm.nix @@ -110,7 +110,21 @@ let example = "-vga std"; description = "Options passed to QEMU."; }; - + + virtualisation.useBootLoader = + mkOption { + default = false; + description = + '' + If enabled, the virtual machine will be booted using the + regular boot loader (i.e., GRUB 1 or 2). This allows + testing of the boot loader. If + disabled (the default), the VM directly boots the NixOS + kernel and initial ramdisk, bypassing the boot loader + altogether. + ''; + }; + }; cfg = config.virtualisation; @@ -146,12 +160,17 @@ let -net nic,vlan=0,model=virtio \ -chardev socket,id=samba,path=./samba \ -net user,vlan=0,guestfwd=tcp:10.0.2.4:139-chardev:samba''${QEMU_NET_OPTS:+,$QEMU_NET_OPTS} \ - -drive file=$NIX_DISK_IMAGE,if=virtio,boot=on,cache=writeback,werror=report \ - -kernel ${config.system.build.toplevel}/kernel \ - -initrd ${config.system.build.toplevel}/initrd \ + ${if cfg.useBootLoader then '' + -drive index=0,file=$NIX_DISK_IMAGE,if=virtio,cache=writeback,werror=report \ + -drive index=1,file=${bootDisk}/disk.img,if=virtio,boot=on \ + '' else '' + -drive file=$NIX_DISK_IMAGE,if=virtio,boot=on,cache=writeback,werror=report \ + -kernel ${config.system.build.toplevel}/kernel \ + -initrd ${config.system.build.toplevel}/initrd \ + -append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.toplevel}/init regInfo=${regInfo} ${kernelConsole} $QEMU_KERNEL_PARAMS" \ + ''} \ ${qemuGraphics} \ $QEMU_OPTS \ - -append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.bootStage2} systemConfig=${config.system.build.toplevel} regInfo=${regInfo} ${kernelConsole} $QEMU_KERNEL_PARAMS" \ ${config.virtualisation.qemu.options} ''; @@ -165,11 +184,54 @@ let printRegistration=1 perl ${pkgs.pathsFromGraph} closure-* > $out ''; + + # Generate a hard disk image containing a /boot partition and GRUB + # in the MBR. Used when the `useBootLoader' option is set. + bootDisk = + pkgs.vmTools.runInLinuxVM ( + pkgs.runCommand "nixos-boot-disk" + { preVM = + '' + mkdir $out + diskImage=$out/disk.img + ${pkgs.vmTools.kvm}/bin/qemu-img create -f qcow2 $diskImage "32M" + ''; + buildInputs = [ pkgs.utillinux ]; + } + '' + # Create a single /boot 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 + . /sys/class/block/vda/uevent + ${pkgs.e2fsprogs}/sbin/mkfs.ext3 -L boot /dev/vda1 + ${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda1 + + # Mount /boot. + mkdir /boot + mount /dev/vda1 /boot + + # This is needed for GRUB 0.97, which doesn't know about virtio devices. + mkdir /boot/grub + echo '(hd0) /dev/vda' > /boot/grub/device.map + + # Install GRUB and generate the GRUB boot menu. + touch /etc/NIXOS + mkdir -p /nix/var/nix/profiles + ${config.system.build.toplevel}/bin/switch-to-configuration boot + + umount /boot + '' + ); + in { require = options; + boot.loader.grub.device = mkOverride 50 "/dev/vda"; + # All the modules the initrd needs to mount the host filesystem via # CIFS. Also use paravirtualised network and block devices for # performance. @@ -207,6 +269,7 @@ in boot.initrd.postMountCommands = '' + mkdir -p $targetRoot/boot mount -o remount,ro $targetRoot/nix/store ${optionalString cfg.writableStore '' mkdir /mnt-store-tmpfs @@ -225,19 +288,21 @@ in boot.postBootCommands = '' ( source /proc/cmdline - ${config.environment.nix}/bin/nix-store --load-db < $regInfo + if [ -n "$regInfo" ]; then + ${config.environment.nix}/bin/nix-store --load-db < $regInfo + fi ) ''; virtualisation.pathsInNixDB = [ config.system.build.toplevel ]; # Mount the host filesystem via CIFS, and bind-mount the Nix store - # of the host into our own filesystem. We use mkOverrideTemplate to allow + # of the host into our own filesystem. We use mkOverride to allow # this module to be applied to "normal" NixOS system 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 = mkOverrideTemplate 50 {} + fileSystems = mkOverride 50 ( [ { mountPoint = "/"; device = "/dev/vda"; } @@ -253,13 +318,21 @@ in options = "bind"; neededForBoot = true; } - ]; + ] ++ optional cfg.useBootLoader + { mountPoint = "/boot"; + device = "/dev/disk/by-label/boot"; + fsType = "ext3"; + options = "ro"; + noCheck = true; # fsck fails on a r/o filesystem + }); + + swapDevices = mkOverride 50 [ ]; # Starting DHCP brings down eth0, which kills the connection to the # host filesystem and thus deadlocks the system. networking.useDHCP = false; - networking.defaultGateway = mkOverrideTemplate 200 {} "10.0.2.2"; + networking.defaultGateway = mkOverride 200 "10.0.2.2"; networking.nameservers = [ "10.0.2.3" ]; @@ -287,9 +360,9 @@ in # When building a regular system configuration, override whatever # video driver the host uses. - services.xserver.videoDriver = mkOverrideTemplate 50 {} null; - services.xserver.videoDrivers = mkOverrideTemplate 50 {} [ "cirrus" "vesa" ]; - services.xserver.defaultDepth = mkOverrideTemplate 50 {} 0; + services.xserver.videoDriver = mkOverride 50 null; + services.xserver.videoDrivers = mkOverride 50 [ "cirrus" "vesa" ]; + services.xserver.defaultDepth = mkOverride 50 0; services.xserver.monitorSection = '' # Set a higher refresh rate so that resolutions > 800x600 work. @@ -300,5 +373,5 @@ in services.mingetty.ttys = ttys ++ optional (!cfg.graphics) "ttyS0"; # Wireless won't work in the VM. - networking.enableWLAN = mkOverrideTemplate 50 {} false; + networking.enableWLAN = mkOverride 50 false; } diff --git a/modules/virtualisation/xen-dom0.nix b/modules/virtualisation/xen-dom0.nix new file mode 100644 index 000000000000..e10713466f7a --- /dev/null +++ b/modules/virtualisation/xen-dom0.nix @@ -0,0 +1,165 @@ +# Xen hypervisor (Dom0) support. + +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + cfg = config.virtualisation.xen; + + xen = pkgs.xen; + + xendConfig = pkgs.writeText "xend-config.sxp" + '' + (loglevel DEBUG) + (network-script network-bridge) + (vif-script vif-bridge) + ''; + +in + +{ + ###### interface + + options = { + + virtualisation.xen.enable = + mkOption { + default = false; + description = + '' + Setting this option enables the Xen hypervisor, a + virtualisation technology that allows multiple virtual + machines, known as domains, to run + concurrently on the physical machine. NixOS runs as the + privileged Domain 0. This option + requires a reboot to take effect. + ''; + }; + + virtualisation.xen.bootParams = + mkOption { + default = ""; + description = + '' + Parameters passed to the Xen hypervisor at boot time. + ''; + }; + + virtualisation.xen.domain0MemorySize = + mkOption { + default = 0; + example = 512; + description = + '' + Amount of memory (in MiB) allocated to Domain 0 on boot. + If set to 0, all memory is assigned to Domain 0. + ''; + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + environment.systemPackages = [ xen ]; + + # Domain 0 requires a pvops-enabled kernel. + boot.kernelPackages = pkgs.linuxPackages_2_6_32_xen; + + boot.kernelModules = + [ "xen_evtchn" "xen_gntdev" "xen_blkback" "xen_netback" "xen_pciback" + "blktap" "tap" + ]; + + # The radeonfb kernel module causes the screen to go black as soon + # as it's loaded, so don't load it. + boot.blacklistedKernelModules = [ "radeonfb" ]; + + virtualisation.xen.bootParams = + [ "loglvl=all" "guest_loglvl=all" ] ++ + optional (cfg.domain0MemorySize != 0) "dom0_mem=${toString cfg.domain0MemorySize}M"; + + system.extraSystemBuilderCmds = + '' + ln -s ${xen}/boot/xen.gz $out/xen.gz + echo "${toString cfg.bootParams}" > $out/xen-params + ''; + + # Mount the /proc/xen pseudo-filesystem. + system.activationScripts.xen = + '' + if [ -d /proc/xen ]; then + ${pkgs.sysvtools}/bin/mountpoint -q /proc/xen || \ + ${pkgs.utillinux}/bin/mount -t xenfs none /proc/xen + fi + ''; + + jobs.xend = + { description = "Xen control daemon"; + + startOn = "stopped udevtrigger"; + + path = + [ pkgs.bridge_utils pkgs.gawk pkgs.iproute pkgs.nettools + pkgs.utillinux pkgs.bash xen pkgs.pciutils pkgs.procps + ]; + + preStart = + '' + ${xen}/sbin/xend start + + # Wait until Xend is running. + for ((i = 0; i < 60; i++)); do echo "waiting for xend..."; ${xen}/sbin/xend status && break; done + + ${xen}/sbin/xend status || exit 1 + ''; + + postStop = "${xen}/sbin/xend stop"; + }; + + jobs.xendomains = + { description = "Automatically starts, saves and restores Xen domains on startup/shutdown"; + + startOn = "started xend"; + + stopOn = "starting shutdown and stopping xend"; + + path = [ pkgs.xen ]; + + environment.XENDOM_CONFIG = "${xen}/etc/sysconfig/xendomains"; + + preStart = + '' + mkdir -p /var/lock/subsys -m 755 + ${xen}/etc/init.d/xendomains start + ''; + + postStop = "${xen}/etc/init.d/xendomains stop"; + }; + + # To prevent a race between dhclient and xend's bridge setup + # script (which renames eth* to peth* and recreates eth* as a + # virtual device), start dhclient after xend. + jobs.dhclient.startOn = mkOverride 50 "started xend"; + + environment.etc = + [ { source = xendConfig; + target = "xen/xend-config.sxp"; + } + { source = "${xen}/etc/xen/scripts"; + target = "xen/scripts"; + } + ]; + + # Xen provides udev rules. + services.udev.packages = [ xen ]; + + services.udev.path = [ pkgs.bridge_utils pkgs.iproute ]; + + }; + +} diff --git a/modules/virtualisation/xen-domU.nix b/modules/virtualisation/xen-domU.nix new file mode 100644 index 000000000000..a83e5dc612e1 --- /dev/null +++ b/modules/virtualisation/xen-domU.nix @@ -0,0 +1,26 @@ +# Common configuration for Xen DomU NixOS virtual machines. + +{ config, pkgs, ... }: + +{ + # We're being booted using pv-grub, which means that we need to + # generate a GRUB 1 menu without actually installing GRUB. + boot.loader.grub.version = 1; + boot.loader.grub.device = "nodev"; + boot.loader.grub.extraPerEntryConfig = "root (hd0)"; + + boot.initrd.kernelModules = [ "xen-blkfront" ]; + + # Backgrounds don't work, so don't bother. + services.ttyBackgrounds.enable = false; + + # Send syslog messages to the Xen console. + services.syslogd.tty = "hvc0"; + + # Start a mingetty on the Xen console (so that you can login using + # "xm console" in Dom0). + services.mingetty.ttys = [ "hvc0" "tty1" "tty2" ]; + + # Don't run ntpd, since we should get the correct time from Dom0. + services.ntp.enable = false; +} diff --git a/tests/avahi.nix b/tests/avahi.nix new file mode 100644 index 000000000000..2bf811b5cb3c --- /dev/null +++ b/tests/avahi.nix @@ -0,0 +1,60 @@ +{ pkgs, ... }: + +with pkgs; + +{ + nodes = { + one = + { config, pkgs, ... }: { + services.avahi.enable = true; + services.avahi.nssmdns = true; + }; + + two = + { config, pkgs, ... }: { + services.avahi.enable = true; + services.avahi.nssmdns = true; + }; + }; + + # Test whether `avahi-daemon' and `libnss-mdns' work as expected. + testScript = + '' startAll; + + # mDNS. + print STDERR + $one->mustSucceed("avahi-resolve-host-name one.local | tee out"); + $one->mustSucceed("test \"`cut -f1 < out`\" = one.local"); + print STDERR + $one->mustSucceed("avahi-resolve-host-name two.local | tee out"); + $one->mustSucceed("test \"`cut -f1 < out`\" = two.local"); + + print STDERR + $two->mustSucceed("avahi-resolve-host-name one.local | tee out"); + $two->mustSucceed("test \"`cut -f1 < out`\" = one.local"); + print STDERR + $two->mustSucceed("avahi-resolve-host-name two.local | tee out"); + $two->mustSucceed("test \"`cut -f1 < out`\" = two.local"); + + # Basic DNS-SD. + print STDERR + $one->mustSucceed("avahi-browse -r -t _workstation._tcp | tee out"); + $one->mustSucceed("test `wc -l < out` -gt 0"); + print STDERR + $two->mustSucceed("avahi-browse -r -t _workstation._tcp | tee out"); + $two->mustSucceed("test `wc -l < out` -gt 0"); + + # More DNS-SD. + $one->execute("avahi-publish -s \"This is a test\" _test._tcp 123 one=1 &"); + sleep 5; + print STDERR + $two->mustSucceed("avahi-browse -r -t _test._tcp | tee out"); + $two->mustSucceed("test `wc -l < out` -gt 0"); + + # NSS-mDNS. + print STDERR $one->mustSucceed("getent hosts one.local"); + print STDERR $one->mustSucceed("getent hosts two.local"); + print STDERR $two->mustSucceed("getent hosts one.local"); + print STDERR $two->mustSucceed("getent hosts two.local"); + ''; +} diff --git a/tests/default.nix b/tests/default.nix index e99bce510ec4..12a7244d6e10 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -6,6 +6,7 @@ with import ../lib/testing.nix { inherit nixpkgs services system; }; { + avahi = makeTest (import ./avahi.nix); bittorrent = makeTest (import ./bittorrent.nix); firefox = makeTest (import ./firefox.nix); installer = makeTests (import ./installer.nix); @@ -18,6 +19,7 @@ with import ../lib/testing.nix { inherit nixpkgs services system; }; proxy = makeTest (import ./proxy.nix); quake3 = makeTest (import ./quake3.nix); remote_builds = makeTest (import ./remote-builds.nix); + simple = makeTest (import ./simple.nix); subversion = makeTest (import ./subversion.nix); trac = makeTest (import ./trac.nix); } diff --git a/tests/installer.nix b/tests/installer.nix index 62684c48e5a7..e8337ebe2bb6 100644 --- a/tests/installer.nix +++ b/tests/installer.nix @@ -170,7 +170,7 @@ let $machine->waitUntilSucceeds("cat /proc/swaps | grep -q /dev"); $machine->mustSucceed("nix-env -i coreutils >&2"); - $machine->mustSucceed("type -tP ls") =~ /profiles/ + $machine->mustSucceed("type -tP ls | tee /dev/stderr") =~ /.nix-profile/ or die "nix-env failed"; $machine->mustSucceed("nixos-rebuild switch >&2"); @@ -296,5 +296,43 @@ in { ''; fileSystems = rootFS + bootFS; }; + + # Rebuild the CD configuration with a little modification. + rebuildCD = + { inherit iso; + nodes = { }; + testScript = + '' + # damn, it's costly to evaluate nixos-rebuild (1G of ram) + my $machine = Machine->new({ cdrom => glob("${iso}/iso/*.iso"), qemuFlags => '${qemuNICFlags 1 1} -m 1024' }); + $machine->start; + # Make sure that we get a login prompt etc. + $machine->mustSucceed("echo hello"); + $machine->waitForJob("tty1"); + $machine->waitForJob("rogue"); + $machine->waitForJob("nixos-manual"); + + # Make sure that we don't try to download anything. + $machine->stopJob("dhclient"); + $machine->mustSucceed("rm /etc/resolv.conf"); + + # Enable sshd service. + $machine->mustSucceed( + "sed -i 's,^}\$,jobs.sshd.startOn = pkgs.lib.mkOverride 0 \"startup\"; },' /etc/nixos/configuration.nix" + ); + + my $cfg = $machine->mustSucceed("cat /etc/nixos/configuration.nix"); + print STDERR "New CD config:\n$cfg\n"; + + # Apply the new CD configuration. + $machine->mustSucceed("nixos-rebuild test --no-pull"); + + # Connect to it-self. + #$machine->waitForJob("sshd"); + #$machine->mustSucceed("ssh root@127.0.0.1 echo hello"); + + $machine->shutdown; + ''; + }; } diff --git a/tests/simple.nix b/tests/simple.nix new file mode 100644 index 000000000000..eee13a101334 --- /dev/null +++ b/tests/simple.nix @@ -0,0 +1,11 @@ +{ pkgs, ... }: + +{ + machine = { config, pkgs, ... }: { }; + + testScript = + '' + startAll; + $machine->shutdown; + ''; +}