about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorFrederik Rietdijk <fridh@fridh.nl>2018-11-29 08:12:56 +0100
committerFrederik Rietdijk <fridh@fridh.nl>2018-11-29 08:12:56 +0100
commit9db2421d1f65beb38911e8133349193db0042a1d (patch)
tree90a2f4a56cf871c74aad86138d85e9631c2c2f86 /nixos
parent9caab8ff4a1ad36fbc0ab866f1b0f7c15d35ba90 (diff)
parent8d88e4f6c7b09fe811d92b346e5eafefe07a47c9 (diff)
downloadnixlib-9db2421d1f65beb38911e8133349193db0042a1d.tar
nixlib-9db2421d1f65beb38911e8133349193db0042a1d.tar.gz
nixlib-9db2421d1f65beb38911e8133349193db0042a1d.tar.bz2
nixlib-9db2421d1f65beb38911e8133349193db0042a1d.tar.lz
nixlib-9db2421d1f65beb38911e8133349193db0042a1d.tar.xz
nixlib-9db2421d1f65beb38911e8133349193db0042a1d.tar.zst
nixlib-9db2421d1f65beb38911e8133349193db0042a1d.zip
Merge master into staging-next
Diffstat (limited to 'nixos')
-rw-r--r--nixos/doc/manual/configuration/modularity.xml19
-rw-r--r--nixos/doc/manual/development/running-nixos-tests-interactively.xml2
-rw-r--r--nixos/doc/manual/development/writing-nixos-tests.xml2
-rw-r--r--nixos/doc/manual/release-notes/rl-1903.xml10
-rw-r--r--nixos/lib/testing.nix2
-rwxr-xr-xnixos/maintainers/scripts/gce/create-gce.sh4
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image.nix4
-rw-r--r--nixos/modules/programs/sway-beta.nix2
-rw-r--r--nixos/modules/services/cluster/kubernetes/default.nix8
-rw-r--r--nixos/modules/services/databases/postgresql.nix3
-rw-r--r--nixos/modules/services/networking/ntpd.nix38
-rw-r--r--nixos/modules/services/x11/urxvtd.nix30
-rw-r--r--nixos/modules/system/boot/systemd-nspawn.nix2
-rw-r--r--nixos/modules/virtualisation/container-config.nix8
-rw-r--r--nixos/modules/virtualisation/google-compute-config.nix262
-rw-r--r--nixos/modules/virtualisation/google-compute-image.nix360
-rw-r--r--nixos/tests/gitlab.nix4
17 files changed, 399 insertions, 361 deletions
diff --git a/nixos/doc/manual/configuration/modularity.xml b/nixos/doc/manual/configuration/modularity.xml
index 298ffd661f67..cda36eba25c1 100644
--- a/nixos/doc/manual/configuration/modularity.xml
+++ b/nixos/doc/manual/configuration/modularity.xml
@@ -127,4 +127,23 @@ nix-repl> map (x: x.hostName) config.<xref linkend="opt-services.httpd.virtualHo
 [ "example.org" "example.gov" ]
 </screen>
  </para>
+
+ <para>
+   While abstracting your configuration, you may find it useful to generate
+   modules using code, instead of writing files. The example
+   below would have the same effect as importing a file which sets those
+   options.
+   <screen>
+     { config, pkgs, ... }:
+
+     let netConfig = { hostName }: {
+       networking.hostName = hostName;
+       networking.useDHCP = false;
+    };
+
+    in
+
+    { imports = [ (netConfig "nixos.localdomain") ]; }
+  </screen>
+</para>
 </section>
diff --git a/nixos/doc/manual/development/running-nixos-tests-interactively.xml b/nixos/doc/manual/development/running-nixos-tests-interactively.xml
index b25d3dcb9116..c15ad448317f 100644
--- a/nixos/doc/manual/development/running-nixos-tests-interactively.xml
+++ b/nixos/doc/manual/development/running-nixos-tests-interactively.xml
@@ -19,7 +19,7 @@ starting VDE switch for network 1
 &gt; startAll
 &gt; testScript
 &gt; $machine->succeed("touch /tmp/foo")
-&gt; print($machine->succeed("pwd"), "\n") # Show stdout of command
+&gt; print($machine->succeed("pwd")) # Show stdout of command
 </screen>
   The function <command>testScript</command> executes the entire test script
   and drops you back into the test driver command line upon its completion.
diff --git a/nixos/doc/manual/development/writing-nixos-tests.xml b/nixos/doc/manual/development/writing-nixos-tests.xml
index 983f8f9cbe3e..4a2615c9407b 100644
--- a/nixos/doc/manual/development/writing-nixos-tests.xml
+++ b/nixos/doc/manual/development/writing-nixos-tests.xml
@@ -108,7 +108,7 @@ xlink:href="https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualis
 <programlisting>
 $machine->start;
 $machine->waitForUnit("default.target");
-die unless $machine->succeed("uname") =~ /Linux/;
+$machine->succeed("uname") =~ /Linux/ or die;
 </programlisting>
   The first line is actually unnecessary; machines are implicitly started when
   you first execute an action on them (such as <literal>waitForUnit</literal>
diff --git a/nixos/doc/manual/release-notes/rl-1903.xml b/nixos/doc/manual/release-notes/rl-1903.xml
index 49f475913d8a..cedd5fc21c6d 100644
--- a/nixos/doc/manual/release-notes/rl-1903.xml
+++ b/nixos/doc/manual/release-notes/rl-1903.xml
@@ -113,6 +113,16 @@
    </listitem>
    <listitem>
     <para>
+      The <literal>ntp</literal> module now has sane default restrictions.
+      If you're relying on the previous defaults, which permitted all queries
+      and commands from all firewall-permitted sources, you can set
+      <varname>services.ntp.restrictDefault</varname> and
+      <varname>services.ntp.restrictSource</varname> to
+      <literal>[]</literal>.
+    </para>
+   </listitem>
+   <listitem>
+    <para>
      Package <varname>rabbitmq_server</varname> is renamed to
      <varname>rabbitmq-server</varname>.
     </para>
diff --git a/nixos/lib/testing.nix b/nixos/lib/testing.nix
index 690f7dfd5fac..0bb3fd53e853 100644
--- a/nixos/lib/testing.nix
+++ b/nixos/lib/testing.nix
@@ -1,5 +1,5 @@
 { system
-, pkgs
+, pkgs ? import ../.. { inherit system config; }
   # Use a minimal kernel?
 , minimal ? false
   # Ignored
diff --git a/nixos/maintainers/scripts/gce/create-gce.sh b/nixos/maintainers/scripts/gce/create-gce.sh
index 0fd26d34d07f..48748a59d298 100755
--- a/nixos/maintainers/scripts/gce/create-gce.sh
+++ b/nixos/maintainers/scripts/gce/create-gce.sh
@@ -7,9 +7,9 @@ BUCKET_NAME="${BUCKET_NAME:-nixos-cloud-images}"
 TIMESTAMP="$(date +%Y%m%d%H%M)"
 export TIMESTAMP
 
-nix-build '<nixpkgs/nixos>' \
+nix-build '<nixpkgs/nixos/lib/eval-config.nix>' \
    -A config.system.build.googleComputeImage \
-   --arg configuration "{ imports = [ <nixpkgs/nixos/modules/virtualisation/google-compute-image.nix> ]; }" \
+   --arg modules "[ <nixpkgs/nixos/modules/virtualisation/google-compute-image.nix> ]" \
    --argstr system x86_64-linux \
    -o gce \
    -j 10
diff --git a/nixos/modules/installer/cd-dvd/sd-image.nix b/nixos/modules/installer/cd-dvd/sd-image.nix
index b6e1d11c2b54..69746a8e9799 100644
--- a/nixos/modules/installer/cd-dvd/sd-image.nix
+++ b/nixos/modules/installer/cd-dvd/sd-image.nix
@@ -134,7 +134,9 @@ in
         ${config.sdImage.populateBootCommands}
 
         # Copy the populated /boot into the SD image
-        (cd boot; mcopy -bpsvm -i ../bootpart.img ./* ::)
+        (cd boot; mcopy -psvm -i ../bootpart.img ./* ::)
+        # Verify the FAT partition before copying it.
+        fsck.vfat -vn bootpart.img
         dd conv=notrunc if=bootpart.img of=$img seek=$START count=$SECTORS
       '';
     }) {};
diff --git a/nixos/modules/programs/sway-beta.nix b/nixos/modules/programs/sway-beta.nix
index e651ea4cca33..8447f94ca254 100644
--- a/nixos/modules/programs/sway-beta.nix
+++ b/nixos/modules/programs/sway-beta.nix
@@ -8,7 +8,7 @@ let
 
   swayWrapped = pkgs.writeShellScriptBin "sway" ''
     ${cfg.extraSessionCommands}
-    exec ${pkgs.dbus.dbus-launch} --exit-with-session ${swayPackage}/bin/sway
+    exec ${pkgs.dbus.dbus-launch} --exit-with-session ${swayPackage}/bin/sway "$@"
   '';
   swayJoined = pkgs.symlinkJoin {
     name = "sway-joined";
diff --git a/nixos/modules/services/cluster/kubernetes/default.nix b/nixos/modules/services/cluster/kubernetes/default.nix
index e63d91eb9aca..6f3c45b29bf2 100644
--- a/nixos/modules/services/cluster/kubernetes/default.nix
+++ b/nixos/modules/services/cluster/kubernetes/default.nix
@@ -784,7 +784,7 @@ in {
     clusterCidr = mkOption {
       description = "Kubernetes controller manager and proxy CIDR Range for Pods in cluster.";
       default = "10.1.0.0/16";
-      type = types.str;
+      type = types.nullOr types.str;
     };
 
     flannel.enable = mkOption {
@@ -1018,9 +1018,9 @@ in {
             ${if (cfg.controllerManager.rootCaFile!=null)
               then "--root-ca-file=${cfg.controllerManager.rootCaFile}"
               else "--root-ca-file=/var/run/kubernetes/apiserver.crt"} \
-            ${optionalString (cfg.clusterCidr!=null)
-              "--cluster-cidr=${cfg.clusterCidr}"} \
-            --allocate-node-cidrs=true \
+            ${if (cfg.clusterCidr!=null)
+              then "--cluster-cidr=${cfg.clusterCidr} --allocate-node-cidrs=true"
+              else "--allocate-node-cidrs=false"} \
             ${optionalString (cfg.controllerManager.featureGates != [])
               "--feature-gates=${concatMapStringsSep "," (feature: "${feature}=true") cfg.controllerManager.featureGates}"} \
             ${optionalString cfg.verbose "--v=6"} \
diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix
index f592be0e768b..aeab445a9983 100644
--- a/nixos/modules/services/databases/postgresql.nix
+++ b/nixos/modules/services/databases/postgresql.nix
@@ -238,6 +238,9 @@ in
             User = "postgres";
             Group = "postgres";
             PermissionsStartOnly = true;
+            Type = if lib.versionAtLeast cfg.package.version "9.6"
+                   then "notify"
+                   else "simple";
 
             # Shut down Postgres using SIGINT ("Fast Shutdown mode").  See
             # http://www.postgresql.org/docs/current/static/server-shutdown.html
diff --git a/nixos/modules/services/networking/ntpd.nix b/nixos/modules/services/networking/ntpd.nix
index 32174100b0f7..588d1c6edb07 100644
--- a/nixos/modules/services/networking/ntpd.nix
+++ b/nixos/modules/services/networking/ntpd.nix
@@ -15,6 +15,10 @@ let
   configFile = pkgs.writeText "ntp.conf" ''
     driftfile ${stateDir}/ntp.drift
 
+    restrict default ${toString cfg.restrictDefault}
+    restrict -6 default ${toString cfg.restrictDefault}
+    restrict source ${toString cfg.restrictSource}
+
     restrict 127.0.0.1
     restrict -6 ::1
 
@@ -36,9 +40,38 @@ in
       enable = mkOption {
         default = false;
         description = ''
-          Whether to synchronise your machine's time using the NTP
-          protocol.
+          Whether to synchronise your machine's time using ntpd, as a peer in
+          the NTP network.
+          </para>
+          <para>
+          Disables <literal>systemd.timesyncd</literal> if enabled.
+        '';
+      };
+
+      restrictDefault = mkOption {
+        type = types.listOf types.str;
+        description = ''
+          The restriction flags to be set by default.
+          </para>
+          <para>
+          The default flags prevent external hosts from using ntpd as a DDoS
+          reflector, setting system time, and querying OS/ntpd version. As
+          recommended in section 6.5.1.1.3, answer "No" of
+          http://support.ntp.org/bin/view/Support/AccessRestrictions
+        '';
+        default = [ "limited" "kod" "nomodify" "notrap" "noquery" "nopeer" ];
+      };
+
+      restrictSource = mkOption {
+        type = types.listOf types.str;
+        description = ''
+          The restriction flags to be set on source.
+          </para>
+          <para>
+          The default flags allow peers to be added by ntpd from configured
+          pool(s), but not by other means.
         '';
+        default = [ "limited" "kod" "nomodify" "notrap" "noquery" ];
       };
 
       servers = mkOption {
@@ -51,6 +84,7 @@ in
       extraFlags = mkOption {
         type = types.listOf types.str;
         description = "Extra flags passed to the ntpd command.";
+        example = literalExample ''[ "--interface=eth0" ]'';
         default = [];
       };
 
diff --git a/nixos/modules/services/x11/urxvtd.nix b/nixos/modules/services/x11/urxvtd.nix
index f2ce089ce19a..5531d7f153c2 100644
--- a/nixos/modules/services/x11/urxvtd.nix
+++ b/nixos/modules/services/x11/urxvtd.nix
@@ -18,27 +18,17 @@ in {
   };
 
   config = mkIf cfg.enable {
-    systemd.user = {
-      sockets.urxvtd = {
-        description = "socket for urxvtd, the urxvt terminal daemon";
-        wantedBy = [ "graphical-session.target" ];
-        partOf = [ "graphical-session.target" ];
-        socketConfig = {
-          ListenStream = "%t/urxvtd-socket";
-        };
+    systemd.user.services.urxvtd = {
+      description = "urxvt terminal daemon";
+      wantedBy = [ "graphical-session.target" ];
+      partOf = [ "graphical-session.target" ];
+      path = [ pkgs.xsel ];
+      serviceConfig = {
+        ExecStart = "${pkgs.rxvt_unicode-with-plugins}/bin/urxvtd -o";
+        Environment = "RXVT_SOCKET=%t/urxvtd-socket";
+        Restart = "on-failure";
+        RestartSec = "5s";
       };
-
-      services.urxvtd = {
-        description = "urxvt terminal daemon";
-        path = [ pkgs.xsel ];
-        serviceConfig = {
-          ExecStart = "${pkgs.rxvt_unicode-with-plugins}/bin/urxvtd -o";
-          Environment = "RXVT_SOCKET=%t/urxvtd-socket";
-          Restart = "on-failure";
-          RestartSec = "5s";
-        };
-      };
-
     };
 
     environment.systemPackages = [ pkgs.rxvt_unicode-with-plugins ];
diff --git a/nixos/modules/system/boot/systemd-nspawn.nix b/nixos/modules/system/boot/systemd-nspawn.nix
index 4f538ccdbbe1..649453418b53 100644
--- a/nixos/modules/system/boot/systemd-nspawn.nix
+++ b/nixos/modules/system/boot/systemd-nspawn.nix
@@ -112,7 +112,7 @@ in {
 
       environment.etc."systemd/nspawn".source = generateUnits "nspawn" units [] [];
 
-      systemd.targets."multi-user".wants = [ "machines.target "];
+      systemd.targets."multi-user".wants = [ "machines.target" ];
   };
 
 }
diff --git a/nixos/modules/virtualisation/container-config.nix b/nixos/modules/virtualisation/container-config.nix
index 561db7cabcfb..78c59d98a5eb 100644
--- a/nixos/modules/virtualisation/container-config.nix
+++ b/nixos/modules/virtualisation/container-config.nix
@@ -22,12 +22,8 @@ with lib;
     # Not supported in systemd-nspawn containers.
     security.audit.enable = false;
 
-    # Make sure that root user in container will talk to host nix-daemon
-    environment.etc."profile".text = ''
-    export NIX_REMOTE=daemon
-    '';
-
-
+    # Use the host's nix-daemon.
+    environment.variables.NIX_REMOTE = "daemon";
 
   };
 
diff --git a/nixos/modules/virtualisation/google-compute-config.nix b/nixos/modules/virtualisation/google-compute-config.nix
index 8f20100bc1b1..1f8485b274fc 100644
--- a/nixos/modules/virtualisation/google-compute-config.nix
+++ b/nixos/modules/virtualisation/google-compute-config.nix
@@ -1,5 +1,261 @@
-{ ... }:
-
+{ config, lib, pkgs, ... }:
+with lib;
+let
+  gce = pkgs.google-compute-engine;
+  cfg = config.virtualisation.googleComputeImage;
+in
 {
-  imports = [ <nixpkgs/nixos/modules/virtualisation/google-compute-image.nix> ];
+  imports = [
+    ../profiles/headless.nix
+    ../profiles/qemu-guest.nix
+  ];
+
+
+  fileSystems."/" = {
+    device = "/dev/disk/by-label/nixos";
+    autoResize = true;
+  };
+
+  boot.growPartition = true;
+  boot.kernelParams = [ "console=ttyS0" "panic=1" "boot.panic_on_fail" ];
+  boot.initrd.kernelModules = [ "virtio_scsi" ];
+  boot.kernelModules = [ "virtio_pci" "virtio_net" ];
+
+  # Generate a GRUB menu.  Amazon's pv-grub uses this to boot our kernel/initrd.
+  boot.loader.grub.device = "/dev/sda";
+  boot.loader.timeout = 0;
+
+  # Don't put old configurations in the GRUB menu.  The user has no
+  # way to select them anyway.
+  boot.loader.grub.configurationLimit = 0;
+
+  # Allow root logins only using the SSH key that the user specified
+  # at instance creation time.
+  services.openssh.enable = true;
+  services.openssh.permitRootLogin = "prohibit-password";
+  services.openssh.passwordAuthentication = mkDefault false;
+
+  # Use GCE udev rules for dynamic disk volumes
+  services.udev.packages = [ gce ];
+
+  # Force getting the hostname from Google Compute.
+  networking.hostName = mkDefault "";
+
+  # Always include cryptsetup so that NixOps can use it.
+  environment.systemPackages = [ pkgs.cryptsetup ];
+
+  # Make sure GCE image does not replace host key that NixOps sets
+  environment.etc."default/instance_configs.cfg".text = lib.mkDefault ''
+    [InstanceSetup]
+    set_host_keys = false
+  '';
+
+  # Rely on GCP's firewall instead
+  networking.firewall.enable = mkDefault false;
+
+  # Configure default metadata hostnames
+  networking.extraHosts = ''
+    169.254.169.254 metadata.google.internal metadata
+  '';
+
+  networking.timeServers = [ "metadata.google.internal" ];
+
+  networking.usePredictableInterfaceNames = false;
+
+  # GC has 1460 MTU
+  networking.interfaces.eth0.mtu = 1460;
+
+  # allow the google-accounts-daemon to manage users
+  users.mutableUsers = true;
+  # and allow users to sudo without password
+  security.sudo.enable = true;
+  security.sudo.extraConfig = ''
+  %google-sudoers ALL=(ALL:ALL) NOPASSWD:ALL
+  '';
+
+  # NOTE: google-accounts tries to write to /etc/sudoers.d but the folder doesn't exist
+  # FIXME: not such file or directory on dynamic SSH provisioning
+  systemd.services.google-accounts-daemon = {
+    description = "Google Compute Engine Accounts Daemon";
+    # This daemon creates dynamic users
+    enable = config.users.mutableUsers;
+    after = [
+      "network.target"
+      "google-instance-setup.service"
+      "google-network-setup.service"
+    ];
+    requires = ["network.target"];
+    wantedBy = ["multi-user.target"];
+    path = with pkgs; [ shadow ];
+    serviceConfig = {
+      Type = "simple";
+      ExecStart = "${gce}/bin/google_accounts_daemon --debug";
+    };
+  };
+
+  systemd.services.google-clock-skew-daemon = {
+    description = "Google Compute Engine Clock Skew Daemon";
+    after = [
+      "network.target"
+      "google-instance-setup.service"
+      "google-network-setup.service"
+    ];
+    requires = ["network.target"];
+    wantedBy = ["multi-user.target"];
+    serviceConfig = {
+      Type = "simple";
+      ExecStart = "${gce}/bin/google_clock_skew_daemon --debug";
+    };
+  };
+
+  systemd.services.google-instance-setup = {
+    description = "Google Compute Engine Instance Setup";
+    after = ["local-fs.target" "network-online.target" "network.target" "rsyslog.service"];
+    before = ["sshd.service"];
+    wants = ["local-fs.target" "network-online.target" "network.target"];
+    wantedBy = [ "sshd.service" "multi-user.target" ];
+    path = with pkgs; [ ethtool openssh ];
+    serviceConfig = {
+      ExecStart = "${gce}/bin/google_instance_setup --debug";
+      Type = "oneshot";
+    };
+  };
+
+  systemd.services.google-network-daemon = {
+    description = "Google Compute Engine Network Daemon";
+    after = ["local-fs.target" "network-online.target" "network.target" "rsyslog.service" "google-instance-setup.service"];
+    wants = ["local-fs.target" "network-online.target" "network.target"];
+    requires = ["network.target"];
+    partOf = ["network.target"];
+    wantedBy = [ "multi-user.target" ];
+    path = with pkgs; [ iproute ];
+    serviceConfig = {
+      ExecStart = "${gce}/bin/google_network_daemon --debug";
+    };
+  };
+
+  systemd.services.google-shutdown-scripts = {
+    description = "Google Compute Engine Shutdown Scripts";
+    after = [
+      "local-fs.target"
+      "network-online.target"
+      "network.target"
+      "rsyslog.service"
+      "systemd-resolved.service"
+      "google-instance-setup.service"
+      "google-network-daemon.service"
+    ];
+    wants = [ "local-fs.target" "network-online.target" "network.target"];
+    wantedBy = [ "multi-user.target" ];
+    serviceConfig = {
+      ExecStart = "${pkgs.coreutils}/bin/true";
+      ExecStop = "${gce}/bin/google_metadata_script_runner --debug --script-type shutdown";
+      Type = "oneshot";
+      RemainAfterExit = true;
+      TimeoutStopSec = "infinity";
+    };
+  };
+
+  systemd.services.google-startup-scripts = {
+    description = "Google Compute Engine Startup Scripts";
+    after = [
+      "local-fs.target"
+      "network-online.target"
+      "network.target"
+      "rsyslog.service"
+      "google-instance-setup.service"
+      "google-network-daemon.service"
+    ];
+    wants = ["local-fs.target" "network-online.target" "network.target"];
+    wantedBy = [ "multi-user.target" ];
+    serviceConfig = {
+      ExecStart = "${gce}/bin/google_metadata_script_runner --debug --script-type startup";
+      KillMode = "process";
+      Type = "oneshot";
+    };
+  };
+
+
+  # Settings taken from https://github.com/GoogleCloudPlatform/compute-image-packages/blob/master/google_config/sysctl/11-gce-network-security.conf
+  boot.kernel.sysctl = {
+    # Turn on SYN-flood protections.  Starting with 2.6.26, there is no loss
+    # of TCP functionality/features under normal conditions.  When flood
+    # protections kick in under high unanswered-SYN load, the system
+    # should remain more stable, with a trade off of some loss of TCP
+    # functionality/features (e.g. TCP Window scaling).
+    "net.ipv4.tcp_syncookies" = mkDefault "1";
+
+    # ignores source-routed packets
+    "net.ipv4.conf.all.accept_source_route" = mkDefault "0";
+
+    # ignores source-routed packets
+    "net.ipv4.conf.default.accept_source_route" = mkDefault "0";
+
+    # ignores ICMP redirects
+    "net.ipv4.conf.all.accept_redirects" = mkDefault "0";
+
+    # ignores ICMP redirects
+    "net.ipv4.conf.default.accept_redirects" = mkDefault "0";
+
+    # ignores ICMP redirects from non-GW hosts
+    "net.ipv4.conf.all.secure_redirects" = mkDefault "1";
+
+    # ignores ICMP redirects from non-GW hosts
+    "net.ipv4.conf.default.secure_redirects" = mkDefault "1";
+
+    # don't allow traffic between networks or act as a router
+    "net.ipv4.ip_forward" = mkDefault "0";
+
+    # don't allow traffic between networks or act as a router
+    "net.ipv4.conf.all.send_redirects" = mkDefault "0";
+
+    # don't allow traffic between networks or act as a router
+    "net.ipv4.conf.default.send_redirects" = mkDefault "0";
+
+    # reverse path filtering - IP spoofing protection
+    "net.ipv4.conf.all.rp_filter" = mkDefault "1";
+
+    # reverse path filtering - IP spoofing protection
+    "net.ipv4.conf.default.rp_filter" = mkDefault "1";
+
+    # ignores ICMP broadcasts to avoid participating in Smurf attacks
+    "net.ipv4.icmp_echo_ignore_broadcasts" = mkDefault "1";
+
+    # ignores bad ICMP errors
+    "net.ipv4.icmp_ignore_bogus_error_responses" = mkDefault "1";
+
+    # logs spoofed, source-routed, and redirect packets
+    "net.ipv4.conf.all.log_martians" = mkDefault "1";
+
+    # log spoofed, source-routed, and redirect packets
+    "net.ipv4.conf.default.log_martians" = mkDefault "1";
+
+    # implements RFC 1337 fix
+    "net.ipv4.tcp_rfc1337" = mkDefault "1";
+
+    # randomizes addresses of mmap base, heap, stack and VDSO page
+    "kernel.randomize_va_space" = mkDefault "2";
+
+    # Reboot the machine soon after a kernel panic.
+    "kernel.panic" = mkDefault "10";
+
+    ## Not part of the original config
+
+    # provides protection from ToCToU races
+    "fs.protected_hardlinks" = mkDefault "1";
+
+    # provides protection from ToCToU races
+    "fs.protected_symlinks" = mkDefault "1";
+
+    # makes locating kernel addresses more difficult
+    "kernel.kptr_restrict" = mkDefault "1";
+
+    # set ptrace protections
+    "kernel.yama.ptrace_scope" = mkOverride 500 "1";
+
+    # set perf only available to root
+    "kernel.perf_event_paranoid" = mkDefault "2";
+
+  };
+
 }
diff --git a/nixos/modules/virtualisation/google-compute-image.nix b/nixos/modules/virtualisation/google-compute-image.nix
index f9ebe7696523..0d2d25d30752 100644
--- a/nixos/modules/virtualisation/google-compute-image.nix
+++ b/nixos/modules/virtualisation/google-compute-image.nix
@@ -2,334 +2,60 @@
 
 with lib;
 let
-  diskSize = 1536; # MB
-  gce = pkgs.google-compute-engine;
+  cfg = config.virtualisation.googleComputeImage;
+  defaultConfigFile = pkgs.writeText "configuration.nix" ''
+    { ... }:
+    {
+      imports = [
+        <nixpkgs/nixos/modules/virtualisation/google-compute-image.nix>
+      ];
+    }
+  '';
 in
 {
-  imports = [ ../profiles/headless.nix ../profiles/qemu-guest.nix ];
-
-  system.build.googleComputeImage = import ../../lib/make-disk-image.nix {
-    name = "google-compute-image";
-    postVM = ''
-      PATH=$PATH:${pkgs.stdenv.lib.makeBinPath [ pkgs.gnutar pkgs.gzip ]}
-      pushd $out
-      mv $diskImage disk.raw
-      tar -Szcf nixos-image-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}.raw.tar.gz disk.raw
-      rm $out/disk.raw
-      popd
-    '';
-    configFile = <nixpkgs/nixos/modules/virtualisation/google-compute-config.nix>;
-    format = "raw";
-    inherit diskSize;
-    inherit config lib pkgs;
-  };
-
-  fileSystems."/" = {
-    device = "/dev/disk/by-label/nixos";
-    autoResize = true;
-  };
-
-  boot.growPartition = true;
-  boot.kernelParams = [ "console=ttyS0" "panic=1" "boot.panic_on_fail" ];
-  boot.initrd.kernelModules = [ "virtio_scsi" ];
-  boot.kernelModules = [ "virtio_pci" "virtio_net" ];
-
-  # Generate a GRUB menu.  Amazon's pv-grub uses this to boot our kernel/initrd.
-  boot.loader.grub.device = "/dev/sda";
-  boot.loader.timeout = 0;
-
-  # Don't put old configurations in the GRUB menu.  The user has no
-  # way to select them anyway.
-  boot.loader.grub.configurationLimit = 0;
-
-  # Allow root logins only using the SSH key that the user specified
-  # at instance creation time.
-  services.openssh.enable = true;
-  services.openssh.permitRootLogin = "prohibit-password";
-  services.openssh.passwordAuthentication = mkDefault false;
-
-  # Use GCE udev rules for dynamic disk volumes
-  services.udev.packages = [ gce ];
-
-  # Force getting the hostname from Google Compute.
-  networking.hostName = mkDefault "";
-
-  # Always include cryptsetup so that NixOps can use it.
-  environment.systemPackages = [ pkgs.cryptsetup ];
-
-  # Make sure GCE image does not replace host key that NixOps sets
-  environment.etc."default/instance_configs.cfg".text = lib.mkDefault ''
-    [InstanceSetup]
-    set_host_keys = false
-  '';
-
-  # Rely on GCP's firewall instead
-  networking.firewall.enable = mkDefault false;
-
-  # Configure default metadata hostnames
-  networking.extraHosts = ''
-    169.254.169.254 metadata.google.internal metadata
-  '';
-
-  networking.timeServers = [ "metadata.google.internal" ];
-
-  networking.usePredictableInterfaceNames = false;
-
-  # GC has 1460 MTU
-  networking.interfaces.eth0.mtu = 1460;
-
-  # allow the google-accounts-daemon to manage users
-  users.mutableUsers = true;
-  # and allow users to sudo without password
-  security.sudo.enable = true;
-  security.sudo.extraConfig = ''
-  %google-sudoers ALL=(ALL:ALL) NOPASSWD:ALL
-  '';
-
-  # NOTE: google-accounts tries to write to /etc/sudoers.d but the folder doesn't exist
-  # FIXME: not such file or directory on dynamic SSH provisioning
-  systemd.services.google-accounts-daemon = {
-    description = "Google Compute Engine Accounts Daemon";
-    # This daemon creates dynamic users
-    enable = config.users.mutableUsers;
-    after = [
-      "network.target"
-      "google-instance-setup.service"
-      "google-network-setup.service"
-    ];
-    requires = ["network.target"];
-    wantedBy = ["multi-user.target"];
-    path = with pkgs; [ shadow ];
-    serviceConfig = {
-      Type = "simple";
-      ExecStart = "${gce}/bin/google_accounts_daemon --debug";
-    };
-  };
-
-  systemd.services.google-clock-skew-daemon = {
-    description = "Google Compute Engine Clock Skew Daemon";
-    after = [
-      "network.target"
-      "google-instance-setup.service"
-      "google-network-setup.service"
-    ];
-    requires = ["network.target"];
-    wantedBy = ["multi-user.target"];
-    serviceConfig = {
-      Type = "simple";
-      ExecStart = "${gce}/bin/google_clock_skew_daemon --debug";
-    };
-  };
-
-  systemd.services.google-instance-setup = {
-    description = "Google Compute Engine Instance Setup";
-    after = ["local-fs.target" "network-online.target" "network.target" "rsyslog.service"];
-    before = ["sshd.service"];
-    wants = ["local-fs.target" "network-online.target" "network.target"];
-    wantedBy = [ "sshd.service" "multi-user.target" ];
-    path = with pkgs; [ ethtool openssh ];
-    serviceConfig = {
-      ExecStart = "${gce}/bin/google_instance_setup --debug";
-      Type = "oneshot";
-    };
-  };
 
-  systemd.services.google-network-daemon = {
-    description = "Google Compute Engine Network Daemon";
-    after = ["local-fs.target" "network-online.target" "network.target" "rsyslog.service" "google-instance-setup.service"];
-    wants = ["local-fs.target" "network-online.target" "network.target"];
-    requires = ["network.target"];
-    partOf = ["network.target"];
-    wantedBy = [ "multi-user.target" ];
-    path = with pkgs; [ iproute ];
-    serviceConfig = {
-      ExecStart = "${gce}/bin/google_network_daemon --debug";
-    };
-  };
+  imports = [ ./google-compute-config.nix ];
 
-  systemd.services.google-shutdown-scripts = {
-    description = "Google Compute Engine Shutdown Scripts";
-    after = [
-      "local-fs.target"
-      "network-online.target"
-      "network.target"
-      "rsyslog.service"
-      "systemd-resolved.service"
-      "google-instance-setup.service"
-      "google-network-daemon.service"
-    ];
-    wants = [ "local-fs.target" "network-online.target" "network.target"];
-    wantedBy = [ "multi-user.target" ];
-    serviceConfig = {
-      ExecStart = "${pkgs.coreutils}/bin/true";
-      ExecStop = "${gce}/bin/google_metadata_script_runner --debug --script-type shutdown";
-      Type = "oneshot";
-      RemainAfterExit = true;
-      TimeoutStopSec = "infinity";
+  options = {
+    virtualisation.googleComputeImage.diskSize = mkOption {
+      type = with types; int;
+      default = 1536;
+      description = ''
+        Size of disk image. Unit is MB.
+      '';
     };
-  };
 
-  systemd.services.google-startup-scripts = {
-    description = "Google Compute Engine Startup Scripts";
-    after = [
-      "local-fs.target"
-      "network-online.target"
-      "network.target"
-      "rsyslog.service"
-      "google-instance-setup.service"
-      "google-network-daemon.service"
-    ];
-    wants = ["local-fs.target" "network-online.target" "network.target"];
-    wantedBy = [ "multi-user.target" ];
-    serviceConfig = {
-      ExecStart = "${gce}/bin/google_metadata_script_runner --debug --script-type startup";
-      KillMode = "process";
-      Type = "oneshot";
+    virtualisation.googleComputeImage.configFile = mkOption {
+      type = with types; nullOr str;
+      default = null;
+      description = ''
+        A path to a configuration file which will be placed at `/etc/nixos/configuration.nix`
+        and be used when switching to a new configuration.
+        If set to `null`, a default configuration is used, where the only import is
+        `<nixpkgs/nixos/modules/virtualisation/google-compute-image.nix>`.
+      '';
     };
   };
 
-  # TODO: remove this
-  systemd.services.fetch-ssh-keys =
-    { description = "Fetch host keys and authorized_keys for root user";
-
-      wantedBy = [ "sshd.service" ];
-      before = [ "sshd.service" ];
-      after = [ "network-online.target" ];
-      wants = [ "network-online.target" ];
-
-      script = let wget = "${pkgs.wget}/bin/wget --retry-connrefused -t 15 --waitretry=10 --header='Metadata-Flavor: Google'";
-                   mktemp = "mktemp --tmpdir=/run"; in
-        ''
-          # When dealing with cryptographic keys, we want to keep things private.
-          umask 077
-          # Don't download the SSH key if it has already been downloaded
-          echo "Obtaining SSH keys..."
-          mkdir -m 0700 -p /root/.ssh
-          AUTH_KEYS=$(${mktemp})
-          ${wget} -O $AUTH_KEYS http://metadata.google.internal/computeMetadata/v1/instance/attributes/sshKeys
-          if [ -s $AUTH_KEYS ]; then
-
-            # Read in key one by one, split in case Google decided
-            # to append metadata (it does sometimes) and add to
-            # authorized_keys if not already present.
-            touch /root/.ssh/authorized_keys
-            NEW_KEYS=$(${mktemp})
-            # Yes this is a nix escape of two single quotes.
-            while IFS=''' read -r line || [[ -n "$line" ]]; do
-              keyLine=$(echo -n "$line" | cut -d ':' -f2)
-              IFS=' ' read -r -a array <<< "$keyLine"
-              if [ ''${#array[@]} -ge 3 ]; then
-                echo ''${array[@]:0:3} >> $NEW_KEYS
-                echo "Added ''${array[@]:2} to authorized_keys"
-              fi
-            done < $AUTH_KEYS
-            mv $NEW_KEYS /root/.ssh/authorized_keys
-            chmod 600 /root/.ssh/authorized_keys
-            rm -f $KEY_PUB
-          else
-            echo "Downloading http://metadata.google.internal/computeMetadata/v1/project/attributes/sshKeys failed."
-            false
-          fi
-          rm -f $AUTH_KEYS
-          SSH_HOST_KEYS_DIR=$(${mktemp} -d)
-          ${wget} -O $SSH_HOST_KEYS_DIR/ssh_host_ed25519_key http://metadata.google.internal/computeMetadata/v1/instance/attributes/ssh_host_ed25519_key
-          ${wget} -O $SSH_HOST_KEYS_DIR/ssh_host_ed25519_key.pub http://metadata.google.internal/computeMetadata/v1/instance/attributes/ssh_host_ed25519_key_pub
-          if [ -s $SSH_HOST_KEYS_DIR/ssh_host_ed25519_key -a -s $SSH_HOST_KEYS_DIR/ssh_host_ed25519_key.pub ]; then
-              mv -f $SSH_HOST_KEYS_DIR/ssh_host_ed25519_key* /etc/ssh/
-              chmod 600 /etc/ssh/ssh_host_ed25519_key
-              chmod 644 /etc/ssh/ssh_host_ed25519_key.pub
-          else
-              echo "Setup of ssh host keys from http://metadata.google.internal/computeMetadata/v1/instance/attributes/ failed."
-              false
-          fi
-          rm -rf $SSH_HOST_KEYS_DIR
-        '';
-      serviceConfig.Type = "oneshot";
-      serviceConfig.RemainAfterExit = true;
-      serviceConfig.StandardError = "journal+console";
-      serviceConfig.StandardOutput = "journal+console";
+  #### implementation
+  config = {
+
+    system.build.googleComputeImage = import ../../lib/make-disk-image.nix {
+      name = "google-compute-image";
+      postVM = ''
+        PATH=$PATH:${with pkgs; stdenv.lib.makeBinPath [ gnutar gzip ]}
+        pushd $out
+        mv $diskImage disk.raw
+        tar -Szcf nixos-image-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}.raw.tar.gz disk.raw
+        rm $out/disk.raw
+        popd
+      '';
+      format = "raw";
+      configFile = if isNull cfg.configFile then defaultConfigFile else cfg.configFile;
+      inherit (cfg) diskSize;
+      inherit config lib pkgs;
     };
 
-  # Settings taken from https://github.com/GoogleCloudPlatform/compute-image-packages/blob/master/google_config/sysctl/11-gce-network-security.conf
-  boot.kernel.sysctl = {
-    # Turn on SYN-flood protections.  Starting with 2.6.26, there is no loss
-    # of TCP functionality/features under normal conditions.  When flood
-    # protections kick in under high unanswered-SYN load, the system
-    # should remain more stable, with a trade off of some loss of TCP
-    # functionality/features (e.g. TCP Window scaling).
-    "net.ipv4.tcp_syncookies" = mkDefault "1";
-
-    # ignores source-routed packets
-    "net.ipv4.conf.all.accept_source_route" = mkDefault "0";
-
-    # ignores source-routed packets
-    "net.ipv4.conf.default.accept_source_route" = mkDefault "0";
-
-    # ignores ICMP redirects
-    "net.ipv4.conf.all.accept_redirects" = mkDefault "0";
-
-    # ignores ICMP redirects
-    "net.ipv4.conf.default.accept_redirects" = mkDefault "0";
-
-    # ignores ICMP redirects from non-GW hosts
-    "net.ipv4.conf.all.secure_redirects" = mkDefault "1";
-
-    # ignores ICMP redirects from non-GW hosts
-    "net.ipv4.conf.default.secure_redirects" = mkDefault "1";
-
-    # don't allow traffic between networks or act as a router
-    "net.ipv4.ip_forward" = mkDefault "0";
-
-    # don't allow traffic between networks or act as a router
-    "net.ipv4.conf.all.send_redirects" = mkDefault "0";
-
-    # don't allow traffic between networks or act as a router
-    "net.ipv4.conf.default.send_redirects" = mkDefault "0";
-
-    # reverse path filtering - IP spoofing protection
-    "net.ipv4.conf.all.rp_filter" = mkDefault "1";
-
-    # reverse path filtering - IP spoofing protection
-    "net.ipv4.conf.default.rp_filter" = mkDefault "1";
-
-    # ignores ICMP broadcasts to avoid participating in Smurf attacks
-    "net.ipv4.icmp_echo_ignore_broadcasts" = mkDefault "1";
-
-    # ignores bad ICMP errors
-    "net.ipv4.icmp_ignore_bogus_error_responses" = mkDefault "1";
-
-    # logs spoofed, source-routed, and redirect packets
-    "net.ipv4.conf.all.log_martians" = mkDefault "1";
-
-    # log spoofed, source-routed, and redirect packets
-    "net.ipv4.conf.default.log_martians" = mkDefault "1";
-
-    # implements RFC 1337 fix
-    "net.ipv4.tcp_rfc1337" = mkDefault "1";
-
-    # randomizes addresses of mmap base, heap, stack and VDSO page
-    "kernel.randomize_va_space" = mkDefault "2";
-
-    # Reboot the machine soon after a kernel panic.
-    "kernel.panic" = mkDefault "10";
-
-    ## Not part of the original config
-
-    # provides protection from ToCToU races
-    "fs.protected_hardlinks" = mkDefault "1";
-
-    # provides protection from ToCToU races
-    "fs.protected_symlinks" = mkDefault "1";
-
-    # makes locating kernel addresses more difficult
-    "kernel.kptr_restrict" = mkDefault "1";
-
-    # set ptrace protections
-    "kernel.yama.ptrace_scope" = mkOverride 500 "1";
-
-    # set perf only available to root
-    "kernel.perf_event_paranoid" = mkDefault "2";
-
   };
 
 }
diff --git a/nixos/tests/gitlab.nix b/nixos/tests/gitlab.nix
index 661caa8aa832..269da8aa215f 100644
--- a/nixos/tests/gitlab.nix
+++ b/nixos/tests/gitlab.nix
@@ -16,6 +16,7 @@ import ./make-test.nix ({ pkgs, lib, ...} : with lib; {
 
       services.nginx = {
         enable = true;
+        recommendedProxySettings = true;
         virtualHosts = {
           "localhost" = {
             locations."/".proxyPass = "http://unix:/run/gitlab/gitlab-workhorse.socket";
@@ -75,7 +76,8 @@ import ./make-test.nix ({ pkgs, lib, ...} : with lib; {
     $gitlab->waitForUnit("gitlab.service");
     $gitlab->waitForUnit("gitlab-sidekiq.service");
     $gitlab->waitForFile("/var/gitlab/state/tmp/sockets/gitlab.socket");
-    $gitlab->waitUntilSucceeds("curl -sSf http://localhost/users/sign_in");
+    $gitlab->waitUntilSucceeds("curl -sSf http://gitlab/users/sign_in");
+    $gitlab->succeed("curl -isSf http://gitlab  | grep -i location | grep -q http://gitlab/users/sign_in");
     $gitlab->succeed("${pkgs.sudo}/bin/sudo -u gitlab -H gitlab-rake gitlab:check 1>&2")
   '';
 })