diff --git a/examples/default.nix b/examples/default.nix index 0a065b9..c359dc5 100644 --- a/examples/default.nix +++ b/examples/default.nix @@ -12,11 +12,36 @@ nixng, }: let + modifiedMakeSystem = + { + config ? { }, + specialArgs ? { }, + ... + }@args: + nglib.makeSystem ( + args + // { + config = { + nixos.acceptRisks = "I accept the risks"; + + imports = [ config ]; + }; + specialArgs = specialArgs // { + __enableExperimentalNixOSCompatibility = true; + }; + } + ); + + modifiedNglib = nglib // { + makeSystem = modifiedMakeSystem; + }; + examples = { "gitea" = ./gitea; "gitea-sane" = ./gitea/sane.nix; "apache" = ./apache; "nginx" = ./nginx; + "nginx-nixos" = ./nginx-nixos; "crond" = ./crond; "nix" = ./nix; "hydra" = ./hydra; @@ -33,4 +58,10 @@ let "ntfy-sh" = ./ntfy-sh; }; in -nixpkgs.lib.mapAttrs (_: v: import v { inherit nixpkgs nglib nixng; }) examples +nixpkgs.lib.mapAttrs ( + _: v: + import v { + inherit nixpkgs nixng; + nglib = modifiedNglib; + } +) examples diff --git a/examples/nginx-nixos/default.nix b/examples/nginx-nixos/default.nix new file mode 100644 index 0000000..84692e0 --- /dev/null +++ b/examples/nginx-nixos/default.nix @@ -0,0 +1,41 @@ +# SPDX-FileCopyrightText: 2021 Richard Brežák and NixNG contributors +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +{ nglib, nixpkgs, ... }: +nglib.makeSystem { + inherit nixpkgs; + system = "x86_64-linux"; + name = "nixng-nginx-nixos"; + config = ( + { pkgs, config, ... }: + { + config = { + dinit = { + enable = true; + }; + + init.services.nginx = { + shutdownOnExit = true; + ensureSomething.link."documentRoot" = { + src = "${pkgs.apacheHttpd}/htdocs"; + dst = "/var/www"; + }; + }; + + nixos.services.nginx = { + enable = true; + virtualHosts."example.org" = { + locations."/" = { + proxyPass = "google.com"; + }; + }; + }; + }; + } + ); +} diff --git a/lib/dag.nix b/lib/dag.nix index 2c5d7a1..298c33c 100644 --- a/lib/dag.nix +++ b/lib/dag.nix @@ -6,7 +6,7 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -{ lib }: +{ lib, ... }: import (builtins.fetchurl { url = "https://raw.githubusercontent.com/nix-community/home-manager/45abf3d38a2b51c00c347cab6950f3734e023bba/modules/lib/dag.nix"; sha256 = "sha256-NN9iKanf86D1MH9Nx8nsQj9T2+Poy9XeW9pLcZIyFHU="; diff --git a/lib/default.nix b/lib/default.nix index f3a6a25..dd54b19 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -1,13 +1,15 @@ lib: -let - inherit (lib) types; - this = { - makeSystem = import ./make-system.nix { - nglib = this; - overlay = import ../overlay; +lib.fix ( + nglib: + let + overlay = import ../overlay; + args = { + inherit lib nglib overlay; }; - dag = import ./dag.nix { inherit lib; }; - generators = import ./generators.nix { inherit lib; }; + in + { + dag = import ./dag.nix args; + generators = import ./generators.nix args; mkDefaultRec = lib.mapAttrsRecursive (_: v: lib.mkDefault v); mkApply = fun: x: { original = x; @@ -18,31 +20,31 @@ let description: lib.mkOption { inherit description; - type = types.attrsOf ( - types.submodule { + type = lib.types.attrsOf ( + lib.types.submodule { options = { data = lib.mkOption { description = '' Script fragment which to run. ''; - type = types.str; + type = lib.types.str; }; before = lib.mkOption { description = '' Script before dependencies. See /lib/dag.nix. ''; - type = with types; listOf str; + type = lib.types.listOf lib.types.str; }; after = lib.mkOption { description = '' Script after dependencies. See /lib/dag.nix ''; - type = with types; listOf str; + type = lib.types.listOf lib.types.str; }; }; } ); - apply = this.dag.dagTopoSort; + apply = nglib.dag.dagTopoSort; default = { }; }; @@ -63,11 +65,7 @@ let '') fragments )} ''; - - nottmpfiles = import ./nottmpfiles { - inherit lib; - nglib = this; - }; + nottmpfiles = import ./nottmpfiles args; maybeChangeUserAndGroup = user: group: script: @@ -75,6 +73,26 @@ let "chpst -u ${user}${lib.optionalString (group != null) ":${group}"} ${script}" else script; - }; -in -this + + errorExperimentalNixOS = + config: + lib.throwIfNot (config.nixos.acceptRisks == "I accept the risks") '' + NixOS module compatibility is highly experimental, severely unfinished and most definitely has + functional and security bugs. Unless you know what you're doing and are willing to accept the risks + reconsider it's usage. To signify you are aware of these risks, set the option + `config.nixos.acceptRisks` to `"I accept the risks"`. + + If you run into any of the aforementioned deficiencies please reach out on Matrix at + `#nixng:matrix.redalder.org`. + ''; + + inherit (import ./options.nix args) + mkUserOption + mkGroupOption + mkOptionsEqual + getOptionFromPath + ; + + makeSystem = import ./make-system.nix { inherit lib nglib overlay; }; + } +) diff --git a/lib/generators.nix b/lib/generators.nix index 551241e..451cd96 100644 --- a/lib/generators.nix +++ b/lib/generators.nix @@ -6,7 +6,7 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -{ lib }: +{ lib, ... }: let inherit (lib) isAttrs diff --git a/lib/make-system.nix b/lib/make-system.nix index 1f8ae23..1918807 100644 --- a/lib/make-system.nix +++ b/lib/make-system.nix @@ -7,7 +7,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. # These arguments are provided by the overarching NixNG repository and are not user confugurable. -{ nglib, overlay }: +{ nglib, overlay, ... }: # These arguments are user configurable { nixpkgs, @@ -24,6 +24,8 @@ let evaledModules = evalModules { specialArgs = specialArgs // { inherit nglib; + __enableExperimentalNixOSCompatibility = + specialArgs.__enableExperimentalNixOSCompatibility or false; }; modules = diff --git a/lib/options.nix b/lib/options.nix new file mode 100644 index 0000000..40321fe --- /dev/null +++ b/lib/options.nix @@ -0,0 +1,56 @@ +{ lib, nglib, ... }: +{ + mkUserOption = + user: description: + lib.mkOption { + inherit description; + type = lib.types.str; + default = user; + }; + + mkGroupOption = + group: description: + lib.mkOption { + inherit description; + type = lib.types.str; + default = group; + }; + + getOptionFromPath = + path: options: + let + getOptionFromPath' = + pathLeft: pathRight: subtree: + if pathRight == [ ] then + subtree + else + let + newSubtree = ( + subtree.${lib.head pathRight} or (lib.evalModules { + modules = subtree.type.getSubModules ++ subtree.definitions; + inherit (subtree.type.functor.payload) class specialArgs; + }).options.${lib.head pathRight} + or (abort ("cannot find option '" + lib.concatStringsSep "." path + "'")) + ); + in + getOptionFromPath' (pathLeft ++ [ (lib.head pathRight) ]) (lib.tail pathRight) newSubtree; + in + getOptionFromPath' [ ] path options; + + mkOptionsEqual = + to: from: mapper: + { config, options, ... }: + let + fromOpt = nglib.getOptionFromPath from options; + toOpt = nglib.getOptionFromPath to options; + + prio = fromOpt.highestPrio or lib.defaultOverridePriority; + defsWithPrio = map (def: lib.mkOverride prio (mapper def)) fromOpt.definitions; + in + { + config = lib.attrsets.setAttrByPath to (lib.mkMerge defsWithPrio); + options = lib.attrsets.setAttrByPath from ( + lib.mkOption { apply = x: lib.attrsets.getAttrFromPath to config; } + ); + }; +} diff --git a/modules/list.nix b/modules/list.nix index 9c60b6a..7d7df3a 100644 --- a/modules/list.nix +++ b/modules/list.nix @@ -50,4 +50,6 @@ ./services/dnsmasq.nix ./services/attic.nix ./services/ntfy-sh.nix + + ./nixos ] diff --git a/modules/nixos/assertions.nix b/modules/nixos/assertions.nix new file mode 100644 index 0000000..a41f3f1 --- /dev/null +++ b/modules/nixos/assertions.nix @@ -0,0 +1,16 @@ +{ + config, + lib, + nglib, + ... +}: +{ + options.nixos = lib.mkOption { type = lib.types.submodule { imports = [ ../assertions.nix ]; }; }; + + imports = [ + (nglib.mkOptionsEqual [ "assertions" ] [ + "nixos" + "assertions" + ] lib.id) + ]; +} diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix new file mode 100644 index 0000000..0429fb6 --- /dev/null +++ b/modules/nixos/default.nix @@ -0,0 +1,55 @@ +{ + lib, + pkgs, + config, + __enableExperimentalNixOSCompatibility, + ... +}: +{ + imports = lib.optionals __enableExperimentalNixOSCompatibility ([ + ./systemd.nix + ./nginx.nix + ./users.nix + ./postgresql.nix + ./assertions.nix + ./oauth2-proxy.nix + ./nix.nix + ./meta.nix + ./networking.nix + ]); + + options.nixos = lib.mkOption { + type = lib.types.submodule { + options = { + acceptRisks = lib.mkOption { + visible = false; + description = '' + This is an invisible option, intention is for the user to hit the scary warning first + and only then learn of this option and declare acceptance of the risks. + ''; + type = lib.types.str; + default = "I don't know of the risks"; + }; + }; + config._module.args = { + inherit pkgs; + }; + }; + default = { }; + }; + + config.assertions = lib.optionals __enableExperimentalNixOSCompatibility [ + { + assertion = (config.nixos.acceptRisks == "I accept the risks"); + message = '' + NixOS module compatibility is highly experimental, severely unfinished and most definitely has + functional and security bugs. Unless you know what you're doing and are willing to accept the risks + reconsider it's usage. To signify you are aware of these risks, set the option + `config.nixos.acceptRisks` to `"I accept the risks"`. + + If you run into any of the aforementioned deficiencies please reach out on Matrix at + `#nixng:matrix.redalder.org`. + ''; + } + ]; +} diff --git a/modules/nixos/meta.nix b/modules/nixos/meta.nix new file mode 100644 index 0000000..603a78d --- /dev/null +++ b/modules/nixos/meta.nix @@ -0,0 +1,6 @@ +{ lib, ... }: +{ + options = { + nixos.meta = lib.mkOption { type = lib.types.unspecified; }; + }; +} diff --git a/modules/nixos/networking.nix b/modules/nixos/networking.nix new file mode 100644 index 0000000..0fd6602 --- /dev/null +++ b/modules/nixos/networking.nix @@ -0,0 +1,13 @@ +{ lib, config, ... }: +{ + options = { + nixos.networking.hostName = lib.mkOption { + type = lib.types.str; + description = '' + Machine hostname, this has currently no effect on NixNG and is completely + local to the NixOS compatibility layer. + ''; + default = "unnamed"; + }; + }; +} diff --git a/modules/nixos/nginx.nix b/modules/nixos/nginx.nix new file mode 100644 index 0000000..0c293c8 --- /dev/null +++ b/modules/nixos/nginx.nix @@ -0,0 +1,235 @@ +{ + lib, + config, + pkgs, + options, + nglib, + ... +}: +let + cfg = config.nixos.services.nginx; + + recommendedProxyConfig = { + proxy_set_header = [ + [ + "Host" + "$$host" + ] + [ + "X-Real-IP" + "$$remote_addr" + ] + [ + "X-Forwarded-For" + "$$proxy_add_x_forwarded_for" + ] + [ + "X-Forwarded-Proto" + "$$scheme" + ] + [ + "X-Forwarded-Host" + "$$host" + ] + [ + "X-Forwarded-Server" + "$$host" + ] + ]; + }; +in +{ + options = { + nixos.services.nginx = { + enable = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Enable NixOS compatible nginx module. This module should have the same + semantics as the upstream module, as such see + [the upstream options](https://search.nixos.org/options?query=services.nginx). + + WARNING: this module only implements a rather small subset of the upstream + NixOS module, but the parts that are implemented should have mostly the same + semantics. + ''; + }; + + recommendedProxySettings = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + Applies recommended proxy settings, should be the same options as the + upstream NixOS module. + ''; + }; + + proxyTimeout = lib.mkOption { + type = lib.types.str; + default = "60s"; + example = "20s"; + description = '' + Change the proxy related timeouts in recommendedProxySettings. + ''; + }; + + virtualHosts = lib.mkOption { + description = '' + Declarative virtual host configuration. + ''; + type = lib.types.attrsOf ( + lib.types.submodule { + options = { + locations = lib.mkOption { + type = lib.types.attrsOf ( + lib.types.submodule { + options.proxyPass = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + }; + + options.proxyWebsockets = lib.mkOption { + type = lib.types.bool; + default = false; + }; + + options.extraConfig = lib.mkOption { + type = lib.types.lines; + default = ""; + }; + } + ); + default = { }; + }; + + forceSSL = lib.mkOption { + type = lib.types.bool; + default = false; + }; + + addSSL = lib.mkOption { + type = lib.types.bool; + default = false; + }; + + useHTTPS = lib.mkOption { + type = lib.types.bool; + default = false; + }; + }; + } + ); + default = { }; + }; + }; + }; + + imports = [ + (nglib.mkOptionsEqual + [ + "services" + "nginx" + "enable" + ] + [ + "nixos" + "services" + "nginx" + "enable" + ] + lib.id + ) + ]; + + config = { + services.nginx = lib.mkIf config.services.nginx.enable ({ + envsubst = true; + configuration = lib.singleton { + daemon = "off"; + worker_processes = 8; + user = "nginx"; + + events."" = { + use = "epoll"; + worker_connections = 512; + }; + + error_log = [ + "/dev/stderr" + "warn" + ]; + + pid = "/nginx.pid"; + + http."" = + [ + { + server_tokens = "off"; + include = [ [ "${pkgs.nginx}/conf/mime.types" ] ]; + charset = "utf-8"; + access_log = [ + "/dev/stdout" + "combined" + ]; + + # $connection_upgrade is used for websocket proxying + map."$$http_upgrade $$connection_upgrade" = { + default = "upgrade"; + "''" = "close"; + }; + } + ] + ++ (lib.optionals cfg.recommendedProxySettings [ + { + proxy_redirect = "off"; + proxy_connect_timeout = cfg.proxyTimeout; + proxy_send_timeout = cfg.proxyTimeout; + proxy_read_timeout = cfg.proxyTimeout; + proxy_http_version = "1.1"; + # don't let clients close the keep-alive connection to upstream. See the nginx blog for details: + # https://www.nginx.com/blog/avoiding-top-10-nginx-configuration-mistakes/#no-keepalives + proxy_set_header = [ + "Connection" + "''" + ]; + } + recommendedProxyConfig + ]) + ++ (lib.flip lib.mapAttrsToList cfg.virtualHosts ( + server_name: server: { + server."" = { + listen = [ + "80" + "http2" + ]; + inherit server_name; + + location = lib.flip lib.mapAttrs server.locations ( + location: settings: [ + (lib.optionalAttrs ( + settings.proxyPass != null && cfg.recommendedProxySettings + ) recommendedProxyConfig) + (lib.optionalAttrs settings.proxyWebsockets { + proxy_http_version = "1.1"; + proxy_set_header = [ + [ + "Upgrade" + "$$http_upgrade" + ] + [ + "Connection" + "$$connection_upgrade" + ] + ]; + }) + settings.extraConfig + (lib.optionalAttrs (settings.proxyPass != null) { proxy_pass = settings.proxyPass; }) + ] + ); + }; + } + )); + }; + }); + }; +} diff --git a/modules/nixos/nix.nix b/modules/nixos/nix.nix new file mode 100644 index 0000000..a92809e --- /dev/null +++ b/modules/nixos/nix.nix @@ -0,0 +1,22 @@ +{ + nglib, + lib, + config, + ... +}: +{ + imports = [ + (nglib.mkOptionsEqual + [ + "nix" + "config" + ] + [ + "nixos" + "nix" + "config" + ] + lib.id + ) + ]; +} diff --git a/modules/nixos/oauth2-proxy.nix b/modules/nixos/oauth2-proxy.nix new file mode 100644 index 0000000..d08e2d6 --- /dev/null +++ b/modules/nixos/oauth2-proxy.nix @@ -0,0 +1,12 @@ +{ lib, ... }: +{ + options = { + nixos.services.oauth2-proxy = lib.mkOption { + type = lib.types.unspecified; + default = { }; + description = '' + WARNING: this is only a stub module that does nothing. + ''; + }; + }; +} diff --git a/modules/nixos/postgresql.nix b/modules/nixos/postgresql.nix new file mode 100644 index 0000000..23f551f --- /dev/null +++ b/modules/nixos/postgresql.nix @@ -0,0 +1,38 @@ +{ + nglib, + lib, + config, + ... +}: +{ + options = { + nixos.services.postgresql = lib.mkOption { + type = lib.types.unspecified; + default = { }; + description = '' + Enable NixOS compatible PostgreSQL module. This module should have the same + semantics as the upstream module, as such see + [the upstream options](https://search.nixos.org/options?query=services.postgresql). + + WARNING: this module implements a rather complete subset of the upstream + NixOS module, but even then, it's highly experimental and may have semantic + differences. + ''; + }; + }; + + imports = [ + (nglib.mkOptionsEqual + [ + "services" + "postgresql" + ] + [ + "nixos" + "services" + "postgresql" + ] + lib.id + ) + ]; +} diff --git a/modules/nixos/systemd.nix b/modules/nixos/systemd.nix new file mode 100644 index 0000000..d7791c4 --- /dev/null +++ b/modules/nixos/systemd.nix @@ -0,0 +1,206 @@ +{ + lib, + nglib, + config, + pkgs, + ... +}: +{ + options = { + nixos.systemd.services = lib.mkOption { + type = lib.types.attrsOf ( + lib.types.submodule ( + { name, ... }: + { + options = { + description = lib.mkOption { + type = lib.types.str; + default = name; + }; + + after = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + }; + + wants = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + }; + + wantedBy = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + }; + + requires = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + }; + + requiredBy = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + }; + + environment = lib.mkOption { + type = lib.types.attrsOf lib.types.str; + default = { }; + }; + + path = lib.mkOption { + type = lib.types.listOf lib.types.package; + default = { }; + }; + + preStart = lib.mkOption { + type = lib.types.lines; + default = ""; + }; + + reloadIfChanged = lib.mkOption { type = lib.types.bool; }; + + serviceConfig = lib.mkOption { + type = lib.types.submodule { + options = { + Type = lib.mkOption { type = lib.types.str; }; + + ExecStart = lib.mkOption { + type = lib.types.either (lib.types.listOf lib.types.str) lib.types.str; + apply = x: lib.toList x; + }; + + ExecReload = lib.mkOption { + type = lib.types.either (lib.types.listOf lib.types.str) lib.types.str; + apply = x: lib.toList x; + }; + + User = lib.mkOption { type = lib.types.str; }; + + Group = lib.mkOption { type = lib.types.str; }; + + WorkingDirectory = lib.mkOption { type = lib.types.path; }; + + LoadCredential = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + }; + + RuntimeDirectory = lib.mkOption { type = lib.types.str; }; + + Environment = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + }; + + OOMPolicy = lib.mkOption { + type = lib.types.str; + default = ""; + }; + }; + }; + }; + }; + } + ) + ); + default = { }; + description = '' + NixOS compatible services module. This module does not have the same + semantics as the upstream module, as such take upstream behavior with + a lot of salt. + + WARNING: this module only implements a tiny subset of the upstream + NixOS module and the parts that are implemented do NOT have the same + semantics. This module is enough to get very basic NixOS services to work + but for anything more significat it'll for sure break. + ''; + }; + + nixos.systemd.tmpfiles = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + }; + }; + + config = { + init.services = ( + lib.flip lib.mapAttrs config.nixos.systemd.services ( + n: v: + let + combinedDeps = lib.unique (v.after ++ v.wants ++ v.requires); + withCredentials = v.serviceConfig.LoadCredential != [ ]; + credentialsDirectory = "/run/credentials/${n}"; + in + { + dependencies = lib.flip lib.map combinedDeps ( + e: + lib.pipe e [ + (lib.strings.removeSuffix ".service") + (lib.strings.removeSuffix ".target") + ] + ); + enabled = lib.elem "multi-user.target" (v.wantedBy ++ v.requiredBy); + environment = lib.mkMerge [ + v.environment + { + PATH = lib.makeBinPath v.path; + CREDENTIALS_DIRECTORY = lib.mkIf withCredentials credentialsDirectory; + } + (lib.listToAttrs ( + lib.map ( + env: + let + parts = lib.splitString "=" env; + envKey = lib.elemAt parts 0; + envValue = lib.replaceStrings [ "%d" ] [ credentialsDirectory ] (lib.elemAt parts 1); + in + assert (lib.assertMsg (lib.length parts == 2) "\"${env}\" is not of the format \"KEY=VALUE\""); + lib.nameValuePair envKey envValue + ) v.serviceConfig.Environment + )) + ]; + execStartPre = pkgs.writeShellScript "${n}-start-pre" '' + ${nglib.mergeShellFragmentsIsolated ( + lib.map (x: { + name = x; + data = '' + umask 077 + set -euo pipefail + _source="$(cut -f 2 -d ':'<<<"${x}")" + _dest="${credentialsDirectory}/$(cut -f 1 -d ':'<<<"${x}")" + + if ! [ -e "$_source" ] ; then + printf "Credential $_source for service ${n} not found.\n" + exit 1 + fi + + cp "$_source" "$_dest" + chown ${v.serviceConfig.User}:${v.serviceConfig.Group} "$_dest" + ''; + }) v.serviceConfig.LoadCredential + )} + + if ! [ "$_status" = "0" ] ; then + exit "$_status" + fi + + ${v.preStart} + ''; + execStart = pkgs.writeShellScript "${n}-start" ( + lib.concatStringsSep "\n" v.serviceConfig.ExecStart + ); + group = v.serviceConfig.Group; + user = v.serviceConfig.User; + workingDirectory = v.serviceConfig.WorkingDirectory; + tmpfiles = + with nglib.nottmpfiles.dsl; + lib.optionals withCredentials [ + (d credentialsDirectory "0700" config.init.services.${n}.user config.init.services.${n}.group _ _) + (R credentialsDirectory "0700" config.init.services.${n}.user config.init.services.${n}.group _ _) + ]; + } + ) + ); + }; +} diff --git a/modules/nixos/users.nix b/modules/nixos/users.nix new file mode 100644 index 0000000..958a333 --- /dev/null +++ b/modules/nixos/users.nix @@ -0,0 +1,138 @@ +{ + nglib, + lib, + config, + ... +}: +{ + options = { + nixos.users.users = lib.mkOption { + type = lib.types.attrsOf ( + lib.types.submodule ( + { name, ... }: + { + options = { + description = lib.mkOption { + type = lib.types.str; + description = '' + The users description; + ''; + }; + createHome = lib.mkOption { + type = lib.types.bool; + description = '' + Whether to create the user's home folder. + ''; + }; + home = lib.mkOption { + type = lib.types.path; + description = '' + Where should the users home folder be located. + ''; + }; + group = lib.mkOption { + type = lib.types.str; + description = '' + The user's primary group. + ''; + }; + extraGroups = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + description = '' + The user's supplementary groups. + ''; + }; + useDefaultShell = lib.mkOption { + type = lib.types.bool; + description = '' + Whether to use the default shell. + ''; + }; + isSystemUser = lib.mkOption { + type = lib.types.bool; + default = true; + description = '' + This doesn't do anything on NixNG but is here for eval-time compatibility. + Slight difference of behavior is expected. + ''; + }; + isNormalUser = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Indicates whether is an account for a 'real' user. + ''; + }; + name = lib.mkOption { + type = lib.types.str; + default = name; + readOnly = true; + }; + }; + } + ) + ); + default = { }; + description = '' + NixOS compatible users module. This module should have the same + semantics as the upstream module, as such see + [the upstream options](https://search.nixos.org/options?query=users.users). + + WARNING: this module only implements a rather small subset of the upstream + NixOS module, but the parts that are implemented should have mostly the same + semantics. + ''; + }; + + nixos.users.groups = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule { }); + default = { }; + description = '' + NixOS compatible users module. This module should have the same + semantics as the upstream module, as such see + [the upstream options](https://search.nixos.org/options?query=users.users). + + Also see the documentation for NixNG's `users.users`, this compatibility module + maps almost exactly onto it. + + WARNING: this module only implements a rather small subset of the upstream + NixOS module, but the parts that are implemented should have mostly the same + semantics. + ''; + }; + }; + + imports = [ + (nglib.mkOptionsEqual + [ + "users" + "users" + ] + [ + "nixos" + "users" + "users" + ] + ( + def: + lib.removeAttrs (lib.traceValSeq def) [ + "name" + "isSystemUser" + ] + ) + ) + (nglib.mkOptionsEqual + [ + "users" + "groups" + ] + [ + "nixos" + "users" + "groups" + ] + lib.id + ) + ]; +} diff --git a/modules/services/postgresql.nix b/modules/services/postgresql.nix index e090401..48345dd 100644 --- a/modules/services/postgresql.nix +++ b/modules/services/postgresql.nix @@ -105,7 +105,10 @@ in initdbArgs = lib.mkOption { type = with lib.types; listOf str; - default = [ ]; + default = [ + "-E" + "UTF8" + ]; example = [ "--data-checksums" "--allow-group-access"