diff options
Diffstat (limited to 'nixos')
31 files changed, 878 insertions, 381 deletions
diff --git a/nixos/doc/manual/configuration/configuration.xml b/nixos/doc/manual/configuration/configuration.xml index 44ff1f1b571a7..6949189b8883c 100644 --- a/nixos/doc/manual/configuration/configuration.xml +++ b/nixos/doc/manual/configuration/configuration.xml @@ -23,6 +23,7 @@ <xi:include href="xfce.xml" /> <xi:include href="networking.xml" /> <xi:include href="linux-kernel.xml" /> + <xi:include href="subversion.xml" /> <xi:include href="../generated/modules.xml" xpointer="xpointer(//section[@id='modules']/*)" /> <xi:include href="profiles.xml" /> <xi:include href="kubernetes.xml" /> diff --git a/nixos/doc/manual/configuration/subversion.xml b/nixos/doc/manual/configuration/subversion.xml new file mode 100644 index 0000000000000..940d63cc4e6de --- /dev/null +++ b/nixos/doc/manual/configuration/subversion.xml @@ -0,0 +1,140 @@ +<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-services-subversion"> + <title>Subversion</title> + + <para> + <link xlink:href="https://subversion.apache.org/">Subversion</link> + is a centralized version-control system. It can use a <link + xlink:href="http://svnbook.red-bean.com/en/1.7/svn-book.html#svn.serverconfig.choosing">variety + of protocols</link> for communication between client and server. + </para> + <section xml:id="module-services-subversion-apache-httpd"> + <title>Subversion inside Apache HTTP</title> + + <para> + This section focuses on configuring a web-based server on top of + the Apache HTTP server, which uses + <link xlink:href="http://www.webdav.org/">WebDAV</link>/<link + xlink:href="http://www.webdav.org/deltav/WWW10/deltav-intro.htm">DeltaV</link> + for communication. + </para> + + <para>For more information on the general setup, please refer to + the <link + xlink:href="http://svnbook.red-bean.com/en/1.7/svn-book.html#svn.serverconfig.httpd">the + appropriate section of the Subversion book</link>. + </para> + + <para>To configure, include in + <literal>/etc/nixos/configuration.nix</literal> code to activate + Apache HTTP, setting <xref linkend="opt-services.httpd.adminAddr" /> + appropriately: + </para> + + <para> +<programlisting> + services.httpd.enable = true; + services.httpd.adminAddr = ...; + networking.firewall.allowedTCPPorts = [ 80 443 ]; +</programlisting> + </para> + + <para>For a simple Subversion server with basic authentication, + configure the Subversion module for Apache as follows, setting + <literal>hostName</literal> and <literal>documentRoot</literal> + appropriately, and <literal>SVNParentPath</literal> to the parent + directory of the repositories, + <literal>AuthzSVNAccessFile</literal> to the location of the + <code>.authz</code> file describing access permission, and + <literal>AuthUserFile</literal> to the password file. + </para> + <para> +<programlisting> +services.httpd.extraModules = [ + # note that order is *super* important here + { name = "dav_svn"; path = "${pkgs.apacheHttpdPackages.subversion}/modules/mod_dav_svn.so"; } + { name = "authz_svn"; path = "${pkgs.apacheHttpdPackages.subversion}/modules/mod_authz_svn.so"; } + ]; + services.httpd.virtualHosts = { + "svn" = { + hostName = HOSTNAME; + documentRoot = DOCUMENTROOT; + locations."/svn".extraConfig = '' + DAV svn + SVNParentPath REPO_PARENT + AuthzSVNAccessFile ACCESS_FILE + AuthName "SVN Repositories" + AuthType Basic + AuthUserFile PASSWORD_FILE + Require valid-user + ''; + } +</programlisting> + </para> + + <para> + The key <code>"svn"</code> is just a symbolic name identifying the + virtual host. The <code>"/svn"</code> in + <code>locations."/svn".extraConfig</code> is the path underneath + which the repositories will be served. + </para> + + <para><link + xlink:href="https://wiki.archlinux.org/index.php/Subversion">This + page</link> explains how to set up the Subversion configuration + itself. This boils down to the following: + </para> + <para> + Underneath <literal>REPO_PARENT</literal> repositories can be set up + as follows: + </para> + <para> +<screen> +<prompt>$ </prompt> svn create REPO_NAME +</screen> + </para> + <para>Repository files need to be accessible by + <literal>wwwrun</literal>: + </para> + <para> +<screen> +<prompt>$ </prompt> chown -R wwwrun:wwwrun REPO_PARENT +</screen> + </para> + <para> + The password file <literal>PASSWORD_FILE</literal> can be created as follows: + </para> + <para> +<screen> +<prompt>$ </prompt> htpasswd -cs PASSWORD_FILE USER_NAME +</screen> + </para> + <para> + Additional users can be set up similarly, omitting the + <code>c</code> flag: + </para> + <para> +<screen> +<prompt>$ </prompt> htpasswd -s PASSWORD_FILE USER_NAME +</screen> + </para> + <para> + The file describing access permissions + <literal>ACCESS_FILE</literal> will look something like + the following: + </para> + <para> +<programlisting> +[/] +* = r + +[REPO_NAME:/] +USER_NAME = rw +</programlisting> + </para> + <para>The Subversion repositories will be accessible as <code>http://HOSTNAME/svn/REPO_NAME</code>.</para> + </section> +</chapter> diff --git a/nixos/doc/manual/release-notes/rl-2103.xml b/nixos/doc/manual/release-notes/rl-2103.xml index 10d5cda77464b..fda0f8ea074df 100644 --- a/nixos/doc/manual/release-notes/rl-2103.xml +++ b/nixos/doc/manual/release-notes/rl-2103.xml @@ -56,6 +56,11 @@ section of the NixOS manual</link> for more information. </para> </listitem> + <listitem> + <para> + <xref linkend="opt-services.samba-wsdd.enable" /> Web Services Dynamic Discovery host daemon + </para> + </listitem> </itemizedlist> </section> @@ -185,6 +190,48 @@ which is the new stable release. OpenAFS 1.6 was removed. </para> </listitem> + <listitem> + <para> + The <literal>openldap</literal> module now has support for OLC-style + configuration, users of the <literal>configDir</literal> option may wish + to migrate. If you continue to use <literal>configDir</literal>, ensure that + <literal>olcPidFile</literal> is set to <literal>/run/slapd/slapd.pid</literal>. + </para> + <para> + As a result, <literal>extraConfig</literal> and <literal>extraDatabaseConfig</literal> + are removed. To help with migration, you can convert your <literal>slapd.conf</literal> + file to OLC configuration with the following script (find the location of this + configuration file by running <literal>systemctl status openldap</literal>, it is the + <literal>-f</literal> option. + </para> + <programlisting> + TMPDIR=$(mktemp -d) + slaptest -f /path/to/slapd.conf $TMPDIR + slapcat -F $TMPDIR -n0 -H 'ldap:///???(!(objectClass=olcSchemaConfig))' + </programlisting> + <para> + This will dump your current configuration in LDIF format, which should be + straightforward to convert into Nix settings. This does not show your schema + configuration, as this is unnecessarily verbose for users of the default schemas + and <literal>slaptest</literal> is buggy with schemas directly in the config file. + </para> + </listitem> + <listitem> + <para> + Amazon EC2 and OpenStack Compute (nova) images now re-fetch instance meta data and user data from the instance + metadata service (IMDS) on each boot. For example: stopping an EC2 instance, changing its user data, and + restarting the instance will now cause it to fetch and apply the new user data. + </para> + <warning> + <para> + Specifically, <literal>/etc/ec2-metadata</literal> is re-populated on each boot. Some NixOS scripts that read + from this directory are guarded to only run if the files they want to manipulate do not already exist, and so + will not re-apply their changes if the IMDS response changes. Examples: <literal>root</literal>'s SSH key is + only added if <literal>/root/.ssh/authorized_keys</literal> does not exist, and SSH host keys are only set from + user data if they do not exist in <literal>/etc/ssh</literal>. + </para> + </warning> + </listitem> </itemizedlist> </section> diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index bafa222504009..cf0198d7b93d0 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -135,7 +135,7 @@ in #keys = 96; # unused #haproxy = 97; # dynamically allocated as of 2020-03-11 mongodb = 98; - openldap = 99; + #openldap = 99; # dynamically allocated as of PR#94610 #users = 100; # unused cgminer = 101; munin = 102; @@ -451,7 +451,7 @@ in keys = 96; #haproxy = 97; # dynamically allocated as of 2020-03-11 #mongodb = 98; # unused - openldap = 99; + #openldap = 99; # dynamically allocated as of PR#94610 munin = 102; #logcheck = 103; # unused #nix-ssh = 104; # unused diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 0a38fa317305d..214d9356aa6a4 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -583,6 +583,7 @@ ./services/network-filesystems/orangefs/client.nix ./services/network-filesystems/rsyncd.nix ./services/network-filesystems/samba.nix + ./services/network-filesystems/samba-wsdd.nix ./services/network-filesystems/tahoe.nix ./services/network-filesystems/diod.nix ./services/network-filesystems/u9fs.nix diff --git a/nixos/modules/services/databases/foundationdb.nix b/nixos/modules/services/databases/foundationdb.nix index 18727acc7c756..e22127403e91c 100644 --- a/nixos/modules/services/databases/foundationdb.nix +++ b/nixos/modules/services/databases/foundationdb.nix @@ -233,7 +233,7 @@ in type = types.str; default = "Check.Valid=1,Check.Unexpired=1"; description = '' - "Peer verification string". This may be used to adjust which TLS + "Peer verification string". This may be used to adjust which TLS client certificates a server will accept, as a form of user authorization; for example, it may only accept TLS clients who offer a certificate abiding by some locality or organization name. diff --git a/nixos/modules/services/databases/openldap.nix b/nixos/modules/services/databases/openldap.nix index 7472538b887e3..94a5c573768b3 100644 --- a/nixos/modules/services/databases/openldap.nix +++ b/nixos/modules/services/databases/openldap.nix @@ -1,43 +1,121 @@ { config, lib, pkgs, ... }: with lib; - let - cfg = config.services.openldap; + legacyOptions = [ "rootpwFile" "suffix" "dataDir" "rootdn" "rootpw" ]; openldap = cfg.package; - - dataFile = pkgs.writeText "ldap-contents.ldif" cfg.declarativeContents; - configFile = pkgs.writeText "slapd.conf" ((optionalString cfg.defaultSchemas '' - include ${openldap.out}/etc/schema/core.schema - include ${openldap.out}/etc/schema/cosine.schema - include ${openldap.out}/etc/schema/inetorgperson.schema - include ${openldap.out}/etc/schema/nis.schema - '') + '' - ${cfg.extraConfig} - database ${cfg.database} - suffix ${cfg.suffix} - rootdn ${cfg.rootdn} - ${if (cfg.rootpw != null) then '' - rootpw ${cfg.rootpw} - '' else '' - include ${cfg.rootpwFile} - ''} - directory ${cfg.dataDir} - ${cfg.extraDatabaseConfig} - ''); - configOpts = if cfg.configDir == null then "-f ${configFile}" - else "-F ${cfg.configDir}"; -in - -{ - - ###### interface - + configDir = if cfg.configDir != null then cfg.configDir else "/etc/openldap/slapd.d"; + + ldapValueType = let + # Can't do types.either with multiple non-overlapping submodules, so define our own + singleLdapValueType = lib.mkOptionType rec { + name = "LDAP"; + description = "LDAP value"; + check = x: lib.isString x || (lib.isAttrs x && (x ? path || x ? base64)); + merge = lib.mergeEqualOption; + }; + # We don't coerce to lists of single values, as some values must be unique + in types.either singleLdapValueType (types.listOf singleLdapValueType); + + ldapAttrsType = + let + options = { + attrs = mkOption { + type = types.attrsOf ldapValueType; + default = {}; + description = "Attributes of the parent entry."; + }; + children = mkOption { + # Hide the child attributes, to avoid infinite recursion in e.g. documentation + # Actual Nix evaluation is lazy, so this is not an issue there + type = let + hiddenOptions = lib.mapAttrs (name: attr: attr // { visible = false; }) options; + in types.attrsOf (types.submodule { options = hiddenOptions; }); + default = {}; + description = "Child entries of the current entry, with recursively the same structure."; + example = lib.literalExample '' + { + "cn=schema" = { + # The attribute used in the DN must be defined + attrs = { cn = "schema"; }; + children = { + # This entry's DN is expanded to "cn=foo,cn=schema" + "cn=foo" = { ... }; + }; + # These includes are inserted after "cn=schema", but before "cn=foo,cn=schema" + includes = [ ... ]; + }; + } + ''; + }; + includes = mkOption { + type = types.listOf types.path; + default = []; + description = '' + LDIF files to include after the parent's attributes but before its children. + ''; + }; + }; + in types.submodule { inherit options; }; + + valueToLdif = attr: values: let + listValues = if lib.isList values then values else lib.singleton values; + in map (value: + if lib.isAttrs value then + if lib.hasAttr "path" value + then "${attr}:< file://${value.path}" + else "${attr}:: ${value.base64}" + else "${attr}: ${lib.replaceStrings [ "\n" ] [ "\n " ] value}" + ) listValues; + + attrsToLdif = dn: { attrs, children, includes, ... }: ['' + dn: ${dn} + ${lib.concatStringsSep "\n" (lib.flatten (lib.mapAttrsToList valueToLdif attrs))} + ''] ++ (map (path: "include: file://${path}\n") includes) ++ ( + lib.flatten (lib.mapAttrsToList (name: value: attrsToLdif "${name},${dn}" value) children) + ); +in { + imports = let + deprecationNote = "This option is removed due to the deprecation of `slapd.conf` upstream. Please migrate to `services.openldap.settings`, see the release notes for advice with this process."; + mkDatabaseOption = old: new: + lib.mkChangedOptionModule [ "services" "openldap" old ] [ "services" "openldap" "settings" "children" ] + (config: let + database = lib.getAttrFromPath [ "services" "openldap" "database" ] config; + value = lib.getAttrFromPath [ "services" "openldap" old ] config; + in lib.setAttrByPath ([ "olcDatabase={1}${database}" "attrs" ] ++ new) value); + in [ + (lib.mkRemovedOptionModule [ "services" "openldap" "extraConfig" ] deprecationNote) + (lib.mkRemovedOptionModule [ "services" "openldap" "extraDatabaseConfig" ] deprecationNote) + + (lib.mkChangedOptionModule [ "services" "openldap" "logLevel" ] [ "services" "openldap" "settings" "attrs" "olcLogLevel" ] + (config: lib.splitString " " (lib.getAttrFromPath [ "services" "openldap" "logLevel" ] config))) + (lib.mkChangedOptionModule [ "services" "openldap" "defaultSchemas" ] [ "services" "openldap" "settings" "children" "cn=schema" "includes"] + (config: lib.optionals (lib.getAttrFromPath [ "services" "openldap" "defaultSchemas" ] config) ( + map (schema: "${openldap}/etc/schema/${schema}.ldif") [ "core" "cosine" "inetorgperson" "nis" ]))) + + (lib.mkChangedOptionModule [ "services" "openldap" "database" ] [ "services" "openldap" "settings" "children" ] + (config: let + database = lib.getAttrFromPath [ "services" "openldap" "database" ] config; + in { + "olcDatabase={1}${database}".attrs = { + # objectClass is case-insensitive, so don't need to capitalize ${database} + objectClass = [ "olcdatabaseconfig" "olc${database}config" ]; + olcDatabase = "{1}${database}"; + olcDbDirectory = lib.mkDefault "/var/db/openldap"; + }; + "cn=schema".includes = lib.mkDefault ( + map (schema: "${openldap}/etc/schema/${schema}.ldif") [ "core" "cosine" "inetorgperson" "nis" ] + ); + })) + (mkDatabaseOption "rootpwFile" [ "olcRootPW" "path" ]) + (mkDatabaseOption "suffix" [ "olcSuffix" ]) + (mkDatabaseOption "dataDir" [ "olcDbDirectory" ]) + (mkDatabaseOption "rootdn" [ "olcRootDN" ]) + (mkDatabaseOption "rootpw" [ "olcRootPW" ]) + ]; options = { - services.openldap = { - enable = mkOption { type = types.bool; default = false; @@ -77,224 +155,170 @@ in example = [ "ldaps:///" ]; }; - dataDir = mkOption { - type = types.path; - default = "/var/db/openldap"; - description = "The database directory."; - }; - - defaultSchemas = mkOption { - type = types.bool; - default = true; - description = '' - Include the default schemas core, cosine, inetorgperson and nis. - This setting will be ignored if configDir is set. - ''; - }; - - database = mkOption { - type = types.str; - default = "mdb"; - description = '' - Database type to use for the LDAP. - This setting will be ignored if configDir is set. - ''; - }; - - suffix = mkOption { - type = types.str; - example = "dc=example,dc=org"; - description = '' - Specify the DN suffix of queries that will be passed to this backend - database. - This setting will be ignored if configDir is set. - ''; - }; - - rootdn = mkOption { - type = types.str; - example = "cn=admin,dc=example,dc=org"; - description = '' - Specify the distinguished name that is not subject to access control - or administrative limit restrictions for operations on this database. - This setting will be ignored if configDir is set. - ''; - }; - - rootpw = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - Password for the root user. - This setting will be ignored if configDir is set. - Using this option will store the root password in plain text in the - world-readable nix store. To avoid this the <literal>rootpwFile</literal> can be used. + settings = mkOption { + type = ldapAttrsType; + description = "Configuration for OpenLDAP, in OLC format"; + example = lib.literalExample '' + { + attrs.olcLogLevel = [ "stats" ]; + children = { + "cn=schema".includes = [ + "\${pkgs.openldap}/etc/schema/core.ldif" + "\${pkgs.openldap}/etc/schema/cosine.ldif" + "\${pkgs.openldap}/etc/schema/inetorgperson.ldif" + ]; + "olcDatabase={-1}frontend" = { + attrs = { + objectClass = "olcDatabaseConfig"; + olcDatabase = "{-1}frontend"; + olcAccess = [ "{0}to * by dn.exact=uidNumber=0+gidNumber=0,cn=peercred,cn=external,cn=auth manage stop by * none stop" ]; + }; + }; + "olcDatabase={0}config" = { + attrs = { + objectClass = "olcDatabaseConfig"; + olcDatabase = "{0}config"; + olcAccess = [ "{0}to * by * none break" ]; + }; + }; + "olcDatabase={1}mdb" = { + attrs = { + objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ]; + olcDatabase = "{1}mdb"; + olcDbDirectory = "/var/db/ldap"; + olcDbIndex = [ + "objectClass eq" + "cn pres,eq" + "uid pres,eq" + "sn pres,eq,subany" + ]; + olcSuffix = "dc=example,dc=com"; + olcAccess = [ "{0}to * by * read break" ]; + }; + }; + }; + }; ''; }; - rootpwFile = mkOption { - type = types.nullOr types.str; - default = null; - description = '' - Password file for the root user. - The file should contain the string <literal>rootpw</literal> followed by the password. - e.g.: <literal>rootpw mysecurepassword</literal> - ''; - }; - - logLevel = mkOption { - type = types.str; - default = "0"; - example = "acl trace"; - description = "The log level selector of slapd."; - }; - + # This option overrides settings configDir = mkOption { type = types.nullOr types.path; default = null; - description = "Use this optional config directory instead of using slapd.conf"; + description = '' + Use this config directory instead of generating one from the + <literal>settings</literal> option. Overrides all NixOS settings. If + you use this option,ensure `olcPidFile` is set to `/run/slapd/slapd.conf`. + ''; example = "/var/db/slapd.d"; }; - extraConfig = mkOption { - type = types.lines; - default = ""; - description = " - slapd.conf configuration - "; - example = literalExample '' - ''' - include ${openldap.out}/etc/schema/core.schema - include ${openldap.out}/etc/schema/cosine.schema - include ${openldap.out}/etc/schema/inetorgperson.schema - include ${openldap.out}/etc/schema/nis.schema - - database bdb - suffix dc=example,dc=org - rootdn cn=admin,dc=example,dc=org - # NOTE: change after first start - rootpw secret - directory /var/db/openldap - ''' - ''; - }; - declarativeContents = mkOption { - type = with types; nullOr lines; - default = null; + type = with types; attrsOf lines; + default = {}; description = '' - Declarative contents for the LDAP database, in LDIF format. + Declarative contents for the LDAP database, in LDIF format by suffix. - Note a few facts when using it. First, the database - <emphasis>must</emphasis> be stored in the directory defined by - <code>dataDir</code>. Second, all <code>dataDir</code> will be erased - when starting the LDAP server. Third, modifications to the database - are not prevented, they are just dropped on the next reboot of the - server. Finally, performance-wise the database and indexes are rebuilt - on each server startup, so this will slow down server startup, + All data will be erased when starting the LDAP server. Modifications + to the database are not prevented, they are just dropped on the next + reboot of the server. Performance-wise the database and indexes are + rebuilt on each server startup, so this will slow down server startup, especially with large databases. ''; - example = '' - dn: dc=example,dc=org - objectClass: domain - dc: example - - dn: ou=users,dc=example,dc=org - objectClass = organizationalUnit - ou: users - - # ... + example = lib.literalExample '' + { + "dc=example,dc=org" = ''' + dn= dn: dc=example,dc=org + objectClass: domain + dc: example + + dn: ou=users,dc=example,dc=org + objectClass = organizationalUnit + ou: users + + # ... + '''; + } ''; }; - - extraDatabaseConfig = mkOption { - type = types.lines; - default = ""; - description = '' - slapd.conf configuration after the database option. - This setting will be ignored if configDir is set. - ''; - example = '' - # Indices to maintain for this directory - # unique id so equality match only - index uid eq - # allows general searching on commonname, givenname and email - index cn,gn,mail eq,sub - # allows multiple variants on surname searching - index sn eq,sub - # sub above includes subintial,subany,subfinal - # optimise department searches - index ou eq - # if searches will include objectClass uncomment following - # index objectClass eq - # shows use of default index parameter - index default eq,sub - # indices missing - uses default eq,sub - index telephonenumber - - # other database parameters - # read more in slapd.conf reference section - cachesize 10000 - checkpoint 128 15 - ''; - }; - }; - - }; - - meta = { - maintainers = [ lib.maintainers.mic92 ]; }; - - ###### implementation + meta.maintainers = with lib.maintainters; [ mic92 kwohlfahrt ]; config = mkIf cfg.enable { - assertions = [ - { - assertion = cfg.configDir != null || cfg.rootpwFile != null || cfg.rootpw != null; - message = "services.openldap: Unless configDir is set, either rootpw or rootpwFile must be set"; - } - ]; - + assertions = map (opt: { + assertion = ((getAttr opt cfg) != "_mkMergedOptionModule") -> (cfg.database != "_mkMergedOptionModule"); + message = "Legacy OpenLDAP option `services.openldap.${opt}` requires `services.openldap.database` (use value \"mdb\" if unsure)"; + }) legacyOptions; environment.systemPackages = [ openldap ]; + # Literal attributes must always be set + services.openldap.settings = { + attrs = { + objectClass = "olcGlobal"; + cn = "config"; + olcPidFile = "/run/slapd/slapd.pid"; + }; + children."cn=schema".attrs = { + cn = "schema"; + objectClass = "olcSchemaConfig"; + }; + }; + systemd.services.openldap = { description = "LDAP server"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; - preStart = '' + preStart = let + settingsFile = pkgs.writeText "config.ldif" (lib.concatStringsSep "\n" (attrsToLdif "cn=config" cfg.settings)); + + dbSettings = lib.filterAttrs (name: value: lib.hasPrefix "olcDatabase=" name) cfg.settings.children; + dataDirs = lib.mapAttrs' (name: value: lib.nameValuePair value.attrs.olcSuffix value.attrs.olcDbDirectory) + (lib.filterAttrs (_: value: value.attrs ? olcDbDirectory) dbSettings); + dataFiles = lib.mapAttrs (dn: contents: pkgs.writeText "${dn}.ldif" contents) cfg.declarativeContents; + mkLoadScript = dn: let + dataDir = lib.escapeShellArg (getAttr dn dataDirs); + in '' + rm -rf ${dataDir}/* + ${openldap}/bin/slapadd -F ${lib.escapeShellArg configDir} -b ${dn} -l ${getAttr dn dataFiles} + chown -R "${cfg.user}:${cfg.group}" ${dataDir} + ''; + in '' mkdir -p /run/slapd chown -R "${cfg.user}:${cfg.group}" /run/slapd - ${optionalString (cfg.declarativeContents != null) '' - rm -Rf "${cfg.dataDir}" - ''} - mkdir -p "${cfg.dataDir}" - ${optionalString (cfg.declarativeContents != null) '' - ${openldap.out}/bin/slapadd ${configOpts} -l ${dataFile} - ''} - chown -R "${cfg.user}:${cfg.group}" "${cfg.dataDir}" - ${openldap}/bin/slaptest ${configOpts} + mkdir -p ${lib.escapeShellArg configDir} ${lib.escapeShellArgs (lib.attrValues dataDirs)} + chown "${cfg.user}:${cfg.group}" ${lib.escapeShellArg configDir} ${lib.escapeShellArgs (lib.attrValues dataDirs)} + + ${lib.optionalString (cfg.configDir == null) ('' + rm -Rf ${configDir}/* + ${openldap}/bin/slapadd -F ${configDir} -bcn=config -l ${settingsFile} + '')} + chown -R "${cfg.user}:${cfg.group}" ${lib.escapeShellArg configDir} + + ${lib.concatStrings (map mkLoadScript (lib.attrNames cfg.declarativeContents))} + ${openldap}/bin/slaptest -u -F ${lib.escapeShellArg configDir} ''; - serviceConfig.ExecStart = - "${openldap.out}/libexec/slapd -d '${cfg.logLevel}' " + - "-u '${cfg.user}' -g '${cfg.group}' " + - "-h '${concatStringsSep " " cfg.urlList}' " + - "${configOpts}"; + serviceConfig = { + ExecStart = lib.escapeShellArgs ([ + "${openldap}/libexec/slapd" "-u" cfg.user "-g" cfg.group "-F" configDir + "-h" (lib.concatStringsSep " " cfg.urlList) + ]); + Type = "forking"; + PIDFile = cfg.settings.attrs.olcPidFile; + }; }; - users.users.openldap = - { name = cfg.user; + users.users = lib.optionalAttrs (cfg.user == "openldap") { + openldap = { group = cfg.group; - uid = config.ids.uids.openldap; - }; - - users.groups.openldap = - { name = cfg.group; - gid = config.ids.gids.openldap; + isSystemUser = true; }; + }; + users.groups = lib.optionalAttrs (cfg.group == "openldap") { + openldap = {}; + }; }; } diff --git a/nixos/modules/services/mail/postfix.nix b/nixos/modules/services/mail/postfix.nix index fd4d16cdc37b0..319b3b638444f 100644 --- a/nixos/modules/services/mail/postfix.nix +++ b/nixos/modules/services/mail/postfix.nix @@ -834,12 +834,6 @@ in }; services.postfix.masterConfig = { - smtp_inet = { - name = "smtp"; - type = "inet"; - private = false; - command = "smtpd"; - }; pickup = { private = false; wakeup = 60; @@ -921,6 +915,12 @@ in in concatLists (mapAttrsToList mkKeyVal cfg.submissionOptions); }; } // optionalAttrs cfg.enableSmtp { + smtp_inet = { + name = "smtp"; + type = "inet"; + private = false; + command = "smtpd"; + }; smtp = {}; relay = { command = "smtp"; diff --git a/nixos/modules/services/mail/rspamd.nix b/nixos/modules/services/mail/rspamd.nix index 86a3f52107d51..a6c19a2af73eb 100644 --- a/nixos/modules/services/mail/rspamd.nix +++ b/nixos/modules/services/mail/rspamd.nix @@ -408,7 +408,7 @@ in }; imports = [ (mkRemovedOptionModule [ "services" "rspamd" "socketActivation" ] - "Socket activation never worked correctly and could at this time not be fixed and so was removed") + "Socket activation never worked correctly and could at this time not be fixed and so was removed") (mkRenamedOptionModule [ "services" "rspamd" "bindSocket" ] [ "services" "rspamd" "workers" "normal" "bindSockets" ]) (mkRenamedOptionModule [ "services" "rspamd" "bindUISocket" ] [ "services" "rspamd" "workers" "controller" "bindSockets" ]) (mkRemovedOptionModule [ "services" "rmilter" ] "Use services.rspamd.* instead to set up milter service") diff --git a/nixos/modules/services/misc/gitlab.nix b/nixos/modules/services/misc/gitlab.nix index 122bc3000b416..c4037b49e7e2c 100644 --- a/nixos/modules/services/misc/gitlab.nix +++ b/nixos/modules/services/misc/gitlab.nix @@ -43,9 +43,13 @@ let [gitlab-shell] dir = "${cfg.packages.gitlab-shell}" + + [gitlab] secret_file = "${cfg.statePath}/gitlab_shell_secret" - gitlab_url = "http+unix://${pathUrlQuote gitlabSocket}" - http_settings = { self_signed_cert = false } + url = "http+unix://${pathUrlQuote gitlabSocket}" + + [gitlab.http-settings] + self_signed_cert = false ${concatStringsSep "\n" (attrValues (mapAttrs (k: v: '' [[storage]] @@ -119,6 +123,7 @@ let receive_pack = true; }; workhorse.secret_file = "${cfg.statePath}/.gitlab_workhorse_secret"; + gitlab_kas.secret_file = "${cfg.statePath}/.gitlab_kas_secret"; git.bin_path = "git"; monitoring = { ip_whitelist = [ "127.0.0.0/8" "::1/128" ]; @@ -668,6 +673,7 @@ in { rm "${config.services.postgresql.dataDir}/.reassigning_${cfg.databaseName}" fi $PSQL '${cfg.databaseName}' -tAc "CREATE EXTENSION IF NOT EXISTS pg_trgm" + $PSQL '${cfg.databaseName}' -tAc "CREATE EXTENSION IF NOT EXISTS btree_gist;" ''; serviceConfig = { @@ -750,7 +756,8 @@ in { }; systemd.services.gitaly = { - after = [ "network.target" ]; + after = [ "network.target" "gitlab.service" ]; + requires = [ "gitlab.service" ]; wantedBy = [ "multi-user.target" ]; path = with pkgs; [ openssh @@ -839,7 +846,7 @@ in { }; systemd.services.gitlab = { - after = [ "gitlab-workhorse.service" "gitaly.service" "network.target" "gitlab-postgresql.service" "redis.service" ]; + after = [ "gitlab-workhorse.service" "network.target" "gitlab-postgresql.service" "redis.service" ]; requires = [ "gitlab-sidekiq.service" ]; wantedBy = [ "multi-user.target" ]; environment = gitlabEnv; diff --git a/nixos/modules/services/misc/siproxd.nix b/nixos/modules/services/misc/siproxd.nix index 0e87fc461d3fc..20fe0793b84b6 100644 --- a/nixos/modules/services/misc/siproxd.nix +++ b/nixos/modules/services/misc/siproxd.nix @@ -39,7 +39,7 @@ in default = false; description = '' Whether to enable the Siproxd SIP - proxy/masquerading daemon. + proxy/masquerading daemon. ''; }; @@ -57,29 +57,29 @@ in hostsAllowReg = mkOption { type = types.listOf types.str; - default = [ ]; + default = [ ]; example = [ "192.168.1.0/24" "192.168.2.0/24" ]; - description = '' + description = '' Acess control list for incoming SIP registrations. ''; }; hostsAllowSip = mkOption { type = types.listOf types.str; - default = [ ]; + default = [ ]; example = [ "123.45.0.0/16" "123.46.0.0/16" ]; - description = '' + description = '' Acess control list for incoming SIP traffic. ''; }; hostsDenySip = mkOption { type = types.listOf types.str; - default = [ ]; + default = [ ]; example = [ "10.0.0.0/8" "11.0.0.0/8" ]; - description = '' + description = '' Acess control list for denying incoming - SIP registrations and traffic. + SIP registrations and traffic. ''; }; @@ -87,7 +87,7 @@ in type = types.int; default = 5060; description = '' - Port to listen for incoming SIP messages. + Port to listen for incoming SIP messages. ''; }; diff --git a/nixos/modules/services/misc/svnserve.nix b/nixos/modules/services/misc/svnserve.nix index 3335ed09d40e0..f70e3ca7fef0a 100644 --- a/nixos/modules/services/misc/svnserve.nix +++ b/nixos/modules/services/misc/svnserve.nix @@ -25,7 +25,7 @@ in svnBaseDir = mkOption { default = "/repos"; - description = "Base directory from which Subversion repositories are accessed."; + description = "Base directory from which Subversion repositories are accessed."; }; }; diff --git a/nixos/modules/services/network-filesystems/netatalk.nix b/nixos/modules/services/network-filesystems/netatalk.nix index 7674c8f7fa8d1..ca9d32311f5f3 100644 --- a/nixos/modules/services/network-filesystems/netatalk.nix +++ b/nixos/modules/services/network-filesystems/netatalk.nix @@ -108,10 +108,10 @@ in extmap = mkOption { type = types.lines; - default = ""; - description = '' - File name extension mappings. - See <literal>man extmap.conf</literal> for more information. + default = ""; + description = '' + File name extension mappings. + See <literal>man extmap.conf</literal> for more information. ''; }; @@ -132,10 +132,10 @@ in Type = "forking"; GuessMainPID = "no"; PIDFile = "/run/lock/netatalk"; - ExecStartPre = "${pkgs.coreutils}/bin/mkdir -m 0755 -p /var/lib/netatalk/CNID"; + ExecStartPre = "${pkgs.coreutils}/bin/mkdir -m 0755 -p /var/lib/netatalk/CNID"; ExecStart = "${pkgs.netatalk}/sbin/netatalk -F ${afpConfFile}"; ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; - ExecStop = "${pkgs.coreutils}/bin/kill -TERM $MAINPID"; + ExecStop = "${pkgs.coreutils}/bin/kill -TERM $MAINPID"; Restart = "always"; RestartSec = 1; }; diff --git a/nixos/modules/services/network-filesystems/samba-wsdd.nix b/nixos/modules/services/network-filesystems/samba-wsdd.nix new file mode 100644 index 0000000000000..004d07064afd4 --- /dev/null +++ b/nixos/modules/services/network-filesystems/samba-wsdd.nix @@ -0,0 +1,124 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.samba-wsdd; + +in { + options = { + services.samba-wsdd = { + enable = mkEnableOption '' + Enable Web Services Dynamic Discovery host daemon. This enables (Samba) hosts, like your local NAS device, + to be found by Web Service Discovery Clients like Windows. + <note> + <para>If you use the firewall consider adding the following:</para> + <programlisting> + networking.firewall.allowedTCPPorts = [ 5357 ]; + networking.firewall.allowedUDPPorts = [ 3702 ]; + </programlisting> + </note> + ''; + interface = mkOption { + type = types.nullOr types.str; + default = null; + example = "eth0"; + description = "Interface or address to use."; + }; + hoplimit = mkOption { + type = types.nullOr types.int; + default = null; + example = 2; + description = "Hop limit for multicast packets (default = 1)."; + }; + workgroup = mkOption { + type = types.nullOr types.str; + default = null; + example = "HOME"; + description = "Set workgroup name (default WORKGROUP)."; + }; + hostname = mkOption { + type = types.nullOr types.str; + default = null; + example = "FILESERVER"; + description = "Override (NetBIOS) hostname to be used (default hostname)."; + }; + domain = mkOption { + type = types.nullOr types.str; + default = null; + description = "Set domain name (disables workgroup)."; + }; + discovery = mkOption { + type = types.bool; + default = false; + description = "Enable discovery operation mode."; + }; + listen = mkOption { + type = types.str; + default = "/run/wsdd/wsdd.sock"; + description = "Listen on path or localhost port in discovery mode."; + }; + extraOptions = mkOption { + type = types.listOf types.str; + default = [ "--shortlog" ]; + example = [ "--verbose" "--no-http" "--ipv4only" "--no-host" ]; + description = "Additional wsdd options."; + }; + }; + }; + + config = mkIf cfg.enable { + + environment.systemPackages = [ pkgs.wsdd ]; + + systemd.services.samba-wsdd = { + description = "Web Services Dynamic Discovery host daemon"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + DynamicUser = true; + Type = "simple"; + ExecStart = '' + ${pkgs.wsdd}/bin/wsdd ${optionalString (cfg.interface != null) "--interface '${cfg.interface}'"} \ + ${optionalString (cfg.hoplimit != null) "--hoplimit '${toString cfg.hoplimit}'"} \ + ${optionalString (cfg.workgroup != null) "--workgroup '${cfg.workgroup}'"} \ + ${optionalString (cfg.hostname != null) "--hostname '${cfg.hostname}'"} \ + ${optionalString (cfg.domain != null) "--domain '${cfg.domain}'"} \ + ${optionalString cfg.discovery "--discovery --listen '${cfg.listen}'"} \ + ${escapeShellArgs cfg.extraOptions} + ''; + # Runtime directory and mode + RuntimeDirectory = "wsdd"; + RuntimeDirectoryMode = "0750"; + # Access write directories + UMask = "0027"; + # Capabilities + CapabilityBoundingSet = ""; + # Security + NoNewPrivileges = true; + # Sandboxing + ProtectSystem = "strict"; + ProtectHome = true; + PrivateTmp = true; + PrivateDevices = true; + PrivateUsers = false; + ProtectHostname = true; + ProtectClock = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectKernelLogs = true; + ProtectControlGroups = true; + RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ]; + RestrictNamespaces = true; + LockPersonality = true; + MemoryDenyWriteExecute = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + PrivateMounts = true; + # System Call Filtering + SystemCallArchitectures = "native"; + SystemCallFilter = "~@clock @cpu-emulation @debug @module @mount @obsolete @privileged @raw-io @reboot @resources @swap"; + }; + }; + }; +} diff --git a/nixos/modules/services/networking/morty.nix b/nixos/modules/services/networking/morty.nix index e3a6444c11635..e110a5c86101f 100644 --- a/nixos/modules/services/networking/morty.nix +++ b/nixos/modules/services/networking/morty.nix @@ -29,9 +29,11 @@ in key = mkOption { type = types.str; default = ""; - description = "HMAC url validation key (hexadecimal encoded). - Leave blank to disable. Without validation key, anyone can - submit proxy requests. Leave blank to disable."; + description = '' + HMAC url validation key (hexadecimal encoded). + Leave blank to disable. Without validation key, anyone can + submit proxy requests. Leave blank to disable. + ''; defaultText = "No HMAC url validation. Generate with echo -n somevalue | openssl dgst -sha1 -hmac somekey"; }; @@ -85,10 +87,10 @@ in serviceConfig = { User = "morty"; ExecStart = ''${cfg.package}/bin/morty \ - -listen ${cfg.listenAddress}:${toString cfg.port} \ - ${optionalString cfg.ipv6 "-ipv6"} \ - ${optionalString (cfg.key != "") "-key " + cfg.key} \ - ''; + -listen ${cfg.listenAddress}:${toString cfg.port} \ + ${optionalString cfg.ipv6 "-ipv6"} \ + ${optionalString (cfg.key != "") "-key " + cfg.key} \ + ''; }; }; environment.systemPackages = [ cfg.package ]; diff --git a/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix b/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix index 808cb863a9cf8..1d1e0bd1ca19a 100644 --- a/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix +++ b/nixos/modules/services/networking/strongswan-swanctl/swanctl-params.nix @@ -1173,20 +1173,20 @@ in { ppk = mkPrefixedAttrsOfParams { secret = mkOptionalStrParam '' - Value of the PPK. It may either be an ASCII string, a hex encoded string - if it has a <literal>0x</literal> prefix or a Base64 encoded string if - it has a <literal>0s</literal> prefix in its value. Should have at least - 256 bits of entropy for 128-bit security. + Value of the PPK. It may either be an ASCII string, a hex encoded string + if it has a <literal>0x</literal> prefix or a Base64 encoded string if + it has a <literal>0s</literal> prefix in its value. Should have at least + 256 bits of entropy for 128-bit security. ''; id = mkPrefixedAttrsOfParam (mkOptionalStrParam "") '' - PPK identity the PPK belongs to. Multiple unique identities may be - specified, each having an <literal>id</literal> prefix, if a secret is - shared between multiple peers. + PPK identity the PPK belongs to. Multiple unique identities may be + specified, each having an <literal>id</literal> prefix, if a secret is + shared between multiple peers. ''; } '' - Postquantum Preshared Key (PPK) section for a specific secret. Each PPK is - defined in a unique section having the <literal>ppk</literal> prefix. + Postquantum Preshared Key (PPK) section for a specific secret. Each PPK is + defined in a unique section having the <literal>ppk</literal> prefix. ''; private = mkPrefixedAttrsOfParams { diff --git a/nixos/modules/services/networking/wasabibackend.nix b/nixos/modules/services/networking/wasabibackend.nix index 6eacffe709b0d..8482823e197f7 100644 --- a/nixos/modules/services/networking/wasabibackend.nix +++ b/nixos/modules/services/networking/wasabibackend.nix @@ -21,7 +21,7 @@ let RegTestBitcoinCoreRpcEndPoint = "${cfg.rpc.ip}:${toString cfg.rpc.port}"; }; - configFile = pkgs.writeText "wasabibackend.conf" (builtins.toJSON confOptions); + configFile = pkgs.writeText "wasabibackend.conf" (builtins.toJSON confOptions); in { diff --git a/nixos/modules/services/security/oauth2_proxy.nix b/nixos/modules/services/security/oauth2_proxy.nix index 2f9e94bd77bac..486f3ab05386d 100644 --- a/nixos/modules/services/security/oauth2_proxy.nix +++ b/nixos/modules/services/security/oauth2_proxy.nix @@ -448,7 +448,7 @@ in default = false; description = '' In case when running behind a reverse proxy, controls whether headers - like <literal>X-Real-Ip</literal> are accepted. Usage behind a reverse + like <literal>X-Real-Ip</literal> are accepted. Usage behind a reverse proxy will require this flag to be set to avoid logging the reverse proxy IP address. ''; @@ -524,7 +524,7 @@ in type = types.nullOr types.str; default = null; description = '' - Profile access endpoint. + Profile access endpoint. ''; }; diff --git a/nixos/modules/services/x11/window-managers/evilwm.nix b/nixos/modules/services/x11/window-managers/evilwm.nix index 6e19e3572c79d..6f1db2110f879 100644 --- a/nixos/modules/services/x11/window-managers/evilwm.nix +++ b/nixos/modules/services/x11/window-managers/evilwm.nix @@ -16,8 +16,8 @@ in services.xserver.windowManager.session = singleton { name = "evilwm"; start = '' - ${pkgs.evilwm}/bin/evilwm & - waitPID=$! + ${pkgs.evilwm}/bin/evilwm & + waitPID=$! ''; }; environment.systemPackages = [ pkgs.evilwm ]; diff --git a/nixos/modules/virtualisation/ec2-metadata-fetcher.nix b/nixos/modules/virtualisation/ec2-metadata-fetcher.nix index 812e93ec4aabb..dca5c2abd4e0c 100644 --- a/nixos/modules/virtualisation/ec2-metadata-fetcher.nix +++ b/nixos/modules/virtualisation/ec2-metadata-fetcher.nix @@ -8,9 +8,14 @@ # Make sure that every package you depend on here is already listed as # a channel blocker for both the full-sized and small channels. # Otherwise, we risk breaking user deploys in released channels. +# +# Also note: OpenStack's metadata service for its instances aims to be +# compatible with the EC2 IMDS. Where possible, try to keep the set of +# fetched metadata in sync with ./openstack-metadata-fetcher.nix . '' metaDir=${targetRoot}etc/ec2-metadata mkdir -m 0755 -p "$metaDir" + rm -f "$metaDir/*" get_imds_token() { # retry-delay of 1 selected to give the system a second to get going, @@ -61,19 +66,12 @@ echo "getting EC2 instance metadata..." - if ! [ -e "$metaDir/ami-manifest-path" ]; then - wget ${wgetExtraOptions} --header "X-aws-ec2-metadata-token: $IMDS_TOKEN" -O "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path - fi - - if ! [ -e "$metaDir/user-data" ]; then - wget ${wgetExtraOptions} --header "X-aws-ec2-metadata-token: $IMDS_TOKEN" -O "$metaDir/user-data" http://169.254.169.254/1.0/user-data && chmod 600 "$metaDir/user-data" - fi - - if ! [ -e "$metaDir/hostname" ]; then - wget ${wgetExtraOptions} --header "X-aws-ec2-metadata-token: $IMDS_TOKEN" -O "$metaDir/hostname" http://169.254.169.254/1.0/meta-data/hostname - fi + wget_imds() { + wget ${wgetExtraOptions} --header "X-aws-ec2-metadata-token: $IMDS_TOKEN" "$@"; + } - if ! [ -e "$metaDir/public-keys-0-openssh-key" ]; then - wget ${wgetExtraOptions} --header "X-aws-ec2-metadata-token: $IMDS_TOKEN" -O "$metaDir/public-keys-0-openssh-key" http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key - fi + wget_imds -O "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path + wget_imds -O "$metaDir/user-data" http://169.254.169.254/1.0/user-data && chmod 600 "$metaDir/user-data" + wget_imds -O "$metaDir/hostname" http://169.254.169.254/1.0/meta-data/hostname + wget_imds -O "$metaDir/public-keys-0-openssh-key" http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key '' diff --git a/nixos/modules/virtualisation/nixos-containers.nix b/nixos/modules/virtualisation/nixos-containers.nix index 8fbb4efd20196..26398afb3cf51 100644 --- a/nixos/modules/virtualisation/nixos-containers.nix +++ b/nixos/modules/virtualisation/nixos-containers.nix @@ -614,17 +614,17 @@ in ''; }; - timeoutStartSec = mkOption { - type = types.str; - default = "1min"; - description = '' - Time for the container to start. In case of a timeout, - the container processes get killed. - See <citerefentry><refentrytitle>systemd.time</refentrytitle> - <manvolnum>7</manvolnum></citerefentry> - for more information about the format. - ''; - }; + timeoutStartSec = mkOption { + type = types.str; + default = "1min"; + description = '' + Time for the container to start. In case of a timeout, + the container processes get killed. + See <citerefentry><refentrytitle>systemd.time</refentrytitle> + <manvolnum>7</manvolnum></citerefentry> + for more information about the format. + ''; + }; bindMounts = mkOption { type = with types; attrsOf (submodule bindMountOpts); diff --git a/nixos/modules/virtualisation/openstack-metadata-fetcher.nix b/nixos/modules/virtualisation/openstack-metadata-fetcher.nix index b531787c31a29..8c191397cf9a5 100644 --- a/nixos/modules/virtualisation/openstack-metadata-fetcher.nix +++ b/nixos/modules/virtualisation/openstack-metadata-fetcher.nix @@ -1,23 +1,21 @@ { targetRoot, wgetExtraOptions }: + +# OpenStack's metadata service aims to be EC2-compatible. Where +# possible, try to keep the set of fetched metadata in sync with +# ./ec2-metadata-fetcher.nix . '' metaDir=${targetRoot}etc/ec2-metadata mkdir -m 0755 -p "$metaDir" + rm -f "$metaDir/*" - echo "getting EC2 instance metadata..." - - if ! [ -e "$metaDir/ami-manifest-path" ]; then - wget ${wgetExtraOptions} -O "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path - fi - - if ! [ -e "$metaDir/user-data" ]; then - wget ${wgetExtraOptions} -O "$metaDir/user-data" http://169.254.169.254/1.0/user-data && chmod 600 "$metaDir/user-data" - fi + echo "getting instance metadata..." - if ! [ -e "$metaDir/hostname" ]; then - wget ${wgetExtraOptions} -O "$metaDir/hostname" http://169.254.169.254/1.0/meta-data/hostname - fi + wget_imds() { + wget ${wgetExtraOptions} "$@" + } - if ! [ -e "$metaDir/public-keys-0-openssh-key" ]; then - wget ${wgetExtraOptions} -O "$metaDir/public-keys-0-openssh-key" http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key - fi + wget_imds -O "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path + wget_imds -O "$metaDir/user-data" http://169.254.169.254/1.0/user-data && chmod 600 "$metaDir/user-data" + wget_imds -O "$metaDir/hostname" http://169.254.169.254/1.0/meta-data/hostname + wget_imds -O "$metaDir/public-keys-0-openssh-key" http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key '' diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 3c10d62151869..899509696e3c4 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -315,6 +315,7 @@ in runInMachine = handleTest ./run-in-machine.nix {}; rxe = handleTest ./rxe.nix {}; samba = handleTest ./samba.nix {}; + samba-wsdd = handleTest ./samba-wsdd.nix {}; sanoid = handleTest ./sanoid.nix {}; sbt = handleTest ./sbt.nix {}; sbt-extras = handleTest ./sbt-extras.nix {}; diff --git a/nixos/tests/fcitx/default.nix b/nixos/tests/fcitx/default.nix index d28a5801f97f9..cbeb95d33b0cb 100644 --- a/nixos/tests/fcitx/default.nix +++ b/nixos/tests/fcitx/default.nix @@ -1,15 +1,15 @@ -import ../make-test-python.nix ( +import ../make-test-python.nix ( { pkgs, ... - }: + }: # copy_from_host works only for store paths rec { name = "fcitx"; - machine = - { - pkgs, - ... - }: + machine = + { + pkgs, + ... + }: { virtualisation.memorySize = 1024; @@ -19,11 +19,11 @@ import ../make-test-python.nix ( environment.systemPackages = [ # To avoid clashing with xfce4-terminal - pkgs.alacritty + pkgs.alacritty ]; - services.xserver = + services.xserver = { enable = true; @@ -37,7 +37,7 @@ import ../make-test-python.nix ( desktopManager.xfce.enable = true; }; - + i18n = { inputMethod = { enabled = "fcitx"; @@ -50,14 +50,14 @@ import ../make-test-python.nix ( } ; - testScript = { nodes, ... }: - let + testScript = { nodes, ... }: + let user = nodes.machine.config.users.users.alice; userName = user.name; userHome = user.home; xauth = "${userHome}/.Xauthority"; fcitx_confdir = "${userHome}/.config/fcitx"; - in + in '' # We need config files before login session # So copy first thing @@ -92,7 +92,7 @@ import ../make-test-python.nix ( machine.send_key("ctrl-alt-shift-u") machine.sleep(5) machine.sleep(1) - + ### Search for smiling face machine.send_chars("smil") machine.sleep(1) diff --git a/nixos/tests/gitlab.nix b/nixos/tests/gitlab.nix index 7e4e8bcef92dc..1214cddd09370 100644 --- a/nixos/tests/gitlab.nix +++ b/nixos/tests/gitlab.nix @@ -33,9 +33,9 @@ import ./make-test-python.nix ({ pkgs, lib, ...} : with lib; { initialRootPasswordFile = pkgs.writeText "rootPassword" initialRootPassword; smtp.enable = true; secrets = { - secretFile = pkgs.writeText "secret" "Aig5zaic"; - otpFile = pkgs.writeText "otpsecret" "Riew9mue"; - dbFile = pkgs.writeText "dbsecret" "we2quaeZ"; + secretFile = pkgs.writeText "secret" "r8X9keSKynU7p4aKlh4GO1Bo77g5a7vj"; + otpFile = pkgs.writeText "otpsecret" "Zu5hGx3YvQx40DvI8WoZJQpX2paSDOlG"; + dbFile = pkgs.writeText "dbsecret" "lsGltKWTejOf6JxCVa7nLDenzkO9wPLR"; jwsFile = pkgs.runCommand "oidcKeyBase" {} "${pkgs.openssl}/bin/openssl genrsa 2048 > $out"; }; }; diff --git a/nixos/tests/morty.nix b/nixos/tests/morty.nix index ff30b7c072bb1..924dce2717e3b 100644 --- a/nixos/tests/morty.nix +++ b/nixos/tests/morty.nix @@ -12,9 +12,9 @@ import ./make-test-python.nix ({ pkgs, ... }: { ... }: { services.morty = { enable = true; - key = "78a9cd0cfee20c672f78427efb2a2a96036027f0"; - port = 3001; - }; + key = "78a9cd0cfee20c672f78427efb2a2a96036027f0"; + port = 3001; + }; }; }; diff --git a/nixos/tests/openldap.nix b/nixos/tests/openldap.nix index f8321a2c522dc..392fae243467b 100644 --- a/nixos/tests/openldap.nix +++ b/nixos/tests/openldap.nix @@ -1,33 +1,125 @@ -import ./make-test-python.nix { - name = "openldap"; - - machine = { pkgs, ... }: { - services.openldap = { - enable = true; - suffix = "dc=example"; - rootdn = "cn=root,dc=example"; - rootpw = "notapassword"; - database = "bdb"; - extraDatabaseConfig = '' - directory /var/db/openldap - ''; - declarativeContents = '' - dn: dc=example - objectClass: domain - dc: example - - dn: ou=users,dc=example - objectClass: organizationalUnit - ou: users - ''; - }; - }; +{ pkgs, system ? builtins.currentSystem, ... }: let + dbContents = '' + dn: dc=example + objectClass: domain + dc: example + dn: ou=users,dc=example + objectClass: organizationalUnit + ou: users + ''; testScript = '' machine.wait_for_unit("openldap.service") machine.succeed( - "systemctl status openldap.service", 'ldapsearch -LLL -D "cn=root,dc=example" -w notapassword -b "dc=example"', ) ''; +in { + # New-style configuration + current = import ./make-test-python.nix { + inherit testScript; + name = "openldap"; + + machine = { pkgs, ... }: { + environment.etc."openldap/root_password".text = "notapassword"; + services.openldap = { + enable = true; + settings = { + children = { + "cn=schema".includes = [ + "${pkgs.openldap}/etc/schema/core.ldif" + "${pkgs.openldap}/etc/schema/cosine.ldif" + "${pkgs.openldap}/etc/schema/inetorgperson.ldif" + "${pkgs.openldap}/etc/schema/nis.ldif" + ]; + "olcDatabase={1}mdb" = { + # This tests string, base64 and path values, as well as lists of string values + attrs = { + objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ]; + olcDatabase = "{1}mdb"; + olcDbDirectory = "/var/db/openldap"; + olcSuffix = "dc=example"; + olcRootDN = { + # cn=root,dc=example + base64 = "Y249cm9vdCxkYz1leGFtcGxl"; + }; + olcRootPW = { + path = "/etc/openldap/root_password"; + }; + }; + }; + }; + }; + declarativeContents."dc=example" = dbContents; + }; + }; + }; + + # Old-style configuration + oldOptions = import ./make-test-python.nix { + inherit testScript; + name = "openldap"; + + machine = { pkgs, ... }: { + services.openldap = { + enable = true; + logLevel = "stats acl"; + defaultSchemas = true; + database = "mdb"; + suffix = "dc=example"; + rootdn = "cn=root,dc=example"; + rootpw = "notapassword"; + declarativeContents."dc=example" = dbContents; + }; + }; + }; + + # Manually managed configDir, for example if dynamic config is essential + manualConfigDir = import ./make-test-python.nix { + name = "openldap"; + + machine = { pkgs, ... }: { + services.openldap = { + enable = true; + configDir = "/var/db/slapd.d"; + }; + }; + + testScript = let + contents = pkgs.writeText "data.ldif" dbContents; + config = pkgs.writeText "config.ldif" '' + dn: cn=config + cn: config + objectClass: olcGlobal + olcLogLevel: stats + olcPidFile: /run/slapd/slapd.pid + + dn: cn=schema,cn=config + cn: schema + objectClass: olcSchemaConfig + + include: file://${pkgs.openldap}/etc/schema/core.ldif + include: file://${pkgs.openldap}/etc/schema/cosine.ldif + include: file://${pkgs.openldap}/etc/schema/inetorgperson.ldif + + dn: olcDatabase={1}mdb,cn=config + objectClass: olcDatabaseConfig + objectClass: olcMdbConfig + olcDatabase: {1}mdb + olcDbDirectory: /var/db/openldap + olcDbIndex: objectClass eq + olcSuffix: dc=example + olcRootDN: cn=root,dc=example + olcRootPW: notapassword + ''; + in '' + machine.succeed( + "mkdir -p /var/db/slapd.d /var/db/openldap", + "slapadd -F /var/db/slapd.d -n0 -l ${config}", + "slapadd -F /var/db/slapd.d -n1 -l ${contents}", + "chown -R openldap:openldap /var/db/slapd.d /var/db/openldap", + "systemctl restart openldap", + ) + '' + testScript; + }; } diff --git a/nixos/tests/quorum.nix b/nixos/tests/quorum.nix index 846d2a9301889..d5906806a0a2b 100644 --- a/nixos/tests/quorum.nix +++ b/nixos/tests/quorum.nix @@ -55,7 +55,7 @@ import ./make-test-python.nix ({ pkgs, ... }: { parentHash = "0x0000000000000000000000000000000000000000000000000000000000000000"; timestamp = "0x5cffc201"; - }; + }; }; }; }; diff --git a/nixos/tests/rspamd.nix b/nixos/tests/rspamd.nix index bf3f0de620445..6eaa02ef42917 100644 --- a/nixos/tests/rspamd.nix +++ b/nixos/tests/rspamd.nix @@ -209,7 +209,7 @@ in return false end, score = 5.0, - description = 'Allow no cows', + description = 'Allow no cows', group = "cows", } rspamd_logger.infox(rspamd_config, 'Work dammit!!!') diff --git a/nixos/tests/samba-wsdd.nix b/nixos/tests/samba-wsdd.nix new file mode 100644 index 0000000000000..1edef6c0056de --- /dev/null +++ b/nixos/tests/samba-wsdd.nix @@ -0,0 +1,44 @@ +import ./make-test-python.nix ({ pkgs, ... }: + +{ + name = "samba-wsdd"; + meta.maintainers = with pkgs.stdenv.lib.maintainers; [ izorkin ]; + + nodes = { + client_wsdd = { pkgs, ... }: { + services.samba-wsdd = { + enable = true; + interface = "eth1"; + workgroup = "WORKGROUP"; + hostname = "CLIENT-WSDD"; + discovery = true; + extraOptions = [ "--no-host" ]; + }; + networking.firewall.allowedTCPPorts = [ 5357 ]; + networking.firewall.allowedUDPPorts = [ 3702 ]; + }; + + server_wsdd = { ... }: { + services.samba-wsdd = { + enable = true; + interface = "eth1"; + workgroup = "WORKGROUP"; + hostname = "SERVER-WSDD"; + }; + networking.firewall.allowedTCPPorts = [ 5357 ]; + networking.firewall.allowedUDPPorts = [ 3702 ]; + }; + }; + + testScript = '' + client_wsdd.start() + client_wsdd.wait_for_unit("samba-wsdd") + + server_wsdd.start() + server_wsdd.wait_for_unit("samba-wsdd") + + client_wsdd.wait_until_succeeds( + "echo list | ${pkgs.libressl.nc}/bin/nc -U /run/wsdd/wsdd.sock | grep -i SERVER-WSDD" + ) + ''; +}) diff --git a/nixos/tests/sssd-ldap.nix b/nixos/tests/sssd-ldap.nix index b68403a0102a8..4831eaa4ba20b 100644 --- a/nixos/tests/sssd-ldap.nix +++ b/nixos/tests/sssd-ldap.nix @@ -1,4 +1,4 @@ -import ./make-test-python.nix ({ pkgs, ... }: +({ pkgs, ... }: let dbDomain = "example.org"; dbSuffix = "dc=example,dc=org"; @@ -7,8 +7,7 @@ import ./make-test-python.nix ({ pkgs, ... }: ldapRootPassword = "foobar"; testUser = "alice"; - in - { + in import ./make-test-python.nix { name = "sssd-ldap"; meta = with pkgs.stdenv.lib.maintainers; { @@ -18,34 +17,53 @@ import ./make-test-python.nix ({ pkgs, ... }: machine = { pkgs, ... }: { services.openldap = { enable = true; - rootdn = "cn=${ldapRootUser},${dbSuffix}"; - rootpw = ldapRootPassword; - suffix = dbSuffix; - declarativeContents = '' - dn: ${dbSuffix} - objectClass: top - objectClass: dcObject - objectClass: organization - o: ${dbDomain} + settings = { + children = { + "cn=schema".includes = [ + "${pkgs.openldap}/etc/schema/core.ldif" + "${pkgs.openldap}/etc/schema/cosine.ldif" + "${pkgs.openldap}/etc/schema/inetorgperson.ldif" + "${pkgs.openldap}/etc/schema/nis.ldif" + ]; + "olcDatabase={1}mdb" = { + attrs = { + objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ]; + olcDatabase = "{1}mdb"; + olcDbDirectory = "/var/db/openldap"; + olcSuffix = dbSuffix; + olcRootDN = "cn=${ldapRootUser},${dbSuffix}"; + olcRootPW = ldapRootPassword; + }; + }; + }; + }; + declarativeContents = { + ${dbSuffix} = '' + dn: ${dbSuffix} + objectClass: top + objectClass: dcObject + objectClass: organization + o: ${dbDomain} - dn: ou=posix,${dbSuffix} - objectClass: top - objectClass: organizationalUnit + dn: ou=posix,${dbSuffix} + objectClass: top + objectClass: organizationalUnit - dn: ou=accounts,ou=posix,${dbSuffix} - objectClass: top - objectClass: organizationalUnit + dn: ou=accounts,ou=posix,${dbSuffix} + objectClass: top + objectClass: organizationalUnit - dn: uid=${testUser},ou=accounts,ou=posix,${dbSuffix} - objectClass: person - objectClass: posixAccount - # userPassword: somePasswordHash - homeDirectory: /home/${testUser} - uidNumber: 1234 - gidNumber: 1234 - cn: "" - sn: "" - ''; + dn: uid=${testUser},ou=accounts,ou=posix,${dbSuffix} + objectClass: person + objectClass: posixAccount + # userPassword: somePasswordHash + homeDirectory: /home/${testUser} + uidNumber: 1234 + gidNumber: 1234 + cn: "" + sn: "" + ''; + }; }; services.sssd = { |