diff options
author | Luca Bruno <lethalman88@gmail.com> | 2015-11-25 21:31:09 +0100 |
---|---|---|
committer | Luca Bruno <lethalman88@gmail.com> | 2015-11-25 21:37:30 +0100 |
commit | a41292792498e03024d682d092947c2153290073 (patch) | |
tree | b937402b60ea79cfa0e5562dad3268127a491d81 /nixos | |
parent | 8a664fd5bc6b170bdf809030de6871fd6a454f5a (diff) | |
parent | b34a6c96ee14518b82648c5a8c1b29225c15d9df (diff) |
Merge remote-tracking branch 'origin/master' into closure-size
Diffstat (limited to 'nixos')
39 files changed, 1040 insertions, 379 deletions
diff --git a/nixos/default.nix b/nixos/default.nix index 5d69b79e13a69..6359d10c88059 100644 --- a/nixos/default.nix +++ b/nixos/default.nix @@ -1,12 +1,20 @@ { configuration ? import ./lib/from-env.nix "NIXOS_CONFIG" <nixos-config> , system ? builtins.currentSystem +, extraModules ? [] + # This attribute is used to specify a different nixos version, a different + # system or additional modules which might be set conditionally. +, reEnter ? false }: let + reEnterModule = { + config.nixos.path = with (import ../lib); mkIf reEnter (mkForce null); + config.nixos.configuration = configuration; + }; eval = import ./lib/eval-config.nix { inherit system; - modules = [ configuration ]; + modules = [ configuration reEnterModule ] ++ extraModules; }; inherit (eval) pkgs; @@ -14,14 +22,14 @@ let # This is for `nixos-rebuild build-vm'. vmConfig = (import ./lib/eval-config.nix { inherit system; - modules = [ configuration ./modules/virtualisation/qemu-vm.nix ]; + modules = [ configuration reEnterModule ./modules/virtualisation/qemu-vm.nix ] ++ extraModules; }).config; # This is for `nixos-rebuild build-vm-with-bootloader'. vmWithBootLoaderConfig = (import ./lib/eval-config.nix { inherit system; modules = - [ configuration + [ configuration reEnterModule ./modules/virtualisation/qemu-vm.nix { virtualisation.useBootLoader = true; } ]; @@ -30,7 +38,7 @@ let in { - inherit (eval) config options; + inherit (eval.config.nixos.reflect) config options; system = eval.config.system.build.toplevel; diff --git a/nixos/doc/manual/configuration/configuration.xml b/nixos/doc/manual/configuration/configuration.xml index 8fde0dc7e6110..afffd60bc485f 100644 --- a/nixos/doc/manual/configuration/configuration.xml +++ b/nixos/doc/manual/configuration/configuration.xml @@ -26,6 +26,7 @@ effect after you run <command>nixos-rebuild</command>.</para> <!-- FIXME: auto-include NixOS module docs --> <xi:include href="postgresql.xml" /> +<xi:include href="nixos.xml" /> <!-- Apache; libvirtd virtualisation --> diff --git a/nixos/doc/manual/default.nix b/nixos/doc/manual/default.nix index 61a71d834050d..4bfd08869b7f1 100644 --- a/nixos/doc/manual/default.nix +++ b/nixos/doc/manual/default.nix @@ -55,6 +55,7 @@ let cp -prd $sources/* . # */ chmod -R u+w . cp ${../../modules/services/databases/postgresql.xml} configuration/postgresql.xml + cp ${../../modules/misc/nixos.xml} configuration/nixos.xml ln -s ${optionsDocBook} options-db.xml echo "${version}" > version ''; diff --git a/nixos/doc/manual/installation/obtaining.xml b/nixos/doc/manual/installation/obtaining.xml index afd6c9543f70c..f6e8b218e2b3c 100644 --- a/nixos/doc/manual/installation/obtaining.xml +++ b/nixos/doc/manual/installation/obtaining.xml @@ -39,8 +39,8 @@ running NixOS system through several other means: <para>Using NixOps, the NixOS-based cloud deployment tool, which allows you to provision VirtualBox and EC2 NixOS instances from declarative specifications. Check out the <link - xlink:href="https://github.com/NixOS/nixops">NixOps - homepage</link> for details.</para> + xlink:href="https://nixos.org/nixops">NixOps homepage</link> for + details.</para> </listitem> </itemizedlist> diff --git a/nixos/doc/manual/release-notes/rl-unstable.xml b/nixos/doc/manual/release-notes/rl-unstable.xml index 573b99d4902f4..97ac03a770f6e 100644 --- a/nixos/doc/manual/release-notes/rl-unstable.xml +++ b/nixos/doc/manual/release-notes/rl-unstable.xml @@ -6,6 +6,26 @@ <title>Unstable</title> +<para>In addition to numerous new and upgraded packages, this release +has the following highlights:</para> + +<itemizedlist> + + <listitem> + <para>You can now pin a specific version of NixOS in your <filename>configuration.nix</filename> + by setting: + +<programlisting> +nixos.path = ./nixpkgs-unstable-2015-12-06/nixos; +</programlisting> + + This will make NixOS re-evaluate your configuration with the modules of + the specified NixOS version at the given path. For more details, see + <xref linkend="module-misc-nixos" /></para> + </listitem> + +</itemizedlist> + <para>When upgrading from a previous release, please be aware of the following incompatible changes:</para> @@ -54,6 +74,21 @@ nginx.override { </para> </listitem> + <listitem> + <para><command>s3sync</command> is removed, as it hasn't been + developed by upstream for 4 years and only runs with ruby 1.8. + For an actively-developer alternative look at + <command>tarsnap</command> and others. + </para> + </listitem> + + <listitem> + <para><command>ruby_1_8</command> has been removed as it's not + supported from upstream anymore and probably contains security + issues. + </para> + </listitem> + </itemizedlist> </section> diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index de9a318fdd243..c9810b6fccb14 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -235,6 +235,8 @@ kibana = 211; xtreemfs = 212; calibre-server = 213; + heapster = 214; + bepasty = 215; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -448,6 +450,7 @@ #kibana = 211; xtreemfs = 212; calibre-server = 213; + bepasty = 215; # When adding a gid, make sure it doesn't match an existing # uid. Users and groups with the same name should have equal diff --git a/nixos/modules/misc/nixos.nix b/nixos/modules/misc/nixos.nix new file mode 100644 index 0000000000000..356129211d065 --- /dev/null +++ b/nixos/modules/misc/nixos.nix @@ -0,0 +1,82 @@ +{ config, options, lib, ... }: + +# This modules is used to inject a different NixOS version as well as its +# argument such that one can pin a specific version with the versionning +# system of the configuration. +let + nixosReentry = import config.nixos.path { + inherit (config.nixos) configuration extraModules; + inherit (config.nixpkgs) system; + reEnter = true; + }; +in + +with lib; + +{ + options = { + nixos.path = mkOption { + default = null; + example = literalExample "./nixpkgs-15.09/nixos"; + type = types.nullOr types.path; + description = '' + This option give the ability to evaluate the current set of modules + with a different version of NixOS. This option can be used version + the version of NixOS with the configuration without relying on the + <literal>NIX_PATH</literal> environment variable. + ''; + }; + + nixos.system = mkOption { + example = "i686-linux"; + type = types.uniq types.str; + description = '' + Name of the system used to compile NixOS. + ''; + }; + + nixos.extraModules = mkOption { + default = []; + example = literalExample "mkIf config.services.openssh.enable [ ./sshd-config.nix ]"; + type = types.listOf types.unspecified; + description = '' + Define additional modules which would be loaded to evaluate the + configuration. + ''; + }; + + nixos.configuration = mkOption { + type = types.unspecified; + internal = true; + description = '' + Option used by <filename>nixos/default.nix</filename> to re-inject + the same configuration module as the one used for the current + execution. + ''; + }; + + nixos.reflect = mkOption { + default = { inherit config options; }; + type = types.unspecified; + internal = true; + description = '' + Provides <literal>config</literal> and <literal>options</literal> + computed by the module system and given as argument to all + modules. These are used for introspection of options and + configuration by tools such as <literal>nixos-option</literal>. + ''; + }; + }; + + config = mkMerge [ + (mkIf (config.nixos.path != null) (mkForce { + system.build.toplevel = nixosReentry.system; + system.build.vm = nixosReentry.vm; + nixos.reflect = { inherit (nixosReentry) config options; }; + })) + + { meta.maintainers = singleton lib.maintainers.pierron; + meta.doc = ./nixos.xml; + } + ]; +} diff --git a/nixos/modules/misc/nixos.xml b/nixos/modules/misc/nixos.xml new file mode 100644 index 0000000000000..f8d3b4bc6e33b --- /dev/null +++ b/nixos/modules/misc/nixos.xml @@ -0,0 +1,84 @@ +<chapter xmlns="http://docbook.org/ns/docbook" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xi="http://www.w3.org/2001/XInclude" + version="5.0" + xml:id="module-misc-nixos"> + +<title>NixOS Reentry</title> + +<!-- FIXME: render nicely --> + +<!-- FIXME: source can be added automatically --> +<para><emphasis>Source:</emphasis> <filename>modules/misc/nixos.nix</filename></para> + +<!-- FIXME: more stuff, like maintainer? --> + +<para>NixOS reentry can be used for both pinning the evaluation to a +specific version of NixOS, and to dynamically add additional modules into +the Module evaluation.</para> + +<section><title>NixOS Version Pinning</title> + +<para>To pin a specific version of NixOS, you need a version that you can +either clone localy, or that you can fetch remotely.</para> + +<para>If you already have a cloned version of NixOS in the directory +<filename>/etc/nixos/nixpkgs-16-03</filename>, then you can specify the +<option>nixos.path</option> with either the path or the relative path of +your NixOS clone. For example, you can add the following to your +<filename>/etc/nixos/configuration.nix</filename> file: + +<programlisting> +nixos.path = ./nixpkgs-16-03/nixos; +</programlisting> +</para> + +<para>Another option is to fetch a specific version of NixOS, with either +the <literal>fetchTarball</literal> builtin, or the +<literal>pkgs.fetchFromGithub</literal> function and use the result as an +input. + +<programlisting> +nixos.path = "${builtins.fetchTarball https://github.com/NixOS/nixpkgs/archive/1f27976e03c15183191d1b4aa1a40d1f14666cd2.tar.gz}/nixos"; +</programlisting> +</para> + +</section> + + +<section><title>Adding Module Dynamically</title> + +<para>To add additional module, the recommended way is to use statically +known modules in the list of imported arguments as described in <xref +linkend="sec-modularity" />. Unfortunately, this recommended method has +limitation, such that the list of imported files cannot be selected based on +the content of the configuration. + +Fortunately, NixOS reentry system can be used as an alternative to register +new imported modules based on the content of the configuration. To do so, +one should define both <option>nixos.path</option> and +<option>nixos.extraModules</option> options. + +<programlisting> +nixos.path = <nixos>; +nixos.extraModules = + if config.networking.hostName == "server" then + [ ./server.nix ] else [ ./client.nix ]; +</programlisting> + +Also note, that the above can be reimplemented in a different way which is +not as expensive, by using <literal>mkIf</literal> at the top each +configuration if both modules are present on the file system (see <xref +linkend="sec-option-definitions" />) and by always inmporting both +modules.</para> + +</section> + +<section><title>Options</title> + +<para>FIXME: auto-generated list of module options.</para> + +</section> + + +</chapter> diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 034ea933a7dbb..a8cf38f1c8fe9 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -52,6 +52,7 @@ ./misc/lib.nix ./misc/locate.nix ./misc/meta.nix + ./misc/nixos.nix ./misc/nixpkgs.nix ./misc/passthru.nix ./misc/version.nix @@ -189,6 +190,7 @@ ./services/mail/spamassassin.nix ./services/misc/apache-kafka.nix ./services/misc/autofs.nix + ./services/misc/bepasty.nix ./services/misc/canto-daemon.nix ./services/misc/calibre-server.nix ./services/misc/cpuminer-cryptonight.nix @@ -238,6 +240,8 @@ ./services/monitoring/dd-agent.nix ./services/monitoring/grafana.nix ./services/monitoring/graphite.nix + ./services/monitoring/heapster.nix + ./services/monitoring/longview.nix ./services/monitoring/monit.nix ./services/monitoring/munin.nix ./services/monitoring/nagios.nix diff --git a/nixos/modules/profiles/base.nix b/nixos/modules/profiles/base.nix index 79324f83646bd..20a1f7f1ed8c2 100644 --- a/nixos/modules/profiles/base.nix +++ b/nixos/modules/profiles/base.nix @@ -1,7 +1,7 @@ # This module defines the software packages included in the "minimal" # installation CD. It might be useful elsewhere. -{ config, pkgs, ... }: +{ config, lib, pkgs, ... }: { # Include some utilities that are useful for installing or repairing @@ -50,5 +50,5 @@ boot.supportedFilesystems = [ "btrfs" "reiserfs" "vfat" "f2fs" "xfs" "zfs" "ntfs" "cifs" ]; # Configure host id for ZFS to work - networking.hostId = "8425e349"; + networking.hostId = lib.mkDefault "8425e349"; } diff --git a/nixos/modules/programs/bash/bash.nix b/nixos/modules/programs/bash/bash.nix index 75efd5e290397..1c3c07a1c2109 100644 --- a/nixos/modules/programs/bash/bash.nix +++ b/nixos/modules/programs/bash/bash.nix @@ -90,8 +90,8 @@ in promptInit = mkOption { default = '' - if test "$TERM" != "dumb"; then - # Provide a nice prompt. + # Provide a nice prompt if the terminal supports it. + if [ "$TERM" != "dumb" -o -n "$INSIDE_EMACS" ]; then PROMPT_COLOR="1;31m" let $UID && PROMPT_COLOR="1;32m" PS1="\n\[\033[$PROMPT_COLOR\][\u@\h:\w]\\$\[\033[0m\] " diff --git a/nixos/modules/programs/ibus.nix b/nixos/modules/programs/ibus.nix index b8702a743d8ae..a42753a292b28 100644 --- a/nixos/modules/programs/ibus.nix +++ b/nixos/modules/programs/ibus.nix @@ -27,7 +27,7 @@ in }; config = mkIf cfg.enable { - environment.systemPackages = [ pkgs.ibus ]; + environment.systemPackages = [ pkgs.ibus pkgs.gnome3.dconf ]; gtkPlugins = [ pkgs.ibus ]; qtPlugins = [ pkgs.ibus-qt ]; diff --git a/nixos/modules/programs/zsh/zsh.nix b/nixos/modules/programs/zsh/zsh.nix index 74dd6af0bddea..9f7596a21e725 100644 --- a/nixos/modules/programs/zsh/zsh.nix +++ b/nixos/modules/programs/zsh/zsh.nix @@ -25,7 +25,7 @@ in enable = mkOption { default = false; description = '' - Whenever to configure Zsh as an interactive shell. + Whether to configure zsh as an interactive shell. ''; type = types.bool; }; @@ -73,6 +73,14 @@ in type = types.lines; }; + enableCompletion = mkOption { + default = true; + description = '' + Enable zsh completion for all interactive zsh shells. + ''; + type = types.bool; + }; + }; }; @@ -101,6 +109,13 @@ in export HISTFILE=$HOME/.zsh_history setopt HIST_IGNORE_DUPS SHARE_HISTORY HIST_FCNTL_LOCK + + # Tell zsh how to find installed completions + for p in ''${(z)NIX_PROFILES}; do + fpath+=($p/share/zsh/site-functions $p/share/zsh/$ZSH_VERSION/functions) + done + + ${if cfg.enableCompletion then "autoload -U compinit && compinit" else ""} ''; }; @@ -161,7 +176,8 @@ in environment.etc."zinputrc".source = ./zinputrc; - environment.systemPackages = [ pkgs.zsh ]; + environment.systemPackages = [ pkgs.zsh ] + ++ optional cfg.enableCompletion pkgs.nix-zsh-completions; #users.defaultUserShell = mkDefault "/run/current-system/sw/bin/zsh"; diff --git a/nixos/modules/services/cluster/kubernetes.nix b/nixos/modules/services/cluster/kubernetes.nix index a06384e271392..42efde36678f2 100644 --- a/nixos/modules/services/cluster/kubernetes.nix +++ b/nixos/modules/services/cluster/kubernetes.nix @@ -512,6 +512,7 @@ in { wantedBy = [ "multi-user.target" ]; requires = ["kubernetes-setup.service"]; after = [ "network-interfaces.target" "etcd.service" "docker.service" ]; + path = [ pkgs.gitMinimal pkgs.openssh ]; script = '' export PATH="/bin:/sbin:/usr/bin:/usr/sbin:$PATH" exec ${cfg.package}/bin/kubelet \ diff --git a/nixos/modules/services/databases/influxdb.nix b/nixos/modules/services/databases/influxdb.nix index 4be0428caa330..8d63f14c67b5c 100644 --- a/nixos/modules/services/databases/influxdb.nix +++ b/nixos/modules/services/databases/influxdb.nix @@ -5,43 +5,103 @@ with lib; let cfg = config.services.influxdb; - influxdbConfig = pkgs.writeText "config.toml" '' - bind-address = "${cfg.bindAddress}" + configOptions = recursiveUpdate { + meta = { + bind-address = ":8088"; + commit-timeout = "50ms"; + dir = "${cfg.dataDir}/meta"; + election-timeout = "1s"; + heartbeat-timeout = "1s"; + hostname = "localhost"; + leader-lease-timeout = "500ms"; + retention-autocreate = true; + }; + + data = { + dir = "${cfg.dataDir}/data"; + wal-dir = "${cfg.dataDir}/wal"; + max-wal-size = 104857600; + wal-enable-logging = true; + wal-flush-interval = "10m"; + wal-partition-flush-delay = "2s"; + }; + + cluster = { + shard-writer-timeout = "5s"; + write-timeout = "5s"; + }; - [logging] - level = "info" - file = "stdout" + retention = { + enabled = true; + check-interval = "30m"; + }; - [admin] - port = ${toString cfg.adminPort} - assets = "${pkgs.influxdb}/share/influxdb/admin" + http = { + enabled = true; + auth-enabled = false; + bind-address = ":8086"; + https-enabled = false; + log-enabled = true; + pprof-enabled = false; + write-tracing = false; + }; - [api] - port = ${toString cfg.apiPort} - ${cfg.apiExtraConfig} + monitor = { + store-enabled = false; + store-database = "_internal"; + store-interval = "10s"; + }; - [input_plugins] - ${cfg.inputPluginsConfig} + admin = { + enabled = true; + bind-address = ":8083"; + https-enabled = false; + }; - [raft] - dir = "${cfg.dataDir}/raft" - ${cfg.raftConfig} + graphite = [{ + enabled = false; + }]; - [storage] - dir = "${cfg.dataDir}/db" - ${cfg.storageConfig} + udp = [{ + enabled = false; + }]; - [cluster] - ${cfg.clusterConfig} + collectd = { + enabled = false; + typesdb = "${pkgs.collectd}/share/collectd/types.db"; + database = "collectd_db"; + port = 25826; + }; - [sharding] - ${cfg.shardingConfig} + opentsdb = { + enabled = false; + }; - [wal] - dir = "${cfg.dataDir}/wal" - ${cfg.walConfig} + continuous_queries = { + enabled = true; + log-enabled = true; + recompute-previous-n = 2; + recompute-no-older-than = "10m"; + compute-runs-per-interval = 10; + compute-no-more-than = "2m"; + }; - ${cfg.extraConfig} + hinted-handoff = { + enabled = true; + dir = "${cfg.dataDir}/hh"; + max-size = 1073741824; + max-age = "168h"; + retry-rate-limit = 0; + retry-interval = "1s"; + }; + } cfg.extraConfig; + + configFile = pkgs.runCommand "config.toml" { + buildInputs = [ pkgs.remarshal ]; + } '' + remarshal -if json -of toml \ + < ${pkgs.writeText "config.json" (builtins.toJSON configOptions)} \ + > $out ''; in { @@ -82,124 +142,10 @@ in type = types.path; }; - bindAddress = mkOption { - default = "127.0.0.1"; - description = "Address where influxdb listens"; - type = types.str; - }; - - adminPort = mkOption { - default = 8083; - description = "The port where influxdb admin listens"; - type = types.int; - }; - - apiPort = mkOption { - default = 8086; - description = "The port where influxdb api listens"; - type = types.int; - }; - - apiExtraConfig = mkOption { - default = '' - read-timeout = "5s" - ''; - description = "Extra influxdb api configuration"; - example = '' - ssl-port = 8084 - ssl-cert = /path/to/cert.pem - read-timeout = "5s" - ''; - type = types.lines; - }; - - inputPluginsConfig = mkOption { - default = ""; - description = "Configuration of influxdb extra plugins"; - example = '' - [input_plugins.graphite] - enabled = true - port = 2003 - database = "graphite" - ''; - }; - - raftConfig = mkOption { - default = '' - port = 8090 - ''; - description = "Influxdb raft configuration"; - type = types.lines; - }; - - storageConfig = mkOption { - default = '' - write-buffer-size = 10000 - ''; - description = "Influxdb raft configuration"; - type = types.lines; - }; - - clusterConfig = mkOption { - default = '' - protobuf_port = 8099 - protobuf_timeout = "2s" - protobuf_heartbeat = "200ms" - protobuf_min_backoff = "1s" - protobuf_max_backoff = "10s" - - write-buffer-size = 10000 - max-response-buffer-size = 100 - - concurrent-shard-query-limit = 10 - ''; - description = "Influxdb cluster configuration"; - type = types.lines; - }; - - leveldbConfig = mkOption { - default = '' - max-open-files = 40 - lru-cache-size = "200m" - max-open-shards = 0 - point-batch-size = 100 - write-batch-size = 5000000 - ''; - description = "Influxdb leveldb configuration"; - type = types.lines; - }; - - shardingConfig = mkOption { - default = '' - replication-factor = 1 - - [sharding.short-term] - duration = "7d" - split = 1 - - [sharding.long-term] - duration = "30d" - split = 1 - ''; - description = "Influxdb sharding configuration"; - type = types.lines; - }; - - walConfig = mkOption { - default = '' - flush-after = 1000 - bookmark-after = 1000 - index-after = 1000 - requests-per-logfile = 10000 - ''; - description = "Influxdb write-ahead log configuration"; - type = types.lines; - }; - extraConfig = mkOption { - default = ""; + default = {}; description = "Extra configuration options for influxdb"; - type = types.string; + type = types.attrs; }; }; @@ -215,7 +161,7 @@ in wantedBy = [ "multi-user.target" ]; after = [ "network-interfaces.target" ]; serviceConfig = { - ExecStart = ''${cfg.package}/bin/influxdb -config "${influxdbConfig}"''; + ExecStart = ''${cfg.package}/bin/influxd -config "${configFile}"''; User = "${cfg.user}"; Group = "${cfg.group}"; PermissionsStartOnly = true; @@ -224,11 +170,6 @@ in mkdir -m 0770 -p ${cfg.dataDir} if [ "$(id -u)" = 0 ]; then chown -R ${cfg.user}:${cfg.group} ${cfg.dataDir}; fi ''; - postStart = mkBefore '' - until ${pkgs.curl.bin}/bin/curl -s -o /dev/null 'http://${cfg.bindAddress}:${toString cfg.apiPort}/'; do - sleep 1; - done - ''; }; users.extraUsers = optional (cfg.user == "influxdb") { diff --git a/nixos/modules/services/misc/bepasty.nix b/nixos/modules/services/misc/bepasty.nix new file mode 100644 index 0000000000000..12671cb1b6cd9 --- /dev/null +++ b/nixos/modules/services/misc/bepasty.nix @@ -0,0 +1,151 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + gunicorn = pkgs.pythonPackages.gunicorn; + bepasty = pkgs.pythonPackages.bepasty-server; + gevent = pkgs.pythonPackages.gevent; + python = pkgs.pythonPackages.python; + cfg = config.services.bepasty; + user = "bepasty"; + group = "bepasty"; + default_home = "/var/lib/bepasty"; +in +{ + options.services.bepasty = { + enable = mkEnableOption "Bepasty servers"; + + servers = mkOption { + default = {}; + description = '' + configure a number of bepasty servers which will be started with + gunicorn. + ''; + type = with types ; attrsOf (submodule ({ + + options = { + + bind = mkOption { + type = types.str; + description = '' + Bind address to be used for this server. + ''; + example = "0.0.0.0:8000"; + default = "127.0.0.1:8000"; + }; + + + dataDir = mkOption { + type = types.str; + description = '' + Path to the directory where the pastes will be saved to + ''; + default = default_home+"/data"; + }; + + defaultPermissions = mkOption { + type = types.str; + description = '' + default permissions for all unauthenticated accesses. + ''; + example = "read,create,delete"; + default = "read"; + }; + + extraConfig = mkOption { + type = types.str; + description = '' + Extra configuration for bepasty server to be appended on the + configuration. + see https://bepasty-server.readthedocs.org/en/latest/quickstart.html#configuring-bepasty + for all options. + ''; + default = ""; + example = '' + PERMISSIONS = { + 'myadminsecret': 'admin,list,create,read,delete', + } + MAX_ALLOWED_FILE_SIZE = 5 * 1000 * 1000 + ''; + }; + + secretKey = mkOption { + type = types.str; + description = '' + server secret for safe session cookies, must be set. + ''; + default = ""; + }; + + workDir = mkOption { + type = types.str; + description = '' + Path to the working directory (used for config and pidfile). + Defaults to the users home directory. + ''; + default = default_home; + }; + + }; + })); + }; + }; + + config = mkIf cfg.enable { + environment.systemPackages = [ bepasty ]; + + # creates gunicorn systemd service for each configured server + systemd.services = mapAttrs' (name: server: + nameValuePair ("bepasty-server-${name}-gunicorn") + ({ + description = "Bepasty Server ${name}"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + restartIfChanged = true; + + environment = { + BEPASTY_CONFIG = "${server.workDir}/bepasty-${name}.conf"; + PYTHONPATH= "${bepasty}/lib/${python.libPrefix}/site-packages:${gevent}/lib/${python.libPrefix}/site-packages"; + }; + + serviceConfig = { + Type = "simple"; + PrivateTmp = true; + ExecStartPre = assert server.secretKey != ""; pkgs.writeScript "bepasty-server.${name}-init" '' + #!/bin/sh + mkdir -p "${server.workDir}" + mkdir -p "${server.dataDir}" + chown ${user}:${group} "${server.workDir}" "${server.dataDir}" + cat > ${server.workDir}/bepasty-${name}.conf <<EOF + SITENAME="${name}" + STORAGE_FILESYSTEM_DIRECTORY="${server.dataDir}" + SECRET_KEY="${server.secretKey}" + DEFAULT_PERMISSIONS="${server.defaultPermissions}" + ${server.extraConfig} + EOF + ''; + ExecStart = ''${gunicorn}/bin/gunicorn bepasty.wsgi --name ${name} \ + -u ${user} \ + -g ${group} \ + --workers 3 --log-level=info \ + --bind=${server.bind} \ + --pid ${server.workDir}/gunicorn-${name}.pid \ + -k gevent + ''; + }; + }) + ) cfg.servers; + + users.extraUsers = [{ + uid = config.ids.uids.bepasty; + name = user; + group = group; + home = default_home; + }]; + + users.extraGroups = [{ + name = group; + gid = config.ids.gids.bepasty; + }]; + }; +} diff --git a/nixos/modules/services/misc/devmon.nix b/nixos/modules/services/misc/devmon.nix index 7a1f7c2e079e7..9dc8fee2964b1 100644 --- a/nixos/modules/services/misc/devmon.nix +++ b/nixos/modules/services/misc/devmon.nix @@ -18,11 +18,13 @@ in { }; config = mkIf cfg.enable { - systemd.services.devmon = { + systemd.user.services.devmon = { description = "devmon automatic device mounting daemon"; - wantedBy = [ "multi-user.target" ]; - path = [ pkgs.udevil ]; + wantedBy = [ "default.target" ]; + path = [ pkgs.udevil pkgs.procps pkgs.udisks2 pkgs.which ]; serviceConfig.ExecStart = "${pkgs.udevil}/bin/devmon"; }; + + services.udisks2.enable = true; }; } diff --git a/nixos/modules/services/monitoring/bosun.nix b/nixos/modules/services/monitoring/bosun.nix index ebe4741f01bd7..214a19d9483fe 100644 --- a/nixos/modules/services/monitoring/bosun.nix +++ b/nixos/modules/services/monitoring/bosun.nix @@ -6,9 +6,11 @@ let cfg = config.services.bosun; configFile = pkgs.writeText "bosun.conf" '' - tsdbHost = ${cfg.opentsdbHost} + ${optionalString (cfg.opentsdbHost !=null) "tsdbHost = ${cfg.opentsdbHost}"} + ${optionalString (cfg.influxHost !=null) "influxHost = ${cfg.influxHost}"} httpListen = ${cfg.listenAddress} stateFile = ${cfg.stateFile} + ledisDir = ${cfg.ledisDir} checkFrequency = ${cfg.checkFrequency} ${cfg.extraConfig} @@ -54,10 +56,20 @@ in { }; opentsdbHost = mkOption { - type = types.string; + type = types.nullOr types.string; default = "localhost:4242"; description = '' Host and port of the OpenTSDB database that stores bosun data. + To disable opentsdb you can pass null as parameter. + ''; + }; + + influxHost = mkOption { + type = types.nullOr types.string; + default = null; + example = "localhost:8086"; + description = '' + Host and port of the influxdb database. ''; }; @@ -70,13 +82,21 @@ in { }; stateFile = mkOption { - type = types.string; + type = types.path; default = "/var/lib/bosun/bosun.state"; description = '' Path to bosun's state file. ''; }; + ledisDir = mkOption { + type = types.path; + default = "/var/lib/bosun/ledis_data"; + description = '' + Path to bosun's ledis data dir + ''; + }; + checkFrequency = mkOption { type = types.str; default = "5m"; @@ -103,7 +123,7 @@ in { }; config = mkIf cfg.enable { - + systemd.services.bosun = { description = "bosun metrics collector (part of Bosun)"; wantedBy = [ "multi-user.target" ]; diff --git a/nixos/modules/services/monitoring/grafana.nix b/nixos/modules/services/monitoring/grafana.nix index 5302728eae91e..6053990e8d3b0 100644 --- a/nixos/modules/services/monitoring/grafana.nix +++ b/nixos/modules/services/monitoring/grafana.nix @@ -7,150 +7,37 @@ let b2s = val: if val then "true" else "false"; - cfgFile = pkgs.writeText "grafana.ini" '' - app_name = grafana - app_mode = production - - [server] - ; protocol (http or https) - protocol = ${cfg.protocol} - ; the ip address to bind to, empty will bind to all interfaces - http_addr = ${cfg.addr} - ; the http port to use - http_port = ${toString cfg.port} - ; The public facing domain name used to access grafana from a browser - domain = ${cfg.domain} - ; the full public facing url - root_url = ${cfg.rootUrl} - router_logging = false - ; the path relative to the binary where the static (html/js/css) files are placed - static_root_path = ${cfg.staticRootPath} - ; enable gzip - enable_gzip = false - ; https certs & key file - cert_file = ${cfg.certFile} - cert_key = ${cfg.certKey} - - [analytics] - # Server reporting, sends usage counters to stats.grafana.org every 24 hours. - # No ip addresses are being tracked, only simple counters to track - # running instances, dashboard and error counts. It is very helpful to us. - # Change this option to false to disable reporting. - reporting_enabled = true - ; Google Analytics universal tracking code, only enabled if you specify an id here - google_analytics_ua_id = - - [database] - ; Either "mysql", "postgres" or "sqlite3", it's your choice - type = ${cfg.database.type} - host = ${cfg.database.host} - name = ${cfg.database.name} - user = ${cfg.database.user} - password = ${cfg.database.password} - ; For "postgres" only, either "disable", "require" or "verify-full" - ssl_mode = disable - ; For "sqlite3" only - path = ${cfg.database.path} - - [session] - ; Either "memory", "file", "redis", "mysql", default is "memory" - provider = file - ; Provider config options - ; memory: not have any config yet - ; file: session file path, e.g. `data/sessions` - ; redis: config like redis server addr, poolSize, password, e.g. `127.0.0.1:6379,100,grafana` - ; mysql: go-sql-driver/mysql dsn config string, e.g. `user:password@tcp(127.0.0.1)/database_name` - provider_config = data/sessions - ; Session cookie name - cookie_name = grafana_sess - ; If you use session in https only, default is false - cookie_secure = false - ; Session life time, default is 86400 - session_life_time = 86400 - ; session id hash func, Either "sha1", "sha256" or "md5" default is sha1 - session_id_hashfunc = sha1 - ; Session hash key, default is use random string - session_id_hashkey = - - [security] - ; default admin user, created on startup - admin_user = ${cfg.security.adminUser} - ; default admin password, can be changed before first start of grafana, or in profile settings - admin_password = ${cfg.security.adminPassword} - ; used for signing - secret_key = ${cfg.security.secretKey} - ; Auto-login remember days - login_remember_days = 7 - cookie_username = grafana_user - cookie_remember_name = grafana_remember - - [users] - ; disable user signup / registration - allow_sign_up = ${b2s cfg.users.allowSignUp} - ; Allow non admin users to create organizations - allow_org_create = ${b2s cfg.users.allowOrgCreate} - # Set to true to automatically assign new users to the default organization (id 1) - auto_assign_org = ${b2s cfg.users.autoAssignOrg} - ; Default role new users will be automatically assigned (if disabled above is set to true) - auto_assign_org_role = ${cfg.users.autoAssignOrgRole} - - [auth.anonymous] - ; enable anonymous access - enabled = ${b2s cfg.auth.anonymous.enable} - ; specify organization name that should be used for unauthenticated users - org_name = Main Org. - ; specify role for unauthenticated users - org_role = Viewer - - [auth.github] - enabled = false - client_id = some_id - client_secret = some_secret - scopes = user:email - auth_url = https://github.com/login/oauth/authorize - token_url = https://github.com/login/oauth/access_token - - [auth.google] - enabled = false - client_id = some_client_id - client_secret = some_client_secret - scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email - auth_url = https://accounts.google.com/o/oauth2/auth - token_url = https://accounts.google.com/o/oauth2/token - - [log] - root_path = data/log - ; Either "console", "file", default is "console" - ; Use comma to separate multiple modes, e.g. "console, file" - mode = console - ; Buffer length of channel, keep it as it is if you don't know what it is. - buffer_len = 10000 - ; Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Trace" - level = Info - - ; For "console" mode only - [log.console] - level = - - ; For "file" mode only - [log.file] - level = - ; This enables automated log rotate(switch of following options), default is true - log_rotate = true - ; Max line number of single file, default is 1000000 - max_lines = 1000000 - ; Max size shift of single file, default is 28 means 1 << 28, 256MB - max_lines_shift = 28 - ; Segment log daily, default is true - daily_rotate = true - ; Expired days of log file(delete after max days), default is 7 - max_days = 7 - - [event_publisher] - enabled = false - rabbitmq_url = amqp://localhost/ - exchange = grafana_events - ''; + envOptions = { + PATHS_DATA = cfg.dataDir; + PATHS_LOGS = "${cfg.dataDir}/log"; + + SERVER_PROTOCOL = cfg.protocol; + SERVER_HTTP_ADDR = cfg.addr; + SERVER_HTTP_PORT = cfg.port; + SERVER_DOMAIN = cfg.domain; + SERVER_ROOT_URL = cfg.rootUrl; + SERVER_STATIC_ROOT_PATH = cfg.staticRootPath; + SERVER_CERT_FILE = cfg.certFile; + SERVER_CERT_KEY = cfg.certKey; + + DATABASE_TYPE = cfg.database.type; + DATABASE_HOST = cfg.database.host; + DATABASE_NAME = cfg.database.name; + DATABASE_USER = cfg.database.user; + DATABASE_PASSWORD = cfg.database.password; + DATABASE_PATH = cfg.database.path; + + SECURITY_ADMIN_USER = cfg.security.adminUser; + SECURITY_ADMIN_PASSWORD = cfg.security.adminPassword; + SECURITY_SECRET_KEY = cfg.security.secretKey; + + USERS_ALLOW_SIGN_UP = b2s cfg.users.allowSignUp; + USERS_ALLOW_ORG_CREATE = b2s cfg.users.allowOrgCreate; + USERS_AUTO_ASSIGN_ORG = b2s cfg.users.autoAssignOrg; + USERS_AUTO_ASSIGN_ORG_ROLE = cfg.users.autoAssignOrgRole; + + AUTH_ANONYMOUS_ENABLE = b2s cfg.auth.anonymous.enable; + } // cfg.extraOptions; in { options.services.grafana = { @@ -306,6 +193,16 @@ in { type = types.bool; }; }; + + extraOptions = mkOption { + description = '' + Extra configuration options passed as env variables as specified in + <link xlink:href="http://docs.grafana.org/installation/configuration/">documentation</link>, + but without GF_ prefix + ''; + default = {}; + type = types.attrsOf types.str; + }; }; config = mkIf cfg.enable { @@ -317,11 +214,15 @@ in { description = "Grafana Service Daemon"; wantedBy = ["multi-user.target"]; after = ["networking.target"]; + environment = mapAttrs' (n: v: nameValuePair "GF_${n}" (toString v)) envOptions; serviceConfig = { - ExecStart = "${cfg.package}/bin/grafana --config ${cfgFile} web"; + ExecStart = "${cfg.package}/bin/grafana -homepath ${cfg.dataDir}"; WorkingDirectory = cfg.dataDir; User = "grafana"; }; + preStart = '' + ln -fs ${cfg.package}/share/grafana/conf ${cfg.dataDir} + ''; }; users.extraUsers.grafana = { @@ -331,7 +232,7 @@ in { createHome = true; }; - services.grafana.staticRootPath = mkDefault "${cfg.package.out}/share/go/src/github.com/grafana/grafana/public"; + services.grafana.staticRootPath = mkDefault "${cfg.package}/share/grafana/public"; }; } diff --git a/nixos/modules/services/monitoring/heapster.nix b/nixos/modules/services/monitoring/heapster.nix new file mode 100644 index 0000000000000..74b8c9ccd3ed0 --- /dev/null +++ b/nixos/modules/services/monitoring/heapster.nix @@ -0,0 +1,57 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.heapster; +in { + options.services.heapster = { + enable = mkOption { + description = "Whether to enable heapster monitoring"; + default = false; + type = types.bool; + }; + + source = mkOption { + description = "Heapster metric source"; + example = "kubernetes:https://kubernetes.default"; + type = types.string; + }; + + sink = mkOption { + description = "Heapster metic sink"; + example = "influxdb:http://localhost:8086"; + type = types.string; + }; + + extraOpts = mkOption { + description = "Heapster extra options"; + default = ""; + type = types.string; + }; + + package = mkOption { + description = "Package to use by heapster"; + default = pkgs.heapster; + type = types.package; + }; + }; + + config = mkIf cfg.enable { + systemd.services.heapster = { + wantedBy = ["multi-user.target"]; + after = ["cadvisor.service" "kube-apiserver.service"]; + + serviceConfig = { + ExecStart = "${cfg.package}/bin/heapster --source=${cfg.source} --sink=${cfg.sink} ${cfg.extraOpts}"; + User = "heapster"; + }; + }; + + users.extraUsers = singleton { + name = "heapster"; + uid = config.ids.uids.heapster; + description = "Heapster user"; + }; + }; +} diff --git a/nixos/modules/services/monitoring/longview.nix b/nixos/modules/services/monitoring/longview.nix new file mode 100644 index 0000000000000..770d56e60efb1 --- /dev/null +++ b/nixos/modules/services/monitoring/longview.nix @@ -0,0 +1,118 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.longview; + + pidFile = "/run/longview.pid"; + + apacheConf = optionalString (cfg.apacheStatusUrl != "") '' + location ${cfg.apacheStatusUrl}?auto + ''; + mysqlConf = optionalString (cfg.mysqlUser != "") '' + username ${cfg.mysqlUser} + password ${cfg.mysqlPassword} + ''; + nginxConf = optionalString (cfg.nginxStatusUrl != "") '' + location ${cfg.nginxStatusUrl} + ''; + +in + +{ + options = { + + services.longview = { + + enable = mkOption { + type = types.bool; + default = false; + description = '' + If enabled, system metrics will be sent to Linode LongView. + ''; + }; + + apiKey = mkOption { + type = types.str; + example = "01234567-89AB-CDEF-0123456789ABCDEF"; + description = '' + Longview API key. To get this, look in Longview settings which + are found at https://manager.linode.com/longview/. + ''; + }; + + apacheStatusUrl = mkOption { + type = types.str; + default = ""; + example = "http://127.0.0.1/server-status"; + description = '' + The Apache status page URL. If provided, Longview will + gather statistics from this location. This requires Apache + mod_status to be loaded and enabled. + ''; + }; + + nginxStatusUrl = mkOption { + type = types.str; + default = ""; + example = "http://127.0.0.1/nginx_status"; + description = '' + The Nginx status page URL. Longview will gather statistics + from this URL. This requires the Nginx stub_status module to + be enabled and configured at the given location. + ''; + }; + + mysqlUser = mkOption { + type = types.str; + default = ""; + description = '' + The user for connecting to the MySQL database. If provided, + Longview will connect to MySQL and collect statistics about + queries, etc. This user does not need to have been granted + any extra privileges. + ''; + }; + + mysqlPassword = mkOption { + type = types.str; + description = '' + The password corresponding to mysqlUser. Warning: this is + stored in cleartext in the Nix store! + ''; + }; + }; + + }; + + config = mkIf cfg.enable { + systemd.services.longview = + { description = "Longview Metrics Collection"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig.Type = "forking"; + serviceConfig.ExecStop = "-${pkgs.coreutils}/bin/kill -TERM $MAINPID"; + serviceConfig.ExecReload = "-${pkgs.coreutils}/bin/kill -HUP $MAINPID"; + serviceConfig.PIDFile = pidFile; + serviceConfig.ExecStart = "${pkgs.longview}/bin/longview"; + }; + + environment.etc."linode/longview.key" = { + mode = "0400"; + text = cfg.apiKey; + }; + environment.etc."linode/longview.d/Apache.conf" = { + mode = "0400"; + text = apacheConf; + }; + environment.etc."linode/longview.d/MySQL.conf" = { + mode = "0400"; + text = mysqlConf; + }; + environment.etc."linode/longview.d/Nginx.conf" = { + mode = "0400"; + text = nginxConf; + }; + }; +} diff --git a/nixos/modules/services/networking/i2pd.nix b/nixos/modules/services/networking/i2pd.nix index 5e974555aada6..c467402dbcf69 100644 --- a/nixos/modules/services/networking/i2pd.nix +++ b/nixos/modules/services/networking/i2pd.nix @@ -10,23 +10,59 @@ let extip = "EXTIP=\$(${pkgs.curl.bin}/bin/curl -sf \"http://jsonip.com\" | ${pkgs.gawk}/bin/awk -F'\"' '{print $4}')"; - i2pSh = pkgs.writeScriptBin "i2pd" '' + toOneZero = b: if b then "1" else "0"; + + i2pdConf = pkgs.writeText "i2pd.conf" '' + v6 = ${toOneZero cfg.enableIPv6} + unreachable = ${toOneZero cfg.unreachable} + floodfill = ${toOneZero cfg.floodfill} + ${if isNull cfg.port then "" else "port = ${toString cfg.port}"} + httpproxyport = ${toString cfg.proxy.httpPort} + socksproxyport = ${toString cfg.proxy.socksPort} + ircaddress = ${cfg.irc.host} + ircport = ${toString cfg.irc.port} + ircdest = ${cfg.irc.dest} + irckeys = ${cfg.irc.keyFile} + eepport = ${toString cfg.eep.port} + ${if isNull cfg.sam.port then "" else "--samport=${toString cfg.sam.port}"} + eephost = ${cfg.eep.host} + eepkeys = ${cfg.eep.keyFile} + ''; + + i2pdTunnelConf = pkgs.writeText "i2pd-tunnels.conf" '' + ${flip concatMapStrings + (collect (tun: tun ? port && tun ? destination) cfg.outTunnels) + (tun: let portStr = toString tun.port; in '' + [${tun.name}] + type = client + destination = ${tun.destination} + keys = ${tun.keys} + address = ${tun.address} + port = ${toString tun.port} + '') + } + ${flip concatMapStrings + (collect (tun: tun ? port && tun ? host) cfg.outTunnels) + (tun: let portStr = toString tun.port; in '' + [${tun.name}] + type = server + destination = ${tun.destination} + keys = ${tun.keys} + host = ${tun.address} + port = ${tun.port} + inport = ${tun.inPort} + accesslist = ${concatStringSep "," tun.accessList} + '') + } + ''; + + i2pdSh = pkgs.writeScriptBin "i2pd" '' #!/bin/sh ${if isNull cfg.extIp then extip else ""} - ${pkgs.i2pd}/bin/i2p --log=1 --daemon=0 --service=0 \ - --v6=${if cfg.enableIPv6 then "1" else "0"} \ - --unreachable=${if cfg.unreachable then "1" else "0"} \ + ${pkgs.i2pd}/bin/i2pd --log=1 --daemon=0 --service=0 \ --host=${if isNull cfg.extIp then "$EXTIP" else cfg.extIp} \ - ${if isNull cfg.port then "" else "--port=${toString cfg.port}"} \ - --httpproxyport=${toString cfg.proxy.httpPort} \ - --socksproxyport=${toString cfg.proxy.socksPort} \ - --ircport=${toString cfg.irc.port} \ - --ircdest=${cfg.irc.dest} \ - --irckeys=${cfg.irc.keyFile} \ - --eepport=${toString cfg.eep.port} \ - ${if isNull cfg.sam.port then "" else "--samport=${toString cfg.sam.port}"} \ - --eephost=${cfg.eep.host} \ - --eepkeys=${cfg.eep.keyFile} + --conf=${i2pdConf} \ + --tunnelscfg=${i2pdTunnelConf} ''; in @@ -63,11 +99,19 @@ in ''; }; + floodfill = mkOption { + type = types.bool; + default = false; + description = '' + If the router is declared to be unreachable and needs introduction nodes. + ''; + }; + port = mkOption { type = with types; nullOr int; default = null; description = '' - I2P listen port. If no one is given the router will pick between 9111 and 30777. + I2P listen port. If no one is given the router will pick between 9111 and 30777. ''; }; @@ -107,6 +151,13 @@ in }; irc = { + host = mkOption { + type = types.str; + default = "127.0.0.1"; + description = '' + Address to forward incoming traffic to. 127.0.0.1 by default. + ''; + }; dest = mkOption { type = types.str; default = "irc.postman.i2p"; @@ -163,6 +214,94 @@ in ''; }; }; + + outTunnels = mkOption { + default = {}; + type = with types; loaOf optionSet; + description = '' + ''; + options = [ ({ name, config, ... }: { + + options = { + name = mkOption { + type = types.str; + description = "The name of the tunnel."; + }; + destination = mkOption { + type = types.str; + description = "Remote endpoint, I2P hostname or b32.i2p address."; + }; + keys = mkOption { + type = types.str; + default = name + "-keys.dat"; + description = "Keyset used for tunnel identity."; + }; + address = mkOption { + type = types.str; + default = "127.0.0.1"; + description = "Local bind address for tunnel."; + }; + port = mkOption { + type = types.int; + default = 0; + description = "Local tunnel listen port."; + }; + }; + + config = { + name = mkDefault name; + }; + + }) ]; + }; + + inTunnels = mkOption { + default = {}; + type = with types; loaOf optionSet; + description = '' + ''; + options = [ ({ name, config, ... }: { + + options = { + + name = mkOption { + type = types.str; + description = "The name of the tunnel."; + }; + keys = mkOption { + type = types.path; + default = name + "-keys.dat"; + description = "Keyset used for tunnel identity."; + }; + address = mkOption { + type = types.str; + default = "127.0.0.1"; + description = "Local service IP address."; + }; + port = mkOption { + type = types.int; + default = 0; + description = "Local tunnel listen port."; + }; + inPort = mkOption { + type = types.int; + default = 0; + description = "I2P service port. Default to the tunnel's listen port."; + }; + accessList = mkOption { + type = with types; listOf str; + default = []; + description = "I2P nodes that are allowed to connect to this service."; + }; + + }; + + config = { + name = mkDefault name; + }; + + }) ]; + }; }; }; @@ -190,9 +329,8 @@ in User = "i2pd"; WorkingDirectory = homeDir; Restart = "on-abort"; - ExecStart = "${i2pSh}/bin/i2pd"; + ExecStart = "${i2pdSh}/bin/i2pd"; }; }; }; } -# diff --git a/nixos/modules/services/networking/nix-serve.nix b/nixos/modules/services/networking/nix-serve.nix index 4f8b9357a828b..880a1d361dfeb 100644 --- a/nixos/modules/services/networking/nix-serve.nix +++ b/nixos/modules/services/networking/nix-serve.nix @@ -56,7 +56,7 @@ in serviceConfig = { ExecStart = "${pkgs.nix-serve}/bin/nix-serve " + - "--port ${cfg.bindAddress}:${toString cfg.port} ${cfg.extraParams}"; + "--listen ${cfg.bindAddress}:${toString cfg.port} ${cfg.extraParams}"; User = "nix-serve"; Group = "nogroup"; }; diff --git a/nixos/modules/services/scheduling/cron.nix b/nixos/modules/services/scheduling/cron.nix index 1b5e83173e8fe..f5e132fd77d87 100644 --- a/nixos/modules/services/scheduling/cron.nix +++ b/nixos/modules/services/scheduling/cron.nix @@ -39,7 +39,7 @@ in enable = mkOption { type = types.bool; - default = true; + example = true; description = "Whether to enable the Vixie cron daemon."; }; diff --git a/nixos/modules/services/torrent/transmission.nix b/nixos/modules/services/torrent/transmission.nix index c8fc08570408c..5822fb111b82c 100644 --- a/nixos/modules/services/torrent/transmission.nix +++ b/nixos/modules/services/torrent/transmission.nix @@ -9,7 +9,7 @@ let homeDir = "/var/lib/transmission"; downloadDir = "${homeDir}/Downloads"; incompleteDir = "${homeDir}/.incomplete"; - + settingsDir = "${homeDir}/.config/transmission-daemon"; settingsFile = pkgs.writeText "settings.json" (builtins.toJSON fullSettings); @@ -21,7 +21,7 @@ let else toString ''"${x}"''; # for users in group "transmission" to have access to torrents - fullSettings = cfg.settings // { umask = 2; }; + fullSettings = { download-dir = downloadDir; incomplete-dir = incompleteDir; } // cfg.settings // { umask = 2; }; in { options = { @@ -35,7 +35,7 @@ in Transmission daemon can be controlled via the RPC interface using transmission-remote or the WebUI (http://localhost:9091/ by default). - Torrents are downloaded to ${homeDir}/Downloads/ by default and are + Torrents are downloaded to ${downloadDir} by default and are accessible to users in the "transmission" group. ''; }; @@ -83,7 +83,7 @@ in # 1) Only the "transmission" user and group have access to torrents. # 2) Optionally update/force specific fields into the configuration file. serviceConfig.ExecStartPre = '' - ${pkgs.stdenv.shell} -c "chmod 770 ${homeDir} && mkdir -p ${settingsDir} ${downloadDir} ${incompleteDir} && rm -f ${settingsDir}/settings.json && cp -f ${settingsFile} ${settingsDir}/settings.json" + ${pkgs.stdenv.shell} -c "mkdir -p ${homeDir} ${settingsDir} ${fullSettings.download-dir} ${fullSettings.incomplete-dir} && chmod 770 ${homeDir} ${settingsDir} ${fullSettings.download-dir} ${fullSettings.incomplete-dir} && rm -f ${settingsDir}/settings.json && cp -f ${settingsFile} ${settingsDir}/settings.json" ''; serviceConfig.ExecStart = "${pkgs.transmission}/bin/transmission-daemon -f --port ${toString config.services.transmission.port}"; serviceConfig.ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; diff --git a/nixos/modules/services/web-servers/apache-httpd/wordpress.nix b/nixos/modules/services/web-servers/apache-httpd/wordpress.nix index 921f774bcaa02..7a0314027a3d7 100644 --- a/nixos/modules/services/web-servers/apache-httpd/wordpress.nix +++ b/nixos/modules/services/web-servers/apache-httpd/wordpress.nix @@ -17,10 +17,10 @@ let define('DB_HOST', '${config.dbHost}'); define('DB_CHARSET', 'utf8'); $table_prefix = '${config.tablePrefix}'; + ${config.extraConfig} if ( !defined('ABSPATH') ) define('ABSPATH', dirname(__FILE__) . '/'); require_once(ABSPATH . 'wp-settings.php'); - ${config.extraConfig} ''; # .htaccess to support pretty URLs diff --git a/nixos/modules/services/x11/desktop-managers/kde5.nix b/nixos/modules/services/x11/desktop-managers/kde5.nix index 6fdd5b4fa36df..dc6aa137cbd3d 100644 --- a/nixos/modules/services/x11/desktop-managers/kde5.nix +++ b/nixos/modules/services/x11/desktop-managers/kde5.nix @@ -108,7 +108,7 @@ in kdeApps.okular kdeApps.print-manager - kdeApps.oxygen-icons + (kdeApps.oxygen-icons or kf5.oxygen-icons5) pkgs.hicolor_icon_theme plasma5.kde-gtk-config @@ -155,7 +155,7 @@ in GST_PLUGIN_SYSTEM_PATH_1_0 = [ "/lib/gstreamer-1.0" ]; }; - fonts.fonts = [ plasma5.oxygen-fonts ]; + fonts.fonts = [ (plasma5.oxygen-fonts or pkgs.noto-fonts) ]; programs.ssh.askPassword = "${plasma5.ksshaskpass}/bin/ksshaskpass"; diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix index 88eefa13de35e..33b6dd32c1936 100644 --- a/nixos/modules/services/x11/desktop-managers/xfce.nix +++ b/nixos/modules/services/x11/desktop-managers/xfce.nix @@ -18,6 +18,14 @@ in description = "Enable the Xfce desktop environment."; }; + services.xserver.desktopManager.xfce.thunarPlugins = mkOption { + default = []; + type = types.listOf types.package; + example = literalExample "[ pkgs.xfce.thunar-archive-plugin ]"; + description = '' + A list of plugin that should be installed with Thunar. + ''; + }; }; @@ -49,7 +57,7 @@ in pkgs.xfce.mousepad pkgs.xfce.ristretto pkgs.xfce.terminal - pkgs.xfce.thunar + (pkgs.xfce.thunar.override { thunarPlugins = cfg.thunarPlugins; }) pkgs.xfce.xfce4icontheme pkgs.xfce.xfce4panel pkgs.xfce.xfce4session diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix index 58eb6f050131e..52847d2f8d2c8 100644 --- a/nixos/modules/services/x11/display-managers/gdm.nix +++ b/nixos/modules/services/x11/display-managers/gdm.nix @@ -162,7 +162,7 @@ in gdm.text = '' auth requisite pam_nologin.so - auth required pam_env.so + auth required pam_env.so envfile=${config.system.build.pamEnvironment} auth required pam_succeed_if.so uid >= 1000 quiet auth optional ${gnome3.gnome_keyring}/lib/security/pam_gnome_keyring.so diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix index 2dfa07ac6cb13..48fab02435665 100644 --- a/nixos/modules/services/x11/display-managers/lightdm.nix +++ b/nixos/modules/services/x11/display-managers/lightdm.nix @@ -150,7 +150,7 @@ in allowNullPassword = true; startSession = true; text = '' - auth required pam_env.so + auth required pam_env.so envfile=${config.system.build.pamEnvironment} auth required pam_permit.so account required pam_permit.so diff --git a/nixos/modules/services/x11/display-managers/slim.nix b/nixos/modules/services/x11/display-managers/slim.nix index 545f4283828a9..e3db0230d3b7b 100644 --- a/nixos/modules/services/x11/display-managers/slim.nix +++ b/nixos/modules/services/x11/display-managers/slim.nix @@ -18,6 +18,7 @@ let halt_cmd ${config.systemd.package}/sbin/shutdown -h now reboot_cmd ${config.systemd.package}/sbin/shutdown -r now ${optionalString (cfg.defaultUser != null) ("default_user " + cfg.defaultUser)} + ${optionalString (cfg.defaultUser != null) ("focus_password yes")} ${optionalString cfg.autoLogin "auto_login yes"} ${cfg.extraConfig} ''; @@ -57,8 +58,8 @@ in theme = mkOption { type = types.nullOr types.path; default = pkgs.fetchurl { - url = https://github.com/jagajaga/nixos-slim-theme/archive/1.1.tar.gz; - sha256 = "66c3020a6716130a20c3898567339b990fbd7888a3b7bbcb688f6544d1c05c31"; + url = "https://github.com/jagajaga/nixos-slim-theme/archive/2.0.tar.gz"; + sha256 = "0lldizhigx7bjhxkipii87y432hlf5wdvamnfxrryf9z7zkfypc8"; }; example = literalExample '' pkgs.fetchurl { diff --git a/nixos/modules/system/boot/systemd-unit-options.nix b/nixos/modules/system/boot/systemd-unit-options.nix index a7a334dec285e..d4cab93b26b83 100644 --- a/nixos/modules/system/boot/systemd-unit-options.nix +++ b/nixos/modules/system/boot/systemd-unit-options.nix @@ -170,6 +170,15 @@ in rec { ''; }; + onFailure = mkOption { + default = []; + type = types.listOf types.str; + description = '' + A list of one or more units that are activated when + this unit enters the "failed" state. + ''; + }; + }; diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix index 0b7647093e0f3..d145baeebe936 100644 --- a/nixos/modules/system/boot/systemd.nix +++ b/nixos/modules/system/boot/systemd.nix @@ -199,6 +199,8 @@ let { X-Restart-Triggers = toString config.restartTriggers; } // optionalAttrs (config.description != "") { Description = config.description; + } // optionalAttrs (config.onFailure != []) { + OnFailure = toString config.onFailure; }; }; }; diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix index dbe0c9c6e03a4..d0dd7670157ef 100644 --- a/nixos/modules/tasks/filesystems.nix +++ b/nixos/modules/tasks/filesystems.nix @@ -58,6 +58,15 @@ let ''; }; + formatOptions = mkOption { + default = ""; + type = types.str; + description = '' + If <option>autoFormat</option> option is set specifies + extra options passed to mkfs. + ''; + }; + autoResize = mkOption { default = false; type = types.bool; @@ -81,6 +90,9 @@ let mountPoint = mkDefault name; device = mkIf (config.fsType == "tmpfs") (mkDefault config.fsType); options = mkIf config.autoResize "x-nixos.autoresize"; + + # -F needed to allow bare block device without partitions + formatOptions = mkIf ((builtins.substring 0 3 config.fsType) == "ext") (mkDefault "-F"); }; }; @@ -192,8 +204,6 @@ in let mountPoint' = escapeSystemdPath fs.mountPoint; device' = escapeSystemdPath fs.device; - # -F needed to allow bare block device without partitions - mkfsOpts = optional ((builtins.substring 0 3 fs.fsType) == "ext") "-F"; in nameValuePair "mkfs-${device'}" { description = "Initialisation of Filesystem ${fs.device}"; wantedBy = [ "${mountPoint'}.mount" ]; @@ -208,7 +218,7 @@ in type=$(blkid -p -s TYPE -o value "${fs.device}" || true) if [ -z "$type" ]; then echo "creating ${fs.fsType} filesystem on ${fs.device}..." - mkfs.${fs.fsType} ${concatStringsSep " " mkfsOpts} "${fs.device}" + mkfs.${fs.fsType} ${fs.formatOptions} "${fs.device}" fi ''; unitConfig.RequiresMountsFor = [ "${dirOf fs.device}" ]; diff --git a/nixos/modules/tasks/scsi-link-power-management.nix b/nixos/modules/tasks/scsi-link-power-management.nix index a74023dec21a9..484c0a0186d7f 100644 --- a/nixos/modules/tasks/scsi-link-power-management.nix +++ b/nixos/modules/tasks/scsi-link-power-management.nix @@ -2,18 +2,19 @@ with lib; +let cfg = config.powerManagement.scsiLinkPolicy; in + { ###### interface options = { powerManagement.scsiLinkPolicy = mkOption { - default = ""; - example = "min_power"; - type = types.str; + default = null; + type = types.nullOr (types.enum [ "min_power" "max_performance" "medium_power" ]); description = '' - Configure the SCSI link power management policy. By default, - the kernel configures "max_performance". + SCSI link power management policy. The kernel default is + "max_performance". ''; }; @@ -22,25 +23,10 @@ with lib; ###### implementation - config = mkIf (config.powerManagement.scsiLinkPolicy != "") { - - jobs."scsi-link-pm" = - { description = "SCSI Link Power Management Policy"; - - startOn = "stopped udevtrigger"; - - task = true; - - unitConfig.ConditionPathIsReadWrite = "/sys/class/scsi_host"; - - script = '' - shopt -s nullglob - for x in /sys/class/scsi_host/host*/link_power_management_policy; do - echo ${config.powerManagement.scsiLinkPolicy} > $x - done - ''; - }; - + config = mkIf (cfg != null) { + services.udev.extraRules = '' + SUBSYSTEM=="scsi_host", ACTION=="add", KERNEL=="host*", ATTR{link_power_management_policy}="${cfg}" + ''; }; } diff --git a/nixos/modules/virtualisation/docker.nix b/nixos/modules/virtualisation/docker.nix index 0c642bf3b816c..718ca08514771 100644 --- a/nixos/modules/virtualisation/docker.nix +++ b/nixos/modules/virtualisation/docker.nix @@ -31,16 +31,11 @@ in socketActivation = mkOption { type = types.bool; - default = false; + default = true; description = '' This option enables docker with socket activation. I.e. docker will start when first called by client. - - Note: This is false by default because systemd lower than 214 that - nixos uses so far, doesn't support SocketGroup option, so socket - created by docker has root group now. This will likely be changed - in future. So set this option explicitly to false if you wish. ''; }; storageDriver = diff --git a/nixos/release.nix b/nixos/release.nix index 1a1ed4bca4106..f0df3fe3e1efd 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -276,6 +276,7 @@ in rec { tests.networkingProxy = callTest tests/networking-proxy.nix {}; tests.nfs3 = callTest tests/nfs.nix { version = 3; }; tests.nfs4 = callTest tests/nfs.nix { version = 4; }; + tests.nixosPinVersion = callTest tests/nixos-pin-version.nix {}; tests.nsd = callTest tests/nsd.nix {}; tests.openssh = callTest tests/openssh.nix {}; tests.panamax = hydraJob (import tests/panamax.nix { system = "x86_64-linux"; }); @@ -284,6 +285,7 @@ in rec { tests.proxy = callTest tests/proxy.nix {}; tests.quake3 = callTest tests/quake3.nix {}; tests.runInMachine = callTest tests/run-in-machine.nix {}; + tests.sddm = callTest tests/sddm.nix {}; tests.simple = callTest tests/simple.nix {}; tests.tomcat = callTest tests/tomcat.nix {}; tests.udisks2 = callTest tests/udisks2.nix {}; diff --git a/nixos/tests/nixos-pin-version.nix b/nixos/tests/nixos-pin-version.nix new file mode 100644 index 0000000000000..91fba2e759d28 --- /dev/null +++ b/nixos/tests/nixos-pin-version.nix @@ -0,0 +1,57 @@ +{ system ? builtins.currentSystem }: + +with import ../lib/testing.nix { inherit system; }; +let +in + +pkgs.stdenv.mkDerivation rec { + name = "nixos-pin-version"; + src = ../..; + buildInputs = with pkgs; [ nix gnugrep ]; + + withoutPath = pkgs.writeText "configuration.nix" '' + { + nixos.extraModules = [ ({lib, ...}: { system.nixosRevision = lib.mkForce "ABCDEF"; }) ]; + } + ''; + + withPath = pkgs.writeText "configuration.nix" '' + { + nixos.path = ${src}/nixos ; + nixos.extraModules = [ ({lib, ...}: { system.nixosRevision = lib.mkForce "ABCDEF"; }) ]; + } + ''; + + phases = "buildPhase"; + buildPhase = '' + datadir="${pkgs.nix}/share" + export TEST_ROOT=$(pwd)/test-tmp + export NIX_STORE_DIR=$TEST_ROOT/store + export NIX_LOCALSTATE_DIR=$TEST_ROOT/var + export NIX_LOG_DIR=$TEST_ROOT/var/log/nix + export NIX_STATE_DIR=$TEST_ROOT/var/nix + export NIX_DB_DIR=$TEST_ROOT/db + export NIX_CONF_DIR=$TEST_ROOT/etc + export NIX_MANIFESTS_DIR=$TEST_ROOT/var/nix/manifests + export NIX_BUILD_HOOK= + export PAGER=cat + cacheDir=$TEST_ROOT/binary-cache + nix-store --init + + export NIX_PATH="nixpkgs=$src:nixos=$src/nixos:nixos-config=${withoutPath}" ; + if test $(nix-instantiate $src/nixos -A config.system.nixosRevision --eval-only) != '"ABCDEF"' ; then :; + else + echo "Unexpected re-entry without the nixos.path option defined."; + exit 1; + fi; + + export NIX_PATH="nixpkgs=$src:nixos=$src/nixos:nixos-config=${withPath}" ; + if test $(nix-instantiate $src/nixos -A config.system.nixosRevision --eval-only) = '"ABCDEF"' ; then :; + else + echo "Expected a re-entry when the nixos.path option is defined."; + exit 1; + fi; + + touch $out; + ''; +} diff --git a/nixos/tests/sddm.nix b/nixos/tests/sddm.nix new file mode 100644 index 0000000000000..e11b5714d5c28 --- /dev/null +++ b/nixos/tests/sddm.nix @@ -0,0 +1,28 @@ +import ./make-test.nix ({ pkgs, ...} : { + name = "sddm"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ ttuegel ]; + }; + + machine = { lib, ... }: { + imports = [ ./common/user-account.nix ]; + services.xserver.enable = true; + services.xserver.displayManager.sddm = { + enable = true; + autoLogin = { + enable = true; + user = "alice"; + }; + }; + services.xserver.windowManager.default = "icewm"; + services.xserver.windowManager.icewm.enable = true; + services.xserver.desktopManager.default = "none"; + }; + + enableOCR = true; + + testScript = { nodes, ... }: '' + startAll; + $machine->waitForWindow("^IceWM "); + ''; +}) |