summary refs log tree commit diff
path: root/nixos/modules
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules')
-rw-r--r--nixos/modules/hardware/all-firmware.nix4
-rw-r--r--nixos/modules/installer/cd-dvd/iso-image.nix4
-rw-r--r--nixos/modules/installer/tools/tools.nix37
-rw-r--r--nixos/modules/misc/ids.nix3
-rw-r--r--nixos/modules/module-list.nix6
-rw-r--r--nixos/modules/programs/cdemu.nix49
-rw-r--r--nixos/modules/security/ca.nix45
-rw-r--r--nixos/modules/services/audio/mpd.nix1
-rw-r--r--nixos/modules/services/cluster/panamax.nix153
-rw-r--r--nixos/modules/services/misc/canto-daemon.nix37
-rw-r--r--nixos/modules/services/misc/gitlab.nix2
-rw-r--r--nixos/modules/services/misc/parsoid.nix100
-rw-r--r--nixos/modules/services/network-filesystems/samba.nix99
-rw-r--r--nixos/modules/services/networking/consul.nix46
-rw-r--r--nixos/modules/services/networking/dhcpcd.nix4
-rw-r--r--nixos/modules/services/networking/dnscrypt-proxy.nix2
-rw-r--r--nixos/modules/services/networking/i2pd.nix2
-rw-r--r--nixos/modules/services/networking/openntpd.nix10
-rw-r--r--nixos/modules/services/networking/sabnzbd.nix13
-rw-r--r--nixos/modules/services/networking/tinc.nix162
-rw-r--r--nixos/modules/services/web-servers/apache-httpd/limesurvey.nix196
-rw-r--r--nixos/modules/services/web-servers/uwsgi.nix112
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix3
-rw-r--r--nixos/modules/services/x11/display-managers/gdm.nix2
-rw-r--r--nixos/modules/services/x11/window-managers/default.nix28
-rw-r--r--nixos/modules/services/x11/window-managers/xmonad.nix29
-rw-r--r--nixos/modules/system/boot/kernel.nix3
-rw-r--r--nixos/modules/system/boot/loader/grub/grub.nix34
-rw-r--r--nixos/modules/system/boot/loader/grub/install-grub.pl120
-rw-r--r--nixos/modules/system/boot/stage-1-init.sh9
-rw-r--r--nixos/modules/system/boot/stage-1.nix2
-rw-r--r--nixos/modules/system/boot/systemd.nix5
-rw-r--r--nixos/modules/tasks/filesystems/zfs.nix32
33 files changed, 1171 insertions, 183 deletions
diff --git a/nixos/modules/hardware/all-firmware.nix b/nixos/modules/hardware/all-firmware.nix
index 37a9f4d0d314..17aa29425956 100644
--- a/nixos/modules/hardware/all-firmware.nix
+++ b/nixos/modules/hardware/all-firmware.nix
@@ -12,8 +12,7 @@ with lib;
       default = false;
       type = types.bool;
       description = ''
-        Turn on this option if you want to enable all the firmware shipped with Debian/Ubuntu
-        and iwlwifi.
+        Turn on this option if you want to enable all the firmware shipped in linux-firmware.
       '';
     };
 
@@ -26,7 +25,6 @@ with lib;
     hardware.firmware = [
       "${pkgs.firmwareLinuxNonfree}/lib/firmware"
       "${pkgs.iwlegacy}/lib/firmware"
-      "${pkgs.iwlwifi}/lib/firmware"
     ];
   };
 
diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix
index 84de7800c2a9..39db7d9b8f72 100644
--- a/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -58,8 +58,8 @@ let
 
   efiImg = pkgs.runCommand "efi-image_eltorito" { buildInputs = [ pkgs.mtools ]; }
     ''
-      #Let's hope 10M is enough
-      dd bs=2048 count=5120 if=/dev/zero of="$out"
+      #Let's hope 15M is enough
+      dd bs=2048 count=7680 if=/dev/zero of="$out"
       ${pkgs.dosfstools}/sbin/mkfs.vfat "$out"
       mcopy -svi "$out" ${efiDir}/* ::
       mmd -i "$out" boot
diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix
index 2c796250a982..63d2077fbe19 100644
--- a/nixos/modules/installer/tools/tools.nix
+++ b/nixos/modules/installer/tools/tools.nix
@@ -53,46 +53,9 @@ let
     inherit (config.system) nixosVersion nixosCodeName;
   };
 
-  /*
-  nixos-gui = pkgs.xulrunnerWrapper {
-    launcher = "nixos-gui";
-    application = pkgs.stdenv.mkDerivation {
-      name = "nixos-gui";
-      buildCommand = ''
-        cp -r "$gui" "$out"
-
-        # Do not force the copy if the file exists in the sources (this
-        # happens for developpers)
-        test -e "$out/chrome/content/jquery-1.5.2.js" ||
-          cp -f "$jquery" "$out/chrome/content/jquery-1.5.2.js"
-      '';
-      gui = lib.cleanSource "${modulesPath}/../gui";
-      jquery = pkgs.fetchurl {
-        url = http://code.jquery.com/jquery-1.5.2.min.js;
-        sha256 = "8f0a19ee8c606b35a10904951e0a27da1896eafe33c6e88cb7bcbe455f05a24a";
-      };
-    };
-  };
-  */
-
 in
 
 {
-  /*
-  options = {
-
-    installer.enableGraphicalTools = mkOption {
-      default = false;
-      type = types.bool;
-      example = true;
-      description = ''
-        Enable the installation of graphical tools.
-      '';
-    };
-
-  };
-  */
-
   config = {
     environment.systemPackages =
       [ nixos-build-vms
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 7415af8ab6af..f3cda7b95416 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -177,6 +177,8 @@
       cadvisor = 167;
       nylon = 168;
       apache-kafka = 169;
+      panamax = 170;
+
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
       nixbld = 30000; # start of range of uids
@@ -315,6 +317,7 @@
       kubernetes = 162;
       gitlab = 165;
       nylon = 166;
+      panamax = 170;
 
       # When adding a gid, make sure it doesn't match an existing
       # uid. Users and groups with the same name should have equal
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 6c6aab14ee72..0fad59d55717 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -55,6 +55,7 @@
   ./programs/atop.nix
   ./programs/bash/bash.nix
   ./programs/blcr.nix
+  ./programs/cdemu.nix
   ./programs/command-not-found/command-not-found.nix
   ./programs/dconf.nix
   ./programs/environment.nix
@@ -104,6 +105,7 @@
   ./services/backup/tarsnap.nix
   ./services/cluster/fleet.nix
   ./services/cluster/kubernetes.nix
+  ./services/cluster/panamax.nix
   ./services/computing/torque/server.nix
   ./services/computing/torque/mom.nix
   ./services/continuous-integration/jenkins/default.nix
@@ -172,6 +174,7 @@
   ./services/mail/spamassassin.nix
   ./services/misc/apache-kafka.nix
   #./services/misc/autofs.nix
+  ./services/misc/canto-daemon.nix
   ./services/misc/cpuminer-cryptonight.nix
   ./services/misc/cgminer.nix
   ./services/misc/dictd.nix
@@ -189,6 +192,7 @@
   ./services/misc/nix-gc.nix
   ./services/misc/nixos-manual.nix
   ./services/misc/nix-ssh-serve.nix
+  ./services/misc/parsoid.nix
   ./services/misc/phd.nix
   ./services/misc/redmine.nix
   ./services/misc/rippled.nix
@@ -293,6 +297,7 @@
   ./services/networking/syncthing.nix
   ./services/networking/tcpcrypt.nix
   ./services/networking/teamspeak3.nix
+  ./services/networking/tinc.nix
   ./services/networking/tftpd.nix
   ./services/networking/tlsdated.nix
   ./services/networking/tox-bootstrapd.nix
@@ -341,6 +346,7 @@
   ./services/web-servers/nginx/default.nix
   ./services/web-servers/phpfpm.nix
   ./services/web-servers/tomcat.nix
+  ./services/web-servers/uwsgi.nix
   ./services/web-servers/varnish/default.nix
   ./services/web-servers/winstone.nix
   ./services/web-servers/zope2.nix
diff --git a/nixos/modules/programs/cdemu.nix b/nixos/modules/programs/cdemu.nix
new file mode 100644
index 000000000000..d1b1915eea91
--- /dev/null
+++ b/nixos/modules/programs/cdemu.nix
@@ -0,0 +1,49 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.programs.cdemu;
+in {
+
+  options = {
+    programs.cdemu = {
+      enable = mkOption {
+        default = false;
+        description = "Whether to enable cdemu for users of appropriate group (default cdrom)";
+      };
+      group = mkOption {
+        default = "cdrom";
+        description = "Required group for users of cdemu";
+      };
+      gui = mkOption {
+        default = true;
+        description = "Whether to install cdemu GUI (gCDEmu)";
+      };
+      image-analyzer = mkOption {
+        default = true;
+        description = "Whether to install image analyzer";
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    boot = {
+      extraModulePackages = [ pkgs.linuxPackages.vhba ];
+      kernelModules = [ "vhba" ];
+    };
+
+    services = {
+      udev.extraRules = ''
+        KERNEL=="vhba_ctl", MODE="0660", OWNER="root", GROUP="${cfg.group}"
+      '';
+      dbus.packages = [ pkgs.cdemu-daemon ];
+    };
+
+    environment.systemPackages =
+      [ pkgs.cdemu-daemon pkgs.cdemu-client ]
+      ++ optional cfg.gui pkgs.gcdemu
+      ++ optional cfg.image-analyzer pkgs.image-analyzer;
+  };
+
+}
diff --git a/nixos/modules/security/ca.nix b/nixos/modules/security/ca.nix
index f430a5a6339f..e070ffc95e43 100644
--- a/nixos/modules/security/ca.nix
+++ b/nixos/modules/security/ca.nix
@@ -4,10 +4,53 @@ with lib;
 
 {
 
+  options = {
+
+    security.pki.certificateFiles = mkOption {
+      type = types.listOf types.path;
+      default = [];
+      example = literalExample "[ \"\${pkgs.cacert}/etc/ca-bundle.crt\" ]";
+      description = ''
+        A list of files containing trusted root certificates in PEM
+        format. These are concatenated to form
+        <filename>/etc/ssl/certs/ca-bundle.crt</filename>, which is
+        used by many programs that use OpenSSL, such as
+        <command>curl</command> and <command>git</command>.
+      '';
+    };
+
+    security.pki.certificates = mkOption {
+      type = types.listOf types.string;
+      default = [];
+      example = singleton ''
+        NixOS.org
+        =========
+        -----BEGIN CERTIFICATE-----
+        MIIGUDCCBTigAwIBAgIDD8KWMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
+        TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
+        ...
+        -----END CERTIFICATE-----
+      '';
+      description = ''
+        A list of trusted root certificates in PEM format.
+      '';
+    };
+
+  };
+
   config = {
 
+    security.pki.certificateFiles = [ "${pkgs.cacert}/etc/ca-bundle.crt" ];
+
     environment.etc =
-      [ { source = "${pkgs.cacert}/etc/ca-bundle.crt";
+      [ { source = pkgs.runCommand "ca-bundle.crt"
+          { files =
+              config.security.pki.certificateFiles ++
+              [ (builtins.toFile "extra.crt" (concatStringsSep "\n" config.security.pki.certificates)) ];
+           }
+          ''
+            cat $files > $out
+          '';
           target = "ssl/certs/ca-bundle.crt";
         }
       ];
diff --git a/nixos/modules/services/audio/mpd.nix b/nixos/modules/services/audio/mpd.nix
index eab7993387de..b79052337597 100644
--- a/nixos/modules/services/audio/mpd.nix
+++ b/nixos/modules/services/audio/mpd.nix
@@ -100,6 +100,7 @@ in {
       script = "exec mpd --no-daemon ${mpdConf}";
       serviceConfig = {
         User = "mpd";
+        PermissionsStartOnly = true;
       };
     };
 
diff --git a/nixos/modules/services/cluster/panamax.nix b/nixos/modules/services/cluster/panamax.nix
new file mode 100644
index 000000000000..a7233f23c913
--- /dev/null
+++ b/nixos/modules/services/cluster/panamax.nix
@@ -0,0 +1,153 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.panamax;
+
+  panamax_api = pkgs.panamax_api.override { dataDir = cfg.dataDir + "/api"; };
+  panamax_ui = pkgs.panamax_ui.override { dataDir = cfg.dataDir + "/ui"; };
+
+in {
+
+  ##### Interface
+  options.services.panamax = {
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Whether to enable Panamax service.
+      '';
+    };
+
+    UIPort = mkOption {
+      type = types.int;
+      default = 8888;
+      description = ''
+        Panamax UI listening port.
+      '';
+    };
+
+    APIPort = mkOption {
+      type = types.int;
+      default = 3000;
+      description = ''
+        Panamax UI listening port.
+      '';
+    };
+
+    dataDir = mkOption {
+      type = types.str;
+      default = "/var/lib/panamax";
+      description = ''
+        Data dir for Panamax.
+      '';
+    };
+
+    fleetctlEndpoint = mkOption {
+      type = types.str;
+      default = "http://127.0.0.1:4001";
+      description = ''
+        Panamax fleetctl endpoint.
+      '';
+    };
+
+    journalEndpoint = mkOption {
+      type = types.str;
+      default = "http://127.0.0.1:19531";
+      description = ''
+        Panamax journal endpoint.
+      '';
+    };
+
+    secretKey = mkOption {
+      type = types.str;
+      default = "SomethingVeryLong.";
+      description = ''
+        Panamax secret key (do change this).
+      '';
+    };
+
+  };
+
+  ##### Implementation
+  config = mkIf cfg.enable {
+    systemd.services.panamax-api = {
+      description = "Panamax API";
+
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" "fleet.service" "etcd.service" "docker.service" ];
+
+      path = [ panamax_api ];
+      environment = {
+        RAILS_ENV = "production";
+        JOURNAL_ENDPOINT = cfg.journalEndpoint;
+        FLEETCTL_ENDPOINT = cfg.fleetctlEndpoint;
+        PANAMAX_DATABASE_PATH = "${cfg.dataDir}/api/db/mnt/db.sqlite3";
+      };
+
+      preStart = ''
+        rm -rf ${cfg.dataDir}/state/tmp
+        mkdir -p ${cfg.dataDir}/api/{db/mnt,state/log,state/tmp}
+        ln -sf ${panamax_api}/share/panamax-api/_db/{schema.rb,seeds.rb,migrate} ${cfg.dataDir}/api/db/
+
+        if [ ! -f ${cfg.dataDir}/.created ]; then
+          bundle exec rake db:setup
+          bundle exec rake db:seed
+          bundle exec rake panamax:templates:load || true
+          touch ${cfg.dataDir}/.created
+        else
+          bundle exec rake db:migrate
+        fi
+      '';
+
+      serviceConfig = {
+        ExecStart = "${panamax_api}/bin/bundle exec rails server --binding 127.0.0.1 --port ${toString cfg.APIPort}";
+        User = "panamax";
+        Group = "panamax";
+      };
+    };
+
+    systemd.services.panamax-ui = {
+      description = "Panamax UI";
+
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" "panamax_api.service" ];
+
+      path = [ panamax_ui ];
+      environment = {
+        RAILS_ENV = "production";
+        JOURNAL_ENDPOINT = cfg.journalEndpoint;
+        PMX_API_PORT_3000_TCP_ADDR = "localhost";
+        PMX_API_PORT_3000_TCP_PORT = toString cfg.APIPort;
+        SECRET_KEY_BASE = cfg.secretKey;
+      };
+
+      preStart = ''
+        rm -rf ${cfg.dataDir}/state/tmp
+        mkdir -p ${cfg.dataDir}/ui/state/{log,tmp}
+      '';
+
+      serviceConfig = {
+        ExecStart = "${panamax_ui}/bin/bundle exec rails server --binding 127.0.0.1 --port ${toString cfg.UIPort}";
+        User = "panamax";
+        Group = "panamax";
+      };
+    };
+
+    users.extraUsers.panamax =
+    { uid = config.ids.uids.panamax;
+      description = "Panamax user";
+      createHome = true;
+      home = cfg.dataDir;
+      extraGroups = [ "docker" ];
+    };
+
+    services.journald.enableHttpGateway = mkDefault true;
+    services.fleet.enable = mkDefault true;
+    virtualisation.docker.enable = mkDefault true;
+
+    environment.systemPackages = [ panamax_api panamax_ui ];
+    users.extraGroups.panamax.gid = config.ids.gids.panamax;
+  };
+}
diff --git a/nixos/modules/services/misc/canto-daemon.nix b/nixos/modules/services/misc/canto-daemon.nix
new file mode 100644
index 000000000000..db51a263aab5
--- /dev/null
+++ b/nixos/modules/services/misc/canto-daemon.nix
@@ -0,0 +1,37 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+cfg = config.services.canto-daemon;
+
+in {
+
+##### interface
+
+  options = {
+
+    services.canto-daemon = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whether to enable the canto RSS daemon.";
+      };
+    };
+
+  };
+
+##### implementation
+
+  config = mkIf cfg.enable {
+
+    systemd.user.services.canto-daemon = {
+      description = "Canto RSS Daemon";
+      after = [ "network.target" ];
+      wantedBy = [ "default.target" ];
+      serviceConfig.ExecStart = "${pkgs.canto-daemon}/bin/canto-daemon";
+    };
+  };
+
+}
diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix
index ddb0bd671dd1..4505c5ceb84f 100644
--- a/nixos/modules/services/misc/gitlab.nix
+++ b/nixos/modules/services/misc/gitlab.nix
@@ -61,7 +61,7 @@ let
           --set GITLAB_SHELL_SECRET_PATH "${cfg.stateDir}/config/gitlab_shell_secret"\
           --set GITLAB_HOST "${cfg.host}"\
           --set GITLAB_PORT "${toString cfg.port}"\
-          --set GITLAB_BACKUP_PATH"${cfg.backupPath}"\
+          --set GITLAB_BACKUP_PATH "${cfg.backupPath}"\
           --set RAILS_ENV "production"
     '';
   };
diff --git a/nixos/modules/services/misc/parsoid.nix b/nixos/modules/services/misc/parsoid.nix
new file mode 100644
index 000000000000..0844190a5490
--- /dev/null
+++ b/nixos/modules/services/misc/parsoid.nix
@@ -0,0 +1,100 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.parsoid;
+
+  conf = ''
+    exports.setup = function( parsoidConfig ) {
+      ${toString (mapAttrsToList (name: str: "parsoidConfig.setInterwiki('${name}', '${str}');") cfg.interwikis)}
+
+      parsoidConfig.serverInterface = "${cfg.interface}";
+      parsoidConfig.serverPort = ${toString cfg.port};
+
+      parsoidConfig.useSelser = true;
+
+      ${cfg.extraConfig}
+    };
+  '';
+
+  confFile = builtins.toFile "localsettings.js" conf;
+
+in
+{
+  ##### interface
+
+  options = {
+
+    services.parsoid = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable Parsoid -- bidirectional
+          wikitext parser.
+        '';
+      };
+
+      interwikis = mkOption {
+        type = types.attrsOf types.str;
+        example = { localhost = "http://localhost/api.php"; };
+        description = ''
+          Used MediaWiki API endpoints.
+        '';
+      };
+
+      workers = mkOption {
+        type = types.int;
+        default = 2;
+        description = ''
+          Number of Parsoid workers.
+        '';
+      };
+
+      interface = mkOption {
+        type = types.str;
+        default = "127.0.0.1";
+        description = ''
+          Interface to listen on.
+        '';
+      };
+
+      port = mkOption {
+        type = types.int;
+        default = 8000;
+        description = ''
+          Port to listen on.
+        '';
+      };
+
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
+        description = ''
+          Extra configuration to add to parsoid configuration.
+        '';
+      };
+
+    };
+
+  };
+
+  ##### implementation
+
+  config = mkIf cfg.enable {
+
+    systemd.services.parsoid = {
+      description = "Bidirectional wikitext parser";
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      serviceConfig = {
+        ExecStart = "${pkgs.nodePackages.parsoid}/lib/node_modules/parsoid/api/server.js -c ${confFile} -n ${toString cfg.workers}";
+      };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/network-filesystems/samba.nix b/nixos/modules/services/network-filesystems/samba.nix
index 6fcf89999523..8c79bf663d15 100644
--- a/nixos/modules/services/network-filesystems/samba.nix
+++ b/nixos/modules/services/network-filesystems/samba.nix
@@ -6,25 +6,11 @@ let
 
   cfg = config.services.samba;
 
-  logDir = "/var/log/samba";
-  privateDir = "/var/samba/private";
-
   samba = cfg.package;
 
   setupScript =
     ''
-      if ! test -d /var/samba ; then
-        mkdir -p /var/samba/locks /var/samba/cores/nmbd  /var/samba/cores/smbd /var/samba/cores/winbindd
-      fi
-
-      passwdFile="$(${pkgs.gnused}/bin/sed -n 's/^.*smb[ ]\+passwd[ ]\+file[ ]\+=[ ]\+\(.*\)/\1/p' ${configFile})"
-      if [ -n "$passwdFile" ]; then
-        echo 'INFO: [samba] creating directory containing passwd file'
-        mkdir -p "$(dirname "$passwdFile")"
-      fi
-
-      mkdir -p ${logDir}
-      mkdir -p ${privateDir}
+      mkdir -p /var/lock/samba /var/log/samba /var/cache/samba /var/lib/samba/private
     '';
 
   shareConfig = name:
@@ -39,9 +25,10 @@ let
     (if cfg.configText != null then cfg.configText else
     ''
       [ global ]
-      log file = ${logDir}/log.%m
-      private dir = ${privateDir}
-      ${optionalString cfg.syncPasswordsByPam "pam password change = true"}
+      security = ${cfg.securityType}
+      passwd program = /var/setuid-wrappers/passwd %u
+      pam password change = ${toString cfg.syncPasswordsByPam}
+      invalid users = ${toString cfg.invalidUsers}
 
       ${cfg.extraConfig}
 
@@ -83,14 +70,16 @@ in
     services.samba = {
 
       enable = mkOption {
+        type = types.bool;
         default = false;
-        description = "
+        description = ''
           Whether to enable Samba, which provides file and print
           services to Windows clients through the SMB/CIFS protocol.
-        ";
+        '';
       };
 
       package = mkOption {
+        type = types.package;
         default = pkgs.samba;
         example = pkgs.samba4;
         description = ''
@@ -99,72 +88,47 @@ in
       };
 
       syncPasswordsByPam = mkOption {
+        type = types.bool;
         default = false;
-        description = "
-          enabling this will add a line directly after pam_unix.so.
+        description = ''
+          Enabling this will add a line directly after pam_unix.so.
           Whenever a password is changed the samba password will be updated as well.
           However you still yave to add the samba password once using smbpasswd -a user
           If you don't want to maintain an extra pwd database you still can send plain text
           passwords which is not secure.
-        ";
+        '';
       };
 
-      extraConfig = mkOption {
-        # !!! Bad default.
-        default = ''
-          # [global] continuing global section here, section is started by nix to set pids etc
-
-            smb passwd file = /etc/samba/passwd
-
-            # is this useful ?
-            domain master = auto
-
-            encrypt passwords = Yes
-            client plaintext auth = No
-
-            # yes: if you use this you probably also want to enable syncPasswordsByPam
-            # no: You can still use the pam password database. However
-            # passwords will be sent plain text on network (discouraged)
-
-            workgroup = Users
-            server string = %h
-            comment = Samba
-            log file = /var/log/samba/log.%m
-            log level = 10
-            max log size = 50000
-            security = ${cfg.securityType}
-
-            client lanman auth = Yes
-            dns proxy = no
-            invalid users = root
-            passdb backend = tdbsam
-            passwd program = /usr/bin/passwd %u
+      invalidUsers = mkOption {
+        type = types.listOf types.str;
+        default = [ "root" ];
+        description = ''
+          List of users who are denied to login via Samba.
         '';
-
-        description = "
-          additional global section and extra section lines go in here.
-        ";
       };
 
-      configFile = mkOption {
-        description = "
-          internal use to pass filepath to samba pam module
-        ";
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
+        description = ''
+          Additional global section and extra section lines go in here.
+        '';
       };
 
       configText = mkOption {
         type = types.nullOr types.lines;
         default = null;
-        description = "
+        description = ''
           Verbatim contents of smb.conf. If null (default), use the
           autogenerated file from NixOS instead.
-        ";
+        '';
       };
 
       securityType = mkOption {
-        description = "Samba security type";
+        type = types.str;
         default = "user";
         example = "share";
+        description = "Samba security type";
       };
 
       nsswins = mkOption {
@@ -179,12 +143,11 @@ in
 
       shares = mkOption {
         default = {};
-        description =
-          ''
+        description = ''
           A set describing shared resources.
           See <command>man smb.conf</command> for options.
-          '';
-        type = types.attrsOf (types.attrsOf types.str);
+        '';
+        type = types.attrsOf (types.attrsOf types.unspecified);
         example =
           { srv =
              { path = "/srv";
diff --git a/nixos/modules/services/networking/consul.nix b/nixos/modules/services/networking/consul.nix
index b2d5854fbc0c..3ae010e81070 100644
--- a/nixos/modules/services/networking/consul.nix
+++ b/nixos/modules/services/networking/consul.nix
@@ -122,6 +122,34 @@ in
         '';
       };
 
+      alerts = {
+        enable = mkEnableOption "Whether to enable consul-alerts";
+
+        listenAddr = mkOption {
+          description = "Api listening address.";
+          default = "localhost:9000";
+          type = types.str;
+        };
+
+        consulAddr = mkOption {
+          description = "Consul api listening adddress";
+          default = "localhost:8500";
+          type = types.str;
+        };
+
+        watchChecks = mkOption {
+          description = "Whether to enable check watcher.";
+          default = true;
+          type = types.bool;
+        };
+
+        watchEvents = mkOption {
+          description = "Whether to enable event watcher.";
+          default = true;
+          type = types.bool;
+        };
+      };
+
     };
 
   };
@@ -204,5 +232,23 @@ in
       '';
     };
 
+    systemd.services.consul-alerts = mkIf (cfg.alerts.enable) {
+      wantedBy = [ "multi-user.target" ];
+      after = [ "consul.service" ];
+
+      path = [ pkgs.consul ];
+
+      serviceConfig = {
+        ExecStart = ''
+          ${pkgs.consul-alerts}/bin/consul-alerts start \
+            --alert-addr=${cfg.alerts.listenAddr} \
+            --consul-addr=${cfg.alerts.consulAddr} \
+            ${optionalString cfg.alerts.watchChecks "--watch-checks"} \
+            ${optionalString cfg.alerts.watchEvents "--watch-events"}
+        '';
+        User = if cfg.dropPrivileges then "consul" else null;
+      };
+    };
+
   };
 }
diff --git a/nixos/modules/services/networking/dhcpcd.nix b/nixos/modules/services/networking/dhcpcd.nix
index 1ad8cbae15cf..0430d31b99a7 100644
--- a/nixos/modules/services/networking/dhcpcd.nix
+++ b/nixos/modules/services/networking/dhcpcd.nix
@@ -68,8 +68,10 @@ let
           # will actually do something: if ntpd cannot resolve the
           # server hostnames in its config file, then it will never do
           # anything ever again ("couldn't resolve ..., giving up on
-          # it"), so we silently lose time synchronisation.
+          # it"), so we silently lose time synchronisation. This also
+          # applies to openntpd.
           ${config.systemd.package}/bin/systemctl try-restart ntpd.service
+          ${config.systemd.package}/bin/systemctl try-restart openntpd.service
 
           ${config.systemd.package}/bin/systemctl start ip-up.target
       fi
diff --git a/nixos/modules/services/networking/dnscrypt-proxy.nix b/nixos/modules/services/networking/dnscrypt-proxy.nix
index 26549bfe6f14..d1b5fbedfa6f 100644
--- a/nixos/modules/services/networking/dnscrypt-proxy.nix
+++ b/nixos/modules/services/networking/dnscrypt-proxy.nix
@@ -103,7 +103,7 @@ in
           ${pkgs.tzdata}/share/zoneinfo/** r,
 
           ${dnscrypt-proxy}/share/dnscrypt-proxy/** r,
-          ${pkgs.gcc.gcc}/lib/libssp.so.* mr,
+          ${pkgs.gcc.cc}/lib/libssp.so.* mr,
           ${pkgs.libsodium}/lib/libsodium.so.* mr,
         }
       '')
diff --git a/nixos/modules/services/networking/i2pd.nix b/nixos/modules/services/networking/i2pd.nix
index 95b0ae59ff3c..7ee78f01d497 100644
--- a/nixos/modules/services/networking/i2pd.nix
+++ b/nixos/modules/services/networking/i2pd.nix
@@ -8,7 +8,7 @@ let
 
   homeDir = "/var/lib/i2pd";
 
-  extip = "EXTIP=$(${pkgs.curl}/bin/curl -sf "http://jsonip.com" | ${pkgs.gawk}/bin/awk -F'\"' '{print $4}')";
+  extip = "EXTIP=\$(${pkgs.curl}/bin/curl -sf \"http://jsonip.com\" | ${pkgs.gawk}/bin/awk -F'\"' '{print $4}')";
 
   i2pSh = pkgs.writeScriptBin "i2pd" ''
     #!/bin/sh
diff --git a/nixos/modules/services/networking/openntpd.nix b/nixos/modules/services/networking/openntpd.nix
index d1c32db49c4c..e53fc574fbea 100644
--- a/nixos/modules/services/networking/openntpd.nix
+++ b/nixos/modules/services/networking/openntpd.nix
@@ -5,10 +5,7 @@ with lib;
 let
   cfg = config.services.openntpd;
 
-  package = pkgs.openntpd.override {
-    privsepUser = "ntp";
-    privsepPath = "/var/empty";
-  };
+  package = pkgs.openntpd_nixos;
 
   cfgFile = pkgs.writeText "openntpd.conf" ''
     ${concatStringsSep "\n" (map (s: "server ${s}") cfg.servers)}
@@ -54,6 +51,9 @@ in
   config = mkIf cfg.enable {
     services.ntp.enable = mkForce false;
 
+    # Add ntpctl to the environment for status checking
+    environment.systemPackages = [ package ];
+
     users.extraUsers = singleton {
       name = "ntp";
       uid = config.ids.uids.ntp;
@@ -64,6 +64,8 @@ in
     systemd.services.openntpd = {
       description = "OpenNTP Server";
       wantedBy = [ "multi-user.target" ];
+      wants = [ "network-online.target" ];
+      after = [ "dnsmasq.service" "bind.service" "network-online.target" ];
       serviceConfig.ExecStart = "${package}/sbin/ntpd -d -f ${cfgFile} ${cfg.extraOptions}";
     };
   };
diff --git a/nixos/modules/services/networking/sabnzbd.nix b/nixos/modules/services/networking/sabnzbd.nix
index 83db0841b346..77bf64b80d0f 100644
--- a/nixos/modules/services/networking/sabnzbd.nix
+++ b/nixos/modules/services/networking/sabnzbd.nix
@@ -39,13 +39,14 @@ in
         }
       ];
 
-    jobs.sabnzbd =
+    systemd.services.sabnzbd =
       { description = "sabnzbd server";
-
-        startOn = "started network-interfaces";
-        stopOn = "stopping network-interfaces";
-
-        exec = "${sabnzbd}/bin/sabnzbd -d -f ${cfg.configFile}";
+        wantedBy    = [ "multi-user.target" ];
+        after = [ "network.target" ];
+        serviceConfig = {
+          Type = "forking";
+          ExecStart = "${sabnzbd}/bin/sabnzbd -d -f ${cfg.configFile}";
+        };
       };
 
   };
diff --git a/nixos/modules/services/networking/tinc.nix b/nixos/modules/services/networking/tinc.nix
new file mode 100644
index 000000000000..f9ca796ea652
--- /dev/null
+++ b/nixos/modules/services/networking/tinc.nix
@@ -0,0 +1,162 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.services.tinc;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.tinc = {
+
+      networks = mkOption {
+        default = { };
+        type = types.loaOf types.optionSet;
+        description = ''
+          Defines the tinc networks which will be started.
+          Each network invokes a different daemon.
+        '';
+        options = {
+
+          extraConfig = mkOption {
+            default = "";
+            type = types.lines;
+            description = ''
+              Extra lines to add to the tinc service configuration file.
+            '';
+          };
+
+          name = mkOption {
+            default = null;
+            type = types.nullOr types.str;
+            description = ''
+              The name of the node which is used as an identifier when communicating
+              with the remote nodes in the mesh. If null then the hostname of the system
+              is used.
+            '';
+          };
+
+          debugLevel = mkOption {
+            default = 0;
+            type = types.addCheck types.int (l: l >= 0 && l <= 5);
+            description = ''
+              The amount of debugging information to add to the log. 0 means little
+              logging while 5 is the most logging. <command>man tincd</command> for
+              more details.
+            '';
+          };
+
+          hosts = mkOption {
+            default = { };
+            type = types.loaOf types.lines;
+            description = ''
+              The name of the host in the network as well as the configuration for that host.
+              This name should only contain alphanumerics and underscores.
+            '';
+          };
+
+          interfaceType = mkOption {
+            default = "tun";
+            type = types.addCheck types.str (n: n == "tun" || n == "tap");
+            description = ''
+              The type of virtual interface used for the network connection
+            '';
+          };
+
+          package = mkOption {
+            default = pkgs.tinc_pre;
+            description = ''
+              The package to use for the tinc daemon's binary.
+            '';
+          };
+
+        };
+      };
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf (cfg.networks != { }) {
+
+    environment.etc = fold (a: b: a // b) { }
+      (flip mapAttrsToList cfg.networks (network: data:
+        flip mapAttrs' data.hosts (host: text: nameValuePair
+          ("tinc/${network}/hosts/${host}")
+          ({ mode = "0444"; inherit text; })
+        ) // {
+          "tinc/${network}/tinc.conf" = {
+            mode = "0444";
+            text = ''
+              Name = ${if data.name == null then "$HOST" else data.name}
+              DeviceType = ${data.interfaceType}
+              Device = /dev/net/tun
+              Interface = tinc.${network}
+              ${data.extraConfig}
+            '';
+          };
+        }
+      ));
+
+    networking.interfaces = flip mapAttrs' cfg.networks (network: data: nameValuePair
+      ("tinc.${network}")
+      ({
+        virtual = true;
+        virtualType = "${data.interfaceType}";
+      })
+    );
+
+    systemd.services = flip mapAttrs' cfg.networks (network: data: nameValuePair
+      ("tinc.${network}")
+      ({
+        description = "Tinc Daemon - ${network}";
+        wantedBy = [ "network.target" ];
+        after = [ "network-interfaces.target" ];
+        path = [ data.package ];
+        restartTriggers = [ config.environment.etc."tinc/${network}/tinc.conf".source ]
+          ++ mapAttrsToList (host: _ : config.environment.etc."tinc/${network}/hosts/${host}".source) data.hosts;
+        serviceConfig = {
+          Type = "simple";
+          PIDFile = "/run/tinc.${network}.pid";
+        };
+        preStart = ''
+          mkdir -p /etc/tinc/${network}/hosts
+
+          # Determine how we should generate our keys
+          if type tinc >/dev/null 2>&1; then
+            # Tinc 1.1+ uses the tinc helper application for key generation
+
+            # Prefer ED25519 keys (only in 1.1+)
+            [ -f "/etc/tinc/${network}/ed25519_key.priv" ] || tinc -n ${network} generate-ed25519-keys
+
+            # Otherwise use RSA keys
+            [ -f "/etc/tinc/${network}/rsa_key.priv" ] || tinc -n ${network} generate-rsa-keys 4096
+          else
+            # Tinc 1.0 uses the tincd application
+            [ -f "/etc/tinc/${network}/rsa_key.priv" ] || tincd -n ${network} -K 4096
+          fi
+        '';
+        script = ''
+          tincd -D -U tinc.${network} -n ${network} --pidfile /run/tinc.${network}.pid -d ${toString data.debugLevel}
+        '';
+      })
+    );
+
+    users.extraUsers = flip mapAttrs' cfg.networks (network: _:
+      nameValuePair ("tinc.${network}") ({
+        description = "Tinc daemon user for ${network}";
+      })
+    );
+
+  };
+
+}
diff --git a/nixos/modules/services/web-servers/apache-httpd/limesurvey.nix b/nixos/modules/services/web-servers/apache-httpd/limesurvey.nix
new file mode 100644
index 000000000000..6f1f67970f6c
--- /dev/null
+++ b/nixos/modules/services/web-servers/apache-httpd/limesurvey.nix
@@ -0,0 +1,196 @@
+{ config, lib, pkgs, serverInfo, php, ... }:
+
+with lib;
+
+let
+
+  httpd = serverInfo.serverConfig.package;
+
+  version24 = !versionOlder httpd.version "2.4";
+
+  allGranted = if version24 then ''
+    Require all granted
+  '' else ''
+    Order allow,deny
+    Allow from all
+  '';
+
+  limesurveyConfig = pkgs.writeText "config.php" ''
+    <?php
+    $config = array();
+    $config['name']  = "${config.siteName}";
+    $config['runtimePath'] = "${config.dataDir}/tmp/runtime";
+    $config['components'] = array();
+    $config['components']['db'] = array();
+    $config['components']['db']['connectionString'] = '${config.dbType}:host=${config.dbHost};port=${toString config.dbPort};user=${config.dbUser};password=${config.dbPassword};dbname=${config.dbName};';
+    $config['components']['db']['username'] = '${config.dbUser}';
+    $config['components']['db']['password'] = '${config.dbPassword}';
+    $config['components']['db']['charset'] = 'utf-8';
+    $config['components']['db']['tablePrefix'] = "prefix_";
+    $config['components']['assetManager'] = array();
+    $config['components']['assetManager']['basePath'] = '${config.dataDir}/tmp/assets';
+    $config['config'] = array();
+    $config['config']['debug'] = 1;
+    $config['config']['tempdir']  = "${config.dataDir}/tmp";
+    $config['config']['tempdir']  = "${config.dataDir}/tmp";
+    $config['config']['uploaddir']  = "${config.dataDir}/upload";
+    $config['config']['force_ssl'] = '${if config.forceSSL then "on" else ""}';
+    $config['config']['defaultlang'] = '${config.defaultLang}';
+    return $config;
+    ?>
+  '';
+
+  limesurveyRoot = "${pkgs.limesurvey}/share/limesurvey/";
+
+in rec {
+
+  extraConfig = ''
+    Alias ${config.urlPrefix}/tmp ${config.dataDir}/tmp
+
+    <Directory ${config.dataDir}/tmp>
+      ${allGranted}
+      Options -Indexes +FollowSymlinks
+    </Directory>
+
+    Alias ${config.urlPrefix}/upload ${config.dataDir}/upload
+
+    <Directory ${config.dataDir}/upload>
+      ${allGranted}
+      Options -Indexes
+    </Directory>
+
+    ${if config.urlPrefix != "" then ''
+      Alias ${config.urlPrefix} ${limesurveyRoot}
+    '' else ''
+      RewriteEngine On
+      RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
+      RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
+    ''}
+
+    <Directory ${limesurveyRoot}>
+      DirectoryIndex index.php
+    </Directory>
+  '';
+
+  globalEnvVars = [
+    { name = "LIMESURVEY_CONFIG"; value = limesurveyConfig; }
+  ];
+
+  documentRoot = if config.urlPrefix == "" then limesurveyRoot else null;
+
+  enablePHP = true;
+
+  options = {
+
+    id = mkOption {
+      default = "main";
+      description = ''
+        A unique identifier necessary to keep multiple owncloud server
+        instances on the same machine apart.  This is used to
+        disambiguate the administrative scripts, which get names like
+        mediawiki-$id-change-password.
+      '';
+    };
+
+    urlPrefix = mkOption {
+      default = "";
+      description = "Url prefix for site.";
+      type = types.str;
+    };
+
+    dbType = mkOption {
+      default = "pgsql";
+      description = "Type of database for limesurvey, for now, only pgsql.";
+      type = types.enum ["pgsql"];
+    };
+
+    dbName = mkOption {
+      default = "limesurvey";
+      description = "Name of the database that holds the limesurvey data.";
+      type = types.str;
+    };
+
+    dbHost = mkOption {
+      default = "localhost";
+      description = "Limesurvey database host.";
+      type = types.str;
+    };
+
+    dbPort = mkOption {
+      default = 5432;
+      description = "Limesurvey database port.";
+      type = types.int;
+    };
+
+    dbUser = mkOption {
+      default = "limesurvey";
+      description = "Limesurvey database user.";
+      type = types.str;
+    };
+
+    dbPassword = mkOption {
+      example = "foobar";
+      description = "Limesurvey database password.";
+      type = types.str;
+    };
+
+    adminUser = mkOption {
+      description = "Limesurvey admin username.";
+      default = "admin";
+      type = types.str;
+    };
+
+    adminPassword = mkOption {
+      description = "Default limesurvey admin password.";
+      default = "admin";
+      type = types.str;
+    };
+
+    adminEmail = mkOption {
+      description = "Limesurvey admin email.";
+      default = "admin@admin.com";
+      type = types.str;
+    };
+
+    forceSSL = mkOption {
+      default = false;
+      description = "Force use of HTTPS connection.";
+      type = types.bool;
+    };
+
+    siteName = mkOption {
+      default = "LimeSurvey";
+      description = "LimeSurvey name of the site.";
+      type = types.str;
+    };
+
+    defaultLang = mkOption {
+      default = "en";
+      description = "LimeSurvey default language.";
+      type = types.str;
+    };
+
+    dataDir = mkOption {
+      default = "/var/lib/limesurvey";
+      description = "LimeSurvey data directory.";
+      type = types.path;
+    };
+  };
+
+  startupScript = pkgs.writeScript "limesurvey_startup.sh" ''
+    if [ ! -f ${config.dataDir}/.created ]; then
+      mkdir -p ${config.dataDir}/{tmp/runtime,tmp/assets,tmp/upload,upload}
+      chmod -R ug+rw ${config.dataDir}
+      chmod -R o-rwx ${config.dataDir}
+      chown -R wwwrun:wwwrun ${config.dataDir}
+
+      ${pkgs.postgresql}/bin/createuser --no-superuser --no-createdb --no-createrole "${config.dbUser}" || true
+      ${pkgs.postgresql}/bin/createdb "${config.dbName}" -O "${config.dbUser}" || true
+      ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/psql -U postgres -d postgres -c "alter user ${config.dbUser} with password '${config.dbPassword}';" || true
+
+      ${pkgs.limesurvey}/bin/limesurvey-console install '${config.adminUser}' '${config.adminPassword}' '${config.adminUser}' '${config.adminEmail}'
+
+      touch ${config.dataDir}/.created
+    fi
+  '';
+}
diff --git a/nixos/modules/services/web-servers/uwsgi.nix b/nixos/modules/services/web-servers/uwsgi.nix
new file mode 100644
index 000000000000..6e454a2dacd7
--- /dev/null
+++ b/nixos/modules/services/web-servers/uwsgi.nix
@@ -0,0 +1,112 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.uwsgi;
+
+  python2Pkgs = pkgs.python2Packages.override {
+    python = pkgs.uwsgi.python2;
+    self = python2Pkgs;
+  };
+
+  python3Pkgs = pkgs.python3Packages.override {
+    python = pkgs.uwsgi.python3;
+    self = python3Pkgs;
+  };
+
+  buildCfg = c: if builtins.typeOf c != "set" then builtins.readFile c else builtins.toJSON {
+    uwsgi =
+      if c.type == "normal"
+        then {
+          pythonpath =
+               (if c ? python2Packages
+                then builtins.map (x: "${x}/${pkgs.uwsgi.python2.sitePackages}") (c.python2Packages python2Pkgs)
+                else [])
+            ++ (if c ? python3Packages
+                then builtins.map (x: "${x}/${pkgs.uwsgi.python3.sitePackages}") (c.python3Packages python3Pkgs)
+                else []);
+          plugins = cfg.plugins;
+        } // removeAttrs c [ "type" "python2Packages" "python3Packages" ]
+      else if c.type == "emperor"
+        then {
+          emperor = if builtins.typeOf c.vassals != "set" then c.vassals
+                    else pkgs.buildEnv {
+                      name = "vassals";
+                      paths = mapAttrsToList (n: c: pkgs.writeTextDir "${n}.json" (buildCfg c)) c.vassals;
+                    };
+        } // removeAttrs c [ "type" "vassals" ]
+      else abort "type should be either 'normal' or 'emperor'";
+  };
+
+  uwsgi = pkgs.uwsgi.override {
+    plugins = cfg.plugins;
+  };
+
+in {
+
+  options = {
+    services.uwsgi = {
+      
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Enable uWSGI";
+      };
+
+      instance = mkOption {
+        type = types.attrs;
+        default = {
+          type = "normal";
+        };
+        example = literalExample ''
+          {
+            type = "emperor";
+            vassals = {
+              moin = {
+                type = "normal";
+                python2Packages = self: with self; [ moinmoin ];
+                socket = "/run/uwsgi.sock";
+              };
+            };
+          }
+        '';
+        description = ''
+          uWSGI configuration. This awaits either a path to file or a set which will be made into one.
+          If given a set, it awaits an attribute <literal>type</literal> which can be either <literal>normal</literal>
+          or <literal>emperor</literal>.
+
+          For <literal>normal</literal> mode you can specify <literal>python2Packages</literal> and
+          <literal>python3Packages</literal> as functions from libraries set into lists of libraries.
+          For <literal>emperor</literal> mode, you should use <literal>vassals</literal> attribute
+          which should be either a set of names and configurations or a path to a directory.
+        '';
+      };
+
+      plugins = mkOption {
+        type = types.listOf types.str;
+        default = [];
+        description = "Plugins used with uWSGI";
+      };
+
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    systemd.services.uwsgi = {
+      wantedBy = [ "multi-user.target" ];
+      
+      serviceConfig = {
+        Type = "notify";
+        ExecStart = "${uwsgi}/bin/uwsgi --json ${pkgs.writeText "uwsgi.json" (buildCfg cfg.instance)}";
+        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+        ExecStop = "${pkgs.coreutils}/bin/kill -INT $MAINPID";
+        NotifyAccess = "main";
+        KillSignal = "SIGQUIT";
+      };
+
+    };
+  };
+}
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index c4329cd77550..6398a15bfcc8 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -114,6 +114,9 @@ in {
           # Let nautilus find extensions
           export NAUTILUS_EXTENSION_DIR=${config.system.path}/lib/nautilus/extensions-3.0/
 
+          # Find the mouse
+          export XCURSOR_PATH=~/.icons:${config.system.path}/share/icons
+
           # Update user dirs as described in http://freedesktop.org/wiki/Software/xdg-user-dirs/
           ${pkgs.xdg-user-dirs}/bin/xdg-user-dirs-update
 
diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix
index 080588df2472..b3da0cda04a3 100644
--- a/nixos/modules/services/x11/display-managers/gdm.nix
+++ b/nixos/modules/services/x11/display-managers/gdm.nix
@@ -55,6 +55,8 @@ in
           GDM_X_SERVER = "${cfg.xserverBin} ${cfg.xserverArgs}";
           GDM_SESSIONS_DIR = "${cfg.session.desktops}";
           XDG_CONFIG_DIRS = "${gnome3.gnome_settings_daemon}/etc/xdg";
+          # Find the mouse
+          XCURSOR_PATH = "~/.icons:${config.system.path}/share/icons";
         };
         execCmd = "exec ${gdm}/sbin/gdm";
       };
diff --git a/nixos/modules/services/x11/window-managers/default.nix b/nixos/modules/services/x11/window-managers/default.nix
index 4f2a2309b60c..7ec32fe83b54 100644
--- a/nixos/modules/services/x11/window-managers/default.nix
+++ b/nixos/modules/services/x11/window-managers/default.nix
@@ -7,19 +7,19 @@ let
 in
 
 {
-  imports =
-    [ ./compiz.nix
-      ./openbox.nix
-      ./metacity.nix
-      ./none.nix
-      ./twm.nix
-      ./wmii.nix
-      ./xmonad.nix
-      ./i3.nix
-      ./herbstluftwm.nix
-      ./bspwm.nix
-      ./stumpwm.nix
-    ];
+  imports = [
+    ./bspwm.nix
+    ./compiz.nix
+    ./herbstluftwm.nix
+    ./i3.nix
+    ./metacity.nix
+    ./openbox.nix
+    ./stumpwm.nix
+    ./twm.nix
+    ./windowmaker.nix
+    ./wmii.nix
+    ./xmonad.nix
+    ./none.nix ];
 
   options = {
 
@@ -61,4 +61,4 @@ in
   config = {
     services.xserver.displayManager.session = cfg.session;
   };
-}
\ No newline at end of file
+}
diff --git a/nixos/modules/services/x11/window-managers/xmonad.nix b/nixos/modules/services/x11/window-managers/xmonad.nix
index 74acfc219759..c922ca7848d1 100644
--- a/nixos/modules/services/x11/window-managers/xmonad.nix
+++ b/nixos/modules/services/x11/window-managers/xmonad.nix
@@ -3,11 +3,12 @@
 let
   inherit (lib) mkOption mkIf optionals literalExample;
   cfg = config.services.xserver.windowManager.xmonad;
-  xmonadEnv = cfg.haskellPackages.ghcWithPackages(self: [
-    self.xmonad
-  ] ++ optionals cfg.enableContribAndExtras [ self.xmonadContrib self.xmonadExtras]
-    ++ optionals (cfg.extraPackages != null) (cfg.extraPackages self));
-  xmessage = pkgs.xlibs.xmessage;
+  xmonad = pkgs.xmonad-with-packages.override {
+    ghcWithPackages = cfg.haskellPackages.ghcWithPackages;
+    packages = self: cfg.extraPackages self ++
+                     optionals cfg.enableContribAndExtras
+                     [ self.xmonad-contrib self.xmonad-extras ];
+  };
 in
 {
   options = {
@@ -19,9 +20,9 @@ in
       };
 
       haskellPackages = mkOption {
-        default = pkgs.haskellPackages;
-        defaultText = "pkgs.haskellPackages";
-        example = literalExample "pkgs.haskellPackages_ghc701";
+        default = pkgs.haskellngPackages;
+        defaultText = "pkgs.haskellngPackages";
+        example = literalExample "pkgs.haskell-ng.packages.ghc784";
         description = ''
           haskellPackages used to build Xmonad and other packages.
           This can be used to change the GHC version used to build
@@ -31,17 +32,17 @@ in
       };
 
       extraPackages = mkOption {
-        default = null;
+        default = self: [];
         example = literalExample ''
           haskellPackages: [
-            haskellPackages.xmonadContrib
-            haskellPackages.monadLogger
+            haskellPackages.xmonad-contrib
+            haskellPackages.monad-logger
           ]
         '';
         description = ''
           Extra packages available to ghc when rebuilding Xmonad. The
           value must be a function which receives the attrset defined
-          in <varname>haskellpackages</varname> as the sole argument.
+          in <varname>haskellPackages</varname> as the sole argument.
         '';
       };
 
@@ -58,12 +59,12 @@ in
       session = [{
         name = "xmonad";
         start = ''
-          XMONAD_GHC=${xmonadEnv}/bin/ghc XMONAD_XMESSAGE=${xmessage}/bin/xmessage xmonad &
+          ${xmonad}/bin/xmonad &
           waitPID=$!
         '';
       }];
     };
 
-    environment.systemPackages = [ cfg.haskellPackages.xmonad ];
+    environment.systemPackages = [ xmonad ];
   };
 }
diff --git a/nixos/modules/system/boot/kernel.nix b/nixos/modules/system/boot/kernel.nix
index 79b173a6ead8..0cae9cb844c8 100644
--- a/nixos/modules/system/boot/kernel.nix
+++ b/nixos/modules/system/boot/kernel.nix
@@ -193,8 +193,9 @@ in
         "ohci_hcd"
         "ohci_pci"
         "xhci_hcd"
+        "xhci_pci"
         "usbhid"
-        "hid_generic"
+        "hid_generic" "hid_lenovo"
         "hid_apple" "hid_logitech_dj" "hid_lenovo_tpkbd" "hid_roccat"
 
         # Unix domain sockets (needed by udev).
diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix
index b16a725aba8e..0cfef7df1972 100644
--- a/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixos/modules/system/boot/loader/grub/grub.nix
@@ -6,6 +6,8 @@ let
 
   cfg = config.boot.loader.grub;
 
+  efi = config.boot.loader.efi;
+
   realGrub = if cfg.version == 1 then pkgs.grub
     else pkgs.grub2.override { zfsSupport = cfg.zfsSupport; };
 
@@ -16,21 +18,31 @@ let
     then null
     else realGrub;
 
+  grubEfi =
+    # EFI version of Grub v2
+    if (cfg.devices != ["nodev"]) && cfg.efiSupport && (cfg.version == 2)
+    then pkgs.grub2.override { zfsSupport = cfg.zfsSupport; efiSupport = cfg.efiSupport; }
+    else null;
+
   f = x: if x == null then "" else "" + x;
 
   grubConfig = pkgs.writeText "grub-config.xml" (builtins.toXML
     { splashImage = f config.boot.loader.grub.splashImage;
       grub = f grub;
+      grubTarget = f (grub.grubTarget or "");
       shell = "${pkgs.stdenv.shell}";
       fullVersion = (builtins.parseDrvName realGrub.name).version;
+      grubEfi = f grubEfi;
+      grubTargetEfi = if cfg.efiSupport && (cfg.version == 2) then f grubEfi.grubTarget else "";
+      inherit (efi) efiSysMountPoint canTouchEfiVariables;
       inherit (cfg)
         version extraConfig extraPerEntryConfig extraEntries
         extraEntriesBeforeNixOS extraPrepareConfig configurationLimit copyKernels timeout
-        default devices fsIdentifier;
-      path = (makeSearchPath "bin" [
+        default devices fsIdentifier efiSupport;
+      path = (makeSearchPath "bin" ([
         pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.findutils pkgs.diffutils pkgs.btrfsProgs
-        pkgs.utillinux
-      ]) + ":" + (makeSearchPath "sbin" [
+        pkgs.utillinux ] ++ (if cfg.efiSupport && (cfg.version == 2) then [pkgs.efibootmgr ] else [])
+      )) + ":" + (makeSearchPath "sbin" [
         pkgs.mdadm pkgs.utillinux
       ]);
     });
@@ -231,6 +243,18 @@ in
         type = types.bool;
         description = ''
           Whether grub should be build against libzfs.
+          ZFS support is only available for GRUB v2.
+          This option is ignored for GRUB v1.
+        '';
+      };
+
+      efiSupport = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Whether grub should be build with EFI support.
+          EFI support is only available for GRUB v2.
+          This option is ignored for GRUB v1.
         '';
       };
 
@@ -269,7 +293,7 @@ in
         if cfg.devices == [] then
           throw "You must set the option ‘boot.loader.grub.device’ to make the system bootable."
         else
-          "PERL5LIB=${makePerlPath (with pkgs.perlPackages; [ FileSlurp XMLLibXML XMLSAX ])} " +
+          "PERL5LIB=${makePerlPath (with pkgs.perlPackages; [ FileSlurp XMLLibXML XMLSAX ListCompare ])} " +
           (if cfg.enableCryptodisk then "GRUB_ENABLE_CRYPTODISK=y " else "") +
           "${pkgs.perl}/bin/perl ${./install-grub.pl} ${grubConfig}";
 
diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl
index ffee0271e93b..74a934c67931 100644
--- a/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ b/nixos/modules/system/boot/loader/grub/install-grub.pl
@@ -7,6 +7,7 @@ use File::Path;
 use File::stat;
 use File::Copy;
 use File::Slurp;
+require List::Compare;
 use POSIX;
 use Cwd;
 
@@ -39,6 +40,7 @@ sub runCommand {
 
 my $grub = get("grub");
 my $grubVersion = int(get("version"));
+my $grubTarget = get("grubTarget");
 my $extraConfig = get("extraConfig");
 my $extraPrepareConfig = get("extraPrepareConfig");
 my $extraPerEntryConfig = get("extraPerEntryConfig");
@@ -50,6 +52,10 @@ my $copyKernels = get("copyKernels") eq "true";
 my $timeout = int(get("timeout"));
 my $defaultEntry = int(get("default"));
 my $fsIdentifier = get("fsIdentifier");
+my $grubEfi = get("grubEfi");
+my $grubTargetEfi = get("grubTargetEfi");
+my $canTouchEfiVariables = get("canTouchEfiVariables");
+my $efiSysMountPoint = get("efiSysMountPoint");
 $ENV{'PATH'} = get("path");
 
 die "unsupported GRUB version\n" if $grubVersion != 1 && $grubVersion != 2;
@@ -103,6 +109,8 @@ sub GetFs {
 
         # Skip the read-only bind-mount on /nix/store.
         next if $mountPoint eq "/nix/store" && (grep { $_ eq "rw" } @superOptions) && (grep { $_ eq "ro" } @mountOptions);
+        # Skip mount point generated by systemd-efi-boot-generator?
+        next if $fsType eq "autofs";
 
         # Ensure this matches the intended directory
         next unless PathInMount($dir, $mountPoint);
@@ -402,16 +410,114 @@ foreach my $fn (glob "/boot/kernels/*") {
 }
 
 
-# Install GRUB if the version changed from the last time we installed
-# it.  FIXME: shouldn't we reinstall if ‘devices’ changed?
-my $prevVersion = readFile("/boot/grub/version") // "";
-if (($ENV{'NIXOS_INSTALL_GRUB'} // "") eq "1" || get("fullVersion") ne $prevVersion) {
+#
+# Install GRUB if the parameters changed from the last time we installed it.
+#
+
+struct(GrubState => {
+    version => '$',
+    efi => '$',
+    devices => '$',
+    efiMountPoint => '$',
+});
+sub readGrubState {
+    my $defaultGrubState = GrubState->new(version => "", efi => "", devices => "", efiMountPoint => "" );
+    open FILE, "</boot/grub/state" or return $defaultGrubState;
+    local $/ = "\n";
+    my $version = <FILE>;
+    chomp($version);
+    my $efi = <FILE>;
+    chomp($efi);
+    my $devices = <FILE>;
+    chomp($devices);
+    my $efiMountPoint = <FILE>;
+    chomp($efiMountPoint);
+    close FILE;
+    my $grubState = GrubState->new(version => $version, efi => $efi, devices => $devices, efiMountPoint => $efiMountPoint );
+    return $grubState
+}
+
+sub getDeviceTargets {
+    my @devices = ();
     foreach my $dev ($dom->findnodes('/expr/attrs/attr[@name = "devices"]/list/string/@value')) {
         $dev = $dev->findvalue(".") or die;
+        push(@devices, $dev);
+    }
+    return @devices;
+}
+
+# check whether to install GRUB EFI or not
+sub getEfiTarget {
+    if (($grub ne "") && ($grubEfi ne "")) {
+        # EFI can only be installed when target is set;
+        # A target is also required then for non-EFI grub
+        if (($grubTarget eq "") || ($grubTargetEfi eq "")) { die }
+        else { return "both" }
+    } elsif (($grub ne "") && ($grubEfi eq "")) {
+        # TODO: It would be safer to disallow non-EFI grub installation if no taget is given.
+        #       If no target is given, then grub auto-detects the target which can lead to errors.
+        #       E.g. it seems as if grub would auto-detect a EFI target based on the availability
+        #       of a EFI partition.
+        #       However, it seems as auto-detection is currently relied on for non-x86_64 and non-i386
+        #       architectures in NixOS. That would have to be fixed in the nixos modules first.
+        return "no"
+    } elsif (($grub eq "") && ($grubEfi ne "")) {
+        # EFI can only be installed when target is set;
+        if ($grubTargetEfi eq "") { die }
+        else {return "only" }
+    } else {
+        # at least one grub target has to be given
+        die
+    }
+}
+
+my @deviceTargets = getDeviceTargets();
+my $efiTarget = getEfiTarget();
+my $prevGrubState = readGrubState();
+my @prevDeviceTargets = split/:/, $prevGrubState->devices;
+
+my $devicesDiffer = scalar (List::Compare->new( '-u', '-a', \@deviceTargets, \@prevDeviceTargets)->get_symmetric_difference() );
+my $versionDiffer = (get("fullVersion") eq \$prevGrubState->version);
+my $efiDiffer = ($efiTarget eq \$prevGrubState->efi);
+my $efiMountPointDiffer = ($efiSysMountPoint eq \$prevGrubState->efiMountPoint);
+my $requireNewInstall = $devicesDiffer || $versionDiffer || $efiDiffer || $efiMountPointDiffer || (($ENV{'NIXOS_INSTALL_GRUB'} // "") eq "1");
+
+
+# install non-EFI GRUB
+if (($requireNewInstall != 0) && ($efiTarget eq "no" || $efiTarget eq "both")) {
+    foreach my $dev (@deviceTargets) {
         next if $dev eq "nodev";
         print STDERR "installing the GRUB $grubVersion boot loader on $dev...\n";
-        system("$grub/sbin/grub-install", "--recheck", Cwd::abs_path($dev)) == 0
-            or die "$0: installation of GRUB on $dev failed\n";
+        if ($grubTarget eq "") {
+            system("$grub/sbin/grub-install", "--recheck", Cwd::abs_path($dev)) == 0
+                or die "$0: installation of GRUB on $dev failed\n";
+        } else {
+            system("$grub/sbin/grub-install", "--recheck", "--target=$grubTarget", Cwd::abs_path($dev)) == 0
+                or die "$0: installation of GRUB on $dev failed\n";
+        }
     }
-    writeFile("/boot/grub/version", get("fullVersion"));
+}
+
+
+# install EFI GRUB
+if (($requireNewInstall != 0) && ($efiTarget eq "only" || $efiTarget eq "both")) {
+    print STDERR "installing the GRUB $grubVersion EFI boot loader into $efiSysMountPoint...\n";
+    if ($canTouchEfiVariables eq "true") {
+        system("$grubEfi/sbin/grub-install", "--recheck", "--target=$grubTargetEfi", "--efi-directory=$efiSysMountPoint") == 0
+                or die "$0: installation of GRUB EFI into $efiSysMountPoint failed\n";
+    } else {
+        system("$grubEfi/sbin/grub-install", "--recheck", "--target=$grubTargetEfi", "--efi-directory=$efiSysMountPoint", "--no-nvram") == 0
+                or die "$0: installation of GRUB EFI into $efiSysMountPoint failed\n";
+    }
+}
+
+
+# update GRUB state file
+if ($requireNewInstall != 0) {
+    open FILE, ">/boot/grub/state" or die "cannot create /boot/grub/state: $!\n";
+    print FILE get("fullVersion"), "\n" or die;
+    print FILE $efiTarget, "\n" or die;
+    print FILE join( ":", @deviceTargets ), "\n" or die;
+    print FILE $efiSysMountPoint, "\n" or die;
+    close FILE or die;
 }
diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh
index 0b7d4de6d205..8f185217c3f8 100644
--- a/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixos/modules/system/boot/stage-1-init.sh
@@ -7,6 +7,8 @@ export LD_LIBRARY_PATH=@extraUtils@/lib
 export PATH=@extraUtils@/bin
 ln -s @extraUtils@/bin /bin
 
+# Stop LVM complaining about fd3
+export LVM_SUPPRESS_FD_WARNINGS=true
 
 fail() {
     if [ -n "$panicOnFail" ]; then exit 1; fi
@@ -347,7 +349,8 @@ while read -u 3 mountPoint; do
     # that we don't properly recognise.
     if test -z "$pseudoDevice" -a ! -e $device; then
         echo -n "waiting for device $device to appear..."
-        for try in $(seq 1 20); do
+        try=20
+        while [ $try -gt 0 ]; do
             sleep 1
             # also re-try lvm activation now that new block devices might have appeared
             lvm vgchange -ay
@@ -355,8 +358,12 @@ while read -u 3 mountPoint; do
             udevadm trigger --action=add
             if test -e $device; then break; fi
             echo -n "."
+            try=$((try - 1))
         done
         echo
+        if [ $try -eq 0 ]; then
+          echo "Timed out waiting for device $device, trying to mount anyway."
+        fi
     fi
 
     # Wait once more for the udev queue to empty, just in case it's
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index f0d8b04d0875..16bebe03740a 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -46,7 +46,7 @@ let
       cp -pv ${pkgs.glibc}/lib/libpthread.so.* $out/lib
       cp -pv ${pkgs.glibc}/lib/librt.so.* $out/lib
       cp -pv ${pkgs.glibc}/lib/libdl.so.* $out/lib
-      cp -pv ${pkgs.gcc.gcc}/lib*/libgcc_s.so.* $out/lib
+      cp -pv ${pkgs.gcc.cc}/lib*/libgcc_s.so.* $out/lib
 
       # Copy BusyBox.
       cp -pvd ${pkgs.busybox}/bin/* ${pkgs.busybox}/sbin/* $out/bin/
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index 053a85c4c5b9..f853a8f6775c 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -1040,6 +1040,11 @@ in
       ''
         # This file is created automatically and should not be modified.
         # Please change the option ‘systemd.tmpfiles.rules’ instead.
+
+        z /var/log/journal 2755 root systemd-journal - -
+        z /var/log/journal/%m 2755 root systemd-journal - -
+        z /var/log/journal/%m/* 0640 root systemd-journal - -
+
         ${concatStringsSep "\n" cfg.tmpfiles.rules}
       '';
 
diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix
index ab5942b79453..93782ffa4d58 100644
--- a/nixos/modules/tasks/filesystems/zfs.nix
+++ b/nixos/modules/tasks/filesystems/zfs.nix
@@ -21,11 +21,12 @@ let
 
   kernel = config.boot.kernelPackages;
 
-  splPkg = if cfgZfs.useGit then kernel.spl_git else kernel.spl;
-  zfsPkg = if cfgZfs.useGit then kernel.zfs_git else kernel.zfs;
+  splKernelPkg = if cfgZfs.useGit then kernel.spl_git else kernel.spl;
+  zfsKernelPkg = if cfgZfs.useGit then kernel.zfs_git else kernel.zfs;
+  zfsUserPkg = if cfgZfs.useGit then pkgs.zfs_git else pkgs.zfs;
 
   autosnapPkg = pkgs.zfstools.override {
-    zfs = zfsPkg;
+    zfs = zfsUserPkg;
   };
 
   zfsAutoSnap = "${autosnapPkg}/bin/zfs-auto-snapshot";
@@ -54,7 +55,8 @@ in
     boot.zfs = {
       useGit = mkOption {
         type = types.bool;
-        default = false;
+        # TODO(wkennington): Revert when 0.6.4 is out
+        default = versionAtLeast config.boot.kernelPackages.kernel.version "3.19";
         example = true;
         description = ''
           Use the git version of the SPL and ZFS packages.
@@ -195,17 +197,17 @@ in
 
       boot = {
         kernelModules = [ "spl" "zfs" ] ;
-        extraModulePackages = [ splPkg zfsPkg ];
+        extraModulePackages = [ splKernelPkg zfsKernelPkg ];
       };
 
       boot.initrd = mkIf inInitrd {
         kernelModules = [ "spl" "zfs" ];
         extraUtilsCommands =
           ''
-            cp -v ${zfsPkg}/sbin/zfs $out/bin
-            cp -v ${zfsPkg}/sbin/zdb $out/bin
-            cp -v ${zfsPkg}/sbin/zpool $out/bin
-            cp -pdv ${zfsPkg}/lib/lib*.so* $out/lib
+            cp -v ${zfsUserPkg}/sbin/zfs $out/bin
+            cp -v ${zfsUserPkg}/sbin/zdb $out/bin
+            cp -v ${zfsUserPkg}/sbin/zpool $out/bin
+            cp -pdv ${zfsUserPkg}/lib/lib*.so* $out/lib
             cp -pdv ${pkgs.zlib}/lib/lib*.so* $out/lib
           '';
         postDeviceCommands = concatStringsSep "\n" ([''
@@ -228,12 +230,12 @@ in
         zfsSupport = true;
       };
 
-      environment.etc."zfs/zed.d".source = "${zfsPkg}/etc/zfs/zed.d/*";
+      environment.etc."zfs/zed.d".source = "${zfsUserPkg}/etc/zfs/zed.d/*";
 
-      system.fsPackages = [ zfsPkg ];                  # XXX: needed? zfs doesn't have (need) a fsck
-      environment.systemPackages = [ zfsPkg ];
-      services.udev.packages = [ zfsPkg ];             # to hook zvol naming, etc.
-      systemd.packages = [ zfsPkg ];
+      system.fsPackages = [ zfsUserPkg ];                  # XXX: needed? zfs doesn't have (need) a fsck
+      environment.systemPackages = [ zfsUserPkg ];
+      services.udev.packages = [ zfsUserPkg ];             # to hook zvol naming, etc.
+      systemd.packages = [ zfsUserPkg ];
 
       systemd.services = let
         getPoolFilesystems = pool:
@@ -260,7 +262,7 @@ in
               RemainAfterExit = true;
             };
             script = ''
-              zpool_cmd="${zfsPkg}/sbin/zpool"
+              zpool_cmd="${zfsUserPkg}/sbin/zpool"
               ("$zpool_cmd" list "${pool}" >/dev/null) || "$zpool_cmd" import -N ${optionalString cfgZfs.forceImportAll "-f"} "${pool}"
             '';
           };