diff options
author | Vladimír Čunát <vcunat@gmail.com> | 2014-09-06 16:51:14 +0200 |
---|---|---|
committer | Vladimír Čunát <vcunat@gmail.com> | 2014-09-06 16:52:45 +0200 |
commit | 06fea81c6e3d71689b59df6e2bbc11fe01ce9056 (patch) | |
tree | 5849b904bf1eb3bc8cb28b29729d83a4d0337542 /nixos | |
parent | 20be024d1bae622409fa56844b2f8799bbf29bb0 (diff) | |
parent | 0c398f60405090743fbdcf14faf1193c642b6328 (diff) | |
download | nixlib-06fea81c6e3d71689b59df6e2bbc11fe01ce9056.tar nixlib-06fea81c6e3d71689b59df6e2bbc11fe01ce9056.tar.gz nixlib-06fea81c6e3d71689b59df6e2bbc11fe01ce9056.tar.bz2 nixlib-06fea81c6e3d71689b59df6e2bbc11fe01ce9056.tar.lz nixlib-06fea81c6e3d71689b59df6e2bbc11fe01ce9056.tar.xz nixlib-06fea81c6e3d71689b59df6e2bbc11fe01ce9056.tar.zst nixlib-06fea81c6e3d71689b59df6e2bbc11fe01ce9056.zip |
Merge recent master into staging
Hydra: ?compare=1150594
Diffstat (limited to 'nixos')
31 files changed, 1032 insertions, 245 deletions
diff --git a/nixos/doc/manual/man-nixos-option.xml b/nixos/doc/manual/man-nixos-option.xml index 7952847d4db5..554b29691805 100644 --- a/nixos/doc/manual/man-nixos-option.xml +++ b/nixos/doc/manual/man-nixos-option.xml @@ -17,11 +17,6 @@ <refsynopsisdiv> <cmdsynopsis> <command>nixos-option</command> - <group choice="opt"> - <option>-v</option> - <option>-d</option> - <option>-l</option> - </group> <arg choice='plain'><replaceable>option.name</replaceable></arg> </cmdsynopsis> </refsynopsisdiv> @@ -31,50 +26,13 @@ <para>This command evaluates the configuration specified in <filename>/etc/nixos/configuration.nix</filename> and returns the properties -of the option name given as argument. By default, it returns the value of -the option.</para> +of the option name given as argument.</para> <para>When the option name is not an option, the command prints the list of attributes contained in the attribute set.</para> </refsection> -<refsection><title>Options</title> - -<para>This command accepts the following options:</para> - -<variablelist> - - <varlistentry> - <term><option>--value</option>, <option>-v</option></term> - <listitem> - <para>Returns the value of the option. This is the default operation - if no other options are defined.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>--description</option>, <option>-d</option></term> - <listitem> - <para>Return the default value, the example and the description of the - option when available.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term><option>--lookup</option>, <option>-l</option></term> - <listitem> - <para>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.</para> - </listitem> - </varlistentry> - -</variablelist> - -</refsection> - - <refsection><title>Environment</title> <variablelist> @@ -103,27 +61,21 @@ grub initScript $ nixos-option boot.loader.grub.enable -true</screen></para> +Value: +true -<para>Prints option information: +Default: +true -<screen>$ 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).</screen></para> - -<para>Find the locations which are declaring and defining an option: +Whether to enable the GNU GRUB boot loader. -<screen>$ nixos-option -l hardware.firmware Declared by: - /mnt/data/nix-sources/nixos/modules/services/hardware/udev.nix + "/path/to/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix" Defined by: - /path/to/nixpkgs/nixos/modules/system/boot/kernel.nix - /path/to/nixpkgs/nixos/modules/hardware/network/rt73.nix - /path/to/nixpkgs/nixos/modules/hardware/network/intel-3945abg.nix - /path/to/nixpkgs/nixos/modules/hardware/network/intel-2200bg.nix</screen></para> + "/nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix" +</screen></para> </refsection> diff --git a/nixos/modules/config/pulseaudio.nix b/nixos/modules/config/pulseaudio.nix index 1b84bbaf10c5..fb5715022b78 100644 --- a/nixos/modules/config/pulseaudio.nix +++ b/nixos/modules/config/pulseaudio.nix @@ -10,10 +10,12 @@ let systemWide = cfg.enable && cfg.systemWide; nonSystemWide = cfg.enable && !cfg.systemWide; - uid = config.ids.uids.pulseaudio; - gid = config.ids.gids.pulseaudio; + ids = config.ids; - stateDir = "/run/pulse"; + uid = ids.uids.pulseaudio; + gid = ids.gids.pulseaudio; + + stateDir = "/var/run/pulse"; # Create pulse/client.conf even if PulseAudio is disabled so # that we can disable the autospawn feature in programs that @@ -138,6 +140,8 @@ in { group = "pulse"; extraGroups = [ "audio" ]; description = "PulseAudio system service user"; + home = stateDir; + createHome = true; }; users.extraGroups.pulse.gid = gid; @@ -147,10 +151,6 @@ in { wantedBy = [ "sound.target" ]; before = [ "sound.target" ]; environment.PULSE_RUNTIME_PATH = stateDir; - preStart = '' - mkdir -p --mode 755 ${stateDir} - chown -R pulse:pulse ${stateDir} - ''; serviceConfig = { ExecStart = "${cfg.package}/bin/pulseaudio -D --log-level=${cfg.daemon.logLevel} --system --use-pid-file -n --file=${cfg.configFile}"; PIDFile = "${stateDir}/pid"; diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix index 623cfdedd269..22f31c460802 100644 --- a/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixos/modules/installer/cd-dvd/iso-image.nix @@ -11,7 +11,7 @@ let # The Grub image. grubImage = pkgs.runCommand "grub_eltorito" {} '' - ${pkgs.grub2}/bin/grub-mkimage -O i386-pc -o tmp biosdisk iso9660 help linux linux16 chain png jpeg echo gfxmenu reboot + ${pkgs.grub2}/bin/grub-mkimage -p /boot/grub -O i386-pc -o tmp biosdisk iso9660 help linux linux16 chain png jpeg echo gfxmenu reboot cat ${pkgs.grub2}/lib/grub/*/cdboot.img tmp > $out ''; # */ diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl index c507f7f979fa..e8f100d64984 100644 --- a/nixos/modules/installer/tools/nixos-generate-config.pl +++ b/nixos/modules/installer/tools/nixos-generate-config.pl @@ -20,6 +20,13 @@ sub uniq { return @res; } +sub runCommand { + my ($cmd) = @_; + open FILE, "$cmd 2>&1 |" or die "Failed to execute: $cmd\n"; + my @ret = <FILE>; + close FILE; + return ($?, @ret); +} # Process the command line. my $outDir = "/etc/nixos"; @@ -304,10 +311,13 @@ foreach my $fs (read_file("/proc/self/mountinfo")) { # Maybe this is a bind-mount of a filesystem we saw earlier? if (defined $fsByDev{$fields[2]}) { - my $path = $fields[3]; $path = "" if $path eq "/"; - my $base = $fsByDev{$fields[2]}; - $base = "" if $base eq "/"; - $fileSystems .= <<EOF; + # Make sure this isn't a btrfs subvolume + my ($status, @msg) = runCommand("btrfs subvol show $rootDir$mountPoint"); + if (join("", @msg) =~ /ERROR:/) { + my $path = $fields[3]; $path = "" if $path eq "/"; + my $base = $fsByDev{$fields[2]}; + $base = "" if $base eq "/"; + $fileSystems .= <<EOF; fileSystems.\"$mountPoint\" = { device = \"$base$path\"; fsType = \"none\"; @@ -315,7 +325,8 @@ foreach my $fs (read_file("/proc/self/mountinfo")) { }; EOF - next; + next; + } } $fsByDev{$fields[2]} = $mountPoint; @@ -337,6 +348,30 @@ EOF } } + # Is this a btrfs filesystem? + if ($fsType eq "btrfs") { + my ($status, @id_info) = runCommand("btrfs subvol show $rootDir$mountPoint"); + if ($status != 0 || join("", @msg) =~ /ERROR:/) { + die "Failed to retreive subvolume info for $mountPoint\n"; + } + my @ids = join("", @id_info) =~ m/Object ID:[ \t\n]*([^ \t\n]*)/; + if ($#ids > 0) { + die "Btrfs subvol name for $mountPoint listed multiple times in mount\n" + } elsif ($#ids == 0) { + my ($status, @path_info) = runCommand("btrfs subvol list $rootDir$mountPoint"); + if ($status != 0) { + die "Failed to find $mountPoint subvolume id from btrfs\n"; + } + my @paths = join("", @path_info) =~ m/ID $ids[0] [^\n]* path ([^\n]*)/; + if ($#paths > 0) { + die "Btrfs returned multiple paths for a single subvolume id, mountpoint $mountPoint\n"; + } elsif ($#paths != 0) { + die "Btrfs did not return a path for the subvolume at $mountPoint\n"; + } + push @extraOptions, "subvol=$paths[0]"; + } + } + # Emit the filesystem. $fileSystems .= <<EOF; fileSystems.\"$mountPoint\" = diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh index 86952486ade0..bd334c2a3cb4 100644 --- a/nixos/modules/installer/tools/nixos-install.sh +++ b/nixos/modules/installer/tools/nixos-install.sh @@ -7,6 +7,9 @@ # * nix-env -p /nix/var/nix/profiles/system -i <nix-expr for the configuration> # * install the boot loader +# Ensure a consistent umask. +umask 0022 + # Re-exec ourselves in a private mount namespace so that our bind # mounts get cleaned up automatically. if [ "$(id -u)" = 0 ]; then @@ -243,7 +246,7 @@ chroot $mountPoint /nix/var/nix/profiles/system/activate # Ask the user to set a root password. if [ -t 0 ] ; then echo "setting root password..." - chroot $mountPoint passwd + chroot $mountPoint /var/setuid-wrappers/passwd fi diff --git a/nixos/modules/installer/tools/nixos-option.sh b/nixos/modules/installer/tools/nixos-option.sh index edc94d732084..d995787c76fe 100644 --- a/nixos/modules/installer/tools/nixos-option.sh +++ b/nixos/modules/installer/tools/nixos-option.sh @@ -11,9 +11,6 @@ usage () { # Process Arguments # ##################### -desc=false -defs=false -value=false xml=false verbose=false @@ -24,14 +21,11 @@ for arg; do if test -z "$argfun"; then case $arg in -*) - longarg="" sarg="$arg" + longarg="" while test "$sarg" != "-"; do case $sarg in --*) longarg=$arg; sarg="--";; - -d*) longarg="$longarg --description";; - -v*) longarg="$longarg --value";; - -l*) longarg="$longarg --lookup";; -*) usage;; esac # remove the first letter option @@ -42,9 +36,6 @@ for arg; do esac for larg in $longarg; do case $larg in - --description) desc=true;; - --value) value=true;; - --lookup) defs=true;; --xml) xml=true;; --verbose) verbose=true;; --help) usage;; @@ -67,16 +58,6 @@ for arg; do fi done -if $xml; then - value=true - desc=true - defs=true -fi - -if ! $defs && ! $desc; then - value=true -fi - if $verbose; then set -x else @@ -95,8 +76,7 @@ evalAttr(){ local prefix="$1" local strict="$2" local suffix="$3" - echo "(import <nixos> {}).$prefix${option:+.$option}${suffix:+.$suffix}" | - evalNix ${strict:+--strict} + echo "(import <nixos> {}).$prefix${option:+.$option}${suffix:+.$suffix}" | evalNix ${strict:+--strict} } evalOpt(){ @@ -189,35 +169,35 @@ EOF fi if test "$(evalOpt "_type" 2> /dev/null)" = '"option"'; then - $value && evalCfg 1 - - if $desc; then - $value && echo; - - if default=$(evalOpt "default" - 2> /dev/null); then - echo "Default: $default" - else - echo "Default: <None>" - fi - if example=$(evalOpt "example" - 2> /dev/null); then - echo "Example: $example" - fi - echo "Description:" - eval printf $(evalOpt "description") + echo "Value:" + evalCfg 1 + + echo + + echo "Default:" + if default=$(evalOpt "default" - 2> /dev/null); then + echo "$default" + else + echo "<None>" + fi + echo + if example=$(evalOpt "example" - 2> /dev/null); then + echo "Example: $example" fi + echo "Description:" + echo + eval printf $(evalOpt "description") - if $defs; then - $desc || $value && echo; + echo $desc; - printPath () { echo " $1"; } + printPath () { echo " $1"; } - echo "Declared by:" - nixMap printPath "$(findSources "declarations")" - echo "" - echo "Defined by:" - nixMap printPath "$(findSources "files")" - echo "" - fi + echo "Declared by:" + nixMap printPath "$(findSources "declarations")" + echo + echo "Defined by:" + nixMap printPath "$(findSources "files")" + echo else # echo 1>&2 "Warning: This value is not an option." diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix index 39da2f1f0be6..91a30695a7a5 100644 --- a/nixos/modules/installer/tools/tools.nix +++ b/nixos/modules/installer/tools/tools.nix @@ -38,6 +38,7 @@ let nixos-generate-config = makeProg { name = "nixos-generate-config"; src = ./nixos-generate-config.pl; + path = [ pkgs.btrfsProgs ]; perl = "${pkgs.perl}/bin/perl -I${pkgs.perlPackages.FileSlurp}/lib/perl5/site_perl"; }; diff --git a/nixos/modules/installer/virtualbox-demo.nix b/nixos/modules/installer/virtualbox-demo.nix index f68f8dc40aa8..49ec08996104 100644 --- a/nixos/modules/installer/virtualbox-demo.nix +++ b/nixos/modules/installer/virtualbox-demo.nix @@ -10,6 +10,9 @@ with lib; ../profiles/clone-config.nix ]; + # FIXME: UUID detection is currently broken + boot.loader.grub.fsIdentifier = "provided"; + # Allow mounting of shared folders. users.extraUsers.demo.extraGroups = [ "vboxsf" ]; diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index efd8b253cd4c..37531ad1cdfd 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -150,6 +150,7 @@ zookeeper = 140; dnsmasq = 141; uhub = 142; + yandexdisk=143; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 76d1ed8a9d43..61a98ca12ffb 100644..100755 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -161,10 +161,13 @@ ./services/misc/folding-at-home.nix ./services/misc/gitolite.nix ./services/misc/gpsd.nix + ./services/misc/mesos-master.nix + ./services/misc/mesos-slave.nix ./services/misc/nix-daemon.nix ./services/misc/nix-gc.nix ./services/misc/nixos-manual.nix ./services/misc/nix-ssh-serve.nix + ./services/misc/phd.nix ./services/misc/rippled.nix ./services/misc/rogue.nix ./services/misc/siproxd.nix @@ -192,6 +195,8 @@ ./services/network-filesystems/openafs-client/default.nix ./services/network-filesystems/rsyncd.nix ./services/network-filesystems/samba.nix + ./services/network-filesystems/diod.nix + ./services/network-filesystems/yandex-disk.nix ./services/networking/amuled.nix ./services/networking/atftpd.nix ./services/networking/avahi-daemon.nix diff --git a/nixos/modules/services/misc/mesos-master.nix b/nixos/modules/services/misc/mesos-master.nix new file mode 100644 index 000000000000..bdf88d427c5d --- /dev/null +++ b/nixos/modules/services/misc/mesos-master.nix @@ -0,0 +1,103 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.mesos.master; + +in { + + options.services.mesos = { + + master = { + enable = mkOption { + description = "Whether to enable the Mesos Master."; + default = false; + type = types.uniq types.bool; + }; + + port = mkOption { + description = "Mesos Master port"; + default = 5050; + type = types.int; + }; + + zk = mkOption { + description = '' + ZooKeeper URL (used for leader election amongst masters). + May be one of: + zk://host1:port1,host2:port2,.../mesos + zk://username:password@host1:port1,host2:port2,.../mesos + ''; + type = types.str; + }; + + workDir = mkOption { + description = "The Mesos work directory."; + default = "/var/lib/mesos/master"; + type = types.str; + }; + + extraCmdLineOptions = mkOption { + description = '' + Extra command line options for Mesos Master. + + See https://mesos.apache.org/documentation/latest/configuration/ + ''; + default = [ "" ]; + type = types.listOf types.string; + example = [ "--credentials=VALUE" ]; + }; + + quorum = mkOption { + description = '' + The size of the quorum of replicas when using 'replicated_log' based + registry. It is imperative to set this value to be a majority of + masters i.e., quorum > (number of masters)/2. + + If 0 will fall back to --registry=in_memory. + ''; + default = 0; + type = types.int; + }; + + logLevel = mkOption { + description = '' + The logging level used. Possible values: + 'INFO', 'WARNING', 'ERROR' + ''; + default = "INFO"; + type = types.str; + }; + + }; + + + }; + + + config = mkIf cfg.enable { + systemd.services.mesos-master = { + description = "Mesos Master"; + wantedBy = [ "multi-user.target" ]; + after = [ "network-interfaces.target" ]; + serviceConfig = { + ExecStart = '' + ${pkgs.mesos}/bin/mesos-master \ + --port=${toString cfg.port} \ + --zk=${cfg.zk} \ + ${if cfg.quorum == 0 then "--registry=in_memory" else "--registry=replicated_log --quorum=${cfg.quorum}"} \ + --work_dir=${cfg.workDir} \ + --logging_level=${cfg.logLevel} \ + ${toString cfg.extraCmdLineOptions} + ''; + PermissionsStartOnly = true; + }; + preStart = '' + mkdir -m 0700 -p ${cfg.workDir} + ''; + }; + }; + +} + diff --git a/nixos/modules/services/misc/mesos-slave.nix b/nixos/modules/services/misc/mesos-slave.nix new file mode 100644 index 000000000000..e9a898167161 --- /dev/null +++ b/nixos/modules/services/misc/mesos-slave.nix @@ -0,0 +1,93 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.mesos.slave; + +in { + + options.services.mesos = { + slave = { + enable = mkOption { + description = "Whether to enable the Mesos Slave."; + default = false; + type = types.uniq types.bool; + }; + + port = mkOption { + description = "Mesos Slave port"; + default = 5051; + type = types.int; + }; + + master = mkOption { + description = '' + May be one of: + zk://host1:port1,host2:port2,.../path + zk://username:password@host1:port1,host2:port2,.../path + ''; + type = types.str; + }; + + withHadoop = mkOption { + description = "Add the HADOOP_HOME to the slave."; + default = false; + type = types.bool; + }; + + workDir = mkOption { + description = "The Mesos work directory."; + default = "/var/lib/mesos/slave"; + type = types.str; + }; + + extraCmdLineOptions = mkOption { + description = '' + Extra command line options for Mesos Slave. + + See https://mesos.apache.org/documentation/latest/configuration/ + ''; + default = [ "" ]; + type = types.listOf types.string; + example = [ "--gc_delay=3days" ]; + }; + + logLevel = mkOption { + description = '' + The logging level used. Possible values: + 'INFO', 'WARNING', 'ERROR' + ''; + default = "INFO"; + type = types.str; + }; + + }; + + }; + + + config = mkIf cfg.enable { + systemd.services.mesos-slave = { + description = "Mesos Slave"; + wantedBy = [ "multi-user.target" ]; + after = [ "network-interfaces.target" ]; + serviceConfig = { + ExecStart = '' + ${pkgs.mesos}/bin/mesos-slave \ + --port=${toString cfg.port} \ + --master=${cfg.master} \ + ${optionalString cfg.withHadoop "--hadoop-home=${pkgs.hadoop}"} \ + --work_dir=${cfg.workDir} \ + --logging_level=${cfg.logLevel} \ + ${toString cfg.extraCmdLineOptions} + ''; + PermissionsStartOnly = true; + }; + preStart = '' + mkdir -m 0700 -p ${cfg.workDir} + ''; + }; + }; + +} \ No newline at end of file diff --git a/nixos/modules/services/misc/phd.nix b/nixos/modules/services/misc/phd.nix new file mode 100644 index 000000000000..e605ce5de16e --- /dev/null +++ b/nixos/modules/services/misc/phd.nix @@ -0,0 +1,52 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.phd; + +in + +{ + + ###### interface + + options = { + + services.phd = { + + enable = mkOption { + default = false; + description = " + Enable daemons for phabricator. + "; + }; + + }; + + }; + + ###### implementation + + config = mkIf cfg.enable { + + systemd.services.phd = { + path = [ pkgs.phabricator pkgs.php pkgs.mercurial pkgs.git pkgs.subversion ]; + + after = [ "httpd.service" ]; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + ExecStart = "${pkgs.phabricator}/phabricator/bin/phd start"; + ExecStop = "${pkgs.phabricator}/phabricator/bin/phd stop"; + User = "wwwrun"; + RestartSec = "30s"; + Restart = "always"; + StartLimitInterval = "1m"; + }; + }; + + }; + +} diff --git a/nixos/modules/services/network-filesystems/diod.nix b/nixos/modules/services/network-filesystems/diod.nix new file mode 100644 index 000000000000..1ab5f52d438c --- /dev/null +++ b/nixos/modules/services/network-filesystems/diod.nix @@ -0,0 +1,159 @@ +{ config, lib, pkgs, ... }: +with lib; +let + cfg = config.services.diod; + + diodBool = b: if b then "1" else "0"; + + diodConfig = pkgs.writeText "diod.conf" '' + allsquash = ${diodBool cfg.allsquash} + auth_required = ${diodBool cfg.authRequired} + exportall = ${diodBool cfg.exportall} + exportopts = "${concatStringsSep "," cfg.exportopts}" + exports = { ${concatStringsSep ", " (map (s: ''"${s}"'' ) cfg.exports)} } + listen = { ${concatStringsSep ", " (map (s: ''"${s}"'' ) cfg.listen)} } + logdest = "${cfg.logdest}" + nwthreads = ${toString cfg.nwthreads} + squashuser = "${cfg.squashuser}" + statfs_passthru = ${diodBool cfg.statfsPassthru} + userdb = ${diodBool cfg.userdb} + ${cfg.extraConfig} + ''; +in +{ + options = { + services.diod = { + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable the diod 9P file server."; + }; + + listen = mkOption { + type = types.listOf types.str; + default = [ ]; + description = '' + [ "IP:PORT" [,"IP:PORT",...] ] + List the interfaces and ports that diod should listen on. + ''; + }; + + exports = mkOption { + type = types.listOf types.path; + default = []; + description = '' + List the file systems that clients will be allowed to mount. All paths should + be fully qualified. The exports table can include two types of element: + a string element (as above), + or an alternate table element form { path="/path", opts="ro" }. + In the alternate form, the (optional) opts attribute is a comma-separated list + of export options. The two table element forms can be mixed in the exports + table. Note that although diod will not traverse file system boundaries for a + given mount due to inode uniqueness constraints, subdirectories of a file + system can be separately exported. + ''; + }; + + exportall = mkOption { + type = types.bool; + default = true; + description = '' + Export all file systems listed in /proc/mounts. If new file systems are mounted + after diod has started, they will become immediately mountable. If there is a + duplicate entry for a file system in the exports list, any options listed in + the exports entry will apply. + ''; + }; + + exportopts = mkOption { + type = types.listOf types.str; + default = []; + description = '' + Establish a default set of export options. These are overridden, not appended + to, by opts attributes in an "exports" entry. + ''; + }; + + nwthreads = mkOption { + type = types.int; + default = 16; + description = '' + Sets the (fixed) number of worker threads created to handle 9P + requests for a unique aname. + ''; + }; + + authRequired = mkOption { + type = types.bool; + default = false; + description = '' + Allow clients to connect without authentication, i.e. without a valid MUNGE credential. + ''; + }; + + userdb = mkOption { + type = types.bool; + default = false; + description = '' + This option disables password/group lookups. It allows any uid to attach and + assumes gid=uid, and supplementary groups contain only the primary gid. + ''; + }; + + allsquash = mkOption { + type = types.bool; + default = true; + description = '' + Remap all users to "nobody". The attaching user need not be present in the + password file. + ''; + }; + + squashuser = mkOption { + type = types.str; + default = "nobody"; + description = '' + Change the squash user. The squash user must be present in the password file. + ''; + }; + + logdest = mkOption { + type = types.str; + default = "syslog:daemon:err"; + description = '' + Set the destination for logging. + The value has the form of "syslog:facility:level" or "filename". + ''; + }; + + + statfsPassthru = mkOption { + type = types.bool; + default = false; + description = '' + This option configures statfs to return the host file system's type + rather than V9FS_MAGIC. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = "Extra configuration options for diod.conf."; + }; + }; + }; + + config = mkIf config.services.diod.enable { + environment.systemPackages = [ pkgs.diod ]; + + systemd.services.diod = { + description = "diod 9P file server"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + serviceConfig = { + ExecStart = "${pkgs.diod}/sbin/diod -c ${diodConfig}"; + }; + }; + }; +} diff --git a/nixos/modules/services/network-filesystems/yandex-disk.nix b/nixos/modules/services/network-filesystems/yandex-disk.nix new file mode 100644 index 000000000000..df9626d17c92 --- /dev/null +++ b/nixos/modules/services/network-filesystems/yandex-disk.nix @@ -0,0 +1,104 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + cfg = config.services.yandex-disk; + + dir = "/var/lib/yandex-disk"; + + u = if cfg.user != null then cfg.user else "yandexdisk"; + +in + +{ + + ###### interface + + options = { + + services.yandex-disk = { + + enable = mkOption { + default = false; + description = " + Whether to enable Yandex-disk client. See https://disk.yandex.ru/ + "; + }; + + username = mkOption { + default = ""; + type = types.string; + description = '' + Your yandex.com login name. + ''; + }; + + password = mkOption { + default = ""; + type = types.string; + description = '' + Your yandex.com password. Warning: it will be world-readable in /nix/store. + ''; + }; + + user = mkOption { + default = null; + description = '' + The user the yandex-disk daemon should run as. + ''; + }; + + directory = mkOption { + default = "/home/Yandex.Disk"; + description = "The directory to use for Yandex.Disk storage"; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + users.extraUsers = mkIf (cfg.user == null) [ { + name = u; + uid = config.ids.uids.yandexdisk; + group = "nogroup"; + home = dir; + } ]; + + systemd.services.yandex-disk = { + description = "Yandex-disk server"; + + after = [ "network.target" ]; + + wantedBy = [ "multi-user.target" ]; + + # FIXME: have to specify ${directory} here as well + unitConfig.RequiresMountsFor = dir; + + script = '' + mkdir -p -m 700 ${dir} + chown ${u} ${dir} + + if ! test -d "${cfg.directory}" ; then + mkdir -p -m 755 ${cfg.directory} || + exit 1 + fi + + ${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${u} \ + -c '${pkgs.yandex-disk}/bin/yandex-disk token -p ${cfg.password} ${cfg.username} ${dir}/token' + + ${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} ${u} \ + -c '${pkgs.yandex-disk}/bin/yandex-disk start --no-daemon -a ${dir}/token -d ${cfg.directory}' + ''; + + }; + }; + +} + diff --git a/nixos/modules/services/networking/copy-com.nix b/nixos/modules/services/networking/copy-com.nix new file mode 100644 index 000000000000..36bd29109b8a --- /dev/null +++ b/nixos/modules/services/networking/copy-com.nix @@ -0,0 +1,53 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.copy-com; + +in + +{ + options = { + + services.copy-com = { + + enable = mkOption { + default = false; + description = " + Enable the copy.com client. + + The first time copy.com is run, it needs to be configured. Before enabling run + copy_console manually. + "; + }; + + user = mkOption { + description = "The user for which copy should run."; + }; + + debug = mkOption { + default = false; + description = "Output more."; + }; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ pkgs.postfix ]; + + systemd.services."copy-com-${cfg.user}" = { + description = "Copy.com Client"; + after = [ "network.target" "local-fs.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = "${pkgs.copy-com}/bin/copy_console ${if cfg.debug then "-consoleOutput -debugToConsole=dirwatch,path-watch,csm_path,csm -debug -console" else ""}"; + User = "${cfg.user}"; + }; + + }; + }; + +} + diff --git a/nixos/modules/services/networking/dnsmasq.nix b/nixos/modules/services/networking/dnsmasq.nix index d2a8af6ac8b1..5c68dd89fb12 100644 --- a/nixos/modules/services/networking/dnsmasq.nix +++ b/nixos/modules/services/networking/dnsmasq.nix @@ -11,7 +11,10 @@ let conf-file=/etc/dnsmasq-conf.conf resolv-file=/etc/dnsmasq-resolv.conf ''} - ${cfg.extraConfig} + ${flip concatMapStrings cfg.servers (server: '' + server=${server} + '')} + ${cfg.extraConfig} ''; in @@ -43,12 +46,10 @@ in default = []; example = [ "8.8.8.8" "8.8.4.4" ]; description = '' - The parameter to dnsmasq -S. + The DNS servers which dnsmasq should query. ''; }; - - extraConfig = mkOption { type = types.string; default = ""; @@ -67,8 +68,8 @@ in config = mkIf config.services.dnsmasq.enable { - environment.systemPackages = [ dnsmasq ] - ++ (if cfg.resolveLocalQueries then [ pkgs.openresolv ] else []); + networking.nameservers = + optional cfg.resolveLocalQueries "127.0.0.1"; services.dbus.packages = [ dnsmasq ]; @@ -83,10 +84,14 @@ in description = "dnsmasq daemon"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; + path = [ dnsmasq ]; + preStart = '' + touch /etc/dnsmasq-{conf,resolv}.conf + dnsmasq --test + ''; serviceConfig = { Type = "dbus"; BusName = "uk.org.thekelleys.dnsmasq"; - ExecStartPre = "${dnsmasq}/bin/dnsmasq --test"; ExecStart = "${dnsmasq}/bin/dnsmasq -k --enable-dbus --user=dnsmasq -C ${dnsmasqConf}"; ExecReload = "${dnsmasq}/bin/kill -HUP $MAINPID"; }; diff --git a/nixos/modules/services/networking/nat.nix b/nixos/modules/services/networking/nat.nix index e8d9d00cc0a2..b6fa3b79eb2f 100644 --- a/nixos/modules/services/networking/nat.nix +++ b/nixos/modules/services/networking/nat.nix @@ -75,6 +75,17 @@ in ''; }; + networking.nat.forwardPorts = mkOption { + type = types.listOf types.attrs; + default = []; + example = [ { sourcePort = 8080; destination = "10.0.0.1:80"; } ]; + description = + '' + List of forwarded ports from the external interface to + internal destinations by using DNAT. + ''; + }; + }; @@ -118,6 +129,14 @@ in -s '${range}' -o ${cfg.externalInterface} ${dest} '') cfg.internalIPs} + # NAT from external ports to internal ports. + ${concatMapStrings (fwd: '' + iptables -w -t nat -A PREROUTING \ + -i ${cfg.externalInterface} -p tcp \ + --dport ${builtins.toString fwd.sourcePort} \ + -j DNAT --to-destination ${fwd.destination} + '') cfg.forwardPorts} + echo 1 > /proc/sys/net/ipv4/ip_forward ''; diff --git a/nixos/modules/services/networking/unbound.nix b/nixos/modules/services/networking/unbound.nix index 415ff13bdda5..73b10c1d5611 100644 --- a/nixos/modules/services/networking/unbound.nix +++ b/nixos/modules/services/networking/unbound.nix @@ -6,8 +6,6 @@ let cfg = config.services.unbound; - username = "unbound"; - stateDir = "/var/lib/unbound"; access = concatMapStrings (x: " access-control: ${x} allow\n") cfg.allowedAccess; @@ -21,21 +19,13 @@ let confFile = pkgs.writeText "unbound.conf" '' server: directory: "${stateDir}" - username: ${username} - # make sure unbound can access entropy from inside the chroot. - # e.g. on linux the use these commands (on BSD, devfs(8) is used): - # mount --bind -n /dev/random /etc/unbound/dev/random - # and mount --bind -n /dev/log /etc/unbound/dev/log + username: unbound chroot: "${stateDir}" - # logfile: "${stateDir}/unbound.log" #uncomment to use logfile. - pidfile: "${stateDir}/unbound.pid" - verbosity: 1 # uncomment and increase to get more logging. + pidfile: "" ${interfaces} ${access} - - ${forward} - ${cfg.extraConfig} + ${forward} ''; in @@ -82,7 +72,7 @@ in environment.systemPackages = [ pkgs.unbound ]; users.extraUsers = singleton { - name = username; + name = "unbound"; uid = config.ids.uids.unbound; description = "unbound daemon user"; home = stateDir; @@ -96,8 +86,18 @@ in wants = [" nss-lookup.target" ]; wantedBy = [ "multi-user.target" ]; - path = [ pkgs.unbound ]; - serviceConfig.ExecStart = "${pkgs.unbound}/sbin/unbound -d -c ${confFile}"; + preStart = '' + mkdir -m 0755 -p ${stateDir}/dev/ + cp ${confFile} ${stateDir}/unbound.conf + chown unbound ${stateDir} + touch ${stateDir}/dev/random + ${pkgs.utillinux}/bin/mount --bind -n /dev/random ${stateDir}/dev/random + ''; + + serviceConfig = { + ExecStart = "${pkgs.unbound}/sbin/unbound -d -c ${stateDir}/unbound.conf"; + ExecStopPost="${pkgs.utillinux}/bin/umount ${stateDir}/dev/random"; + }; }; }; diff --git a/nixos/modules/services/printing/cupsd.nix b/nixos/modules/services/printing/cupsd.nix index d229c610669f..8a8085cad280 100644 --- a/nixos/modules/services/printing/cupsd.nix +++ b/nixos/modules/services/printing/cupsd.nix @@ -35,7 +35,7 @@ let bindir = pkgs.buildEnv { name = "cups-progs"; paths = cfg.drivers; - pathsToLink = [ "/lib/cups" "/share/cups" "/bin" ]; + pathsToLink = [ "/lib/cups" "/share/cups" "/bin" "/etc/cups" ]; postBuild = cfg.bindirCmds; }; @@ -89,6 +89,20 @@ in ''; }; + clientConf = mkOption { + type = types.lines; + default = ""; + example = + '' + ServerName server.example.com + Encryption Never + ''; + description = '' + The contents of the client configuration. + (<filename>client.conf</filename>) + ''; + }; + drivers = mkOption { type = types.listOf types.path; example = literalExample "[ pkgs.splix ]"; @@ -124,6 +138,14 @@ in environment.systemPackages = [ cups ]; + environment.variables.CUPS_SERVERROOT = "/etc/cups"; + + environment.etc = [ + { source = pkgs.writeText "client.conf" cfg.clientConf; + target = "cups/client.conf"; + } + ]; + services.dbus.packages = [ cups ]; # Cups uses libusb to talk to printers, and does not use the diff --git a/nixos/modules/services/web-servers/apache-httpd/phabricator.nix b/nixos/modules/services/web-servers/apache-httpd/phabricator.nix index c7a9bdf68c56..e4e3aac8d411 100644 --- a/nixos/modules/services/web-servers/apache-httpd/phabricator.nix +++ b/nixos/modules/services/web-servers/apache-httpd/phabricator.nix @@ -1,35 +1,30 @@ { config, lib, pkgs, ... }: + +with lib; + let - phabricatorRoot = pkgs.stdenv.mkDerivation rec { - version = "2014-05-12"; - name = "phabricator-${version}"; - srcLibphutil = pkgs.fetchgit { - url = git://github.com/facebook/libphutil.git; - rev = "2f3b5a1cf6ea464a0250d4b1c653a795a90d2716"; - sha256 = "9598cec400984dc149162f1e648814a54ea0cd34fcd529973dc83f5486fdd9fd"; - }; - srcArcanist = pkgs.fetchgit { - url = git://github.com/facebook/arcanist.git; - rev = "54c377448db8dbc40f0ca86d43c837d30e493485"; - sha256 = "086db3c0d1154fbad23e7c6def31fd913384ee20247b329515838b669c3028e0"; - }; - srcPhabricator = pkgs.fetchgit { - url = git://github.com/facebook/phabricator.git; - rev = "1644ef185ecf1e9fca3eb6b16351ef46b19d110f"; - sha256 = "e1135e4ba76d53f48aad4161563035414ed7e878f39a8a34a875a01b41b2a084"; - }; - - buildCommand = '' - mkdir -p $out - cp -R ${srcLibphutil} $out/libphutil - cp -R ${srcArcanist} $out/arcanist - cp -R ${srcPhabricator} $out/phabricator - ''; - }; + phabricatorRoot = pkgs.phabricator; in { + enablePHP = true; extraApacheModules = [ "mod_rewrite" ]; DocumentRoot = "${phabricatorRoot}/phabricator/webroot"; + + options = { + git = mkOption { + default = true; + description = "Enable git repositories."; + }; + mercurial = mkOption { + default = true; + description = "Enable mercurial repositories."; + }; + subversion = mkOption { + default = true; + description = "Enable subversion repositories."; + }; + }; + extraConfig = '' DocumentRoot ${phabricatorRoot}/phabricator/webroot @@ -38,4 +33,18 @@ in { RewriteRule ^/favicon.ico - [L,QSA] RewriteRule ^(.*)$ /index.php?__path__=$1 [B,L,QSA] ''; + + extraServerPath = [ + "${pkgs.which}" + "${pkgs.diffutils}" + ] ++ + (if config.mercurial then ["${pkgs.mercurial}"] else []) ++ + (if config.subversion then ["${pkgs.subversion}"] else []) ++ + (if config.git then ["${pkgs.git}"] else []); + + startupScript = pkgs.writeScript "activatePhabricator" '' + mkdir -p /var/repo + chown wwwrun /var/repo + ''; + } diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix index 0cc060db8f90..bc9a155ac95b 100644 --- a/nixos/modules/system/boot/loader/grub/grub.nix +++ b/nixos/modules/system/boot/loader/grub/grub.nix @@ -6,7 +6,8 @@ let cfg = config.boot.loader.grub; - realGrub = if cfg.version == 1 then pkgs.grub else pkgs.grub2; + realGrub = if cfg.version == 1 then pkgs.grub + else pkgs.grub2.override { zfsSupport = cfg.zfsSupport; }; grub = # Don't include GRUB if we're only generating a GRUB menu (e.g., @@ -25,11 +26,12 @@ let inherit (cfg) version extraConfig extraPerEntryConfig extraEntries extraEntriesBeforeNixOS extraPrepareConfig configurationLimit copyKernels timeout - default devices explicitBootRoot; + default devices fsIdentifier; path = (makeSearchPath "bin" [ - pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.findutils pkgs.diffutils + pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.findutils pkgs.diffutils pkgs.btrfsProgs + pkgs.utillinux ]) + ":" + (makeSearchPath "sbin" [ - pkgs.mdadm + pkgs.mdadm pkgs.utillinux ]); }); @@ -209,12 +211,26 @@ in ''; }; - explicitBootRoot = mkOption { - default = ""; - type = types.str; + fsIdentifier = mkOption { + default = "uuid"; + type = types.addCheck types.str + (type: type == "uuid" || type == "label" || type == "provided"); description = '' - The relative path of /boot within the parent volume. Leave empty - if /boot is not a btrfs subvolume. + Determines how grub will identify devices when generating the + configuration file. A value of uuid / label signifies that grub + will always resolve the uuid or label of the device before using + it in the configuration. A value of provided means that grub will + use the device name as show in <command>df</command> or + <command>mount</command>. Note, zfs zpools / datasets are ignored + and will always be mounted using their labels. + ''; + }; + + zfsSupport = mkOption { + default = false; + type = types.bool; + description = '' + Whether grub should be build against libzfs. ''; }; @@ -260,6 +276,9 @@ in ${pkgs.coreutils}/bin/cp -pf "${v}" "/boot/${n}" '') config.boot.loader.grub.extraFiles); + assertions = [{ assertion = !cfg.zfsSupport || cfg.version == 2; + message = "Only grub version 2 provides zfs support";}]; + }) ]; diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl index b4900358a5dc..2dad8b36db32 100644 --- a/nixos/modules/system/boot/loader/grub/install-grub.pl +++ b/nixos/modules/system/boot/loader/grub/install-grub.pl @@ -1,5 +1,6 @@ use strict; use warnings; +use Class::Struct; use XML::LibXML; use File::Basename; use File::Path; @@ -27,6 +28,14 @@ sub writeFile { close FILE or die; } +sub runCommand { + my ($cmd) = @_; + open FILE, "$cmd 2>/dev/null |" or die "Failed to execute: $cmd\n"; + my @ret = <FILE>; + close FILE; + return ($?, @ret); +} + my $grub = get("grub"); my $grubVersion = int(get("version")); my $extraConfig = get("extraConfig"); @@ -39,7 +48,7 @@ my $configurationLimit = int(get("configurationLimit")); my $copyKernels = get("copyKernels") eq "true"; my $timeout = int(get("timeout")); my $defaultEntry = int(get("default")); -my $explicitBootRoot = get("explicitBootRoot"); +my $fsIdentifier = get("fsIdentifier"); $ENV{'PATH'} = get("path"); die "unsupported GRUB version\n" if $grubVersion != 1 && $grubVersion != 2; @@ -48,23 +57,114 @@ print STDERR "updating GRUB $grubVersion menu...\n"; mkpath("/boot/grub", 0, 0700); - # Discover whether /boot is on the same filesystem as / and # /nix/store. If not, then all kernels and initrds must be copied to -# /boot, and all paths in the GRUB config file must be relative to the -# root of the /boot filesystem. `$bootRoot' is the path to be -# prepended to paths under /boot. -my $bootRoot = "/boot"; -if (stat("/")->dev != stat("/boot")->dev) { - $bootRoot = ""; - $copyKernels = 1; -} elsif (stat("/boot")->dev != stat("/nix/store")->dev) { +# /boot. +if (stat("/boot")->dev != stat("/nix/store")->dev) { $copyKernels = 1; } -if ($explicitBootRoot ne "") { - $bootRoot = $explicitBootRoot; +# Discover information about the location of /boot +struct(Fs => { + device => '$', + type => '$', + mount => '$', +}); +sub GetFs { + my ($dir) = @_; + my ($status, @dfOut) = runCommand("df -T $dir"); + if ($status != 0 || $#dfOut != 1) { + die "Failed to retrieve output about $dir from `df`"; + } + my @boot = split(/[ \n\t]+/, $dfOut[1]); + return Fs->new(device => $boot[0], type => $boot[1], mount => $boot[6]); } +struct (Grub => { + path => '$', + search => '$', +}); +my $driveid = 1; +sub GrubFs { + my ($dir) = @_; + my $fs = GetFs($dir); + my $path = "/" . substr($dir, length($fs->mount)); + my $search = ""; + + if ($grubVersion > 1) { + # ZFS is completely separate logic as zpools are always identified by a label + # or custom UUID + if ($fs->type eq 'zfs') { + my $sid = index($fs->device, '/'); + + if ($sid < 0) { + $search = '--label ' . $fs->device; + $path = '/@' . $path; + } else { + $search = '--label ' . substr($fs->device, 0, $sid); + $path = '/' . substr($fs->device, $sid) . '/@' . $path; + } + } else { + my %types = ('uuid' => '--fs-uuid', 'label' => '--label'); + + if ($fsIdentifier eq 'provided') { + # If the provided dev is identifying the partition using a label or uuid, + # we should get the label / uuid and do a proper search + my @matches = $fs->device =~ m/\/dev\/disk\/by-(label|uuid)\/(.*)/; + if ($#matches > 1) { + die "Too many matched devices" + } elsif ($#matches == 1) { + $search = "$types{$matches[0]} $matches[1]" + } + } else { + # Determine the identifying type + $search = $types{$fsIdentifier} . ' '; + + # Based on the type pull in the identifier from the system + my ($status, @devInfo) = runCommand("blkid -o export @{[$fs->device]}"); + if ($status != 0) { + die "Failed to get blkid info for @{[$fs->mount]} on @{[$fs->device]}"; + } + my @matches = join("", @devInfo) =~ m/@{[uc $fsIdentifier]}=([^\n]*)/; + if ($#matches != 0) { + die "Couldn't find a $types{$fsIdentifier} for @{[$fs->device]}\n" + } + $search .= $matches[0]; + } + + # BTRFS is a special case in that we need to fix the referrenced path based on subvolumes + if ($fs->type eq 'btrfs') { + my ($status, @id_info) = runCommand("btrfs subvol show @{[$fs->mount]}"); + if ($status != 0) { + die "Failed to retrieve subvolume info for @{[$fs->mount]}\n"; + } + my @ids = join("", @id_info) =~ m/Object ID:[ \t\n]*([^ \t\n]*)/; + if ($#ids > 0) { + die "Btrfs subvol name for @{[$fs->device]} listed multiple times in mount\n" + } elsif ($#ids == 0) { + my ($status, @path_info) = runCommand("btrfs subvol list @{[$fs->mount]}"); + if ($status != 0) { + die "Failed to find @{[$fs->mount]} subvolume id from btrfs\n"; + } + my @paths = join("", @path_info) =~ m/ID $ids[0] [^\n]* path ([^\n]*)/; + if ($#paths > 0) { + die "Btrfs returned multiple paths for a single subvolume id, mountpoint @{[$fs->mount]}\n"; + } elsif ($#paths != 0) { + die "Btrfs did not return a path for the subvolume at @{[$fs->mount]}\n"; + } + $path = "/$paths[0]$path"; + } + } + } + if (not $search eq "") { + $search = "search --set=drive$driveid " . $search; + $path = "(\$drive$driveid)$path"; + $driveid += 1; + } + } + return Grub->new(path => $path, search => $search); +} +my $grubBoot = GrubFs("/boot"); +my $grubStore = GrubFs("/nix/store"); # Generate the header. my $conf .= "# Automatically generated. DO NOT EDIT THIS FILE!\n"; @@ -76,12 +176,17 @@ if ($grubVersion == 1) { "; if ($splashImage) { copy $splashImage, "/boot/background.xpm.gz" or die "cannot copy $splashImage to /boot\n"; - $conf .= "splashimage $bootRoot/background.xpm.gz\n"; + $conf .= "splashimage " . $grubBoot->path . "/background.xpm.gz\n"; } } else { + if ($copyKernels == 0) { + $conf .= " + " . $grubStore->search; + } $conf .= " + " . $grubBoot->search . " if [ -s \$prefix/grubenv ]; then load_env fi @@ -102,7 +207,7 @@ else { set timeout=$timeout fi - if loadfont $bootRoot/grub/fonts/unicode.pf2; then + if loadfont " . $grubBoot->path . "/grub/fonts/unicode.pf2; then set gfxmode=640x480 insmod gfxterm insmod vbe @@ -116,7 +221,7 @@ else { copy $splashImage, "/boot/background.png" or die "cannot copy $splashImage to /boot\n"; $conf .= " insmod png - if background_image $bootRoot/background.png; then + if background_image " . $grubBoot->path . "/background.png; then set color_normal=white/black set color_highlight=black/white else @@ -138,7 +243,7 @@ mkpath("/boot/kernels", 0, 0755) if $copyKernels; sub copyToKernelsDir { my ($path) = @_; - return $path unless $copyKernels; + return $grubStore->path . substr($path, length("/nix/store")) unless $copyKernels; $path =~ /\/nix\/store\/(.*)/ or die; my $name = $1; $name =~ s/\//-/g; my $dst = "/boot/kernels/$name"; @@ -151,7 +256,7 @@ sub copyToKernelsDir { rename $tmp, $dst or die "cannot rename $tmp to $dst\n"; } $copied{$dst} = 1; - return "$bootRoot/kernels/$name"; + return $grubBoot->path . "/kernels/$name"; } sub addEntry { @@ -178,6 +283,10 @@ sub addEntry { $conf .= " " . ($xen ? "module" : "initrd") . " $initrd\n\n"; } else { $conf .= "menuentry \"$name\" {\n"; + $conf .= $grubBoot->search . "\n"; + if ($copyKernels == 0) { + $conf .= $grubStore->search . "\n"; + } $conf .= " $extraPerEntryConfig\n" if $extraPerEntryConfig; $conf .= " multiboot $xen $xenParams\n" if $xen; $conf .= " " . ($xen ? "module" : "linux") . " $kernel $kernelParams\n"; @@ -195,7 +304,7 @@ addEntry("NixOS - Default", $defaultConfig); $conf .= "$extraEntries\n" unless $extraEntriesBeforeNixOS; # extraEntries could refer to @bootRoot@, which we have to substitute -$conf =~ s/\@bootRoot\@/$bootRoot/g; +$conf =~ s/\@bootRoot\@/$grubBoot->path/g; # Emit submenus for all system profiles. sub addProfile { diff --git a/nixos/modules/tasks/cpu-freq.nix b/nixos/modules/tasks/cpu-freq.nix index a8c63c134287..70bbee8474eb 100644 --- a/nixos/modules/tasks/cpu-freq.nix +++ b/nixos/modules/tasks/cpu-freq.nix @@ -30,9 +30,7 @@ in config = mkIf (!config.boot.isContainer && config.powerManagement.cpuFreqGovernor != null) { - boot.kernelModules = [ "acpi-cpufreq" "speedstep-lib" "pcc-cpufreq" - "cpufreq_${cfg.cpuFreqGovernor}" - ]; + boot.kernelModules = [ "cpufreq_${cfg.cpuFreqGovernor}" ]; environment.systemPackages = [ cpupower ]; diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix index d7deb44c407c..1c4bbc16b499 100644 --- a/nixos/modules/tasks/filesystems/zfs.nix +++ b/nixos/modules/tasks/filesystems/zfs.nix @@ -133,7 +133,7 @@ in }; boot.initrd = mkIf inInitrd { - kernelModules = [ "spl" "zfs" ] ; + kernelModules = [ "spl" "zfs" ]; extraUtilsCommands = '' cp -v ${zfsPkg}/sbin/zfs $out/bin @@ -148,6 +148,10 @@ in ''; }; + boot.loader.grub = mkIf inInitrd { + zfsSupport = true; + }; + systemd.services."zpool-import" = { description = "Import zpools"; after = [ "systemd-udev-settle.service" ]; diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index 2adb4bcfabab..868039177d87 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -1,6 +1,7 @@ -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, utils, ... }: with lib; +with utils; let @@ -10,6 +11,10 @@ let hasSits = cfg.sits != { }; hasBonds = cfg.bonds != { }; + # We must escape interfaces due to the systemd interpretation + subsystemDevice = interface: + "sys-subsystem-net-devices-${escapeSystemdPath interface}.device"; + addrOpts = v: assert v == 4 || v == 6; { @@ -138,8 +143,6 @@ let Whether this interface is virtual and should be created by tunctl. This is mainly useful for creating bridges between a host a virtual network such as VPN or a virtual machine. - - Defaults to tap device, unless interface contains "tun" in its name. ''; }; @@ -151,6 +154,15 @@ let ''; }; + virtualType = mkOption { + default = null; + type = types.nullOr (types.addCheck types.str (v: v == "tun" || v == "tap")); + description = '' + The explicit type of interface to create. Accepts tun or tap strings. + Also accepts null to implicitly detect the type of device. + ''; + }; + proxyARP = mkOption { default = false; type = types.bool; @@ -596,8 +608,8 @@ in nameValuePair "${i.name}-cfg" { description = "Configuration of ${i.name}"; wantedBy = [ "network-interfaces.target" ]; - bindsTo = [ "sys-subsystem-net-devices-${i.name}.device" ]; - after = [ "sys-subsystem-net-devices-${i.name}.device" ]; + bindsTo = [ (subsystemDevice i.name) ]; + after = [ (subsystemDevice i.name) ]; serviceConfig.Type = "oneshot"; serviceConfig.RemainAfterExit = true; path = [ pkgs.iproute pkgs.gawk ]; @@ -673,26 +685,32 @@ in ''); }; - createTunDevice = i: nameValuePair "${i.name}" + createTunDevice = i: nameValuePair "${i.name}-netdev" { description = "Virtual Network Interface ${i.name}"; requires = [ "dev-net-tun.device" ]; after = [ "dev-net-tun.device" ]; - wantedBy = [ "network.target" ]; - requiredBy = [ "sys-subsystem-net-devices-${i.name}.device" ]; - serviceConfig = - { Type = "oneshot"; - RemainAfterExit = true; - ExecStart = "${pkgs.tunctl}/bin/tunctl -t '${i.name}' -u '${i.virtualOwner}'"; - ExecStop = "${pkgs.tunctl}/bin/tunctl -d '${i.name}'"; - }; + wantedBy = [ "network.target" (subsystemDevice i.name) ]; + path = [ pkgs.iproute ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = '' + ip tuntap add dev "${i.name}" \ + ${optionalString (i.virtualType != null) "mode ${i.virtualType}"} \ + user "${i.virtualOwner}" + ''; + postStop = '' + ip link del ${i.name} + ''; }; - createBridgeDevice = n: v: - let - deps = map (i: "sys-subsystem-net-devices-${i}.device") v.interfaces; + createBridgeDevice = n: v: nameValuePair "${n}-netdev" + (let + deps = map subsystemDevice v.interfaces; in { description = "Bridge Interface ${n}"; - wantedBy = [ "network.target" "sys-subsystem-net-devices-${n}.device" ]; + wantedBy = [ "network.target" (subsystemDevice n) ]; bindsTo = deps; after = deps; serviceConfig.Type = "oneshot"; @@ -725,14 +743,14 @@ in ip link set "${n}" down brctl delbr "${n}" ''; - }; + }); - createBondDevice = n: v: - let - deps = map (i: "sys-subsystem-net-devices-${i}.device") v.interfaces; + createBondDevice = n: v: nameValuePair "${n}-netdev" + (let + deps = map subsystemDevice v.interfaces; in { description = "Bond Interface ${n}"; - wantedBy = [ "network.target" "sys-subsystem-net-devices-${n}.device" ]; + wantedBy = [ "network.target" (subsystemDevice n) ]; bindsTo = deps; after = deps; serviceConfig.Type = "oneshot"; @@ -764,14 +782,14 @@ in ifenslave -d "${n}" ip link delete "${n}" ''; - }; + }); - createSitDevice = n: v: - let - deps = optional (v.dev != null) "sys-subsystem-net-devices-${v.dev}.device"; + createSitDevice = n: v: nameValuePair "${n}-netdev" + (let + deps = optional (v.dev != null) (subsystemDevice v.dev); in { description = "6-to-4 Tunnel Interface ${n}"; - wantedBy = [ "network.target" "sys-subsystem-net-devices-${n}.device" ]; + wantedBy = [ "network.target" (subsystemDevice n) ]; bindsTo = deps; after = deps; serviceConfig.Type = "oneshot"; @@ -790,14 +808,14 @@ in postStop = '' ip link delete "${n}" ''; - }; + }); - createVlanDevice = n: v: - let - deps = [ "sys-subsystem-net-devices-${v.interface}.device" ]; + createVlanDevice = n: v: nameValuePair "${n}-netdev" + (let + deps = [ (subsystemDevice v.interface) ]; in { description = "Vlan Interface ${n}"; - wantedBy = [ "network.target" "sys-subsystem-net-devices-${n}.device" ]; + wantedBy = [ "network.target" (subsystemDevice n) ]; bindsTo = deps; after = deps; serviceConfig.Type = "oneshot"; @@ -812,15 +830,15 @@ in postStop = '' ip link delete "${n}" ''; - }; + }); in listToAttrs ( map configureInterface interfaces ++ map createTunDevice (filter (i: i.virtual) interfaces)) - // mapAttrs createBridgeDevice cfg.bridges - // mapAttrs createBondDevice cfg.bonds - // mapAttrs createSitDevice cfg.sits - // mapAttrs createVlanDevice cfg.vlans + // mapAttrs' createBridgeDevice cfg.bridges + // mapAttrs' createBondDevice cfg.bonds + // mapAttrs' createSitDevice cfg.sits + // mapAttrs' createVlanDevice cfg.vlans // { "network-setup" = networkSetup; }; # Set the host and domain names in the activation script. Don't diff --git a/nixos/modules/virtualisation/docker.nix b/nixos/modules/virtualisation/docker.nix index a0aa61353269..1ce066cdc73d 100644 --- a/nixos/modules/virtualisation/docker.nix +++ b/nixos/modules/virtualisation/docker.nix @@ -59,6 +59,7 @@ in config = mkIf cfg.enable (mkMerge [ { environment.systemPackages = [ pkgs.docker ]; + users.extraGroups.docker.gid = config.ids.gids.docker; } (mkIf cfg.socketActivation { diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix index dae3b9210a86..0c72bae35bbc 100644 --- a/nixos/release-combined.nix +++ b/nixos/release-combined.nix @@ -52,6 +52,11 @@ in rec { (all nixos.tests.installer.lvm) (all nixos.tests.installer.separateBoot) (all nixos.tests.installer.simple) + (all nixos.tests.installer.simpleLabels) + (all nixos.tests.installer.simpleProvided) + (all nixos.tests.installer.btrfsSimple) + (all nixos.tests.installer.btrfsSubvols) + (all nixos.tests.installer.btrfsSubvolDefault) (all nixos.tests.ipv6) (all nixos.tests.kde4) (all nixos.tests.login) diff --git a/nixos/release.nix b/nixos/release.nix index e2b93640f917..d4e1a3737e3b 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -231,7 +231,8 @@ in rec { tests.installer.simpleLabels = forAllSystems (system: (import tests/installer.nix { inherit system; }).simpleLabels.test); tests.installer.simpleProvided = forAllSystems (system: (import tests/installer.nix { inherit system; }).simpleProvided.test); tests.installer.btrfsSimple = forAllSystems (system: (import tests/installer.nix { inherit system; }).btrfsSimple.test); - #tests.installer.btrfsSubvols = forAllSystems (system: (import tests/installer.nix { inherit system; }).btrfsSubvols.test); + tests.installer.btrfsSubvols = forAllSystems (system: (import tests/installer.nix { inherit system; }).btrfsSubvols.test); + tests.installer.btrfsSubvolDefault = forAllSystems (system: (import tests/installer.nix { inherit system; }).btrfsSubvolDefault.test); tests.influxdb = callTest tests/influxdb.nix {}; tests.ipv6 = callTest tests/ipv6.nix {}; tests.jenkins = callTest tests/jenkins.nix {}; diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix index 6ee52fd63d8b..66ab2567e197 100644 --- a/nixos/tests/installer.nix +++ b/nixos/tests/installer.nix @@ -35,8 +35,8 @@ let # The configuration to install. - makeConfig = { testChannel, useEFI, grubVersion, grubDevice }: pkgs.writeText "configuration.nix" - '' + makeConfig = { testChannel, useEFI, grubVersion, grubDevice, grubIdentifier }: + pkgs.writeText "configuration.nix" '' { config, pkgs, modulesPath, ... }: { imports = @@ -54,6 +54,7 @@ let ''} boot.loader.grub.device = "${grubDevice}"; boot.loader.grub.extraConfig = "serial; terminal_output.serial"; + boot.loader.grub.fsIdentifier = "${grubIdentifier}"; ''} environment.systemPackages = [ ${optionalString testChannel "pkgs.rlwrap"} ]; @@ -93,7 +94,7 @@ let # disk, and then reboot from the hard disk. It's parameterized with # a test script fragment `createPartitions', which must create # partitions and filesystems. - testScriptFun = { createPartitions, testChannel, useEFI, grubVersion, grubDevice }: + testScriptFun = { createPartitions, testChannel, useEFI, grubVersion, grubDevice, grubIdentifier }: let # FIXME: OVMF doesn't boot from virtio http://www.mail-archive.com/edk2-devel@lists.sourceforge.net/msg01501.html iface = if useEFI || grubVersion == 1 then "scsi" else "virtio"; @@ -161,7 +162,7 @@ let $machine->succeed("cat /mnt/etc/nixos/hardware-configuration.nix >&2"); $machine->copyFileFromHost( - "${ makeConfig { inherit testChannel useEFI grubVersion grubDevice; } }", + "${ makeConfig { inherit testChannel useEFI grubVersion grubDevice grubIdentifier; } }", "/mnt/etc/nixos/configuration.nix"); # Perform the installation. @@ -216,13 +217,13 @@ let makeInstallerTest = name: - { createPartitions, testChannel ? false, useEFI ? false, grubVersion ? 2, grubDevice ? "/dev/vda" }: + { createPartitions, testChannel ? false, useEFI ? false, grubVersion ? 2, grubDevice ? "/dev/vda", grubIdentifier ? "uuid" }: makeTest { inherit iso; name = "installer-" + name; nodes = if testChannel then { inherit webserver; } else { }; testScript = testScriptFun { - inherit createPartitions testChannel useEFI grubVersion grubDevice; + inherit createPartitions testChannel useEFI grubVersion grubDevice grubIdentifier; }; }; @@ -461,11 +462,36 @@ in { "mount LABEL=root /mnt", "btrfs subvol create /mnt/boot", "btrfs subvol create /mnt/nixos", + "btrfs subvol create /mnt/nixos/default", "umount /mnt", - "mount -o defaults,subvol=nixos LABEL=root /mnt", + "mount -o defaults,subvol=nixos/default LABEL=root /mnt", "mkdir /mnt/boot", "mount -o defaults,subvol=boot LABEL=root /mnt/boot", ); ''; }; + + # Test to see if we can detect default and aux subvolumes correctly + btrfsSubvolDefault = makeInstallerTest "btrfsSubvolDefault" { + createPartitions = '' + $machine->succeed( + "sgdisk -Z /dev/vda", + "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda", + "mkswap /dev/vda2 -L swap", + "swapon -L swap", + "mkfs.btrfs -L root /dev/vda3", + "btrfs device scan", + "mount LABEL=root /mnt", + "btrfs subvol create /mnt/badpath", + "btrfs subvol create /mnt/badpath/boot", + "btrfs subvol create /mnt/nixos", + "btrfs subvol set-default \$(btrfs subvol list /mnt | grep 'nixos' | awk '{print \$2}') /mnt", + "umount /mnt", + "mount -o defaults LABEL=root /mnt", + "mkdir -p /mnt/badpath/boot", # Help ensure the detection mechanism is actually looking up subvolumes + "mkdir /mnt/boot", + "mount -o defaults,subvol=badpath/boot LABEL=root /mnt/boot", + ); + ''; + }; } diff --git a/nixos/tests/phabricator.nix b/nixos/tests/phabricator.nix index 53038474c91a..0fe31f66502d 100644 --- a/nixos/tests/phabricator.nix +++ b/nixos/tests/phabricator.nix @@ -32,9 +32,16 @@ import ./make-test.nix ({ pkgs, ... }: { }]; }; + phd = { + enable = true; + }; + mysql = { enable = true; package = pkgs.mysql; + extraOptions = '' + sql_mode=STRICT_ALL_TABLES + ''; }; }; |