diff options
Diffstat (limited to 'nixos/modules/services')
-rw-r--r-- | nixos/modules/services/cluster/kubernetes/dashboard.nix | 3 | ||||
-rw-r--r-- | nixos/modules/services/cluster/kubernetes/default.nix | 1 | ||||
-rw-r--r-- | nixos/modules/services/databases/aerospike.nix | 155 | ||||
-rw-r--r-- | nixos/modules/services/databases/neo4j.nix | 677 | ||||
-rw-r--r-- | nixos/modules/services/desktops/bamf.nix | 23 | ||||
-rw-r--r-- | nixos/modules/services/hardware/pcscd.nix | 4 | ||||
-rw-r--r-- | nixos/modules/services/misc/clipmenu.nix | 31 | ||||
-rw-r--r-- | nixos/modules/services/networking/ssh/sshd.nix | 16 | ||||
-rw-r--r-- | nixos/modules/services/printing/cupsd.nix | 17 | ||||
-rw-r--r-- | nixos/modules/services/web-servers/apache-httpd/default.nix | 2 | ||||
-rw-r--r-- | nixos/modules/services/x11/desktop-managers/plasma5.nix | 5 | ||||
-rw-r--r-- | nixos/modules/services/x11/desktop-managers/xfce.nix | 8 | ||||
-rw-r--r-- | nixos/modules/services/x11/display-managers/sddm.nix | 26 |
13 files changed, 856 insertions, 112 deletions
diff --git a/nixos/modules/services/cluster/kubernetes/dashboard.nix b/nixos/modules/services/cluster/kubernetes/dashboard.nix index 6d9faada4401..cbd6e8f7bf73 100644 --- a/nixos/modules/services/cluster/kubernetes/dashboard.nix +++ b/nixos/modules/services/cluster/kubernetes/dashboard.nix @@ -10,8 +10,8 @@ in { rbac = mkOption { description = "Role-based access control (RBAC) options"; + default = {}; type = types.submodule { - options = { enable = mkOption { description = "Whether to enable role based access control is enabled for kubernetes dashboard"; @@ -24,7 +24,6 @@ in { type = types.bool; default = false; }; - }; }; }; diff --git a/nixos/modules/services/cluster/kubernetes/default.nix b/nixos/modules/services/cluster/kubernetes/default.nix index 2707c176efd8..e5aba210b019 100644 --- a/nixos/modules/services/cluster/kubernetes/default.nix +++ b/nixos/modules/services/cluster/kubernetes/default.nix @@ -1116,6 +1116,7 @@ in { wantedBy = [ "kubernetes.target" ]; after = [ "kube-apiserver.service" ]; environment.ADDON_PATH = "/etc/kubernetes/addons/"; + path = [ pkgs.gawk ]; serviceConfig = { Slice = "kubernetes.slice"; ExecStart = "${cfg.package}/bin/kube-addons"; diff --git a/nixos/modules/services/databases/aerospike.nix b/nixos/modules/services/databases/aerospike.nix new file mode 100644 index 000000000000..5f33164998be --- /dev/null +++ b/nixos/modules/services/databases/aerospike.nix @@ -0,0 +1,155 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.aerospike; + + aerospikeConf = pkgs.writeText "aerospike.conf" '' + # This stanza must come first. + service { + user aerospike + group aerospike + paxos-single-replica-limit 1 # Number of nodes where the replica count is automatically reduced to 1. + proto-fd-max 15000 + work-directory ${cfg.workDir} + } + logging { + console { + context any info + } + } + mod-lua { + system-path ${cfg.package}/share/udf/lua + user-path ${cfg.workDir}/udf/lua + } + network { + ${cfg.networkConfig} + } + ${cfg.extraConfig} + ''; + +in + +{ + + ###### interface + + options = { + + services.aerospike = { + enable = mkEnableOption "Aerospike server"; + + package = mkOption { + default = pkgs.aerospike; + type = types.package; + description = "Which Aerospike derivation to use"; + }; + + workDir = mkOption { + type = types.str; + default = "/var/lib/aerospike"; + description = "Location where Aerospike stores its files"; + }; + + networkConfig = mkOption { + type = types.lines; + default = '' + service { + address any + port 3000 + } + + heartbeat { + address any + mode mesh + port 3002 + interval 150 + timeout 10 + } + + fabric { + address any + port 3001 + } + + info { + address any + port 3003 + } + ''; + description = "network section of configuration file"; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + namespace test { + replication-factor 2 + memory-size 4G + default-ttl 30d + storage-engine memory + } + ''; + description = "Extra configuration"; + }; + }; + + }; + + + ###### implementation + + config = mkIf config.services.aerospike.enable { + + users.users.aerospike = { + name = "aerospike"; + group = "aerospike"; + uid = config.ids.uids.aerospike; + description = "Aerospike server user"; + }; + users.groups.aerospike.gid = config.ids.gids.aerospike; + + systemd.services.aerospike = rec { + description = "Aerospike server"; + + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + serviceConfig = { + ExecStart = "${cfg.package}/bin/asd --fgdaemon --config-file ${aerospikeConf}"; + User = "aerospike"; + Group = "aerospike"; + LimitNOFILE = 100000; + PermissionsStartOnly = true; + }; + + preStart = '' + if [ $(echo "$(${pkgs.procps}/bin/sysctl -n kernel.shmall) < 4294967296" | ${pkgs.bc}/bin/bc) == "1" ]; then + echo "kernel.shmall too low, setting to 4G pages" + ${pkgs.procps}/bin/sysctl -w kernel.shmall=4294967296 + fi + if [ $(echo "$(${pkgs.procps}/bin/sysctl -n kernel.shmmax) < 1073741824" | ${pkgs.bc}/bin/bc) == "1" ]; then + echo "kernel.shmmax too low, setting to 1GB" + ${pkgs.procps}/bin/sysctl -w kernel.shmmax=1073741824 + fi + if [ $(echo "$(cat /proc/sys/net/core/rmem_max) < 15728640" | ${pkgs.bc}/bin/bc) == "1" ]; then + echo "increasing socket buffer limit (/proc/sys/net/core/rmem_max): $(cat /proc/sys/net/core/rmem_max) -> 15728640" + echo 15728640 > /proc/sys/net/core/rmem_max + fi + if [ $(echo "$(cat /proc/sys/net/core/wmem_max) < 5242880" | ${pkgs.bc}/bin/bc) == "1" ]; then + echo "increasing socket buffer limit (/proc/sys/net/core/wmem_max): $(cat /proc/sys/net/core/wmem_max) -> 5242880" + echo 5242880 > /proc/sys/net/core/wmem_max + fi + install -d -m0700 -o ${serviceConfig.User} -g ${serviceConfig.Group} "${cfg.workDir}" + install -d -m0700 -o ${serviceConfig.User} -g ${serviceConfig.Group} "${cfg.workDir}/smd" + install -d -m0700 -o ${serviceConfig.User} -g ${serviceConfig.Group} "${cfg.workDir}/udf" + install -d -m0700 -o ${serviceConfig.User} -g ${serviceConfig.Group} "${cfg.workDir}/udf/lua" + ''; + }; + + }; + +} diff --git a/nixos/modules/services/databases/neo4j.nix b/nixos/modules/services/databases/neo4j.nix index 5015618c4247..5533182c3116 100644 --- a/nixos/modules/services/databases/neo4j.nix +++ b/nixos/modules/services/databases/neo4j.nix @@ -1,32 +1,87 @@ -{ config, lib, pkgs, ... }: +{ config, options, lib, pkgs, ... }: with lib; let cfg = config.services.neo4j; + certDirOpt = options.services.neo4j.directories.certificates; + isDefaultPathOption = opt: isOption opt && opt.type == types.path && opt.highestPrio >= 1500; + + sslPolicies = mapAttrsToList ( + name: conf: '' + dbms.ssl.policy.${name}.allow_key_generation=${boolToString conf.allowKeyGeneration} + dbms.ssl.policy.${name}.base_directory=${conf.baseDirectory} + ${optionalString (conf.ciphers != null) '' + dbms.ssl.policy.${name}.ciphers=${concatStringsSep "," conf.ciphers} + ''} + dbms.ssl.policy.${name}.client_auth=${conf.clientAuth} + ${if length (splitString "/" conf.privateKey) > 1 then + ''dbms.ssl.policy.${name}.private_key=${conf.privateKey}'' + else + ''dbms.ssl.policy.${name}.private_key=${conf.baseDirectory}/${conf.privateKey}'' + } + ${if length (splitString "/" conf.privateKey) > 1 then + ''dbms.ssl.policy.${name}.public_certificate=${conf.publicCertificate}'' + else + ''dbms.ssl.policy.${name}.public_certificate=${conf.baseDirectory}/${conf.publicCertificate}'' + } + dbms.ssl.policy.${name}.revoked_dir=${conf.revokedDir} + dbms.ssl.policy.${name}.tls_versions=${concatStringsSep "," conf.tlsVersions} + dbms.ssl.policy.${name}.trust_all=${boolToString conf.trustAll} + dbms.ssl.policy.${name}.trusted_dir=${conf.trustedDir} + '' + ) cfg.ssl.policies; serverConfig = pkgs.writeText "neo4j.conf" '' - dbms.directories.data=${cfg.dataDir}/data - dbms.directories.certificates=${cfg.certDir} - dbms.directories.logs=${cfg.dataDir}/logs - dbms.directories.plugins=${cfg.dataDir}/plugins - dbms.connector.http.type=HTTP - dbms.connector.http.enabled=true - dbms.connector.http.address=${cfg.listenAddress}:${toString cfg.port} - ${optionalString cfg.enableBolt '' - dbms.connector.bolt.type=BOLT - dbms.connector.bolt.enabled=true - dbms.connector.bolt.tls_level=OPTIONAL - dbms.connector.bolt.address=${cfg.listenAddress}:${toString cfg.boltPort} + # General + dbms.allow_upgrade=${boolToString cfg.allowUpgrade} + dbms.connectors.default_listen_address=${cfg.defaultListenAddress} + dbms.read_only=${boolToString cfg.readOnly} + ${optionalString (cfg.workerCount > 0) '' + dbms.threads.worker_count=${toString cfg.workerCount} ''} - ${optionalString cfg.enableHttps '' - dbms.connector.https.type=HTTP - dbms.connector.https.enabled=true - dbms.connector.https.encryption=TLS - dbms.connector.https.address=${cfg.listenAddress}:${toString cfg.httpsPort} + + # Directories + dbms.directories.certificates=${cfg.directories.certificates} + dbms.directories.data=${cfg.directories.data} + dbms.directories.logs=${cfg.directories.home}/logs + dbms.directories.plugins=${cfg.directories.plugins} + ${optionalString (cfg.constrainLoadCsv) '' + dbms.directories.import=${cfg.directories.imports} ''} - dbms.shell.enabled=true - ${cfg.extraServerConfig} + + # HTTP Connector + ${optionalString (cfg.http.enable) '' + dbms.connector.http.enabled=${boolToString cfg.http.enable} + dbms.connector.http.listen_address=${cfg.http.listenAddress} + ''} + ${optionalString (!cfg.http.enable) '' + # It is not possible to disable the HTTP connector. To fully prevent + # clients from connecting to HTTP, block the HTTP port (7474 by default) + # via firewall. listen_address is set to the loopback interface to + # prevent remote clients from connecting. + dbms.connector.http.listen_address=127.0.0.1 + ''} + + # HTTPS Connector + dbms.connector.https.enabled=${boolToString cfg.https.enable} + dbms.connector.https.listen_address=${cfg.https.listenAddress} + https.ssl_policy=${cfg.https.sslPolicy} + + # BOLT Connector + dbms.connector.bolt.enabled=${boolToString cfg.bolt.enable} + dbms.connector.bolt.listen_address=${cfg.bolt.listenAddress} + bolt.ssl_policy=${cfg.bolt.sslPolicy} + dbms.connector.bolt.tls_level=${cfg.bolt.tlsLevel} + + # neo4j-shell + dbms.shell.enabled=${boolToString cfg.shell.enable} + + # SSL Policies + ${concatStringsSep "\n" sslPolicies} + + # Default retention policy from neo4j.conf + dbms.tx_log.rotation.retention_policy=1 days # Default JVM parameters from neo4j.conf dbms.jvm.additional=-XX:+UseG1GC @@ -36,8 +91,14 @@ let dbms.jvm.additional=-XX:+TrustFinalNonStaticFields dbms.jvm.additional=-XX:+DisableExplicitGC dbms.jvm.additional=-Djdk.tls.ephemeralDHKeySize=2048 - + dbms.jvm.additional=-Djdk.tls.rejectClientInitiatedRenegotiation=true dbms.jvm.additional=-Dunsupported.dbms.udc.source=tarball + + # Usage Data Collector + dbms.udc.enabled=${boolToString cfg.udc.enable} + + # Extra Configuration + ${cfg.extraServerConfig} ''; in { @@ -45,105 +106,547 @@ in { ###### interface options.services.neo4j = { + enable = mkOption { - description = "Whether to enable neo4j."; + type = types.bool; default = false; + description = '' + Whether to enable Neo4j Community Edition. + ''; + }; + + allowUpgrade = mkOption { type = types.bool; + default = false; + description = '' + Allow upgrade of Neo4j database files from an older version. + ''; + }; + + constrainLoadCsv = mkOption { + type = types.bool; + default = true; + description = '' + Sets the root directory for file URLs used with the Cypher + <literal>LOAD CSV</literal> clause to be that defined by + <option>directories.imports</option>. It restricts + access to only those files within that directory and its + subdirectories. + </para> + <para> + Setting this option to <literal>false</literal> introduces + possible security problems. + ''; + }; + + defaultListenAddress = mkOption { + type = types.str; + default = "127.0.0.1"; + description = '' + Default network interface to listen for incoming connections. To + listen for connections on all interfaces, use "0.0.0.0". + </para> + <para> + Specifies the default IP address and address part of connector + specific <option>listenAddress</option> options. To bind specific + connectors to a specific network interfaces, specify the entire + <option>listenAddress</option> option for that connector. + ''; + }; + + extraServerConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra configuration for Neo4j Community server. Refer to the + <link xlink:href="https://neo4j.com/docs/operations-manual/current/reference/configuration-settings/">complete reference</link> + of Neo4j configuration settings. + ''; }; package = mkOption { - description = "Neo4j package to use."; + type = types.package; default = pkgs.neo4j; defaultText = "pkgs.neo4j"; - type = types.package; + description = '' + Neo4j package to use. + ''; }; - listenAddress = mkOption { - description = "Neo4j listen address."; - default = "127.0.0.1"; - type = types.str; + readOnly = mkOption { + type = types.bool; + default = false; + description = '' + Only allow read operations from this Neo4j instance. + ''; }; - port = mkOption { - description = "Neo4j port to listen for HTTP traffic."; - default = 7474; - type = types.int; + workerCount = mkOption { + type = types.ints.between 0 44738; + default = 0; + description = '' + Number of Neo4j worker threads, where the default of + <literal>0</literal> indicates a worker count equal to the number of + available processors. + ''; }; - enableBolt = mkOption { - description = "Enable bolt for Neo4j."; - default = true; - type = types.bool; + bolt = { + enable = mkOption { + type = types.bool; + default = true; + description = '' + Enable the BOLT connector for Neo4j. Setting this option to + <literal>false</literal> will stop Neo4j from listening for incoming + connections on the BOLT port (7687 by default). + ''; + }; + + listenAddress = mkOption { + type = types.str; + default = ":7687"; + description = '' + Neo4j listen address for BOLT traffic. The listen address is + expressed in the format <literal><ip-address>:<port-number></literal>. + ''; + }; + + sslPolicy = mkOption { + type = types.str; + default = "legacy"; + description = '' + Neo4j SSL policy for BOLT traffic. + </para> + <para> + The legacy policy is a special policy which is not defined in + the policy configuration section, but rather derives from + <option>directories.certificates</option> and + associated files (by default: <filename>neo4j.key</filename> and + <filename>neo4j.cert</filename>). Its use will be deprecated. + </para> + <para> + Note: This connector must be configured to support/require + SSL/TLS for the legacy policy to actually be utilized. See + <option>bolt.tlsLevel</option>. + ''; + }; + + tlsLevel = mkOption { + type = types.enum [ "REQUIRED" "OPTIONAL" "DISABLED" ]; + default = "OPTIONAL"; + description = '' + SSL/TSL requirement level for BOLT traffic. + ''; + }; }; - boltPort = mkOption { - description = "Neo4j port to listen for BOLT traffic."; - default = 7687; - type = types.int; + directories = { + certificates = mkOption { + type = types.path; + default = "${cfg.directories.home}/certificates"; + description = '' + Directory for storing certificates to be used by Neo4j for + TLS connections. + </para> + <para> + When setting this directory to something other than its default, + ensure the directory's existence, and that read/write permissions are + given to the Neo4j daemon user <literal>neo4j</literal>. + </para> + <para> + Note that changing this directory from its default will prevent + the directory structure required for each SSL policy from being + automatically generated. A policy's directory structure as defined by + its <option>baseDirectory</option>,<option>revokedDir</option> and + <option>trustedDir</option> must then be setup manually. The + existence of these directories is mandatory, as well as the presence + of the certificate file and the private key. Ensure the correct + permissions are set on these directories and files. + ''; + }; + + data = mkOption { + type = types.path; + default = "${cfg.directories.home}/data"; + description = '' + Path of the data directory. You must not configure more than one + Neo4j installation to use the same data directory. + </para> + <para> + When setting this directory to something other than its default, + ensure the directory's existence, and that read/write permissions are + given to the Neo4j daemon user <literal>neo4j</literal>. + ''; + }; + + home = mkOption { + type = types.path; + default = "/var/lib/neo4j"; + description = '' + Path of the Neo4j home directory. Other default directories are + subdirectories of this path. This directory will be created if + non-existent, and its ownership will be <command>chown</command> to + the Neo4j daemon user <literal>neo4j</literal>. + ''; + }; + + imports = mkOption { + type = types.path; + default = "${cfg.directories.home}/import"; + description = '' + The root directory for file URLs used with the Cypher + <literal>LOAD CSV</literal> clause. Only meaningful when + <option>constrainLoadCvs</option> is set to + <literal>true</literal>. + </para> + <para> + When setting this directory to something other than its default, + ensure the directory's existence, and that read permission is + given to the Neo4j daemon user <literal>neo4j</literal>. + ''; + }; + + plugins = mkOption { + type = types.path; + default = "${cfg.directories.home}/plugins"; + description = '' + Path of the database plugin directory. Compiled Java JAR files that + contain database procedures will be loaded if they are placed in + this directory. + </para> + <para> + When setting this directory to something other than its default, + ensure the directory's existence, and that read permission is + given to the Neo4j daemon user <literal>neo4j</literal>. + ''; + }; }; - enableHttps = mkOption { - description = "Enable https for Neo4j."; - default = false; - type = types.bool; + http = { + enable = mkOption { + type = types.bool; + default = true; + description = '' + The HTTP connector is required for Neo4j, and cannot be disabled. + Setting this option to <literal>false</literal> will force the HTTP + connector's <option>listenAddress</option> to the loopback + interface to prevent connection of remote clients. To prevent all + clients from connecting, block the HTTP port (7474 by default) by + firewall. + ''; + }; + + listenAddress = mkOption { + type = types.str; + default = ":7474"; + description = '' + Neo4j listen address for HTTP traffic. The listen address is + expressed in the format <literal><ip-address>:<port-number></literal>. + ''; + }; }; - httpsPort = mkOption { - description = "Neo4j port to listen for HTTPS traffic."; - default = 7473; - type = types.int; + https = { + enable = mkOption { + type = types.bool; + default = true; + description = '' + Enable the HTTPS connector for Neo4j. Setting this option to + <literal>false</literal> will stop Neo4j from listening for incoming + connections on the HTTPS port (7473 by default). + ''; + }; + + listenAddress = mkOption { + type = types.str; + default = ":7473"; + description = '' + Neo4j listen address for HTTPS traffic. The listen address is + expressed in the format <literal><ip-address>:<port-number></literal>. + ''; + }; + + sslPolicy = mkOption { + type = types.str; + default = "legacy"; + description = '' + Neo4j SSL policy for HTTPS traffic. + </para> + <para> + The legacy policy is a special policy which is not defined in the + policy configuration section, but rather derives from + <option>directories.certificates</option> and + associated files (by default: <filename>neo4j.key</filename> and + <filename>neo4j.cert</filename>). Its use will be deprecated. + ''; + }; }; - certDir = mkOption { - description = "Neo4j TLS certificates directory."; - default = "${cfg.dataDir}/certificates"; - type = types.path; + shell = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enable a remote shell server which Neo4j Shell clients can log in to. + Only applicable to <command>neo4j-shell</command>. + ''; + }; }; - dataDir = mkOption { - description = "Neo4j data directory."; - default = "/var/lib/neo4j"; - type = types.path; + ssl.policies = mkOption { + type = with types; attrsOf (submodule ({ name, config, options, ... }: { + options = { + + allowKeyGeneration = mkOption { + type = types.bool; + default = false; + description = '' + Allows the generation of a private key and associated self-signed + certificate. Only performed when both objects cannot be found for + this policy. It is recommended to turn this off again after keys + have been generated. + </para> + <para> + The public certificate is required to be duplicated to the + directory holding trusted certificates as defined by the + <option>trustedDir</option> option. + </para> + <para> + Keys should in general be generated and distributed offline by a + trusted certificate authority and not by utilizing this mode. + ''; + }; + + baseDirectory = mkOption { + type = types.path; + default = "${cfg.directories.certificates}/${name}"; + description = '' + The mandatory base directory for cryptographic objects of this + policy. This path is only automatically generated when this + option as well as <option>directories.certificates</option> are + left at their default. Ensure read/write permissions are given + to the Neo4j daemon user <literal>neo4j</literal>. + </para> + <para> + It is also possible to override each individual + configuration with absolute paths. See the + <option>privateKey</option> and <option>publicCertificate</option> + policy options. + ''; + }; + + ciphers = mkOption { + type = types.nullOr (types.listOf types.str); + default = null; + description = '' + Restrict the allowed ciphers of this policy to those defined + here. The default ciphers are those of the JVM platform. + ''; + }; + + clientAuth = mkOption { + type = types.enum [ "NONE" "OPTIONAL" "REQUIRE" ]; + default = "REQUIRE"; + description = '' + The client authentication stance for this policy. + ''; + }; + + privateKey = mkOption { + type = types.str; + default = "private.key"; + description = '' + The name of private PKCS #8 key file for this policy to be found + in the <option>baseDirectory</option>, or the absolute path to + the key file. It is mandatory that a key can be found or generated. + ''; + }; + + publicCertificate = mkOption { + type = types.str; + default = "public.crt"; + description = '' + The name of public X.509 certificate (chain) file in PEM format + for this policy to be found in the <option>baseDirectory</option>, + or the absolute path to the certificate file. It is mandatory + that a certificate can be found or generated. + </para> + <para> + The public certificate is required to be duplicated to the + directory holding trusted certificates as defined by the + <option>trustedDir</option> option. + ''; + }; + + revokedDir = mkOption { + type = types.path; + default = "${config.baseDirectory}/revoked"; + description = '' + Path to directory of CRLs (Certificate Revocation Lists) in + PEM format. Must be an absolute path. The existence of this + directory is mandatory and will need to be created manually when: + setting this option to something other than its default; setting + either this policy's <option>baseDirectory</option> or + <option>directories.certificates</option> to something other than + their default. Ensure read/write permissions are given to the + Neo4j daemon user <literal>neo4j</literal>. + ''; + }; + + tlsVersions = mkOption { + type = types.listOf types.str; + default = [ "TLSv1.2" ]; + description = '' + Restrict the TLS protocol versions of this policy to those + defined here. + ''; + }; + + trustAll = mkOption { + type = types.bool; + default = false; + description = '' + Makes this policy trust all remote parties. Enabling this is not + recommended and the policy's trusted directory will be ignored. + Use of this mode is discouraged. It would offer encryption but + no security. + ''; + }; + + trustedDir = mkOption { + type = types.path; + default = "${config.baseDirectory}/trusted"; + description = '' + Path to directory of X.509 certificates in PEM format for + trusted parties. Must be an absolute path. The existence of this + directory is mandatory and will need to be created manually when: + setting this option to something other than its default; setting + either this policy's <option>baseDirectory</option> or + <option>directories.certificates</option> to something other than + their default. Ensure read/write permissions are given to the + Neo4j daemon user <literal>neo4j</literal>. + </para> + <para> + The public certificate as defined by + <option>publicCertificate</option> is required to be duplicated + to this directory. + ''; + }; + + directoriesToCreate = mkOption { + type = types.listOf types.path; + internal = true; + readOnly = true; + description = '' + Directories of this policy that will be created automatically + when the certificates directory is left at its default value. + This includes all options of type path that are left at their + default value. + ''; + }; + + }; + + config.directoriesToCreate = optionals + (certDirOpt.highestPrio >= 1500 && options.baseDirectory.highestPrio >= 1500) + (map (opt: opt.value) (filter isDefaultPathOption (attrValues options))); + + })); + default = {}; + description = '' + Defines the SSL policies for use with Neo4j connectors. Each attribute + of this set defines a policy, with the attribute name defining the name + of the policy and its namespace. Refer to the operations manual section + on Neo4j's + <link xlink:href="https://neo4j.com/docs/operations-manual/current/security/ssl-framework/">SSL Framework</link> + for further details. + ''; }; - extraServerConfig = mkOption { - description = "Extra configuration for neo4j server."; - default = ""; - type = types.lines; + udc = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enable the Usage Data Collector which Neo4j uses to collect usage + data. Refer to the operations manual section on the + <link xlink:href="https://neo4j.com/docs/operations-manual/current/configuration/usage-data-collector/">Usage Data Collector</link> + for more information. + ''; + }; }; + }; ###### implementation - config = mkIf cfg.enable { - systemd.services.neo4j = { - description = "Neo4j Daemon"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - environment = { - NEO4J_HOME = "${cfg.package}/share/neo4j"; - NEO4J_CONF = "${cfg.dataDir}/conf"; - }; - serviceConfig = { - ExecStart = "${cfg.package}/bin/neo4j console"; - User = "neo4j"; - PermissionsStartOnly = true; - LimitNOFILE = 40000; - }; - preStart = '' - mkdir -m 0700 -p ${cfg.dataDir}/{data/graph.db,conf,logs} - ln -fs ${serverConfig} ${cfg.dataDir}/conf/neo4j.conf - if [ "$(id -u)" = 0 ]; then chown -R neo4j ${cfg.dataDir}; fi - ''; - }; + config = + let + # Assertion helpers + policyNameList = attrNames cfg.ssl.policies; + validPolicyNameList = [ "legacy" ] ++ policyNameList; + validPolicyNameString = concatStringsSep ", " validPolicyNameList; + + # Capture various directories left at their default so they can be created. + defaultDirectoriesToCreate = map (opt: opt.value) (filter isDefaultPathOption (attrValues options.services.neo4j.directories)); + policyDirectoriesToCreate = concatMap (pol: pol.directoriesToCreate) (attrValues cfg.ssl.policies); + in + + mkIf cfg.enable { + assertions = [ + { assertion = !elem "legacy" policyNameList; + message = "The policy 'legacy' is special to Neo4j, and its name is reserved."; } + { assertion = elem cfg.bolt.sslPolicy validPolicyNameList; + message = "Invalid policy assigned: `services.neo4j.bolt.sslPolicy = \"${cfg.bolt.sslPolicy}\"`, defined policies are: ${validPolicyNameString}"; } + { assertion = elem cfg.https.sslPolicy validPolicyNameList; + message = "Invalid policy assigned: `services.neo4j.https.sslPolicy = \"${cfg.https.sslPolicy}\"`, defined policies are: ${validPolicyNameString}"; } + ]; + + systemd.services.neo4j = { + description = "Neo4j Daemon"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + environment = { + NEO4J_HOME = "${cfg.package}/share/neo4j"; + NEO4J_CONF = "${cfg.directories.home}/conf"; + }; + serviceConfig = { + ExecStart = "${cfg.package}/bin/neo4j console"; + User = "neo4j"; + PermissionsStartOnly = true; + LimitNOFILE = 40000; + }; + + preStart = '' + # Directories Setup + # Always ensure home exists with nested conf, logs directories. + mkdir -m 0700 -p ${cfg.directories.home}/{conf,logs} - environment.systemPackages = [ cfg.package ]; + # Create other sub-directories and policy directories that have been left at their default. + ${concatMapStringsSep "\n" ( + dir: '' + mkdir -m 0700 -p ${dir} + '') (defaultDirectoriesToCreate ++ policyDirectoriesToCreate)} - users.users = singleton { - name = "neo4j"; - uid = config.ids.uids.neo4j; - description = "Neo4j daemon user"; - home = cfg.dataDir; + # Place the configuration where Neo4j can find it. + ln -fs ${serverConfig} ${cfg.directories.home}/conf/neo4j.conf + + # Ensure neo4j user ownership + chown -R neo4j ${cfg.directories.home} + ''; + }; + + environment.systemPackages = [ cfg.package ]; + + users.users = singleton { + name = "neo4j"; + uid = config.ids.uids.neo4j; + description = "Neo4j daemon user"; + home = cfg.directories.home; + }; }; + + meta = { + maintainers = with lib.maintainers; [ patternspandemic ]; }; } diff --git a/nixos/modules/services/desktops/bamf.nix b/nixos/modules/services/desktops/bamf.nix new file mode 100644 index 000000000000..0928ee81a648 --- /dev/null +++ b/nixos/modules/services/desktops/bamf.nix @@ -0,0 +1,23 @@ +# Bamf + +{ config, lib, pkgs, ... }: + +with lib; + +{ + ###### interface + + options = { + services.bamf = { + enable = mkEnableOption "bamf"; + }; + }; + + ###### implementation + + config = mkIf config.services.bamf.enable { + services.dbus.packages = [ pkgs.bamf ]; + + systemd.packages = [ pkgs.bamf ]; + }; +} diff --git a/nixos/modules/services/hardware/pcscd.nix b/nixos/modules/services/hardware/pcscd.nix index fa97e8bf746b..f3fc4c3cc79e 100644 --- a/nixos/modules/services/hardware/pcscd.nix +++ b/nixos/modules/services/hardware/pcscd.nix @@ -61,8 +61,8 @@ in { description = "PCSC-Lite daemon"; environment.PCSCLITE_HP_DROPDIR = pluginEnv; serviceConfig = { - ExecStart = "${pkgs.pcsclite}/sbin/pcscd -f -x -c ${cfgFile}"; - ExecReload = "${pkgs.pcsclite}/sbin/pcscd -H"; + ExecStart = "${getBin pkgs.pcsclite}/sbin/pcscd -f -x -c ${cfgFile}"; + ExecReload = "${getBin pkgs.pcsclite}/sbin/pcscd -H"; }; }; }; diff --git a/nixos/modules/services/misc/clipmenu.nix b/nixos/modules/services/misc/clipmenu.nix new file mode 100644 index 000000000000..3ba050044cac --- /dev/null +++ b/nixos/modules/services/misc/clipmenu.nix @@ -0,0 +1,31 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.clipmenu; +in { + + options.services.clipmenu = { + enable = mkEnableOption "clipmenu, the clipboard management daemon"; + + package = mkOption { + type = types.package; + default = pkgs.clipmenu; + defaultText = "pkgs.clipmenu"; + description = "clipmenu derivation to use."; + }; + }; + + config = mkIf cfg.enable { + systemd.user.services.clipmenu = { + enable = true; + description = "Clipboard management daemon"; + wantedBy = [ "graphical-session.target" ]; + after = [ "graphical-session.target" ]; + serviceConfig.ExecStart = "${cfg.package}/bin/clipmenud"; + }; + + environment.systemPackages = [ cfg.package ]; + }; +} diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix index 8b04fac089ef..7b2d1920f0f1 100644 --- a/nixos/modules/services/networking/ssh/sshd.nix +++ b/nixos/modules/services/networking/ssh/sshd.nix @@ -198,6 +198,10 @@ in [ { type = "rsa"; bits = 4096; path = "/etc/ssh/ssh_host_rsa_key"; } { type = "ed25519"; path = "/etc/ssh/ssh_host_ed25519_key"; } ]; + example = + [ { type = "rsa"; bits = 4096; path = "/etc/ssh/ssh_host_rsa_key"; rounds = 100; openSSHFormat = true; } + { type = "ed25519"; path = "/etc/ssh/ssh_host_ed25519_key"; rounds = 100; comment = "key comment"; } + ]; description = '' NixOS can automatically generate SSH host keys. This option specifies the path, type and size of each key. See @@ -358,7 +362,14 @@ in ${flip concatMapStrings cfg.hostKeys (k: '' if ! [ -f "${k.path}" ]; then - ssh-keygen -t "${k.type}" ${if k ? bits then "-b ${toString k.bits}" else ""} -f "${k.path}" -N "" + ssh-keygen \ + -t "${k.type}" \ + ${if k ? bits then "-b ${toString k.bits}" else ""} \ + ${if k ? rounds then "-a ${toString k.rounds}" else ""} \ + ${if k ? comment then "-C '${k.comment}'" else ""} \ + ${if k ? openSSHFormat && k.openSSHFormat then "-o" else ""} \ + -f "${k.path}" \ + -N "" fi '')} ''; @@ -404,6 +415,9 @@ in unixAuth = cfg.passwordAuthentication; }; + # These values are merged with the ones defined externally, see: + # https://github.com/NixOS/nixpkgs/pull/10155 + # https://github.com/NixOS/nixpkgs/pull/41745 services.openssh.authorizedKeysFiles = [ ".ssh/authorized_keys" ".ssh/authorized_keys2" "/etc/ssh/authorized_keys.d/%u" ]; diff --git a/nixos/modules/services/printing/cupsd.nix b/nixos/modules/services/printing/cupsd.nix index b074d15cbec1..dbf18ec1d114 100644 --- a/nixos/modules/services/printing/cupsd.nix +++ b/nixos/modules/services/printing/cupsd.nix @@ -124,6 +124,16 @@ in ''; }; + startWhenNeeded = mkOption { + type = types.bool; + default = false; + description = '' + If set, CUPS is socket-activated; that is, + instead of having it permanently running as a daemon, + systemd will start it on the first incoming connection. + ''; + }; + listenAddresses = mkOption { type = types.listOf types.str; default = [ "localhost:631" ]; @@ -287,8 +297,13 @@ in systemd.packages = [ cups.out ]; + systemd.sockets.cups = mkIf cfg.startWhenNeeded { + wantedBy = [ "sockets.target" ]; + listenStreams = map (x: replaceStrings ["localhost"] ["127.0.0.1"] (removePrefix "*:" x)) cfg.listenAddresses; + }; + systemd.services.cups = - { wantedBy = [ "multi-user.target" ]; + { wantedBy = optionals (!cfg.startWhenNeeded) [ "multi-user.target" ]; wants = [ "network.target" ]; after = [ "network.target" ]; diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix index b71ff0531cc8..eb8ee9b5cf46 100644 --- a/nixos/modules/services/web-servers/apache-httpd/default.nix +++ b/nixos/modules/services/web-servers/apache-httpd/default.nix @@ -656,7 +656,7 @@ in message = "SSL is enabled for httpd, but sslServerCert and/or sslServerKey haven't been specified."; } ]; - warnings = map (cfg: ''apache-httpd's port option is deprecated. Use listen = [{/*ip = "*"; */ port = ${toString cfg.port}";}]; instead'' ) (lib.filter (cfg: cfg.port != 0) allHosts); + warnings = map (cfg: ''apache-httpd's port option is deprecated. Use listen = [{/*ip = "*"; */ port = ${toString cfg.port};}]; instead'' ) (lib.filter (cfg: cfg.port != 0) allHosts); users.users = optionalAttrs (mainCfg.user == "wwwrun") (singleton { name = "wwwrun"; diff --git a/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixos/modules/services/x11/desktop-managers/plasma5.nix index 91d091d7d7e2..4b9e561d53c8 100644 --- a/nixos/modules/services/x11/desktop-managers/plasma5.nix +++ b/nixos/modules/services/x11/desktop-managers/plasma5.nix @@ -221,6 +221,11 @@ in security.pam.services.sddm.enableKwallet = true; security.pam.services.slim.enableKwallet = true; + # Update the start menu for each user that has `isNormalUser` set. + system.activationScripts.plasmaSetup = stringAfter [ "users" "groups" ] + (concatStringsSep "\n" + (mapAttrsToList (name: value: "${pkgs.su}/bin/su ${name} -c kbuildsycoca5") + (filterAttrs (n: v: v.isNormalUser) config.users.users))); }) ]; diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix index 7dcc600d2664..ae155470419d 100644 --- a/nixos/modules/services/x11/desktop-managers/xfce.nix +++ b/nixos/modules/services/x11/desktop-managers/xfce.nix @@ -43,12 +43,6 @@ in default = true; description = "Enable the XFWM (default) window manager."; }; - - screenLock = mkOption { - type = types.enum [ "xscreensaver" "xlockmore" "slock" ]; - default = "xlockmore"; - description = "Application used by XFCE to lock the screen."; - }; }; }; @@ -92,7 +86,7 @@ in thunar-volman # TODO: drop ] ++ (if config.hardware.pulseaudio.enable then [ xfce4-mixer-pulse xfce4-volumed-pulse ] - else [ xfce4-mixer xfce4-volumed ]) + else [ xfce4-mixer xfce4-volumed ]) # TODO: NetworkManager doesn't belong here ++ optionals config.networking.networkmanager.enable [ networkmanagerapplet ] ++ optionals config.powerManagement.enable [ xfce4-power-manager ] diff --git a/nixos/modules/services/x11/display-managers/sddm.nix b/nixos/modules/services/x11/display-managers/sddm.nix index 8db7414e811f..426b899586f5 100644 --- a/nixos/modules/services/x11/display-managers/sddm.nix +++ b/nixos/modules/services/x11/display-managers/sddm.nix @@ -19,17 +19,6 @@ let Xsetup = pkgs.writeScript "Xsetup" '' #!/bin/sh - - # Prior to Qt 5.9.2, there is a QML cache invalidation bug which sometimes - # strikes new Plasma 5 releases. If the QML cache is not invalidated, SDDM - # will segfault without explanation. We really tore our hair out for awhile - # before finding the bug: - # https://bugreports.qt.io/browse/QTBUG-62302 - # We work around the problem by deleting the QML cache before startup. It - # will be regenerated, causing a small but perceptible delay when SDDM - # starts. - rm -fr /var/lib/sddm/.cache/sddm-greeter/qmlcache - ${cfg.setupScript} ''; @@ -285,5 +274,20 @@ in # To enable user switching, allow sddm to allocate TTYs/displays dynamically. services.xserver.tty = null; services.xserver.display = null; + + systemd.tmpfiles.rules = [ + # Prior to Qt 5.9.2, there is a QML cache invalidation bug which sometimes + # strikes new Plasma 5 releases. If the QML cache is not invalidated, SDDM + # will segfault without explanation. We really tore our hair out for awhile + # before finding the bug: + # https://bugreports.qt.io/browse/QTBUG-62302 + # We work around the problem by deleting the QML cache before startup. + # This was supposedly fixed in Qt 5.9.2 however it has been reported with + # 5.10 and 5.11 as well. The initial workaround was to delete the directory + # in the Xsetup script but that doesn't do anything. + # Instead we use tmpfiles.d to ensure it gets wiped. + # This causes a small but perceptible delay when SDDM starts. + "e ${config.users.users.sddm.home}/.cache - - - 0" + ]; }; } |