summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
Diffstat (limited to 'nixos')
-rw-r--r--nixos/lib/make-squashfs.nix2
-rw-r--r--nixos/lib/make-system-tarball.sh2
-rw-r--r--nixos/lib/test-driver/test-driver.pl6
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-minimal.nix8
-rw-r--r--nixos/modules/installer/cd-dvd/iso-image.nix2
-rw-r--r--nixos/modules/misc/ids.nix4
-rw-r--r--nixos/modules/misc/locate.nix11
-rw-r--r--nixos/modules/module-list.nix2
-rw-r--r--nixos/modules/profiles/base.nix2
-rw-r--r--nixos/modules/services/monitoring/graphite.nix2
-rw-r--r--nixos/modules/services/monitoring/prometheus/alertmanager.nix4
-rw-r--r--nixos/modules/services/networking/asterisk.nix60
-rw-r--r--nixos/modules/services/networking/bird.nix1
-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/miredo.nix93
-rw-r--r--nixos/modules/services/networking/ssh/sshd.nix5
-rw-r--r--nixos/modules/services/torrent/flexget.nix6
-rw-r--r--nixos/modules/services/web-apps/atlassian/crowd.nix17
-rw-r--r--nixos/modules/services/x11/desktop-managers/gnome3.nix1
-rw-r--r--nixos/modules/services/x11/hardware/wacom.nix4
-rw-r--r--nixos/modules/virtualisation/docker.nix4
-rw-r--r--nixos/modules/virtualisation/openstack/common.nix30
-rw-r--r--nixos/modules/virtualisation/openstack/glance.nix245
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix4
-rw-r--r--nixos/release.nix1
-rw-r--r--nixos/tests/glance.nix77
-rw-r--r--nixos/tests/gnome3.nix2
-rw-r--r--nixos/tests/openssh.nix23
29 files changed, 581 insertions, 41 deletions
diff --git a/nixos/lib/make-squashfs.nix b/nixos/lib/make-squashfs.nix
index 2baa4f667607..4100af27becb 100644
--- a/nixos/lib/make-squashfs.nix
+++ b/nixos/lib/make-squashfs.nix
@@ -25,6 +25,6 @@ stdenv.mkDerivation {
 
       # Generate the squashfs image.
       mksquashfs nix-path-registration $storePaths $out \
-        -keep-as-directory -all-root -comp xz
+        -keep-as-directory -all-root -b 1048576 -comp xz -Xdict-size 100%
     '';
 }
diff --git a/nixos/lib/make-system-tarball.sh b/nixos/lib/make-system-tarball.sh
index efb83d914287..73a009d8488a 100644
--- a/nixos/lib/make-system-tarball.sh
+++ b/nixos/lib/make-system-tarball.sh
@@ -54,7 +54,7 @@ mkdir -p $out/tarball
 
 rm env-vars
 
-tar --sort=name --mtime='1970-01-01' -cvJf $out/tarball/$fileName.tar.xz * $extraArgs
+tar --sort=name --mtime='@1' --owner=0 --group=0 --numeric-owner -cvJf $out/tarball/$fileName.tar.xz * $extraArgs
 
 mkdir -p $out/nix-support
 echo $system > $out/nix-support/system
diff --git a/nixos/lib/test-driver/test-driver.pl b/nixos/lib/test-driver/test-driver.pl
index 8ad0d67f68c3..854be99552a0 100644
--- a/nixos/lib/test-driver/test-driver.pl
+++ b/nixos/lib/test-driver/test-driver.pl
@@ -8,6 +8,7 @@ use IO::Pty;
 use Logger;
 use Cwd;
 use POSIX qw(_exit dup2);
+use Time::HiRes qw(clock_gettime CLOCK_MONOTONIC);
 
 $SIG{PIPE} = 'IGNORE'; # because Unix domain sockets may die unexpectedly
 
@@ -179,7 +180,12 @@ END {
     $log->close();
 }
 
+my $now1 = clock_gettime(CLOCK_MONOTONIC);
 
 runTests;
 
+my $now2 = clock_gettime(CLOCK_MONOTONIC);
+
+printf STDERR "test script finished in %.2fs\n", $now2 - $now1;
+
 exit ($nrSucceeded < $nrTests ? 1 : 0);
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix b/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix
index 4641b8fcf9d1..f4122ab0e518 100644
--- a/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix
+++ b/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix
@@ -1,11 +1,15 @@
 # This module defines a small NixOS installation CD.  It does not
 # contain any graphical stuff.
 
-{ config, lib, ... }:
+{ config, lib, pkgs, ... }:
 
 {
   imports =
     [ ./installation-cd-base.nix
-      ../../profiles/minimal.nix
+    ];
+
+  environment.systemPackages =
+    [
+      pkgs.vim
     ];
 }
diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix
index 4fc8bf5428f8..fea1c8849537 100644
--- a/nixos/modules/installer/cd-dvd/iso-image.nix
+++ b/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -178,7 +178,7 @@ in
         image. It significantly increases image size. Use that when
         you want to be able to keep all the sources needed to build your
         system or when you are going to install the system on a computer
-        with slow on non-existent network connection.
+        with slow or non-existent network connection.
       '';
     };
 
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 707057711831..6ab4b24a3491 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -281,6 +281,7 @@
       riak-cs = 263;
       infinoted = 264;
       keystone = 265;
+      glance = 266;
 
       # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
 
@@ -467,7 +468,7 @@
       ihaskell = 189;
       i2p = 190;
       lambdabot = 191;
-      #asterisk = 192; # unused
+      asterisk = 192;
       plex = 193;
       sabnzbd = 194;
       #grafana = 196; #unused
@@ -532,6 +533,7 @@
       riak-cs = 263;
       infinoted = 264;
       keystone = 265;
+      glance = 266;
 
       # 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/misc/locate.nix b/nixos/modules/misc/locate.nix
index 27a0fa6cf3d4..3cb5bb1a351a 100644
--- a/nixos/modules/misc/locate.nix
+++ b/nixos/modules/misc/locate.nix
@@ -15,6 +15,15 @@ in {
       '';
     };
 
+    locate = mkOption {
+      type = types.package;
+      default = pkgs.findutils;
+      example = "pkgs.mlocate";
+      description = ''
+        The locate implementation to use
+      '';
+    };
+
     interval = mkOption {
       type = types.str;
       default = "02:15";
@@ -77,7 +86,7 @@ in {
         script =
           ''
             mkdir -m 0755 -p $(dirname ${toString cfg.output})
-            exec updatedb \
+            exec ${cfg.locate}/bin/updatedb \
               --localuser=${cfg.localuser} \
               ${optionalString (!cfg.includeStore) "--prunepaths='/nix/store'"} \
               --output=${toString cfg.output} ${concatStringsSep " " cfg.extraFlags}
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index b3177589716d..be09fb80e0ac 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -393,6 +393,7 @@
   ./services/networking/minidlna.nix
   ./services/networking/miniupnpd.nix
   ./services/networking/mosquitto.nix
+  ./services/networking/miredo.nix
   ./services/networking/mstpd.nix
   ./services/networking/murmur.nix
   ./services/networking/namecoind.nix
@@ -633,4 +634,5 @@
   ./virtualisation/xen-dom0.nix
   ./virtualisation/xe-guest-utilities.nix
   ./virtualisation/openstack/keystone.nix
+  ./virtualisation/openstack/glance.nix
 ]
diff --git a/nixos/modules/profiles/base.nix b/nixos/modules/profiles/base.nix
index f90d0d992ec8..687cd9d80d36 100644
--- a/nixos/modules/profiles/base.nix
+++ b/nixos/modules/profiles/base.nix
@@ -45,7 +45,7 @@
   ];
 
   # Include support for various filesystems.
-  boot.supportedFilesystems = [ "btrfs" "reiserfs" "vfat" "f2fs" "xfs" "zfs" "ntfs" "cifs" ];
+  boot.supportedFilesystems = [ "btrfs" "reiserfs" "vfat" "f2fs" "xfs" "ntfs" "cifs" ];
 
   # Configure host id for ZFS to work
   networking.hostId = lib.mkDefault "8425e349";
diff --git a/nixos/modules/services/monitoring/graphite.nix b/nixos/modules/services/monitoring/graphite.nix
index b8be9296bc97..c5352e5887da 100644
--- a/nixos/modules/services/monitoring/graphite.nix
+++ b/nixos/modules/services/monitoring/graphite.nix
@@ -585,7 +585,7 @@ in {
         serviceConfig = {
           ExecStart = ''
             ${pkgs.pythonPackages.graphite_beacon}/bin/graphite-beacon \
-              --config ${pkgs.writeText "graphite-beacon.json" (builtins.toJSON cfg.beacon.config)}
+              --config=${pkgs.writeText "graphite-beacon.json" (builtins.toJSON cfg.beacon.config)}
           '';
           User = "graphite";
           Group = "graphite";
diff --git a/nixos/modules/services/monitoring/prometheus/alertmanager.nix b/nixos/modules/services/monitoring/prometheus/alertmanager.nix
index a9c0ce4ed6cb..da2cd02eaa3b 100644
--- a/nixos/modules/services/monitoring/prometheus/alertmanager.nix
+++ b/nixos/modules/services/monitoring/prometheus/alertmanager.nix
@@ -62,8 +62,8 @@ in {
       };
 
       listenAddress = mkOption {
-        type = types.nullOr types.str;
-        default = null;
+        type = types.str;
+        default = "";
         description = ''
           Address to listen on for the web interface and API.
         '';
diff --git a/nixos/modules/services/networking/asterisk.nix b/nixos/modules/services/networking/asterisk.nix
index 13617a1b6c58..5c71a1d8ddae 100644
--- a/nixos/modules/services/networking/asterisk.nix
+++ b/nixos/modules/services/networking/asterisk.nix
@@ -6,29 +6,38 @@ let
   cfg = config.services.asterisk;
 
   asteriskUser = "asterisk";
+  asteriskGroup = "asterisk";
 
   varlibdir = "/var/lib/asterisk";
   spooldir = "/var/spool/asterisk";
   logdir = "/var/log/asterisk";
 
+  # Add filecontents from files of useTheseDefaultConfFiles to confFiles, do not override
+  defaultConfFiles = subtractLists (attrNames cfg.confFiles) cfg.useTheseDefaultConfFiles;
+  allConfFiles =
+    cfg.confFiles //
+    builtins.listToAttrs (map (x: { name = x;
+                                    value = builtins.readFile (pkgs.asterisk + "/etc/asterisk/" + x); })
+                              defaultConfFiles);
+
   asteriskEtc = pkgs.stdenv.mkDerivation
   ((mapAttrs' (name: value: nameValuePair
         # Fudge the names to make bash happy
         ((replaceChars ["."] ["_"] name) + "_")
         (value)
-      ) cfg.confFiles) //
+      ) allConfFiles) //
   {
     confFilesString = concatStringsSep " " (
-      attrNames cfg.confFiles
+      attrNames allConfFiles
     );
 
-    name = "asterisk.etc";
+    name = "asterisk-etc";
 
     # Default asterisk.conf file
     # (Notice that astetcdir will be set to the path of this derivation)
     asteriskConf = ''
       [directories]
-      astetcdir => @out@
+      astetcdir => /etc/asterisk
       astmoddir => ${pkgs.asterisk}/lib/asterisk/modules
       astvarlibdir => /var/lib/asterisk
       astdbdir => /var/lib/asterisk
@@ -169,6 +178,16 @@ in
         '';
       };
 
+      useTheseDefaultConfFiles = mkOption {
+        default = [ "ari.conf" "acl.conf" "agents.conf" "amd.conf" "calendar.conf" "cdr.conf" "cdr_syslog.conf" "cdr_custom.conf" "cel.conf" "cel_custom.conf" "cli_aliases.conf" "confbridge.conf" "dundi.conf" "features.conf" "hep.conf" "iax.conf" "pjsip.conf" "pjsip_wizard.conf" "phone.conf" "phoneprov.conf" "queues.conf" "res_config_sqlite3.conf" "res_parking.conf" "statsd.conf" "udptl.conf" "unistim.conf" ];
+        type = types.listOf types.str;
+        example = [ "sip.conf" "dundi.conf" ];
+        description = ''Sets these config files to the default content. The default value for
+          this option contains all necesscary files to avoid errors at startup.
+          This does not override settings via <option>services.asterisk.confFiles</option>.
+        '';
+      };
+
       extraArguments = mkOption {
         default = [];
         type = types.listOf types.str;
@@ -182,12 +201,22 @@ in
   };
 
   config = mkIf cfg.enable {
-    users.extraUsers = singleton
-    { name = asteriskUser;
-      uid = config.ids.uids.asterisk;
-      description = "Asterisk daemon user";
-      home = varlibdir;
-    };
+    environment.systemPackages = [ pkgs.asterisk ];
+
+    environment.etc.asterisk.source = asteriskEtc;
+
+    users.extraUsers.asterisk =
+      { name = asteriskUser;
+        group = asteriskGroup;
+        uid = config.ids.uids.asterisk;
+        description = "Asterisk daemon user";
+        home = varlibdir;
+      };
+
+    users.extraGroups.asterisk =
+      { name = asteriskGroup;
+        gid = config.ids.gids.asterisk;
+      };
 
     systemd.services.asterisk = {
       description = ''
@@ -196,14 +225,17 @@ in
 
       wantedBy = [ "multi-user.target" ];
 
+      # Do not restart, to avoid disruption of running calls. Restart unit by yourself!
+      restartIfChanged = false;
+
       preStart = ''
         # Copy skeleton directory tree to /var
         for d in '${varlibdir}' '${spooldir}' '${logdir}'; do
           # TODO: Make exceptions for /var directories that likely should be updated
           if [ ! -e "$d" ]; then
             mkdir -p "$d"
-            cp --recursive ${pkgs.asterisk}/"$d" "$d"
-            chown --recursive ${asteriskUser} "$d"
+            cp --recursive ${pkgs.asterisk}/"$d"/* "$d"/
+            chown --recursive ${asteriskUser}:${asteriskGroup} "$d"
             find "$d" -type d | xargs chmod 0755
           fi
         done
@@ -215,7 +247,9 @@ in
             # FIXME: This doesn't account for arguments with spaces
             argString = concatStringsSep " " cfg.extraArguments;
           in
-          "${pkgs.asterisk}/bin/asterisk -U ${asteriskUser} -C ${asteriskEtc}/asterisk.conf ${argString} -F";
+          "${pkgs.asterisk}/bin/asterisk -U ${asteriskUser} -C /etc/asterisk/asterisk.conf ${argString} -F";
+        ExecReload = ''${pkgs.asterisk}/bin/asterisk -x "core reload"
+          '';
         Type = "forking";
         PIDFile = "/var/run/asterisk/asterisk.pid";
       };
diff --git a/nixos/modules/services/networking/bird.nix b/nixos/modules/services/networking/bird.nix
index 174354c9eb40..1a7a1e24b702 100644
--- a/nixos/modules/services/networking/bird.nix
+++ b/nixos/modules/services/networking/bird.nix
@@ -34,6 +34,7 @@ let
 
       ###### implementation
       config = mkIf cfg.enable {
+        environment.systemPackages = [ pkg ];
         systemd.services.${variant} = {
           description = "BIRD Internet Routing Daemon";
           wantedBy = [ "multi-user.target" ];
diff --git a/nixos/modules/services/networking/dnscrypt-proxy.nix b/nixos/modules/services/networking/dnscrypt-proxy.nix
index 82bf178f4cb7..462039803f80 100644
--- a/nixos/modules/services/networking/dnscrypt-proxy.nix
+++ b/nixos/modules/services/networking/dnscrypt-proxy.nix
@@ -263,6 +263,8 @@ in
     systemd.services.dnscrypt-proxy = {
       description = "dnscrypt-proxy daemon";
 
+      before = [ "nss-lookup.target" ];
+
       after = [ "network.target" ]
         ++ optional apparmorEnabled "apparmor.service"
         ++ optional useUpstreamResolverList "init-dnscrypt-proxy-statedir.service";
diff --git a/nixos/modules/services/networking/i2pd.nix b/nixos/modules/services/networking/i2pd.nix
index 578376764eba..abb7a4e9137c 100644
--- a/nixos/modules/services/networking/i2pd.nix
+++ b/nixos/modules/services/networking/i2pd.nix
@@ -147,7 +147,7 @@ let
   host = ${tun.address}
   port = ${tun.port}
   inport = ${tun.inPort}
-  accesslist = ${concatStringSep "," tun.accessList}
+  accesslist = ${builtins.concatStringsSep "," tun.accessList}
   '')
   }
   '';
diff --git a/nixos/modules/services/networking/miredo.nix b/nixos/modules/services/networking/miredo.nix
new file mode 100644
index 000000000000..e4422e7f5b02
--- /dev/null
+++ b/nixos/modules/services/networking/miredo.nix
@@ -0,0 +1,93 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.services.miredo;
+  pidFile = "/run/miredo.pid";
+  miredoConf = pkgs.writeText "miredo.conf" ''
+    InterfaceName ${cfg.interfaceName}
+    ServerAddress ${cfg.serverAddress}
+    ${optionalString (cfg.bindAddress != null) "BindAddress ${cfg.bindAddress}"}
+    ${optionalString (cfg.bindPort != null) "BindPort ${cfg.bindPort}"}
+  '';
+in
+{
+
+  ###### interface
+
+  options = {
+
+    services.miredo = {
+
+      enable = mkEnableOption "Whether miredo should be run on startup.";
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.miredo;
+        defaultText = "pkgs.miredo";
+        description = ''
+          The package to use for the miredo daemon's binary.
+        '';
+      };
+
+      serverAddress = mkOption {
+        default = "teredo.remlab.net";
+        type = types.str;
+        description = ''
+          The hostname or primary IPv4 address of the Teredo server.
+          This setting is required if Miredo runs as a Teredo client.
+          "teredo.remlab.net" is an experimental service for testing only.
+          Please use another server for production and/or large scale deployments.
+        '';
+      };
+
+      interfaceName = mkOption {
+        default = "teredo";
+        type = types.str;
+        description = ''
+          Name of the network tunneling interface.
+        '';
+      };
+
+      bindAddress = mkOption {
+        default = null;
+        type = types.nullOr types.str;
+        description = ''
+          Depending on the local firewall/NAT rules, you might need to force
+          Miredo to use a fixed UDP port and or IPv4 address.
+        '';
+      };
+
+      bindPort = mkOption {
+        default = null;
+        type = types.nullOr types.str;
+        description = ''
+          Depending on the local firewall/NAT rules, you might need to force
+          Miredo to use a fixed UDP port and or IPv4 address.
+        '';
+      };
+    };
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    systemd.services.miredo = {
+      wantedBy = [ "multi-user.target" ];
+      after = [ "network.target" ];
+      description = "Teredo IPv6 Tunneling Daemon";
+      serviceConfig = {
+        Restart = "always";
+        RestartSec = "5s";
+        ExecStartPre = "${cfg.package}/bin/miredo-checkconf -f ${miredoConf}";
+        ExecStart = "${cfg.package}/bin/miredo -c ${miredoConf} -p ${pidFile} -f";
+        ExecReload = "/bin/kill -HUP $MAINPID";
+      };
+    };
+
+  };
+
+}
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index 073391ffdbbc..80659f19c597 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -264,8 +264,7 @@ in
                 StandardInput = "socket";
               } else {
                 Restart = "always";
-                Type = "forking";
-                PIDFile = "/run/sshd.pid";
+                Type = "simple";
               });
           };
 
@@ -322,8 +321,6 @@ in
 
     services.openssh.extraConfig = mkOrder 0
       ''
-        PidFile /run/sshd.pid
-
         Protocol 2
 
         UsePAM yes
diff --git a/nixos/modules/services/torrent/flexget.nix b/nixos/modules/services/torrent/flexget.nix
index 1252aa1c549c..4b9038e3e251 100644
--- a/nixos/modules/services/torrent/flexget.nix
+++ b/nixos/modules/services/torrent/flexget.nix
@@ -4,7 +4,7 @@ with lib;
 
 let
   cfg = config.services.flexget;
-  pkg = pkgs.python27Packages.flexget;
+  pkg = pkgs.flexget;
   ymlFile = pkgs.writeText "flexget.yml" ''
     ${cfg.config}
 
@@ -54,12 +54,12 @@ in {
 
   config = mkIf cfg.enable {
 
-    environment.systemPackages = [ pkgs.python27Packages.flexget ];
+    environment.systemPackages = [ pkg ];
 
     systemd.services = {
       flexget = {
         description = "FlexGet Daemon";
-        path = [ pkgs.pythonPackages.flexget ];
+        path = [ pkg ];
         serviceConfig = {
           User = cfg.user;
           Environment = "TZ=${config.time.timeZone}";
diff --git a/nixos/modules/services/web-apps/atlassian/crowd.nix b/nixos/modules/services/web-apps/atlassian/crowd.nix
index 5e79678023da..ada26f8057ba 100644
--- a/nixos/modules/services/web-apps/atlassian/crowd.nix
+++ b/nixos/modules/services/web-apps/atlassian/crowd.nix
@@ -6,7 +6,12 @@ let
 
   cfg = config.services.crowd;
 
-  pkg = pkgs.atlassian-crowd;
+  pkg = pkgs.atlassian-crowd.override {
+    home = cfg.home;
+    port = cfg.listenPort;
+    proxyUrl = "${cfg.proxy.scheme}://${cfg.proxy.name}:${toString cfg.proxy.port}";
+    openidPassword = cfg.openidPassword;
+  };
 
 in
 
@@ -45,6 +50,11 @@ in
         description = "Port to listen on.";
       };
 
+      openidPassword = mkOption {
+        type = types.str;
+        description = "Application password for OpenID server.";
+      };
+
       catalinaOptions = mkOption {
         type = types.listOf types.str;
         default = [];
@@ -119,10 +129,10 @@ in
       };
 
       preStart = ''
-        mkdir -p ${cfg.home}/{logs,work}
+        mkdir -p ${cfg.home}/{logs,work,database}
 
         mkdir -p /run/atlassian-crowd
-        ln -sf ${cfg.home}/{work,server.xml} /run/atlassian-crowd
+        ln -sf ${cfg.home}/{database,work,server.xml} /run/atlassian-crowd
 
         chown -R ${cfg.user} ${cfg.home}
 
@@ -134,7 +144,6 @@ in
       '';
 
       script = "${pkg}/start_crowd.sh";
-      #stopScript  = "${pkg}/bin/stop_crowd.sh";
 
       serviceConfig = {
         User = cfg.user;
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index 5d1af09e7aa7..17e84b1d9a16 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -123,6 +123,7 @@ in {
     services.packagekit.enable = mkDefault true;
     hardware.bluetooth.enable = mkDefault true;
     services.xserver.libinput.enable = mkDefault true; # for controlling touchpad settings via gnome control center
+    services.udev.packages = [ pkgs.gnome3.gnome_settings_daemon ];
 
     fonts.fonts = [ pkgs.dejavu_fonts pkgs.cantarell_fonts ];
 
diff --git a/nixos/modules/services/x11/hardware/wacom.nix b/nixos/modules/services/x11/hardware/wacom.nix
index 540ed168b489..a27889c36a70 100644
--- a/nixos/modules/services/x11/hardware/wacom.nix
+++ b/nixos/modules/services/x11/hardware/wacom.nix
@@ -22,7 +22,7 @@ in
           which will make Xorg reconfigure the device ?
 
           If you're not satisfied by the default behaviour you can override
-          <option>environment.etc."X11/xorg.conf.d/50-wacom.conf"</option> in
+          <option>environment.etc."X11/xorg.conf.d/70-wacom.conf"</option> in
           configuration.nix easily.
         '';
       };
@@ -40,7 +40,7 @@ in
 
     services.udev.packages = [ pkgs.xf86_input_wacom ];
 
-    environment.etc."X11/xorg.conf.d/50-wacom.conf".source = "${pkgs.xf86_input_wacom}/share/X11/xorg.conf.d/50-wacom.conf";
+    environment.etc."X11/xorg.conf.d/70-wacom.conf".source = "${pkgs.xf86_input_wacom}/share/X11/xorg.conf.d/70-wacom.conf";
 
   };
 
diff --git a/nixos/modules/virtualisation/docker.nix b/nixos/modules/virtualisation/docker.nix
index 92249573a4b7..4b30a38f832f 100644
--- a/nixos/modules/virtualisation/docker.nix
+++ b/nixos/modules/virtualisation/docker.nix
@@ -130,4 +130,8 @@ in
     }
   ]);
 
+  imports = [
+    (mkRemovedOptionModule ["virtualisation" "docker" "socketActivation"] "This option was removed in favor of starting docker at boot")
+  ];
+
 }
diff --git a/nixos/modules/virtualisation/openstack/common.nix b/nixos/modules/virtualisation/openstack/common.nix
index 3fce54a2fa59..2feb0a873951 100644
--- a/nixos/modules/virtualisation/openstack/common.nix
+++ b/nixos/modules/virtualisation/openstack/common.nix
@@ -51,4 +51,34 @@ rec {
 	      };
             };});
   };
+  
+  databaseOption = name: {
+    host = mkOption {
+      type = types.str;
+      default = "localhost";
+      description = ''
+        Host of the database.
+      '';
+    };
+
+    name = mkOption {
+      type = types.str;
+      default = name;
+      description = ''
+        Name of the existing database.
+      '';
+    };
+
+    user = mkOption {
+      type = types.str;
+      default = name;
+      description = ''
+        The database user. The user must exist and has access to
+        the specified database.
+      '';
+    };
+    password = mkSecretOption {
+      name = name + "MysqlPassword";
+      description = "The database user's password";};
+  };
 }
diff --git a/nixos/modules/virtualisation/openstack/glance.nix b/nixos/modules/virtualisation/openstack/glance.nix
new file mode 100644
index 000000000000..4d85718e369c
--- /dev/null
+++ b/nixos/modules/virtualisation/openstack/glance.nix
@@ -0,0 +1,245 @@
+{ config, lib, pkgs, ... }:
+
+with lib; with import ./common.nix {inherit lib;};
+
+let
+  cfg = config.virtualisation.openstack.glance;
+  commonConf = ''
+    [database]
+    connection = "mysql://${cfg.database.user}:${cfg.database.password.pattern}@${cfg.database.host}/${cfg.database.name}"
+    notification_driver = noop
+
+    [keystone_authtoken]
+    auth_url = ${cfg.authUrl}
+    auth_plugin = password
+    project_name = service
+    project_domain_id = default
+    user_domain_id = default
+    username = ${cfg.serviceUsername}
+    password = ${cfg.servicePassword.pattern}
+
+    [glance_store]
+    default_store = file
+    filesystem_store_datadir = /var/lib/glance/images/
+  '';
+  glanceApiConfTpl = pkgs.writeText "glance-api.conf" ''
+    ${commonConf}
+
+    [paste_deploy]
+    flavor = keystone
+    config_file = ${cfg.package}/etc/glance-api-paste.ini
+  '';
+  glanceRegistryConfTpl = pkgs.writeText "glance-registry.conf" ''
+    ${commonConf}
+
+    [paste_deploy]
+    config_file = ${cfg.package}/etc/glance-registry-paste.ini
+  '';
+  glanceApiConf = "/var/lib/glance/glance-api.conf";
+  glanceRegistryConf = "/var/lib/glance/glance-registry.conf";
+
+in {
+  options.virtualisation.openstack.glance = {
+    package = mkOption {
+      type = types.package;
+      default = pkgs.glance;
+      example = literalExample "pkgs.glance";
+      description = ''
+        Glance package to use.
+      '';
+    };
+
+    enable = mkOption {
+      default = false;
+      type = types.bool;
+      description = ''
+        This option enables Glance as a single-machine
+        installation. That is, all of Glance's components are
+        enabled on this machine. This is useful for evaluating and
+        experimenting with Glance. Note we are currently not
+        providing any configurations for a multi-node setup.
+      '';
+    };
+
+    authUrl = mkOption {
+      type = types.str;
+      default = http://localhost:5000;
+      description = ''
+        Complete public Identity (Keystone) API endpoint. Note this is
+        unversionned.
+      '';
+    };
+
+    serviceUsername = mkOption {
+      type = types.str;
+      default = "glance";
+      description = ''
+        The Glance service username. This user is created if bootstrap
+        is enable, otherwise it has to be manually created before
+        starting this service.
+      '';
+    };
+
+    servicePassword = mkSecretOption {
+      name = "glanceAdminPassword";
+      description = ''
+        The Glance service user's password.
+      '';
+    };
+
+    database = databaseOption "glance";
+
+    bootstrap = {
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Bootstrap the Glance service by creating the service tenant,
+          an admin account and a public endpoint. This option provides
+          a ready-to-use glance service. This is only done at the
+          first Glance execution by the systemd post start section.
+          The keystone admin account is used to create required
+          Keystone resource for the Glance service.
+
+          <note><para> This option is a helper for setting up
+          development or testing environments.</para></note>
+        '';
+      };
+
+      endpointPublic = mkOption {
+        type = types.str;
+        default = "http://localhost:9292";
+        description = ''
+          The public image endpoint. The link <link
+          xlink:href="http://docs.openstack.org/liberty/install-guide-rdo/keystone-services.html">
+          create endpoint</link> provides more informations
+          about that.
+        '';
+      };
+
+      keystoneAdminUsername = mkOption {
+        type = types.str;
+        default = "admin";
+        description = ''
+          The keystone admin user name used to create the Glance account.
+        '';
+      };
+
+      keystoneAdminPassword = mkSecretOption {
+        name = "keystoneAdminPassword";
+        description = ''
+          The keystone admin user's password.
+        '';
+      };
+
+      keystoneAdminTenant = mkOption {
+        type = types.str;
+        default = "admin";
+        description = ''
+          The keystone admin tenant used to create the Glance account.
+        '';
+      };
+      keystoneAuthUrl = mkOption {
+        type = types.str;
+        default = "http://localhost:5000/v2.0";
+        description = ''
+          The keystone auth url used to create the Glance account.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    users.extraUsers = [{
+      name = "glance";
+      group = "glance";
+      uid = config.ids.gids.glance;
+
+    }];
+    users.extraGroups = [{
+      name = "glance";
+      gid = config.ids.gids.glance;
+    }];
+
+    systemd.services.glance-registry = {
+      description = "OpenStack Glance Registry Daemon";
+      after = [ "network.target"];
+      path = [ pkgs.curl pkgs.pythonPackages.keystoneclient pkgs.gawk ];
+      wantedBy = [ "multi-user.target" ];
+      preStart = ''
+        mkdir -m 775 -p /var/lib/glance/{images,scrubber,image_cache}
+        chown glance:glance /var/lib/glance/{images,scrubber,image_cache}
+
+        # Secret file managment
+        cp ${glanceRegistryConfTpl} ${glanceRegistryConf};
+        chown glance:glance ${glanceRegistryConf};
+        chmod 640 ${glanceRegistryConf}
+        ${replaceSecret cfg.database.password glanceRegistryConf}
+        ${replaceSecret cfg.servicePassword glanceRegistryConf}
+
+        cp ${glanceApiConfTpl} ${glanceApiConf};
+        chown glance:glance ${glanceApiConf};
+        chmod 640 ${glanceApiConf}
+        ${replaceSecret cfg.database.password glanceApiConf}
+        ${replaceSecret cfg.servicePassword glanceApiConf}
+
+        # Initialise the database
+        ${cfg.package}/bin/glance-manage --config-file=${glanceApiConf} --config-file=${glanceRegistryConf} db_sync
+      '';
+      postStart = ''
+        set -eu
+        export OS_AUTH_URL=${cfg.bootstrap.keystoneAuthUrl}
+        export OS_USERNAME=${cfg.bootstrap.keystoneAdminUsername}
+        export OS_PASSWORD=${getSecret cfg.bootstrap.keystoneAdminPassword}
+        export OS_TENANT_NAME=${cfg.bootstrap.keystoneAdminTenant}
+
+        # Wait until the keystone is available for use
+        count=0
+        while ! keystone user-get ${cfg.bootstrap.keystoneAdminUsername} > /dev/null
+        do
+            if [ $count -eq 30 ]
+            then
+                echo "Tried 30 times, giving up..."
+                exit 1
+            fi
+
+            echo "Keystone not yet started. Waiting for 1 second..."
+            count=$((count++))
+            sleep 1
+        done
+
+        # If the service glance doesn't exist, we consider glance is
+        # not initialized
+        if ! keystone service-get glance
+        then
+            keystone service-create --type image --name glance
+            ID=$(keystone service-get glance | awk '/ id / { print $4 }')
+            keystone endpoint-create --region RegionOne --service $ID --internalurl http://localhost:9292 --adminurl http://localhost:9292 --publicurl ${cfg.bootstrap.endpointPublic}
+
+            keystone user-create --name ${cfg.serviceUsername} --tenant service --pass ${getSecret cfg.servicePassword}
+            keystone user-role-add --tenant service --user ${cfg.serviceUsername} --role admin
+        fi
+        '';
+      serviceConfig = {
+        PermissionsStartOnly = true; # preStart must be run as root
+        TimeoutStartSec = "600"; # 10min for initial db migrations
+        User = "glance";
+        Group = "glance";
+        ExecStart = "${cfg.package}/bin/glance-registry --config-file=${glanceRegistryConf}";
+      };
+    };
+    systemd.services.glance-api = {
+      description = "OpenStack Glance API Daemon";
+      after = [ "glance-registry.service" "network.target"];
+      requires = [ "glance-registry.service" "network.target"]; 
+      wantedBy = [ "multi-user.target" ];
+      serviceConfig = {
+        PermissionsStartOnly = true; # preStart must be run as root
+        User = "glance";
+        Group = "glance";
+        ExecStart = "${cfg.package}/bin/glance-api --config-file=${glanceApiConf}";
+      };
+    };
+  };
+
+}
diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix
index 041c7dbec702..586f5d9c0a38 100644
--- a/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixos/modules/virtualisation/qemu-vm.nix
@@ -440,13 +440,13 @@ in
         ${if cfg.writableStore then "/nix/.ro-store" else "/nix/store"} =
           { device = "store";
             fsType = "9p";
-            options = [ "trans=virtio" "version=9p2000.L" "cache=loose" ];
+            options = [ "trans=virtio" "version=9p2000.L" "veryloose" ];
             neededForBoot = true;
           };
         "/tmp/xchg" =
           { device = "xchg";
             fsType = "9p";
-            options = [ "trans=virtio" "version=9p2000.L" "cache=loose" ];
+            options = [ "trans=virtio" "version=9p2000.L" "veryloose" ];
             neededForBoot = true;
           };
         "/tmp/shared" =
diff --git a/nixos/release.nix b/nixos/release.nix
index 366eecf773e2..dfa9b67654fb 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -242,6 +242,7 @@ in rec {
   tests.firewall = callTest tests/firewall.nix {};
   tests.fleet = hydraJob (import tests/fleet.nix { system = "x86_64-linux"; });
   #tests.gitlab = callTest tests/gitlab.nix {};
+  tests.glance = callTest tests/glance.nix {};
   tests.gocd-agent = callTest tests/gocd-agent.nix {};
   tests.gocd-server = callTest tests/gocd-server.nix {};
   tests.gnome3 = callTest tests/gnome3.nix {};
diff --git a/nixos/tests/glance.nix b/nixos/tests/glance.nix
new file mode 100644
index 000000000000..992b77227a4b
--- /dev/null
+++ b/nixos/tests/glance.nix
@@ -0,0 +1,77 @@
+{ system ? builtins.currentSystem }:
+
+with import ../lib/testing.nix { inherit system; };
+with pkgs.lib;
+
+let
+  glanceMysqlPassword = "glanceMysqlPassword";
+  glanceAdminPassword = "glanceAdminPassword";
+
+  createDb = pkgs.writeText "db-provisionning.sql" ''
+    create database keystone;
+    GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' IDENTIFIED BY 'keystone';
+    GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' IDENTIFIED BY 'keystone';
+
+    create database glance;
+    GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'localhost' IDENTIFIED BY '${glanceMysqlPassword}';
+    GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'%' IDENTIFIED BY '${glanceMysqlPassword}';
+  '';
+
+  image =
+    (import ../lib/eval-config.nix {
+      inherit system;
+      modules = [ ../../nixos/modules/virtualisation/nova-image.nix ];
+    }).config.system.build.novaImage;
+
+  # The admin keystone account
+  adminOpenstackCmd = "OS_TENANT_NAME=admin OS_USERNAME=admin OS_PASSWORD=keystone OS_AUTH_URL=http://localhost:5000/v3 OS_IDENTITY_API_VERSION=3 openstack";
+
+in makeTest {
+  meta = with pkgs.stdenv.lib.maintainers; {
+    maintainers = [ lewo ];
+  };
+  machine =
+    { config, pkgs, ... }:
+    {
+      services.mysql.enable = true;
+      services.mysql.package = pkgs.mysql;
+      services.mysql.initialScript = createDb;
+
+      virtualisation = {
+        openstack.keystone = {
+          enable = true;
+          database.password = { value = "keystone"; storage = "fromNixStore"; };
+          adminToken = { value = "adminToken"; storage = "fromNixStore"; };
+          bootstrap.enable = true;
+          bootstrap.adminPassword = { value = "keystone"; storage = "fromNixStore"; };
+        };
+
+        openstack.glance = {
+          enable = true;
+          database.password = { value = glanceMysqlPassword; storage = "fromNixStore"; };
+          servicePassword = { value = glanceAdminPassword; storage = "fromNixStore"; };
+
+          bootstrap = {
+            enable = true;
+            keystoneAdminPassword = { value = "keystone"; storage = "fromNixStore"; };
+          };
+        };
+
+        memorySize = 2096;
+        diskSize = 4 * 1024;
+        };
+
+      environment.systemPackages = with pkgs.pythonPackages; with pkgs; [
+        openstackclient
+      ];
+    };
+
+  testScript =
+    ''
+     $machine->waitForUnit("glance-api.service");
+
+     # Since Glance api can take time to start, we retry until success
+     $machine->waitUntilSucceeds("${adminOpenstackCmd} image create nixos --file ${image}/nixos.img --disk-format qcow2 --container-format bare --public");
+     $machine->succeed("${adminOpenstackCmd} image list") =~ /nixos/ or die;
+    '';
+}
diff --git a/nixos/tests/gnome3.nix b/nixos/tests/gnome3.nix
index bd8f9502e2fc..4787d42d695a 100644
--- a/nixos/tests/gnome3.nix
+++ b/nixos/tests/gnome3.nix
@@ -29,7 +29,7 @@ import ./make-test.nix ({ pkgs, ...} : {
       $machine->succeed("su - alice -c 'DISPLAY=:0.0 gnome-terminal &'");
       $machine->succeed("xauth merge ~alice/.Xauthority");
       $machine->waitForWindow(qr/Terminal/);
-      $machine->mustSucceed("timeout 900 bash -c 'journalctl -f|grep -m 1 \"GNOME Shell started\"'");
+      $machine->succeed("timeout 900 bash -c 'while read msg; do if [[ \$msg =~ \"GNOME Shell started\" ]]; then break; fi; done < <(journalctl -f)'");
       $machine->sleep(10);
       $machine->screenshot("screen");
     '';
diff --git a/nixos/tests/openssh.nix b/nixos/tests/openssh.nix
index 390363b88e21..291544996889 100644
--- a/nixos/tests/openssh.nix
+++ b/nixos/tests/openssh.nix
@@ -35,6 +35,18 @@ in {
         ];
       };
 
+    server_lazy =
+      { config, pkgs, ... }:
+
+      {
+        services.openssh = { enable = true; startWhenNeeded = true; };
+        security.pam.services.sshd.limits =
+          [ { domain = "*"; item = "memlock"; type = "-"; value = 1024; } ];
+        users.extraUsers.root.openssh.authorizedKeys.keys = [
+          snakeOilPublicKey
+        ];
+      };
+
     client =
       { config, pkgs, ... }: { };
 
@@ -50,6 +62,8 @@ in {
     subtest "manual-authkey", sub {
       $server->succeed("mkdir -m 700 /root/.ssh");
       $server->copyFileFromHost("key.pub", "/root/.ssh/authorized_keys");
+      $server_lazy->succeed("mkdir -m 700 /root/.ssh");
+      $server_lazy->copyFileFromHost("key.pub", "/root/.ssh/authorized_keys");
 
       $client->succeed("mkdir -m 700 /root/.ssh");
       $client->copyFileFromHost("key", "/root/.ssh/id_ed25519");
@@ -58,6 +72,10 @@ in {
       $client->waitForUnit("network.target");
       $client->succeed("ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no server 'echo hello world' >&2");
       $client->succeed("ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no server 'ulimit -l' | grep 1024");
+
+      $client->succeed("ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no server_lazy 'echo hello world' >&2");
+      $client->succeed("ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no server_lazy 'ulimit -l' | grep 1024");
+
     };
 
     subtest "configured-authkey", sub {
@@ -66,6 +84,11 @@ in {
       $client->succeed("ssh -o UserKnownHostsFile=/dev/null" .
                        " -o StrictHostKeyChecking=no -i privkey.snakeoil" .
                        " server true");
+
+      $client->succeed("ssh -o UserKnownHostsFile=/dev/null" .
+                       " -o StrictHostKeyChecking=no -i privkey.snakeoil" .
+                       " server_lazy true");
+
     };
   '';
 })