about summary refs log tree commit diff
path: root/nixpkgs/nixos/modules/programs
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/modules/programs')
-rw-r--r--nixpkgs/nixos/modules/programs/adb.nix29
-rw-r--r--nixpkgs/nixos/modules/programs/atop.nix36
-rw-r--r--nixpkgs/nixos/modules/programs/autojump.nix33
-rw-r--r--nixpkgs/nixos/modules/programs/bash/bash.nix236
-rw-r--r--nixpkgs/nixos/modules/programs/bash/inputrc37
-rw-r--r--nixpkgs/nixos/modules/programs/bcc.nix9
-rw-r--r--nixpkgs/nixos/modules/programs/blcr.nix27
-rw-r--r--nixpkgs/nixos/modules/programs/browserpass.nix32
-rw-r--r--nixpkgs/nixos/modules/programs/captive-browser.nix122
-rw-r--r--nixpkgs/nixos/modules/programs/ccache.nix83
-rw-r--r--nixpkgs/nixos/modules/programs/cdemu.nix58
-rw-r--r--nixpkgs/nixos/modules/programs/chromium.nix89
-rw-r--r--nixpkgs/nixos/modules/programs/clickshare.nix21
-rw-r--r--nixpkgs/nixos/modules/programs/command-not-found/command-not-found.nix95
-rw-r--r--nixpkgs/nixos/modules/programs/command-not-found/command-not-found.pl51
-rw-r--r--nixpkgs/nixos/modules/programs/criu.nix26
-rw-r--r--nixpkgs/nixos/modules/programs/dconf.nix44
-rw-r--r--nixpkgs/nixos/modules/programs/digitalbitbox/default.nix39
-rw-r--r--nixpkgs/nixos/modules/programs/digitalbitbox/doc.xml74
-rw-r--r--nixpkgs/nixos/modules/programs/dmrconfig.nix38
-rw-r--r--nixpkgs/nixos/modules/programs/environment.nix61
-rw-r--r--nixpkgs/nixos/modules/programs/evince.nix42
-rw-r--r--nixpkgs/nixos/modules/programs/file-roller.nix39
-rw-r--r--nixpkgs/nixos/modules/programs/firejail.nix48
-rw-r--r--nixpkgs/nixos/modules/programs/fish.nix240
-rw-r--r--nixpkgs/nixos/modules/programs/fish_completion-generator.patch11
-rw-r--r--nixpkgs/nixos/modules/programs/freetds.nix61
-rw-r--r--nixpkgs/nixos/modules/programs/fuse.nix37
-rw-r--r--nixpkgs/nixos/modules/programs/gnome-disks.nix46
-rw-r--r--nixpkgs/nixos/modules/programs/gnome-documents.nix50
-rw-r--r--nixpkgs/nixos/modules/programs/gnupg.nix112
-rw-r--r--nixpkgs/nixos/modules/programs/gpaste.nix34
-rw-r--r--nixpkgs/nixos/modules/programs/gphoto2.nix30
-rw-r--r--nixpkgs/nixos/modules/programs/iftop.nix18
-rw-r--r--nixpkgs/nixos/modules/programs/iotop.nix17
-rw-r--r--nixpkgs/nixos/modules/programs/java.nix58
-rw-r--r--nixpkgs/nixos/modules/programs/kbdlight.nix16
-rw-r--r--nixpkgs/nixos/modules/programs/less.nix131
-rw-r--r--nixpkgs/nixos/modules/programs/light.nix27
-rw-r--r--nixpkgs/nixos/modules/programs/mininet.nix39
-rw-r--r--nixpkgs/nixos/modules/programs/mosh.nix43
-rw-r--r--nixpkgs/nixos/modules/programs/mtr.nix28
-rw-r--r--nixpkgs/nixos/modules/programs/nano.nix42
-rw-r--r--nixpkgs/nixos/modules/programs/nm-applet.nix14
-rw-r--r--nixpkgs/nixos/modules/programs/npm.nix46
-rw-r--r--nixpkgs/nixos/modules/programs/oblogout.nix176
-rw-r--r--nixpkgs/nixos/modules/programs/plotinus.nix36
-rw-r--r--nixpkgs/nixos/modules/programs/plotinus.xml30
-rw-r--r--nixpkgs/nixos/modules/programs/qt5ct.nix31
-rw-r--r--nixpkgs/nixos/modules/programs/screen.nix32
-rw-r--r--nixpkgs/nixos/modules/programs/sedutil.nix18
-rw-r--r--nixpkgs/nixos/modules/programs/shadow.nix115
-rw-r--r--nixpkgs/nixos/modules/programs/shell.nix54
-rw-r--r--nixpkgs/nixos/modules/programs/singularity.nix29
-rw-r--r--nixpkgs/nixos/modules/programs/slock.nix26
-rw-r--r--nixpkgs/nixos/modules/programs/spacefm.nix55
-rw-r--r--nixpkgs/nixos/modules/programs/ssh.nix267
-rw-r--r--nixpkgs/nixos/modules/programs/ssmtp.nix165
-rw-r--r--nixpkgs/nixos/modules/programs/sway.nix93
-rw-r--r--nixpkgs/nixos/modules/programs/sysdig.nix14
-rw-r--r--nixpkgs/nixos/modules/programs/systemtap.nix28
-rw-r--r--nixpkgs/nixos/modules/programs/thefuck.nix39
-rw-r--r--nixpkgs/nixos/modules/programs/tmux.nix184
-rw-r--r--nixpkgs/nixos/modules/programs/tsm-client.nix287
-rw-r--r--nixpkgs/nixos/modules/programs/udevil.nix14
-rw-r--r--nixpkgs/nixos/modules/programs/venus.nix173
-rw-r--r--nixpkgs/nixos/modules/programs/vim.nix23
-rw-r--r--nixpkgs/nixos/modules/programs/virtualbox.nix8
-rw-r--r--nixpkgs/nixos/modules/programs/wavemon.nix28
-rw-r--r--nixpkgs/nixos/modules/programs/way-cooler.nix78
-rw-r--r--nixpkgs/nixos/modules/programs/waybar.nix20
-rw-r--r--nixpkgs/nixos/modules/programs/wireshark.nix42
-rw-r--r--nixpkgs/nixos/modules/programs/xfs_quota.nix110
-rw-r--r--nixpkgs/nixos/modules/programs/xonsh.nix60
-rw-r--r--nixpkgs/nixos/modules/programs/xss-lock.nix44
-rw-r--r--nixpkgs/nixos/modules/programs/yabar.nix162
-rw-r--r--nixpkgs/nixos/modules/programs/zmap.nix18
-rw-r--r--nixpkgs/nixos/modules/programs/zsh/oh-my-zsh.nix138
-rw-r--r--nixpkgs/nixos/modules/programs/zsh/oh-my-zsh.xml155
-rw-r--r--nixpkgs/nixos/modules/programs/zsh/zinputrc42
-rw-r--r--nixpkgs/nixos/modules/programs/zsh/zsh-autoenv.nix28
-rw-r--r--nixpkgs/nixos/modules/programs/zsh/zsh-autosuggestions.nix60
-rw-r--r--nixpkgs/nixos/modules/programs/zsh/zsh-syntax-highlighting.nix100
-rw-r--r--nixpkgs/nixos/modules/programs/zsh/zsh.nix238
84 files changed, 5689 insertions, 0 deletions
diff --git a/nixpkgs/nixos/modules/programs/adb.nix b/nixpkgs/nixos/modules/programs/adb.nix
new file mode 100644
index 000000000000..250d8c252a3b
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/adb.nix
@@ -0,0 +1,29 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+  meta.maintainers = [ maintainers.mic92 ];
+
+  ###### interface
+  options = {
+    programs.adb = {
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Whether to configure system to use Android Debug Bridge (adb).
+          To grant access to a user, it must be part of adbusers group:
+          <code>users.users.alice.extraGroups = ["adbusers"];</code>
+        '';
+      };
+    };
+  };
+
+  ###### implementation
+  config = mkIf config.programs.adb.enable {
+    services.udev.packages = [ pkgs.android-udev-rules ];
+    environment.systemPackages = [ pkgs.androidenv.androidPkgs_9_0.platform-tools ];
+    users.groups.adbusers = {};
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/atop.nix b/nixpkgs/nixos/modules/programs/atop.nix
new file mode 100644
index 000000000000..4651cdb76e0b
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/atop.nix
@@ -0,0 +1,36 @@
+# Global configuration for atop.
+
+{ config, lib, ... }:
+
+with lib;
+
+let cfg = config.programs.atop;
+
+in
+{
+  ###### interface
+
+  options = {
+
+    programs.atop = {
+
+      settings = mkOption {
+        type = types.attrs;
+        default = {};
+        example = {
+          flags = "a1f";
+          interval = 5;
+        };
+        description = ''
+          Parameters to be written to <filename>/etc/atoprc</filename>.
+        '';
+      };
+
+    };
+  };
+
+  config = mkIf (cfg.settings != {}) {
+    environment.etc."atoprc".text =
+      concatStrings (mapAttrsToList (n: v: "${n} ${toString v}\n") cfg.settings);
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/autojump.nix b/nixpkgs/nixos/modules/programs/autojump.nix
new file mode 100644
index 000000000000..3a8feec4bb45
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/autojump.nix
@@ -0,0 +1,33 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.autojump;
+  prg = config.programs;
+in
+{
+  options = {
+    programs.autojump = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable autojump.
+        '';
+      };
+    };
+  }; 
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    environment.pathsToLink = [ "/share/autojump" ];
+    environment.systemPackages = [ pkgs.autojump ];
+
+    programs.bash.interactiveShellInit = "source ${pkgs.autojump}/share/autojump/autojump.bash"; 
+    programs.zsh.interactiveShellInit = mkIf prg.zsh.enable "source ${pkgs.autojump}/share/autojump/autojump.zsh";
+    programs.fish.interactiveShellInit = mkIf prg.fish.enable "source ${pkgs.autojump}/share/autojump/autojump.fish";
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/bash/bash.nix b/nixpkgs/nixos/modules/programs/bash/bash.nix
new file mode 100644
index 000000000000..a7e57b8608d7
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/bash/bash.nix
@@ -0,0 +1,236 @@
+# This module defines global configuration for the Bash shell, in
+# particular /etc/bashrc and /etc/profile.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfge = config.environment;
+
+  cfg = config.programs.bash;
+
+  bashCompletion = optionalString cfg.enableCompletion ''
+    # Check whether we're running a version of Bash that has support for
+    # programmable completion. If we do, enable all modules installed in
+    # the system and user profile in obsolete /etc/bash_completion.d/
+    # directories. Bash loads completions in all
+    # $XDG_DATA_DIRS/bash-completion/completions/
+    # on demand, so they do not need to be sourced here.
+    if shopt -q progcomp &>/dev/null; then
+      . "${pkgs.bash-completion}/etc/profile.d/bash_completion.sh"
+      nullglobStatus=$(shopt -p nullglob)
+      shopt -s nullglob
+      for p in $NIX_PROFILES; do
+        for m in "$p/etc/bash_completion.d/"*; do
+          . $m
+        done
+      done
+      eval "$nullglobStatus"
+      unset nullglobStatus p m
+    fi
+  '';
+
+  bashAliases = concatStringsSep "\n" (
+    mapAttrsFlatten (k: v: "alias ${k}=${escapeShellArg v}")
+      (filterAttrs (k: v: v != null) cfg.shellAliases)
+  );
+
+in
+
+{
+  options = {
+
+    programs.bash = {
+
+      /*
+      enable = mkOption {
+        default = true;
+        description = ''
+          Whenever to configure Bash as an interactive shell.
+          Note that this tries to make Bash the default
+          <option>users.defaultUserShell</option>,
+          which in turn means that you might need to explicitly
+          set this variable if you have another shell configured
+          with NixOS.
+        '';
+        type = types.bool;
+      };
+      */
+
+      shellAliases = mkOption {
+        default = {};
+        description = ''
+          Set of aliases for bash shell, which overrides <option>environment.shellAliases</option>.
+          See <option>environment.shellAliases</option> for an option format description.
+        '';
+        type = with types; attrsOf (nullOr (either str path));
+      };
+
+      shellInit = mkOption {
+        default = "";
+        description = ''
+          Shell script code called during bash shell initialisation.
+        '';
+        type = types.lines;
+      };
+
+      loginShellInit = mkOption {
+        default = "";
+        description = ''
+          Shell script code called during login bash shell initialisation.
+        '';
+        type = types.lines;
+      };
+
+      interactiveShellInit = mkOption {
+        default = "";
+        description = ''
+          Shell script code called during interactive bash shell initialisation.
+        '';
+        type = types.lines;
+      };
+
+      promptInit = mkOption {
+        default = ''
+          # Provide a nice prompt if the terminal supports it.
+          if [ "$TERM" != "dumb" -o -n "$INSIDE_EMACS" ]; then
+            PROMPT_COLOR="1;31m"
+            let $UID && PROMPT_COLOR="1;32m"
+            if [ -n "$INSIDE_EMACS" ]; then
+              # Emacs term mode doesn't support xterm title escape sequence (\e]0;)
+              PS1="\n\[\033[$PROMPT_COLOR\][\u@\h:\w]\\$\[\033[0m\] "
+            else
+              PS1="\n\[\033[$PROMPT_COLOR\][\[\e]0;\u@\h: \w\a\]\u@\h:\w]\\$\[\033[0m\] "
+            fi
+            if test "$TERM" = "xterm"; then
+              PS1="\[\033]2;\h:\u:\w\007\]$PS1"
+            fi
+          fi
+        '';
+        description = ''
+          Shell script code used to initialise the bash prompt.
+        '';
+        type = types.lines;
+      };
+
+      enableCompletion = mkOption {
+        default = true;
+        description = ''
+          Enable Bash completion for all interactive bash shells.
+        '';
+        type = types.bool;
+      };
+
+    };
+
+  };
+
+  config = /* mkIf cfg.enable */ {
+
+    programs.bash = {
+
+      shellAliases = mapAttrs (name: mkDefault) cfge.shellAliases;
+
+      shellInit = ''
+        if [ -z "$__NIXOS_SET_ENVIRONMENT_DONE" ]; then
+            . ${config.system.build.setEnvironment}
+        fi
+
+        ${cfge.shellInit}
+      '';
+
+      loginShellInit = cfge.loginShellInit;
+
+      interactiveShellInit = ''
+        # Check the window size after every command.
+        shopt -s checkwinsize
+
+        # Disable hashing (i.e. caching) of command lookups.
+        set +h
+
+        ${cfg.promptInit}
+        ${bashCompletion}
+        ${bashAliases}
+
+        ${cfge.interactiveShellInit}
+      '';
+
+    };
+
+    environment.etc."profile".text =
+      ''
+        # /etc/profile: DO NOT EDIT -- this file has been generated automatically.
+        # This file is read for login shells.
+
+        # Only execute this file once per shell.
+        if [ -n "$__ETC_PROFILE_SOURCED" ]; then return; fi
+        __ETC_PROFILE_SOURCED=1
+
+        # Prevent this file from being sourced by interactive non-login child shells.
+        export __ETC_PROFILE_DONE=1
+
+        ${cfg.shellInit}
+        ${cfg.loginShellInit}
+
+        # Read system-wide modifications.
+        if test -f /etc/profile.local; then
+            . /etc/profile.local
+        fi
+
+        if [ -n "''${BASH_VERSION:-}" ]; then
+            . /etc/bashrc
+        fi
+      '';
+
+    environment.etc."bashrc".text =
+      ''
+        # /etc/bashrc: DO NOT EDIT -- this file has been generated automatically.
+
+        # Only execute this file once per shell.
+        if [ -n "$__ETC_BASHRC_SOURCED" -o -n "$NOSYSBASHRC" ]; then return; fi
+        __ETC_BASHRC_SOURCED=1
+
+        # If the profile was not loaded in a parent process, source
+        # it.  But otherwise don't do it because we don't want to
+        # clobber overridden values of $PATH, etc.
+        if [ -z "$__ETC_PROFILE_DONE" ]; then
+            . /etc/profile
+        fi
+
+        # We are not always an interactive shell.
+        if [ -n "$PS1" ]; then
+            ${cfg.interactiveShellInit}
+        fi
+
+        # Read system-wide modifications.
+        if test -f /etc/bashrc.local; then
+            . /etc/bashrc.local
+        fi
+      '';
+
+    # Configuration for readline in bash. We use "option default"
+    # priority to allow user override using both .text and .source.
+    environment.etc."inputrc".source = mkOptionDefault ./inputrc;
+
+    users.defaultUserShell = mkDefault pkgs.bashInteractive;
+
+    environment.pathsToLink = optionals cfg.enableCompletion [
+      "/etc/bash_completion.d"
+      "/share/bash-completion"
+    ];
+
+    environment.systemPackages = optional cfg.enableCompletion
+      pkgs.nix-bash-completions;
+
+    environment.shells =
+      [ "/run/current-system/sw/bin/bash"
+        "/run/current-system/sw/bin/sh"
+        "${pkgs.bashInteractive}/bin/bash"
+        "${pkgs.bashInteractive}/bin/sh"
+      ];
+
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/bash/inputrc b/nixpkgs/nixos/modules/programs/bash/inputrc
new file mode 100644
index 000000000000..f339eb649ed8
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/bash/inputrc
@@ -0,0 +1,37 @@
+# inputrc borrowed from CentOS (RHEL).
+
+set bell-style none
+
+set meta-flag on
+set input-meta on
+set convert-meta off
+set output-meta on
+set colored-stats on
+
+#set mark-symlinked-directories on
+
+$if mode=emacs
+
+# for linux console and RH/Debian xterm
+"\e[1~": beginning-of-line
+"\e[4~": end-of-line
+"\e[5~": beginning-of-history
+"\e[6~": end-of-history
+"\e[3~": delete-char
+"\e[2~": quoted-insert
+"\e[5C": forward-word
+"\e[5D": backward-word
+"\e[1;5C": forward-word
+"\e[1;5D": backward-word
+
+# for rxvt
+"\e[8~": end-of-line
+
+# for non RH/Debian xterm, can't hurt for RH/DEbian xterm
+"\eOH": beginning-of-line
+"\eOF": end-of-line
+
+# for freebsd console
+"\e[H": beginning-of-line
+"\e[F": end-of-line
+$endif
diff --git a/nixpkgs/nixos/modules/programs/bcc.nix b/nixpkgs/nixos/modules/programs/bcc.nix
new file mode 100644
index 000000000000..d76249bb5cab
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/bcc.nix
@@ -0,0 +1,9 @@
+{ config, lib, ... }:
+{
+  options.programs.bcc.enable = lib.mkEnableOption "bcc";
+
+  config = lib.mkIf config.programs.bcc.enable {
+    environment.systemPackages = [ config.boot.kernelPackages.bcc ];
+    boot.extraModulePackages = [ config.boot.kernelPackages.bcc ];
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/blcr.nix b/nixpkgs/nixos/modules/programs/blcr.nix
new file mode 100644
index 000000000000..804e1d01f12b
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/blcr.nix
@@ -0,0 +1,27 @@
+{ config, lib, ... }:
+
+let
+  inherit (lib) mkOption mkIf;
+  cfg = config.environment.blcr;
+  blcrPkg = config.boot.kernelPackages.blcr;
+in
+
+{
+  ###### interface
+
+  options = {
+    environment.blcr.enable = mkOption {
+      default = false;
+      description =
+        "Whether to enable support for the BLCR checkpointing tool.";
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    boot.kernelModules = [ "blcr" "blcr_imports" ];
+    boot.extraModulePackages = [ blcrPkg ];
+    environment.systemPackages = [ blcrPkg ];
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/browserpass.nix b/nixpkgs/nixos/modules/programs/browserpass.nix
new file mode 100644
index 000000000000..e1456d3c1848
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/browserpass.nix
@@ -0,0 +1,32 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+
+  options.programs.browserpass.enable = mkEnableOption "Browserpass native messaging host";
+
+  config = mkIf config.programs.browserpass.enable {
+    environment.etc = let
+      appId = "com.github.browserpass.native.json";
+      source = part: "${pkgs.browserpass}/lib/browserpass/${part}/${appId}";
+    in {
+      # chromium
+      "chromium/native-messaging-hosts/${appId}".source = source "hosts/chromium";
+      "chromium/policies/managed/${appId}".source = source "policies/chromium";
+
+      # chrome
+      "opt/chrome/native-messaging-hosts/${appId}".source = source "hosts/chromium";
+      "opt/chrome/policies/managed/${appId}".source = source "policies/chromium";
+
+      # vivaldi
+      "opt/vivaldi/native-messaging-hosts/${appId}".source = source "hosts/chromium";
+      "opt/vivaldi/policies/managed/${appId}".source = source "policies/chromium";
+
+      # brave
+      "opt/brave/native-messaging-hosts/${appId}".source = source "hosts/chromium";
+      "opt/brave/policies/managed/${appId}".source = source "policies/chromium";
+    };
+    nixpkgs.config.firefox.enableBrowserpass = true;
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/captive-browser.nix b/nixpkgs/nixos/modules/programs/captive-browser.nix
new file mode 100644
index 000000000000..55d474e5c9db
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/captive-browser.nix
@@ -0,0 +1,122 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.captive-browser;
+in
+{
+  ###### interface
+
+  options = {
+    programs.captive-browser = {
+      enable = mkEnableOption "captive browser";
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.captive-browser;
+        defaultText = "pkgs.captive-browser";
+        description = "Which package to use for captive-browser";
+      };
+
+      interface = mkOption {
+        type = types.str;
+        description = "your public network interface (wlp3s0, wlan0, eth0, ...)";
+      };
+
+      # the options below are the same as in "captive-browser.toml"
+      browser = mkOption {
+        type = types.str;
+        default = concatStringsSep " " [ ''${pkgs.chromium}/bin/chromium''
+                                         ''--user-data-dir=$HOME/.chromium-captive''
+                                         ''--proxy-server="socks5://$PROXY"''
+                                         ''--host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE localhost"''
+                                         ''--no-first-run''
+                                         ''--new-window''
+                                         ''--incognito''
+                                         ''http://cache.nixos.org/''
+                                       ];
+        description = ''
+          The shell (/bin/sh) command executed once the proxy starts.
+          When browser exits, the proxy exits. An extra env var PROXY is available.
+
+          Here, we use a separate Chrome instance in Incognito mode, so that
+          it can run (and be waited for) alongside the default one, and that
+          it maintains no state across runs. To configure this browser open a
+          normal window in it, settings will be preserved.
+
+          @volth: chromium is to open a plain HTTP (not HTTPS nor redirect to HTTPS!) website.
+                  upstream uses http://example.com but I have seen captive portals whose DNS server resolves "example.com" to 127.0.0.1
+        '';
+      };
+
+      dhcp-dns = mkOption {
+        type = types.str;
+        description = ''
+          The shell (/bin/sh) command executed to obtain the DHCP
+          DNS server address. The first match of an IPv4 regex is used.
+          IPv4 only, because let's be real, it's a captive portal.
+        '';
+      };
+
+      socks5-addr = mkOption {
+        type = types.str;
+        default = "localhost:1666";
+        description = ''the listen address for the SOCKS5 proxy server'';
+      };
+
+      bindInterface = mkOption {
+        default = true;
+        type = types.bool;
+        description = ''
+          Binds <package>captive-browser</package> to the network interface declared in
+          <literal>cfg.interface</literal>. This can be used to avoid collisions
+          with private subnets.
+        '';
+      };
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    programs.captive-browser.dhcp-dns = mkOptionDefault (
+      if config.networking.networkmanager.enable then
+        "${pkgs.networkmanager}/bin/nmcli dev show ${escapeShellArg cfg.interface} | ${pkgs.gnugrep}/bin/fgrep IP4.DNS"
+      else if config.networking.dhcpcd.enable then
+        "${pkgs.dhcpcd}/bin/dhcpcd -U ${escapeShellArg cfg.interface} | ${pkgs.gnugrep}/bin/fgrep domain_name_servers"
+      else if config.networking.useNetworkd then
+        "${cfg.package}/bin/systemd-networkd-dns ${escapeShellArg cfg.interface}"
+      else
+        "${config.security.wrapperDir}/udhcpc --quit --now -f -i ${escapeShellArg cfg.interface} -O dns --script ${
+            pkgs.writeScript "udhcp-script" ''
+              #!/bin/sh
+              if [ "$1" = bound ]; then
+                echo "$dns"
+              fi
+            ''}"
+    );
+
+    security.wrappers.udhcpc = {
+      capabilities  = "cap_net_raw+p";
+      source        = "${pkgs.busybox}/bin/udhcpc";
+    };
+
+    security.wrappers.captive-browser = {
+      capabilities  = "cap_net_raw+p";
+      source        = pkgs.writeScript "captive-browser" ''
+                        #!${pkgs.bash}/bin/bash
+                        export XDG_CONFIG_HOME=${pkgs.writeTextDir "captive-browser.toml" ''
+                                                  browser = """${cfg.browser}"""
+                                                  dhcp-dns = """${cfg.dhcp-dns}"""
+                                                  socks5-addr = """${cfg.socks5-addr}"""
+                                                  ${optionalString cfg.bindInterface ''
+                                                    bind-device = """${cfg.interface}"""
+                                                  ''}
+                                                ''}
+                        exec ${cfg.package}/bin/captive-browser
+                      '';
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/ccache.nix b/nixpkgs/nixos/modules/programs/ccache.nix
new file mode 100644
index 000000000000..874774c72b47
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/ccache.nix
@@ -0,0 +1,83 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+let
+  cfg = config.programs.ccache;
+in {
+  options.programs.ccache = {
+    # host configuration
+    enable = mkEnableOption "CCache";
+    cacheDir = mkOption {
+      type = types.path;
+      description = "CCache directory";
+      default = "/var/cache/ccache";
+    };
+    # target configuration
+    packageNames = mkOption {
+      type = types.listOf types.str;
+      description = "Nix top-level packages to be compiled using CCache";
+      default = [];
+      example = [ "wxGTK30" "qt48" "ffmpeg_3_3" "libav_all" ];
+    };
+  };
+
+  config = mkMerge [
+    # host configuration
+    (mkIf cfg.enable {
+      systemd.tmpfiles.rules = [ "d ${cfg.cacheDir} 0770 root nixbld -" ];
+
+      # "nix-ccache --show-stats" and "nix-ccache --clear"
+      security.wrappers.nix-ccache = {
+        group = "nixbld";
+        setgid = true;
+        source = pkgs.writeScript "nix-ccache.pl" ''
+          #!${pkgs.perl}/bin/perl
+
+          %ENV=( CCACHE_DIR => '${cfg.cacheDir}' );
+          sub untaint {
+            my $v = shift;
+            return '-C' if $v eq '-C' || $v eq '--clear';
+            return '-V' if $v eq '-V' || $v eq '--version';
+            return '-s' if $v eq '-s' || $v eq '--show-stats';
+            return '-z' if $v eq '-z' || $v eq '--zero-stats';
+            exec('${pkgs.ccache}/bin/ccache', '-h');
+          }
+          exec('${pkgs.ccache}/bin/ccache', map { untaint $_ } @ARGV);
+        '';
+      };
+    })
+
+    # target configuration
+    (mkIf (cfg.packageNames != []) {
+      nixpkgs.overlays = [
+        (self: super: genAttrs cfg.packageNames (pn: super.${pn}.override { stdenv = builtins.trace "with ccache: ${pn}" self.ccacheStdenv; }))
+
+        (self: super: {
+          ccacheWrapper = super.ccacheWrapper.override {
+            extraConfig = ''
+              export CCACHE_COMPRESS=1
+              export CCACHE_DIR="${cfg.cacheDir}"
+              export CCACHE_UMASK=007
+              if [ ! -d "$CCACHE_DIR" ]; then
+                echo "====="
+                echo "Directory '$CCACHE_DIR' does not exist"
+                echo "Please create it with:"
+                echo "  sudo mkdir -m0770 '$CCACHE_DIR'"
+                echo "  sudo chown root:nixbld '$CCACHE_DIR'"
+                echo "====="
+                exit 1
+              fi
+              if [ ! -w "$CCACHE_DIR" ]; then
+                echo "====="
+                echo "Directory '$CCACHE_DIR' is not accessible for user $(whoami)"
+                echo "Please verify its access permissions"
+                echo "====="
+                exit 1
+              fi
+            '';
+          };
+        })
+      ];
+    })
+  ];
+}
\ No newline at end of file
diff --git a/nixpkgs/nixos/modules/programs/cdemu.nix b/nixpkgs/nixos/modules/programs/cdemu.nix
new file mode 100644
index 000000000000..6a0185d362c5
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/cdemu.nix
@@ -0,0 +1,58 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.programs.cdemu;
+in {
+
+  options = {
+    programs.cdemu = {
+      enable = mkOption {
+        default = false;
+        description = ''
+          <command>cdemu</command> for members of
+          <option>programs.cdemu.group</option>.
+        '';
+      };
+      group = mkOption {
+        default = "cdrom";
+        description = ''
+          Group that users must be in to use <command>cdemu</command>.
+        '';
+      };
+      gui = mkOption {
+        default = true;
+        description = ''
+          Whether to install the <command>cdemu</command> GUI (gCDEmu).
+        '';
+      };
+      image-analyzer = mkOption {
+        default = true;
+        description = ''
+          Whether to install the image analyzer.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    boot = {
+      extraModulePackages = [ config.boot.kernelPackages.vhba ];
+      kernelModules = [ "vhba" ];
+    };
+
+    services = {
+      udev.extraRules = ''
+        KERNEL=="vhba_ctl", MODE="0660", OWNER="root", GROUP="${cfg.group}"
+      '';
+      dbus.packages = [ pkgs.cdemu-daemon ];
+    };
+
+    environment.systemPackages =
+      [ pkgs.cdemu-daemon pkgs.cdemu-client ]
+      ++ optional cfg.gui pkgs.gcdemu
+      ++ optional cfg.image-analyzer pkgs.image-analyzer;
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/chromium.nix b/nixpkgs/nixos/modules/programs/chromium.nix
new file mode 100644
index 000000000000..41c49db8c71c
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/chromium.nix
@@ -0,0 +1,89 @@
+{ config, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.chromium;
+
+  defaultProfile = filterAttrs (k: v: v != null) {
+    HomepageLocation = cfg.homepageLocation;
+    DefaultSearchProviderSearchURL = cfg.defaultSearchProviderSearchURL;
+    DefaultSearchProviderSuggestURL = cfg.defaultSearchProviderSuggestURL;
+    ExtensionInstallForcelist = map (extension:
+      "${extension};https://clients2.google.com/service/update2/crx"
+    ) cfg.extensions;
+  };
+in
+
+{
+  ###### interface
+
+  options = {
+    programs.chromium = {
+      enable = mkEnableOption "<command>chromium</command> policies";
+
+      extensions = mkOption {
+        type = types.listOf types.str;
+        description = ''
+          List of chromium extensions to install.
+          For list of plugins ids see id in url of extensions on
+          <link xlink:href="https://chrome.google.com/webstore/category/extensions">chrome web store</link>
+          page.
+        '';
+        default = [];
+        example = literalExample ''
+          [
+            "chlffgpmiacpedhhbkiomidkjlcfhogd" # pushbullet
+            "mbniclmhobmnbdlbpiphghaielnnpgdp" # lightshot
+            "gcbommkclmclpchllfjekcdonpmejbdp" # https everywhere
+            "cjpalhdlnbpafiamejdnhcphjbkeiagm" # ublock origin
+          ]
+        '';
+      };
+
+      homepageLocation = mkOption {
+        type = types.nullOr types.str;
+        description = "Chromium default homepage";
+        default = null;
+        example = "https://nixos.org";
+      };
+
+      defaultSearchProviderSearchURL = mkOption {
+        type = types.nullOr types.str;
+        description = "Chromium default search provider url.";
+        default = null;
+        example =
+          "https://encrypted.google.com/search?q={searchTerms}&{google:RLZ}{google:originalQueryForSuggestion}{google:assistedQueryStats}{google:searchFieldtrialParameter}{google:searchClient}{google:sourceId}{google:instantExtendedEnabledParameter}ie={inputEncoding}";
+      };
+
+      defaultSearchProviderSuggestURL = mkOption {
+        type = types.nullOr types.str;
+        description = "Chromium default search provider url for suggestions.";
+        default = null;
+        example =
+          "https://encrypted.google.com/complete/search?output=chrome&q={searchTerms}";
+      };
+
+      extraOpts = mkOption {
+        type = types.attrs;
+        description = ''
+          Extra chromium policy options, see
+          <link xlink:href="https://www.chromium.org/administrators/policy-list-3">https://www.chromium.org/administrators/policy-list-3</link>
+          for a list of avalible options
+        '';
+        default = {};
+      };
+    };
+  };
+
+  ###### implementation
+
+  config = lib.mkIf cfg.enable {
+    # for chromium
+    environment.etc."chromium/policies/managed/default.json".text = builtins.toJSON defaultProfile;
+    environment.etc."chromium/policies/managed/extra.json".text = builtins.toJSON cfg.extraOpts;
+    # for google-chrome https://www.chromium.org/administrators/linux-quick-start
+    environment.etc."opt/chrome/policies/managed/default.json".text = builtins.toJSON defaultProfile;
+    environment.etc."opt/chrome/policies/managed/extra.json".text = builtins.toJSON cfg.extraOpts;
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/clickshare.nix b/nixpkgs/nixos/modules/programs/clickshare.nix
new file mode 100644
index 000000000000..9980a7daf525
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/clickshare.nix
@@ -0,0 +1,21 @@
+{ config, lib, pkgs, ... }:
+
+{
+
+  options.programs.clickshare-csc1.enable =
+    lib.options.mkEnableOption ''
+      Barco ClickShare CSC-1 driver/client.
+      This allows users in the <literal>clickshare</literal>
+      group to access and use a ClickShare USB dongle
+      that is connected to the machine
+    '';
+
+  config = lib.modules.mkIf config.programs.clickshare-csc1.enable {
+    environment.systemPackages = [ pkgs.clickshare-csc1 ];
+    services.udev.packages = [ pkgs.clickshare-csc1 ];
+    users.groups.clickshare = {};
+  };
+
+  meta.maintainers = [ lib.maintainers.yarny ];
+
+}
diff --git a/nixpkgs/nixos/modules/programs/command-not-found/command-not-found.nix b/nixpkgs/nixos/modules/programs/command-not-found/command-not-found.nix
new file mode 100644
index 000000000000..656c255fcb18
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/command-not-found/command-not-found.nix
@@ -0,0 +1,95 @@
+# This module provides suggestions of packages to install if the user
+# tries to run a missing command in Bash.  This is implemented using a
+# SQLite database that maps program names to Nix package names (e.g.,
+# "pdflatex" is mapped to "tetex").
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.command-not-found;
+  commandNotFound = pkgs.substituteAll {
+    name = "command-not-found";
+    dir = "bin";
+    src = ./command-not-found.pl;
+    isExecutable = true;
+    inherit (pkgs) perl;
+    inherit (cfg) dbPath;
+    perlFlags = concatStrings (map (path: "-I ${path}/${pkgs.perl.libPrefix} ")
+      [ pkgs.perlPackages.DBI pkgs.perlPackages.DBDSQLite pkgs.perlPackages.StringShellQuote ]);
+  };
+
+in
+
+{
+  options.programs.command-not-found = {
+
+    enable = mkOption {
+      type = types.bool;
+      default = true;
+      description = ''
+        Whether interactive shells should show which Nix package (if
+        any) provides a missing command.
+      '';
+    };
+
+    dbPath = mkOption {
+      default = "/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite" ;
+      description = ''
+        Absolute path to programs.sqlite.
+
+        By default this file will be provided by your channel
+        (nixexprs.tar.xz).
+      '';
+      type = types.path;
+    };
+  };
+
+  config = mkIf cfg.enable {
+    programs.bash.interactiveShellInit =
+      ''
+        # This function is called whenever a command is not found.
+        command_not_found_handle() {
+          local p=${commandNotFound}/bin/command-not-found
+          if [ -x $p -a -f ${cfg.dbPath} ]; then
+            # Run the helper program.
+            $p "$@"
+            # Retry the command if we just installed it.
+            if [ $? = 126 ]; then
+              "$@"
+            else
+              return 127
+            fi
+          else
+            echo "$1: command not found" >&2
+            return 127
+          fi
+        }
+      '';
+
+    programs.zsh.interactiveShellInit =
+      ''
+        # This function is called whenever a command is not found.
+        command_not_found_handler() {
+          local p=${commandNotFound}/bin/command-not-found
+          if [ -x $p -a -f ${cfg.dbPath} ]; then
+            # Run the helper program.
+            $p "$@"
+
+            # Retry the command if we just installed it.
+            if [ $? = 126 ]; then
+              "$@"
+            fi
+          else
+            # Indicate than there was an error so ZSH falls back to its default handler
+            echo "$1: command not found" >&2
+            return 127
+          fi
+        }
+      '';
+
+    environment.systemPackages = [ commandNotFound ];
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/command-not-found/command-not-found.pl b/nixpkgs/nixos/modules/programs/command-not-found/command-not-found.pl
new file mode 100644
index 000000000000..ab7aa204653c
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/command-not-found/command-not-found.pl
@@ -0,0 +1,51 @@
+#! @perl@/bin/perl -w @perlFlags@
+
+use strict;
+use DBI;
+use DBD::SQLite;
+use String::ShellQuote;
+use Config;
+
+my $program = $ARGV[0];
+
+my $dbPath = "@dbPath@";
+
+my $dbh = DBI->connect("dbi:SQLite:dbname=$dbPath", "", "")
+    or die "cannot open database `$dbPath'";
+$dbh->{RaiseError} = 0;
+$dbh->{PrintError} = 0;
+
+my $system = $ENV{"NIX_SYSTEM"} // $Config{myarchname};
+
+my $res = $dbh->selectall_arrayref(
+    "select package from Programs where system = ? and name = ?",
+    { Slice => {} }, $system, $program);
+
+if (!defined $res || scalar @$res == 0) {
+    print STDERR "$program: command not found\n";
+} elsif (scalar @$res == 1) {
+    my $package = @$res[0]->{package};
+    if ($ENV{"NIX_AUTO_INSTALL"} // "") {
+        print STDERR <<EOF;
+The program ‘$program’ is currently not installed. It is provided by
+the package ‘$package’, which I will now install for you.
+EOF
+        ;
+        exit 126 if system("nix-env", "-iA", "nixos.$package") == 0;
+    } elsif ($ENV{"NIX_AUTO_RUN"} // "") {
+        exec("nix-shell", "-p", $package, "--run", shell_quote("exec", @ARGV));
+    } else {
+        print STDERR <<EOF;
+The program ‘$program’ is currently not installed. You can install it by typing:
+  nix-env -iA nixos.$package
+EOF
+    }
+} else {
+    print STDERR <<EOF;
+The program ‘$program’ is currently not installed. It is provided by
+several packages. You can install it by typing one of the following:
+EOF
+    print STDERR "  nix-env -iA nixos.$_->{package}\n" foreach @$res;
+}
+
+exit 127;
diff --git a/nixpkgs/nixos/modules/programs/criu.nix b/nixpkgs/nixos/modules/programs/criu.nix
new file mode 100644
index 000000000000..48cf5c88a9fc
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/criu.nix
@@ -0,0 +1,26 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.programs.criu;
+in {
+
+  options = {
+    programs.criu = {
+      enable = mkOption {
+        default = false;
+        description = ''
+          Install <command>criu</command> along with necessary kernel options.
+        '';
+      };
+    };
+  };
+  config = mkIf cfg.enable {
+    system.requiredKernelConfig = with config.lib.kernelConfig; [
+      (isYes "CHECKPOINT_RESTORE")
+    ];
+    boot.kernel.features.criu = true;
+    environment.systemPackages = [ pkgs.criu ];
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/dconf.nix b/nixpkgs/nixos/modules/programs/dconf.nix
new file mode 100644
index 000000000000..b7bfb8504b6f
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/dconf.nix
@@ -0,0 +1,44 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.dconf;
+
+  mkDconfProfile = name: path:
+    { source = path; target = "dconf/profile/${name}"; };
+
+in
+{
+  ###### interface
+
+  options = {
+    programs.dconf = {
+      enable = mkEnableOption "dconf";
+
+      profiles = mkOption {
+        type = types.attrsOf types.path;
+        default = {};
+        description = "Set of dconf profile files.";
+        internal = true;
+      };
+
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf (cfg.profiles != {} || cfg.enable) {
+    environment.etc = optionals (cfg.profiles != {})
+      (mapAttrsToList mkDconfProfile cfg.profiles);
+
+    services.dbus.packages = [ pkgs.gnome3.dconf ];
+
+    environment.variables.GIO_EXTRA_MODULES = optional cfg.enable
+      "${pkgs.gnome3.dconf.lib}/lib/gio/modules";
+    # https://github.com/NixOS/nixpkgs/pull/31891
+    #environment.variables.XDG_DATA_DIRS = optional cfg.enable
+    #  "$(echo ${pkgs.gsettings-desktop-schemas}/share/gsettings-schemas/gsettings-desktop-schemas-*)";
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/digitalbitbox/default.nix b/nixpkgs/nixos/modules/programs/digitalbitbox/default.nix
new file mode 100644
index 000000000000..2fe0a14412c5
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/digitalbitbox/default.nix
@@ -0,0 +1,39 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.digitalbitbox;
+in
+
+{
+  options.programs.digitalbitbox = {
+    enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Installs the Digital Bitbox application and enables the complementary hardware module.
+      '';
+    };
+
+    package = mkOption {
+      type = types.package;
+      default = pkgs.digitalbitbox;
+      defaultText = "pkgs.digitalbitbox";
+      description = "The Digital Bitbox package to use. This can be used to install a package with udev rules that differ from the defaults.";
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ cfg.package ];
+    hardware.digitalbitbox = {
+      enable = true;
+      package = cfg.package;
+    };
+  };
+
+  meta = {
+    doc = ./doc.xml;
+    maintainers = with lib.maintainers; [ vidbina ];
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/digitalbitbox/doc.xml b/nixpkgs/nixos/modules/programs/digitalbitbox/doc.xml
new file mode 100644
index 000000000000..c63201628dbd
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/digitalbitbox/doc.xml
@@ -0,0 +1,74 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="module-programs-digitalbitbox">
+ <title>Digital Bitbox</title>
+ <para>
+  Digital Bitbox is a hardware wallet and second-factor authenticator.
+ </para>
+ <para>
+  The <literal>digitalbitbox</literal> programs module may be installed by
+  setting <literal>programs.digitalbitbox</literal> to <literal>true</literal>
+  in a manner similar to
+<programlisting>
+<xref linkend="opt-programs.digitalbitbox.enable"/> = true;
+</programlisting>
+  and bundles the <literal>digitalbitbox</literal> package (see
+  <xref
+      linkend="sec-digitalbitbox-package" />), which contains the
+  <literal>dbb-app</literal> and <literal>dbb-cli</literal> binaries, along
+  with the hardware module (see
+  <xref
+      linkend="sec-digitalbitbox-hardware-module" />) which sets up the
+  necessary udev rules to access the device.
+ </para>
+ <para>
+  Enabling the digitalbitbox module is pretty much the easiest way to get a
+  Digital Bitbox device working on your system.
+ </para>
+ <para>
+  For more information, see
+  <link xlink:href="https://digitalbitbox.com/start_linux" />.
+ </para>
+ <section xml:id="sec-digitalbitbox-package">
+  <title>Package</title>
+
+  <para>
+   The binaries, <literal>dbb-app</literal> (a GUI tool) and
+   <literal>dbb-cli</literal> (a CLI tool), are available through the
+   <literal>digitalbitbox</literal> package which could be installed as
+   follows:
+<programlisting>
+<xref linkend="opt-environment.systemPackages"/> = [
+  pkgs.digitalbitbox
+];
+</programlisting>
+  </para>
+ </section>
+ <section xml:id="sec-digitalbitbox-hardware-module">
+  <title>Hardware</title>
+
+  <para>
+   The digitalbitbox hardware package enables the udev rules for Digital Bitbox
+   devices and may be installed as follows:
+<programlisting>
+<xref linkend="opt-hardware.digitalbitbox.enable"/> = true;
+</programlisting>
+  </para>
+
+  <para>
+   In order to alter the udev rules, one may provide different values for the
+   <literal>udevRule51</literal> and <literal>udevRule52</literal> attributes
+   by means of overriding as follows:
+<programlisting>
+programs.digitalbitbox = {
+  <link linkend="opt-programs.digitalbitbox.enable">enable</link> = true;
+  <link linkend="opt-programs.digitalbitbox.package">package</link> = pkgs.digitalbitbox.override {
+    udevRule51 = "something else";
+  };
+};
+</programlisting>
+  </para>
+ </section>
+</chapter>
diff --git a/nixpkgs/nixos/modules/programs/dmrconfig.nix b/nixpkgs/nixos/modules/programs/dmrconfig.nix
new file mode 100644
index 000000000000..e48a4f318370
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/dmrconfig.nix
@@ -0,0 +1,38 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.dmrconfig;
+
+in {
+  meta.maintainers = [ maintainers.etu ];
+
+  ###### interface
+  options = {
+    programs.dmrconfig = {
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Whether to configure system to enable use of dmrconfig. This
+          enables the required udev rules and installs the program.
+        '';
+        relatedPackages = [ "dmrconfig" ];
+      };
+
+      package = mkOption {
+        default = pkgs.dmrconfig;
+        type = types.package;
+        defaultText = "pkgs.dmrconfig";
+        description = "dmrconfig derivation to use";
+      };
+    };
+  };
+
+  ###### implementation
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ cfg.package ];
+    services.udev.packages = [ cfg.package ];
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/environment.nix b/nixpkgs/nixos/modules/programs/environment.nix
new file mode 100644
index 000000000000..4d762314298d
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/environment.nix
@@ -0,0 +1,61 @@
+# This module defines a standard configuration for NixOS global environment.
+
+# Most of the stuff here should probably be moved elsewhere sometime.
+
+{ config, lib, ... }:
+
+with lib;
+
+let
+
+  cfg = config.environment;
+
+in
+
+{
+
+  config = {
+
+    environment.variables =
+      { NIXPKGS_CONFIG = "/etc/nix/nixpkgs-config.nix";
+        PAGER = mkDefault "less -R";
+        EDITOR = mkDefault "nano";
+        XCURSOR_PATH = [ "$HOME/.icons" ];
+      };
+
+    environment.profiles = mkAfter
+      [ "/nix/var/nix/profiles/default"
+        "/run/current-system/sw"
+      ];
+
+    # TODO: move most of these elsewhere
+    environment.profileRelativeEnvVars =
+      { PATH = [ "/bin" ];
+        INFOPATH = [ "/info" "/share/info" ];
+        KDEDIRS = [ "" ];
+        STRIGI_PLUGIN_PATH = [ "/lib/strigi/" ];
+        QT_PLUGIN_PATH = [ "/lib/qt4/plugins" "/lib/kde4/plugins" ];
+        QTWEBKIT_PLUGIN_PATH = [ "/lib/mozilla/plugins/" ];
+        GTK_PATH = [ "/lib/gtk-2.0" "/lib/gtk-3.0" ];
+        XDG_CONFIG_DIRS = [ "/etc/xdg" ];
+        XDG_DATA_DIRS = [ "/share" ];
+        MOZ_PLUGIN_PATH = [ "/lib/mozilla/plugins" ];
+        LIBEXEC_PATH = [ "/lib/libexec" ];
+      };
+
+    environment.extraInit =
+      ''
+         unset ASPELL_CONF
+         for i in ${concatStringsSep " " (reverseList cfg.profiles)} ; do
+           if [ -d "$i/lib/aspell" ]; then
+             export ASPELL_CONF="dict-dir $i/lib/aspell"
+           fi
+         done
+
+         export NIX_USER_PROFILE_DIR="/nix/var/nix/profiles/per-user/$USER"
+         export NIX_PROFILES="${concatStringsSep " " (reverseList cfg.profiles)}"
+      '';
+
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/evince.nix b/nixpkgs/nixos/modules/programs/evince.nix
new file mode 100644
index 000000000000..473fddb09d02
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/evince.nix
@@ -0,0 +1,42 @@
+# Evince.
+
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+{
+
+  # Added 2019-08-09
+  imports = [
+    (mkRenamedOptionModule
+      [ "services" "gnome3" "evince" "enable" ]
+      [ "programs" "evince" "enable" ])
+  ];
+
+  ###### interface
+
+  options = {
+
+    programs.evince = {
+
+      enable = mkEnableOption
+        "Evince, the GNOME document viewer";
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf config.programs.evince.enable {
+
+    environment.systemPackages = [ pkgs.evince ];
+
+    services.dbus.packages = [ pkgs.evince ];
+
+    systemd.packages = [ pkgs.evince ];
+
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/file-roller.nix b/nixpkgs/nixos/modules/programs/file-roller.nix
new file mode 100644
index 000000000000..64f6a94e7641
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/file-roller.nix
@@ -0,0 +1,39 @@
+# File Roller.
+
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+{
+
+  # Added 2019-08-09
+  imports = [
+    (mkRenamedOptionModule
+      [ "services" "gnome3" "file-roller" "enable" ]
+      [ "programs" "file-roller" "enable" ])
+  ];
+
+  ###### interface
+
+  options = {
+
+    programs.file-roller = {
+
+      enable = mkEnableOption "File Roller, an archive manager for GNOME";
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf config.programs.file-roller.enable {
+
+    environment.systemPackages = [ pkgs.gnome3.file-roller ];
+
+    services.dbus.packages = [ pkgs.gnome3.file-roller ];
+
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/firejail.nix b/nixpkgs/nixos/modules/programs/firejail.nix
new file mode 100644
index 000000000000..46ee4bc0f7a0
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/firejail.nix
@@ -0,0 +1,48 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.firejail;
+
+  wrappedBins = pkgs.stdenv.mkDerivation rec {
+    name = "firejail-wrapped-binaries";
+    nativeBuildInputs = with pkgs; [ makeWrapper ];
+    buildCommand = ''
+      mkdir -p $out/bin
+      ${lib.concatStringsSep "\n" (lib.mapAttrsToList (command: binary: ''
+      cat <<_EOF >$out/bin/${command}
+      #!${pkgs.stdenv.shell} -e
+      /run/wrappers/bin/firejail ${binary} "\$@"
+      _EOF
+      chmod 0755 $out/bin/${command}
+      '') cfg.wrappedBinaries)}
+    '';
+  };
+
+in {
+  options.programs.firejail = {
+    enable = mkEnableOption "firejail";
+
+    wrappedBinaries = mkOption {
+      type = types.attrs;
+      default = {};
+      description = ''
+        Wrap the binaries in firejail and place them in the global path.
+        </para>
+        <para>
+        You will get file collisions if you put the actual application binary in
+        the global environment and applications started via .desktop files are
+        not wrapped if they specify the absolute path to the binary.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    security.wrappers.firejail.source = "${lib.getBin pkgs.firejail}/bin/firejail";
+
+    environment.systemPackages = [ wrappedBins ];
+  };
+
+  meta.maintainers = with maintainers; [ peterhoeg ];
+}
diff --git a/nixpkgs/nixos/modules/programs/fish.nix b/nixpkgs/nixos/modules/programs/fish.nix
new file mode 100644
index 000000000000..87f6816e4ac0
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/fish.nix
@@ -0,0 +1,240 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfge = config.environment;
+
+  cfg = config.programs.fish;
+
+  fishAliases = concatStringsSep "\n" (
+    mapAttrsFlatten (k: v: "alias ${k} ${escapeShellArg v}")
+      (filterAttrs (k: v: v != null) cfg.shellAliases)
+  );
+
+in
+
+{
+
+  options = {
+
+    programs.fish = {
+
+      enable = mkOption {
+        default = false;
+        description = ''
+          Whether to configure fish as an interactive shell.
+        '';
+        type = types.bool;
+      };
+
+      vendor.config.enable = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Whether fish should source configuration snippets provided by other packages.
+        '';
+      };
+
+      vendor.completions.enable = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Whether fish should use completion files provided by other packages.
+        '';
+      };
+
+      vendor.functions.enable = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Whether fish should autoload fish functions provided by other packages.
+        '';
+      };
+
+      shellAliases = mkOption {
+        default = {};
+        description = ''
+          Set of aliases for fish shell, which overrides <option>environment.shellAliases</option>.
+          See <option>environment.shellAliases</option> for an option format description.
+        '';
+        type = with types; attrsOf (nullOr (either str path));
+      };
+
+      shellInit = mkOption {
+        default = "";
+        description = ''
+          Shell script code called during fish shell initialisation.
+        '';
+        type = types.lines;
+      };
+
+      loginShellInit = mkOption {
+        default = "";
+        description = ''
+          Shell script code called during fish login shell initialisation.
+        '';
+        type = types.lines;
+      };
+
+      interactiveShellInit = mkOption {
+        default = "";
+        description = ''
+          Shell script code called during interactive fish shell initialisation.
+        '';
+        type = types.lines;
+      };
+
+      promptInit = mkOption {
+        default = "";
+        description = ''
+          Shell script code used to initialise fish prompt.
+        '';
+        type = types.lines;
+      };
+
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    programs.fish.shellAliases = mapAttrs (name: mkDefault) cfge.shellAliases;
+
+    environment.etc."fish/foreign-env/shellInit".text = cfge.shellInit;
+    environment.etc."fish/foreign-env/loginShellInit".text = cfge.loginShellInit;
+    environment.etc."fish/foreign-env/interactiveShellInit".text = cfge.interactiveShellInit;
+
+    environment.etc."fish/nixos-env-preinit.fish".text = ''
+      # This happens before $__fish_datadir/config.fish sets fish_function_path, so it is currently
+      # unset. We set it and then completely erase it, leaving its configuration to $__fish_datadir/config.fish
+      set fish_function_path ${pkgs.fish-foreign-env}/share/fish-foreign-env/functions $__fish_datadir/functions
+
+      # source the NixOS environment config
+      if [ -z "$__NIXOS_SET_ENVIRONMENT_DONE" ]
+          fenv source ${config.system.build.setEnvironment}
+      end
+
+      # clear fish_function_path so that it will be correctly set when we return to $__fish_datadir/config.fish
+      set -e fish_function_path
+    '';
+
+    environment.etc."fish/config.fish".text = ''
+      # /etc/fish/config.fish: DO NOT EDIT -- this file has been generated automatically.
+
+      # if we haven't sourced the general config, do it
+      if not set -q __fish_nixos_general_config_sourced
+        set fish_function_path ${pkgs.fish-foreign-env}/share/fish-foreign-env/functions $fish_function_path
+        fenv source /etc/fish/foreign-env/shellInit > /dev/null
+        set -e fish_function_path[1]
+
+        ${cfg.shellInit}
+
+        # and leave a note so we don't source this config section again from
+        # this very shell (children will source the general config anew)
+        set -g __fish_nixos_general_config_sourced 1
+      end
+
+      # if we haven't sourced the login config, do it
+      status --is-login; and not set -q __fish_nixos_login_config_sourced
+      and begin
+        set fish_function_path ${pkgs.fish-foreign-env}/share/fish-foreign-env/functions $fish_function_path
+        fenv source /etc/fish/foreign-env/loginShellInit > /dev/null
+        set -e fish_function_path[1]
+
+        ${cfg.loginShellInit}
+
+        # and leave a note so we don't source this config section again from
+        # this very shell (children will source the general config anew)
+        set -g __fish_nixos_login_config_sourced 1
+      end
+
+      # if we haven't sourced the interactive config, do it
+      status --is-interactive; and not set -q __fish_nixos_interactive_config_sourced
+      and begin
+        ${fishAliases}
+
+        set fish_function_path ${pkgs.fish-foreign-env}/share/fish-foreign-env/functions $fish_function_path
+        fenv source /etc/fish/foreign-env/interactiveShellInit > /dev/null
+        set -e fish_function_path[1]
+
+        ${cfg.promptInit}
+        ${cfg.interactiveShellInit}
+
+        # and leave a note so we don't source this config section again from
+        # this very shell (children will source the general config anew,
+        # allowing configuration changes in, e.g, aliases, to propagate)
+        set -g __fish_nixos_interactive_config_sourced 1
+      end
+    '';
+
+    programs.fish.interactiveShellInit = ''
+      # add completions generated by NixOS to $fish_complete_path
+      begin
+        # joins with null byte to acommodate all characters in paths, then respectively gets all paths before (exclusive) / after (inclusive) the first one including "generated_completions",
+        # splits by null byte, and then removes all empty lines produced by using 'string'
+        set -l prev (string join0 $fish_complete_path | string match --regex "^.*?(?=\x00[^\x00]*generated_completions.*)" | string split0 | string match -er ".")
+        set -l post (string join0 $fish_complete_path | string match --regex "[^\x00]*generated_completions.*" | string split0 | string match -er ".")
+        set fish_complete_path $prev "/etc/fish/generated_completions" $post
+      end
+    '';
+
+    environment.etc."fish/generated_completions".source =
+      let
+        patchedGenerator = pkgs.stdenv.mkDerivation {
+          name = "fish_patched-completion-generator";
+          srcs = [
+            "${pkgs.fish}/share/fish/tools/create_manpage_completions.py"
+            "${pkgs.fish}/share/fish/tools/deroff.py"
+          ];
+          unpackCmd = "cp $curSrc $(basename $curSrc)";
+          sourceRoot = ".";
+          patches = [ ./fish_completion-generator.patch ]; # to prevent collisions of identical completion files
+          dontBuild = true;
+          installPhase = ''
+            mkdir -p $out
+            cp * $out/
+          '';
+          preferLocalBuild = true;
+          allowSubstitutes = false;
+        };
+        generateCompletions = package: pkgs.runCommand
+          "${package.name}_fish-completions"
+          (
+            {
+              inherit package;
+              preferLocalBuild = true;
+              allowSubstitutes = false;
+            }
+            // optionalAttrs (package ? meta.priority) { meta.priority = package.meta.priority; }
+          )
+          ''
+            mkdir -p $out
+            if [ -d $package/share/man ]; then
+              find $package/share/man -type f | xargs ${pkgs.python3.interpreter} ${patchedGenerator}/create_manpage_completions.py --directory $out >/dev/null
+            fi
+          '';
+      in
+        pkgs.buildEnv {
+          name = "system_fish-completions";
+          ignoreCollisions = true;
+          paths = map generateCompletions config.environment.systemPackages;
+        };
+
+    # include programs that bring their own completions
+    environment.pathsToLink = []
+      ++ optional cfg.vendor.config.enable "/share/fish/vendor_conf.d"
+      ++ optional cfg.vendor.completions.enable "/share/fish/vendor_completions.d"
+      ++ optional cfg.vendor.functions.enable "/share/fish/vendor_functions.d";
+
+    environment.systemPackages = [ pkgs.fish ];
+
+    environment.shells = [
+      "/run/current-system/sw/bin/fish"
+      "${pkgs.fish}/bin/fish"
+    ];
+
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/fish_completion-generator.patch b/nixpkgs/nixos/modules/programs/fish_completion-generator.patch
new file mode 100644
index 000000000000..a8c797d185a6
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/fish_completion-generator.patch
@@ -0,0 +1,11 @@
+--- a/create_manpage_completions.py
++++ b/create_manpage_completions.py
+@@ -776,8 +776,6 @@ def parse_manpage_at_path(manpage_path, output_directory):
+
+             built_command_output.insert(0, "# " + CMDNAME)
+
+-            # Output the magic word Autogenerated so we can tell if we can overwrite this
+-            built_command_output.insert(1, "# Autogenerated from man page " + manpage_path)
+             # built_command_output.insert(2, "# using " + parser.__class__.__name__) # XXX MISATTRIBUTES THE CULPABILE PARSER! Was really using Type2 but reporting TypeDeroffManParser
+
+             for line in built_command_output:
diff --git a/nixpkgs/nixos/modules/programs/freetds.nix b/nixpkgs/nixos/modules/programs/freetds.nix
new file mode 100644
index 000000000000..e0860a242b74
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/freetds.nix
@@ -0,0 +1,61 @@
+# Global configuration for freetds environment.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.environment.freetds;
+
+in
+{
+  ###### interface
+
+  options = {
+
+    environment.freetds = mkOption {
+      type = types.attrsOf types.str;
+      default = {};
+      example = literalExample ''
+        { MYDATABASE = '''
+            host = 10.0.2.100
+            port = 1433
+            tds version = 7.2
+          ''';
+        }
+      '';
+      description = 
+        ''
+        Configure freetds database entries. Each attribute denotes
+        a section within freetds.conf, and the value (a string) is the config
+        content for that section. When at least one entry is configured
+        the global environment variables FREETDSCONF, FREETDS and SYBASE
+        will be configured to allow the programs that use freetds to find the
+        library and config.
+        '';
+
+    };
+
+  };
+
+  ###### implementation
+
+  config = mkIf (length (attrNames cfg) > 0) {
+
+    environment.variables.FREETDSCONF = "/etc/freetds.conf";
+    environment.variables.FREETDS = "/etc/freetds.conf";
+    environment.variables.SYBASE = "${pkgs.freetds}";
+
+    environment.etc."freetds.conf" = { text = 
+      (concatStrings (mapAttrsToList (name: value:
+        ''
+        [${name}]
+        ${value}
+        ''
+      ) cfg));
+    };
+
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/fuse.nix b/nixpkgs/nixos/modules/programs/fuse.nix
new file mode 100644
index 000000000000..c15896efbb51
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/fuse.nix
@@ -0,0 +1,37 @@
+{ config, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.fuse;
+in {
+  meta.maintainers = with maintainers; [ primeos ];
+
+  options.programs.fuse = {
+    mountMax = mkOption {
+      # In the C code it's an "int" (i.e. signed and at least 16 bit), but
+      # negative numbers obviously make no sense:
+      type = types.ints.between 0 32767; # 2^15 - 1
+      default = 1000;
+      description = ''
+        Set the maximum number of FUSE mounts allowed to non-root users.
+      '';
+    };
+
+    userAllowOther = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Allow non-root users to specify the allow_other or allow_root mount
+        options, see mount.fuse3(8).
+      '';
+    };
+  };
+
+  config =  {
+    environment.etc."fuse.conf".text = ''
+      ${optionalString (!cfg.userAllowOther) "#"}user_allow_other
+      mount_max = ${toString cfg.mountMax}
+    '';
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/gnome-disks.nix b/nixpkgs/nixos/modules/programs/gnome-disks.nix
new file mode 100644
index 000000000000..1cf839a6ddb0
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/gnome-disks.nix
@@ -0,0 +1,46 @@
+# GNOME Disks.
+
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+{
+
+  # Added 2019-08-09
+  imports = [
+    (mkRenamedOptionModule
+      [ "services" "gnome3" "gnome-disks" "enable" ]
+      [ "programs" "gnome-disks" "enable" ])
+  ];
+
+  ###### interface
+
+  options = {
+
+    programs.gnome-disks = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable GNOME Disks daemon, a program designed to
+          be a UDisks2 graphical front-end.
+        '';
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf config.programs.gnome-disks.enable {
+
+    environment.systemPackages = [ pkgs.gnome3.gnome-disk-utility ];
+
+    services.dbus.packages = [ pkgs.gnome3.gnome-disk-utility ];
+
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/gnome-documents.nix b/nixpkgs/nixos/modules/programs/gnome-documents.nix
new file mode 100644
index 000000000000..bfa3d409ee30
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/gnome-documents.nix
@@ -0,0 +1,50 @@
+# GNOME Documents.
+
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+{
+
+  # Added 2019-08-09
+  imports = [
+    (mkRenamedOptionModule
+      [ "services" "gnome3" "gnome-documents" "enable" ]
+      [ "programs" "gnome-documents" "enable" ])
+  ];
+
+  ###### interface
+
+  options = {
+
+    programs.gnome-documents = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable GNOME Documents, a document
+          manager application for GNOME.
+        '';
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf config.programs.gnome-documents.enable {
+
+    environment.systemPackages = [ pkgs.gnome3.gnome-documents ];
+
+    services.dbus.packages = [ pkgs.gnome3.gnome-documents ];
+
+    services.gnome3.gnome-online-accounts.enable = true;
+
+    services.gnome3.gnome-online-miners.enable = true;
+
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/gnupg.nix b/nixpkgs/nixos/modules/programs/gnupg.nix
new file mode 100644
index 000000000000..9618d61a1f5b
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/gnupg.nix
@@ -0,0 +1,112 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.programs.gnupg;
+
+in
+
+{
+
+  options.programs.gnupg = {
+    package = mkOption {
+      type = types.package;
+      default = pkgs.gnupg;
+      defaultText = "pkgs.gnupg";
+      description = ''
+        The gpg package that should be used.
+      '';
+    };
+
+    agent.enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Enables GnuPG agent with socket-activation for every user session.
+      '';
+    };
+
+    agent.enableSSHSupport = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Enable SSH agent support in GnuPG agent. Also sets SSH_AUTH_SOCK
+        environment variable correctly. This will disable socket-activation
+        and thus always start a GnuPG agent per user session.
+      '';
+    };
+
+    agent.enableExtraSocket = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Enable extra socket for GnuPG agent.
+      '';
+    };
+
+    agent.enableBrowserSocket = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Enable browser socket for GnuPG agent.
+      '';
+    };
+
+    dirmngr.enable = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        Enables GnuPG network certificate management daemon with socket-activation for every user session.
+      '';
+    };
+  };
+
+  config = mkIf cfg.agent.enable {
+    systemd.user.sockets.gpg-agent = {
+      wantedBy = [ "sockets.target" ];
+    };
+
+    systemd.user.sockets.gpg-agent-ssh = mkIf cfg.agent.enableSSHSupport {
+      wantedBy = [ "sockets.target" ];
+    };
+
+    systemd.user.sockets.gpg-agent-extra = mkIf cfg.agent.enableExtraSocket {
+      wantedBy = [ "sockets.target" ];
+    };
+
+    systemd.user.sockets.gpg-agent-browser = mkIf cfg.agent.enableBrowserSocket {
+      wantedBy = [ "sockets.target" ];
+    };
+
+    systemd.user.sockets.dirmngr = mkIf cfg.dirmngr.enable {
+      wantedBy = [ "sockets.target" ];
+    };
+
+    systemd.packages = [ cfg.package ];
+
+    environment.interactiveShellInit = ''
+      # Bind gpg-agent to this TTY if gpg commands are used.
+      export GPG_TTY=$(tty)
+
+    '' + (optionalString cfg.agent.enableSSHSupport ''
+      # SSH agent protocol doesn't support changing TTYs, so bind the agent
+      # to every new TTY.
+      ${cfg.package}/bin/gpg-connect-agent --quiet updatestartuptty /bye > /dev/null
+    '');
+
+    environment.extraInit = mkIf cfg.agent.enableSSHSupport ''
+      if [ -z "$SSH_AUTH_SOCK" ]; then
+        export SSH_AUTH_SOCK=$(${cfg.package}/bin/gpgconf --list-dirs agent-ssh-socket)
+      fi
+    '';
+
+    assertions = [
+      { assertion = cfg.agent.enableSSHSupport -> !config.programs.ssh.startAgent;
+        message = "You can't use ssh-agent and GnuPG agent with SSH support enabled at the same time!";
+      }
+    ];
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/gpaste.nix b/nixpkgs/nixos/modules/programs/gpaste.nix
new file mode 100644
index 000000000000..4f6deb77e5eb
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/gpaste.nix
@@ -0,0 +1,34 @@
+# GPaste.
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+
+  # Added 2019-08-09
+  imports = [
+    (mkRenamedOptionModule
+      [ "services" "gnome3" "gpaste" "enable" ]
+      [ "programs" "gpaste" "enable" ])
+  ];
+
+  ###### interface
+  options = {
+     programs.gpaste = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to enable GPaste, a clipboard manager.
+        '';
+      };
+    };
+  };
+
+  ###### implementation
+  config = mkIf config.programs.gpaste.enable {
+    environment.systemPackages = [ pkgs.gnome3.gpaste ];
+    services.dbus.packages = [ pkgs.gnome3.gpaste ];
+    systemd.packages = [ pkgs.gnome3.gpaste ];
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/gphoto2.nix b/nixpkgs/nixos/modules/programs/gphoto2.nix
new file mode 100644
index 000000000000..93923ff3133c
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/gphoto2.nix
@@ -0,0 +1,30 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+  meta.maintainers = [ maintainers.league ];
+
+  ###### interface
+  options = {
+    programs.gphoto2 = {
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Whether to configure system to use gphoto2.
+          To grant digital camera access to a user, the user must
+          be part of the camera group:
+          <code>users.users.alice.extraGroups = ["camera"];</code>
+        '';
+      };
+    };
+  };
+
+  ###### implementation
+  config = mkIf config.programs.gphoto2.enable {
+    services.udev.packages = [ pkgs.libgphoto2 ];
+    environment.systemPackages = [ pkgs.gphoto2 ];
+    users.groups.camera = {};
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/iftop.nix b/nixpkgs/nixos/modules/programs/iftop.nix
new file mode 100644
index 000000000000..a98a9a8187d4
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/iftop.nix
@@ -0,0 +1,18 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.iftop;
+in {
+  options = {
+    programs.iftop.enable = mkEnableOption "iftop + setcap wrapper";
+  };
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.iftop ];
+    security.wrappers.iftop = {
+      source = "${pkgs.iftop}/bin/iftop";
+      capabilities = "cap_net_raw+p";
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/iotop.nix b/nixpkgs/nixos/modules/programs/iotop.nix
new file mode 100644
index 000000000000..5512dbc62f72
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/iotop.nix
@@ -0,0 +1,17 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.iotop;
+in {
+  options = {
+    programs.iotop.enable = mkEnableOption "iotop + setcap wrapper";
+  };
+  config = mkIf cfg.enable {
+    security.wrappers.iotop = {
+      source = "${pkgs.iotop}/bin/iotop";
+      capabilities = "cap_net_admin+p";
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/java.nix b/nixpkgs/nixos/modules/programs/java.nix
new file mode 100644
index 000000000000..d31698c3b392
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/java.nix
@@ -0,0 +1,58 @@
+# This module provides JAVA_HOME, with a different way to install java
+# system-wide.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.java;
+in
+
+{
+
+  options = {
+
+    programs.java = {
+
+      enable = mkEnableOption "java" // {
+        description = ''
+          Install and setup the Java development kit.
+          <note>
+          <para>This adds JAVA_HOME to the global environment, by sourcing the
+            jdk's setup-hook on shell init. It is equivalent to starting a shell
+            through 'nix-shell -p jdk', or roughly the following system-wide
+            configuration:
+          </para>
+          <programlisting>
+            environment.variables.JAVA_HOME = ''${pkgs.jdk.home}/lib/openjdk;
+            environment.systemPackages = [ pkgs.jdk ];
+          </programlisting>
+          </note>
+        '';
+      };
+
+      package = mkOption {
+        default = pkgs.jdk;
+        defaultText = "pkgs.jdk";
+        description = ''
+          Java package to install. Typical values are pkgs.jdk or pkgs.jre.
+        '';
+        type = types.package;
+      };
+
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    environment.systemPackages = [ cfg.package ];
+
+    environment.shellInit = ''
+      test -e ${cfg.package}/nix-support/setup-hook && source ${cfg.package}/nix-support/setup-hook
+    '';
+
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/kbdlight.nix b/nixpkgs/nixos/modules/programs/kbdlight.nix
new file mode 100644
index 000000000000..58e45872fac8
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/kbdlight.nix
@@ -0,0 +1,16 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.kbdlight;
+
+in
+{
+  options.programs.kbdlight.enable = mkEnableOption "kbdlight";
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.kbdlight ];
+    security.wrappers.kbdlight.source = "${pkgs.kbdlight.out}/bin/kbdlight";
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/less.nix b/nixpkgs/nixos/modules/programs/less.nix
new file mode 100644
index 000000000000..9fdf99e9c694
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/less.nix
@@ -0,0 +1,131 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.programs.less;
+
+  configText = if (cfg.configFile != null) then (builtins.readFile cfg.configFile) else ''
+    #command
+    ${concatStringsSep "\n"
+      (mapAttrsToList (command: action: "${command} ${action}") cfg.commands)
+    }
+    ${if cfg.clearDefaultCommands then "#stop" else ""}
+
+    #line-edit
+    ${concatStringsSep "\n"
+      (mapAttrsToList (command: action: "${command} ${action}") cfg.lineEditingKeys)
+    }
+
+    #env
+    ${concatStringsSep "\n"
+      (mapAttrsToList (variable: values: "${variable}=${values}") cfg.envVariables)
+    }
+  '';
+
+  lessKey = pkgs.runCommand "lesskey"
+            { src = pkgs.writeText "lessconfig" configText; preferLocalBuild = true; }
+            "${pkgs.less}/bin/lesskey -o $out $src";
+
+in
+
+{
+  options = {
+
+    programs.less = {
+
+      enable = mkEnableOption "less";
+
+      configFile = mkOption {
+        type = types.nullOr types.path;
+        default = null;
+        example = literalExample "$${pkgs.my-configs}/lesskey";
+        description = ''
+          Path to lesskey configuration file.
+
+          <option>configFile</option> takes precedence over <option>commands</option>,
+          <option>clearDefaultCommands</option>, <option>lineEditingKeys</option>, and
+          <option>envVariables</option>.
+        '';
+      };
+
+      commands = mkOption {
+        type = types.attrsOf types.str;
+        default = {};
+        example = {
+          "h" = "noaction 5\e(";
+          "l" = "noaction 5\e)";
+        };
+        description = "Defines new command keys.";
+      };
+
+      clearDefaultCommands = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Clear all default commands.
+          You should remember to set the quit key.
+          Otherwise you will not be able to leave less without killing it.
+        '';
+      };
+
+      lineEditingKeys = mkOption {
+        type = types.attrsOf types.str;
+        default = {};
+        example = {
+          "\e" = "abort";
+        };
+        description = "Defines new line-editing keys.";
+      };
+
+      envVariables = mkOption {
+        type = types.attrsOf types.str;
+        default = {};
+        example = {
+          LESS = "--quit-if-one-screen";
+        };
+        description = "Defines environment variables.";
+      };
+
+      lessopen = mkOption {
+        type = types.nullOr types.str;
+        default = "|${pkgs.lesspipe}/bin/lesspipe.sh %s";
+        description = ''
+          Before less opens a file, it first gives your input preprocessor a chance to modify the way the contents of the file are displayed.
+        '';
+      };
+
+      lessclose = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        description = ''
+          When less closes a file opened in such a way, it will call another program, called the input postprocessor, which may  perform  any  desired  clean-up  action (such  as deleting the replacement file created by LESSOPEN).
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    environment.systemPackages = [ pkgs.less ];
+
+    environment.variables = {
+      "LESSKEY_SYSTEM" = toString lessKey;
+    } // optionalAttrs (cfg.lessopen != null) {
+      "LESSOPEN" = cfg.lessopen;
+    } // optionalAttrs (cfg.lessclose != null) {
+      "LESSCLOSE" = cfg.lessclose;
+    };
+
+    warnings = optional (
+      cfg.clearDefaultCommands && (all (x: x != "quit") (attrValues cfg.commands))
+    ) ''
+      config.programs.less.clearDefaultCommands clears all default commands of less but there is no alternative binding for exiting.
+      Consider adding a binding for 'quit'.
+    '';
+  };
+
+  meta.maintainers = with maintainers; [ johnazoidberg ];
+
+}
diff --git a/nixpkgs/nixos/modules/programs/light.nix b/nixpkgs/nixos/modules/programs/light.nix
new file mode 100644
index 000000000000..9f2a03e7e763
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/light.nix
@@ -0,0 +1,27 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.light;
+
+in
+{
+  options = {
+    programs.light = {
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Whether to install Light backlight control command
+          and udev rules granting access to members of the "video" group.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.light ];
+    services.udev.packages = [ pkgs.light ];
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/mininet.nix b/nixpkgs/nixos/modules/programs/mininet.nix
new file mode 100644
index 000000000000..ecc924325e6b
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/mininet.nix
@@ -0,0 +1,39 @@
+# Global configuration for mininet
+# kernel must have NETNS/VETH/SCHED
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg  = config.programs.mininet;
+
+  generatedPath = with pkgs; makeSearchPath "bin"  [
+    iperf ethtool iproute socat
+  ];
+
+  pyEnv = pkgs.python.withPackages(ps: [ ps.mininet-python ]);
+
+  mnexecWrapped = pkgs.runCommand "mnexec-wrapper"
+    { buildInputs = [ pkgs.makeWrapper pkgs.pythonPackages.wrapPython ]; }
+    ''
+      makeWrapper ${pkgs.mininet}/bin/mnexec \
+        $out/bin/mnexec \
+        --prefix PATH : "${generatedPath}"
+
+      ln -s ${pyEnv}/bin/mn $out/bin/mn
+
+      # mn errors out without a telnet binary
+      # pkgs.telnet brings an undesired ifconfig into PATH see #43105
+      ln -s ${pkgs.telnet}/bin/telnet $out/bin/telnet
+    '';
+in
+{
+  options.programs.mininet.enable = mkEnableOption "Mininet";
+
+  config = mkIf cfg.enable {
+
+    virtualisation.vswitch.enable = true;
+
+    environment.systemPackages = [ mnexecWrapped ];
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/mosh.nix b/nixpkgs/nixos/modules/programs/mosh.nix
new file mode 100644
index 000000000000..359fe23e0ecd
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/mosh.nix
@@ -0,0 +1,43 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg  = config.programs.mosh;
+
+in
+{
+  options.programs.mosh = {
+    enable = mkOption {
+      description = ''
+        Whether to enable mosh. Note, this will open ports in your firewall!
+      '';
+      default = false;
+      type = lib.types.bool;
+    };
+    withUtempter = mkOption {
+      description = ''
+        Whether to enable libutempter for mosh.
+        This is required so that mosh can write to /var/run/utmp (which can be queried with `who` to display currently connected user sessions).
+        Note, this will add a guid wrapper for the group utmp!
+      '';
+      default = true;
+      type = lib.types.bool;
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = with pkgs; [ mosh ];
+    networking.firewall.allowedUDPPortRanges = [ { from = 60000; to = 61000; } ];
+    security.wrappers = mkIf cfg.withUtempter {
+      utempter = {
+        source = "${pkgs.libutempter}/lib/utempter/utempter";
+        owner = "nobody";
+        group = "utmp";
+        setuid = false;
+        setgid = true;
+      };
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/mtr.nix b/nixpkgs/nixos/modules/programs/mtr.nix
new file mode 100644
index 000000000000..1fdec4c04f68
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/mtr.nix
@@ -0,0 +1,28 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.mtr;
+in {
+  options = {
+    programs.mtr = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to add mtr to the global environment and configure a
+          setcap wrapper for it.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = with pkgs; [ mtr ];
+    security.wrappers.mtr-packet = {
+      source = "${pkgs.mtr}/bin/mtr-packet";
+      capabilities = "cap_net_raw+p";
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/nano.nix b/nixpkgs/nixos/modules/programs/nano.nix
new file mode 100644
index 000000000000..6a4d46338e19
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/nano.nix
@@ -0,0 +1,42 @@
+{ config, lib, pkgs, ... }:
+
+let
+  cfg = config.programs.nano;
+  LF = "\n";
+in
+
+{
+  ###### interface
+
+  options = {
+    programs.nano = {
+
+      nanorc = lib.mkOption {
+        type = lib.types.lines;
+        default = "";
+        description = ''
+          The system-wide nano configuration.
+          See <citerefentry><refentrytitle>nanorc</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+        '';
+        example = ''
+          set nowrap
+          set tabstospaces
+          set tabsize 2
+        '';
+      };
+      syntaxHighlight = lib.mkOption {
+        type = lib.types.bool;
+        default = true;
+        description = "Whether to enable syntax highlight for various languages.";
+      };
+    };
+  };
+
+  ###### implementation
+
+  config = lib.mkIf (cfg.nanorc != "" || cfg.syntaxHighlight) {
+    environment.etc."nanorc".text = lib.concatStrings [ cfg.nanorc
+      (lib.optionalString cfg.syntaxHighlight ''${LF}include "${pkgs.nano}/share/nano/*.nanorc"'') ];
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/nm-applet.nix b/nixpkgs/nixos/modules/programs/nm-applet.nix
new file mode 100644
index 000000000000..e42219e9638c
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/nm-applet.nix
@@ -0,0 +1,14 @@
+{ config, lib, pkgs, ... }:
+
+{
+  options.programs.nm-applet.enable = lib.mkEnableOption "nm-applet";
+
+  config = lib.mkIf config.programs.nm-applet.enable {
+    systemd.user.services.nm-applet = {
+      description = "Network manager applet";
+      wantedBy = [ "graphical-session.target" ];
+      partOf = [ "graphical-session.target" ];
+      serviceConfig.ExecStart = "${pkgs.networkmanagerapplet}/bin/nm-applet";
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/npm.nix b/nixpkgs/nixos/modules/programs/npm.nix
new file mode 100644
index 000000000000..5fdd4fa841a1
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/npm.nix
@@ -0,0 +1,46 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.npm;
+in
+
+{
+  ###### interface
+
+  options = {
+    programs.npm = {
+      enable = mkEnableOption "<command>npm</command> global config";
+
+      npmrc = lib.mkOption {
+        type = lib.types.lines;
+        description = ''
+          The system-wide npm configuration.
+          See <link xlink:href="https://docs.npmjs.com/misc/config"/>.
+        '';
+        default = ''
+          prefix = ''${HOME}/.npm
+        '';
+        example = ''
+          prefix = ''${HOME}/.npm
+          https-proxy=proxy.example.com
+          init-license=MIT
+          init-author-url=http://npmjs.org
+          color=true
+        '';
+      };
+    };
+  };
+
+  ###### implementation
+
+  config = lib.mkIf cfg.enable {
+    environment.etc."npmrc".text = cfg.npmrc;
+
+    environment.variables.NPM_CONFIG_GLOBALCONFIG = "/etc/npmrc";
+
+    environment.systemPackages = [ pkgs.nodePackages.npm ];
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/oblogout.nix b/nixpkgs/nixos/modules/programs/oblogout.nix
new file mode 100644
index 000000000000..720c29b1eaee
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/oblogout.nix
@@ -0,0 +1,176 @@
+# Global configuration for oblogout.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.programs.oblogout;
+
+in
+{
+  ###### interface
+
+  options = {
+
+    programs.oblogout = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to install OBLogout and create <filename>/etc/oblogout.conf</filename>.
+          See <filename>${pkgs.oblogout}/share/doc/README</filename>.
+        '';
+      };
+
+      opacity = mkOption {
+        type = types.int;
+        default = 70;
+        description = ''
+          Opacity percentage of Cairo rendered backgrounds.
+        '';
+      };
+
+      bgcolor = mkOption {
+        type = types.str;
+        default = "black";
+        description = ''
+          Colour name or hex code (#ffffff) of the background color.
+        '';
+      };
+
+      buttontheme = mkOption {
+        type = types.str;
+        default = "simplistic";
+        description = ''
+          Icon theme for the buttons, must be in the themes folder of
+          the package, or in
+          <filename>~/.themes/&lt;name&gt;/oblogout/</filename>.
+        '';
+      };
+
+      buttons = mkOption {
+        type = types.str;
+        default =  "cancel, logout, restart, shutdown, suspend, hibernate";
+        description = ''
+          List and order of buttons to show.
+        '';
+      };
+
+      cancel = mkOption {
+        type = types.str;
+        default =  "Escape";
+        description = ''
+          Cancel logout/shutdown shortcut.
+        '';
+      };
+
+      shutdown = mkOption {
+        type = types.str;
+        default = "S";
+        description = ''
+          Shutdown shortcut.
+        '';
+      };
+
+      restart = mkOption {
+        type = types.str;
+        default = "R";
+        description = ''
+          Restart shortcut.
+        '';
+      };
+
+      suspend = mkOption {
+        type = types.str;
+        default = "U";
+        description = ''
+          Suspend shortcut.
+        '';
+      };
+
+      logout = mkOption {
+        type = types.str;
+        default = "L";
+        description = ''
+          Logout shortcut.
+        '';
+      };
+
+      lock = mkOption {
+        type = types.str;
+        default = "K";
+        description = ''
+          Lock session shortcut.
+        '';
+      };
+
+      hibernate = mkOption {
+        type = types.str;
+        default =  "H";
+        description = ''
+          Hibernate shortcut.
+        '';
+      };
+
+      clogout = mkOption {
+        type = types.str;
+        default = "openbox --exit";
+        description = ''
+          Command to logout.
+        '';
+      };
+
+      clock = mkOption {
+        type = types.str;
+        default = "";
+        description = ''
+          Command to lock screen.
+        '';
+      };
+
+      cswitchuser = mkOption {
+        type = types.str;
+        default = "";
+        description = ''
+          Command to switch user.
+        '';
+      };
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.oblogout ];
+
+    environment.etc."oblogout.conf".text = ''
+      [settings]
+      usehal = false
+
+      [looks]
+      opacity = ${toString cfg.opacity}
+      bgcolor = ${cfg.bgcolor}
+      buttontheme = ${cfg.buttontheme}
+      buttons = ${cfg.buttons}
+
+      [shortcuts]
+      cancel = ${cfg.cancel}
+      shutdown = ${cfg.shutdown}
+      restart = ${cfg.restart}
+      suspend = ${cfg.suspend}
+      logout = ${cfg.logout}
+      lock = ${cfg.lock}
+      hibernate = ${cfg.hibernate}
+
+      [commands]
+      shutdown = systemctl poweroff
+      restart = systemctl reboot
+      suspend = systemctl suspend
+      hibernate = systemctl hibernate
+      logout = ${cfg.clogout}
+      lock = ${cfg.clock}
+      switchuser = ${cfg.cswitchuser}
+    '';
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/plotinus.nix b/nixpkgs/nixos/modules/programs/plotinus.nix
new file mode 100644
index 000000000000..065e72d6c374
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/plotinus.nix
@@ -0,0 +1,36 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.plotinus;
+in
+{
+  meta = {
+    maintainers = pkgs.plotinus.meta.maintainers;
+    doc = ./plotinus.xml;
+  };
+
+  ###### interface
+
+  options = {
+    programs.plotinus = {
+      enable = mkOption {
+        default = false;
+        description = ''
+          Whether to enable the Plotinus GTK+3 plugin.  Plotinus provides a
+          popup (triggered by Ctrl-Shift-P) to search the menus of a
+          compatible application.
+        '';
+        type = types.bool;
+      };
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    environment.variables.XDG_DATA_DIRS = [ "${pkgs.plotinus}/share/gsettings-schemas/${pkgs.plotinus.name}" ];
+    environment.variables.GTK3_MODULES = [ "${pkgs.plotinus}/lib/libplotinus.so" ];
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/plotinus.xml b/nixpkgs/nixos/modules/programs/plotinus.xml
new file mode 100644
index 000000000000..902cd89e0c49
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/plotinus.xml
@@ -0,0 +1,30 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="module-program-plotinus">
+ <title>Plotinus</title>
+ <para>
+  <emphasis>Source:</emphasis>
+  <filename>modules/programs/plotinus.nix</filename>
+ </para>
+ <para>
+  <emphasis>Upstream documentation:</emphasis>
+  <link xlink:href="https://github.com/p-e-w/plotinus"/>
+ </para>
+ <para>
+  Plotinus is a searchable command palette in every modern GTK+ application.
+ </para>
+ <para>
+  When in a GTK+3 application and Plotinus is enabled, you can press
+  <literal>Ctrl+Shift+P</literal> to open the command palette. The command
+  palette provides a searchable list of of all menu items in the application.
+ </para>
+ <para>
+  To enable Plotinus, add the following to your
+  <filename>configuration.nix</filename>:
+<programlisting>
+<xref linkend="opt-programs.plotinus.enable"/> = true;
+</programlisting>
+ </para>
+</chapter>
diff --git a/nixpkgs/nixos/modules/programs/qt5ct.nix b/nixpkgs/nixos/modules/programs/qt5ct.nix
new file mode 100644
index 000000000000..aeb7fc508495
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/qt5ct.nix
@@ -0,0 +1,31 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+  meta.maintainers = [ maintainers.romildo ];
+
+  ###### interface
+  options = {
+    programs.qt5ct = {
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Whether to enable the Qt5 Configuration Tool (qt5ct), a
+          program that allows users to configure Qt5 settings (theme,
+          font, icons, etc.) under desktop environments or window
+          manager without Qt integration.
+
+          Official home page: <link xlink:href="https://sourceforge.net/projects/qt5ct/">https://sourceforge.net/projects/qt5ct/</link>
+        '';
+      };
+    };
+  };
+
+  ###### implementation
+  config = mkIf config.programs.qt5ct.enable {
+    environment.variables.QT_QPA_PLATFORMTHEME = "qt5ct";
+    environment.systemPackages = with pkgs; [ qt5ct libsForQt5.qtstyleplugins ];
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/screen.nix b/nixpkgs/nixos/modules/programs/screen.nix
new file mode 100644
index 000000000000..c1daaa58f16f
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/screen.nix
@@ -0,0 +1,32 @@
+{ config, lib, pkgs, ... }:
+
+let
+  inherit (lib) mkOption mkIf types;
+  cfg = config.programs.screen;
+in
+
+{
+  ###### interface
+
+  options = {
+    programs.screen = {
+
+      screenrc = mkOption {
+        default = "";
+        description = ''
+          The contents of /etc/screenrc file.
+        '';
+        type = types.lines;
+      };
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf (cfg.screenrc != "") {
+    environment.etc."screenrc".text = cfg.screenrc;
+
+    environment.systemPackages = [ pkgs.screen ];
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/sedutil.nix b/nixpkgs/nixos/modules/programs/sedutil.nix
new file mode 100644
index 000000000000..7efc80f4abba
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/sedutil.nix
@@ -0,0 +1,18 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.sedutil;
+
+in {
+  options.programs.sedutil.enable = mkEnableOption "sedutil";
+
+  config = mkIf cfg.enable {
+    boot.kernelParams = [
+      "libata.allow_tpm=1"
+    ];
+
+    environment.systemPackages = with pkgs; [ sedutil ];
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/shadow.nix b/nixpkgs/nixos/modules/programs/shadow.nix
new file mode 100644
index 000000000000..8ec4169207db
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/shadow.nix
@@ -0,0 +1,115 @@
+# Configuration for the pwdutils suite of tools: passwd, useradd, etc.
+
+{ config, lib, utils, pkgs, ... }:
+
+with lib;
+
+let
+
+  loginDefs =
+    ''
+      DEFAULT_HOME yes
+
+      SYS_UID_MIN  400
+      SYS_UID_MAX  499
+      UID_MIN      1000
+      UID_MAX      29999
+
+      SYS_GID_MIN  400
+      SYS_GID_MAX  499
+      GID_MIN      1000
+      GID_MAX      29999
+
+      TTYGROUP     tty
+      TTYPERM      0620
+
+      # Ensure privacy for newly created home directories.
+      UMASK        077
+
+      # Uncomment this and install chfn SUID to allow non-root
+      # users to change their account GECOS information.
+      # This should be made configurable.
+      #CHFN_RESTRICT frwh
+
+    '';
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    users.defaultUserShell = lib.mkOption {
+      description = ''
+        This option defines the default shell assigned to user
+        accounts. This can be either a full system path or a shell package.
+
+        This must not be a store path, since the path is
+        used outside the store (in particular in /etc/passwd).
+      '';
+      example = literalExample "pkgs.zsh";
+      type = types.either types.path types.shellPackage;
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = {
+
+    environment.systemPackages =
+      lib.optional config.users.mutableUsers pkgs.shadow ++
+      lib.optional (types.shellPackage.check config.users.defaultUserShell)
+        config.users.defaultUserShell;
+
+    environment.etc =
+      [ { # /etc/login.defs: global configuration for pwdutils.  You
+          # cannot login without it!
+          source = pkgs.writeText "login.defs" loginDefs;
+          target = "login.defs";
+        }
+
+        { # /etc/default/useradd: configuration for useradd.
+          source = pkgs.writeText "useradd"
+            ''
+              GROUP=100
+              HOME=/home
+              SHELL=${utils.toShellPath config.users.defaultUserShell}
+            '';
+          target = "default/useradd";
+        }
+      ];
+
+    security.pam.services =
+      { chsh = { rootOK = true; };
+        chfn = { rootOK = true; };
+        su = { rootOK = true; forwardXAuth = true; logFailures = true; };
+        passwd = {};
+        # Note: useradd, groupadd etc. aren't setuid root, so it
+        # doesn't really matter what the PAM config says as long as it
+        # lets root in.
+        useradd = { rootOK = true; };
+        usermod = { rootOK = true; };
+        userdel = { rootOK = true; };
+        groupadd = { rootOK = true; };
+        groupmod = { rootOK = true; };
+        groupmems = { rootOK = true; };
+        groupdel = { rootOK = true; };
+        login = { startSession = true; allowNullPassword = true; showMotd = true; updateWtmp = true; };
+        chpasswd = { rootOK = true; };
+      };
+
+    security.wrappers = {
+      su.source        = "${pkgs.shadow.su}/bin/su";
+      sg.source        = "${pkgs.shadow.out}/bin/sg";
+      newgrp.source    = "${pkgs.shadow.out}/bin/newgrp";
+      newuidmap.source = "${pkgs.shadow.out}/bin/newuidmap";
+      newgidmap.source = "${pkgs.shadow.out}/bin/newgidmap";
+    } // (if config.users.mutableUsers then {
+      passwd.source    = "${pkgs.shadow.out}/bin/passwd";
+    } else {});
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/shell.nix b/nixpkgs/nixos/modules/programs/shell.nix
new file mode 100644
index 000000000000..b7f7b91b5fbe
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/shell.nix
@@ -0,0 +1,54 @@
+# This module defines a standard configuration for NixOS shells.
+
+{ config, lib, ... }:
+
+with lib;
+
+{
+
+  config = {
+
+    environment.shellInit =
+      ''
+        # Set up the per-user profile.
+        mkdir -m 0755 -p "$NIX_USER_PROFILE_DIR"
+        if [ "$(stat -c '%u' "$NIX_USER_PROFILE_DIR")" != "$(id -u)" ]; then
+            echo "WARNING: the per-user profile dir $NIX_USER_PROFILE_DIR should belong to user id $(id -u)" >&2
+        fi
+
+        if [ -w "$HOME" ]; then
+          if ! [ -L "$HOME/.nix-profile" ]; then
+              if [ "$USER" != root ]; then
+                  ln -s "$NIX_USER_PROFILE_DIR/profile" "$HOME/.nix-profile"
+              else
+                  # Root installs in the system-wide profile by default.
+                  ln -s /nix/var/nix/profiles/default "$HOME/.nix-profile"
+              fi
+          fi
+
+          # Subscribe the root user to the NixOS channel by default.
+          if [ "$USER" = root -a ! -e "$HOME/.nix-channels" ]; then
+              echo "${config.system.defaultChannel} nixos" > "$HOME/.nix-channels"
+          fi
+
+          # Create the per-user garbage collector roots directory.
+          NIX_USER_GCROOTS_DIR="/nix/var/nix/gcroots/per-user/$USER"
+          mkdir -m 0755 -p "$NIX_USER_GCROOTS_DIR"
+          if [ "$(stat -c '%u' "$NIX_USER_GCROOTS_DIR")" != "$(id -u)" ]; then
+              echo "WARNING: the per-user gcroots dir $NIX_USER_GCROOTS_DIR should belong to user id $(id -u)" >&2
+          fi
+
+          # Set up a default Nix expression from which to install stuff.
+          if [ ! -e "$HOME/.nix-defexpr" -o -L "$HOME/.nix-defexpr" ]; then
+              rm -f "$HOME/.nix-defexpr"
+              mkdir -p "$HOME/.nix-defexpr"
+              if [ "$USER" != root ]; then
+                  ln -s /nix/var/nix/profiles/per-user/root/channels "$HOME/.nix-defexpr/channels_root"
+              fi
+          fi
+        fi
+      '';
+
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/singularity.nix b/nixpkgs/nixos/modules/programs/singularity.nix
new file mode 100644
index 000000000000..b27e122bd1d9
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/singularity.nix
@@ -0,0 +1,29 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+let
+  cfg = config.programs.singularity;
+  singularity = pkgs.singularity.overrideAttrs (attrs : {
+    installPhase = attrs.installPhase + ''
+      mv $bin/libexec/singularity/bin/starter-suid $bin/libexec/singularity/bin/starter-suid.orig
+      ln -s /run/wrappers/bin/singularity-suid $bin/libexec/singularity/bin/starter-suid
+    '';
+  });
+in {
+  options.programs.singularity = {
+    enable = mkEnableOption "Singularity";
+  };
+
+  config = mkIf cfg.enable {
+      environment.systemPackages = [ singularity ];
+      security.wrappers.singularity-suid.source = "${singularity}/libexec/singularity/bin/starter-suid.orig";
+      systemd.tmpfiles.rules = [
+        "d /var/singularity/mnt/session 0770 root root -"
+        "d /var/singularity/mnt/final 0770 root root -"
+        "d /var/singularity/mnt/overlay 0770 root root -"
+        "d /var/singularity/mnt/container 0770 root root -"
+        "d /var/singularity/mnt/source 0770 root root -"
+      ];
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/slock.nix b/nixpkgs/nixos/modules/programs/slock.nix
new file mode 100644
index 000000000000..0e1281e62cd7
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/slock.nix
@@ -0,0 +1,26 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.slock;
+
+in
+{
+  options = {
+    programs.slock = {
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Whether to install slock screen locker with setuid wrapper.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.slock ];
+    security.wrappers.slock.source = "${pkgs.slock.out}/bin/slock";
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/spacefm.nix b/nixpkgs/nixos/modules/programs/spacefm.nix
new file mode 100644
index 000000000000..6d03608402fc
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/spacefm.nix
@@ -0,0 +1,55 @@
+# Global configuration for spacefm.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.programs.spacefm;
+
+in
+{
+  ###### interface
+
+  options = {
+
+    programs.spacefm = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to install SpaceFM and create <filename>/etc/spacefm/spacefm.conf</filename>.
+        '';
+      };
+
+      settings = mkOption {
+        type = types.attrs;
+        default = {
+          tmp_dir = "/tmp";
+          terminal_su = "${pkgs.sudo}/bin/sudo";
+          graphical_su = "${pkgs.gksu}/bin/gksu";
+        };
+        example = literalExample ''{
+          tmp_dir = "/tmp";
+          terminal_su = "''${pkgs.sudo}/bin/sudo";
+          graphical_su = "''${pkgs.gksu}/bin/gksu";
+        }'';
+        description = ''
+          The system-wide spacefm configuration.
+          Parameters to be written to <filename>/etc/spacefm/spacefm.conf</filename>.
+          Refer to the <link xlink:href="https://ignorantguru.github.io/spacefm/spacefm-manual-en.html#programfiles-etc">relevant entry</link> in the SpaceFM manual.
+        '';
+      };
+
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.spaceFM ];
+
+    environment.etc."spacefm/spacefm.conf".text =
+      concatStrings (mapAttrsToList (n: v: "${n}=${toString v}\n") cfg.settings);
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/ssh.nix b/nixpkgs/nixos/modules/programs/ssh.nix
new file mode 100644
index 000000000000..733b8f7636fd
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/ssh.nix
@@ -0,0 +1,267 @@
+# Global configuration for the SSH client.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg  = config.programs.ssh;
+
+  askPassword = cfg.askPassword;
+
+  askPasswordWrapper = pkgs.writeScript "ssh-askpass-wrapper"
+    ''
+      #! ${pkgs.runtimeShell} -e
+      export DISPLAY="$(systemctl --user show-environment | ${pkgs.gnused}/bin/sed 's/^DISPLAY=\(.*\)/\1/; t; d')"
+      exec ${askPassword}
+    '';
+
+  knownHosts = map (h: getAttr h cfg.knownHosts) (attrNames cfg.knownHosts);
+
+  knownHostsText = (flip (concatMapStringsSep "\n") knownHosts
+    (h: assert h.hostNames != [];
+      optionalString h.certAuthority "@cert-authority " + concatStringsSep "," h.hostNames + " "
+      + (if h.publicKey != null then h.publicKey else readFile h.publicKeyFile)
+    )) + "\n";
+
+in
+{
+  ###### interface
+
+  options = {
+
+    programs.ssh = {
+
+      askPassword = mkOption {
+        type = types.str;
+        default = "${pkgs.x11_ssh_askpass}/libexec/x11-ssh-askpass";
+        description = ''Program used by SSH to ask for passwords.'';
+      };
+
+      forwardX11 = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to request X11 forwarding on outgoing connections by default.
+          This is useful for running graphical programs on the remote machine and have them display to your local X11 server.
+          Historically, this value has depended on the value used by the local sshd daemon, but there really isn't a relation between the two.
+          Note: there are some security risks to forwarding an X11 connection.
+          NixOS's X server is built with the SECURITY extension, which prevents some obvious attacks.
+          To enable or disable forwarding on a per-connection basis, see the -X and -x options to ssh.
+          The -Y option to ssh enables trusted forwarding, which bypasses the SECURITY extension.
+        '';
+      };
+
+      setXAuthLocation = mkOption {
+        type = types.bool;
+        description = ''
+          Whether to set the path to <command>xauth</command> for X11-forwarded connections.
+          This causes a dependency on X11 packages.
+        '';
+      };
+
+      # Allow DSA keys for now. (These were deprecated in OpenSSH 7.0.)
+      pubkeyAcceptedKeyTypes = mkOption {
+        type = types.listOf types.str;
+        default = [
+          "+ssh-dss"
+        ];
+        example = [ "ssh-ed25519" "ssh-rsa" ];
+        description = ''
+          Specifies the key types that will be used for public key authentication.
+        '';
+      };
+
+      hostKeyAlgorithms = mkOption {
+        type = types.listOf types.str;
+        default = [
+          "+ssh-dss"
+        ];
+        example = [ "ssh-ed25519" "ssh-rsa" ];
+        description = ''
+          Specifies the host key algorithms that the client wants to use in order of preference.
+        '';
+      };
+
+      extraConfig = mkOption {
+        type = types.lines;
+        default = "";
+        description = ''
+          Extra configuration text prepended to <filename>ssh_config</filename>. Other generated
+          options will be added after a <code>Host *</code> pattern.
+          See <citerefentry><refentrytitle>ssh_config</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+          for help.
+        '';
+      };
+
+      startAgent = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to start the OpenSSH agent when you log in.  The OpenSSH agent
+          remembers private keys for you so that you don't have to type in
+          passphrases every time you make an SSH connection.  Use
+          <command>ssh-add</command> to add a key to the agent.
+        '';
+      };
+
+      agentTimeout = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        example = "1h";
+        description = ''
+          How long to keep the private keys in memory. Use null to keep them forever.
+        '';
+      };
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.openssh;
+        defaultText = "pkgs.openssh";
+        description = ''
+          The package used for the openssh client and daemon.
+        '';
+      };
+
+      knownHosts = mkOption {
+        default = {};
+        type = types.loaOf (types.submodule ({ name, ... }: {
+          options = {
+            certAuthority = mkOption {
+              type = types.bool;
+              default = false;
+              description = ''
+                This public key is an SSH certificate authority, rather than an
+                individual host's key.
+              '';
+            };
+            hostNames = mkOption {
+              type = types.listOf types.str;
+              default = [];
+              description = ''
+                A list of host names and/or IP numbers used for accessing
+                the host's ssh service.
+              '';
+            };
+            publicKey = mkOption {
+              default = null;
+              type = types.nullOr types.str;
+              example = "ecdsa-sha2-nistp521 AAAAE2VjZHN...UEPg==";
+              description = ''
+                The public key data for the host. You can fetch a public key
+                from a running SSH server with the <command>ssh-keyscan</command>
+                command. The public key should not include any host names, only
+                the key type and the key itself.
+              '';
+            };
+            publicKeyFile = mkOption {
+              default = null;
+              type = types.nullOr types.path;
+              description = ''
+                The path to the public key file for the host. The public
+                key file is read at build time and saved in the Nix store.
+                You can fetch a public key file from a running SSH server
+                with the <command>ssh-keyscan</command> command. The content
+                of the file should follow the same format as described for
+                the <literal>publicKey</literal> option.
+              '';
+            };
+          };
+          config = {
+            hostNames = mkDefault [ name ];
+          };
+        }));
+        description = ''
+          The set of system-wide known SSH hosts.
+        '';
+        example = literalExample ''
+          {
+            myhost = {
+              hostNames = [ "myhost" "myhost.mydomain.com" "10.10.1.4" ];
+              publicKeyFile = ./pubkeys/myhost_ssh_host_dsa_key.pub;
+            };
+            myhost2 = {
+              hostNames = [ "myhost2" ];
+              publicKeyFile = ./pubkeys/myhost2_ssh_host_dsa_key.pub;
+            };
+          }
+        '';
+      };
+
+    };
+
+  };
+
+  config = {
+
+    programs.ssh.setXAuthLocation =
+      mkDefault (config.services.xserver.enable || config.programs.ssh.forwardX11 || config.services.openssh.forwardX11);
+
+    assertions =
+      [ { assertion = cfg.forwardX11 -> cfg.setXAuthLocation;
+          message = "cannot enable X11 forwarding without setting XAuth location";
+        }
+      ] ++ flip mapAttrsToList cfg.knownHosts (name: data: {
+        assertion = (data.publicKey == null && data.publicKeyFile != null) ||
+                    (data.publicKey != null && data.publicKeyFile == null);
+        message = "knownHost ${name} must contain either a publicKey or publicKeyFile";
+      });
+
+    # SSH configuration. Slight duplication of the sshd_config
+    # generation in the sshd service.
+    environment.etc."ssh/ssh_config".text =
+      ''
+        # Custom options from `extraConfig`, to override generated options
+        ${cfg.extraConfig}
+
+        # Generated options from other settings
+        Host *
+        AddressFamily ${if config.networking.enableIPv6 then "any" else "inet"}
+
+        ${optionalString cfg.setXAuthLocation ''
+          XAuthLocation ${pkgs.xorg.xauth}/bin/xauth
+        ''}
+
+        ForwardX11 ${if cfg.forwardX11 then "yes" else "no"}
+
+        ${optionalString (cfg.pubkeyAcceptedKeyTypes != []) "PubkeyAcceptedKeyTypes ${concatStringsSep "," cfg.pubkeyAcceptedKeyTypes}"}
+        ${optionalString (cfg.hostKeyAlgorithms != []) "HostKeyAlgorithms ${concatStringsSep "," cfg.hostKeyAlgorithms}"}
+      '';
+
+    environment.etc."ssh/ssh_known_hosts".text = knownHostsText;
+
+    # FIXME: this should really be socket-activated for über-awesomeness.
+    systemd.user.services.ssh-agent = mkIf cfg.startAgent
+      { description = "SSH Agent";
+        wantedBy = [ "default.target" ];
+        unitConfig.ConditionUser = "!@system";
+        serviceConfig =
+          { ExecStartPre = "${pkgs.coreutils}/bin/rm -f %t/ssh-agent";
+            ExecStart =
+                "${cfg.package}/bin/ssh-agent " +
+                optionalString (cfg.agentTimeout != null) ("-t ${cfg.agentTimeout} ") +
+                "-a %t/ssh-agent";
+            StandardOutput = "null";
+            Type = "forking";
+            Restart = "on-failure";
+            SuccessExitStatus = "0 2";
+          };
+        # Allow ssh-agent to ask for confirmation. This requires the
+        # unit to know about the user's $DISPLAY (via ‘systemctl
+        # import-environment’).
+        environment.SSH_ASKPASS = optionalString config.services.xserver.enable askPasswordWrapper;
+        environment.DISPLAY = "fake"; # required to make ssh-agent start $SSH_ASKPASS
+      };
+
+    environment.extraInit = optionalString cfg.startAgent
+      ''
+        if [ -z "$SSH_AUTH_SOCK" -a -n "$XDG_RUNTIME_DIR" ]; then
+          export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent"
+        fi
+      '';
+
+    environment.variables.SSH_ASKPASS = optionalString config.services.xserver.enable askPassword;
+
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/ssmtp.nix b/nixpkgs/nixos/modules/programs/ssmtp.nix
new file mode 100644
index 000000000000..0e060e3f5226
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/ssmtp.nix
@@ -0,0 +1,165 @@
+# Configuration for `ssmtp', a trivial mail transfer agent that can
+# replace sendmail/postfix on simple systems.  It delivers email
+# directly to an SMTP server defined in its configuration file, wihout
+# queueing mail locally.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.networking.defaultMailServer;
+
+in
+
+{
+
+  options = {
+
+    networking.defaultMailServer = {
+
+      directDelivery = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Use the trivial Mail Transfer Agent (MTA)
+          <command>ssmtp</command> package to allow programs to send
+          e-mail.  If you don't want to run a “real” MTA like
+          <command>sendmail</command> or <command>postfix</command> on
+          your machine, set this option to <literal>true</literal>, and
+          set the option
+          <option>networking.defaultMailServer.hostName</option> to the
+          host name of your preferred mail server.
+        '';
+      };
+
+      hostName = mkOption {
+        type = types.str;
+        example = "mail.example.org";
+        description = ''
+          The host name of the default mail server to use to deliver
+          e-mail. Can also contain a port number (ex: mail.example.org:587),
+          defaults to port 25 if no port is given.
+        '';
+      };
+
+      root = mkOption {
+        type = types.str;
+        default = "";
+        example = "root@example.org";
+        description = ''
+          The e-mail to which mail for users with UID &lt; 1000 is forwarded.
+        '';
+      };
+
+      domain = mkOption {
+        type = types.str;
+        default = "";
+        example = "example.org";
+        description = ''
+          The domain from which mail will appear to be sent.
+        '';
+      };
+
+      useTLS = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether TLS should be used to connect to the default mail
+          server.
+        '';
+      };
+
+      useSTARTTLS = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether the STARTTLS should be used to connect to the default
+          mail server.  (This is needed for TLS-capable mail servers
+          running on the default SMTP port 25.)
+        '';
+      };
+
+      authUser = mkOption {
+        type = types.str;
+        default = "";
+        example = "foo@example.org";
+        description = ''
+          Username used for SMTP auth. Leave blank to disable.
+        '';
+      };
+
+      authPass = mkOption {
+        type = types.str;
+        default = "";
+        example = "correctHorseBatteryStaple";
+        description = ''
+          Password used for SMTP auth. (STORED PLAIN TEXT, WORLD-READABLE IN NIX STORE)
+
+          It's recommended to use <option>authPassFile</option>
+          which takes precedence over <option>authPass</option>.
+        '';
+      };
+
+      authPassFile = mkOption {
+        type = types.nullOr types.str;
+        default = null;
+        example = "/run/keys/ssmtp-authpass";
+        description = ''
+          Path to a file that contains the password used for SMTP auth. The file
+          should not contain a trailing newline, if the password does not contain one.
+          This file should be readable by the users that need to execute ssmtp.
+
+          <option>authPassFile</option> takes precedence over <option>authPass</option>.
+
+          Warning: when <option>authPass</option> is non-empty <option>authPassFile</option>
+          defaults to a file in the WORLD-READABLE Nix store containing that password.
+        '';
+      };
+
+      setSendmail = mkOption {
+        type = types.bool;
+        default = true;
+        description = "Whether to set the system sendmail to ssmtp's.";
+      };
+
+    };
+
+  };
+
+
+  config = mkIf cfg.directDelivery {
+
+    networking.defaultMailServer.authPassFile = mkIf (cfg.authPass != "")
+      (mkDefault (toString (pkgs.writeTextFile {
+        name = "ssmtp-authpass";
+        text = cfg.authPass;
+      })));
+
+    environment.etc."ssmtp/ssmtp.conf".text =
+      let yesNo = yes : if yes then "YES" else "NO"; in
+      ''
+        MailHub=${cfg.hostName}
+        FromLineOverride=YES
+        ${optionalString (cfg.root   != "") "root=${cfg.root}"}
+        ${optionalString (cfg.domain != "") "rewriteDomain=${cfg.domain}"}
+        UseTLS=${yesNo cfg.useTLS}
+        UseSTARTTLS=${yesNo cfg.useSTARTTLS}
+        #Debug=YES
+        ${optionalString (cfg.authUser != "")       "AuthUser=${cfg.authUser}"}
+        ${optionalString (cfg.authPassFile != null) "AuthPassFile=${cfg.authPassFile}"}
+      '';
+
+    environment.systemPackages = [pkgs.ssmtp];
+
+    services.mail.sendmailSetuidWrapper = mkIf cfg.setSendmail {
+      program = "sendmail";
+      source = "${pkgs.ssmtp}/bin/sendmail";
+      setuid = false;
+      setgid = false;
+    };
+
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/sway.nix b/nixpkgs/nixos/modules/programs/sway.nix
new file mode 100644
index 000000000000..b4f03151cdc1
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/sway.nix
@@ -0,0 +1,93 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.sway;
+  swayPackage = pkgs.sway;
+
+  swayWrapped = pkgs.writeShellScriptBin "sway" ''
+    set -o errexit
+
+    if [ ! "$_SWAY_WRAPPER_ALREADY_EXECUTED" ]; then
+      export _SWAY_WRAPPER_ALREADY_EXECUTED=1
+      ${cfg.extraSessionCommands}
+    fi
+
+    if [ "$DBUS_SESSION_BUS_ADDRESS" ]; then
+      export DBUS_SESSION_BUS_ADDRESS
+      exec ${swayPackage}/bin/sway "$@"
+    else
+      exec ${pkgs.dbus}/bin/dbus-run-session ${swayPackage}/bin/sway "$@"
+    fi
+  '';
+  swayJoined = pkgs.symlinkJoin {
+    name = "sway-joined";
+    paths = [ swayWrapped swayPackage ];
+  };
+in {
+  options.programs.sway = {
+    enable = mkEnableOption ''
+      Sway, the i3-compatible tiling Wayland compositor. You can manually launch
+      Sway by executing "exec sway" on a TTY. Copy /etc/sway/config to
+      ~/.config/sway/config to modify the default configuration. See
+      https://github.com/swaywm/sway/wiki and "man 5 sway" for more information.
+      Please have a look at the "extraSessionCommands" example for running
+      programs natively under Wayland'';
+
+    extraSessionCommands = mkOption {
+      type = types.lines;
+      default = "";
+      example = ''
+        export SDL_VIDEODRIVER=wayland
+        # needs qt5.qtwayland in systemPackages
+        export QT_QPA_PLATFORM=wayland
+        export QT_WAYLAND_DISABLE_WINDOWDECORATION="1"
+        # Fix for some Java AWT applications (e.g. Android Studio),
+        # use this if they aren't displayed properly:
+        export _JAVA_AWT_WM_NONREPARENTING=1
+      '';
+      description = ''
+        Shell commands executed just before Sway is started.
+      '';
+    };
+
+    extraPackages = mkOption {
+      type = with types; listOf package;
+      default = with pkgs; [
+        swaylock swayidle
+        xwayland rxvt_unicode dmenu
+      ];
+      defaultText = literalExample ''
+        with pkgs; [ swaylock swayidle xwayland rxvt_unicode dmenu ];
+      '';
+      example = literalExample ''
+        with pkgs; [
+          xwayland
+          i3status i3status-rust
+          termite rofi light
+        ]
+      '';
+      description = ''
+        Extra packages to be installed system wide.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment = {
+      systemPackages = [ swayJoined ] ++ cfg.extraPackages;
+      etc = {
+        "sway/config".source = mkOptionDefault "${swayPackage}/etc/sway/config";
+        #"sway/security.d".source = mkOptionDefault "${swayPackage}/etc/sway/security.d/";
+        #"sway/config.d".source = mkOptionDefault "${swayPackage}/etc/sway/config.d/";
+      };
+    };
+    security.pam.services.swaylock = {};
+    hardware.opengl.enable = mkDefault true;
+    fonts.enableDefaultFonts = mkDefault true;
+    programs.dconf.enable = mkDefault true;
+  };
+
+  meta.maintainers = with lib.maintainers; [ gnidorah primeos colemickens ];
+}
diff --git a/nixpkgs/nixos/modules/programs/sysdig.nix b/nixpkgs/nixos/modules/programs/sysdig.nix
new file mode 100644
index 000000000000..fbbf29065564
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/sysdig.nix
@@ -0,0 +1,14 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.sysdig;
+in {
+  options.programs.sysdig.enable = mkEnableOption "sysdig";
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.sysdig ];
+    boot.extraModulePackages = [ config.boot.kernelPackages.sysdig ];
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/systemtap.nix b/nixpkgs/nixos/modules/programs/systemtap.nix
new file mode 100644
index 000000000000..ca81e018c9dc
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/systemtap.nix
@@ -0,0 +1,28 @@
+{ config, lib, ... }:
+
+with lib;
+
+let cfg = config.programs.systemtap;
+in {
+
+  options = {
+    programs.systemtap = {
+      enable = mkOption {
+        default = false;
+        description = ''
+          Install <command>systemtap</command> along with necessary kernel options.
+        '';
+      };
+    };
+  };
+  config = mkIf cfg.enable {
+    system.requiredKernelConfig = with config.lib.kernelConfig; [
+      (isYes "DEBUG")
+    ];
+    boot.kernel.features.debug = true;
+    environment.systemPackages = [
+      config.boot.kernelPackages.systemtap
+    ];
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/thefuck.nix b/nixpkgs/nixos/modules/programs/thefuck.nix
new file mode 100644
index 000000000000..21ed6603c1bd
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/thefuck.nix
@@ -0,0 +1,39 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  prg = config.programs;
+  cfg = prg.thefuck;
+
+  initScript = ''
+    eval $(${pkgs.thefuck}/bin/thefuck --alias ${cfg.alias})
+  '';
+in
+  {
+    options = {
+      programs.thefuck = {
+        enable = mkEnableOption "thefuck";
+
+        alias = mkOption {
+          default = "fuck";
+          type = types.string;
+
+          description = ''
+            `thefuck` needs an alias to be configured.
+            The default value is `fuck`, but you can use anything else as well.
+          '';
+        };
+      };
+    };
+
+    config = mkIf cfg.enable {
+      environment.systemPackages = with pkgs; [ thefuck ];
+
+      programs.bash.interactiveShellInit = initScript;
+      programs.zsh.interactiveShellInit = mkIf prg.zsh.enable initScript;
+      programs.fish.interactiveShellInit = mkIf prg.fish.enable ''
+        ${pkgs.thefuck}/bin/thefuck --alias | source
+      '';
+    };
+  }
diff --git a/nixpkgs/nixos/modules/programs/tmux.nix b/nixpkgs/nixos/modules/programs/tmux.nix
new file mode 100644
index 000000000000..ed077e3daa76
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/tmux.nix
@@ -0,0 +1,184 @@
+{ config, pkgs, lib, ... }:
+
+let
+  inherit (lib) mkOption mkIf types;
+
+  cfg = config.programs.tmux;
+
+  defaultKeyMode  = "emacs";
+  defaultResize   = 5;
+  defaultShortcut = "b";
+  defaultTerminal = "screen";
+
+  boolToStr = value: if value then "on" else "off";
+
+  tmuxConf = ''
+    set  -g default-terminal "${cfg.terminal}"
+    set  -g base-index      ${toString cfg.baseIndex}
+    setw -g pane-base-index ${toString cfg.baseIndex}
+
+    ${if cfg.newSession then "new-session" else ""}
+
+    ${if cfg.reverseSplit then ''
+    bind v split-window -h
+    bind s split-window -v
+    '' else ""}
+
+    set -g status-keys ${cfg.keyMode}
+    set -g mode-keys   ${cfg.keyMode}
+
+    ${if cfg.keyMode == "vi" && cfg.customPaneNavigationAndResize then ''
+    bind h select-pane -L
+    bind j select-pane -D
+    bind k select-pane -U
+    bind l select-pane -R
+
+    bind -r H resize-pane -L ${toString cfg.resizeAmount}
+    bind -r J resize-pane -D ${toString cfg.resizeAmount}
+    bind -r K resize-pane -U ${toString cfg.resizeAmount}
+    bind -r L resize-pane -R ${toString cfg.resizeAmount}
+    '' else ""}
+
+    ${if (cfg.shortcut != defaultShortcut) then ''
+    # rebind main key: C-${cfg.shortcut}
+    unbind C-${defaultShortcut}
+    set -g prefix C-${cfg.shortcut}
+    bind ${cfg.shortcut} send-prefix
+    bind C-${cfg.shortcut} last-window
+    '' else ""}
+
+    setw -g aggressive-resize ${boolToStr cfg.aggressiveResize}
+    setw -g clock-mode-style  ${if cfg.clock24 then "24" else "12"}
+    set  -s escape-time       ${toString cfg.escapeTime}
+    set  -g history-limit     ${toString cfg.historyLimit}
+
+    ${cfg.extraTmuxConf}
+  '';
+
+in {
+  ###### interface
+
+  options = {
+    programs.tmux = {
+
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = "Whenever to configure <command>tmux</command> system-wide.";
+        relatedPackages = [ "tmux" ];
+      };
+
+      aggressiveResize = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Resize the window to the size of the smallest session for which it is the current window.
+        '';
+      };
+
+      baseIndex = mkOption {
+        default = 0;
+        example = 1;
+        type = types.int;
+        description = "Base index for windows and panes.";
+      };
+
+      clock24 = mkOption {
+        default = false;
+        type = types.bool;
+        description = "Use 24 hour clock.";
+      };
+
+      customPaneNavigationAndResize = mkOption {
+        default = false;
+        type = types.bool;
+        description = "Override the hjkl and HJKL bindings for pane navigation and resizing in VI mode.";
+      };
+
+      escapeTime = mkOption {
+        default = 500;
+        example = 0;
+        type = types.int;
+        description = "Time in milliseconds for which tmux waits after an escape is input.";
+      };
+
+      extraTmuxConf = mkOption {
+        default = "";
+        description = ''
+          Additional contents of /etc/tmux.conf
+        '';
+        type = types.lines;
+      };
+
+      historyLimit = mkOption {
+        default = 2000;
+        example = 5000;
+        type = types.int;
+        description = "Maximum number of lines held in window history.";
+      };
+
+      keyMode = mkOption {
+        default = defaultKeyMode;
+        example = "vi";
+        type = types.enum [ "emacs" "vi" ];
+        description = "VI or Emacs style shortcuts.";
+      };
+
+      newSession = mkOption {
+        default = false;
+        type = types.bool;
+        description = "Automatically spawn a session if trying to attach and none are running.";
+      };
+
+      reverseSplit = mkOption {
+        default = false;
+        type = types.bool;
+        description = "Reverse the window split shortcuts.";
+      };
+
+      resizeAmount = mkOption {
+        default = defaultResize;
+        example = 10;
+        type = types.int;
+        description = "Number of lines/columns when resizing.";
+      };
+
+      shortcut = mkOption {
+        default = defaultShortcut;
+        example = "a";
+        type = types.str;
+        description = "Ctrl following by this key is used as the main shortcut.";
+      };
+
+      terminal = mkOption {
+        default = defaultTerminal;
+        example = "screen-256color";
+        type = types.str;
+        description = "Set the $TERM variable.";
+      };
+
+      secureSocket = mkOption {
+        default = true;
+        type = types.bool;
+        description = ''
+          Store tmux socket under /run, which is more secure than /tmp, but as a
+          downside it doesn't survive user logout.
+        '';
+      };
+    };
+  };
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+    environment = {
+      etc."tmux.conf".text = tmuxConf;
+
+      systemPackages = [ pkgs.tmux ];
+
+      variables = {
+        TMUX_TMPDIR = lib.optional cfg.secureSocket ''''${XDG_RUNTIME_DIR:-"/run/user/$(id -u)"}'';
+      };
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/tsm-client.nix b/nixpkgs/nixos/modules/programs/tsm-client.nix
new file mode 100644
index 000000000000..eb6f12475286
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/tsm-client.nix
@@ -0,0 +1,287 @@
+{ config, lib, pkgs, ... }:
+
+let
+
+  inherit (builtins) length map;
+  inherit (lib.attrsets) attrNames filterAttrs hasAttr mapAttrs mapAttrsToList optionalAttrs;
+  inherit (lib.modules) mkDefault mkIf;
+  inherit (lib.options) literalExample mkEnableOption mkOption;
+  inherit (lib.strings) concatStringsSep optionalString toLower;
+  inherit (lib.types) addCheck attrsOf lines loaOf nullOr package path port str strMatching submodule;
+
+  # Checks if given list of strings contains unique
+  # elements when compared without considering case.
+  # Type: checkIUnique :: [string] -> bool
+  # Example: checkIUnique ["foo" "Foo"] => false
+  checkIUnique = lst:
+    let
+      lenUniq = l: length (lib.lists.unique l);
+    in
+      lenUniq lst == lenUniq (map toLower lst);
+
+  # TSM rejects servername strings longer than 64 chars.
+  servernameType = strMatching ".{1,64}";
+
+  serverOptions = { name, config, ... }: {
+    options.name = mkOption {
+      type = servernameType;
+      example = "mainTsmServer";
+      description = ''
+        Local name of the IBM TSM server,
+        must be uncapitalized and no longer than 64 chars.
+        The value will be used for the
+        <literal>server</literal>
+        directive in <filename>dsm.sys</filename>.
+      '';
+    };
+    options.server = mkOption {
+      type = strMatching ".+";
+      example = "tsmserver.company.com";
+      description = ''
+        Host/domain name or IP address of the IBM TSM server.
+        The value will be used for the
+        <literal>tcpserveraddress</literal>
+        directive in <filename>dsm.sys</filename>.
+      '';
+    };
+    options.port = mkOption {
+      type = addCheck port (p: p<=32767);
+      default = 1500;  # official default
+      description = ''
+        TCP port of the IBM TSM server.
+        The value will be used for the
+        <literal>tcpport</literal>
+        directive in <filename>dsm.sys</filename>.
+        TSM does not support ports above 32767.
+      '';
+    };
+    options.node = mkOption {
+      type = strMatching ".+";
+      example = "MY-TSM-NODE";
+      description = ''
+        Target node name on the IBM TSM server.
+        The value will be used for the
+        <literal>nodename</literal>
+        directive in <filename>dsm.sys</filename>.
+      '';
+    };
+    options.genPasswd = mkEnableOption ''
+      automatic client password generation.
+      This option influences the
+      <literal>passwordaccess</literal>
+      directive in <filename>dsm.sys</filename>.
+      The password will be stored in the directory
+      given by the option <option>passwdDir</option>.
+      <emphasis>Caution</emphasis>:
+      If this option is enabled and the server forces
+      to renew the password (e.g. on first connection),
+      a random password will be generated and stored
+    '';
+    options.passwdDir = mkOption {
+      type = path;
+      example = "/home/alice/tsm-password";
+      description = ''
+        Directory that holds the TSM
+        node's password information.
+        The value will be used for the
+        <literal>passworddir</literal>
+        directive in <filename>dsm.sys</filename>.
+      '';
+    };
+    options.includeExclude = mkOption {
+      type = lines;
+      default = "";
+      example = ''
+        exclude.dir     /nix/store
+        include.encrypt /home/.../*
+      '';
+      description = ''
+        <literal>include.*</literal> and
+        <literal>exclude.*</literal> directives to be
+        used when sending files to the IBM TSM server.
+        The lines will be written into a file that the
+        <literal>inclexcl</literal>
+        directive in <filename>dsm.sys</filename> points to.
+      '';
+    };
+    options.extraConfig = mkOption {
+      # TSM option keys are case insensitive;
+      # we have to ensure there are no keys that
+      # differ only by upper and lower case.
+      type = addCheck
+        (attrsOf (nullOr str))
+        (attrs: checkIUnique (attrNames attrs));
+      default = {};
+      example.compression = "yes";
+      example.passwordaccess = null;
+      description = ''
+        Additional key-value pairs for the server stanza.
+        Values must be strings, or <literal>null</literal>
+        for the key not to be used in the stanza
+        (e.g. to overrule values generated by other options).
+      '';
+    };
+    options.text = mkOption {
+      type = lines;
+      example = literalExample
+        ''lib.modules.mkAfter "compression no"'';
+      description = ''
+        Additional text lines for the server stanza.
+        This option can be used if certion configuration keys
+        must be used multiple times or ordered in a certain way
+        as the <option>extraConfig</option> option can't
+        control the order of lines in the resulting stanza.
+        Note that the <literal>server</literal>
+        line at the beginning of the stanza is
+        not part of this option's value.
+      '';
+    };
+    options.stanza = mkOption {
+      type = str;
+      internal = true;
+      visible = false;
+      description = "Server stanza text generated from the options.";
+    };
+    config.name = mkDefault name;
+    # Client system-options file directives are explained here:
+    # https://www.ibm.com/support/knowledgecenter/SSEQVQ_8.1.8/client/c_opt_usingopts.html
+    config.extraConfig =
+      mapAttrs (lib.trivial.const mkDefault) (
+        {
+          commmethod = "v6tcpip";  # uses v4 or v6, based on dns lookup result
+          tcpserveraddress = config.server;
+          tcpport = builtins.toString config.port;
+          nodename = config.node;
+          passwordaccess = if config.genPasswd then "generate" else "prompt";
+          passworddir = ''"${config.passwdDir}"'';
+        } // optionalAttrs (config.includeExclude!="") {
+          inclexcl = ''"${pkgs.writeText "inclexcl.dsm.sys" config.includeExclude}"'';
+        }
+      );
+    config.text =
+      let
+        attrset = filterAttrs (k: v: v!=null) config.extraConfig;
+        mkLine = k: v: k + optionalString (v!="") "  ${v}";
+        lines = mapAttrsToList mkLine attrset;
+      in
+        concatStringsSep "\n" lines;
+    config.stanza = ''
+      server  ${config.name}
+      ${config.text}
+    '';
+  };
+
+  options.programs.tsmClient = {
+    enable = mkEnableOption ''
+      IBM Spectrum Protect (Tivoli Storage Manager, TSM)
+      client command line applications with a
+      client system-options file "dsm.sys"
+    '';
+    servers = mkOption {
+      type = loaOf (submodule [ serverOptions ]);
+      default = {};
+      example.mainTsmServer = {
+        server = "tsmserver.company.com";
+        node = "MY-TSM-NODE";
+        extraConfig.compression = "yes";
+      };
+      description = ''
+        Server definitions ("stanzas")
+        for the client system-options file.
+      '';
+    };
+    defaultServername = mkOption {
+      type = nullOr servernameType;
+      default = null;
+      example = "mainTsmServer";
+      description = ''
+        If multiple server stanzas are declared with
+        <option>programs.tsmClient.servers</option>,
+        this option may be used to name a default
+        server stanza that IBM TSM uses in the absence of
+        a user-defined <filename>dsm.opt</filename> file.
+        This option translates to a
+        <literal>defaultserver</literal> configuration line.
+      '';
+    };
+    dsmSysText = mkOption {
+      type = lines;
+      readOnly = true;
+      description = ''
+        This configuration key contains the effective text
+        of the client system-options file "dsm.sys".
+        It should not be changed, but may be
+        used to feed the configuration into other
+        TSM-depending packages used on the system.
+      '';
+    };
+    package = mkOption {
+      type = package;
+      default = pkgs.tsm-client;
+      defaultText = "pkgs.tsm-client";
+      example = literalExample "pkgs.tsm-client-withGui";
+      description = ''
+        The TSM client derivation to be
+        added to the system environment.
+        It will called with <literal>.override</literal>
+        to add paths to the client system-options file.
+      '';
+    };
+    wrappedPackage = mkOption {
+      type = package;
+      readOnly = true;
+      description = ''
+        The TSM client derivation, wrapped with the path
+        to the client system-options file "dsm.sys".
+        This option is to provide the effective derivation
+        for other modules that want to call TSM executables.
+      '';
+    };
+  };
+
+  cfg = config.programs.tsmClient;
+
+  assertions = [
+    {
+      assertion = checkIUnique (mapAttrsToList (k: v: v.name) cfg.servers);
+      message = ''
+        TSM servernames contain duplicate name
+        (note that case doesn't matter!)
+      '';
+    }
+    {
+      assertion = (cfg.defaultServername!=null)->(hasAttr cfg.defaultServername cfg.servers);
+      message = "TSM defaultServername not found in list of servers";
+    }
+  ];
+
+  dsmSysText = ''
+    ****  IBM Spectrum Protect (Tivoli Storage Manager)
+    ****  client system-options file "dsm.sys".
+    ****  Do not edit!
+    ****  This file is generated by NixOS configuration.
+
+    ${optionalString (cfg.defaultServername!=null) "defaultserver  ${cfg.defaultServername}"}
+
+    ${concatStringsSep "\n" (mapAttrsToList (k: v: v.stanza) cfg.servers)}
+  '';
+
+in
+
+{
+
+  inherit options;
+
+  config = mkIf cfg.enable {
+    inherit assertions;
+    programs.tsmClient.dsmSysText = dsmSysText;
+    programs.tsmClient.wrappedPackage = cfg.package.override rec {
+      dsmSysCli = pkgs.writeText "dsm.sys" cfg.dsmSysText;
+      dsmSysApi = dsmSysCli;
+    };
+    environment.systemPackages = [ cfg.wrappedPackage ];
+  };
+
+  meta.maintainers = [ lib.maintainers.yarny ];
+
+}
diff --git a/nixpkgs/nixos/modules/programs/udevil.nix b/nixpkgs/nixos/modules/programs/udevil.nix
new file mode 100644
index 000000000000..ba5670f9dfe9
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/udevil.nix
@@ -0,0 +1,14 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.udevil;
+
+in {
+  options.programs.udevil.enable = mkEnableOption "udevil";
+
+  config = mkIf cfg.enable {
+    security.wrappers.udevil.source = "${lib.getBin pkgs.udevil}/bin/udevil";
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/venus.nix b/nixpkgs/nixos/modules/programs/venus.nix
new file mode 100644
index 000000000000..110570ac3f06
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/venus.nix
@@ -0,0 +1,173 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+  cfg = config.services.venus;
+
+  configFile = pkgs.writeText "venus.ini"
+    ''
+      [Planet]
+      name = ${cfg.name}
+      link = ${cfg.link}
+      owner_name = ${cfg.ownerName}
+      owner_email = ${cfg.ownerEmail}
+      output_theme = ${cfg.cacheDirectory}/theme
+      output_dir = ${cfg.outputDirectory}
+      cache_directory = ${cfg.cacheDirectory}
+      items_per_page = ${toString cfg.itemsPerPage}
+      ${(concatStringsSep "\n\n"
+            (map ({ name, feedUrl, homepageUrl }:
+            ''
+              [${feedUrl}]
+              name = ${name}
+              link = ${homepageUrl}
+            '') cfg.feeds))}
+    '';
+
+in
+{
+
+  options = {
+    services.venus = {
+      enable = mkOption {
+        default = false;
+        type = types.bool;
+        description = ''
+          Planet Venus is an awesome ‘river of news’ feed reader. It downloads
+          news feeds published by web sites and aggregates their content
+          together into a single combined feed, latest news first.
+        '';
+      };
+
+      dates = mkOption {
+        default = "*:0/15";
+        type = types.str;
+        description = ''
+          Specification (in the format described by
+          <citerefentry><refentrytitle>systemd.time</refentrytitle>
+          <manvolnum>7</manvolnum></citerefentry>) of the time at
+          which the Venus will collect feeds.
+        '';
+      };
+
+      user = mkOption {
+        default = "root";
+        type = types.str;
+        description = ''
+          User for running venus script.
+        '';
+      };
+
+      group = mkOption {
+        default = "root";
+        type = types.str;
+        description = ''
+          Group for running venus script.
+        '';
+      };
+
+      name = mkOption {
+        default = "NixOS Planet";
+        type = types.str;
+        description = ''
+          Your planet's name.
+        '';
+      };
+
+      link = mkOption {
+        default = "http://planet.nixos.org";
+        type = types.str;
+        description = ''
+          Link to the main page.
+        '';
+      };
+
+      ownerName = mkOption {
+        default = "Rok Garbas";
+        type = types.str;
+        description = ''
+          Your name.
+        '';
+      };
+
+      ownerEmail = mkOption {
+        default = "some@example.com";
+        type = types.str;
+        description = ''
+          Your e-mail address.
+        '';
+      };
+
+      outputTheme = mkOption {
+        default = "${pkgs.venus}/themes/classic_fancy";
+        type = types.path;
+        description = ''
+          Directory containing a config.ini file which is merged with this one.
+          This is typically used to specify templating and bill of material
+          information.
+        '';
+      };
+
+      outputDirectory = mkOption {
+        type = types.path;
+        description = ''
+          Directory to place output files.
+        '';
+      };
+
+      cacheDirectory = mkOption {
+        default = "/var/cache/venus";
+        type = types.path;
+        description = ''
+            Where cached feeds are stored.
+        '';
+      };
+
+      itemsPerPage = mkOption {
+        default = 15;
+        type = types.int;
+        description = ''
+          How many items to put on each page.
+        '';
+      };
+
+      feeds = mkOption {
+        default = [];
+        example = [
+          {
+            name = "Rok Garbas";
+            feedUrl= "http://url/to/rss/feed.xml";
+            homepageUrl = "http://garbas.si";
+          }
+        ];
+        description = ''
+          List of feeds.
+        '';
+      };
+
+    };
+  };
+
+  config = mkIf cfg.enable {
+
+    system.activationScripts.venus =
+      ''
+        mkdir -p ${cfg.outputDirectory}
+        chown ${cfg.user}:${cfg.group} ${cfg.outputDirectory} -R
+        rm -rf ${cfg.cacheDirectory}/theme
+        mkdir -p ${cfg.cacheDirectory}/theme
+        cp -R ${cfg.outputTheme}/* ${cfg.cacheDirectory}/theme
+        chown ${cfg.user}:${cfg.group} ${cfg.cacheDirectory} -R
+      '';
+
+    systemd.services.venus =
+      { description = "Planet Venus Feed Reader";
+        path  = [ pkgs.venus ];
+        script = "exec venus-planet ${configFile}";
+        serviceConfig.User = "${cfg.user}";
+        serviceConfig.Group = "${cfg.group}";
+        startAt = cfg.dates;
+      };
+
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/vim.nix b/nixpkgs/nixos/modules/programs/vim.nix
new file mode 100644
index 000000000000..fe0e7f2c6d6b
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/vim.nix
@@ -0,0 +1,23 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.vim;
+in {
+  options.programs.vim = {
+    defaultEditor = mkOption {
+      type = types.bool;
+      default = false;
+      description = ''
+        When enabled, installs vim and configures vim to be the default editor
+        using the EDITOR environment variable.
+      '';
+    };
+  };
+
+  config = mkIf cfg.defaultEditor {
+        environment.systemPackages = [ pkgs.vim ];
+        environment.variables = { EDITOR = mkOverride 900 "vim"; };
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/virtualbox.nix b/nixpkgs/nixos/modules/programs/virtualbox.nix
new file mode 100644
index 000000000000..be96cf23b396
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/virtualbox.nix
@@ -0,0 +1,8 @@
+let
+  msg = "Importing <nixpkgs/nixos/modules/programs/virtualbox.nix> is "
+      + "deprecated, please use `virtualisation.virtualbox.host.enable = true' "
+      + "instead.";
+in {
+  config.warnings = [ msg ];
+  config.virtualisation.virtualbox.host.enable = true;
+}
diff --git a/nixpkgs/nixos/modules/programs/wavemon.nix b/nixpkgs/nixos/modules/programs/wavemon.nix
new file mode 100644
index 000000000000..ac665fe4a023
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/wavemon.nix
@@ -0,0 +1,28 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.wavemon;
+in {
+  options = {
+    programs.wavemon = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to add wavemon to the global environment and configure a
+          setcap wrapper for it.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = with pkgs; [ wavemon ];
+    security.wrappers.wavemon = {
+      source = "${pkgs.wavemon}/bin/wavemon";
+      capabilities = "cap_net_admin+ep";
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/way-cooler.nix b/nixpkgs/nixos/modules/programs/way-cooler.nix
new file mode 100644
index 000000000000..f27bd42bd764
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/way-cooler.nix
@@ -0,0 +1,78 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.way-cooler;
+  way-cooler = pkgs.way-cooler;
+
+  wcWrapped = pkgs.writeShellScriptBin "way-cooler" ''
+    ${cfg.extraSessionCommands}
+    exec ${pkgs.dbus}/bin/dbus-run-session ${way-cooler}/bin/way-cooler
+  '';
+  wcJoined = pkgs.symlinkJoin {
+    name = "way-cooler-wrapped";
+    paths = [ wcWrapped way-cooler ];
+  };
+  configFile = readFile "${way-cooler}/etc/way-cooler/init.lua";
+  spawnBar = ''
+    util.program.spawn_at_startup("lemonbar");
+  '';
+in
+{
+  options.programs.way-cooler = {
+    enable = mkEnableOption "way-cooler";
+
+    extraSessionCommands = mkOption {
+      default     = "";
+      type        = types.lines;
+      example = ''
+        export XKB_DEFAULT_LAYOUT=us,de
+        export XKB_DEFAULT_VARIANT=,nodeadkeys
+        export XKB_DEFAULT_OPTIONS=grp:caps_toggle,
+      '';
+      description = ''
+        Shell commands executed just before way-cooler is started.
+      '';
+    };
+
+    extraPackages = mkOption {
+      type = with types; listOf package;
+      default = with pkgs; [
+        westonLite xwayland dmenu
+      ];
+      example = literalExample ''
+        with pkgs; [
+          westonLite xwayland dmenu
+        ]
+      '';
+      description = ''
+        Extra packages to be installed system wide.
+      '';
+    };
+
+    enableBar = mkOption {
+      type = types.bool;
+      default = true;
+      description = ''
+        Whether to enable an unofficial bar.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ wcJoined ] ++ cfg.extraPackages;
+
+    security.pam.services.wc-lock = {};
+    environment.etc."way-cooler/init.lua".text = ''
+      ${configFile}
+      ${optionalString cfg.enableBar spawnBar}
+    '';
+
+    hardware.opengl.enable = mkDefault true;
+    fonts.enableDefaultFonts = mkDefault true;
+    programs.dconf.enable = mkDefault true;
+  };
+
+  meta.maintainers = with maintainers; [ gnidorah ];
+}
diff --git a/nixpkgs/nixos/modules/programs/waybar.nix b/nixpkgs/nixos/modules/programs/waybar.nix
new file mode 100644
index 000000000000..22530e6c7d4d
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/waybar.nix
@@ -0,0 +1,20 @@
+{ lib, pkgs, config, ... }:
+
+with lib;
+
+{
+  options.programs.waybar = {
+    enable = mkEnableOption "waybar";
+  };
+
+  config = mkIf config.programs.waybar.enable {
+    systemd.user.services.waybar = {
+      description = "Waybar as systemd service";
+      wantedBy = [ "graphical-session.target" ];
+      partOf = [ "graphical-session.target" ];
+      script = "${pkgs.waybar}/bin/waybar";
+    };
+  };
+
+  meta.maintainers = [ maintainers.FlorianFranzen ];
+}
diff --git a/nixpkgs/nixos/modules/programs/wireshark.nix b/nixpkgs/nixos/modules/programs/wireshark.nix
new file mode 100644
index 000000000000..819f15b98a05
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/wireshark.nix
@@ -0,0 +1,42 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.wireshark;
+  wireshark = cfg.package;
+in {
+  options = {
+    programs.wireshark = {
+      enable = mkOption {
+        type = types.bool;
+        default = false;
+        description = ''
+          Whether to add Wireshark to the global environment and configure a
+          setcap wrapper for 'dumpcap' for users in the 'wireshark' group.
+        '';
+      };
+      package = mkOption {
+        type = types.package;
+        default = pkgs.wireshark-cli;
+        defaultText = "pkgs.wireshark-cli";
+        description = ''
+          Which Wireshark package to install in the global environment.
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ wireshark ];
+    users.groups.wireshark = {};
+
+    security.wrappers.dumpcap = {
+      source = "${wireshark}/bin/dumpcap";
+      capabilities = "cap_net_raw+p";
+      owner = "root";
+      group = "wireshark";
+      permissions = "u+rx,g+x";
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/xfs_quota.nix b/nixpkgs/nixos/modules/programs/xfs_quota.nix
new file mode 100644
index 000000000000..648fd9a8a94f
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/xfs_quota.nix
@@ -0,0 +1,110 @@
+# Configuration for the xfs_quota command
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.programs.xfs_quota;
+
+  limitOptions = opts: concatStringsSep " " [
+    (optionalString (opts.sizeSoftLimit != null) "bsoft=${opts.sizeSoftLimit}")
+    (optionalString (opts.sizeHardLimit != null) "bhard=${opts.sizeHardLimit}")
+  ];
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    programs.xfs_quota = {
+      projects = mkOption {
+        default = {};
+        type = types.attrsOf (types.submodule {
+          options = {
+            id = mkOption {
+              type = types.int;
+              description = "Project ID.";
+            };
+
+            fileSystem = mkOption {
+              type = types.str;
+              description = "XFS filesystem hosting the xfs_quota project.";
+              default = "/";
+            };
+
+            path = mkOption {
+              type = types.str;
+              description = "Project directory.";
+            };
+
+            sizeSoftLimit = mkOption {
+              type = types.nullOr types.str;
+              default = null;
+              example = "30g";
+              description = "Soft limit of the project size";
+            };
+
+            sizeHardLimit = mkOption {
+              type = types.nullOr types.str;
+              default = null;
+              example = "50g";
+              description = "Hard limit of the project size.";
+            };
+          };
+        });
+
+        description = "Setup of xfs_quota projects. Make sure the filesystem is mounted with the pquota option.";
+
+        example = {
+          "projname" = {
+            id = 50;
+            path = "/xfsprojects/projname";
+            sizeHardLimit = "50g";
+          };
+        };
+      };
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf (cfg.projects != {}) {
+
+    environment.etc.projects.source = pkgs.writeText "etc-project"
+      (concatStringsSep "\n" (mapAttrsToList
+        (name: opts: "${toString opts.id}:${opts.path}") cfg.projects));
+
+    environment.etc.projid.source = pkgs.writeText "etc-projid"
+      (concatStringsSep "\n" (mapAttrsToList
+        (name: opts: "${name}:${toString opts.id}") cfg.projects));
+
+    systemd.services = mapAttrs' (name: opts:
+      nameValuePair "xfs_quota-${name}" {
+        description = "Setup xfs_quota for project ${name}";
+        script = ''
+          ${pkgs.xfsprogs.bin}/bin/xfs_quota -x -c 'project -s ${name}' ${opts.fileSystem}
+          ${pkgs.xfsprogs.bin}/bin/xfs_quota -x -c 'limit -p ${limitOptions opts} ${name}' ${opts.fileSystem}
+        '';
+
+        wantedBy = [ "multi-user.target" ];
+        after = [ ((replaceChars [ "/" ] [ "-" ] opts.fileSystem) + ".mount") ];
+
+        restartTriggers = [ config.environment.etc.projects.source ];
+
+        serviceConfig = {
+          Type = "oneshot";
+          RemainAfterExit = true;
+        };
+      }
+    ) cfg.projects;
+
+  };
+
+}
diff --git a/nixpkgs/nixos/modules/programs/xonsh.nix b/nixpkgs/nixos/modules/programs/xonsh.nix
new file mode 100644
index 000000000000..5cd2a49f8073
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/xonsh.nix
@@ -0,0 +1,60 @@
+# This module defines global configuration for the xonsh.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.programs.xonsh;
+
+in
+
+{
+
+  options = {
+
+    programs.xonsh = {
+
+      enable = mkOption {
+        default = false;
+        description = ''
+          Whether to configure xonsh as an interactive shell.
+        '';
+        type = types.bool;
+      };
+
+      package = mkOption {
+        type = types.package;
+        default = pkgs.xonsh;
+        example = literalExample "pkgs.xonsh.override { configFile = \"/path/to/xonshrc\"; }";
+        description = ''
+          xonsh package to use.
+        '';
+      };
+
+      config = mkOption {
+        default = "";
+        description = "Control file to customize your shell behavior.";
+        type = types.lines;
+      };
+
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    environment.etc."xonshrc".text = cfg.config;
+
+    environment.systemPackages = [ cfg.package ];
+
+    environment.shells =
+      [ "/run/current-system/sw/bin/xonsh"
+        "${cfg.package}/bin/xonsh"
+      ];
+
+  };
+
+}
+
diff --git a/nixpkgs/nixos/modules/programs/xss-lock.nix b/nixpkgs/nixos/modules/programs/xss-lock.nix
new file mode 100644
index 000000000000..070463311db5
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/xss-lock.nix
@@ -0,0 +1,44 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.xss-lock;
+in
+{
+  options.programs.xss-lock = {
+    enable = mkEnableOption "xss-lock";
+
+    lockerCommand = mkOption {
+      default = "${pkgs.i3lock}/bin/i3lock";
+      example = literalExample ''''${pkgs.i3lock-fancy}/bin/i3lock-fancy'';
+      type = types.string;
+      description = "Locker to be used with xsslock";
+    };
+
+    extraOptions = mkOption {
+      default = [ ];
+      example = [ "--ignore-sleep" ];
+      type = types.listOf types.str;
+      description = ''
+        Additional command-line arguments to pass to
+        <command>xss-lock</command>.
+      '';
+    };
+  };
+
+  config = mkIf cfg.enable {
+    systemd.user.services.xss-lock = {
+      description = "XSS Lock Daemon";
+      wantedBy = [ "graphical-session.target" ];
+      partOf = [ "graphical-session.target" ];
+      serviceConfig.ExecStart = with lib;
+        strings.concatStringsSep " " ([
+            "${pkgs.xss-lock}/bin/xss-lock"
+          ] ++ (map escapeShellArg cfg.extraOptions) ++ [
+            "--"
+            cfg.lockerCommand
+        ]);
+    };
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/yabar.nix b/nixpkgs/nixos/modules/programs/yabar.nix
new file mode 100644
index 000000000000..db085211366e
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/yabar.nix
@@ -0,0 +1,162 @@
+{ lib, pkgs, config, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.yabar;
+
+  mapExtra = v: lib.concatStringsSep "\n" (mapAttrsToList (
+    key: val: "${key} = ${if (isString val) then "\"${val}\"" else "${builtins.toString val}"};"
+  ) v);
+
+  listKeys = r: concatStringsSep "," (map (n: "\"${n}\"") (attrNames r));
+
+  configFile = let
+    bars = mapAttrsToList (
+      name: cfg: ''
+        ${name}: {
+          font: "${cfg.font}";
+          position: "${cfg.position}";
+
+          ${mapExtra cfg.extra}
+
+          block-list: [${listKeys cfg.indicators}]
+
+          ${concatStringsSep "\n" (mapAttrsToList (
+            name: cfg: ''
+              ${name}: {
+                exec: "${cfg.exec}";
+                align: "${cfg.align}";
+                ${mapExtra cfg.extra}
+              };
+            ''
+          ) cfg.indicators)}
+        };
+      ''
+    ) cfg.bars;
+  in pkgs.writeText "yabar.conf" ''
+    bar-list = [${listKeys cfg.bars}];
+    ${concatStringsSep "\n" bars}
+  '';
+in
+  {
+    options.programs.yabar = {
+      enable = mkEnableOption "yabar";
+
+      package = mkOption {
+        default = pkgs.yabar-unstable;
+        example = literalExample "pkgs.yabar";
+        type = types.package;
+
+        # `yabar-stable` segfaults under certain conditions.
+        apply = x: if x == pkgs.yabar-unstable then x else flip warn x ''
+          It's not recommended to use `yabar' with `programs.yabar', the (old) stable release
+          tends to segfault under certain circumstances:
+
+          * https://github.com/geommer/yabar/issues/86
+          * https://github.com/geommer/yabar/issues/68
+          * https://github.com/geommer/yabar/issues/143
+
+          Most of them don't occur on master anymore, until a new release is published, it's recommended
+          to use `yabar-unstable'.
+        '';
+
+        description = ''
+          The package which contains the `yabar` binary.
+
+          Nixpkgs provides the `yabar` and `yabar-unstable`
+          derivations since 18.03, so it's possible to choose.
+        '';
+      };
+
+      bars = mkOption {
+        default = {};
+        type = types.attrsOf(types.submodule {
+          options = {
+            font = mkOption {
+              default = "sans bold 9";
+              example = "Droid Sans, FontAwesome Bold 9";
+              type = types.string;
+
+              description = ''
+                The font that will be used to draw the status bar.
+              '';
+            };
+
+            position = mkOption {
+              default = "top";
+              example = "bottom";
+              type = types.enum [ "top" "bottom" ];
+
+              description = ''
+                The position where the bar will be rendered.
+              '';
+            };
+
+            extra = mkOption {
+              default = {};
+              type = types.attrsOf types.string;
+
+              description = ''
+                An attribute set which contains further attributes of a bar.
+              '';
+            };
+
+            indicators = mkOption {
+              default = {};
+              type = types.attrsOf(types.submodule {
+                options.exec = mkOption {
+                  example = "YABAR_DATE";
+                  type = types.string;
+                  description = ''
+                     The type of the indicator to be executed.
+                  '';
+                };
+
+                options.align = mkOption {
+                  default = "left";
+                  example = "right";
+                  type = types.enum [ "left" "center" "right" ];
+
+                  description = ''
+                    Whether to align the indicator at the left or right of the bar.
+                  '';
+                };
+
+                options.extra = mkOption {
+                  default = {};
+                  type = types.attrsOf (types.either types.string types.int);
+
+                  description = ''
+                    An attribute set which contains further attributes of a indicator.
+                  '';
+                };
+              });
+
+              description = ''
+                Indicators that should be rendered by yabar.
+              '';
+            };
+          };
+        });
+
+        description = ''
+          List of bars that should be rendered by yabar.
+        '';
+      };
+    };
+
+    config = mkIf cfg.enable {
+      systemd.user.services.yabar = {
+        description = "yabar service";
+        wantedBy = [ "graphical-session.target" ];
+        partOf = [ "graphical-session.target" ];
+
+        script = ''
+          ${cfg.package}/bin/yabar -c ${configFile}
+        '';
+
+        serviceConfig.Restart = "always";
+      };
+    };
+  }
diff --git a/nixpkgs/nixos/modules/programs/zmap.nix b/nixpkgs/nixos/modules/programs/zmap.nix
new file mode 100644
index 000000000000..2e27fce4d7c6
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/zmap.nix
@@ -0,0 +1,18 @@
+{ pkgs, config, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.zmap;
+in {
+  options.programs.zmap = {
+    enable = mkEnableOption "ZMap";
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = [ pkgs.zmap ];
+
+    environment.etc."zmap/blacklist.conf".source = "${pkgs.zmap}/etc/zmap/blacklist.conf";
+    environment.etc."zmap/zmap.conf".source = "${pkgs.zmap}/etc/zmap.conf";
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/zsh/oh-my-zsh.nix b/nixpkgs/nixos/modules/programs/zsh/oh-my-zsh.nix
new file mode 100644
index 000000000000..f4df4e983e42
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/zsh/oh-my-zsh.nix
@@ -0,0 +1,138 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfg = config.programs.zsh.ohMyZsh;
+
+  mkLinkFarmEntry = name: dir:
+    let
+      env = pkgs.buildEnv {
+        name = "zsh-${name}-env";
+        paths = cfg.customPkgs;
+        pathsToLink = "/share/zsh/${dir}";
+      };
+    in
+      { inherit name; path = "${env}/share/zsh/${dir}"; };
+
+  mkLinkFarmEntry' = name: mkLinkFarmEntry name name;
+
+  custom =
+    if cfg.custom != null then cfg.custom
+    else if length cfg.customPkgs == 0 then null
+    else pkgs.linkFarm "oh-my-zsh-custom" [
+      (mkLinkFarmEntry' "themes")
+      (mkLinkFarmEntry "completions" "site-functions")
+      (mkLinkFarmEntry' "plugins")
+    ];
+
+in
+  {
+    options = {
+      programs.zsh.ohMyZsh = {
+        enable = mkOption {
+          default = false;
+          description = ''
+            Enable oh-my-zsh.
+          '';
+        };
+
+        package = mkOption {
+          default = pkgs.oh-my-zsh;
+          defaultText = "pkgs.oh-my-zsh";
+          description = ''
+            Package to install for `oh-my-zsh` usage.
+          '';
+
+          type = types.package;
+        };
+
+        plugins = mkOption {
+          default = [];
+          type = types.listOf(types.str);
+          description = ''
+            List of oh-my-zsh plugins
+          '';
+        };
+
+        custom = mkOption {
+          default = null;
+          type = with types; nullOr str;
+          description = ''
+            Path to a custom oh-my-zsh package to override config of oh-my-zsh.
+            (Can't be used along with `customPkgs`).
+          '';
+        };
+
+        customPkgs = mkOption {
+          default = [];
+          type = types.listOf types.package;
+          description = ''
+            List of custom packages that should be loaded into `oh-my-zsh`.
+          '';
+        };
+
+        theme = mkOption {
+          default = "";
+          type = types.str;
+          description = ''
+            Name of the theme to be used by oh-my-zsh.
+          '';
+        };
+
+        cacheDir = mkOption {
+          default = "$HOME/.cache/oh-my-zsh";
+          type = types.str;
+          description = ''
+            Cache directory to be used by `oh-my-zsh`.
+            Without this option it would default to the read-only nix store.
+          '';
+        };
+      };
+    };
+
+    config = mkIf cfg.enable {
+
+      # Prevent zsh from overwriting oh-my-zsh's prompt
+      programs.zsh.promptInit = mkDefault "";
+
+      environment.systemPackages = [ cfg.package ];
+
+      programs.zsh.interactiveShellInit = ''
+        # oh-my-zsh configuration generated by NixOS
+        export ZSH=${cfg.package}/share/oh-my-zsh
+
+        ${optionalString (length(cfg.plugins) > 0)
+          "plugins=(${concatStringsSep " " cfg.plugins})"
+        }
+
+        ${optionalString (custom != null)
+          "ZSH_CUSTOM=\"${custom}\""
+        }
+
+        ${optionalString (stringLength(cfg.theme) > 0)
+          "ZSH_THEME=\"${cfg.theme}\""
+        }
+
+        ${optionalString (cfg.cacheDir != null) ''
+          if [[ ! -d "${cfg.cacheDir}" ]]; then
+            mkdir -p "${cfg.cacheDir}"
+          fi
+          ZSH_CACHE_DIR=${cfg.cacheDir}
+        ''}
+
+        source $ZSH/oh-my-zsh.sh
+      '';
+
+      assertions = [
+        {
+          assertion = cfg.custom != null -> cfg.customPkgs == [];
+          message = "If `cfg.custom` is set for `ZSH_CUSTOM`, `customPkgs` can't be used!";
+        }
+      ];
+
+    };
+
+    meta.doc = ./oh-my-zsh.xml;
+  }
diff --git a/nixpkgs/nixos/modules/programs/zsh/oh-my-zsh.xml b/nixpkgs/nixos/modules/programs/zsh/oh-my-zsh.xml
new file mode 100644
index 000000000000..568c2de65576
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/zsh/oh-my-zsh.xml
@@ -0,0 +1,155 @@
+<chapter xmlns="http://docbook.org/ns/docbook"
+         xmlns:xlink="http://www.w3.org/1999/xlink"
+         xmlns:xi="http://www.w3.org/2001/XInclude"
+         version="5.0"
+         xml:id="module-programs-zsh-ohmyzsh">
+ <title>Oh my ZSH</title>
+ <para>
+  <literal><link xlink:href="https://ohmyz.sh/">oh-my-zsh</link></literal> is a
+  framework to manage your <link xlink:href="https://www.zsh.org/">ZSH</link>
+  configuration including completion scripts for several CLI tools or custom
+  prompt themes.
+ </para>
+ <section xml:id="module-programs-oh-my-zsh-usage">
+  <title>Basic usage</title>
+
+  <para>
+   The module uses the <literal>oh-my-zsh</literal> package with all available
+   features. The initial setup using Nix expressions is fairly similar to the
+   configuration format of <literal>oh-my-zsh</literal>.
+<programlisting>
+{
+  programs.zsh.ohMyZsh = {
+    enable = true;
+    plugins = [ "git" "python" "man" ];
+    theme = "agnoster";
+  };
+}
+</programlisting>
+   For a detailed explanation of these arguments please refer to the
+   <link xlink:href="https://github.com/robbyrussell/oh-my-zsh/wiki"><literal>oh-my-zsh</literal>
+   docs</link>.
+  </para>
+
+  <para>
+   The expression generates the needed configuration and writes it into your
+   <literal>/etc/zshrc</literal>.
+  </para>
+ </section>
+ <section xml:id="module-programs-oh-my-zsh-additions">
+  <title>Custom additions</title>
+
+  <para>
+   Sometimes third-party or custom scripts such as a modified theme may be
+   needed. <literal>oh-my-zsh</literal> provides the
+   <link xlink:href="https://github.com/robbyrussell/oh-my-zsh/wiki/Customization#overriding-internals"><literal>ZSH_CUSTOM</literal></link>
+   environment variable for this which points to a directory with additional
+   scripts.
+  </para>
+
+  <para>
+   The module can do this as well:
+<programlisting>
+{
+  programs.zsh.ohMyZsh.custom = "~/path/to/custom/scripts";
+}
+</programlisting>
+  </para>
+ </section>
+ <section xml:id="module-programs-oh-my-zsh-environments">
+  <title>Custom environments</title>
+
+  <para>
+   There are several extensions for <literal>oh-my-zsh</literal> packaged in
+   <literal>nixpkgs</literal>. One of them is
+   <link xlink:href="https://github.com/spwhitt/nix-zsh-completions">nix-zsh-completions</link>
+   which bundles completion scripts and a plugin for
+   <literal>oh-my-zsh</literal>.
+  </para>
+
+  <para>
+   Rather than using a single mutable path for <literal>ZSH_CUSTOM</literal>,
+   it's also possible to generate this path from a list of Nix packages:
+<programlisting>
+{ pkgs, ... }:
+{
+  programs.zsh.ohMyZsh.customPkgs = with pkgs; [
+    pkgs.nix-zsh-completions
+    # and even more...
+  ];
+}
+</programlisting>
+   Internally a single store path will be created using
+   <literal>buildEnv</literal>. Please refer to the docs of
+   <link xlink:href="https://nixos.org/nixpkgs/manual/#sec-building-environment"><literal>buildEnv</literal></link>
+   for further reference.
+  </para>
+
+  <para>
+   <emphasis>Please keep in mind that this is not compatible with
+   <literal>programs.zsh.ohMyZsh.custom</literal> as it requires an immutable
+   store path while <literal>custom</literal> shall remain mutable! An
+   evaluation failure will be thrown if both <literal>custom</literal> and
+   <literal>customPkgs</literal> are set.</emphasis>
+  </para>
+ </section>
+ <section xml:id="module-programs-oh-my-zsh-packaging-customizations">
+  <title>Package your own customizations</title>
+
+  <para>
+   If third-party customizations (e.g. new themes) are supposed to be added to
+   <literal>oh-my-zsh</literal> there are several pitfalls to keep in mind:
+  </para>
+
+  <itemizedlist>
+   <listitem>
+    <para>
+     To comply with the default structure of <literal>ZSH</literal> the entire
+     output needs to be written to <literal>$out/share/zsh.</literal>
+    </para>
+   </listitem>
+   <listitem>
+    <para>
+     Completion scripts are supposed to be stored at
+     <literal>$out/share/zsh/site-functions</literal>. This directory is part
+     of the
+     <literal><link xlink:href="http://zsh.sourceforge.net/Doc/Release/Functions.html">fpath</link></literal>
+     and the package should be compatible with pure <literal>ZSH</literal>
+     setups. The module will automatically link the contents of
+     <literal>site-functions</literal> to completions directory in the proper
+     store path.
+    </para>
+   </listitem>
+   <listitem>
+    <para>
+     The <literal>plugins</literal> directory needs the structure
+     <literal>pluginname/pluginname.plugin.zsh</literal> as structured in the
+     <link xlink:href="https://github.com/robbyrussell/oh-my-zsh/tree/91b771914bc7c43dd7c7a43b586c5de2c225ceb7/plugins">upstream
+     repo.</link>
+    </para>
+   </listitem>
+  </itemizedlist>
+
+  <para>
+   A derivation for <literal>oh-my-zsh</literal> may look like this:
+<programlisting>
+{ stdenv, fetchFromGitHub }:
+
+stdenv.mkDerivation rec {
+  name = "exemplary-zsh-customization-${version}";
+  version = "1.0.0";
+  src = fetchFromGitHub {
+    # path to the upstream repository
+  };
+
+  dontBuild = true;
+  installPhase = ''
+    mkdir -p $out/share/zsh/site-functions
+    cp {themes,plugins} $out/share/zsh
+    cp completions $out/share/zsh/site-functions
+  '';
+}
+</programlisting>
+  </para>
+ </section>
+</chapter>
diff --git a/nixpkgs/nixos/modules/programs/zsh/zinputrc b/nixpkgs/nixos/modules/programs/zsh/zinputrc
new file mode 100644
index 000000000000..6121f3e21f16
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/zsh/zinputrc
@@ -0,0 +1,42 @@
+# Stolen from ArchWiki
+
+# create a zkbd compatible hash;
+# to add other keys to this hash, see: man 5 terminfo
+typeset -A key
+
+key[Home]=${terminfo[khome]}
+
+key[End]=${terminfo[kend]}
+key[Insert]=${terminfo[kich1]}
+key[Delete]=${terminfo[kdch1]}
+key[Up]=${terminfo[kcuu1]}
+key[Down]=${terminfo[kcud1]}
+key[Left]=${terminfo[kcub1]}
+key[Right]=${terminfo[kcuf1]}
+key[PageUp]=${terminfo[kpp]}
+key[PageDown]=${terminfo[knp]}
+
+# setup key accordingly
+[[ -n "${key[Home]}"     ]]  && bindkey  "${key[Home]}"     beginning-of-line
+[[ -n "${key[End]}"      ]]  && bindkey  "${key[End]}"      end-of-line
+[[ -n "${key[Insert]}"   ]]  && bindkey  "${key[Insert]}"   overwrite-mode
+[[ -n "${key[Delete]}"   ]]  && bindkey  "${key[Delete]}"   delete-char
+[[ -n "${key[Up]}"       ]]  && bindkey  "${key[Up]}"       up-line-or-history
+[[ -n "${key[Down]}"     ]]  && bindkey  "${key[Down]}"     down-line-or-history
+[[ -n "${key[Left]}"     ]]  && bindkey  "${key[Left]}"     backward-char
+[[ -n "${key[Right]}"    ]]  && bindkey  "${key[Right]}"    forward-char
+[[ -n "${key[PageUp]}"   ]]  && bindkey  "${key[PageUp]}"   beginning-of-buffer-or-history
+[[ -n "${key[PageDown]}" ]]  && bindkey  "${key[PageDown]}" end-of-buffer-or-history
+
+# Finally, make sure the terminal is in application mode, when zle is
+# active. Only then are the values from $terminfo valid.
+if (( ${+terminfo[smkx]} )) && (( ${+terminfo[rmkx]} )); then
+    function zle-line-init () {
+        printf '%s' "${terminfo[smkx]}"
+    }
+    function zle-line-finish () {
+        printf '%s' "${terminfo[rmkx]}"
+    }
+    zle -N zle-line-init
+    zle -N zle-line-finish
+fi
diff --git a/nixpkgs/nixos/modules/programs/zsh/zsh-autoenv.nix b/nixpkgs/nixos/modules/programs/zsh/zsh-autoenv.nix
new file mode 100644
index 000000000000..630114bcda9f
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/zsh/zsh-autoenv.nix
@@ -0,0 +1,28 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.zsh.zsh-autoenv;
+in {
+  options = {
+    programs.zsh.zsh-autoenv = {
+      enable = mkEnableOption "zsh-autoenv";
+      package = mkOption {
+        default = pkgs.zsh-autoenv;
+        defaultText = "pkgs.zsh-autoenv";
+        description = ''
+          Package to install for `zsh-autoenv` usage.
+        '';
+
+        type = types.package;
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    programs.zsh.interactiveShellInit = ''
+      source ${cfg.package}/share/zsh-autoenv/autoenv.zsh
+    '';
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/zsh/zsh-autosuggestions.nix b/nixpkgs/nixos/modules/programs/zsh/zsh-autosuggestions.nix
new file mode 100644
index 000000000000..ded17f38a618
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/zsh/zsh-autosuggestions.nix
@@ -0,0 +1,60 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.zsh.autosuggestions;
+in
+{
+  options.programs.zsh.autosuggestions = {
+
+    enable = mkEnableOption "zsh-autosuggestions";
+
+    highlightStyle = mkOption {
+      type = types.str;
+      default = "fg=8"; # https://github.com/zsh-users/zsh-autosuggestions/tree/v0.4.3#suggestion-highlight-style
+      description = "Highlight style for suggestions ({fore,back}ground color)";
+      example = "fg=cyan";
+    };
+
+    strategy = mkOption {
+      type = types.enum [ "history" "match_prev_cmd" ];
+      default = "history";
+      description = ''
+        Set ZSH_AUTOSUGGEST_STRATEGY to choose the strategy for generating suggestions.
+        There are currently two to choose from:
+
+          * history: Chooses the most recent match.
+          * match_prev_cmd: Chooses the most recent match whose preceding history item matches
+            the most recently executed command (more info). Note that this strategy won't work as
+            expected with ZSH options that don't preserve the history order such as
+            HIST_IGNORE_ALL_DUPS or HIST_EXPIRE_DUPS_FIRST.
+      '';
+    };
+
+    extraConfig = mkOption {
+      type = with types; attrsOf str;
+      default = {};
+      description = "Attribute set with additional configuration values";
+      example = literalExample ''
+        {
+          "ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE" = "20";
+        }
+      '';
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    programs.zsh.interactiveShellInit = ''
+      source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.zsh
+
+      export ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="${cfg.highlightStyle}"
+      export ZSH_AUTOSUGGEST_STRATEGY=("${cfg.strategy}")
+
+      ${concatStringsSep "\n" (mapAttrsToList (key: value: ''export ${key}="${value}"'') cfg.extraConfig)}
+    '';
+
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/zsh/zsh-syntax-highlighting.nix b/nixpkgs/nixos/modules/programs/zsh/zsh-syntax-highlighting.nix
new file mode 100644
index 000000000000..89087a229eb7
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/zsh/zsh-syntax-highlighting.nix
@@ -0,0 +1,100 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  cfg = config.programs.zsh.syntaxHighlighting;
+in
+{
+  options = {
+    programs.zsh.syntaxHighlighting = {
+      enable = mkEnableOption "zsh-syntax-highlighting";
+
+      highlighters = mkOption {
+        default = [ "main" ];
+
+        # https://github.com/zsh-users/zsh-syntax-highlighting/blob/master/docs/highlighters.md
+        type = types.listOf(types.enum([
+          "main"
+          "brackets"
+          "pattern"
+          "cursor"
+          "root"
+          "line"
+        ]));
+
+        description = ''
+          Specifies the highlighters to be used by zsh-syntax-highlighting.
+
+          The following defined options can be found here:
+          https://github.com/zsh-users/zsh-syntax-highlighting/blob/master/docs/highlighters.md
+        '';
+      };
+
+      patterns = mkOption {
+        default = {};
+        type = types.attrsOf types.string;
+
+        example = literalExample ''
+          {
+            "rm -rf *" = "fg=white,bold,bg=red";
+          }
+        '';
+
+        description = ''
+          Specifies custom patterns to be highlighted by zsh-syntax-highlighting.
+
+          Please refer to the docs for more information about the usage:
+          https://github.com/zsh-users/zsh-syntax-highlighting/blob/master/docs/highlighters/pattern.md
+        '';
+      };
+      styles = mkOption {
+        default = {};
+        type = types.attrsOf types.string;
+
+        example = literalExample ''
+          {
+            "alias" = "fg=magenta,bold";
+          }
+        '';
+
+        description = ''
+          Specifies custom styles to be highlighted by zsh-syntax-highlighting.
+
+          Please refer to the docs for more information about the usage:
+          https://github.com/zsh-users/zsh-syntax-highlighting/blob/master/docs/highlighters/main.md
+        '';
+      };
+    };
+  };
+
+  config = mkIf cfg.enable {
+    environment.systemPackages = with pkgs; [ zsh-syntax-highlighting ];
+
+    assertions = [
+      {
+        assertion = length(attrNames cfg.patterns) > 0 -> elem "pattern" cfg.highlighters;
+        message = ''
+          When highlighting patterns, "pattern" needs to be included in the list of highlighters.
+        '';
+      }
+    ];
+
+    programs.zsh.interactiveShellInit = with pkgs;
+      lib.concatStringsSep "\n" ([
+        "source ${zsh-syntax-highlighting}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh"
+      ] ++ optional (length(cfg.highlighters) > 0)
+        "ZSH_HIGHLIGHT_HIGHLIGHTERS=(${concatStringsSep " " cfg.highlighters})"
+        ++ optionals (length(attrNames cfg.patterns) > 0)
+          (mapAttrsToList (
+            pattern: design:
+            "ZSH_HIGHLIGHT_PATTERNS+=('${pattern}' '${design}')"
+          ) cfg.patterns)
+        ++ optionals (length(attrNames cfg.styles) > 0)
+          (mapAttrsToList (
+            styles: design:
+            "ZSH_HIGHLIGHT_STYLES[${styles}]='${design}'"
+          ) cfg.styles)
+      );
+  };
+}
diff --git a/nixpkgs/nixos/modules/programs/zsh/zsh.nix b/nixpkgs/nixos/modules/programs/zsh/zsh.nix
new file mode 100644
index 000000000000..bd1a77680663
--- /dev/null
+++ b/nixpkgs/nixos/modules/programs/zsh/zsh.nix
@@ -0,0 +1,238 @@
+# This module defines global configuration for the zshell.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  cfge = config.environment;
+
+  cfg = config.programs.zsh;
+
+  zshAliases = concatStringsSep "\n" (
+    mapAttrsFlatten (k: v: "alias ${k}=${escapeShellArg v}")
+      (filterAttrs (k: v: v != null) cfg.shellAliases)
+  );
+
+in
+
+{
+
+  options = {
+
+    programs.zsh = {
+
+      enable = mkOption {
+        default = false;
+        description = ''
+          Whether to configure zsh as an interactive shell. To enable zsh for
+          a particular user, use the <option>users.users.&lt;name?&gt;.shell</option>
+          option for that user. To enable zsh system-wide use the
+          <option>users.defaultUserShell</option> option.
+        '';
+        type = types.bool;
+      };
+
+      shellAliases = mkOption {
+        default = {};
+        description = ''
+          Set of aliases for zsh shell, which overrides <option>environment.shellAliases</option>.
+          See <option>environment.shellAliases</option> for an option format description.
+        '';
+        type = with types; attrsOf (nullOr (either str path));
+      };
+
+      shellInit = mkOption {
+        default = "";
+        description = ''
+          Shell script code called during zsh shell initialisation.
+        '';
+        type = types.lines;
+      };
+
+      loginShellInit = mkOption {
+        default = "";
+        description = ''
+          Shell script code called during zsh login shell initialisation.
+        '';
+        type = types.lines;
+      };
+
+      interactiveShellInit = mkOption {
+        default = "";
+        description = ''
+          Shell script code called during interactive zsh shell initialisation.
+        '';
+        type = types.lines;
+      };
+
+      promptInit = mkOption {
+        default = ''
+          if [ "$TERM" != dumb ]; then
+              autoload -U promptinit && promptinit && prompt walters
+          fi
+        '';
+        description = ''
+          Shell script code used to initialise the zsh prompt.
+        '';
+        type = types.lines;
+      };
+
+      histSize = mkOption {
+        default = 2000;
+        description = ''
+          Change history size.
+        '';
+        type = types.int;
+      };
+
+      histFile = mkOption {
+        default = "$HOME/.zsh_history";
+        description = ''
+          Change history file.
+        '';
+        type = types.str;
+      };
+
+      setOptions = mkOption {
+        type = types.listOf types.str;
+        default = [
+          "HIST_IGNORE_DUPS" "SHARE_HISTORY" "HIST_FCNTL_LOCK"
+        ];
+        example = [ "EXTENDED_HISTORY" "RM_STAR_WAIT" ];
+        description = ''
+          Configure zsh options.
+        '';
+      };
+
+      enableCompletion = mkOption {
+        default = true;
+        description = ''
+          Enable zsh completion for all interactive zsh shells.
+        '';
+        type = types.bool;
+      };
+
+
+      enableGlobalCompInit = mkOption {
+        default = cfg.enableCompletion;
+        description = ''
+          Enable execution of compinit call for all interactive zsh shells.
+
+          This option can be disabled if the user wants to extend its
+          <literal>fpath</literal> and a custom <literal>compinit</literal>
+          call in the local config is required.
+        '';
+        type = types.bool;
+      };
+
+    };
+
+  };
+
+  config = mkIf cfg.enable {
+
+    programs.zsh.shellAliases = mapAttrs (name: mkDefault) cfge.shellAliases;
+
+    environment.etc."zshenv".text =
+      ''
+        # /etc/zshenv: DO NOT EDIT -- this file has been generated automatically.
+        # This file is read for all shells.
+
+        # Only execute this file once per shell.
+        # But don't clobber the environment of interactive non-login children!
+        if [ -n "$__ETC_ZSHENV_SOURCED" ]; then return; fi
+        export __ETC_ZSHENV_SOURCED=1
+
+        if [ -z "$__NIXOS_SET_ENVIRONMENT_DONE" ]; then
+            . ${config.system.build.setEnvironment}
+        fi
+
+        ${cfge.shellInit}
+
+        ${cfg.shellInit}
+
+        # Read system-wide modifications.
+        if test -f /etc/zshenv.local; then
+            . /etc/zshenv.local
+        fi
+      '';
+
+    environment.etc."zprofile".text =
+      ''
+        # /etc/zprofile: DO NOT EDIT -- this file has been generated automatically.
+        # This file is read for login shells.
+
+        # Only execute this file once per shell.
+        if [ -n "$__ETC_ZPROFILE_SOURCED" ]; then return; fi
+        __ETC_ZPROFILE_SOURCED=1
+
+        ${cfge.loginShellInit}
+
+        ${cfg.loginShellInit}
+
+        # Read system-wide modifications.
+        if test -f /etc/zprofile.local; then
+            . /etc/zprofile.local
+        fi
+      '';
+
+    environment.etc."zshrc".text =
+      ''
+        # /etc/zshrc: DO NOT EDIT -- this file has been generated automatically.
+        # This file is read for interactive shells.
+
+        # Only execute this file once per shell.
+        if [ -n "$__ETC_ZSHRC_SOURCED" -o -n "$NOSYSZSHRC" ]; then return; fi
+        __ETC_ZSHRC_SOURCED=1
+
+        . /etc/zinputrc
+
+        # Don't export these, otherwise other shells (bash) will try to use same histfile
+        SAVEHIST=${toString cfg.histSize}
+        HISTSIZE=${toString cfg.histSize}
+        HISTFILE=${cfg.histFile}
+
+        HELPDIR="${pkgs.zsh}/share/zsh/$ZSH_VERSION/help"
+
+        # Tell zsh how to find installed completions
+        for p in ''${(z)NIX_PROFILES}; do
+            fpath+=($p/share/zsh/site-functions $p/share/zsh/$ZSH_VERSION/functions $p/share/zsh/vendor-completions)
+        done
+
+        ${optionalString cfg.enableGlobalCompInit "autoload -U compinit && compinit"}
+
+        ${cfge.interactiveShellInit}
+
+        ${cfg.interactiveShellInit}
+
+        ${optionalString (cfg.setOptions != []) "setopt ${concatStringsSep " " cfg.setOptions}"}
+
+        ${zshAliases}
+
+        ${cfg.promptInit}
+
+        # Read system-wide modifications.
+        if test -f /etc/zshrc.local; then
+            . /etc/zshrc.local
+        fi
+      '';
+
+    environment.etc."zinputrc".source = ./zinputrc;
+
+    environment.systemPackages = [ pkgs.zsh ]
+      ++ optional cfg.enableCompletion pkgs.nix-zsh-completions;
+
+    environment.pathsToLink = optional cfg.enableCompletion "/share/zsh";
+
+    #users.defaultUserShell = mkDefault "/run/current-system/sw/bin/zsh";
+
+    environment.shells =
+      [ "/run/current-system/sw/bin/zsh"
+        "${pkgs.zsh}/bin/zsh"
+      ];
+
+  };
+
+}