diff options
Diffstat (limited to 'nixos/modules/services')
54 files changed, 1643 insertions, 439 deletions
diff --git a/nixos/modules/services/cluster/kubernetes.nix b/nixos/modules/services/cluster/kubernetes.nix index d00c1aaa1055..ba09f04d502b 100644 --- a/nixos/modules/services/cluster/kubernetes.nix +++ b/nixos/modules/services/cluster/kubernetes.nix @@ -78,12 +78,6 @@ in { type = types.int; }; - readOnlyPort = mkOption { - description = "Kubernets apiserver read-only port."; - default = 7080; - type = types.int; - }; - securePort = mkOption { description = "Kubernetes apiserver secure port."; default = 6443; @@ -102,10 +96,16 @@ in { type = types.str; }; + clientCaFile = mkOption { + description = "Kubernetes apiserver CA file for client auth."; + default = ""; + type = types.str; + }; + tokenAuth = mkOption { description = '' Kubernetes apiserver token authentication file. See - <link xlink:href="https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/authentication.md"/> + <link xlink:href="http://kubernetes.io/v1.0/docs/admin/authentication.html"/> ''; default = {}; example = literalExample '' @@ -120,7 +120,7 @@ in { authorizationMode = mkOption { description = '' Kubernetes apiserver authorization mode (AlwaysAllow/AlwaysDeny/ABAC). See - <link xlink:href="https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/authorization.md"/> + <link xlink:href="http://kubernetes.io/v1.0/docs/admin/authorization.html"/> ''; default = "AlwaysAllow"; type = types.enum ["AlwaysAllow" "AlwaysDeny" "ABAC"]; @@ -129,7 +129,7 @@ in { authorizationPolicy = mkOption { description = '' Kubernetes apiserver authorization policy file. See - <link xlink:href="https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/authorization.md"/> + <link xlink:href="http://kubernetes.io/v1.0/docs/admin/authorization.html"/> ''; default = []; example = literalExample '' @@ -158,6 +158,38 @@ in { type = types.str; }; + runtimeConfig = mkOption { + description = '' + Api runtime configuration. See + <link xlink:href="http://kubernetes.io/v1.0/docs/admin/cluster-management.html"/> + ''; + default = ""; + example = "api/all=false,api/v1=true"; + type = types.str; + }; + + admissionControl = mkOption { + description = '' + Kubernetes admission control plugins to use. See + <link xlink:href="http://kubernetes.io/v1.0/docs/admin/admission-controllers.html"/> + ''; + default = ["AlwaysAdmit"]; + example = [ + "NamespaceLifecycle" "NamespaceExists" "LimitRanger" + "SecurityContextDeny" "ServiceAccount" "ResourceQuota" + ]; + type = types.listOf types.str; + }; + + serviceAccountKey = mkOption { + description = '' + Kubernetes apiserver PEM-encoded x509 RSA private or public key file, + used to verify ServiceAccount tokens. + ''; + default = null; + type = types.nullOr types.path; + }; + extraOpts = mkOption { description = "Kubernetes apiserver extra command line options."; default = ""; @@ -222,14 +254,26 @@ in { type = types.str; }; - machines = mkOption { - description = "Kubernetes controller list of machines to schedule to schedule onto"; - default = []; - type = types.listOf types.str; + serviceAccountPrivateKey = mkOption { + description = '' + Kubernetes controller manager PEM-encoded private RSA key file used to + sign service account tokens + ''; + default = null; + type = types.nullOr types.path; + }; + + rootCaFile = mkOption { + description = '' + Kubernetes controller manager certificate authority file included in + service account's token secret. + ''; + default = null; + type = types.nullOr types.path; }; extraOpts = mkOption { - description = "Kubernetes controller extra command line options."; + description = "Kubernetes controller manager extra command line options."; default = ""; type = types.str; }; @@ -260,6 +304,20 @@ in { type = types.int; }; + healthz = { + bind = mkOption { + description = "Kubernetes kubelet healthz listening address."; + default = "127.0.0.1"; + type = types.str; + }; + + port = mkOption { + description = "Kubernetes kubelet healthz port."; + default = 10248; + type = types.int; + }; + }; + hostname = mkOption { description = "Kubernetes kubelet hostname override"; default = config.networking.hostName; @@ -273,7 +331,10 @@ in { }; apiServers = mkOption { - description = "Kubernetes kubelet list of Kubernetes API servers for publishing events, and reading pods and services."; + description = '' + Kubernetes kubelet list of Kubernetes API servers for publishing events, + and reading pods and services. + ''; default = ["${cfg.apiserver.address}:${toString cfg.apiserver.port}"]; type = types.listOf types.str; }; @@ -374,7 +435,6 @@ in { --etcd-servers=${concatMapStringsSep "," (f: "http://${f}") cfg.etcdServers} \ --insecure-bind-address=${cfg.apiserver.address} \ --insecure-port=${toString cfg.apiserver.port} \ - --read-only-port=${toString cfg.apiserver.readOnlyPort} \ --bind-address=${cfg.apiserver.publicAddress} \ --allow-privileged=${if cfg.apiserver.allowPrivileged then "true" else "false"} \ ${optionalString (cfg.apiserver.tlsCertFile!="") @@ -383,22 +443,24 @@ in { "--tls-private-key-file=${cfg.apiserver.tlsPrivateKeyFile}"} \ ${optionalString (cfg.apiserver.tokenAuth!=[]) "--token-auth-file=${tokenAuthFile}"} \ + ${optionalString (cfg.apiserver.clientCaFile!="") + "--client-ca-file=${cfg.apiserver.clientCaFile}"} \ --authorization-mode=${cfg.apiserver.authorizationMode} \ ${optionalString (cfg.apiserver.authorizationMode == "ABAC") "--authorization-policy-file=${authorizationPolicyFile}"} \ --secure-port=${toString cfg.apiserver.securePort} \ --service-cluster-ip-range=${cfg.apiserver.portalNet} \ + ${optionalString (cfg.apiserver.runtimeConfig!="") + "--runtime-config=${cfg.apiserver.runtimeConfig}"} \ + --admission_control=${concatStringsSep "," cfg.apiserver.admissionControl} \ + ${optionalString (cfg.apiserver.serviceAccountKey!=null) + "--service-account-key-file=${cfg.apiserver.serviceAccountKey}"} \ --logtostderr=true \ ${optionalString cfg.verbose "--v=6 --log-flush-frequency=1s"} \ ${cfg.apiserver.extraOpts} ''; User = "kubernetes"; }; - postStart = '' - until ${pkgs.curl}/bin/curl -s -o /dev/null 'http://${cfg.apiserver.address}:${toString cfg.apiserver.port}/'; do - sleep 1; - done - ''; }; }) @@ -431,7 +493,10 @@ in { --address=${cfg.controllerManager.address} \ --port=${toString cfg.controllerManager.port} \ --master=${cfg.controllerManager.master} \ - --machines=${concatStringsSep "," cfg.controllerManager.machines} \ + ${optionalString (cfg.controllerManager.serviceAccountPrivateKey!=null) + "--service-account-private-key-file=${cfg.controllerManager.serviceAccountPrivateKey}"} \ + ${optionalString (cfg.controllerManager.rootCaFile!=null) + "--root-ca-file=${cfg.controllerManager.rootCaFile}"} \ --logtostderr=true \ ${optionalString cfg.verbose "--v=6 --log-flush-frequency=1s"} \ ${cfg.controllerManager.extraOpts} @@ -454,6 +519,8 @@ in { --register-node=${if cfg.kubelet.registerNode then "true" else "false"} \ --address=${cfg.kubelet.address} \ --port=${toString cfg.kubelet.port} \ + --healthz-bind-address=${cfg.kubelet.healthz.bind} \ + --healthz-port=${toString cfg.kubelet.healthz.port} \ --hostname-override=${cfg.kubelet.hostname} \ --allow-privileged=${if cfg.kubelet.allowPrivileged then "true" else "false"} \ --root-dir=${cfg.dataDir} \ @@ -483,6 +550,8 @@ in { ${optionalString cfg.verbose "--v=6 --log-flush-frequency=1s"} \ ${cfg.proxy.extraOpts} ''; + Restart = "always"; # Retry connection + RestartSec = "5s"; }; }; }) @@ -504,9 +573,6 @@ in { User = "kubernetes"; }; }; - - services.skydns.enable = mkDefault true; - services.skydns.domain = mkDefault cfg.kubelet.clusterDomain; }) (mkIf (any (el: el == "master") cfg.roles) { @@ -524,6 +590,9 @@ in { (mkIf (any (el: el == "node" || el == "master") cfg.roles) { services.etcd.enable = mkDefault true; + + services.skydns.enable = mkDefault true; + services.skydns.domain = mkDefault cfg.kubelet.clusterDomain; }) (mkIf ( @@ -538,8 +607,10 @@ in { serviceConfig.Type = "oneshot"; script = '' mkdir -p /var/run/kubernetes - chown kubernetes /var/run/kubernetes - ln -fs ${pkgs.writeText "kubernetes-dockercfg" cfg.dockerCfg} /var/run/kubernetes/.dockercfg + chown kubernetes /var/lib/kubernetes + + rm ${cfg.dataDir}/.dockercfg || true + ln -fs ${pkgs.writeText "kubernetes-dockercfg" cfg.dockerCfg} ${cfg.dataDir}/.dockercfg ''; }; diff --git a/nixos/modules/services/databases/postgresql.nix b/nixos/modules/services/databases/postgresql.nix index 97927055ce37..bae088c6610e 100644 --- a/nixos/modules/services/databases/postgresql.nix +++ b/nixos/modules/services/databases/postgresql.nix @@ -154,6 +154,12 @@ in config = mkIf config.services.postgresql.enable { + services.postgresql.package = + # Note: when changing the default, make it conditional on + # ‘system.stateVersion’ to maintain compatibility with existing + # systems! + mkDefault pkgs.postgresql94; + services.postgresql.authentication = mkAfter '' # Generated file; do not edit! @@ -207,6 +213,7 @@ in serviceConfig = { ExecStart = "@${postgresql}/bin/postgres postgres ${toString flags}"; + ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; User = "postgres"; Group = "postgres"; PermissionsStartOnly = true; diff --git a/nixos/modules/services/databases/riak.nix b/nixos/modules/services/databases/riak.nix new file mode 100644 index 000000000000..bee768fa42ae --- /dev/null +++ b/nixos/modules/services/databases/riak.nix @@ -0,0 +1,148 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.riak; + +in + +{ + + ###### interface + + options = { + + services.riak = { + + enable = mkEnableOption "riak"; + + package = mkOption { + type = types.package; + example = literalExample "pkgs.riak2"; + description = '' + Riak package to use. + ''; + }; + + nodeName = mkOption { + type = types.string; + default = "riak@127.0.0.1"; + description = '' + Name of the Erlang node. + ''; + }; + + distributedCookie = mkOption { + type = types.string; + default = "riak"; + description = '' + Cookie for distributed node communication. All nodes in the + same cluster should use the same cookie or they will not be able to + communicate. + ''; + }; + + dataDir = mkOption { + type = types.path; + default = "/var/db/riak"; + description = '' + Data directory for Riak. + ''; + }; + + logDir = mkOption { + type = types.path; + default = "/var/log/riak"; + description = '' + Log directory for Riak. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Additional text to be appended to <filename>riak.conf</filename>. + ''; + }; + + }; + + }; + + ###### implementation + + config = mkIf cfg.enable { + + environment.systemPackages = [ cfg.package ]; + environment.etc."riak/riak.conf".text = '' + nodename = ${cfg.nodeName} + distributed_cookie = ${cfg.distributedCookie} + + platform_log_dir = ${cfg.logDir} + platform_etc_dir = /etc/riak + platform_data_dir = ${cfg.dataDir} + + ${cfg.extraConfig} + ''; + + users.extraUsers.riak = { + name = "riak"; + uid = config.ids.uids.riak; + group = "riak"; + description = "Riak server user"; + }; + + users.extraGroups.riak.gid = config.ids.gids.riak; + + systemd.services.riak = { + description = "Riak Server"; + + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + path = [ + pkgs.utillinux # for `logger` + pkgs.bash + ]; + + environment.RIAK_DATA_DIR = "${cfg.dataDir}"; + environment.RIAK_LOG_DIR = "${cfg.logDir}"; + environment.RIAK_ETC_DIR = "/etc/riak"; + + preStart = '' + if ! test -e ${cfg.logDir}; then + mkdir -m 0755 -p ${cfg.logDir} + chown -R riak ${cfg.logDir} + fi + + if ! test -e ${cfg.dataDir}; then + mkdir -m 0700 -p ${cfg.dataDir} + chown -R riak ${cfg.dataDir} + fi + ''; + + serviceConfig = { + ExecStart = "${cfg.package}/bin/riak console"; + ExecStop = "${cfg.package}/bin/riak stop"; + StandardInput = "tty"; + User = "riak"; + Group = "riak"; + PermissionsStartOnly = true; + # Give Riak a decent amount of time to clean up. + TimeoutStopSec = 120; + LimitNOFILE = 65536; + }; + + unitConfig.RequiresMountsFor = [ + "${cfg.dataDir}" + "${cfg.logDir}" + "/etc/riak" + ]; + }; + + }; + +} diff --git a/nixos/modules/services/hardware/freefall.nix b/nixos/modules/services/hardware/freefall.nix index 6e6960bac491..7867956c1ab0 100644 --- a/nixos/modules/services/hardware/freefall.nix +++ b/nixos/modules/services/hardware/freefall.nix @@ -39,11 +39,14 @@ with lib; mkService = dev: assert dev != ""; let dev' = utils.escapeSystemdPath dev; in - nameValuePair "freefall-${dev'}" - { description = "Free-fall protection for ${dev}"; + nameValuePair "freefall-${dev'}" { + description = "Free-fall protection for ${dev}"; after = [ "${dev'}.device" ]; wantedBy = [ "${dev'}.device" ]; path = [ pkgs.freefall ]; + unitConfig = { + DefaultDependencies = false; + }; serviceConfig = { ExecStart = "${pkgs.freefall}/bin/freefall ${dev}"; Restart = "on-failure"; diff --git a/nixos/modules/services/hardware/tcsd.nix b/nixos/modules/services/hardware/tcsd.nix index 220b154bd97a..d957b5063d38 100644 --- a/nixos/modules/services/hardware/tcsd.nix +++ b/nixos/modules/services/hardware/tcsd.nix @@ -17,8 +17,8 @@ let # what is available directly from the PCR registers. firmware_log_file = /sys/kernel/security/tpm0/binary_bios_measurements kernel_log_file = /sys/kernel/security/ima/binary_runtime_measurements - #firmware_pcrs = 0,1,2,3,4,5,6,7 - #kernel_pcrs = 10,11 + firmware_pcrs = ${cfg.firmwarePCRs} + kernel_pcrs = ${cfg.kernelPCRs} platform_cred = ${cfg.platformCred} conformance_cred = ${cfg.conformanceCred} endorsement_cred = ${cfg.endorsementCred} @@ -60,20 +60,32 @@ in }; stateDir = mkOption { - default = "/var/lib/tpm"; + default = "/var/lib/tpm"; type = types.path; - description = '' + description = '' The location of the system persistent storage file. The system persistent storage file holds keys and data across restarts of the TCSD and system reboots. - ''; + ''; + }; + + firmwarePCRs = mkOption { + default = "0,1,2,3,4,5,6,7"; + type = types.string; + description = "PCR indices used in the TPM for firmware measurements."; + }; + + kernelPCRs = mkOption { + default = "8,9,10,11,12"; + type = types.string; + description = "PCR indices used in the TPM for kernel measurements."; }; platformCred = mkOption { default = "${cfg.stateDir}/platform.cert"; type = types.path; description = '' - Path to the platform credential for your TPM. Your TPM + Path to the platform credential for your TPM. Your TPM manufacturer may have provided you with a set of credentials (certificates) that should be used when creating identities using your TPM. When a user of your TPM makes an identity, diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix index fc89de777e8e..513eb27b4069 100644 --- a/nixos/modules/services/hardware/udev.nix +++ b/nixos/modules/services/hardware/udev.nix @@ -171,25 +171,23 @@ in }; hardware.firmware = mkOption { - type = types.listOf types.path; + type = types.listOf types.package; default = []; description = '' - List of directories containing firmware files. Such files + List of packages containing firmware files. Such files will be loaded automatically if the kernel asks for them (i.e., when it has detected specific hardware that requires - firmware to function). If more than one path contains a - firmware file with the same name, the first path in the list - takes precedence. Note that you must rebuild your system if - you add files to any of these directories. For quick testing, + firmware to function). If multiple packages contain firmware + files with the same name, the first package in the list takes + precedence. Note that you must rebuild your system if you add + files to any of these directories. For quick testing, put firmware files in <filename>/root/test-firmware</filename> - and add that directory to the list. Note that you can also - add firmware packages to this list as these are directories in - the nix store. + and add that directory to the list. ''; apply = list: pkgs.buildEnv { name = "firmware"; paths = list; - pathsToLink = [ "/" ]; + pathsToLink = [ "/lib/firmware" ]; ignoreCollisions = true; }; }; @@ -236,7 +234,7 @@ in (isYes "NET") ]; - boot.extraModprobeConfig = "options firmware_class path=${config.hardware.firmware}"; + boot.extraModprobeConfig = "options firmware_class path=${config.hardware.firmware}/lib/firmware"; system.activationScripts.udevd = '' @@ -254,7 +252,7 @@ in # Allow the kernel to find our firmware. if [ -e /sys/module/firmware_class/parameters/path ]; then - echo -n "${config.hardware.firmware}" > /sys/module/firmware_class/parameters/path + echo -n "${config.hardware.firmware}/lib/firmware" > /sys/module/firmware_class/parameters/path fi ''; diff --git a/nixos/modules/services/mail/dovecot.nix b/nixos/modules/services/mail/dovecot.nix index 50ff1b38db12..fca0d2a7f616 100644 --- a/nixos/modules/services/mail/dovecot.nix +++ b/nixos/modules/services/mail/dovecot.nix @@ -10,7 +10,7 @@ let '' base_dir = /var/run/dovecot2/ - protocols = ${optionalString cfg.enableImap "imap"} ${optionalString cfg.enablePop3 "pop3"} + protocols = ${optionalString cfg.enableImap "imap"} ${optionalString cfg.enablePop3 "pop3"} ${optionalString cfg.enableLmtp "lmtp"} '' + (if cfg.sslServerCert!="" then '' @@ -70,6 +70,11 @@ in description = "Start the IMAP listener (when Dovecot is enabled)."; }; + enableLmtp = mkOption { + default = false; + description = "Start the LMTP listener (when Dovecot is enabled)."; + }; + user = mkOption { default = "dovecot2"; description = "Dovecot user name."; diff --git a/nixos/modules/services/mail/mlmmj.nix b/nixos/modules/services/mail/mlmmj.nix index db3a266d011f..5843a6745f58 100644 --- a/nixos/modules/services/mail/mlmmj.nix +++ b/nixos/modules/services/mail/mlmmj.nix @@ -11,7 +11,7 @@ let listCtl = domain: list: "${listDir domain list}/control"; transport = domain: list: "${domain}--${list}@local.list.mlmmj mlmmj:${domain}/${list}"; virtual = domain: list: "${list}@${domain} ${domain}--${list}@local.list.mlmmj"; - alias = domain: list: "${list}: \"|${pkgs.mlmmj}/mlmmj-receive -L ${listDir domain list}/\""; + alias = domain: list: "${list}: \"|${pkgs.mlmmj}/bin/mlmmj-receive -L ${listDir domain list}/\""; subjectPrefix = list: "[${list}]"; listAddress = domain: list: "${list}@${domain}"; customHeaders = list: domain: [ "List-Id: ${list}" "Reply-To: ${list}@${domain}" ]; diff --git a/nixos/modules/services/misc/confd.nix b/nixos/modules/services/misc/confd.nix index 98738b6497bf..50532a8a16fb 100644 --- a/nixos/modules/services/misc/confd.nix +++ b/nixos/modules/services/misc/confd.nix @@ -63,7 +63,7 @@ in { package = mkOption { description = "Confd package to use."; - default = pkgs.goPackages.confd; + default = pkgs.confd; type = types.package; }; }; diff --git a/nixos/modules/services/misc/etcd.nix b/nixos/modules/services/misc/etcd.nix index 26d2753879d0..e1839b936f01 100644 --- a/nixos/modules/services/misc/etcd.nix +++ b/nixos/modules/services/misc/etcd.nix @@ -122,14 +122,6 @@ in { mkdir -m 0700 -p ${cfg.dataDir} if [ "$(id -u)" = 0 ]; then chown etcd ${cfg.dataDir}; fi ''; - postStart = '' - until ${pkgs.etcdctl}/bin/etcdctl set /nixos/state 'up'; do - sleep 1; - done - until ${pkgs.etcdctl}/bin/etcdctl get /nixos/state | grep up; do - sleep 1; - done - ''; }; environment.systemPackages = [ pkgs.etcdctl ]; diff --git a/nixos/modules/services/misc/gitit.nix b/nixos/modules/services/misc/gitit.nix index 56e735d7356b..10a706fbd71d 100644 --- a/nixos/modules/services/misc/gitit.nix +++ b/nixos/modules/services/misc/gitit.nix @@ -8,6 +8,8 @@ let homeDir = "/var/lib/gitit"; + toYesNo = b: if b then "yes" else "no"; + gititShared = with cfg.haskellPackages; gitit + "/share/" + pkgs.stdenv.system + "-" + ghc.name + "/" + gitit.pname + "-" + gitit.version; gititWithPkgs = hsPkgs: extras: hsPkgs.ghcWithPackages (self: with self; [ gitit ] ++ (extras self)); @@ -17,9 +19,6 @@ let in writeScript "gitit" '' #!${stdenv.shell} cd $HOME - export PATH="${makeSearchPath "bin" ( - [ git curl ] ++ (if cfg.pdfExport == "yes" then [texLiveFull] else []) - )}:$PATH"; export NIX_GHC="${env}/bin/ghc" export NIX_GHCPKG="${env}/bin/ghc-pkg" export NIX_GHC_DOCDIR="${env}/share/doc/ghc/html" @@ -27,11 +26,7 @@ let ${env}/bin/gitit -f ${configFile} ''; - gititOptions = let - - yesNo = types.enum [ "yes" "no" ]; - - in { + gititOptions = { enable = mkOption { type = types.bool; @@ -40,7 +35,6 @@ let }; haskellPackages = mkOption { - default = pkgs.haskellPackages; defaultText = "pkgs.haskellPackages"; example = literalExample "pkgs.haskell.packages.ghc784"; description = "haskellPackages used to build gitit and plugins."; @@ -143,7 +137,6 @@ let staticDir = mkOption { type = types.path; - default = gititShared + "/data/static"; description = '' Specifies the path of the static directory (containing javascript, css, and images). If it does not exist, gitit will create it and @@ -204,8 +197,8 @@ let }; showLhsBirdTracks = mkOption { - type = yesNo; - default = "no"; + type = types.bool; + default = false; description = '' Specifies whether to show Haskell code blocks in "bird style", with "> " at the beginning of each line. @@ -214,7 +207,6 @@ let templatesDir = mkOption { type = types.path; - default = gititShared + "/data/templates"; description = '' Specifies the path of the directory containing page templates. If it does not exist, gitit will create it with default templates. Users @@ -286,8 +278,8 @@ let }; tableOfContents = mkOption { - type = yesNo; - default = "yes"; + type = types.bool; + default = true; description = '' Specifies whether to print a tables of contents (with links to sections) on each wiki page. @@ -295,23 +287,18 @@ let }; plugins = mkOption { - type = types.path; - default = gititShared + "/plugins/Dot.hs"; + type = with types; listOf str; description = '' - Specifies a list of plugins to load. Plugins may be specified either - by their path or by their module name. If the plugin name starts + Specifies a list of plugins to load. Plugins may be specified either + by their path or by their module name. If the plugin name starts with Gitit.Plugin., gitit will assume that the plugin is an installed module and will not try to find a source file. - Examples: - plugins: plugins/DotPlugin.hs, CapitalizeEmphasisPlugin.hs - plugins: plugins/DotPlugin - plugins: Gitit.Plugin.InterwikiLinks ''; }; useCache = mkOption { - type = yesNo; - default = "no"; + type = types.bool; + default = false; description = '' Specifies whether to cache rendered pages. Note that if use-feed is selected, feeds will be cached regardless of the value of use-cache. @@ -342,14 +329,14 @@ let }; debugMode = mkOption { - type = yesNo; - default = "no"; + type = types.bool; + default = false; description = "Causes debug information to be logged while gitit is running."; }; compressResponses = mkOption { - type = yesNo; - default = "yes"; + type = types.bool; + default = true; description = "Specifies whether HTTP responses should be compressed."; }; @@ -361,16 +348,18 @@ let line of the file should contain two fields, separated by whitespace. The first field is the mime type, the second is a file extension. For example: - video/x-ms-wmx wmx +<programlisting> +video/x-ms-wmx wmx +</programlisting> If the file is not found, some simple defaults will be used. ''; }; useReCaptcha = mkOption { - type = yesNo; - default = "no"; + type = types.bool; + default = false; description = '' - If "yes", causes gitit to use the reCAPTCHA service + If true, causes gitit to use the reCAPTCHA service (http://recaptcha.net) to prevent bots from creating accounts. ''; }; @@ -475,8 +464,8 @@ let }; useFeed = mkOption { - type = yesNo; - default = "no"; + type = types.bool; + default = false; description = '' Specifies whether an ATOM feed should be enabled (for the site and for individual pages). @@ -488,19 +477,19 @@ let default = null; description = '' The base URL of the wiki, to be used in constructing feed IDs and RPX - token_urls. Set this if use-feed is 'yes' or authentication-method + token_urls. Set this if useFeed is false or authentication-method is 'rpx'. ''; }; absoluteUrls = mkOption { - type = yesNo; - default = "no"; + type = types.bool; + default = false; description = '' Make wikilinks absolute with respect to the base-url. So, for example, in a wiki served at the base URL '/wiki', on a page Sub/Page, the wikilink '[Cactus]()' will produce a link to - '/wiki/Cactus' if absolute-urls is 'yes', and a relative link to + '/wiki/Cactus' if absoluteUrls is true, and a relative link to 'Cactus' (referring to '/wiki/Sub/Cactus') if absolute-urls is 'no'. ''; }; @@ -518,10 +507,10 @@ let }; pdfExport = mkOption { - type = yesNo; - default = "no"; + type = types.bool; + default = false; description = '' - If yes, PDF will appear in export options. PDF will be created using + If true, PDF will appear in export options. PDF will be created using pdflatex, which must be installed and in the path. Note that PDF exports create significant additional server load. ''; @@ -541,10 +530,10 @@ let }; xssSanitize = mkOption { - type = yesNo; - default = "yes"; + type = types.bool; + default = true; description = '' - If yes, all HTML (including that produced by pandoc) is filtered + If true, all HTML (including that produced by pandoc) is filtered through xss-sanitize. Set to no only if you trust all of your users. ''; }; @@ -564,7 +553,7 @@ let default-page-type: ${cfg.defaultPageType} math: ${cfg.math} mathjax-script: ${cfg.mathJaxScript} - show-lhs-bird-tracks: ${cfg.showLhsBirdTracks} + show-lhs-bird-tracks: ${toYesNo cfg.showLhsBirdTracks} templates-dir: ${cfg.templatesDir} log-file: ${cfg.logFile} log-level: ${cfg.logLevel} @@ -572,16 +561,16 @@ let no-delete: ${cfg.noDelete} no-edit: ${cfg.noEdit} default-summary: ${cfg.defaultSummary} - table-of-contents: ${cfg.tableOfContents} - plugins: ${cfg.plugins} - use-cache: ${cfg.useCache} + table-of-contents: ${toYesNo cfg.tableOfContents} + plugins: ${concatStringsSep "," cfg.plugins} + use-cache: ${toYesNo cfg.useCache} cache-dir: ${cfg.cacheDir} max-upload-size: ${cfg.maxUploadSize} max-page-size: ${cfg.maxPageSize} - debug-mode: ${cfg.debugMode} - compress-responses: ${cfg.compressResponses} + debug-mode: ${toYesNo cfg.debugMode} + compress-responses: ${toYesNo cfg.compressResponses} mime-types-file: ${cfg.mimeTypesFile} - use-recaptcha: ${cfg.useReCaptcha} + use-recaptcha: ${toYesNo cfg.useReCaptcha} recaptcha-private-key: ${toString cfg.reCaptchaPrivateKey} recaptcha-public-key: ${toString cfg.reCaptchaPublicKey} access-question: ${cfg.accessQuestion} @@ -590,14 +579,14 @@ let rpx-key: ${toString cfg.rpxKey} mail-command: ${cfg.mailCommand} reset-password-message: ${cfg.resetPasswordMessage} - use-feed: ${cfg.useFeed} + use-feed: ${toYesNo cfg.useFeed} base-url: ${toString cfg.baseUrl} - absolute-urls: ${cfg.absoluteUrls} + absolute-urls: ${toYesNo cfg.absoluteUrls} feed-days: ${toString cfg.feedDays} feed-refresh-time: ${toString cfg.feedRefreshTime} - pdf-export: ${cfg.pdfExport} + pdf-export: ${toYesNo cfg.pdfExport} pandoc-user-data: ${toString cfg.pandocUserData} - xss-sanitize: ${cfg.xssSanitize} + xss-sanitize: ${toYesNo cfg.xssSanitize} ''; in @@ -608,6 +597,13 @@ in config = mkIf cfg.enable { + services.gitit = { + haskellPackages = mkDefault pkgs.haskellPackages; + staticDir = gititShared + "/data/static"; + templatesDir = gititShared + "/data/templates"; + plugins = [ ]; + }; + users.extraUsers.gitit = { group = config.users.extraGroups.gitit.name; description = "Gitit user"; @@ -625,8 +621,16 @@ in description = "Git and Pandoc Powered Wiki"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; - - preStart = with cfg; '' + path = with pkgs; [ curl ] + ++ optional cfg.pdfExport texLiveFull + ++ optional (cfg.repositoryType == "darcs") darcs + ++ optional (cfg.repositoryType == "mercurial") mercurial + ++ optional (cfg.repositoryType == "git") git; + + preStart = let + gm = "gitit@${config.networking.hostName}"; + in + with cfg; '' chown ${uid}:${gid} -R ${homeDir} for dir in ${repositoryPath} ${staticDir} ${templatesDir} ${cacheDir} do @@ -638,14 +642,35 @@ in fi done cd ${repositoryPath} - if [ ! -d .git ] - then - ${pkgs.git}/bin/git init - ${pkgs.git}/bin/git config user.email "gitit@${config.networking.hostName}" - ${pkgs.git}/bin/git config user.name "gitit" - chown ${uid}:${gid} -R {repositoryPath} - fi - cd - + ${ + if repositoryType == "darcs" then + '' + if [ ! -d _darcs ] + then + ${pkgs.darcs}/bin/darcs initialize + echo "${gm}" > _darcs/prefs/email + '' + else if repositoryType == "mercurial" then + '' + if [ ! -d .hg ] + then + ${pkgs.mercurial}/bin/hg init + cat >> .hg/hgrc <<NAMED +[ui] +username = gitit ${gm} +NAMED + '' + else + '' + if [ ! -d .git ] + then + ${pkgs.git}/bin/git init + ${pkgs.git}/bin/git config user.email "${gm}" + ${pkgs.git}/bin/git config user.name "gitit" + ''} + chown ${uid}:${gid} -R ${repositoryPath} + fi + cd - ''; serviceConfig = { diff --git a/nixos/modules/services/misc/nix-daemon.nix b/nixos/modules/services/misc/nix-daemon.nix index b5a8a7df9fca..4aed91c34978 100644 --- a/nixos/modules/services/misc/nix-daemon.nix +++ b/nixos/modules/services/misc/nix-daemon.nix @@ -78,8 +78,8 @@ in description = '' This option defines the maximum number of jobs that Nix will try to build in parallel. The default is 1. You should generally - set it to the number of CPUs in your system (e.g., 2 on an Athlon - 64 X2). + set it to the total number of logical cores in your system (e.g., 16 + for two CPUs with 4 cores each and hyper-threading). ''; }; @@ -254,7 +254,7 @@ in requireSignedBinaryCaches = mkOption { type = types.bool; - default = false; + default = true; description = '' If enabled, Nix will only download binaries from binary caches if they are cryptographically signed with any of the @@ -309,6 +309,20 @@ in ''; }; + nixPath = mkOption { + type = types.listOf types.str; + default = + [ "/nix/var/nix/profiles/per-user/root/channels/nixos" + "nixos-config=/etc/nixos/configuration.nix" + "/nix/var/nix/profiles/per-user/root/channels" + ]; + description = '' + The default Nix expression search path, used by the Nix + evaluator to look up paths enclosed in angle brackets + (e.g. <literal><nixpkgs></literal>). + ''; + }; + }; }; @@ -378,7 +392,9 @@ in }; # Set up the environment variables for running Nix. - environment.sessionVariables = cfg.envVars; + environment.sessionVariables = cfg.envVars // + { NIX_PATH = concatStringsSep ":" cfg.nixPath; + }; environment.extraInit = '' diff --git a/nixos/modules/services/misc/nix-gc.nix b/nixos/modules/services/misc/nix-gc.nix index 6a7a7f4cee72..981299352575 100644 --- a/nixos/modules/services/misc/nix-gc.nix +++ b/nixos/modules/services/misc/nix-gc.nix @@ -52,7 +52,7 @@ in systemd.services.nix-gc = { description = "Nix Garbage Collector"; - script = "exec ${config.nix.package}/bin/nix-collect-garbage ${cfg.options}"; + script = "exec ${config.nix.package}/bin/nix-store --gc ${cfg.options}"; startAt = optionalString cfg.automatic cfg.dates; }; diff --git a/nixos/modules/services/misc/rogue.nix b/nixos/modules/services/misc/rogue.nix index ed8da8a518ff..aae02e384c97 100644 --- a/nixos/modules/services/misc/rogue.nix +++ b/nixos/modules/services/misc/rogue.nix @@ -52,6 +52,7 @@ in TTYPath = "/dev/${cfg.tty}"; TTYReset = true; TTYVTDisallocate = true; + WorkingDirectory = "/tmp"; Restart = "always"; }; }; diff --git a/nixos/modules/services/monitoring/dd-agent.nix b/nixos/modules/services/monitoring/dd-agent.nix index 3e90393a662d..8c847af3bfc0 100644 --- a/nixos/modules/services/monitoring/dd-agent.nix +++ b/nixos/modules/services/monitoring/dd-agent.nix @@ -51,12 +51,37 @@ let # ganglia_port: 8651 ''; + diskConfig = pkgs.writeText "disk.yaml" '' + init_config: + + instances: + - use_mount: no + ''; + + networkConfig = pkgs.writeText "network.yaml" '' + init_config: + + instances: + # Network check only supports one configured instance + - collect_connection_state: false + excluded_interfaces: + - lo + - lo0 + ''; + postgresqlConfig = pkgs.writeText "postgres.yaml" cfg.postgresqlConfig; nginxConfig = pkgs.writeText "nginx.yaml" cfg.nginxConfig; - + mongoConfig = pkgs.writeText "mongo.yaml" cfg.mongoConfig; + etcfiles = [ { source = ddConf; target = "dd-agent/datadog.conf"; + } + { source = diskConfig; + target = "dd-agent/conf.d/disk.yaml"; + } + { source = networkConfig; + target = "dd-agent/conf.d/network.yaml"; } ] ++ (optional (cfg.postgresqlConfig != null) { source = postgresqlConfig; @@ -65,6 +90,10 @@ let (optional (cfg.nginxConfig != null) { source = nginxConfig; target = "dd-agent/conf.d/nginx.yaml"; + }) ++ + (optional (cfg.mongoConfig != null) + { source = mongoConfig; + target = "dd-agent/conf.d/mongo.yaml"; }); in { @@ -106,6 +135,12 @@ in { default = null; type = types.uniq (types.nullOr types.string); }; + + mongoConfig = mkOption { + description = "MongoDB integration configuration"; + default = null; + type = types.uniq (types.nullOr types.string); + }; }; config = mkIf cfg.enable { @@ -123,7 +158,7 @@ in { systemd.services.dd-agent = { description = "Datadog agent monitor"; - path = [ pkgs."dd-agent" pkgs.python pkgs.sysstat pkgs.procps]; + path = [ pkgs."dd-agent" pkgs.python pkgs.sysstat pkgs.procps ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { ExecStart = "${pkgs.dd-agent}/bin/dd-agent foreground"; @@ -132,7 +167,7 @@ in { Restart = "always"; RestartSec = 2; }; - restartTriggers = [ pkgs.dd-agent ddConf postgresqlConfig nginxConfig ]; + restartTriggers = [ pkgs.dd-agent ddConf diskConfig networkConfig postgresqlConfig nginxConfig mongoConfig ]; }; systemd.services.dogstatsd = { @@ -149,7 +184,7 @@ in { RestartSec = 2; }; environment.SSL_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt"; - restartTriggers = [ pkgs.dd-agent ddConf postgresqlConfig nginxConfig ]; + restartTriggers = [ pkgs.dd-agent ddConf diskConfig networkConfig postgresqlConfig nginxConfig mongoConfig ]; }; environment.etc = etcfiles; diff --git a/nixos/modules/services/monitoring/grafana.nix b/nixos/modules/services/monitoring/grafana.nix index 6a1799dedc8e..f987c4792e93 100644 --- a/nixos/modules/services/monitoring/grafana.nix +++ b/nixos/modules/services/monitoring/grafana.nix @@ -200,13 +200,13 @@ in { staticRootPath = mkOption { description = "Root path for static assets."; - default = "${cfg.package}/share/go/src/github.com/grafana/grafana/public"; + default = "${cfg.package.out}/share/go/src/github.com/grafana/grafana/public"; type = types.str; }; package = mkOption { description = "Package to use."; - default = pkgs.goPackages.grafana; + default = pkgs.grafana-backend; type = types.package; }; @@ -319,7 +319,7 @@ in { wantedBy = ["multi-user.target"]; after = ["networking.target"]; serviceConfig = { - ExecStart = "${cfg.package}/bin/grafana --config ${cfgFile} web"; + ExecStart = "${cfg.package-backend}/bin/grafana --config ${cfgFile} web"; WorkingDirectory = cfg.dataDir; User = "grafana"; }; diff --git a/nixos/modules/services/monitoring/scollector.nix b/nixos/modules/services/monitoring/scollector.nix index 179c587431ea..8b97daf8881a 100644 --- a/nixos/modules/services/monitoring/scollector.nix +++ b/nixos/modules/services/monitoring/scollector.nix @@ -20,9 +20,11 @@ let cfg.collectors)} ''; - cmdLineOpts = concatStringsSep " " ( - [ "-h=${cfg.bosunHost}" "-c=${collectors}" ] ++ cfg.extraOpts - ); + conf = pkgs.writeText "scollector.toml" '' + Host = "${cfg.bosunHost}" + ColDir = "${collectors}" + ${cfg.extraConfig} + ''; in { @@ -92,6 +94,14 @@ in { ''; }; + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra scollector configuration added to the end of scollector.toml + ''; + }; + }; }; @@ -108,7 +118,7 @@ in { PermissionsStartOnly = true; User = cfg.user; Group = cfg.group; - ExecStart = "${cfg.package}/bin/scollector ${cmdLineOpts}"; + ExecStart = "${cfg.package}/bin/scollector -conf=${conf} ${lib.concatStringsSep " " cfg.extraOpts}"; }; }; diff --git a/nixos/modules/services/monitoring/smartd.nix b/nixos/modules/services/monitoring/smartd.nix index 803bd9e9a65a..61ba16123252 100644 --- a/nixos/modules/services/monitoring/smartd.nix +++ b/nixos/modules/services/monitoring/smartd.nix @@ -4,8 +4,66 @@ with lib; let + host = config.networking.hostName or "unknown" + + optionalString (config.networking.domain != null) ".${config.networking.domain}"; + cfg = config.services.smartd; + nm = cfg.notifications.mail; + nw = cfg.notifications.wall; + nx = cfg.notifications.x11; + + smartdNotify = pkgs.writeScript "smartd-notify.sh" '' + #! ${pkgs.stdenv.shell} + ${optionalString nm.enable '' + { + cat << EOF + From: smartd on ${host} <root> + To: undisclosed-recipients:; + Subject: SMART error on $SMARTD_DEVICESTRING: $SMARTD_FAILTYPE + + $SMARTD_FULLMESSAGE + EOF + + ${pkgs.smartmontools}/sbin/smartctl -a -d "$SMARTD_DEVICETYPE" "$SMARTD_DEVICE" + } | ${nm.mailer} -i "${nm.recipient}" + ''} + ${optionalString nw.enable '' + { + cat << EOF + Problem detected with disk: $SMARTD_DEVICESTRING + Warning message from smartd is: + + $SMARTD_MESSAGE + EOF + } | ${pkgs.utillinux}/bin/wall 2>/dev/null + ''} + ${optionalString nx.enable '' + export DISPLAY=${nx.display} + { + cat << EOF + Problem detected with disk: $SMARTD_DEVICESTRING + Warning message from smartd is: + + $SMARTD_FULLMESSAGE + EOF + } | ${pkgs.xorg.xmessage}/bin/xmessage -file - 2>/dev/null & + ''} + ''; + + notifyOpts = optionalString (nm.enable || nw.enable || nx.enable) + ("-m <nomailer> -M exec ${smartdNotify} " + optionalString cfg.notifications.test "-M test "); + + smartdConf = pkgs.writeText "smartd.conf" '' + # Autogenerated smartd startup config file + DEFAULT ${notifyOpts}${cfg.defaults.monitored} + + ${concatMapStringsSep "\n" (d: "${d.device} ${d.options}") cfg.devices} + + ${optionalString cfg.autodetect + "DEVICESCAN ${notifyOpts}${cfg.defaults.autodetected}"} + ''; + smartdOpts = { name, ... }: { options = { @@ -22,34 +80,11 @@ let type = types.separatedString " "; description = "Options that determine how smartd monitors the device."; }; + }; }; - smartdMail = pkgs.writeScript "smartdmail.sh" '' - #! ${pkgs.stdenv.shell} - TMPNAM=/tmp/smartd-message.$$.tmp - if test -n "$SMARTD_ADDRESS"; then - echo >"$TMPNAM" "From: smartd <root>" - echo >>"$TMPNAM" 'To: undisclosed-recipients:;' - echo >>"$TMPNAM" "Subject: $SMARTD_SUBJECT" - echo >>"$TMPNAM" - echo >>"$TMPNAM" "Failure on $SMARTD_DEVICESTRING: $SMARTD_FAILTYPE" - echo >>"$TMPNAM" - cat >>"$TMPNAM" - ${pkgs.smartmontools}/sbin/smartctl >>"$TMPNAM" -a -d "$SMARTD_DEVICETYPE" "$SMARTD_DEVICE" - /var/setuid-wrappers/sendmail <"$TMPNAM" -f "$SENDER" -i "$SMARTD_ADDRESS" - fi - ''; - - smartdConf = pkgs.writeText "smartd.conf" (concatMapStrings (device: - '' - ${device.device} -a -m root -M exec ${smartdMail} ${device.options} ${cfg.deviceOpts} - '' - ) cfg.devices); - - smartdFlags = if (cfg.devices == []) then "" else "--configfile=${smartdConf}"; - in { @@ -59,26 +94,104 @@ in services.smartd = { - enable = mkOption { - default = false; + enable = mkEnableOption "smartd daemon from <literal>smartmontools</literal> package"; + + autodetect = mkOption { + default = true; type = types.bool; - example = true; description = '' - Run smartd from the smartmontools package. Note that e-mail - notifications will not be enabled unless you configure the list of - devices with <varname>services.smartd.devices</varname> as well. + Whenever smartd should monitor all devices connected to the + machine at the time it's being started (the default). + + Set to false to monitor the devices listed in + <option>services.smartd.devices</option> only. ''; }; - deviceOpts = mkOption { - default = ""; - type = types.string; - example = "-o on -s (S/../.././02|L/../../7/04)"; - description = '' - Additional options for each device that is monitored. The example - turns on SMART Automatic Offline Testing on startup, and schedules short - self-tests daily, and long self-tests weekly. - ''; + notifications = { + + mail = { + enable = mkOption { + default = config.services.mail.sendmailSetuidWrapper != null; + type = types.bool; + description = "Whenever to send e-mail notifications."; + }; + + recipient = mkOption { + default = "root"; + type = types.string; + description = "Recipient of the notification messages."; + }; + + mailer = mkOption { + default = "/var/setuid-wrappers/sendmail"; + type = types.path; + description = '' + Sendmail-compatible binary to be used to send the messages. + + You should probably enable + <option>services.postfix</option> or some other MTA for + this to work. + ''; + }; + }; + + wall = { + enable = mkOption { + default = true; + type = types.bool; + description = "Whenever to send wall notifications to all users."; + }; + }; + + x11 = { + enable = mkOption { + default = config.services.xserver.enable; + type = types.bool; + description = "Whenever to send X11 xmessage notifications."; + }; + + display = mkOption { + default = ":${toString config.services.xserver.display}"; + type = types.string; + description = "DISPLAY to send X11 notifications to."; + }; + }; + + test = mkOption { + default = false; + type = types.bool; + description = "Whenever to send a test notification on startup."; + }; + + }; + + defaults = { + monitored = mkOption { + default = "-a"; + type = types.separatedString " "; + example = "-a -o on -s (S/../.././02|L/../../7/04)"; + description = '' + Common default options for explicitly monitored (listed in + <option>services.smartd.devices</option>) devices. + + The default value turns on monitoring of all the things (see + <literal>man 5 smartd.conf</literal>). + + The example also turns on SMART Automatic Offline Testing on + startup, and schedules short self-tests daily, and long + self-tests weekly. + ''; + }; + + autodetected = mkOption { + default = cfg.defaults.monitored; + type = types.separatedString " "; + description = '' + Like <option>services.smartd.defaults.monitored</option>, but for the + autodetected devices. + ''; + }; }; devices = mkOption { @@ -86,14 +199,9 @@ in example = [ { device = "/dev/sda"; } { device = "/dev/sdb"; options = "-d sat"; } ]; type = types.listOf types.optionSet; options = [ smartdOpts ]; - description = '' - List of devices to monitor. By default -- if this list is empty --, - smartd will monitor all devices connected to the machine at the time - it's being run. Configuring this option has the added benefit of - enabling e-mail notifications to "root" every time smartd detects an - error. - ''; - }; + description = "List of devices to monitor."; + }; + }; }; @@ -103,12 +211,19 @@ in config = mkIf cfg.enable { + assertions = [ { + assertion = cfg.autodetect || cfg.devices != []; + message = "smartd can't run with both disabled autodetect and an empty list of devices to monitor."; + } ]; + systemd.services.smartd = { description = "S.M.A.R.T. Daemon"; wantedBy = [ "multi-user.target" ]; - serviceConfig.ExecStart = "${pkgs.smartmontools}/sbin/smartd --no-fork ${smartdFlags}"; + path = [ pkgs.nettools ]; # for hostname and dnsdomanname calls in smartd + + serviceConfig.ExecStart = "${pkgs.smartmontools}/sbin/smartd --no-fork --configfile=${smartdConf}"; }; }; diff --git a/nixos/modules/services/network-filesystems/nfsd.nix b/nixos/modules/services/network-filesystems/nfsd.nix index 33b7ec3d9f1c..f1838224098b 100644 --- a/nixos/modules/services/network-filesystems/nfsd.nix +++ b/nixos/modules/services/network-filesystems/nfsd.nix @@ -88,10 +88,7 @@ in environment.systemPackages = [ pkgs.nfs-utils ]; - environment.etc = singleton - { source = exports; - target = "exports"; - }; + environment.etc.exports.source = exports; boot.kernelModules = [ "nfsd" ]; diff --git a/nixos/modules/services/networking/copy-com.nix b/nixos/modules/services/networking/copy-com.nix index 36bd29109b8a..69a41ab97963 100644 --- a/nixos/modules/services/networking/copy-com.nix +++ b/nixos/modules/services/networking/copy-com.nix @@ -1,53 +1,53 @@ -{ config, lib, pkgs, ... }: - -with lib; - -let - - cfg = config.services.copy-com; - -in - -{ - options = { - - services.copy-com = { - - enable = mkOption { - default = false; - description = " - Enable the copy.com client. - - The first time copy.com is run, it needs to be configured. Before enabling run - copy_console manually. - "; - }; - - user = mkOption { - description = "The user for which copy should run."; - }; - - debug = mkOption { - default = false; - description = "Output more."; - }; - }; - }; - - config = mkIf cfg.enable { - environment.systemPackages = [ pkgs.postfix ]; - - systemd.services."copy-com-${cfg.user}" = { - description = "Copy.com Client"; - after = [ "network.target" "local-fs.target" ]; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - ExecStart = "${pkgs.copy-com}/bin/copy_console ${if cfg.debug then "-consoleOutput -debugToConsole=dirwatch,path-watch,csm_path,csm -debug -console" else ""}"; - User = "${cfg.user}"; - }; - - }; - }; - -} - +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.copy-com; + +in + +{ + options = { + + services.copy-com = { + + enable = mkOption { + default = false; + description = " + Enable the Copy.com client. + NOTE: before enabling the client for the first time, it must be + configured by first running CopyConsole (command line) or CopyAgent + (graphical) as the appropriate user. + "; + }; + + user = mkOption { + description = "The user for which the Copy.com client should be run."; + }; + + debug = mkOption { + default = false; + description = "Output more (debugging) messages to the console."; + }; + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ pkgs.postfix ]; + + systemd.services."copy-com-${cfg.user}" = { + description = "Copy.com client"; + after = [ "network.target" "local-fs.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = "${pkgs.copy-com}/bin/CopyConsole ${if cfg.debug then "-consoleOutput -debugToConsole=dirwatch,path-watch,csm_path,csm -debug -console" else ""}"; + User = "${cfg.user}"; + }; + + }; + }; + +} + diff --git a/nixos/modules/services/networking/dnsmasq.nix b/nixos/modules/services/networking/dnsmasq.nix index 4a812167bb5f..eb3551515723 100644 --- a/nixos/modules/services/networking/dnsmasq.nix +++ b/nixos/modules/services/networking/dnsmasq.nix @@ -98,6 +98,7 @@ in ExecStart = "${dnsmasq}/bin/dnsmasq -k --enable-dbus --user=dnsmasq -C ${dnsmasqConf}"; ExecReload = "${dnsmasq}/bin/kill -HUP $MAINPID"; }; + restartTriggers = [ config.environment.etc.hosts.source ]; }; }; diff --git a/nixos/modules/services/networking/fan.nix b/nixos/modules/services/networking/fan.nix new file mode 100644 index 000000000000..3170567e5b4a --- /dev/null +++ b/nixos/modules/services/networking/fan.nix @@ -0,0 +1,60 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.networking.fan; + modprobe = "${config.system.sbin.modprobe}/sbin/modprobe"; + +in + +{ + + ###### interface + + options = { + + networking.fan = { + + enable = mkEnableOption "FAN Networking"; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + environment.systemPackages = [ pkgs.fanctl ]; + + systemd.services.fan = { + description = "FAN Networking"; + wantedBy = [ "multi-user.target" ]; + after = [ "network-online.target" ]; + before = [ "docker.service" ]; + restartIfChanged = false; + preStart = '' + if [ ! -f /proc/sys/net/fan/version ]; then + ${modprobe} ipip + if [ ! -f /proc/sys/net/fan/version ]; then + echo "The Fan Networking patches have not been applied to this kernel!" 1>&2 + exit 1 + fi + fi + + mkdir -p /var/lib/fan-networking + ''; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "${pkgs.fanctl}/bin/fanctl up -a"; + ExecStop = "${pkgs.fanctl}/bin/fanctl down -a"; + }; + }; + + }; + +} diff --git a/nixos/modules/services/networking/firewall.nix b/nixos/modules/services/networking/firewall.nix index 40681f5b957a..a61f0250ef8b 100644 --- a/nixos/modules/services/networking/firewall.nix +++ b/nixos/modules/services/networking/firewall.nix @@ -420,6 +420,16 @@ in ''; }; + networking.firewall.extraPackages = mkOption { + default = [ ]; + example = [ pkgs.ipset ]; + description = + '' + Additional packages to be included in the environment of the system + as well as the path of networking.firewall.extraCommands. + ''; + }; + networking.firewall.extraStopCommands = mkOption { type = types.lines; default = ""; @@ -443,7 +453,7 @@ in networking.firewall.trustedInterfaces = [ "lo" ]; - environment.systemPackages = [ pkgs.iptables pkgs.ipset ]; + environment.systemPackages = [ pkgs.iptables ] ++ cfg.extraPackages; boot.kernelModules = map (x: "nf_conntrack_${x}") cfg.connectionTrackingModules; boot.extraModprobeConfig = optionalString (!cfg.autoLoadConntrackHelpers) '' @@ -462,7 +472,7 @@ in before = [ "network-pre.target" ]; after = [ "systemd-modules-load.service" ]; - path = [ pkgs.iptables pkgs.ipset ]; + path = [ pkgs.iptables ] ++ cfg.extraPackages; # FIXME: this module may also try to load kernel modules, but # containers don't have CAP_SYS_MODULE. So the host system had diff --git a/nixos/modules/services/networking/gateone.nix b/nixos/modules/services/networking/gateone.nix new file mode 100644 index 000000000000..93273837181e --- /dev/null +++ b/nixos/modules/services/networking/gateone.nix @@ -0,0 +1,61 @@ +{ config, lib, pkgs, ...}: +with lib; +let + cfg = config.services.gateone; +in +{ +options = { + services.gateone = { + enable = mkEnableOption "GateOne server"; + pidDir = mkOption { + default = "/run/gateone"; + type = types.path; + description = ''Path of pid files for GateOne.''; + }; + settingsDir = mkOption { + default = "/var/lib/gateone"; + type = types.path; + description = ''Path of configuration files for GateOne.''; + }; + }; +}; +config = mkIf cfg.enable { + environment.systemPackages = with pkgs.pythonPackages; [ + gateone pkgs.openssh pkgs.procps pkgs.coreutils ]; + + users.extraUsers.gateone = { + description = "GateOne privilege separation user"; + uid = config.ids.uids.gateone; + home = cfg.settingsDir; + }; + users.extraGroups.gateone.gid = config.ids.gids.gateone; + + systemd.services.gateone = with pkgs; { + description = "GateOne web-based terminal"; + path = [ pythonPackages.gateone nix openssh procps coreutils ]; + preStart = '' + if [ ! -d ${cfg.settingsDir} ] ; then + mkdir -m 0750 -p ${cfg.settingsDir} + chown -R gateone.gateone ${cfg.settingsDir} + fi + if [ ! -d ${cfg.pidDir} ] ; then + mkdir -m 0750 -p ${cfg.pidDir} + chown -R gateone.gateone ${cfg.pidDir} + fi + ''; + #unitConfig.RequiresMountsFor = "${cfg.settingsDir}"; + serviceConfig = { + ExecStart = ''${pythonPackages.gateone}/bin/gateone --settings_dir=${cfg.settingsDir} --pid_file=${cfg.pidDir}/gateone.pid --gid=${toString config.ids.gids.gateone} --uid=${toString config.ids.uids.gateone}''; + User = "gateone"; + Group = "gateone"; + WorkingDirectory = cfg.settingsDir; + PermissionsStartOnly = true; + + }; + + wantedBy = [ "multi-user.target" ]; + requires = [ "network.target" ]; + }; +}; +} + diff --git a/nixos/modules/services/networking/heyefi.nix b/nixos/modules/services/networking/heyefi.nix new file mode 100644 index 000000000000..fc2b5a848578 --- /dev/null +++ b/nixos/modules/services/networking/heyefi.nix @@ -0,0 +1,82 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.heyefi; +in + +{ + + ###### interface + + options = { + + services.heyefi = { + + enable = mkEnableOption "heyefi"; + + cardMacaddress = mkOption { + default = ""; + description = '' + An Eye-Fi card MAC address. + ''; + }; + + uploadKey = mkOption { + default = ""; + description = '' + An Eye-Fi card's upload key. + ''; + }; + + uploadDir = mkOption { + example = "/home/username/pictures"; + description = '' + The directory to upload the files to. + ''; + }; + + user = mkOption { + default = "root"; + description = '' + heyefi will be run under this user (user must exist, + this can be your user name). + ''; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + systemd.services.heyefi = + { + description = "heyefi service"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + User = "${cfg.user}"; + Restart = "always"; + ExecStart = "${pkgs.heyefi}/bin/heyefi"; + }; + + }; + + environment.etc."heyefi/heyefi.config".text = + '' + # /etc/heyefi/heyefi.conf: DO NOT EDIT -- this file has been generated automatically. + cards = [["${config.services.heyefi.cardMacaddress}","${config.services.heyefi.uploadKey}"]] + upload_dir = "${toString config.services.heyefi.uploadDir}" + ''; + + environment.systemPackages = [ pkgs.heyefi ]; + + }; + +} diff --git a/nixos/modules/services/networking/i2p.nix b/nixos/modules/services/networking/i2p.nix index bad22c791388..e6ee5fd1f957 100644 --- a/nixos/modules/services/networking/i2p.nix +++ b/nixos/modules/services/networking/i2p.nix @@ -7,15 +7,7 @@ let homeDir = "/var/lib/i2p"; in { ###### interface - options.services.i2p = { - enable = mkOption { - type = types.bool; - default = false; - description = '' - Enables i2p as a running service upon activation. - ''; - }; - }; + options.services.i2p.enable = mkEnableOption "I2P router"; ###### implementation config = mkIf cfg.enable { diff --git a/nixos/modules/services/networking/kippo.nix b/nixos/modules/services/networking/kippo.nix index 68f26eefe27e..7d70a3d05fa7 100644 --- a/nixos/modules/services/networking/kippo.nix +++ b/nixos/modules/services/networking/kippo.nix @@ -86,8 +86,7 @@ rec { wantedBy = [ "multi-user.target" ]; environment.PYTHONPATH = "${pkgs.kippo}/src/:${pkgs.pythonPackages.pycrypto}/lib/python2.7/site-packages/:${pkgs.pythonPackages.pyasn1}/lib/python2.7/site-packages/:${pkgs.pythonPackages.python}/lib/python2.7/site-packages/:${pkgs.pythonPackages.twisted}/lib/python2.7/site-packages/:."; preStart = '' - if [ ! -d ${cfg.varPath}/ ] ; then - mkdir -p ${cfg.pidPath} + if [ ! -d ${cfg.varPath}/ ] ; then mkdir -p ${cfg.logPath}/tty mkdir -p ${cfg.logPath}/dl mkdir -p ${cfg.varPath}/keys @@ -97,12 +96,15 @@ rec { cp ${pkgs.kippo}/src/txtcmds ${cfg.varPath} -r chmod u+rw ${cfg.varPath} -R - chmod u+rw ${cfg.pidPath} chown kippo.kippo ${cfg.varPath} -R - chown kippo.kippo ${cfg.pidPath} chown kippo.kippo ${cfg.logPath} -R chmod u+rw ${cfg.logPath} -R fi + if [ ! -d ${cfg.pidPath}/ ] ; then + mkdir -p ${cfg.pidPath} + chmod u+rw ${cfg.pidPath} + chown kippo.kippo ${cfg.pidPath} + fi ''; serviceConfig.ExecStart = "${pkgs.pythonPackages.twisted}/bin/twistd -y ${pkgs.kippo}/src/kippo.tac --syslog --rundir=${cfg.varPath}/ --pidfile=${cfg.pidPath}/kippo.pid --prefix=kippo -n"; diff --git a/nixos/modules/services/networking/quassel.nix b/nixos/modules/services/networking/quassel.nix index 579d62884c78..005eb7bd7614 100644 --- a/nixos/modules/services/networking/quassel.nix +++ b/nixos/modules/services/networking/quassel.nix @@ -3,7 +3,7 @@ with lib; let - quassel = pkgs.kde4.quasselDaemon; + quassel = pkgs.quasselDaemon_qt5; cfg = config.services.quassel; user = if cfg.user != null then cfg.user else "quassel"; in diff --git a/nixos/modules/services/networking/racoon.nix b/nixos/modules/services/networking/racoon.nix index 9428d9112a1b..86e13d1ea0d6 100644 --- a/nixos/modules/services/networking/racoon.nix +++ b/nixos/modules/services/networking/racoon.nix @@ -36,7 +36,10 @@ in { Type = "forking"; Restart = "always"; }; - preStart = "rm /var/run/racoon.pid || true"; + preStart = '' + rm /var/run/racoon.pid || true + mkdir -p /var/racoon + ''; }; }; } diff --git a/nixos/modules/services/networking/shout.nix b/nixos/modules/services/networking/shout.nix new file mode 100644 index 000000000000..f55b87a96140 --- /dev/null +++ b/nixos/modules/services/networking/shout.nix @@ -0,0 +1,80 @@ +{ pkgs, lib, config, options, ... }: + +with lib; + +let + cfg = config.services.shout; + shoutHome = "/var/lib/shout"; + +in { + options.services.shout = { + enable = mkEnableOption "Shout web IRC client"; + + private = mkOption { + type = types.bool; + default = false; + description = '' + Make your shout instance private. You will need to configure user + accounts by adding entries in <filename>${shoutHome}/users</filename>. + ''; + }; + + host = mkOption { + type = types.string; + default = "0.0.0.0"; + description = "IP interface to listen on for http connections."; + }; + + port = mkOption { + type = types.int; + default = 9000; + description = "TCP port to listen on for http connections."; + }; + + configFile = mkOption { + type = types.nullOr types.lines; + default = null; + description = '' + Contents of Shout's <filename>config.js</filename> file. If left empty, + Shout will generate from its defaults at first startup. + + Documentation: http://shout-irc.com/docs/server/configuration.html + ''; + }; + }; + + config = mkIf cfg.enable { + users.extraUsers = singleton { + name = "shout"; + uid = config.ids.uids.shout; + description = "Shout daemon user"; + home = shoutHome; + createHome = true; + }; + + systemd.services.shout = { + description = "Shout web IRC client"; + wantedBy = [ "multi-user.target" ]; + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; + preStart = if isNull cfg.configFile then null + else '' + ln -sf ${pkgs.writeText "config.js" cfg.configFile} \ + ${shoutHome}/config.js + ''; + script = concatStringsSep " " [ + "${pkgs.shout}/bin/shout" + (if cfg.private then "--private" else "--public") + "--port" (toString cfg.port) + "--host" (toString cfg.host) + "--home" shoutHome + ]; + serviceConfig = { + User = "shout"; + ProtectHome = "true"; + ProtectSystem = "full"; + PrivateTmp = "true"; + }; + }; + }; +} diff --git a/nixos/modules/services/networking/skydns.nix b/nixos/modules/services/networking/skydns.nix index 3b9390914891..f5eb452fec62 100644 --- a/nixos/modules/services/networking/skydns.nix +++ b/nixos/modules/services/networking/skydns.nix @@ -79,7 +79,7 @@ in { ETCD_CACERT = cfg.etcd.caCert; SKYDNS_ADDR = cfg.address; SKYDNS_DOMAIN = cfg.domain; - SKYDNS_NAMESERVER = concatStringsSep "," cfg.nameservers; + SKYDNS_NAMESERVERS = concatStringsSep "," cfg.nameservers; }; serviceConfig = { ExecStart = "${cfg.package}/bin/skydns"; diff --git a/nixos/modules/services/networking/softether.nix b/nixos/modules/services/networking/softether.nix new file mode 100644 index 000000000000..49538af7d351 --- /dev/null +++ b/nixos/modules/services/networking/softether.nix @@ -0,0 +1,150 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + pkg = pkgs.softether; + cfg = config.services.softether; + +in +{ + + ###### interface + + options = { + + services.softether = { + + enable = mkEnableOption "SoftEther VPN services"; + + vpnserver.enable = mkEnableOption "SoftEther VPN Server"; + + vpnbridge.enable = mkEnableOption "SoftEther VPN Bridge"; + + vpnclient = { + enable = mkEnableOption "SoftEther VPN Client"; + up = mkOption { + type = types.lines; + default = ""; + description = '' + Shell commands executed when the Virtual Network Adapter(s) is/are starting. + ''; + }; + down = mkOption { + type = types.lines; + default = ""; + description = '' + Shell commands executed when the Virtual Network Adapter(s) is/are shutting down. + ''; + }; + }; + + dataDir = mkOption { + type = types.string; + default = "${pkg.dataDir}"; + description = '' + Data directory for SoftEther VPN. + ''; + }; + + }; + + }; + + ###### implementation + + config = mkIf cfg.enable ( + + mkMerge [{ + environment.systemPackages = [ + (pkgs.lib.overrideDerivation pkg (attrs: { + dataDir = cfg.dataDir; + })) + ]; + jobs.softether = { + description = "SoftEther VPN services initial job"; + startOn = "started network-interfaces"; + preStart = '' + for d in vpnserver vpnbridge vpnclient vpncmd; do + if ! test -e ${cfg.dataDir}/$d; then + ${pkgs.coreutils}/bin/mkdir -m0700 -p ${cfg.dataDir}/$d + install -m0600 ${pkg}${cfg.dataDir}/$d/hamcore.se2 ${cfg.dataDir}/$d/hamcore.se2 + fi + done + rm -rf ${cfg.dataDir}/vpncmd/vpncmd + ln -s ${pkg}${cfg.dataDir}/vpncmd/vpncmd ${cfg.dataDir}/vpncmd/vpncmd + ''; + exec = "true"; + }; + } + + (mkIf (cfg.vpnserver.enable) { + systemd.services.vpnserver = { + description = "SoftEther VPN Server"; + after = [ "network-interfaces.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = "${pkg}/bin/vpnserver start"; + ExecStop = "${pkg}/bin/vpnserver stop"; + Type = "forking"; + }; + preStart = '' + rm -rf ${cfg.dataDir}/vpnserver/vpnserver + ln -s ${pkg}${cfg.dataDir}/vpnserver/vpnserver ${cfg.dataDir}/vpnserver/vpnserver + ''; + postStop = '' + rm -rf ${cfg.dataDir}/vpnserver/vpnserver + ''; + }; + }) + + (mkIf (cfg.vpnbridge.enable) { + systemd.services.vpnbridge = { + description = "SoftEther VPN Bridge"; + after = [ "network-interfaces.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = "${pkg}/bin/vpnbridge start"; + ExecStop = "${pkg}/bin/vpnbridge stop"; + Type = "forking"; + }; + preStart = '' + rm -rf ${cfg.dataDir}/vpnbridge/vpnbridge + ln -s ${pkg}${cfg.dataDir}/vpnbridge/vpnbridge ${cfg.dataDir}/vpnbridge/vpnbridge + ''; + postStop = '' + rm -rf ${cfg.dataDir}/vpnbridge/vpnbridge + ''; + }; + }) + + (mkIf (cfg.vpnclient.enable) { + systemd.services.vpnclient = { + description = "SoftEther VPN Client"; + after = [ "network-interfaces.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + ExecStart = "${pkg}/bin/vpnclient start"; + ExecStop = "${pkg}/bin/vpnclient stop"; + Type = "forking"; + }; + preStart = '' + rm -rf ${cfg.dataDir}/vpnclient/vpnclient + ln -s ${pkg}${cfg.dataDir}/vpnclient/vpnclient ${cfg.dataDir}/vpnclient/vpnclient + ''; + postStart = '' + sleep 1 + ${cfg.vpnclient.up} + ''; + postStop = '' + rm -rf ${cfg.dataDir}/vpnclient/vpnclient + sleep 1 + ${cfg.vpnclient.down} + ''; + }; + boot.kernelModules = [ "tun" ]; + }) + + ]); + +} diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix index 4be2b5fe0c0c..5baea4bc6aea 100644 --- a/nixos/modules/services/networking/ssh/sshd.nix +++ b/nixos/modules/services/networking/ssh/sshd.nix @@ -9,14 +9,6 @@ let nssModulesPath = config.system.nssModules.path; - knownHosts = map (h: getAttr h cfg.knownHosts) (attrNames cfg.knownHosts); - - knownHostsText = flip (concatMapStringsSep "\n") knownHosts - (h: - concatStringsSep "," h.hostNames + " " - + (if h.publicKey != null then h.publicKey else readFile h.publicKeyFile) - ); - userOptions = { openssh.authorizedKeys = { @@ -48,8 +40,7 @@ let }; authKeysFiles = let - mkAuthKeyFile = u: { - target = "ssh/authorized_keys.d/${u.name}"; + mkAuthKeyFile = u: nameValuePair "ssh/authorized_keys.d/${u.name}" { mode = "0444"; source = pkgs.writeText "${u.name}-authorized_keys" '' ${concatStringsSep "\n" u.openssh.authorizedKeys.keys} @@ -59,7 +50,7 @@ let usersWithKeys = attrValues (flip filterAttrs config.users.extraUsers (n: u: length u.openssh.authorizedKeys.keys != 0 || length u.openssh.authorizedKeys.keyFiles != 0 )); - in map mkAuthKeyFile usersWithKeys; + in listToAttrs (map mkAuthKeyFile usersWithKeys); in @@ -184,16 +175,11 @@ in hostKeys = mkOption { type = types.listOf types.attrs; default = - [ { path = "/etc/ssh/ssh_host_dsa_key"; - type = "dsa"; - } - { path = "/etc/ssh/ssh_host_ecdsa_key"; - type = "ecdsa"; - bits = 521; - } - { path = "/etc/ssh/ssh_host_ed25519_key"; - type = "ed25519"; - } + [ { type = "rsa"; bits = 4096; path = "/etc/ssh/ssh_host_rsa_key"; } + { type = "ed25519"; path = "/etc/ssh/ssh_host_ed25519_key"; } + ] ++ optionals (!versionAtLeast config.system.stateVersion "15.07") + [ { type = "dsa"; path = "/etc/ssh/ssh_host_dsa_key"; } + { type = "ecdsa"; bits = 521; path = "/etc/ssh/ssh_host_ecdsa_key"; } ]; description = '' NixOS can automatically generate SSH host keys. This option @@ -216,57 +202,6 @@ in description = "Verbatim contents of <filename>sshd_config</filename>."; }; - knownHosts = mkOption { - default = {}; - type = types.loaOf types.optionSet; - description = '' - The set of system-wide known SSH hosts. - ''; - example = [ - { - hostNames = [ "myhost" "myhost.mydomain.com" "10.10.1.4" ]; - publicKeyFile = literalExample "./pubkeys/myhost_ssh_host_dsa_key.pub"; - } - { - hostNames = [ "myhost2" ]; - publicKeyFile = literalExample "./pubkeys/myhost2_ssh_host_dsa_key.pub"; - } - ]; - options = { - 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. - ''; - }; - }; - }; - moduliFile = mkOption { example = "services.openssh.moduliFile = /etc/my-local-ssh-moduli;"; type = types.path; @@ -279,7 +214,7 @@ in }; - users.extraUsers = mkOption { + users.users = mkOption { options = [ userOptions ]; }; @@ -297,14 +232,8 @@ in services.openssh.moduliFile = mkDefault "${cfgc.package}/etc/ssh/moduli"; - environment.etc = authKeysFiles ++ [ - { source = cfg.moduliFile; - target = "ssh/moduli"; - } - { text = knownHostsText; - target = "ssh/ssh_known_hosts"; - } - ]; + environment.etc = authKeysFiles // + { "ssh/moduli".source = cfg.moduliFile; }; systemd = let @@ -422,11 +351,6 @@ in assertions = [{ assertion = if cfg.forwardX11 then cfgc.setXAuthLocation else true; 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"; - }) ++ flip map cfg.listenAddresses ({ addr, port, ... }: { assertion = addr != null; message = "addr must be specified in each listenAddresses entry"; diff --git a/nixos/modules/services/networking/syncthing.nix b/nixos/modules/services/networking/syncthing.nix index 02572c1e27d2..d5accfef1cb5 100644 --- a/nixos/modules/services/networking/syncthing.nix +++ b/nixos/modules/services/networking/syncthing.nix @@ -36,9 +36,7 @@ in dataDir = mkOption { default = "/var/lib/syncthing"; description = '' - Path where the `.syncthing` (settings and keys) and `Sync` - (your synced files) directories will exist. This can be your home - directory. + Path where the settings and keys will exist. ''; }; @@ -57,18 +55,12 @@ in after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; environment.STNORESTART = "placeholder"; # do not self-restart - environment.HOME = "${cfg.dataDir}"; serviceConfig = { User = "${cfg.user}"; PermissionsStartOnly = true; Restart = "always"; - ExecStart = "${pkgs.syncthing}/bin/syncthing -home=${cfg.dataDir}/.syncthing"; + ExecStart = "${pkgs.syncthing}/bin/syncthing -no-browser -home=${cfg.dataDir}"; }; - preStart = '' - mkdir -p ${cfg.dataDir} - chown ${cfg.user} ${cfg.dataDir} - ''; - }; environment.systemPackages = [ pkgs.syncthing ]; diff --git a/nixos/modules/services/printing/cupsd.nix b/nixos/modules/services/printing/cupsd.nix index fd9589883edc..69c76cf97cfd 100644 --- a/nixos/modules/services/printing/cupsd.nix +++ b/nixos/modules/services/printing/cupsd.nix @@ -160,6 +160,17 @@ in ''; }; + snmpConf = mkOption { + type = types.lines; + default = '' + Address @LOCAL + ''; + description = '' + The contents of <filename>/etc/cups/snmp.conf</filename>. See "man + cups-snmp.conf" for a complete description. + ''; + }; + drivers = mkOption { type = types.listOf types.path; example = literalExample "[ pkgs.splix ]"; @@ -199,6 +210,7 @@ in environment.etc."cups/cups-files.conf".text = cfg.cupsFilesConf; environment.etc."cups/cupsd.conf".text = cfg.cupsdConf; environment.etc."cups/cups-browsed.conf".text = cfg.browsedConf; + environment.etc."cups/snmp.conf".text = cfg.snmpConf; services.dbus.packages = [ cups ]; @@ -230,8 +242,8 @@ in ]; }; - systemd.services.cups-browsed = - { description = "Make remote CUPS printers available locally"; + systemd.services.cups-browsed = mkIf config.services.avahi.enable + { description = "CUPS Remote Printer Discovery"; wantedBy = [ "multi-user.target" ]; wants = [ "cups.service" "avahi-daemon.service" ]; diff --git a/nixos/modules/services/scheduling/cron.nix b/nixos/modules/services/scheduling/cron.nix index 1f42086dc1ec..02d80a77da50 100644 --- a/nixos/modules/services/scheduling/cron.nix +++ b/nixos/modules/services/scheduling/cron.nix @@ -4,8 +4,6 @@ with lib; let - inherit (config.services) jobsTags; - # Put all the system cronjobs together. systemCronJobsFile = pkgs.writeText "system-crontab" '' @@ -25,9 +23,9 @@ let sendmailPath = "/var/setuid-wrappers/sendmail"; }; - allFiles = map (f: "\"${f}\"") ( - [ "${systemCronJobsFile}" ] ++ config.services.cron.cronFiles - ); + allFiles = + optional (config.services.cron.systemCronJobs != []) systemCronJobsFile + ++ config.services.cron.cronFiles; in @@ -91,36 +89,49 @@ in ###### implementation - config = mkIf (config.services.cron.enable && allFiles != []) { + config = mkMerge [ - security.setuidPrograms = [ "crontab" ]; + { services.cron.enable = mkDefault (allFiles != []); } - environment.systemPackages = [ cronNixosPkg ]; + (mkIf (config.services.cron.enable) { - systemd.services.cron = - { description = "Cron Daemon"; + security.setuidPrograms = [ "crontab" ]; - wantedBy = [ "multi-user.target" ]; + environment.systemPackages = [ cronNixosPkg ]; - preStart = - '' - rm -f /etc/crontab - cat ${toString allFiles} > /etc/crontab - chmod 0600 /etc/crontab + environment.etc.crontab = + { source = pkgs.runCommand "crontabs" { inherit allFiles; } + '' + touch $out + for i in $allFiles; do + cat "$i" >> $out + done + ''; + mode = "0600"; # Cron requires this. + }; - mkdir -m 710 -p /var/cron + systemd.services.cron = + { description = "Cron Daemon"; - # By default, allow all users to create a crontab. This - # is denoted by the existence of an empty cron.deny file. - if ! test -e /var/cron/cron.allow -o -e /var/cron/cron.deny; then - touch /var/cron/cron.deny - fi - ''; + wantedBy = [ "multi-user.target" ]; - restartTriggers = [ config.environment.etc.localtime.source ]; - serviceConfig.ExecStart = "${cronNixosPkg}/bin/cron -n"; - }; + preStart = + '' + mkdir -m 710 -p /var/cron - }; + # By default, allow all users to create a crontab. This + # is denoted by the existence of an empty cron.deny file. + if ! test -e /var/cron/cron.allow -o -e /var/cron/cron.deny; then + touch /var/cron/cron.deny + fi + ''; + + restartTriggers = [ config.environment.etc.localtime.source ]; + serviceConfig.ExecStart = "${cronNixosPkg}/bin/cron -n"; + }; + + }) + + ]; } diff --git a/nixos/modules/services/security/hologram.nix b/nixos/modules/services/security/hologram.nix index f9abf38942f4..58f308df7a21 100644 --- a/nixos/modules/services/security/hologram.nix +++ b/nixos/modules/services/security/hologram.nix @@ -95,7 +95,7 @@ in { wantedBy = [ "multi-user.target" ]; serviceConfig = { - ExecStart = "${pkgs.goPackages.hologram}/bin/hologram-server --debug --conf ${cfgFile}"; + ExecStart = "${pkgs.hologram}/bin/hologram-server --debug --conf ${cfgFile}"; }; }; }; diff --git a/nixos/modules/services/system/dbus.nix b/nixos/modules/services/system/dbus.nix index 5c20901427cb..77427ce9606e 100644 --- a/nixos/modules/services/system/dbus.nix +++ b/nixos/modules/services/system/dbus.nix @@ -73,6 +73,7 @@ in enable = mkOption { type = types.bool; default = true; + internal = true; description = '' Whether to start the D-Bus message bus daemon, which is required by many other system services and applications. diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index fe50c182bfe5..b16f701a0c9f 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -11,7 +11,9 @@ let ${cfg.config} ${optionalString (cfg.httpConfig != "") '' http { - ${cfg.httpConfig} + ${cfg.httpConfig} + ${cfg.httpServers} + ${cfg.httpDefaultServer} } ''} ${cfg.appendConfig} @@ -60,7 +62,32 @@ in httpConfig = mkOption { type = types.lines; default = ""; - description = "Configuration lines to be appended inside of the http {} block."; + description = '' + Configuration lines to be placed at the top inside of + the http {} block. The option is intended to be used for + the default configuration of the servers. + ''; + }; + + httpServers = mkOption { + type = types.lines; + default = ""; + description = '' + Configuration lines to be placed inside of the http {} + block. The option is intended to be used for defining + individual servers. + ''; + }; + + httpDefaultServer = mkOption { + type = types.lines; + default = ""; + description = '' + Configuration lines to be placed at the bottom inside of + the http {} block. The option is intended to be used for + setting up the default servers. The default server is used + if no previously specified server matches a request. + ''; }; stateDir = mkOption { diff --git a/nixos/modules/services/web-servers/nginx/reverse_proxy.nix b/nixos/modules/services/web-servers/nginx/reverse_proxy.nix new file mode 100644 index 000000000000..c21406dff29a --- /dev/null +++ b/nixos/modules/services/web-servers/nginx/reverse_proxy.nix @@ -0,0 +1,233 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.nginx; + + defaultSSL = cfg.httpDefaultKey != null || cfg.httpDefaultCertificate != null; + + validSSL = key: cert: cert != null && key != null || cert == null && key == null; + +in + +{ + options = { + + services.nginx = { + + reverseProxies = mkOption { + type = types.attrsOf (types.submodule ( + { + options = { + proxy = mkOption { + type = types.str; + default = []; + description = '' + Exclude files and directories matching these patterns. + ''; + }; + + key = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Exclude files and directories matching these patterns. + ''; + }; + + certificate = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Exclude files and directories matching these patterns. + ''; + }; + }; + } + )); + + default = {}; + + example = literalExample '' + { + "hydra.yourdomain.org" = + { proxy = "localhost:3000"; + key = "/etc/nixos/certs/hydra_key.key"; + certificate = "/etc/nixos/certs/hydra_cert.crt"; + }; + } + ''; + + description = '' + A reverse proxy server configuration is created for every attribute. + The attribute name corresponds to the name the server is listening to, + and the proxy option defines the target to forward the requests to. + If a key and certificate are given, then the server is secured through + a SSL connection. Non-SSL requests on port 80 are automatically + re-directed to the SSL server on port 443. + ''; + }; + + httpDefaultKey = mkOption { + type = types.nullOr types.path; + default = null; + example = "/etc/nixos/certs/defaut_key.key"; + description = '' + Key of SSL certificate for default server. + The default certificate is presented by the default server during + the SSL handshake when no specialized server configuration matches + a request. + A default SSL certificate is also helpful if browsers do not + support the TLS Server Name Indication extension (SNI, RFC 6066). + ''; + }; + + httpDefaultCertificate = mkOption { + type = types.nullOr types.path; + default = null; + example = "/etc/nixos/certs/defaut_key.crt"; + description = '' + SSL certificate for default server. + The default certificate is presented by the default server during + the SSL handshake when no specialized server configuration matches + a request. + A default SSL certificate is also helpful if browsers do not + support the TLS Server Name Indication extension (SNI, RFC 6066). + ''; + }; + + }; + + }; + + + config = mkIf (cfg.reverseProxies != {}) { + + assertions = [ + { assertion = all id (mapAttrsToList (n: v: validSSL v.certificate v.key) cfg.reverseProxies); + message = '' + One (or more) reverse proxy configurations specify only either + the key option or the certificate option. Both certificate + with associated key have to be configured to enable SSL for a + server configuration. + + services.nginx.reverseProxies: ${toString cfg.reverseProxies} + ''; + } + { assertion = validSSL cfg.httpDefaultCertificate cfg.httpDefaultKey; + message = '' + The default server configuration specifies only either the key + option or the certificate option. Both httpDefaultCertificate + with associated httpDefaultKey have to be configured to enable + SSL for the default server configuration. + + services.nginx.httpDefaultCertificate: ${toString cfg.httpDefaultCertificate} + + services.nginx.httpDefaultKey : ${toString cfg.httpDefaultKey} + ''; + } + ]; + + services.nginx.config = mkBefore '' + worker_processes 1; + error_log logs/error.log debug; + pid logs/nginx.pid; + events { + worker_connections 1024; + } + ''; + + services.nginx.httpConfig = mkBefore '' + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + access_log logs/access.log main; + sendfile on; + tcp_nopush on; + keepalive_timeout 10; + gzip on; + + ${lib.optionalString defaultSSL '' + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers HIGH:!aNULL:!MD5; + ssl_certificate ${cfg.httpDefaultCertificate}; + ssl_certificate_key ${cfg.httpDefaultKey}; + ''} + ''; + + services.nginx.httpDefaultServer = mkBefore '' + # reject as default policy + server { + listen 80 default_server; + listen [::]:80 default_server; + ${lib.optionalString defaultSSL "listen 443 default_server ssl;"} + return 444; + } + ''; + + services.nginx.httpServers = + let + useSSL = certificate: key: certificate != null && key != null; + + server = servername: proxy: certificate: key: useSSL: '' + server { + server_name ${servername}; + keepalive_timeout 70; + + ${if !useSSL then '' + listen 80; + listen [::]:80; + '' else '' + listen 443 ssl; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_certificate ${certificate}; + ssl_certificate_key ${key}; + ''} + + location / { + proxy_pass ${proxy}; + + ### force timeouts if one of backend is dead ## + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; + + ### Set headers #### + proxy_set_header Accept-Encoding ""; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + ${lib.optionalString useSSL '' + ### Most PHP, Python, Rails, Java App can use this header ### + #proxy_set_header X-Forwarded-Proto https;## + #This is better## + proxy_set_header X-Forwarded-Proto $scheme; + add_header Front-End-Https on; + ''} + + ### By default we don't want to redirect it #### + proxy_redirect off; + proxy_buffering off; + } + } + + ${lib.optionalString useSSL '' + # redirect http to https + server { + listen 80; + listen [::]:80; + server_name ${servername}; + return 301 https://$server_name$request_uri; + } + ''} + ''; + in + concatStrings (mapAttrsToList (n: v: server n v.proxy v.certificate v.key (useSSL v.proxy v.certificate)) cfg.reverseProxies); + + }; + +} diff --git a/nixos/modules/services/x11/desktop-managers/e19.nix b/nixos/modules/services/x11/desktop-managers/e19.nix index 2d5c7b192bc6..74065c862ef7 100644 --- a/nixos/modules/services/x11/desktop-managers/e19.nix +++ b/nixos/modules/services/x11/desktop-managers/e19.nix @@ -62,6 +62,7 @@ in waitPID=$! ''; }]; + services.xserver.displayManager.desktopManagerHandlesLidAndPower = true; security.setuidPrograms = [ "e19_freqset" ]; diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix index cf6d2cab3492..507c2d2da139 100644 --- a/nixos/modules/services/x11/desktop-managers/gnome3.nix +++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix @@ -25,6 +25,24 @@ let ''; }; + nixos-gsettings-desktop-schemas = pkgs.stdenv.mkDerivation { + name = "nixos-gsettings-desktop-schemas"; + buildInputs = [ pkgs.nixos-artwork ]; + buildCommand = '' + mkdir -p $out/share/nixos-gsettings-schemas/nixos-gsettings-desktop-schemas + cp -rf ${gnome3.gsettings_desktop_schemas}/share/gsettings-schemas/gsettings-desktop-schemas*/glib-2.0 $out/share/nixos-gsettings-schemas/nixos-gsettings-desktop-schemas/ + chmod -R a+w $out/share/nixos-gsettings-schemas/nixos-gsettings-desktop-schemas + cat - > $out/share/nixos-gsettings-schemas/nixos-gsettings-desktop-schemas/glib-2.0/schemas/nixos-defaults.gschema.override <<- EOF + [org.gnome.desktop.background] + picture-uri='${pkgs.nixos-artwork}/share/artwork/gnome/Gnome_Dark.png' + + [org.gnome.desktop.screensaver] + picture-uri='${pkgs.nixos-artwork}/share/artwork/gnome/Gnome_Dark.png' + EOF + ${pkgs.glib}/bin/glib-compile-schemas $out/share/nixos-gsettings-schemas/nixos-gsettings-desktop-schemas/glib-2.0/schemas/ + ''; + }; + in { options = { @@ -40,7 +58,7 @@ in { example = literalExample "[ pkgs.gnome3.gpaste ]"; description = "Additional list of packages to be added to the session search path. Useful for gnome shell extensions or gsettings-conditionated autostart."; - apply = list: list ++ [ gnome3.gnome_shell ]; + apply = list: list ++ [ gnome3.gnome_shell gnome3.gnome-shell-extensions ]; }; environment.gnome3.packageSet = mkOption { @@ -81,6 +99,7 @@ in { networking.networkmanager.enable = mkDefault true; services.upower.enable = config.powerManagement.enable; hardware.bluetooth.enable = mkDefault true; + services.xserver.displayManager.desktopManagerHandlesLidAndPower = false; # true doesn't make sense here, GNOME just doesn't handle it anymore fonts.fonts = [ pkgs.dejavu_fonts pkgs.cantarell_fonts ]; @@ -109,6 +128,9 @@ in { # Override default mimeapps export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${mimeAppsList}/share + # Override gsettings-desktop-schema + export XDG_DATA_DIRS=${nixos-gsettings-desktop-schemas}/share/nixos-gsettings-schemas/nixos-gsettings-desktop-schemas''${XDG_DATA_DIRS:+:}$XDG_DATA_DIRS + # Let nautilus find extensions export NAUTILUS_EXTENSION_DIR=${config.system.path}/lib/nautilus/extensions-3.0/ diff --git a/nixos/modules/services/x11/desktop-managers/kde4.nix b/nixos/modules/services/x11/desktop-managers/kde4.nix index 21b6243ba188..7830e984219a 100644 --- a/nixos/modules/services/x11/desktop-managers/kde4.nix +++ b/nixos/modules/services/x11/desktop-managers/kde4.nix @@ -111,6 +111,7 @@ in exec ${kde_workspace}/bin/startkde ''; }; + services.xserver.displayManager.desktopManagerHandlesLidAndPower = true; security.setuidOwners = singleton { program = "kcheckpass"; diff --git a/nixos/modules/services/x11/desktop-managers/kde5.nix b/nixos/modules/services/x11/desktop-managers/kde5.nix index 5061d59b7c7f..01a8704fea71 100644 --- a/nixos/modules/services/x11/desktop-managers/kde5.nix +++ b/nixos/modules/services/x11/desktop-managers/kde5.nix @@ -78,6 +78,7 @@ in bgSupport = true; start = ''exec ${plasma5.plasma-workspace}/bin/startkde;''; }; + services.xserver.displayManager.desktopManagerHandlesLidAndPower = true; security.setuidOwners = singleton { program = "kcheckpass"; diff --git a/nixos/modules/services/x11/desktop-managers/kodi.nix b/nixos/modules/services/x11/desktop-managers/kodi.nix index 1e30308a5139..e6d6efaf3a61 100644 --- a/nixos/modules/services/x11/desktop-managers/kodi.nix +++ b/nixos/modules/services/x11/desktop-managers/kodi.nix @@ -25,7 +25,8 @@ in waitPID=$! ''; }]; + services.xserver.displayManager.desktopManagerHandlesLidAndPower = true; environment.systemPackages = [ pkgs.kodi ]; }; -} \ No newline at end of file +} diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix index fce5bf11f053..746f810a11ff 100644 --- a/nixos/modules/services/x11/desktop-managers/xfce.nix +++ b/nixos/modules/services/x11/desktop-managers/xfce.nix @@ -37,6 +37,7 @@ in exec ${pkgs.stdenv.shell} ${pkgs.xfce.xinitrc} ''; }; + services.xserver.displayManager.desktopManagerHandlesLidAndPower = true; environment.systemPackages = [ pkgs.gtk # To get GTK+'s themes. @@ -62,7 +63,7 @@ in pkgs.xfce.xfwm4 # This supplies some "abstract" icons such as # "utilities-terminal" and "accessories-text-editor". - pkgs.gnome.gnomeicontheme + pkgs.gnome3.defaultIconTheme pkgs.desktop_file_utils pkgs.xfce.libxfce4ui pkgs.xfce.garcon diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix index 7e05cd84be64..fc0803f2acaf 100644 --- a/nixos/modules/services/x11/display-managers/default.nix +++ b/nixos/modules/services/x11/display-managers/default.nix @@ -62,7 +62,7 @@ let if [ -z "$_INHIBITION_LOCK_TAKEN" ]; then export _INHIBITION_LOCK_TAKEN=1 if ! ${config.systemd.package}/bin/loginctl show-session $XDG_SESSION_ID | grep -q '^RemoteHost='; then - exec ${config.systemd.package}/bin/systemd-inhibit --what=handle-lid-switch:handle-power-key --why="See NixOS configuration option 'services.xserver.displayManager.desktopManagerHandlesLidAndPower' for more information." "$0" "$sessionType" + exec ${config.systemd.package}/bin/systemd-inhibit --what=handle-lid-switch:handle-power-key --why="Desktop environment handles power events" "$0" "$sessionType" fi fi @@ -161,7 +161,11 @@ let exit 0 ''; - mkDesktops = names: pkgs.runCommand "desktops" {} + mkDesktops = names: pkgs.runCommand "desktops" + { # trivial derivation + preferLocalBuild = true; + allowSubstitutes = false; + } '' mkdir -p $out ${concatMapStrings (n: '' @@ -225,7 +229,7 @@ in desktopManagerHandlesLidAndPower = mkOption { type = types.bool; - default = true; + default = false; description = '' Whether the display manager should prevent systemd from handling lid and power events. This is normally handled by the desktop diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix index 6c3c52730863..55af2ecbb764 100644 --- a/nixos/modules/services/x11/display-managers/gdm.nix +++ b/nixos/modules/services/x11/display-managers/gdm.nix @@ -18,14 +18,45 @@ in services.xserver.displayManager.gdm = { - enable = mkOption { - type = types.bool; - default = false; - example = true; + enable = mkEnableOption '' + GDM as the display manager. + <emphasis>GDM is very experimental and may render system unusable.</emphasis> + ''; + + autoLogin = mkOption { + default = {}; description = '' - Whether to enable GDM as the display manager. - <emphasis>GDM is very experimental and may render system unusable.</emphasis> + Auto login configuration attrset. ''; + + type = types.submodule { + options = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Automatically log in as the sepecified <option>autoLogin.user</option>. + ''; + }; + + user = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + User to be used for the autologin. + ''; + }; + + delay = mkOption { + type = types.int; + default = 0; + description = '' + Seconds of inactivity after which the autologin will be performed. + ''; + }; + + }; + }; }; }; @@ -37,6 +68,13 @@ in config = mkIf cfg.gdm.enable { + assertions = [ + { assertion = let autoLogin = cfg.gdm.autoLogin; in + if autoLogin.enable then autoLogin.user != null else true; + message = "GDM auto-login requires services.xserver.displayManager.gdm.autoLogin.user to be set"; + } + ]; + services.xserver.displayManager.slim.enable = false; users.extraUsers.gdm = @@ -50,7 +88,7 @@ in users.extraGroups.gdm.gid = config.ids.gids.gdm; services.xserver.displayManager.job = - { + { environment = { GDM_X_SERVER = "${cfg.xserverBin} ${cfg.xserverArgs}"; GDM_SESSIONS_DIR = "${cfg.session.desktops}"; @@ -71,6 +109,25 @@ in programs.dconf.profiles.gdm = "${gdm}/share/dconf/profile/gdm"; + environment.etc."gdm/custom.conf".text = '' + [daemon] + ${optionalString cfg.gdm.autoLogin.enable '' + TimedLoginEnable=true + TimedLogin=${cfg.gdm.autoLogin.user} + TimedLoginDelay=${toString cfg.gdm.autoLogin.delay} + ''} + + [security] + + [xdmcp] + + [greeter] + + [chooser] + + [debug] + ''; + # GDM LFS PAM modules, adapted somehow to NixOS security.pam.services = { gdm-launch-environment.text = '' @@ -89,7 +146,7 @@ in session optional pam_permit.so ''; - gdm.text = '' + gdm.text = '' auth requisite pam_nologin.so auth required pam_env.so @@ -130,7 +187,7 @@ in "auth required pam_deny.so"} account sufficient pam_unix.so - + password requisite pam_unix.so nullok sha512 ${optionalString config.security.pam.enableEcryptfs "password optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so"} diff --git a/nixos/modules/services/x11/redshift.nix b/nixos/modules/services/x11/redshift.nix index 99d19f6ab151..4f39e05f0f8d 100644 --- a/nixos/modules/services/x11/redshift.nix +++ b/nixos/modules/services/x11/redshift.nix @@ -47,6 +47,13 @@ in { type = types.str; }; }; + + services.redshift.extraOptions = mkOption { + type = types.listOf types.str; + default = []; + example = [ "-v" "-m randr" ]; + description = "Additional command-line arguments to pass to the redshift(1) command"; + }; }; config = mkIf cfg.enable { @@ -59,7 +66,8 @@ in { ${pkgs.redshift}/bin/redshift \ -l ${cfg.latitude}:${cfg.longitude} \ -t ${toString cfg.temperature.day}:${toString cfg.temperature.night} \ - -b ${toString cfg.brightness.day}:${toString cfg.brightness.night} + -b ${toString cfg.brightness.day}:${toString cfg.brightness.night} \ + ${lib.strings.concatStringsSep " " cfg.extraOptions} ''; environment = { DISPLAY = ":0"; }; serviceConfig.Restart = "always"; diff --git a/nixos/modules/services/x11/window-managers/default.nix b/nixos/modules/services/x11/window-managers/default.nix index a8b1044ad365..4751de07a15d 100644 --- a/nixos/modules/services/x11/window-managers/default.nix +++ b/nixos/modules/services/x11/window-managers/default.nix @@ -25,6 +25,7 @@ in ./windowmaker.nix ./wmii.nix ./xmonad.nix + ./qtile.nix ./none.nix ]; options = { diff --git a/nixos/modules/services/x11/window-managers/icewm.nix b/nixos/modules/services/x11/window-managers/icewm.nix index 36028da453a5..9a3e80221890 100644 --- a/nixos/modules/services/x11/window-managers/icewm.nix +++ b/nixos/modules/services/x11/window-managers/icewm.nix @@ -3,29 +3,16 @@ with lib; let - cfg = config.services.xserver.windowManager.icewm; - in - { - ###### interface - options = { - - services.xserver.windowManager.icewm.enable = mkOption { - default = false; - description = "Enable the IceWM window manager."; - }; - + services.xserver.windowManager.icewm.enable = mkEnableOption "oroborus"; }; - ###### implementation - config = mkIf cfg.enable { - services.xserver.windowManager.session = singleton { name = "icewm"; start = @@ -36,7 +23,5 @@ in }; environment.systemPackages = [ pkgs.icewm ]; - }; - } diff --git a/nixos/modules/services/x11/window-managers/oroborus.nix b/nixos/modules/services/x11/window-managers/oroborus.nix new file mode 100644 index 000000000000..bd7e3396864b --- /dev/null +++ b/nixos/modules/services/x11/window-managers/oroborus.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.xserver.windowManager.oroborus; +in +{ + ###### interface + options = { + services.xserver.windowManager.oroborus.enable = mkEnableOption "oroborus"; + }; + + ###### implementation + config = mkIf cfg.enable { + services.xserver.windowManager.session = singleton { + name = "oroborus"; + start = '' + ${pkgs.oroborus}/bin/oroborus & + waitPID=$! + ''; + }; + environment.systemPackages = [ pkgs.oroborus ]; + }; +} diff --git a/nixos/modules/services/x11/window-managers/qtile.nix b/nixos/modules/services/x11/window-managers/qtile.nix new file mode 100644 index 000000000000..37f84f0903c3 --- /dev/null +++ b/nixos/modules/services/x11/window-managers/qtile.nix @@ -0,0 +1,25 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.xserver.windowManager.qtile; +in + +{ + options = { + services.xserver.windowManager.qtile.enable = mkEnableOption "qtile"; + }; + + config = mkIf cfg.enable { + services.xserver.windowManager.session = [{ + name = "qtile"; + start = '' + ${pkgs.qtile}/bin/qtile + waitPID=$! + ''; + }]; + + environment.systemPackages = [ pkgs.qtile ]; + }; +} diff --git a/nixos/modules/services/x11/window-managers/wmii.nix b/nixos/modules/services/x11/window-managers/wmii.nix index 75f6fdfe3bc4..e6f534a1be66 100644 --- a/nixos/modules/services/x11/window-managers/wmii.nix +++ b/nixos/modules/services/x11/window-managers/wmii.nix @@ -1,47 +1,43 @@ -{ config, lib, pkgs, ... }: - -with lib; +{ config, lib, pkgs, options, modulesPath }: let - + inherit (lib) mkOption mkIf singleton; cfg = config.services.xserver.windowManager.wmii; - + wmii = pkgs.wmii_hg; in - { options = { - services.xserver.windowManager.wmii.enable = mkOption { default = false; example = true; description = "Enable the wmii window manager."; }; - }; config = mkIf cfg.enable { - services.xserver.windowManager.session = singleton # stop wmii by # $wmiir xwrite /ctl quit # this will cause wmii exiting with exit code 0 + # (or "mod+a quit", which is bound to do the same thing in wmiirc + # by default) # # why this loop? # wmii crashes once a month here. That doesn't matter that much - # wmii can recover very well. However without loop the x session terminates and then your workspace setup is - # lost and all applications running on X will terminate. + # wmii can recover very well. However without loop the X session + # terminates and then your workspace setup is lost and all + # applications running on X will terminate. # Another use case is kill -9 wmii; after rotating screen. - # Note: we don't like kill for that purpose. But it works (-> subject "wmii and xrandr" on mailinglist) + # Note: we don't like kill for that purpose. But it works (-> + # subject "wmii and xrandr" on mailinglist) { name = "wmii"; start = '' while :; do - ${pkgs.wmiiSnap}/bin/wmii && break + ${wmii}/bin/wmii && break done ''; }; - environment.systemPackages = [ pkgs.wmiiSnap ]; - + environment.systemPackages = [ wmii ]; }; - } |