summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/modules/services/cluster/kubernetes/addon-manager.nix83
-rw-r--r--nixos/modules/services/cluster/kubernetes/addons/dashboard.nix36
-rw-r--r--nixos/modules/services/cluster/kubernetes/apiserver.nix69
-rw-r--r--nixos/modules/services/cluster/kubernetes/controller-manager.nix39
-rw-r--r--nixos/modules/services/cluster/kubernetes/default.nix26
-rw-r--r--nixos/modules/services/cluster/kubernetes/flannel.nix68
-rw-r--r--nixos/modules/services/cluster/kubernetes/kubelet.nix86
-rw-r--r--nixos/modules/services/cluster/kubernetes/pki.nix165
-rw-r--r--nixos/modules/services/cluster/kubernetes/proxy.nix37
-rw-r--r--nixos/modules/services/cluster/kubernetes/scheduler.nix34
-rw-r--r--nixos/tests/kubernetes/base.nix5
-rw-r--r--nixos/tests/kubernetes/dns.nix3
-rw-r--r--nixos/tests/kubernetes/rbac.nix4
-rw-r--r--pkgs/applications/editors/vscode/default.nix6
-rw-r--r--pkgs/applications/misc/bleachbit/default.nix28
-rw-r--r--pkgs/applications/misc/stretchly/default.nix139
-rw-r--r--pkgs/applications/networking/browsers/tor-browser-bundle-bin/default.nix10
-rw-r--r--pkgs/applications/version-management/git-and-tools/pre-commit/default.nix4
-rw-r--r--pkgs/development/libraries/libimobiledevice/default.nix8
-rw-r--r--pkgs/development/libraries/libplist/default.nix8
-rw-r--r--pkgs/development/libraries/libusbmuxd/default.nix8
-rw-r--r--pkgs/development/libraries/qtstyleplugin-kvantum-qt4/default.nix8
-rw-r--r--pkgs/development/libraries/qtstyleplugin-kvantum/default.nix4
-rw-r--r--pkgs/development/python-modules/wsproto/default.nix11
-rw-r--r--pkgs/development/python-modules/xdot/default.nix4
-rw-r--r--pkgs/development/ruby-modules/bundix/default.nix4
-rw-r--r--pkgs/development/tools/continuous-integration/gitlab-runner/default.nix8
-rw-r--r--pkgs/development/tools/go-langserver/default.nix9
-rw-r--r--pkgs/tools/filesystems/ifuse/default.nix8
-rw-r--r--pkgs/tools/misc/ideviceinstaller/default.nix10
-rw-r--r--pkgs/tools/misc/usbmuxd/default.nix8
-rw-r--r--pkgs/top-level/all-packages.nix8
32 files changed, 748 insertions, 200 deletions
diff --git a/nixos/modules/services/cluster/kubernetes/addon-manager.nix b/nixos/modules/services/cluster/kubernetes/addon-manager.nix
index 17f2dde31a7..b9a56811d2b 100644
--- a/nixos/modules/services/cluster/kubernetes/addon-manager.nix
+++ b/nixos/modules/services/cluster/kubernetes/addon-manager.nix
@@ -63,18 +63,49 @@ in
     };
 
     enable = mkEnableOption "Whether to enable Kubernetes addon manager.";
+
+    kubeconfig = top.lib.mkKubeConfigOptions "Kubernetes addon manager";
+    bootstrapAddonsKubeconfig = top.lib.mkKubeConfigOptions "Kubernetes addon manager bootstrap";
   };
 
   ###### implementation
-  config = mkIf cfg.enable {
+  config = let
+
+    addonManagerPaths = filter (a: a != null) [
+      cfg.kubeconfig.caFile
+      cfg.kubeconfig.certFile
+      cfg.kubeconfig.keyFile
+    ];
+    bootstrapAddonsPaths = filter (a: a != null) [
+      cfg.bootstrapAddonsKubeconfig.caFile
+      cfg.bootstrapAddonsKubeconfig.certFile
+      cfg.bootstrapAddonsKubeconfig.keyFile
+    ];
+
+  in mkIf cfg.enable {
     environment.etc."kubernetes/addons".source = "${addons}/";
 
+    #TODO: Get rid of kube-addon-manager in the future for the following reasons
+    # - it is basically just a shell script wrapped around kubectl
+    # - it assumes that it is clusterAdmin or can gain clusterAdmin rights through serviceAccount
+    # - it is designed to be used with k8s system components only
+    # - it would be better with a more Nix-oriented way of managing addons
     systemd.services.kube-addon-manager = {
       description = "Kubernetes addon manager";
       wantedBy = [ "kubernetes.target" ];
-      after = [ "kube-apiserver.service" ];
-      environment.ADDON_PATH = "/etc/kubernetes/addons/";
-      path = [ pkgs.gawk ];
+      after = [ "kube-node-online.target" ];
+      before = [ "kubernetes.target" ];
+      environment = {
+        ADDON_PATH = "/etc/kubernetes/addons/";
+        KUBECONFIG = top.lib.mkKubeConfig "kube-addon-manager" cfg.kubeconfig;
+      };
+      path = with pkgs; [ gawk kubectl ];
+      preStart = ''
+        until kubectl -n kube-system get serviceaccounts/default 2>/dev/null; do
+          echo kubectl -n kube-system get serviceaccounts/default: exit status $?
+          sleep 2
+        done
+      '';
       serviceConfig = {
         Slice = "kubernetes.slice";
         ExecStart = "${top.package}/bin/kube-addons";
@@ -84,8 +115,52 @@ in
         Restart = "on-failure";
         RestartSec = 10;
       };
+      unitConfig.ConditionPathExists = addonManagerPaths;
     };
 
+    systemd.paths.kube-addon-manager = {
+      wantedBy = [ "kube-addon-manager.service" ];
+      pathConfig = {
+        PathExists = addonManagerPaths;
+        PathChanged = addonManagerPaths;
+      };
+    };
+
+    services.kubernetes.addonManager.kubeconfig.server = mkDefault top.apiserverAddress;
+
+    systemd.services.kube-addon-manager-bootstrap = mkIf (top.apiserver.enable && top.addonManager.bootstrapAddons != {}) {
+      wantedBy = [ "kube-control-plane-online.target" ];
+      after = [ "kube-apiserver.service" ];
+      before = [ "kube-control-plane-online.target" ];
+      path = [ pkgs.kubectl ];
+      environment = {
+        KUBECONFIG = top.lib.mkKubeConfig "kube-addon-manager-bootstrap" cfg.bootstrapAddonsKubeconfig;
+      };
+      preStart = with pkgs; let
+        files = mapAttrsToList (n: v: writeText "${n}.json" (builtins.toJSON v))
+          cfg.bootstrapAddons;
+      in ''
+        until kubectl auth can-i '*' '*' -q 2>/dev/null; do
+          echo kubectl auth can-i '*' '*': exit status $?
+          sleep 2
+        done
+
+        kubectl apply -f ${concatStringsSep " \\\n -f " files}
+      '';
+      script = "echo Ok";
+      unitConfig.ConditionPathExists = bootstrapAddonsPaths;
+    };
+
+    systemd.paths.kube-addon-manager-bootstrap = {
+      wantedBy = [ "kube-addon-manager-bootstrap.service" ];
+      pathConfig = {
+        PathExists = bootstrapAddonsPaths;
+        PathChanged = bootstrapAddonsPaths;
+      };
+    };
+
+    services.kubernetes.addonManager.bootstrapAddonsKubeconfig.server = mkDefault top.apiserverAddress;
+
     services.kubernetes.addonManager.bootstrapAddons = mkIf isRBACEnabled
     (let
       name = system:kube-addon-manager;
diff --git a/nixos/modules/services/cluster/kubernetes/addons/dashboard.nix b/nixos/modules/services/cluster/kubernetes/addons/dashboard.nix
index 454e7d35bc0..2295694ffc7 100644
--- a/nixos/modules/services/cluster/kubernetes/addons/dashboard.nix
+++ b/nixos/modules/services/cluster/kubernetes/addons/dashboard.nix
@@ -169,6 +169,23 @@ in {
         };
       };
 
+      kubernetes-dashboard-cm = {
+        apiVersion = "v1";
+        kind = "ConfigMap";
+        metadata = {
+          labels = {
+            k8s-app = "kubernetes-dashboard";
+            # Allows editing resource and makes sure it is created first.
+            "addonmanager.kubernetes.io/mode" = "EnsureExists";
+          };
+          name = "kubernetes-dashboard-settings";
+          namespace = "kube-system";
+        };
+      };
+    };
+
+    services.kubernetes.addonManager.bootstrapAddons = mkMerge [{
+
       kubernetes-dashboard-sa = {
         apiVersion = "v1";
         kind = "ServiceAccount";
@@ -210,20 +227,9 @@ in {
         };
         type = "Opaque";
       };
-      kubernetes-dashboard-cm = {
-        apiVersion = "v1";
-        kind = "ConfigMap";
-        metadata = {
-          labels = {
-            k8s-app = "kubernetes-dashboard";
-            # Allows editing resource and makes sure it is created first.
-            "addonmanager.kubernetes.io/mode" = "EnsureExists";
-          };
-          name = "kubernetes-dashboard-settings";
-          namespace = "kube-system";
-        };
-      };
-    } // (optionalAttrs cfg.rbac.enable
+    }
+
+    (optionalAttrs cfg.rbac.enable
       (let
         subjects = [{
           kind = "ServiceAccount";
@@ -323,6 +329,6 @@ in {
             inherit subjects;
           };
         })
-    ));
+    ))];
   };
 }
diff --git a/nixos/modules/services/cluster/kubernetes/apiserver.nix b/nixos/modules/services/cluster/kubernetes/apiserver.nix
index 455d0239604..0c04648355b 100644
--- a/nixos/modules/services/cluster/kubernetes/apiserver.nix
+++ b/nixos/modules/services/cluster/kubernetes/apiserver.nix
@@ -184,6 +184,18 @@ in
       type = bool;
     };
 
+    proxyClientCertFile = mkOption {
+      description = "Client certificate to use for connections to proxy.";
+      default = null;
+      type = nullOr path;
+    };
+
+    proxyClientKeyFile = mkOption {
+      description = "Key to use for connections to proxy.";
+      default = null;
+      type = nullOr path;
+    };
+
     runtimeConfig = mkOption {
       description = ''
         Api runtime configuration. See
@@ -272,11 +284,32 @@ in
   ###### implementation
   config = mkMerge [
 
-    (mkIf cfg.enable {
+    (let
+
+      apiserverPaths = filter (a: a != null) [
+        cfg.clientCaFile
+        cfg.etcd.caFile
+        cfg.etcd.certFile
+        cfg.etcd.keyFile
+        cfg.kubeletClientCaFile
+        cfg.kubeletClientCertFile
+        cfg.kubeletClientKeyFile
+        cfg.serviceAccountKeyFile
+        cfg.tlsCertFile
+        cfg.tlsKeyFile
+      ];
+      etcdPaths = filter (a: a != null) [
+        config.services.etcd.trustedCaFile
+        config.services.etcd.certFile
+        config.services.etcd.keyFile
+      ];
+
+    in mkIf cfg.enable {
         systemd.services.kube-apiserver = {
           description = "Kubernetes APIServer Service";
-          wantedBy = [ "kubernetes.target" ];
-          after = [ "network.target" ];
+          wantedBy = [ "kube-control-plane-online.target" ];
+          after = [ "certmgr.service" ];
+          before = [ "kube-control-plane-online.target" ];
           serviceConfig = {
             Slice = "kubernetes.slice";
             ExecStart = ''${top.package}/bin/kube-apiserver \
@@ -316,6 +349,10 @@ in
                 "--kubelet-client-certificate=${cfg.kubeletClientCertFile}"} \
               ${optionalString (cfg.kubeletClientKeyFile != null)
                 "--kubelet-client-key=${cfg.kubeletClientKeyFile}"} \
+              ${optionalString (cfg.proxyClientCertFile != null)
+                "--proxy-client-cert-file=${cfg.proxyClientCertFile}"} \
+              ${optionalString (cfg.proxyClientKeyFile != null)
+                "--proxy-client-key-file=${cfg.proxyClientKeyFile}"} \
               --insecure-bind-address=${cfg.insecureBindAddress} \
               --insecure-port=${toString cfg.insecurePort} \
               ${optionalString (cfg.runtimeConfig != "")
@@ -341,6 +378,15 @@ in
             Restart = "on-failure";
             RestartSec = 5;
           };
+          unitConfig.ConditionPathExists = apiserverPaths;
+        };
+
+        systemd.paths.kube-apiserver = mkIf top.apiserver.enable {
+          wantedBy = [ "kube-apiserver.service" ];
+          pathConfig = {
+            PathExists = apiserverPaths;
+            PathChanged = apiserverPaths;
+          };
         };
 
         services.etcd = {
@@ -354,6 +400,18 @@ in
           initialAdvertisePeerUrls = mkDefault ["https://${top.masterAddress}:2380"];
         };
 
+        systemd.services.etcd = {
+          unitConfig.ConditionPathExists = etcdPaths;
+        };
+
+        systemd.paths.etcd = {
+          wantedBy = [ "etcd.service" ];
+          pathConfig = {
+            PathExists = etcdPaths;
+            PathChanged = etcdPaths;
+          };
+        };
+
         services.kubernetes.addonManager.bootstrapAddons = mkIf isRBACEnabled {
 
           apiserver-kubelet-api-admin-crb = {
@@ -389,6 +447,11 @@ in
                   ] ++ cfg.extraSANs;
           action = "systemctl restart kube-apiserver.service";
         };
+        apiserverProxyClient = mkCert {
+          name = "kube-apiserver-proxy-client";
+          CN = "front-proxy-client";
+          action = "systemctl restart kube-apiserver.service";
+        };
         apiserverKubeletClient = mkCert {
           name = "kube-apiserver-kubelet-client";
           CN = "system:kube-apiserver";
diff --git a/nixos/modules/services/cluster/kubernetes/controller-manager.nix b/nixos/modules/services/cluster/kubernetes/controller-manager.nix
index 060fd9b78db..ba56f3fa827 100644
--- a/nixos/modules/services/cluster/kubernetes/controller-manager.nix
+++ b/nixos/modules/services/cluster/kubernetes/controller-manager.nix
@@ -104,11 +104,31 @@ in
   };
 
   ###### implementation
-  config = mkIf cfg.enable {
-    systemd.services.kube-controller-manager = {
+  config = let
+
+    controllerManagerPaths = filter (a: a != null) [
+      cfg.kubeconfig.caFile
+      cfg.kubeconfig.certFile
+      cfg.kubeconfig.keyFile
+      cfg.rootCaFile
+      cfg.serviceAccountKeyFile
+      cfg.tlsCertFile
+      cfg.tlsKeyFile
+    ];
+
+  in mkIf cfg.enable {
+    systemd.services.kube-controller-manager = rec {
       description = "Kubernetes Controller Manager Service";
-      wantedBy = [ "kubernetes.target" ];
+      wantedBy = [ "kube-control-plane-online.target" ];
       after = [ "kube-apiserver.service" ];
+      before = [ "kube-control-plane-online.target" ];
+      environment.KUBECONFIG = top.lib.mkKubeConfig "kube-controller-manager" cfg.kubeconfig;
+      preStart = ''
+        until kubectl auth can-i get /api -q 2>/dev/null; do
+          echo kubectl auth can-i get /api: exit status $?
+          sleep 2
+        done
+      '';
       serviceConfig = {
         RestartSec = "30s";
         Restart = "on-failure";
@@ -120,7 +140,7 @@ in
             "--cluster-cidr=${cfg.clusterCidr}"} \
           ${optionalString (cfg.featureGates != [])
             "--feature-gates=${concatMapStringsSep "," (feature: "${feature}=true") cfg.featureGates}"} \
-          --kubeconfig=${top.lib.mkKubeConfig "kube-controller-manager" cfg.kubeconfig} \
+          --kubeconfig=${environment.KUBECONFIG} \
           --leader-elect=${boolToString cfg.leaderElect} \
           ${optionalString (cfg.rootCaFile!=null)
             "--root-ca-file=${cfg.rootCaFile}"} \
@@ -141,7 +161,16 @@ in
         User = "kubernetes";
         Group = "kubernetes";
       };
-      path = top.path;
+      path = top.path ++ [ pkgs.kubectl ];
+      unitConfig.ConditionPathExists = controllerManagerPaths;
+    };
+
+    systemd.paths.kube-controller-manager = {
+      wantedBy = [ "kube-controller-manager.service" ];
+      pathConfig = {
+        PathExists = controllerManagerPaths;
+        PathChanged = controllerManagerPaths;
+      };
     };
 
     services.kubernetes.pki.certs = with top.lib; {
diff --git a/nixos/modules/services/cluster/kubernetes/default.nix b/nixos/modules/services/cluster/kubernetes/default.nix
index 3e53d18f8bb..192c893f8a1 100644
--- a/nixos/modules/services/cluster/kubernetes/default.nix
+++ b/nixos/modules/services/cluster/kubernetes/default.nix
@@ -263,6 +263,30 @@ in {
         wantedBy = [ "multi-user.target" ];
       };
 
+      systemd.targets.kube-control-plane-online = {
+        wantedBy = [ "kubernetes.target" ];
+        before = [ "kubernetes.target" ];
+      };
+
+      systemd.services.kube-control-plane-online = rec {
+        description = "Kubernetes control plane is online";
+        wantedBy = [ "kube-control-plane-online.target" ];
+        after = [ "kube-scheduler.service" "kube-controller-manager.service" ];
+        before = [ "kube-control-plane-online.target" ];
+        environment.KUBECONFIG = cfg.lib.mkKubeConfig "default" cfg.kubeconfig;
+        path = [ pkgs.kubectl ];
+        preStart = ''
+          until kubectl get --raw=/healthz 2>/dev/null; do
+            echo kubectl get --raw=/healthz: exit status $?
+            sleep 3
+          done
+        '';
+        script = "echo Ok";
+        serviceConfig = {
+          TimeoutSec = "500";
+        };
+      };
+
       systemd.tmpfiles.rules = [
         "d /opt/cni/bin 0755 root root -"
         "d /run/kubernetes 0755 kubernetes kubernetes -"
@@ -286,6 +310,8 @@ in {
       services.kubernetes.apiserverAddress = mkDefault ("https://${if cfg.apiserver.advertiseAddress != null
                           then cfg.apiserver.advertiseAddress
                           else "${cfg.masterAddress}:${toString cfg.apiserver.securePort}"}");
+
+      services.kubernetes.kubeconfig.server = mkDefault cfg.apiserverAddress;
     })
   ];
 }
diff --git a/nixos/modules/services/cluster/kubernetes/flannel.nix b/nixos/modules/services/cluster/kubernetes/flannel.nix
index 93ee2fd65ee..e79fbcb6200 100644
--- a/nixos/modules/services/cluster/kubernetes/flannel.nix
+++ b/nixos/modules/services/cluster/kubernetes/flannel.nix
@@ -24,16 +24,26 @@ in
   ###### interface
   options.services.kubernetes.flannel = {
     enable = mkEnableOption "enable flannel networking";
+    kubeconfig = top.lib.mkKubeConfigOptions "Kubernetes flannel";
   };
 
   ###### implementation
-  config = mkIf cfg.enable {
+  config = let
+
+    flannelPaths = filter (a: a != null) [
+      cfg.kubeconfig.caFile
+      cfg.kubeconfig.certFile
+      cfg.kubeconfig.keyFile
+    ];
+    kubeconfig = top.lib.mkKubeConfig "flannel" cfg.kubeconfig;
+
+  in mkIf cfg.enable {
     services.flannel = {
 
       enable = mkDefault true;
       network = mkDefault top.clusterCidr;
-      inherit storageBackend;
-      nodeName = config.services.kubernetes.kubelet.hostname;
+      inherit storageBackend kubeconfig;
+      nodeName = top.kubelet.hostname;
     };
 
     services.kubernetes.kubelet = {
@@ -48,24 +58,66 @@ in
       }];
     };
 
-    systemd.services."mk-docker-opts" = {
+    systemd.services.mk-docker-opts = {
       description = "Pre-Docker Actions";
+      wantedBy = [ "flannel.target" ];
+      before = [ "flannel.target" ];
       path = with pkgs; [ gawk gnugrep ];
       script = ''
         ${mkDockerOpts}/mk-docker-opts -d /run/flannel/docker
         systemctl restart docker
       '';
+      unitConfig.ConditionPathExists = [ "/run/flannel/subnet.env" ];
       serviceConfig.Type = "oneshot";
     };
 
-    systemd.paths."flannel-subnet-env" = {
-      wantedBy = [ "flannel.service" ];
+    systemd.paths.flannel-subnet-env = {
+      wantedBy = [ "mk-docker-opts.service" ];
       pathConfig = {
-        PathModified = "/run/flannel/subnet.env";
+        PathExists = [ "/run/flannel/subnet.env" ];
+        PathChanged = [ "/run/flannel/subnet.env" ];
         Unit = "mk-docker-opts.service";
       };
     };
 
+    systemd.targets.flannel = {
+      wantedBy = [ "kube-node-online.target" ];
+      before = [ "kube-node-online.target" ];
+    };
+
+    systemd.services.flannel = {
+      wantedBy = [ "flannel.target" ];
+      after = [ "kubelet.target" ];
+      before = [ "flannel.target" ];
+      path = with pkgs; [ iptables kubectl ];
+      environment.KUBECONFIG = kubeconfig;
+      preStart = let
+        args = [
+          "--selector=kubernetes.io/hostname=${top.kubelet.hostname}"
+          # flannel exits if node is not registered yet, before that there is no podCIDR
+          "--output=jsonpath={.items[0].spec.podCIDR}"
+          # if jsonpath cannot be resolved exit with status 1
+          "--allow-missing-template-keys=false"
+        ];
+      in ''
+        until kubectl get nodes ${concatStringsSep " " args} 2>/dev/null; do
+          echo Waiting for ${top.kubelet.hostname} to be RegisteredNode
+          sleep 1
+        done
+      '';
+      unitConfig.ConditionPathExists = flannelPaths;
+    };
+
+    systemd.paths.flannel = {
+      wantedBy = [ "flannel.service" ];
+      pathConfig = {
+        PathExists = flannelPaths;
+        PathChanged = flannelPaths;
+      };
+    };
+
+    services.kubernetes.flannel.kubeconfig.server = mkDefault top.apiserverAddress;
+
     systemd.services.docker = {
       environment.DOCKER_OPTS = "-b none";
       serviceConfig.EnvironmentFile = "-/run/flannel/docker";
@@ -92,7 +144,6 @@ in
 
     # give flannel som kubernetes rbac permissions if applicable
     services.kubernetes.addonManager.bootstrapAddons = mkIf ((storageBackend == "kubernetes") && (elem "RBAC" top.apiserver.authorizationMode)) {
-
       flannel-cr = {
         apiVersion = "rbac.authorization.k8s.io/v1beta1";
         kind = "ClusterRole";
@@ -128,7 +179,6 @@ in
           name = "flannel-client";
         }];
       };
-
     };
   };
 }
diff --git a/nixos/modules/services/cluster/kubernetes/kubelet.nix b/nixos/modules/services/cluster/kubernetes/kubelet.nix
index c94bb28bf7f..2a4a0624555 100644
--- a/nixos/modules/services/cluster/kubernetes/kubelet.nix
+++ b/nixos/modules/services/cluster/kubernetes/kubelet.nix
@@ -241,21 +241,28 @@ in
 
   ###### implementation
   config = mkMerge [
-    (mkIf cfg.enable {
+    (let
+
+      kubeletPaths = filter (a: a != null) [
+        cfg.kubeconfig.caFile
+        cfg.kubeconfig.certFile
+        cfg.kubeconfig.keyFile
+        cfg.clientCaFile
+        cfg.tlsCertFile
+        cfg.tlsKeyFile
+      ];
+
+    in mkIf cfg.enable {
       services.kubernetes.kubelet.seedDockerImages = [infraContainer];
 
       systemd.services.kubelet = {
         description = "Kubernetes Kubelet Service";
-        wantedBy = [ "kubernetes.target" ];
-        after = [ "network.target" "docker.service" "kube-apiserver.service" ];
+        wantedBy = [ "kubelet.target" ];
+        after = [ "kube-control-plane-online.target" ];
+        before = [ "kubelet.target" ];
         path = with pkgs; [ gitMinimal openssh docker utillinux iproute ethtool thin-provisioning-tools iptables socat ] ++ top.path;
         preStart = ''
-          ${concatMapStrings (img: ''
-            echo "Seeding docker image: ${img}"
-            docker load <${img}
-          '') cfg.seedDockerImages}
-
-          rm /opt/cni/bin/* || true
+          rm -f /opt/cni/bin/* || true
           ${concatMapStrings (package: ''
             echo "Linking cni package: ${package}"
             ln -fs ${package}/bin/* /opt/cni/bin
@@ -308,6 +315,56 @@ in
           '';
           WorkingDirectory = top.dataDir;
         };
+        unitConfig.ConditionPathExists = kubeletPaths;
+      };
+
+      systemd.paths.kubelet = {
+        wantedBy =  [ "kubelet.service" ];
+        pathConfig = {
+          PathExists = kubeletPaths;
+          PathChanged = kubeletPaths;
+        };
+      };
+
+      systemd.services.docker.before = [ "kubelet.service" ];
+
+      systemd.services.docker-seed-images = {
+        wantedBy = [ "docker.service" ];
+        after = [ "docker.service" ];
+        before = [ "kubelet.service" ];
+        path = with pkgs; [ docker ];
+        preStart = ''
+          ${concatMapStrings (img: ''
+            echo "Seeding docker image: ${img}"
+            docker load <${img}
+          '') cfg.seedDockerImages}
+        '';
+        script = "echo Ok";
+        serviceConfig.Type = "oneshot";
+        serviceConfig.RemainAfterExit = true;
+        serviceConfig.Slice = "kubernetes.slice";
+      };
+
+      systemd.services.kubelet-online = {
+        wantedBy = [ "kube-node-online.target" ];
+        after = [ "flannel.target" "kubelet.target" ];
+        before = [ "kube-node-online.target" ];
+        # it is complicated. flannel needs kubelet to run the pause container before
+        # it discusses the node CIDR with apiserver and afterwards configures and restarts
+        # dockerd. Until then prevent creating any pods because they have to be recreated anyway
+        # because the network of docker0 has been changed by flannel.
+        script = let
+          docker-env = "/run/flannel/docker";
+          flannel-date = "stat --print=%Y ${docker-env}";
+          docker-date = "systemctl show --property=ActiveEnterTimestamp --value docker";
+        in ''
+          until test -f ${docker-env} ; do sleep 1 ; done
+          while test `${flannel-date}` -gt `date +%s --date="$(${docker-date})"` ; do
+            sleep 1
+          done
+        '';
+        serviceConfig.Type = "oneshot";
+        serviceConfig.Slice = "kubernetes.slice";
       };
 
       # Allways include cni plugins
@@ -354,5 +411,16 @@ in
       };
     })
 
+    {
+      systemd.targets.kubelet = {
+        wantedBy = [ "kube-node-online.target" ];
+        before = [ "kube-node-online.target" ];
+      };
+
+      systemd.targets.kube-node-online = {
+        wantedBy = [ "kubernetes.target" ];
+        before = [ "kubernetes.target" ];
+      };
+    }
   ];
 }
diff --git a/nixos/modules/services/cluster/kubernetes/pki.nix b/nixos/modules/services/cluster/kubernetes/pki.nix
index 38deca23a99..75a29473cea 100644
--- a/nixos/modules/services/cluster/kubernetes/pki.nix
+++ b/nixos/modules/services/cluster/kubernetes/pki.nix
@@ -27,12 +27,11 @@ let
   certmgrAPITokenPath = "${top.secretsPath}/${cfsslAPITokenBaseName}";
   cfsslAPITokenLength = 32;
 
-  clusterAdminKubeconfig = with cfg.certs.clusterAdmin;
-    top.lib.mkKubeConfig "cluster-admin" {
-        server = top.apiserverAddress;
-        certFile = cert;
-        keyFile = key;
-    };
+  clusterAdminKubeconfig = with cfg.certs.clusterAdmin; {
+    server = top.apiserverAddress;
+    certFile = cert;
+    keyFile = key;
+  };
 
   remote = with config.services; "https://${kubernetes.masterAddress}:${toString cfssl.port}";
 in
@@ -119,6 +118,12 @@ in
     cfsslCertPathPrefix = "${config.services.cfssl.dataDir}/cfssl";
     cfsslCert = "${cfsslCertPathPrefix}.pem";
     cfsslKey = "${cfsslCertPathPrefix}-key.pem";
+    cfsslPort = toString config.services.cfssl.port;
+
+    certmgrPaths = [
+      top.caFile
+      certmgrAPITokenPath
+    ];
   in
   {
 
@@ -168,13 +173,40 @@ in
         chown cfssl "${cfsslAPITokenPath}" && chmod 400 "${cfsslAPITokenPath}"
       '')]);
 
+    systemd.targets.cfssl-online = {
+      wantedBy = [ "network-online.target" ];
+      after = [ "cfssl.service" "network-online.target" "cfssl-online.service" ];
+    };
+
+    systemd.services.cfssl-online = {
+      description = "Wait for ${remote} to be reachable.";
+      wantedBy = [ "cfssl-online.target" ];
+      before = [ "cfssl-online.target" ];
+      path = [ pkgs.curl ];
+      preStart = ''
+        until curl --fail-early -fskd '{}' ${remote}/api/v1/cfssl/info -o /dev/null; do
+          echo curl ${remote}/api/v1/cfssl/info: exit status $?
+          sleep 2
+        done
+      '';
+      script = "echo Ok";
+      serviceConfig = {
+        TimeoutSec = "300";
+      };
+    };
+
     systemd.services.kube-certmgr-bootstrap = {
       description = "Kubernetes certmgr bootstrapper";
-      wantedBy = [ "certmgr.service" ];
-      after = [ "cfssl.target" ];
+      wantedBy = [ "cfssl-online.target" ];
+      after = [ "cfssl-online.target" ];
+      before = [ "certmgr.service" ];
+      path = with pkgs; [ curl cfssl ];
       script = concatStringsSep "\n" [''
         set -e
 
+        mkdir -p $(dirname ${certmgrAPITokenPath})
+        mkdir -p $(dirname ${top.caFile})
+
         # If there's a cfssl (cert issuer) running locally, then don't rely on user to
         # manually paste it in place. Just symlink.
         # otherwise, create the target file, ready for users to insert the token
@@ -186,15 +218,18 @@ in
         fi
       ''
       (optionalString (cfg.pkiTrustOnBootstrap) ''
-        if [ ! -f "${top.caFile}" ] || [ $(cat "${top.caFile}" | wc -c) -lt 1 ]; then
-          ${pkgs.curl}/bin/curl --fail-early -f -kd '{}' ${remote}/api/v1/cfssl/info | \
-            ${pkgs.cfssl}/bin/cfssljson -stdout >${top.caFile}
+        if [ ! -s "${top.caFile}" ]; then
+          until test -s ${top.caFile}.json; do
+            sleep 2
+            curl --fail-early -fskd '{}' ${remote}/api/v1/cfssl/info -o ${top.caFile}.json
+          done
+          cfssljson -f ${top.caFile}.json -stdout >${top.caFile}
+          rm ${top.caFile}.json
         fi
       '')
       ];
       serviceConfig = {
-        RestartSec = "10s";
-        Restart = "on-failure";
+        TimeoutSec = "500";
       };
     };
 
@@ -230,35 +265,28 @@ in
           mapAttrs mkSpec cfg.certs;
       };
 
-      #TODO: Get rid of kube-addon-manager in the future for the following reasons
-      # - it is basically just a shell script wrapped around kubectl
-      # - it assumes that it is clusterAdmin or can gain clusterAdmin rights through serviceAccount
-      # - it is designed to be used with k8s system components only
-      # - it would be better with a more Nix-oriented way of managing addons
-      systemd.services.kube-addon-manager = mkIf top.addonManager.enable (mkMerge [{
-        environment.KUBECONFIG = with cfg.certs.addonManager;
-          top.lib.mkKubeConfig "addon-manager" {
-            server = top.apiserverAddress;
-            certFile = cert;
-            keyFile = key;
-          };
-        }
-
-        (optionalAttrs (top.addonManager.bootstrapAddons != {}) {
-          serviceConfig.PermissionsStartOnly = true;
-          preStart = with pkgs;
-          let
-            files = mapAttrsToList (n: v: writeText "${n}.json" (builtins.toJSON v))
-              top.addonManager.bootstrapAddons;
-          in
-          ''
-            export KUBECONFIG=${clusterAdminKubeconfig}
-            ${kubectl}/bin/kubectl apply -f ${concatStringsSep " \\\n -f " files}
-          '';
-        })]);
+      systemd.services.certmgr = {
+        wantedBy = [ "cfssl-online.target" ];
+        after = [ "cfssl-online.target" "kube-certmgr-bootstrap.service" ];
+        preStart = ''
+          while ! test -s ${certmgrAPITokenPath} ; do
+            sleep 1
+            echo Waiting for ${certmgrAPITokenPath}
+          done
+        '';
+        unitConfig.ConditionPathExists = certmgrPaths;
+      };
+
+      systemd.paths.certmgr = {
+        wantedBy = [ "certmgr.service" ];
+        pathConfig = {
+          PathExists = certmgrPaths;
+          PathChanged = certmgrPaths;
+        };
+      };
 
       environment.etc.${cfg.etcClusterAdminKubeconfig}.source = mkIf (!isNull cfg.etcClusterAdminKubeconfig)
-        clusterAdminKubeconfig;
+        (top.lib.mkKubeConfig "cluster-admin" clusterAdminKubeconfig);
 
       environment.systemPackages = mkIf (top.kubelet.enable || top.proxy.enable) [
       (pkgs.writeScriptBin "nixos-kubernetes-node-join" ''
@@ -284,38 +312,22 @@ in
           exit 1
         fi
 
+        do_restart=$(test -s ${certmgrAPITokenPath} && echo -n y || echo -n n)
+
         echo $token > ${certmgrAPITokenPath}
         chmod 600 ${certmgrAPITokenPath}
 
-        echo "Restarting certmgr..." >&1
-        systemctl restart certmgr
-
-        echo "Waiting for certs to appear..." >&1
-
-        ${optionalString top.kubelet.enable ''
-          while [ ! -f ${cfg.certs.kubelet.cert} ]; do sleep 1; done
-          echo "Restarting kubelet..." >&1
-          systemctl restart kubelet
-        ''}
-
-        ${optionalString top.proxy.enable ''
-          while [ ! -f ${cfg.certs.kubeProxyClient.cert} ]; do sleep 1; done
-          echo "Restarting kube-proxy..." >&1
-          systemctl restart kube-proxy
-        ''}
-
-        ${optionalString top.flannel.enable ''
-          while [ ! -f ${cfg.certs.flannelClient.cert} ]; do sleep 1; done
-          echo "Restarting flannel..." >&1
-          systemctl restart flannel
-        ''}
+        if [ y = $do_restart ]; then
+          echo "Restarting certmgr..." >&1
+          systemctl restart certmgr
+        fi
 
-        echo "Node joined succesfully"
+        echo "Node joined succesfully" >&1
       '')];
 
       # isolate etcd on loopback at the master node
       # easyCerts doesn't support multimaster clusters anyway atm.
-      services.etcd = with cfg.certs.etcd; {
+      services.etcd = mkIf top.apiserver.enable (with cfg.certs.etcd; {
         listenClientUrls = ["https://127.0.0.1:2379"];
         listenPeerUrls = ["https://127.0.0.1:2380"];
         advertiseClientUrls = ["https://etcd.local:2379"];
@@ -324,19 +336,11 @@ in
         certFile = mkDefault cert;
         keyFile = mkDefault key;
         trustedCaFile = mkDefault caCert;
-      };
+      });
       networking.extraHosts = mkIf (config.services.etcd.enable) ''
         127.0.0.1 etcd.${top.addons.dns.clusterDomain} etcd.local
       '';
 
-      services.flannel = with cfg.certs.flannelClient; {
-        kubeconfig = top.lib.mkKubeConfig "flannel" {
-          server = top.apiserverAddress;
-          certFile = cert;
-          keyFile = key;
-        };
-      };
-
       services.kubernetes = {
 
         apiserver = mkIf top.apiserver.enable (with cfg.certs.apiServer; {
@@ -353,7 +357,16 @@ in
           kubeletClientCaFile = mkDefault caCert;
           kubeletClientCertFile = mkDefault cfg.certs.apiserverKubeletClient.cert;
           kubeletClientKeyFile = mkDefault cfg.certs.apiserverKubeletClient.key;
+          proxyClientCertFile = mkDefault cfg.certs.apiserverProxyClient.cert;
+          proxyClientKeyFile = mkDefault cfg.certs.apiserverProxyClient.key;
         });
+        addonManager = mkIf top.addonManager.enable {
+          kubeconfig = with cfg.certs.addonManager; {
+            certFile = mkDefault cert;
+            keyFile = mkDefault key;
+          };
+          bootstrapAddonsKubeconfig = clusterAdminKubeconfig;
+        };
         controllerManager = mkIf top.controllerManager.enable {
           serviceAccountKeyFile = mkDefault cfg.certs.serviceAccount.key;
           rootCaFile = cfg.certs.controllerManagerClient.caCert;
@@ -362,6 +375,12 @@ in
             keyFile = mkDefault key;
           };
         };
+        flannel = mkIf top.flannel.enable {
+          kubeconfig = with cfg.certs.flannelClient; {
+            certFile = cert;
+            keyFile = key;
+          };
+        };
         scheduler = mkIf top.scheduler.enable {
           kubeconfig = with cfg.certs.schedulerClient; {
             certFile = mkDefault cert;
diff --git a/nixos/modules/services/cluster/kubernetes/proxy.nix b/nixos/modules/services/cluster/kubernetes/proxy.nix
index 83cd3e23100..8a90542fe63 100644
--- a/nixos/modules/services/cluster/kubernetes/proxy.nix
+++ b/nixos/modules/services/cluster/kubernetes/proxy.nix
@@ -45,12 +45,28 @@ in
   };
 
   ###### implementation
-  config = mkIf cfg.enable {
-    systemd.services.kube-proxy = {
+  config = let
+
+    proxyPaths = filter (a: a != null) [
+      cfg.kubeconfig.caFile
+      cfg.kubeconfig.certFile
+      cfg.kubeconfig.keyFile
+    ];
+
+  in mkIf cfg.enable {
+    systemd.services.kube-proxy = rec {
       description = "Kubernetes Proxy Service";
-      wantedBy = [ "kubernetes.target" ];
-      after = [ "kube-apiserver.service" ];
-      path = with pkgs; [ iptables conntrack_tools ];
+      wantedBy = [ "kube-node-online.target" ];
+      after = [ "kubelet-online.service" ];
+      before = [ "kube-node-online.target" ];
+      environment.KUBECONFIG = top.lib.mkKubeConfig "kube-proxy" cfg.kubeconfig;
+      path = with pkgs; [ iptables conntrack_tools kubectl ];
+      preStart = ''
+        until kubectl auth can-i get nodes/${top.kubelet.hostname} -q 2>/dev/null; do
+          echo kubectl auth can-i get nodes/${top.kubelet.hostname}: exit status $?
+          sleep 2
+        done
+      '';
       serviceConfig = {
         Slice = "kubernetes.slice";
         ExecStart = ''${top.package}/bin/kube-proxy \
@@ -59,7 +75,7 @@ in
             "--cluster-cidr=${top.clusterCidr}"} \
           ${optionalString (cfg.featureGates != [])
             "--feature-gates=${concatMapStringsSep "," (feature: "${feature}=true") cfg.featureGates}"} \
-          --kubeconfig=${top.lib.mkKubeConfig "kube-proxy" cfg.kubeconfig} \
+          --kubeconfig=${environment.KUBECONFIG} \
           ${optionalString (cfg.verbosity != null) "--v=${toString cfg.verbosity}"} \
           ${cfg.extraOpts}
         '';
@@ -67,6 +83,15 @@ in
         Restart = "on-failure";
         RestartSec = 5;
       };
+      unitConfig.ConditionPathExists = proxyPaths;
+    };
+
+    systemd.paths.kube-proxy = {
+      wantedBy = [ "kube-proxy.service" ];
+      pathConfig = {
+        PathExists = proxyPaths;
+        PathChanged = proxyPaths;
+      };
     };
 
     services.kubernetes.pki.certs = {
diff --git a/nixos/modules/services/cluster/kubernetes/scheduler.nix b/nixos/modules/services/cluster/kubernetes/scheduler.nix
index 0305b9aefe5..d5852825954 100644
--- a/nixos/modules/services/cluster/kubernetes/scheduler.nix
+++ b/nixos/modules/services/cluster/kubernetes/scheduler.nix
@@ -56,18 +56,35 @@ in
   };
 
   ###### implementation
-  config = mkIf cfg.enable {
-    systemd.services.kube-scheduler = {
+  config =  let
+
+    schedulerPaths = filter (a: a != null) [
+      cfg.kubeconfig.caFile
+      cfg.kubeconfig.certFile
+      cfg.kubeconfig.keyFile
+    ];
+
+  in mkIf cfg.enable {
+    systemd.services.kube-scheduler = rec {
       description = "Kubernetes Scheduler Service";
-      wantedBy = [ "kubernetes.target" ];
+      wantedBy = [ "kube-control-plane-online.target" ];
       after = [ "kube-apiserver.service" ];
+      before = [ "kube-control-plane-online.target" ];
+      environment.KUBECONFIG = top.lib.mkKubeConfig "kube-scheduler" cfg.kubeconfig;
+      path = [ pkgs.kubectl ];
+      preStart = ''
+        until kubectl auth can-i get /api -q 2>/dev/null; do
+          echo kubectl auth can-i get /api: exit status $?
+          sleep 2
+        done
+      '';
       serviceConfig = {
         Slice = "kubernetes.slice";
         ExecStart = ''${top.package}/bin/kube-scheduler \
           --address=${cfg.address} \
           ${optionalString (cfg.featureGates != [])
             "--feature-gates=${concatMapStringsSep "," (feature: "${feature}=true") cfg.featureGates}"} \
-          --kubeconfig=${top.lib.mkKubeConfig "kube-scheduler" cfg.kubeconfig} \
+          --kubeconfig=${environment.KUBECONFIG} \
           --leader-elect=${boolToString cfg.leaderElect} \
           --port=${toString cfg.port} \
           ${optionalString (cfg.verbosity != null) "--v=${toString cfg.verbosity}"} \
@@ -79,6 +96,15 @@ in
         Restart = "on-failure";
         RestartSec = 5;
       };
+      unitConfig.ConditionPathExists = schedulerPaths;
+    };
+
+    systemd.paths.kube-scheduler = {
+      wantedBy = [ "kube-scheduler.service" ];
+      pathConfig = {
+        PathExists = schedulerPaths;
+        PathChanged = schedulerPaths;
+      };
     };
 
     services.kubernetes.pki.certs = {
diff --git a/nixos/tests/kubernetes/base.nix b/nixos/tests/kubernetes/base.nix
index ec1a75e74c4..212023859f6 100644
--- a/nixos/tests/kubernetes/base.nix
+++ b/nixos/tests/kubernetes/base.nix
@@ -30,7 +30,10 @@ let
         { config, pkgs, lib, nodes, ... }:
           mkMerge [
             {
-              boot.postBootCommands = "rm -fr /var/lib/kubernetes/secrets /tmp/shared/*";
+              boot = {
+                postBootCommands = "rm -fr /var/lib/kubernetes/secrets /tmp/shared/*";
+                kernel.sysctl = { "fs.inotify.max_user_instances" = 256; };
+              };
               virtualisation.memorySize = mkDefault 1536;
               virtualisation.diskSize = mkDefault 4096;
               networking = {
diff --git a/nixos/tests/kubernetes/dns.nix b/nixos/tests/kubernetes/dns.nix
index 46bcb01a526..e7db0a58ab6 100644
--- a/nixos/tests/kubernetes/dns.nix
+++ b/nixos/tests/kubernetes/dns.nix
@@ -77,6 +77,7 @@ let
   singleNodeTest = {
     test = ''
       # prepare machine1 for test
+      $machine1->waitForUnit("kubernetes.target");
       $machine1->waitUntilSucceeds("kubectl get node machine1.${domain} | grep -w Ready");
       $machine1->waitUntilSucceeds("docker load < ${redisImage}");
       $machine1->waitUntilSucceeds("kubectl create -f ${redisPod}");
@@ -102,6 +103,8 @@ let
       # Node token exchange
       $machine1->waitUntilSucceeds("cp -f /var/lib/cfssl/apitoken.secret /tmp/shared/apitoken.secret");
       $machine2->waitUntilSucceeds("cat /tmp/shared/apitoken.secret | nixos-kubernetes-node-join");
+      $machine1->waitForUnit("kubernetes.target");
+      $machine2->waitForUnit("kubernetes.target");
 
       # prepare machines for test
       $machine1->waitUntilSucceeds("kubectl get node machine2.${domain} | grep -w Ready");
diff --git a/nixos/tests/kubernetes/rbac.nix b/nixos/tests/kubernetes/rbac.nix
index 3ce7adcd0d7..967fe506004 100644
--- a/nixos/tests/kubernetes/rbac.nix
+++ b/nixos/tests/kubernetes/rbac.nix
@@ -94,6 +94,8 @@ let
 
   singlenode = base // {
     test = ''
+      $machine1->waitForUnit("kubernetes.target");
+
       $machine1->waitUntilSucceeds("kubectl get node machine1.my.zyx | grep -w Ready");
 
       $machine1->waitUntilSucceeds("docker load < ${kubectlImage}");
@@ -116,6 +118,8 @@ let
       # Node token exchange
       $machine1->waitUntilSucceeds("cp -f /var/lib/cfssl/apitoken.secret /tmp/shared/apitoken.secret");
       $machine2->waitUntilSucceeds("cat /tmp/shared/apitoken.secret | nixos-kubernetes-node-join");
+      $machine1->waitForUnit("kubernetes.target");
+      $machine2->waitForUnit("kubernetes.target");
 
       $machine1->waitUntilSucceeds("kubectl get node machine2.my.zyx | grep -w Ready");
 
diff --git a/pkgs/applications/editors/vscode/default.nix b/pkgs/applications/editors/vscode/default.nix
index 189c49cde35..67c1ddf175f 100644
--- a/pkgs/applications/editors/vscode/default.nix
+++ b/pkgs/applications/editors/vscode/default.nix
@@ -108,6 +108,10 @@ in
 
         mkdir -p $out/share/pixmaps
         cp $out/lib/vscode/resources/app/resources/linux/code.png $out/share/pixmaps/code.png
+
+        # Override the previously determined VSCODE_PATH with the one we know to be correct
+        sed -i "/ELECTRON=/iVSCODE_PATH='$out/lib/vscode'" $out/bin/code
+        grep -q "VSCODE_PATH='$out/lib/vscode'" $out/bin/code # check if sed succeeded
       '';
 
     preFixup = lib.optionalString (system == "i686-linux" || system == "x86_64-linux") ''
@@ -129,7 +133,7 @@ in
       homepage = https://code.visualstudio.com/;
       downloadPage = https://code.visualstudio.com/Updates;
       license = licenses.unfree;
-      maintainers = with maintainers; [ eadwu ];
+      maintainers = with maintainers; [ eadwu synthetica ];
       platforms = [ "i686-linux" "x86_64-linux" "x86_64-darwin" ];
     };
   }
diff --git a/pkgs/applications/misc/bleachbit/default.nix b/pkgs/applications/misc/bleachbit/default.nix
index f0dce54675c..3f13972de9b 100644
--- a/pkgs/applications/misc/bleachbit/default.nix
+++ b/pkgs/applications/misc/bleachbit/default.nix
@@ -1,26 +1,26 @@
-{ stdenv, pythonPackages, fetchurl }:
+{ stdenv, pythonPackages, fetchurl, gettext }:
 pythonPackages.buildPythonApplication rec {
-  name = "bleachbit-${version}";
-  version = "2.0";
+  pname = "bleachbit";
+  version = "2.2";
 
-  namePrefix = "";
+  format = "other";
 
   src = fetchurl {
-    url = "mirror://sourceforge/bleachbit/${name}.tar.bz2";
-    sha256 = "0ps98zx4n13q92bq7ykqi6hj3i7brdqgm87i9gk6ibvljp1vxdz9";
+    url = "mirror://sourceforge/${pname}/${pname}-${version}.tar.bz2";
+    sha256 = "1yj9bc3k6s1aib7znb79h5rybfv691zz4szxkwf9fm9nr0dws603";
   };
 
-  buildInputs = [  pythonPackages.wrapPython ];
+  nativeBuildInputs = [ gettext ];
 
-  doCheck = false;
+  # Patch the many hardcoded uses of /usr/share/ and /usr/bin
+  postPatch = ''
+    find -type f -exec sed -i -e 's@/usr/share@${placeholder "out"}/share@g' {} \;
+    find -type f -exec sed -i -e 's@/usr/bin@${placeholder "out"}/bin@g' {} \;
+  '';
 
-  postInstall = ''
-    mkdir -p $out/bin
-    cp bleachbit.py $out/bin/bleachbit
-    chmod +x $out/bin/bleachbit
+  dontBuild = true;
 
-    substituteInPlace $out/bin/bleachbit --replace "#!/usr/bin/env python" "#!${pythonPackages.python.interpreter}"
-  '';
+  installFlags = [ "prefix=${placeholder "out"}" ];
 
   propagatedBuildInputs = with pythonPackages; [ pygtk ];
 
diff --git a/pkgs/applications/misc/stretchly/default.nix b/pkgs/applications/misc/stretchly/default.nix
new file mode 100644
index 00000000000..8f26ee99e22
--- /dev/null
+++ b/pkgs/applications/misc/stretchly/default.nix
@@ -0,0 +1,139 @@
+{ GConf
+, alsaLib
+, at-spi2-atk
+, atk
+, cairo
+, cups
+, dbus
+, expat
+, fetchurl
+, fontconfig
+, gdk_pixbuf
+, glib
+, gtk2
+, gtk3
+, lib
+, libX11
+, libXScrnSaver
+, libXcomposite
+, libXcursor
+, libXdamage
+, libXext
+, libXfixes
+, libXi
+, libXrandr
+, libXrender
+, libXtst
+, libappindicator
+, libdrm
+, libnotify
+, libpciaccess
+, libpng12
+, libxcb
+, nspr
+, nss
+, pango
+, pciutils
+, pulseaudio
+, stdenv
+, udev
+, wrapGAppsHook
+}:
+
+let
+  libs = [
+    GConf
+    alsaLib
+    at-spi2-atk
+    atk
+    cairo
+    cups
+    dbus
+    expat
+    fontconfig
+    gdk_pixbuf
+    glib
+    gtk2
+    gtk3
+    libX11
+    libXScrnSaver
+    libXcomposite
+    libXcursor
+    libXdamage
+    libXext
+    libXfixes
+    libXi
+    libXrandr
+    libXrender
+    libXtst
+    libappindicator
+    libdrm
+    libnotify
+    libpciaccess
+    libpng12
+    libxcb
+    nspr
+    nss
+    pango
+    pciutils
+    pulseaudio
+    stdenv.cc.cc.lib
+    udev
+  ];
+
+  libPath = lib.makeLibraryPath libs;
+in
+
+stdenv.mkDerivation rec {
+  pname = "stretchly";
+  version = "0.19.1";
+
+  src = fetchurl {
+    url = "https://github.com/hovancik/stretchly/releases/download/v${version}/stretchly-${version}.tar.xz";
+    sha256 = "1q2wxfqs8qv9b1rfh5lhmyp3rrgdl05m6ihsgkxlgp0yzi07afz8";
+  };
+
+  nativeBuildInputs = [
+    wrapGAppsHook
+  ];
+
+  buildInputs = libs;
+
+  dontPatchELF = true;
+  dontBuild = true;
+  dontConfigure = true;
+
+  installPhase = ''
+    mkdir -p $out/bin $out/lib/stretchly
+    cp -r ./* $out/lib/stretchly/
+    ln -s $out/lib/stretchly/libffmpeg.so $out/lib/
+    ln -s $out/lib/stretchly/libnode.so $out/lib/
+    ln -s $out/lib/stretchly/stretchly $out/bin/
+  '';
+
+  preFixup = ''
+    patchelf --set-rpath "${libPath}" $out/lib/stretchly/libffmpeg.so
+    patchelf --set-rpath "${libPath}" $out/lib/stretchly/libnode.so
+
+    patchelf \
+      --set-rpath "$out/lib/stretchly:${libPath}" \
+      --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
+      $out/lib/stretchly/stretchly
+  '';
+
+  meta = with stdenv.lib; {
+    description = "A break time reminder app";
+    longDescription = ''
+      stretchly is a cross-platform electron app that reminds you to take
+      breaks when working on your computer. By default, it runs in your tray
+      and displays a reminder window containing an idea for a microbreak for 20
+      seconds every 10 minutes. Every 30 minutes, it displays a window
+      containing an idea for a longer 5 minute break.
+    '';
+    homepage = https://hovancik.net/stretchly;
+    downloadPage = https://hovancik.net/stretchly/downloads/;
+    license = licenses.bsd2;
+    maintainers = with maintainers; [ cdepillabout ];
+    platforms = platforms.linux;
+  };
+}
diff --git a/pkgs/applications/networking/browsers/tor-browser-bundle-bin/default.nix b/pkgs/applications/networking/browsers/tor-browser-bundle-bin/default.nix
index 283c63dcd6f..f37677b0521 100644
--- a/pkgs/applications/networking/browsers/tor-browser-bundle-bin/default.nix
+++ b/pkgs/applications/networking/browsers/tor-browser-bundle-bin/default.nix
@@ -302,10 +302,12 @@ stdenv.mkDerivation rec {
     # easily generated by firefox at startup.
     rm -f "\$HOME/TorBrowser/Data/Browser/profile.default"/{compatibility.ini,extensions.ini,extensions.json}
 
+    # XDG
+    : "\''${XDG_RUNTIME_DIR:=/run/user/\$(id -u)}"
+    : "\''${XDG_CONFIG_HOME:=\$REAL_HOME/.config}"
+
     ${optionalString pulseaudioSupport ''
       # Figure out some envvars for pulseaudio
-      : "\''${XDG_RUNTIME_DIR:=/run/user/\$(id -u)}"
-      : "\''${XDG_CONFIG_HOME:=\$REAL_HOME/.config}"
       : "\''${PULSE_SERVER:=\$XDG_RUNTIME_DIR/pulse/native}"
       : "\''${PULSE_COOKIE:=\$XDG_CONFIG_HOME/pulse/cookie}"
     ''}
@@ -336,9 +338,9 @@ stdenv.mkDerivation rec {
       \
       TMPDIR="\''${TMPDIR:-/tmp}" \
       HOME="\$HOME" \
-      XAUTHORITY="\''${XAUTHORITY:-}" \
+      XAUTHORITY="\''${XAUTHORITY:-\$HOME/.Xauthority}" \
       DISPLAY="\$DISPLAY" \
-      DBUS_SESSION_BUS_ADDRESS="\$DBUS_SESSION_BUS_ADDRESS" \
+      DBUS_SESSION_BUS_ADDRESS="\''${DBUS_SESSION_BUS_ADDRESS:-unix:path=\$XDG_RUNTIME_DIR/bus}" \\
       \
       XDG_DATA_HOME="\$HOME/.local/share" \
       XDG_DATA_DIRS="$WRAPPER_XDG_DATA_DIRS" \
diff --git a/pkgs/applications/version-management/git-and-tools/pre-commit/default.nix b/pkgs/applications/version-management/git-and-tools/pre-commit/default.nix
index 7b86b5429b2..abbec433c02 100644
--- a/pkgs/applications/version-management/git-and-tools/pre-commit/default.nix
+++ b/pkgs/applications/version-management/git-and-tools/pre-commit/default.nix
@@ -1,12 +1,12 @@
 { stdenv, python3Packages }:
 with python3Packages; buildPythonApplication rec {
   pname = "pre-commit";
-  version = "1.14.4";
+  version = "1.15.1";
 
   src = fetchPypi {
     inherit version;
     pname = "pre_commit";
-    sha256 = "1ly40348x9lkzsr7a9grkn7m8m6lhfsv0ihlnp288xbvmrirrmnk";
+    sha256 = "1c4a6g3x44xkr75196m2qhb7fbm0lv40yv312g4hkl00mq713abm";
   };
 
   propagatedBuildInputs = [
diff --git a/pkgs/development/libraries/libimobiledevice/default.nix b/pkgs/development/libraries/libimobiledevice/default.nix
index f4eafcdaace..83a500c1380 100644
--- a/pkgs/development/libraries/libimobiledevice/default.nix
+++ b/pkgs/development/libraries/libimobiledevice/default.nix
@@ -3,15 +3,15 @@
 
 stdenv.mkDerivation rec {
   pname = "libimobiledevice";
-  version = "2018-07-24";
+  version = "2019-04-04";
 
   name = "${pname}-${version}";
 
   src = fetchFromGitHub {
     owner = pname;
     repo = pname;
-    rev = "d7a2e04d2e7880c56116fd35489a7f98755501b7";
-    sha256 = "0cj0j10lmfr28c7nh79n2mcmy31xx50g93h0bqs0l7y76ph4dqkc";
+    rev = "eea4f1be9107c8ab621fd71460e47d0d38e55d71";
+    sha256 = "0wh6z5f5znlqs0grh7c8jj1s411azgyy45klmql5kj3p8qqybqrs";
   };
 
   outputs = [ "out" "dev" ];
@@ -56,6 +56,6 @@ stdenv.mkDerivation rec {
     '';
     license = licenses.lgpl21Plus;
     platforms = platforms.linux;
-    maintainers = with maintainers; [ ];
+    maintainers = with maintainers; [ infinisil ];
   };
 }
diff --git a/pkgs/development/libraries/libplist/default.nix b/pkgs/development/libraries/libplist/default.nix
index 904206ab79b..d622584c9da 100644
--- a/pkgs/development/libraries/libplist/default.nix
+++ b/pkgs/development/libraries/libplist/default.nix
@@ -5,15 +5,15 @@ let
 in
 stdenv.mkDerivation rec {
   pname = "libplist";
-  version = "2019-01-20";
+  version = "2019-04-04";
 
   name = "${pname}-${version}";
 
   src = fetchFromGitHub {
     owner = "libimobiledevice";
     repo = pname;
-    rev = "bec850fe399639f3b8582a39386216970dea15ed";
-    sha256 = "197yw8xz8x2xld8b6975scgnl30j4ibm9llmzljyqngs0zsdwnin";
+    rev = "42bb64ba966082b440cb68cbdadf317f44710017";
+    sha256 = "19yw80yblq29i2jx9yb7bx0lfychy9dncri3fk4as35kq5bf26i8";
   };
 
   outputs = ["bin" "dev" "out" "py"];
@@ -35,7 +35,7 @@ stdenv.mkDerivation rec {
     description = "A library to handle Apple Property List format in binary or XML";
     homepage = https://github.com/libimobiledevice/libplist;
     license = licenses.lgpl21Plus;
-    maintainers = [ ];
+    maintainers = with maintainers; [ infinisil ];
     platforms = platforms.linux;
   };
 }
diff --git a/pkgs/development/libraries/libusbmuxd/default.nix b/pkgs/development/libraries/libusbmuxd/default.nix
index 4192e3c14d3..d9e008af977 100644
--- a/pkgs/development/libraries/libusbmuxd/default.nix
+++ b/pkgs/development/libraries/libusbmuxd/default.nix
@@ -2,15 +2,15 @@
 
 stdenv.mkDerivation rec {
   pname = "libusbmuxd";
-  version = "2019-01-18";
+  version = "2019-03-23";
 
   name = "${pname}-${version}";
 
   src = fetchFromGitHub {
     owner = "libimobiledevice";
     repo = pname;
-    rev = "c75605d862cd1c312494f6c715246febc26b2e05";
-    sha256 = "0467a045k4znmaz61i7a2s7yywj67q830ja6zn7z39k5pqcl2z4p";
+    rev = "873252dc8b4e469c7dc692064ac616104fca5f65";
+    sha256 = "0qx3q0n1f2ajfm3vnairikayzln6iyb2y0i7sqfl8mj45ahl6wyj";
   };
 
   nativeBuildInputs = [ autoreconfHook pkgconfig ];
@@ -21,6 +21,6 @@ stdenv.mkDerivation rec {
     homepage    = https://github.com/libimobiledevice/libusbmuxd;
     license     = licenses.lgpl21Plus;
     platforms   = platforms.linux;
-    maintainers = with maintainers; [ ];
+    maintainers = with maintainers; [ infinisil ];
   };
 }
diff --git a/pkgs/development/libraries/qtstyleplugin-kvantum-qt4/default.nix b/pkgs/development/libraries/qtstyleplugin-kvantum-qt4/default.nix
index 2f0e39eb5c9..88330712dcd 100644
--- a/pkgs/development/libraries/qtstyleplugin-kvantum-qt4/default.nix
+++ b/pkgs/development/libraries/qtstyleplugin-kvantum-qt4/default.nix
@@ -1,14 +1,14 @@
 { stdenv, fetchFromGitHub, qmake4Hook , qt4, libX11, libXext }:
 
 stdenv.mkDerivation rec {
-  name = "qtstyleplugin-kvantum-qt4-${version}";
-  version = "0.10.4";
+  pname = "qtstyleplugin-kvantum-qt4";
+  version = "0.11.0";
 
   src = fetchFromGitHub {
     owner = "tsujan";
     repo = "Kvantum";
-    rev = "0527bb03f2252269fd382e11181a34ca72c96b4b";
-    sha256 = "0ky44s1fgqxraywagx1mv07yz76ppgiz3prq447db78wkwqg2d8p";
+    rev = "V${version}";
+    sha256 = "0aqlv7mj7r9vjm6pvb8pv3cyx35lgz8rjjas3k8wfdr3sqyyy25g";
   };
 
   nativeBuildInputs = [ qmake4Hook ];
diff --git a/pkgs/development/libraries/qtstyleplugin-kvantum/default.nix b/pkgs/development/libraries/qtstyleplugin-kvantum/default.nix
index 39f7fa91b02..dc11cb56091 100644
--- a/pkgs/development/libraries/qtstyleplugin-kvantum/default.nix
+++ b/pkgs/development/libraries/qtstyleplugin-kvantum/default.nix
@@ -2,13 +2,13 @@
 
 stdenv.mkDerivation rec {
   pname = "qtstyleplugin-kvantum";
-  version = "0.10.9";
+  version = "0.11.0";
 
   src = fetchFromGitHub {
     owner = "tsujan";
     repo = "Kvantum";
     rev = "V${version}";
-    sha256 = "1zpq6wsl57kfx0jf0rkxf15ic22ihazj03i3kfiqb07vcrs2cka9";
+    sha256 = "0aqlv7mj7r9vjm6pvb8pv3cyx35lgz8rjjas3k8wfdr3sqyyy25g";
   };
 
   nativeBuildInputs = [ qmake qttools ];
diff --git a/pkgs/development/python-modules/wsproto/default.nix b/pkgs/development/python-modules/wsproto/default.nix
index f9062c18584..ca9872bfbf0 100644
--- a/pkgs/development/python-modules/wsproto/default.nix
+++ b/pkgs/development/python-modules/wsproto/default.nix
@@ -1,12 +1,12 @@
-{ buildPythonPackage, fetchPypi, h11, enum34, pytest }:
+{ lib, buildPythonPackage, fetchPypi, h11, enum34, pytest }:
 
 buildPythonPackage rec {
   pname = "wsproto";
-  version = "0.13.0";
+  version = "0.14.0";
 
   src = fetchPypi {
     inherit pname version;
-    sha256 = "fd6020d825022247053400306448e161d8740bdd52e328e5553cd9eee089f705";
+    sha256 = "1p24dmym6pfsqsyxps6m2cxfl36cmkri0kdy5y5q7s300j3xmhsm";
   };
 
   propagatedBuildInputs = [ h11 enum34 ];
@@ -17,4 +17,9 @@ buildPythonPackage rec {
     py.test
   '';
 
+  meta = with lib; {
+    description = "Pure Python, pure state-machine WebSocket implementation";
+    homepage = https://github.com/python-hyper/wsproto/;
+    license = licenses.mit;
+  };
 }
diff --git a/pkgs/development/python-modules/xdot/default.nix b/pkgs/development/python-modules/xdot/default.nix
index 79f0fb13d70..8ad249a4c1a 100644
--- a/pkgs/development/python-modules/xdot/default.nix
+++ b/pkgs/development/python-modules/xdot/default.nix
@@ -3,11 +3,11 @@
 
 buildPythonPackage rec {
   pname = "xdot";
-  version = "1.0";
+  version = "1.1";
 
   src = fetchPypi {
     inherit pname version;
-    sha256 = "18a2ri8vggaxy7im1x9hki34v519y5jy4n07zpqq5br9syb7h1ky";
+    sha256 = "0cr4rh7dz4dfzyxrk5pzhm0d15gkrgkfp3i5lw178xy81pc56p71";
   };
 
   disabled = !isPy3k;
diff --git a/pkgs/development/ruby-modules/bundix/default.nix b/pkgs/development/ruby-modules/bundix/default.nix
index 92f14114cf1..d6a8f3ddbc6 100644
--- a/pkgs/development/ruby-modules/bundix/default.nix
+++ b/pkgs/development/ruby-modules/bundix/default.nix
@@ -6,13 +6,13 @@ buildRubyGem rec {
 
   name = "${gemName}-${version}";
   gemName = "bundix";
-  version = "2.4.1";
+  version = "2.4.2";
 
   src = fetchFromGitHub {
     owner = "manveru";
     repo = "bundix";
     rev = version;
-    sha256 = "175qmv7dj7v50v71b78dzn5pb4a35ml6p15asks9q1rrlkz0n4gn";
+    sha256 = "03jhj1dy0ljrymjnpi6mcxn36a29qxr835l1lc11879jjzvnr2ax";
   };
 
   buildInputs = [ ruby bundler ];
diff --git a/pkgs/development/tools/continuous-integration/gitlab-runner/default.nix b/pkgs/development/tools/continuous-integration/gitlab-runner/default.nix
index aa262fd5495..c75baf454b3 100644
--- a/pkgs/development/tools/continuous-integration/gitlab-runner/default.nix
+++ b/pkgs/development/tools/continuous-integration/gitlab-runner/default.nix
@@ -1,16 +1,16 @@
 { lib, buildGoPackage, fetchFromGitLab, fetchurl }:
 
 let
-  version = "11.9.0";
+  version = "11.9.2";
   # Gitlab runner embeds some docker images these are prebuilt for arm and x86_64
   docker_x86_64 = fetchurl {
     url = "https://gitlab-runner-downloads.s3.amazonaws.com/v${version}/helper-images/prebuilt-x86_64.tar.xz";
-    sha256 = "1la4pkf8xp5h75dlvb6w7ijczrnci3bmbl77h3y4jicz555jjir3";
+    sha256 = "10zmaywq1vzch4a6zdvnm9kgil9ankc9napix9s9fw45wc0lw01p";
   };
 
   docker_arm = fetchurl {
     url = "https://gitlab-runner-downloads.s3.amazonaws.com/v${version}/helper-images/prebuilt-arm.tar.xz";
-    sha256 = "1axn34aqa17yk2c2vy73fb8ab3nc3021dzj0vk95qificlmj3par";
+    sha256 = "0845ylhb3i3jmi5q6aaix4hw9zdb83v5fhvif0xvvi2m7irg06lf";
   };
 in
 buildGoPackage rec {
@@ -29,7 +29,7 @@ buildGoPackage rec {
     owner = "gitlab-org";
     repo = "gitlab-runner";
     rev = "v${version}";
-    sha256 = "1b4r83glx0n3l060k33s397dw5dpajlxb880yzwsb11hvc6cs39h";
+    sha256 = "00k4myca2djd6h3i83vjndahm5q1rnlkq0p69dhl5jbldwy614ph";
   };
 
   patches = [ ./fix-shell-path.patch ];
diff --git a/pkgs/development/tools/go-langserver/default.nix b/pkgs/development/tools/go-langserver/default.nix
index 84efaf2a4b6..ec0e565eabd 100644
--- a/pkgs/development/tools/go-langserver/default.nix
+++ b/pkgs/development/tools/go-langserver/default.nix
@@ -1,18 +1,17 @@
 { stdenv, buildGoPackage, fetchFromGitHub }:
 
 buildGoPackage rec {
-  name = "go-langserver-${version}";
-  version = "unstable-2018-03-05";
-  rev = "5d7a5dd74738978d635f709669241f164c120ebd";
+  pname = "go-langserver";
+  version = "2.0.0";
 
   goPackagePath = "github.com/sourcegraph/go-langserver";
   subPackages = [ "." ];
 
   src = fetchFromGitHub {
-    inherit rev;
+    rev = "v${version}";
     owner = "sourcegraph";
     repo = "go-langserver";
-    sha256 = "0aih0akk3wk3332znkhr2bzxcc3parijq7n089mdahnf20k69xyz";
+    sha256 = "1wv7xf81s3qi8xydxjkkp8vacdzrq8sbj04346fz73nsn85z0sgp";
   };
 
   meta = with stdenv.lib; {
diff --git a/pkgs/tools/filesystems/ifuse/default.nix b/pkgs/tools/filesystems/ifuse/default.nix
index f9021c5a3aa..083bae24d60 100644
--- a/pkgs/tools/filesystems/ifuse/default.nix
+++ b/pkgs/tools/filesystems/ifuse/default.nix
@@ -2,15 +2,15 @@
 
 stdenv.mkDerivation rec {
   pname = "ifuse";
-  version = "1.1.3";
+  version = "2018-10-08";
 
   name = "${pname}-${version}";
 
   src = fetchFromGitHub {
     owner = "libimobiledevice";
     repo = pname;
-    rev = version;
-    sha256 = "0p01rds3vc5864v48swgqw5dv0h937nqnxggryixg9pkvzhc6cx5";
+    rev = "e75d32c34d0e8b80320f0a007d5ecbb3f55ef7f0";
+    sha256 = "1b9w2i0sliswlkkb890l9i0rxrf631xywxf8ihygfmjdsfw47h1m";
   };
 
   nativeBuildInputs = [ autoreconfHook pkgconfig fuse usbmuxd libimobiledevice ];
@@ -26,6 +26,6 @@ stdenv.mkDerivation rec {
     '';
     license = licenses.lgpl21Plus;
     platforms = platforms.linux;
-    maintainers = with maintainers; [ ];
+    maintainers = with maintainers; [ infinisil ];
   };
 }
diff --git a/pkgs/tools/misc/ideviceinstaller/default.nix b/pkgs/tools/misc/ideviceinstaller/default.nix
index 957267ae10e..15af413a999 100644
--- a/pkgs/tools/misc/ideviceinstaller/default.nix
+++ b/pkgs/tools/misc/ideviceinstaller/default.nix
@@ -2,15 +2,15 @@
 
 stdenv.mkDerivation rec {
   pname = "ideviceinstaller";
-  version = "2018-06-01";
+  version = "2018-10-01";
 
   name = "${pname}-${version}";
 
   src = fetchFromGitHub {
     owner = "libimobiledevice";
     repo = pname;
-    rev = "f7988de8279051f3d2d7973b8d7f2116aa5d9317";
-    sha256 = "1vmdvbwnjz3f90b9bqq7jg04q7awsbi9pmkvgwal8xdpp6jcwkwx";
+    rev = "f14def7cd9303a0fe622732fae9830ae702fdd7c";
+    sha256 = "1biwhbldvgdhn8ygp7w79ca0rivzdjpykr76pyhy7r2fa56mrwq8";
   };
 
   nativeBuildInputs = [ autoreconfHook pkgconfig usbmuxd libimobiledevice libzip ];
@@ -19,12 +19,12 @@ stdenv.mkDerivation rec {
     homepage = https://github.com/libimobiledevice/ideviceinstaller;
     description = "List/modify installed apps of iOS devices";
     longDescription = ''
-      ideviceinstaller is a tool to interact with the installation_proxy 
+      ideviceinstaller is a tool to interact with the installation_proxy
       of an iOS device allowing to install, upgrade, uninstall, archive, restore
       and enumerate installed or archived apps.
     '';
     license = licenses.gpl2;
     platforms = platforms.linux;
-    maintainers = with maintainers; [ aristid ];
+    maintainers = with maintainers; [ aristid infinisil ];
   };
 }
diff --git a/pkgs/tools/misc/usbmuxd/default.nix b/pkgs/tools/misc/usbmuxd/default.nix
index 2dfd4752f07..9b94d003706 100644
--- a/pkgs/tools/misc/usbmuxd/default.nix
+++ b/pkgs/tools/misc/usbmuxd/default.nix
@@ -2,13 +2,13 @@
 
 stdenv.mkDerivation rec {
   pname = "usbmuxd";
-  version = "2018-10-10";
+  version = "2019-03-05";
 
   src = fetchFromGitHub {
     owner = "libimobiledevice";
     repo = pname;
-    rev = "96e4aabe0b9a46ea9da4955a10c774a8e58fe677";
-    sha256 = "03xnj4y606adbhl829vv46qa78f6w2ik4mjz19a34x9lhkcrqxqi";
+    rev = "b1b0bf390363fa36aff1bc09443ff751943b9c34";
+    sha256 = "176hapckx98h4x0ni947qpkv2s95f8xfwz00wi2w7rgbr6cviwjq";
   };
 
   nativeBuildInputs = [ autoreconfHook pkgconfig ];
@@ -33,6 +33,6 @@ stdenv.mkDerivation rec {
     '';
     license = licenses.gpl2Plus;
     platforms = platforms.linux;
-    maintainers = with maintainers; [ ];
+    maintainers = with maintainers; [ infinisil ];
   };
 }
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 2c27791d485..994cc348045 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -15389,9 +15389,7 @@ in
 
   gomodifytags = callPackage ../development/tools/gomodifytags { };
 
-  go-langserver = callPackage ../development/tools/go-langserver {
-    buildGoPackage = buildGo110Package;
-  };
+  go-langserver = callPackage ../development/tools/go-langserver { };
 
   gotests = callPackage ../development/tools/gotests { };
 
@@ -19841,6 +19839,10 @@ in
     bison = bison2;
   };
 
+  stretchly = callPackage ../applications/misc/stretchly {
+    inherit (gnome2) GConf;
+  };
+
   stumpish = callPackage ../applications/window-managers/stumpish {};
 
   stumpwm = callPackage ../applications/window-managers/stumpwm {