diff options
Diffstat (limited to 'nixos')
-rw-r--r-- | nixos/doc/manual/release-notes/rl-2009.xml | 41 | ||||
-rw-r--r-- | nixos/modules/config/networking.nix | 33 | ||||
-rw-r--r-- | nixos/modules/module-list.nix | 2 | ||||
-rw-r--r-- | nixos/modules/services/misc/redmine.nix | 4 | ||||
-rw-r--r-- | nixos/modules/services/networking/networkmanager.nix | 7 | ||||
-rw-r--r-- | nixos/modules/services/security/fprintd.nix | 1 | ||||
-rw-r--r-- | nixos/modules/services/security/usbguard.nix | 23 | ||||
-rw-r--r-- | nixos/modules/services/system/earlyoom.nix | 23 | ||||
-rw-r--r-- | nixos/modules/services/torrent/rtorrent.nix | 209 | ||||
-rw-r--r-- | nixos/modules/services/web-apps/engelsystem.nix | 186 | ||||
-rw-r--r-- | nixos/modules/services/x11/desktop-managers/cde.nix | 17 | ||||
-rw-r--r-- | nixos/modules/tasks/network-interfaces.nix | 16 | ||||
-rw-r--r-- | nixos/modules/virtualisation/cri-o.nix | 75 | ||||
-rw-r--r-- | nixos/tests/all-tests.nix | 2 | ||||
-rw-r--r-- | nixos/tests/engelsystem.nix | 41 | ||||
-rw-r--r-- | nixos/tests/hostname.nix | 66 |
16 files changed, 702 insertions, 44 deletions
diff --git a/nixos/doc/manual/release-notes/rl-2009.xml b/nixos/doc/manual/release-notes/rl-2009.xml index 41f9665a3cd5..e17e8ac24d13 100644 --- a/nixos/doc/manual/release-notes/rl-2009.xml +++ b/nixos/doc/manual/release-notes/rl-2009.xml @@ -400,6 +400,47 @@ systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ]; The rkt module has been removed, it was archived by upstream. </para> </listitem> + <listitem> + <para> + The <link xlink:href="https://bazaar.canonical.com">Bazaar</link> VCS is + unmaintained and, as consequence of the Python 2 EOL, the packages + <literal>bazaar</literal> and <literal>bazaarTools</literal> were + removed. Breezy, the backward compatible fork of Bazaar (see the + <link xlink:href="https://www.jelmer.uk/breezy-intro.html">announcement</link>), + was packaged as <literal>breezy</literal> and can be used instead. + </para> + <para> + Regarding Nixpkgs, <literal>fetchbzr</literal>, + <literal>nix-prefetch-bzr</literal> and Bazaar support in Hydra will + continue to work through Breezy. + </para> + </listitem> + <listitem> + <para> + In addition to the hostname, the fully qualified domain name (FQDN), + which consists of <literal>${cfg.hostName}</literal> and + <literal>${cfg.domain}</literal> is now added to + <literal>/etc/hosts</literal>, to allow local FQDN resolution, as used by the + <literal>hostname --fqdn</literal> command and other applications that + try to determine the FQDN. These new entries take precedence over entries + from the DNS which could cause regressions in some very specific setups. + Additionally the hostname is now resolved to <literal>127.0.0.2</literal> + instead of <literal>127.0.1.1</literal> to be consistent with what + <literal>nss-myhostname</literal> (from systemd) returns. + The old behaviour can e.g. be restored by using + <literal>networking.hosts = lib.mkForce { "127.0.1.1" = [ config.networking.hostName ]; };</literal>. + </para> + </listitem> + <listitem> + <para> + The hostname (<literal>networking.hostName</literal>) must now be a valid + DNS label (see RFC 1035) and as such must not contain the domain part. + This means that the hostname must start with a letter, end with a letter + or digit, and have as interior characters only letters, digits, and + hyphen. The maximum length is 63 characters. Additionally it is + recommended to only use lower-case characters. + </para> + </listitem> </itemizedlist> </section> diff --git a/nixos/modules/config/networking.nix b/nixos/modules/config/networking.nix index 03944de82497..4cb7d81c9972 100644 --- a/nixos/modules/config/networking.nix +++ b/nixos/modules/config/networking.nix @@ -8,9 +8,6 @@ let cfg = config.networking; - localhostMapped4 = cfg.hosts ? "127.0.0.1" && elem "localhost" cfg.hosts."127.0.0.1"; - localhostMapped6 = cfg.hosts ? "::1" && elem "localhost" cfg.hosts."::1"; - localhostMultiple = any (elem "localhost") (attrValues (removeAttrs cfg.hosts [ "127.0.0.1" "::1" ])); in @@ -147,12 +144,6 @@ in config = { assertions = [{ - assertion = localhostMapped4; - message = ''`networking.hosts` doesn't map "127.0.0.1" to "localhost"''; - } { - assertion = !cfg.enableIPv6 || localhostMapped6; - message = ''`networking.hosts` doesn't map "::1" to "localhost"''; - } { assertion = !localhostMultiple; message = '' `networking.hosts` maps "localhost" to something other than "127.0.0.1" @@ -161,22 +152,34 @@ in ''; }]; - networking.hosts = { - "127.0.0.1" = [ "localhost" ]; - } // optionalAttrs (cfg.hostName != "") { - "127.0.1.1" = [ cfg.hostName ]; + # These entries are required for "hostname -f" and to resolve both the + # hostname and FQDN correctly: + networking.hosts = let + hostnames = # Note: The FQDN (canonical hostname) has to come first: + optional (cfg.hostName != "" && cfg.domain != null) "${cfg.hostName}.${cfg.domain}" + ++ optional (cfg.hostName != "") cfg.hostName; # Then the hostname (without the domain) + in { + "127.0.0.2" = hostnames; } // optionalAttrs cfg.enableIPv6 { - "::1" = [ "localhost" ]; + "::1" = hostnames; }; networking.hostFiles = let + # Note: localhostHosts has to appear first in /etc/hosts so that 127.0.0.1 + # resolves back to "localhost" (as some applications assume) instead of + # the FQDN! By default "networking.hosts" also contains entries for the + # FQDN so that e.g. "hostname -f" works correctly. + localhostHosts = pkgs.writeText "localhost-hosts" '' + 127.0.0.1 localhost + ${optionalString cfg.enableIPv6 "::1 localhost"} + ''; stringHosts = let oneToString = set: ip: ip + " " + concatStringsSep " " set.${ip} + "\n"; allToString = set: concatMapStrings (oneToString set) (attrNames set); in pkgs.writeText "string-hosts" (allToString (filterAttrs (_: v: v != []) cfg.hosts)); extraHosts = pkgs.writeText "extra-hosts" cfg.extraHosts; - in mkBefore [ stringHosts extraHosts ]; + in mkBefore [ localhostHosts stringHosts extraHosts ]; environment.etc = { # /etc/services: TCP/UDP port assignments. diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index d5285cfabd78..9f9bf3bc5329 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -817,6 +817,7 @@ ./services/torrent/magnetico.nix ./services/torrent/opentracker.nix ./services/torrent/peerflix.nix + ./services/torrent/rtorrent.nix ./services/torrent/transmission.nix ./services/ttys/agetty.nix ./services/ttys/gpm.nix @@ -829,6 +830,7 @@ ./services/web-apps/cryptpad.nix ./services/web-apps/documize.nix ./services/web-apps/dokuwiki.nix + ./services/web-apps/engelsystem.nix ./services/web-apps/frab.nix ./services/web-apps/gerrit.nix ./services/web-apps/gotify-server.nix diff --git a/nixos/modules/services/misc/redmine.nix b/nixos/modules/services/misc/redmine.nix index 1febdba0c8f9..0e71cf925692 100644 --- a/nixos/modules/services/misc/redmine.nix +++ b/nixos/modules/services/misc/redmine.nix @@ -26,7 +26,7 @@ let scm_mercurial_command: ${pkgs.mercurial}/bin/hg scm_git_command: ${pkgs.gitAndTools.git}/bin/git scm_cvs_command: ${pkgs.cvs}/bin/cvs - scm_bazaar_command: ${pkgs.bazaar}/bin/bzr + scm_bazaar_command: ${pkgs.breezy}/bin/bzr scm_darcs_command: ${pkgs.darcs}/bin/darcs ${cfg.extraConfig} @@ -297,7 +297,7 @@ in environment.SCHEMA = "${cfg.stateDir}/cache/schema.db"; path = with pkgs; [ imagemagick - bazaar + breezy cvs darcs gitAndTools.git diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix index 6f24141b33cf..cc789897b29f 100644 --- a/nixos/modules/services/networking/networkmanager.nix +++ b/nixos/modules/services/networking/networkmanager.nix @@ -449,6 +449,13 @@ in { systemd.services.ModemManager.aliases = [ "dbus-org.freedesktop.ModemManager1.service" ]; + # override unit as recommended by upstream - see https://github.com/NixOS/nixpkgs/issues/88089 + # TODO: keep an eye on modem-manager releases as this will eventually be added to the upstream unit + systemd.services.ModemManager.serviceConfig.ExecStart = [ + "" + "${pkgs.modemmanager}/sbin/ModemManager --filter-policy=STRICT" + ]; + systemd.services.NetworkManager-dispatcher = { wantedBy = [ "network.target" ]; restartTriggers = [ configFile ]; diff --git a/nixos/modules/services/security/fprintd.nix b/nixos/modules/services/security/fprintd.nix index 8ece1ca19013..cbac4ef05b8d 100644 --- a/nixos/modules/services/security/fprintd.nix +++ b/nixos/modules/services/security/fprintd.nix @@ -29,7 +29,6 @@ in type = types.package; default = pkgs.fprintd; defaultText = "pkgs.fprintd"; - example = "pkgs.fprintd-thinkpad"; description = '' fprintd package to use. ''; diff --git a/nixos/modules/services/security/usbguard.nix b/nixos/modules/services/security/usbguard.nix index 4ced5acd9bd9..f4118eb87fc7 100644 --- a/nixos/modules/services/security/usbguard.nix +++ b/nixos/modules/services/security/usbguard.nix @@ -207,6 +207,29 @@ in { Type = "simple"; ExecStart = ''${cfg.package}/bin/usbguard-daemon -P -k -c ${daemonConfFile}''; Restart = "on-failure"; + + AmbientCapabilities = ""; + CapabilityBoundingSet = "CAP_CHOWN CAP_FOWNER"; + DeviceAllow = "/dev/null rw"; + DevicePolicy = "strict"; + IPAddressDeny = "any"; + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateTmp = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectKernelModules = true; + ProtectSystem = true; + ReadOnlyPaths = "-/"; + ReadWritePaths = "-/dev/shm -${dirOf cfg.auditFilePath} -/tmp -${dirOf cfg.ruleFile}"; + RestrictAddressFamilies = "AF_UNIX AF_NETLINK"; + RestrictNamespaces = true; + RestrictRealtime = true; + SystemCallArchitectures = "native"; + SystemCallFilter = "@system-service"; + UMask = "0077"; }; }; }; diff --git a/nixos/modules/services/system/earlyoom.nix b/nixos/modules/services/system/earlyoom.nix index 39d1bf274bd2..c6a001d30eeb 100644 --- a/nixos/modules/services/system/earlyoom.nix +++ b/nixos/modules/services/system/earlyoom.nix @@ -67,9 +67,19 @@ in notificationsCommand = mkOption { type = types.nullOr types.str; default = null; - example = "sudo -u example_user DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus notify-send"; description = '' - Command used to send notifications. + This option is deprecated and ignored by earlyoom since 1.6. + Use <option>services.earlyoom.enableNotifications</option> instead. + ''; + }; + + enableNotifications = mkOption { + type = types.bool; + default = false; + description = '' + Send notifications about killed processes via the system d-bus. + To actually see the notifications in your GUI session, you need to have + <literal>systembus-notify</literal> running as your user. See <link xlink:href="https://github.com/rfjakob/earlyoom#notifications">README</link> for details. ''; @@ -87,9 +97,13 @@ in message = "Both options in conjunction do not make sense"; } ]; + warnings = optional (ecfg.notificationsCommand != null) + "`services.earlyoom.notificationsCommand` is deprecated and ignored by earlyoom since 1.6."; + systemd.services.earlyoom = { description = "Early OOM Daemon for Linux"; wantedBy = [ "multi-user.target" ]; + path = optional ecfg.enableNotifications pkgs.dbus; serviceConfig = { StandardOutput = "null"; StandardError = "syslog"; @@ -100,10 +114,11 @@ in ${optionalString ecfg.useKernelOOMKiller "-k"} \ ${optionalString ecfg.ignoreOOMScoreAdjust "-i"} \ ${optionalString ecfg.enableDebugInfo "-d"} \ - ${optionalString (ecfg.notificationsCommand != null) - "-N ${escapeShellArg ecfg.notificationsCommand}"} + ${optionalString ecfg.enableNotifications "-n"} ''; }; }; + + environment.systemPackages = optional ecfg.enableNotifications pkgs.systembus-notify; }; } diff --git a/nixos/modules/services/torrent/rtorrent.nix b/nixos/modules/services/torrent/rtorrent.nix new file mode 100644 index 000000000000..be57c03b1721 --- /dev/null +++ b/nixos/modules/services/torrent/rtorrent.nix @@ -0,0 +1,209 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let + + cfg = config.services.rtorrent; + +in { + options.services.rtorrent = { + enable = mkEnableOption "rtorrent"; + + dataDir = mkOption { + type = types.str; + default = "/var/lib/rtorrent"; + description = '' + The directory where rtorrent stores its data files. + ''; + }; + + downloadDir = mkOption { + type = types.str; + default = "${cfg.dataDir}/download"; + description = '' + Where to put downloaded files. + ''; + }; + + user = mkOption { + type = types.str; + default = "rtorrent"; + description = '' + User account under which rtorrent runs. + ''; + }; + + group = mkOption { + type = types.str; + default = "rtorrent"; + description = '' + Group under which rtorrent runs. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.rtorrent; + defaultText = "pkgs.rtorrent"; + description = '' + The rtorrent package to use. + ''; + }; + + port = mkOption { + type = types.port; + default = 50000; + description = '' + The rtorrent port. + ''; + }; + + openFirewall = mkOption { + type = types.bool; + default = false; + description = '' + Whether to open the firewall for the port in <option>services.rtorrent.port</option>. + ''; + }; + + rpcSocket = mkOption { + type = types.str; + readOnly = true; + default = "/run/rtorrent/rpc.sock"; + description = '' + RPC socket path. + ''; + }; + + configText = mkOption { + type = types.lines; + default = ""; + description = '' + The content of <filename>rtorrent.rc</filename>. The <link xlink:href="https://rtorrent-docs.readthedocs.io/en/latest/cookbook.html#modernized-configuration-template">modernized configuration template</link> with the values specified in this module will be prepended using mkBefore. You can use mkForce to overwrite the config completly. + ''; + }; + }; + + config = mkIf cfg.enable { + + users.groups = mkIf (cfg.group == "rtorrent") { + rtorrent = {}; + }; + + users.users = mkIf (cfg.user == "rtorrent") { + rtorrent = { + group = cfg.group; + shell = pkgs.bashInteractive; + home = cfg.dataDir; + description = "rtorrent Daemon user"; + isSystemUser = true; + }; + }; + + networking.firewall.allowedTCPPorts = mkIf (cfg.openFirewall) [ cfg.port ]; + + services.rtorrent.configText = mkBefore '' + # Instance layout (base paths) + method.insert = cfg.basedir, private|const|string, (cat,"${cfg.dataDir}/") + method.insert = cfg.watch, private|const|string, (cat,(cfg.basedir),"watch/") + method.insert = cfg.logs, private|const|string, (cat,(cfg.basedir),"log/") + method.insert = cfg.logfile, private|const|string, (cat,(cfg.logs),(system.time),".log") + method.insert = cfg.rpcsock, private|const|string, (cat,"${cfg.rpcSocket}") + + # Create instance directories + execute.throw = sh, -c, (cat, "mkdir -p ", (cfg.basedir), "/session ", (cfg.watch), " ", (cfg.logs)) + + # Listening port for incoming peer traffic (fixed; you can also randomize it) + network.port_range.set = ${toString cfg.port}-${toString cfg.port} + network.port_random.set = no + + # Tracker-less torrent and UDP tracker support + # (conservative settings for 'private' trackers, change for 'public') + dht.mode.set = disable + protocol.pex.set = no + trackers.use_udp.set = no + + # Peer settings + throttle.max_uploads.set = 100 + throttle.max_uploads.global.set = 250 + + throttle.min_peers.normal.set = 20 + throttle.max_peers.normal.set = 60 + throttle.min_peers.seed.set = 30 + throttle.max_peers.seed.set = 80 + trackers.numwant.set = 80 + + protocol.encryption.set = allow_incoming,try_outgoing,enable_retry + + # Limits for file handle resources, this is optimized for + # an `ulimit` of 1024 (a common default). You MUST leave + # a ceiling of handles reserved for rTorrent's internal needs! + network.http.max_open.set = 50 + network.max_open_files.set = 600 + network.max_open_sockets.set = 3000 + + # Memory resource usage (increase if you have a large number of items loaded, + # and/or the available resources to spend) + pieces.memory.max.set = 1800M + network.xmlrpc.size_limit.set = 4M + + # Basic operational settings (no need to change these) + session.path.set = (cat, (cfg.basedir), "session/") + directory.default.set = "${cfg.downloadDir}" + log.execute = (cat, (cfg.logs), "execute.log") + ##log.xmlrpc = (cat, (cfg.logs), "xmlrpc.log") + execute.nothrow = sh, -c, (cat, "echo >", (session.path), "rtorrent.pid", " ", (system.pid)) + + # Other operational settings (check & adapt) + encoding.add = utf8 + system.umask.set = 0027 + system.cwd.set = (cfg.basedir) + network.http.dns_cache_timeout.set = 25 + schedule2 = monitor_diskspace, 15, 60, ((close_low_diskspace, 1000M)) + + # Watch directories (add more as you like, but use unique schedule names) + #schedule2 = watch_start, 10, 10, ((load.start, (cat, (cfg.watch), "start/*.torrent"))) + #schedule2 = watch_load, 11, 10, ((load.normal, (cat, (cfg.watch), "load/*.torrent"))) + + # Logging: + # Levels = critical error warn notice info debug + # Groups = connection_* dht_* peer_* rpc_* storage_* thread_* tracker_* torrent_* + print = (cat, "Logging to ", (cfg.logfile)) + log.open_file = "log", (cfg.logfile) + log.add_output = "info", "log" + ##log.add_output = "tracker_debug", "log" + + # XMLRPC + scgi_local = (cfg.rpcsock) + schedule = scgi_group,0,0,"execute.nothrow=chown,\":rtorrent\",(cfg.rpcsock)" + schedule = scgi_permission,0,0,"execute.nothrow=chmod,\"g+w,o=\",(cfg.rpcsock)" + ''; + + systemd = { + services = { + rtorrent = let + rtorrentConfigFile = pkgs.writeText "rtorrent.rc" cfg.configText; + in { + description = "rTorrent system service"; + after = [ "network.target" ]; + path = [ cfg.package pkgs.bash ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + User = cfg.user; + Group = cfg.group; + Type = "simple"; + Restart = "on-failure"; + WorkingDirectory = cfg.dataDir; + ExecStartPre=''${pkgs.bash}/bin/bash -c "if test -e ${cfg.dataDir}/session/rtorrent.lock && test -z $(${pkgs.procps}/bin/pidof rtorrent); then rm -f ${cfg.dataDir}/session/rtorrent.lock; fi"''; + ExecStart="${cfg.package}/bin/rtorrent -n -o system.daemon.set=true -o import=${rtorrentConfigFile}"; + RuntimeDirectory = "rtorrent"; + RuntimeDirectoryMode = 755; + }; + }; + }; + + tmpfiles.rules = [ "d '${cfg.dataDir}' 0750 ${cfg.user} ${cfg.group} -" ]; + }; + }; +} diff --git a/nixos/modules/services/web-apps/engelsystem.nix b/nixos/modules/services/web-apps/engelsystem.nix new file mode 100644 index 000000000000..899582a20304 --- /dev/null +++ b/nixos/modules/services/web-apps/engelsystem.nix @@ -0,0 +1,186 @@ +{ config, lib, pkgs, utils, ... }: + +let + inherit (lib) mkDefault mkEnableOption mkIf mkOption types literalExample; + cfg = config.services.engelsystem; +in { + options = { + services.engelsystem = { + enable = mkOption { + default = false; + example = true; + description = '' + Whether to enable engelsystem, an online tool for coordinating helpers + and shifts on large events. + ''; + type = lib.types.bool; + }; + + domain = mkOption { + type = types.str; + example = "engelsystem.example.com"; + description = "Domain to serve on."; + }; + + package = mkOption { + type = types.package; + example = literalExample "pkgs.engelsystem"; + description = "Engelsystem package used for the service."; + default = pkgs.engelsystem; + }; + + createDatabase = mkOption { + type = types.bool; + default = true; + description = '' + Whether to create a local database automatically. + This will override every database setting in <option>services.engelsystem.config</option>. + ''; + }; + }; + + services.engelsystem.config = mkOption { + type = types.attrs; + default = { + database = { + host = "localhost"; + database = "engelsystem"; + username = "engelsystem"; + }; + }; + example = { + maintenance = false; + database = { + host = "database.example.com"; + database = "engelsystem"; + username = "engelsystem"; + password._secret = "/var/keys/engelsystem/database"; + }; + email = { + driver = "smtp"; + host = "smtp.example.com"; + port = 587; + from.address = "engelsystem@example.com"; + from.name = "example engelsystem"; + encryption = "tls"; + username = "engelsystem@example.com"; + password._secret = "/var/keys/engelsystem/mail"; + }; + autoarrive = true; + min_password_length = 6; + default_locale = "de_DE"; + }; + description = '' + Options to be added to config.php, as a nix attribute set. Options containing secret data + should be set to an attribute set containing the attribute _secret - a string pointing to a + file containing the value the option should be set to. See the example to get a better + picture of this: in the resulting config.php file, the email.password key will be set to + the contents of the /var/keys/engelsystem/mail file. + + See https://engelsystem.de/doc/admin/configuration/ for available options. + + Note that the admin user login credentials cannot be set here - they always default to + admin:asdfasdf. Log in and change them immediately. + ''; + }; + }; + + config = mkIf cfg.enable { + # create database + services.mysql = mkIf cfg.createDatabase { + enable = true; + package = mkDefault pkgs.mysql; + ensureUsers = [{ + name = "engelsystem"; + ensurePermissions = { "engelsystem.*" = "ALL PRIVILEGES"; }; + }]; + ensureDatabases = [ "engelsystem" ]; + }; + + environment.etc."engelsystem/config.php".source = + pkgs.writeText "config.php" '' + <?php + return json_decode(file_get_contents("/var/lib/engelsystem/config.json"), true); + ''; + + services.phpfpm.pools.engelsystem = { + user = "engelsystem"; + settings = { + "listen.owner" = config.services.nginx.user; + "pm" = "dynamic"; + "pm.max_children" = 32; + "pm.max_requests" = 500; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 2; + "pm.max_spare_servers" = 5; + "php_admin_value[error_log]" = "stderr"; + "php_admin_flag[log_errors]" = true; + "catch_workers_output" = true; + }; + }; + + services.nginx = { + enable = true; + virtualHosts."${cfg.domain}".locations = { + "/" = { + root = "${cfg.package}/share/engelsystem/public"; + extraConfig = '' + index index.php; + try_files $uri $uri/ /index.php?$args; + autoindex off; + ''; + }; + "~ \\.php$" = { + root = "${cfg.package}/share/engelsystem/public"; + extraConfig = '' + fastcgi_pass unix:${config.services.phpfpm.pools.engelsystem.socket}; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include ${config.services.nginx.package}/conf/fastcgi_params; + include ${config.services.nginx.package}/conf/fastcgi.conf; + ''; + }; + }; + }; + + systemd.services."engelsystem-init" = { + wantedBy = [ "multi-user.target" ]; + serviceConfig = { Type = "oneshot"; }; + script = + let + genConfigScript = pkgs.writeScript "engelsystem-gen-config.sh" + (utils.genJqSecretsReplacementSnippet cfg.config "config.json"); + in '' + umask 077 + mkdir -p /var/lib/engelsystem/storage/app + mkdir -p /var/lib/engelsystem/storage/cache/views + cd /var/lib/engelsystem + ${genConfigScript} + chmod 400 config.json + chown -R engelsystem . + ''; + }; + systemd.services."engelsystem-migrate" = { + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "oneshot"; + User = "engelsystem"; + Group = "engelsystem"; + }; + script = '' + ${cfg.package}/bin/migrate + ''; + after = [ "engelsystem-init.service" "mysql.service" ]; + }; + systemd.services."phpfpm-engelsystem".after = + [ "engelsystem-migrate.service" ]; + + users.users.engelsystem = { + isSystemUser = true; + createHome = true; + home = "/var/lib/engelsystem/storage"; + group = "engelsystem"; + }; + users.groups.engelsystem = { }; + }; +} diff --git a/nixos/modules/services/x11/desktop-managers/cde.nix b/nixos/modules/services/x11/desktop-managers/cde.nix index c1b6d3bf064a..2d9504fb5f1e 100644 --- a/nixos/modules/services/x11/desktop-managers/cde.nix +++ b/nixos/modules/services/x11/desktop-managers/cde.nix @@ -8,9 +8,26 @@ let in { options.services.xserver.desktopManager.cde = { enable = mkEnableOption "Common Desktop Environment"; + + extraPackages = mkOption { + type = with types; listOf package; + default = with pkgs.xorg; [ + xclock bitmap xlsfonts xfd xrefresh xload xwininfo xdpyinfo xwd xwud + ]; + example = literalExample '' + with pkgs.xorg; [ + xclock bitmap xlsfonts xfd xrefresh xload xwininfo xdpyinfo xwd xwud + ] + ''; + description = '' + Extra packages to be installed system wide. + ''; + }; }; config = mkIf (xcfg.enable && cfg.enable) { + environment.systemPackages = cfg.extraPackages; + services.rpcbind.enable = true; services.xinetd.enable = true; diff --git a/nixos/modules/tasks/network-interfaces.nix b/nixos/modules/tasks/network-interfaces.nix index 44677d417ead..12cff6b038f8 100644 --- a/nixos/modules/tasks/network-interfaces.nix +++ b/nixos/modules/tasks/network-interfaces.nix @@ -376,10 +376,20 @@ in networking.hostName = mkOption { default = "nixos"; - type = types.str; + # Only allow hostnames without the domain name part (i.e. no FQDNs, see + # e.g. "man 5 hostname") and require valid DNS labels (recommended + # syntax). Note: We also allow underscores for compatibility/legacy + # reasons (as undocumented feature): + type = types.strMatching + "^[[:alpha:]]([[:alnum:]_-]{0,61}[[:alnum:]])?$"; description = '' - The name of the machine. Leave it empty if you want to obtain - it from a DHCP server (if using DHCP). + The name of the machine. Leave it empty if you want to obtain it from a + DHCP server (if using DHCP). The hostname must be a valid DNS label (see + RFC 1035 section 2.3.1: "Preferred name syntax") and as such must not + contain the domain part. This means that the hostname must start with a + letter, end with a letter or digit, and have as interior characters only + letters, digits, and hyphen. The maximum length is 63 characters. + Additionally it is recommended to only use lower-case characters. ''; }; diff --git a/nixos/modules/virtualisation/cri-o.nix b/nixos/modules/virtualisation/cri-o.nix index 2af4214302d6..f267c97b1788 100644 --- a/nixos/modules/virtualisation/cri-o.nix +++ b/nixos/modules/virtualisation/cri-o.nix @@ -5,6 +5,8 @@ with lib; let cfg = config.virtualisation.cri-o; + crioPackage = (pkgs.cri-o.override { inherit (cfg) extraPackages; }); + # Copy configuration files to avoid having the entire sources in the system closure copyFile = filePath: pkgs.runCommandNoCC (builtins.unsafeDiscardStringContext (builtins.baseNameOf filePath)) {} '' cp ${filePath} $out @@ -23,55 +25,90 @@ in enable = mkEnableOption "Container Runtime Interface for OCI (CRI-O)"; storageDriver = mkOption { - type = types.enum ["btrfs" "overlay" "vfs"]; + type = types.enum [ "btrfs" "overlay" "vfs" ]; default = "overlay"; description = "Storage driver to be used"; }; logLevel = mkOption { - type = types.enum ["trace" "debug" "info" "warn" "error" "fatal"]; + type = types.enum [ "trace" "debug" "info" "warn" "error" "fatal" ]; default = "info"; description = "Log level to be used"; }; pauseImage = mkOption { - type = types.str; - default = "k8s.gcr.io/pause:3.1"; - description = "Pause image for pod sandboxes to be used"; + type = types.nullOr types.str; + default = null; + description = "Override the default pause image for pod sandboxes"; + example = [ "k8s.gcr.io/pause:3.2" ]; }; pauseCommand = mkOption { - type = types.str; - default = "/pause"; - description = "Pause command to be executed"; + type = types.nullOr types.str; + default = null; + description = "Override the default pause command"; + example = [ "/pause" ]; + }; + + runtime = mkOption { + type = types.nullOr types.str; + default = null; + description = "Override the default runtime"; + example = [ "crun" ]; + }; + + extraPackages = mkOption { + type = with types; listOf package; + default = [ ]; + example = lib.literalExample '' + [ + pkgs.gvisor + ] + ''; + description = '' + Extra packages to be installed in the CRI-O wrapper. + ''; + }; + + package = lib.mkOption { + type = types.package; + default = crioPackage; + internal = true; + description = '' + The final CRI-O package (including extra packages). + ''; }; }; config = mkIf cfg.enable { - environment.systemPackages = with pkgs; - [ cri-o cri-tools conmon iptables runc utillinux ]; + environment.systemPackages = [ cfg.package pkgs.cri-tools ]; - environment.etc."crictl.yaml".source = copyFile "${pkgs.cri-o.src}/crictl.yaml"; + environment.etc."crictl.yaml".source = copyFile "${pkgs.cri-o-unwrapped.src}/crictl.yaml"; environment.etc."crio/crio.conf".text = '' [crio] storage_driver = "${cfg.storageDriver}" [crio.image] - pause_image = "${cfg.pauseImage}" - pause_command = "${cfg.pauseCommand}" + ${optionalString (cfg.pauseImage != null) ''pause_image = "${cfg.pauseImage}"''} + ${optionalString (cfg.pauseCommand != null) ''pause_command = "${cfg.pauseCommand}"''} [crio.network] plugin_dirs = ["${pkgs.cni-plugins}/bin/"] - network_dir = "/etc/cni/net.d/" [crio.runtime] - conmon = "${pkgs.conmon}/bin/conmon" + cgroup_manager = "systemd" log_level = "${cfg.logLevel}" - manage_network_ns_lifecycle = true + manage_ns_lifecycle = true + + ${optionalString (cfg.runtime != null) '' + default_runtime = "${cfg.runtime}" + [crio.runtime.runtimes] + [crio.runtime.runtimes.${cfg.runtime}] + ''} ''; - environment.etc."cni/net.d/10-crio-bridge.conf".source = copyFile "${pkgs.cri-o.src}/contrib/cni/10-crio-bridge.conf"; + environment.etc."cni/net.d/10-crio-bridge.conf".source = copyFile "${pkgs.cri-o-unwrapped.src}/contrib/cni/10-crio-bridge.conf"; # Enable common /etc/containers configuration virtualisation.containers.enable = true; @@ -81,10 +118,10 @@ in documentation = [ "https://github.com/cri-o/cri-o" ]; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; - path = [ pkgs.utillinux pkgs.runc pkgs.iptables ]; + path = [ cfg.package ]; serviceConfig = { Type = "notify"; - ExecStart = "${pkgs.cri-o}/bin/crio"; + ExecStart = "${cfg.package}/bin/crio"; ExecReload = "/bin/kill -s HUP $MAINPID"; TasksMax = "infinity"; LimitNOFILE = "1048576"; diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index af619ac99a32..47ca015632c7 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -87,6 +87,7 @@ in ecryptfs = handleTest ./ecryptfs.nix {}; ejabberd = handleTest ./xmpp/ejabberd.nix {}; elk = handleTestOn ["x86_64-linux"] ./elk.nix {}; + engelsystem = handleTest ./engelsystem.nix {}; enlightenment = handleTest ./enlightenment.nix {}; env = handleTest ./env.nix {}; etcd = handleTestOn ["x86_64-linux"] ./etcd.nix {}; @@ -133,6 +134,7 @@ in hitch = handleTest ./hitch {}; hocker-fetchdocker = handleTest ./hocker-fetchdocker {}; home-assistant = handleTest ./home-assistant.nix {}; + hostname = handleTest ./hostname.nix {}; hound = handleTest ./hound.nix {}; hydra = handleTest ./hydra {}; hydra-db-migration = handleTest ./hydra/db-migration.nix {}; diff --git a/nixos/tests/engelsystem.nix b/nixos/tests/engelsystem.nix new file mode 100644 index 000000000000..39c10718093f --- /dev/null +++ b/nixos/tests/engelsystem.nix @@ -0,0 +1,41 @@ +import ./make-test-python.nix ( + { pkgs, lib, ... }: + { + name = "engelsystem"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ talyz ]; + }; + + nodes.engelsystem = + { ... }: + { + services.engelsystem = { + enable = true; + domain = "engelsystem"; + createDatabase = true; + }; + networking.firewall.allowedTCPPorts = [ 80 443 ]; + environment.systemPackages = with pkgs; [ + xmlstarlet + libxml2 + ]; + }; + + testScript = '' + engelsystem.start() + engelsystem.wait_for_unit("phpfpm-engelsystem.service") + engelsystem.wait_until_succeeds("curl engelsystem/login -sS -f") + engelsystem.succeed( + "curl engelsystem/login -sS -f -c cookie | xmllint -html -xmlout - >login" + ) + engelsystem.succeed( + "xml sel -T -t -m \"html/head/meta[@name='csrf-token']\" -v @content login >token" + ) + engelsystem.succeed( + "curl engelsystem/login -sS -f -b cookie -F 'login=admin' -F 'password=asdfasdf' -F '_token=<token' -L | xmllint -html -xmlout - >news" + ) + engelsystem.succeed( + "test 'News - Engelsystem' = \"$(xml sel -T -t -c html/head/title news)\"" + ) + ''; + }) diff --git a/nixos/tests/hostname.nix b/nixos/tests/hostname.nix new file mode 100644 index 000000000000..3b87303d73e7 --- /dev/null +++ b/nixos/tests/hostname.nix @@ -0,0 +1,66 @@ +{ system ? builtins.currentSystem, + config ? {}, + pkgs ? import ../.. { inherit system config; } +}: + +with import ../lib/testing-python.nix { inherit system pkgs; }; +with pkgs.lib; + +let + makeHostNameTest = hostName: domain: + let + fqdn = hostName + (optionalString (domain != null) ".${domain}"); + in + makeTest { + name = "hostname-${fqdn}"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ primeos blitz ]; + }; + + machine = { lib, ... }: { + networking.hostName = hostName; + networking.domain = domain; + + environment.systemPackages = with pkgs; [ + inetutils + ]; + }; + + testScript = '' + start_all() + + machine = ${hostName} + + machine.wait_for_unit("network-online.target") + + # The FQDN, domain name, and hostname detection should work as expected: + assert "${fqdn}" == machine.succeed("hostname --fqdn").strip() + assert "${optionalString (domain != null) domain}" == machine.succeed("dnsdomainname").strip() + assert ( + "${hostName}" + == machine.succeed( + 'hostnamectl status | grep "Static hostname" | cut -d: -f2' + ).strip() + ) + + # 127.0.0.1 and ::1 should resolve back to "localhost": + assert ( + "localhost" == machine.succeed("getent hosts 127.0.0.1 | awk '{print $2}'").strip() + ) + assert "localhost" == machine.succeed("getent hosts ::1 | awk '{print $2}'").strip() + + # 127.0.0.2 should resolve back to the FQDN and hostname: + fqdn_and_host_name = "${optionalString (domain != null) "${hostName}.${domain} "}${hostName}" + assert ( + fqdn_and_host_name + == machine.succeed("getent hosts 127.0.0.2 | awk '{print $2,$3}'").strip() + ) + ''; + }; + +in +{ + noExplicitDomain = makeHostNameTest "ahost" null; + + explicitDomain = makeHostNameTest "ahost" "adomain"; +} |