diff options
Diffstat (limited to 'nixos')
19 files changed, 425 insertions, 217 deletions
diff --git a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml index cd8f9e316412..29973bd401fc 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml @@ -22,7 +22,7 @@ </listitem> <listitem> <para> - kOps now defaults to 1.21.0, which uses containerd as the + kOps now defaults to 1.21.1, which uses containerd as the default runtime. </para> </listitem> diff --git a/nixos/doc/manual/release-notes/rl-2111.section.md b/nixos/doc/manual/release-notes/rl-2111.section.md index 0bc35cdb643a..c115ee9513df 100644 --- a/nixos/doc/manual/release-notes/rl-2111.section.md +++ b/nixos/doc/manual/release-notes/rl-2111.section.md @@ -7,7 +7,8 @@ In addition to numerous new and upgraded packages, this release has the followin ## Highlights {#sec-release-21.11-highlights} - PHP now defaults to PHP 8.0, updated from 7.4. -- kOps now defaults to 1.21.0, which uses containerd as the default runtime. + +- kOps now defaults to 1.21.1, which uses containerd as the default runtime. - `python3` now defaults to Python 3.9, updated from Python 3.8. diff --git a/nixos/modules/config/fonts/fonts.nix b/nixos/modules/config/fonts/fonts.nix index 60a0885103d2..f87e61e3ef9f 100644 --- a/nixos/modules/config/fonts/fonts.nix +++ b/nixos/modules/config/fonts/fonts.nix @@ -8,7 +8,7 @@ let # If not running a fancy desktop environment, the cursor is likely set to # the default `cursor.pcf` bitmap font. This is 17px wide, so it's very # small and almost invisible on 4K displays. - fontcursormisc_hidpi = pkgs.xorg.fontcursormisc.overrideAttrs (old: + fontcursormisc_hidpi = pkgs.xorg.fontxfree86type1.overrideAttrs (old: let # The scaling constant is 230/96: the scalable `left_ptr` glyph at # about 23 points is rendered as 17px, on a 96dpi display. diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix index 1e125eced2cb..cf87ca5377dd 100644 --- a/nixos/modules/hardware/video/nvidia.nix +++ b/nixos/modules/hardware/video/nvidia.nix @@ -23,6 +23,7 @@ let offloadCfg = pCfg.offload; primeEnabled = syncCfg.enable || offloadCfg.enable; nvidiaPersistencedEnabled = cfg.nvidiaPersistenced; + nvidiaSettings = cfg.nvidiaSettings; in { @@ -143,6 +144,15 @@ in ''; }; + hardware.nvidia.nvidiaSettings = mkOption { + default = true; + type = types.bool; + description = '' + Whether to add nvidia-settings, NVIDIA's GUI configuration tool, to + systemPackages. + ''; + }; + hardware.nvidia.nvidiaPersistenced = mkOption { default = false; type = types.bool; @@ -279,7 +289,8 @@ in hardware.opengl.extraPackages = optional offloadCfg.enable nvidia_x11.out; hardware.opengl.extraPackages32 = optional offloadCfg.enable nvidia_x11.lib32; - environment.systemPackages = [ nvidia_x11.bin nvidia_x11.settings ] + environment.systemPackages = [ nvidia_x11.bin ] + ++ optionals nvidiaSettings [ nvidia_x11.settings ] ++ optionals nvidiaPersistencedEnabled [ nvidia_x11.persistenced ]; systemd.packages = optional cfg.powerManagement.enable nvidia_x11.out; diff --git a/nixos/modules/services/amqp/rabbitmq.nix b/nixos/modules/services/amqp/rabbitmq.nix index fc8a1bc3c23c..8fdfda9a66d8 100644 --- a/nixos/modules/services/amqp/rabbitmq.nix +++ b/nixos/modules/services/amqp/rabbitmq.nix @@ -7,12 +7,13 @@ let inherit (builtins) concatStringsSep; - config_file_content = lib.generators.toKeyValue {} cfg.configItems; + config_file_content = lib.generators.toKeyValue { } cfg.configItems; config_file = pkgs.writeText "rabbitmq.conf" config_file_content; advanced_config_file = pkgs.writeText "advanced.config" cfg.config; -in { +in +{ ###### interface options = { services.rabbitmq = { @@ -79,7 +80,7 @@ in { }; configItems = mkOption { - default = {}; + default = { }; type = types.attrsOf types.str; example = literalExample '' { @@ -123,16 +124,38 @@ in { }; plugins = mkOption { - default = []; + default = [ ]; type = types.listOf types.str; description = "The names of plugins to enable"; }; pluginDirs = mkOption { - default = []; + default = [ ]; type = types.listOf types.path; description = "The list of directories containing external plugins"; }; + + managementPlugin = mkOption { + description = "The options to run the management plugin"; + type = types.submodule { + options = { + enable = mkOption { + default = false; + type = types.bool; + description = '' + Whether to enable the management plugin + ''; + }; + port = mkOption { + default = 15672; + type = types.port; + description = '' + On which port to run the management plugin + ''; + }; + }; + }; + }; }; }; @@ -157,8 +180,13 @@ in { services.rabbitmq.configItems = { "listeners.tcp.1" = mkDefault "${cfg.listenAddress}:${toString cfg.port}"; + } // optionalAttrs cfg.managementPlugin.enable { + "management.tcp.port" = toString cfg.managementPlugin.port; + "management.tcp.ip" = cfg.listenAddress; }; + services.rabbitmq.plugins = optional cfg.managementPlugin.enable "rabbitmq_management"; + systemd.services.rabbitmq = { description = "RabbitMQ Server"; @@ -180,7 +208,7 @@ in { RABBITMQ_ENABLED_PLUGINS_FILE = pkgs.writeText "enabled_plugins" '' [ ${concatStringsSep "," cfg.plugins} ]. ''; - } // optionalAttrs (cfg.config != "") { RABBITMQ_ADVANCED_CONFIG_FILE = advanced_config_file; }; + } // optionalAttrs (cfg.config != "") { RABBITMQ_ADVANCED_CONFIG_FILE = advanced_config_file; }; serviceConfig = { ExecStart = "${cfg.package}/sbin/rabbitmq-server"; diff --git a/nixos/modules/services/audio/roon-bridge.nix b/nixos/modules/services/audio/roon-bridge.nix index 85273a2039c3..e08f8a4f9e7a 100644 --- a/nixos/modules/services/audio/roon-bridge.nix +++ b/nixos/modules/services/audio/roon-bridge.nix @@ -14,9 +14,6 @@ in { default = false; description = '' Open ports in the firewall for the bridge. - - UDP: 9003 - TCP: 9100 - 9200 ''; }; user = mkOption { @@ -54,10 +51,15 @@ in { }; networking.firewall = mkIf cfg.openFirewall { - allowedTCPPortRanges = [ - { from = 9100; to = 9200; } - ]; + allowedTCPPortRanges = [{ from = 9100; to = 9200; }]; allowedUDPPorts = [ 9003 ]; + extraCommands = '' + iptables -A INPUT -s 224.0.0.0/4 -j ACCEPT + iptables -A INPUT -d 224.0.0.0/4 -j ACCEPT + iptables -A INPUT -s 240.0.0.0/5 -j ACCEPT + iptables -A INPUT -m pkttype --pkt-type multicast -j ACCEPT + iptables -A INPUT -m pkttype --pkt-type broadcast -j ACCEPT + ''; }; diff --git a/nixos/modules/services/audio/roon-server.nix b/nixos/modules/services/audio/roon-server.nix index eceb65044c5b..42da5a100170 100644 --- a/nixos/modules/services/audio/roon-server.nix +++ b/nixos/modules/services/audio/roon-server.nix @@ -14,9 +14,6 @@ in { default = false; description = '' Open ports in the firewall for the server. - - UDP: 9003 - TCP: 9100 - 9200 ''; }; user = mkOption { @@ -54,10 +51,15 @@ in { }; networking.firewall = mkIf cfg.openFirewall { - allowedTCPPortRanges = [ - { from = 9100; to = 9200; } - ]; + allowedTCPPortRanges = [{ from = 9100; to = 9200; }]; allowedUDPPorts = [ 9003 ]; + extraCommands = '' + iptables -A INPUT -s 224.0.0.0/4 -j ACCEPT + iptables -A INPUT -d 224.0.0.0/4 -j ACCEPT + iptables -A INPUT -s 240.0.0.0/5 -j ACCEPT + iptables -A INPUT -m pkttype --pkt-type multicast -j ACCEPT + iptables -A INPUT -m pkttype --pkt-type broadcast -j ACCEPT + ''; }; diff --git a/nixos/modules/services/desktops/pipewire/bluez-hardware.conf.json b/nixos/modules/services/desktops/pipewire/bluez-hardware.conf.json index cae9e1bdba06..46697ece4483 100644 --- a/nixos/modules/services/desktops/pipewire/bluez-hardware.conf.json +++ b/nixos/modules/services/desktops/pipewire/bluez-hardware.conf.json @@ -198,6 +198,17 @@ }, { "sysname": "Linux", + "release": "~^5\\.10\\.(1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50)($|[^0-9])" + }, + { + "sysname": "Linux", + "release": "~^5\\.10\\.", + "no-features": [ + "msbc-alt1" + ] + }, + { + "sysname": "Linux", "release": "~^5\\.12\\.(1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17)($|[^0-9])" }, { diff --git a/nixos/modules/services/desktops/pipewire/pipewire-pulse.conf.json b/nixos/modules/services/desktops/pipewire/pipewire-pulse.conf.json index 17bbbdef1179..3ed994f11145 100644 --- a/nixos/modules/services/desktops/pipewire/pipewire-pulse.conf.json +++ b/nixos/modules/services/desktops/pipewire/pipewire-pulse.conf.json @@ -37,5 +37,6 @@ } } ], + "context.exec": [], "stream.properties": {} } diff --git a/nixos/modules/services/misc/nzbget.nix b/nixos/modules/services/misc/nzbget.nix index 715ec891cd68..27c5f2e395f6 100644 --- a/nixos/modules/services/misc/nzbget.nix +++ b/nixos/modules/services/misc/nzbget.nix @@ -7,24 +7,12 @@ let pkg = pkgs.nzbget; stateDir = "/var/lib/nzbget"; configFile = "${stateDir}/nzbget.conf"; - configOpts = concatStringsSep " " (mapAttrsToList (name: value: "-o ${name}=${value}") nixosOpts); - - nixosOpts = { - # allows nzbget to run as a "simple" service - OutputMode = "loggable"; - # use journald for logging - WriteLog = "none"; - ErrorTarget = "screen"; - WarningTarget = "screen"; - InfoTarget = "screen"; - DetailTarget = "screen"; - # required paths - ConfigTemplate = "${pkg}/share/nzbget/nzbget.conf"; - WebDir = "${pkg}/share/nzbget/webui"; - # nixos handles package updates - UpdateCheck = "none"; - }; - + configOpts = concatStringsSep " " (mapAttrsToList (name: value: "-o ${name}=${escapeShellArg (toStr value)}") cfg.settings); + toStr = v: + if v == true then "yes" + else if v == false then "no" + else if isInt v then toString v + else v; in { imports = [ @@ -50,12 +38,41 @@ in default = "nzbget"; description = "Group under which NZBGet runs"; }; + + settings = mkOption { + type = with types; attrsOf (oneOf [ bool int str ]); + default = {}; + description = '' + NZBGet configuration, passed via command line using switch -o. Refer to + <link xlink:href="https://github.com/nzbget/nzbget/blob/master/nzbget.conf"/> + for details on supported values. + ''; + example = { + MainDir = "/data"; + }; + }; }; }; # implementation config = mkIf cfg.enable { + services.nzbget.settings = { + # allows nzbget to run as a "simple" service + OutputMode = "loggable"; + # use journald for logging + WriteLog = "none"; + ErrorTarget = "screen"; + WarningTarget = "screen"; + InfoTarget = "screen"; + DetailTarget = "screen"; + # required paths + ConfigTemplate = "${pkg}/share/nzbget/nzbget.conf"; + WebDir = "${pkg}/share/nzbget/webui"; + # nixos handles package updates + UpdateCheck = "none"; + }; + systemd.services.nzbget = { description = "NZBGet Daemon"; after = [ "network.target" ]; @@ -64,6 +81,7 @@ in unrar p7zip ]; + preStart = '' if [ ! -f ${configFile} ]; then ${pkgs.coreutils}/bin/install -m 0700 ${pkg}/share/nzbget/nzbget.conf ${configFile} diff --git a/nixos/modules/services/network-filesystems/ipfs.nix b/nixos/modules/services/network-filesystems/ipfs.nix index 2748571be1f7..57f5f6b006c8 100644 --- a/nixos/modules/services/network-filesystems/ipfs.nix +++ b/nixos/modules/services/network-filesystems/ipfs.nix @@ -5,36 +5,41 @@ let opt = options.services.ipfs; ipfsFlags = toString ([ - (optionalString cfg.autoMount "--mount") - (optionalString cfg.enableGC "--enable-gc") - (optionalString (cfg.serviceFdlimit != null) "--manage-fdlimit=false") - (optionalString (cfg.defaultMode == "offline") "--offline") + (optionalString cfg.autoMount "--mount") + (optionalString cfg.enableGC "--enable-gc") + (optionalString (cfg.serviceFdlimit != null) "--manage-fdlimit=false") + (optionalString (cfg.defaultMode == "offline") "--offline") (optionalString (cfg.defaultMode == "norouting") "--routing=none") ] ++ cfg.extraFlags); splitMulitaddr = addrRaw: lib.tail (lib.splitString "/" addrRaw); - multiaddrToListenStream = addrRaw: let + multiaddrToListenStream = addrRaw: + let addr = splitMulitaddr addrRaw; s = builtins.elemAt addr; - in if s 0 == "ip4" && s 2 == "tcp" - then "${s 1}:${s 3}" + in + if s 0 == "ip4" && s 2 == "tcp" + then "${s 1}:${s 3}" else if s 0 == "ip6" && s 2 == "tcp" - then "[${s 1}]:${s 3}" + then "[${s 1}]:${s 3}" else if s 0 == "unix" - then "/${lib.concatStringsSep "/" (lib.tail addr)}" + then "/${lib.concatStringsSep "/" (lib.tail addr)}" else null; # not valid for listen stream, skip - multiaddrToListenDatagram = addrRaw: let + multiaddrToListenDatagram = addrRaw: + let addr = splitMulitaddr addrRaw; s = builtins.elemAt addr; - in if s 0 == "ip4" && s 2 == "udp" - then "${s 1}:${s 3}" + in + if s 0 == "ip4" && s 2 == "udp" + then "${s 1}:${s 3}" else if s 0 == "ip6" && s 2 == "udp" - then "[${s 1}]:${s 3}" + then "[${s 1}]:${s 3}" else null; # not valid for listen datagram, skip -in { +in +{ ###### interface @@ -65,9 +70,10 @@ in { dataDir = mkOption { type = types.str; - default = if versionAtLeast config.system.stateVersion "17.09" - then "/var/lib/ipfs" - else "/var/lib/ipfs/.ipfs"; + default = + if versionAtLeast config.system.stateVersion "17.09" + then "/var/lib/ipfs" + else "/var/lib/ipfs/.ipfs"; description = "The data dir for IPFS"; }; @@ -83,6 +89,12 @@ in { description = "Whether IPFS should try to mount /ipfs and /ipns at startup."; }; + autoMigrate = mkOption { + type = types.bool; + default = true; + description = "Whether IPFS should try to run the fs-repo-migration at startup."; + }; + ipfsMountDir = mkOption { type = types.str; default = "/ipfs"; @@ -137,7 +149,7 @@ in { These are applied last, so may override configuration set by other options in this module. Keep in mind that this configuration is stateful; i.e., unsetting anything in here does not reset the value to the default! ''; - default = {}; + default = { }; example = { Datastore.StorageMax = "100GB"; Discovery.MDNS.Enabled = false; @@ -153,7 +165,7 @@ in { extraFlags = mkOption { type = types.listOf types.str; description = "Extra flags passed to the IPFS daemon"; - default = []; + default = [ ]; }; localDiscovery = mkOption { @@ -168,7 +180,7 @@ in { type = types.nullOr types.int; default = null; description = "The fdlimit for the IPFS systemd unit or <literal>null</literal> to have the daemon attempt to manage it"; - example = 64*1024; + example = 64 * 1024; }; startWhenNeeded = mkOption { @@ -186,6 +198,9 @@ in { environment.systemPackages = [ cfg.package ]; environment.variables.IPFS_PATH = cfg.dataDir; + # https://github.com/lucas-clemente/quic-go/wiki/UDP-Receive-Buffer-Size + boot.kernel.sysctl."net.core.rmem_max" = mkDefault 2500000; + programs.fuse = mkIf cfg.autoMount { userAllowOther = true; }; @@ -226,33 +241,36 @@ in { ${optionalString (! cfg.localDiscovery) "--profile=server"} else ${if cfg.localDiscovery - then "ipfs config profile apply local-discovery" - else "ipfs config profile apply server" + then "ipfs --offline config profile apply local-discovery" + else "ipfs --offline config profile apply server" } fi '' + optionalString cfg.autoMount '' ipfs --offline config Mounts.FuseAllowOther --json true ipfs --offline config Mounts.IPFS ${cfg.ipfsMountDir} ipfs --offline config Mounts.IPNS ${cfg.ipnsMountDir} + '' + optionalString cfg.autoMigrate '' + ${pkgs.ipfs-migrator}/bin/fs-repo-migrations -y '' + concatStringsSep "\n" (collect - isString - (mapAttrsRecursive - (path: value: - # Using heredoc below so that the value is never improperly quoted - '' - read value <<EOF - ${builtins.toJSON value} - EOF - ipfs --offline config --json "${concatStringsSep "." path}" "$value" - '') - ({ Addresses.API = cfg.apiAddress; - Addresses.Gateway = cfg.gatewayAddress; - Addresses.Swarm = cfg.swarmAddress; - } // - cfg.extraConfig)) - ); + isString + (mapAttrsRecursive + (path: value: + # Using heredoc below so that the value is never improperly quoted + '' + read value <<EOF + ${builtins.toJSON value} + EOF + ipfs --offline config --json "${concatStringsSep "." path}" "$value" + '') + ({ + Addresses.API = cfg.apiAddress; + Addresses.Gateway = cfg.gatewayAddress; + Addresses.Swarm = cfg.swarmAddress; + } // + cfg.extraConfig)) + ); serviceConfig = { - ExecStart = ["" "${cfg.package}/bin/ipfs daemon ${ipfsFlags}"]; + ExecStart = [ "" "${cfg.package}/bin/ipfs daemon ${ipfsFlags}" ]; User = cfg.user; Group = cfg.group; } // optionalAttrs (cfg.serviceFdlimit != null) { LimitNOFILE = cfg.serviceFdlimit; }; @@ -263,12 +281,16 @@ in { systemd.sockets.ipfs-gateway = { wantedBy = [ "sockets.target" ]; socketConfig = { - ListenStream = let + ListenStream = + let fromCfg = multiaddrToListenStream cfg.gatewayAddress; - in [ "" ] ++ lib.optional (fromCfg != null) fromCfg; - ListenDatagram = let + in + [ "" ] ++ lib.optional (fromCfg != null) fromCfg; + ListenDatagram = + let fromCfg = multiaddrToListenDatagram cfg.gatewayAddress; - in [ "" ] ++ lib.optional (fromCfg != null) fromCfg; + in + [ "" ] ++ lib.optional (fromCfg != null) fromCfg; }; }; @@ -276,9 +298,11 @@ in { wantedBy = [ "sockets.target" ]; # We also include "%t/ipfs.sock" because there is no way to put the "%t" # in the multiaddr. - socketConfig.ListenStream = let + socketConfig.ListenStream = + let fromCfg = multiaddrToListenStream cfg.apiAddress; - in [ "" "%t/ipfs.sock" ] ++ lib.optional (fromCfg != null) fromCfg; + in + [ "" "%t/ipfs.sock" ] ++ lib.optional (fromCfg != null) fromCfg; }; }; diff --git a/nixos/modules/services/networking/epmd.nix b/nixos/modules/services/networking/epmd.nix index f7cdc0fe79c0..3899d164f16a 100644 --- a/nixos/modules/services/networking/epmd.nix +++ b/nixos/modules/services/networking/epmd.nix @@ -4,9 +4,7 @@ with lib; let cfg = config.services.epmd; - in - { ###### interface options.services.epmd = { @@ -27,16 +25,31 @@ in an Erlang runtime that is already installed for other purposes. ''; }; + listenStream = mkOption + { + type = types.str; + default = "[::]:4369"; + description = '' + the listenStream used by the systemd socket. + see https://www.freedesktop.org/software/systemd/man/systemd.socket.html#ListenStream= for more informations. + use this to change the port epmd will run on. + if not defined, epmd will use "[::]:4369" + ''; + }; }; ###### implementation config = mkIf cfg.enable { + assertions = [{ + assertion = cfg.listenStream == "[::]:4369" -> config.networking.enableIPv6; + message = "epmd listens by default on ipv6, enable ipv6 or change config.services.epmd.listenStream"; + }]; systemd.sockets.epmd = rec { description = "Erlang Port Mapper Daemon Activation Socket"; wantedBy = [ "sockets.target" ]; before = wantedBy; socketConfig = { - ListenStream = "4369"; + ListenStream = cfg.listenStream; Accept = "false"; }; }; diff --git a/nixos/modules/services/networking/syncthing.nix b/nixos/modules/services/networking/syncthing.nix index 2e92fe51e90a..ebe4d89a0e7f 100644 --- a/nixos/modules/services/networking/syncthing.nix +++ b/nixos/modules/services/networking/syncthing.nix @@ -9,7 +9,7 @@ let devices = mapAttrsToList (name: device: { deviceID = device.id; - inherit (device) name addresses introducer; + inherit (device) name addresses introducer autoAcceptFolders; }) cfg.devices; folders = mapAttrsToList ( _: folder: { @@ -37,7 +37,7 @@ let do sleep 1; done curl() { - ${pkgs.curl}/bin/curl -sS -H "X-API-Key: $api_key" \ + ${pkgs.curl}/bin/curl -sSLk -H "X-API-Key: $api_key" \ --retry 1000 --retry-delay 1 --retry-all-errors \ "$@" } @@ -46,7 +46,7 @@ let old_cfg=$(curl ${cfg.guiAddress}/rest/config) # generate the new config by merging with the NixOS config options - new_cfg=$(echo "$old_cfg" | ${pkgs.jq}/bin/jq -c '. * { + new_cfg=$(printf '%s\n' "$old_cfg" | ${pkgs.jq}/bin/jq -c '. * { "devices": (${builtins.toJSON devices}${optionalString (! cfg.overrideDevices) " + .devices"}), "folders": (${builtins.toJSON folders}${optionalString (! cfg.overrideFolders) " + .folders"}) } * ${builtins.toJSON cfg.extraOptions}') @@ -149,6 +149,15 @@ in { ''; }; + autoAcceptFolders = mkOption { + type = types.bool; + default = false; + description = '' + Automatically create or share folders that this device advertises at the default path. + See <link xlink:href="https://docs.syncthing.net/users/config.html?highlight=autoaccept#config-file-format"/>. + ''; + }; + }; })); }; @@ -425,6 +434,15 @@ in { defaultText = literalExample "dataDir${optionalString cond " + \"/.config/syncthing\""}"; }; + extraFlags = mkOption { + type = types.listOf types.str; + default = []; + example = [ "--reset-deltas" ]; + description = '' + Extra flags passed to the syncthing command in the service definition. + ''; + }; + openDefaultPorts = mkOption { type = types.bool; default = false; @@ -517,7 +535,7 @@ in { ${cfg.package}/bin/syncthing \ -no-browser \ -gui-address=${cfg.guiAddress} \ - -home=${cfg.configDir} + -home=${cfg.configDir} ${escapeShellArgs cfg.extraFlags} ''; MemoryDenyWriteExecute = true; NoNewPrivileges = true; diff --git a/nixos/modules/services/web-apps/nextcloud.xml b/nixos/modules/services/web-apps/nextcloud.xml index 3af37b15dd56..ed84487d233a 100644 --- a/nixos/modules/services/web-apps/nextcloud.xml +++ b/nixos/modules/services/web-apps/nextcloud.xml @@ -84,47 +84,93 @@ </para> </section> - <section xml:id="module-services-nextcloud-pitfalls-during-upgrade"> - <title>Pitfalls</title> - - <para> - Unfortunately Nextcloud appears to be very stateful when it comes to - managing its own configuration. The config file lives in the home directory - of the <literal>nextcloud</literal> user (by default - <literal>/var/lib/nextcloud/config/config.php</literal>) and is also used to - track several states of the application (e.g. whether installed or not). - </para> - <para> - All configuration parameters are also stored in - <literal>/var/lib/nextcloud/config/override.config.php</literal> which is generated by - the module and linked from the store to ensure that all values from <literal>config.php</literal> - can be modified by the module. - However <literal>config.php</literal> manages the application's state and shouldn't be touched - manually because of that. - </para> - - <warning> - <para>Don't delete <literal>config.php</literal>! This file - tracks the application's state and a deletion can cause unwanted - side-effects!</para> - </warning> - - <warning> - <para>Don't rerun <literal>nextcloud-occ - maintenance:install</literal>! This command tries to install the application - and can cause unwanted side-effects!</para> - </warning> + <section xml:id="module-services-nextcloud-pitfalls-during-upgrade"> + <title>Common problems</title> + <itemizedlist> + <listitem> + <formalpara> + <title>General notes</title> + <para> + Unfortunately Nextcloud appears to be very stateful when it comes to + managing its own configuration. The config file lives in the home directory + of the <literal>nextcloud</literal> user (by default + <literal>/var/lib/nextcloud/config/config.php</literal>) and is also used to + track several states of the application (e.g., whether installed or not). + </para> + </formalpara> + <para> + All configuration parameters are also stored in + <filename>/var/lib/nextcloud/config/override.config.php</filename> which is generated by + the module and linked from the store to ensure that all values from + <filename>config.php</filename> can be modified by the module. + However <filename>config.php</filename> manages the application's state and shouldn't be + touched manually because of that. + </para> + <warning> + <para>Don't delete <filename>config.php</filename>! This file + tracks the application's state and a deletion can cause unwanted + side-effects!</para> + </warning> - <para> - Nextcloud doesn't allow to move more than one major-version forward. If you're e.g. on - <literal>v16</literal>, you cannot upgrade to <literal>v18</literal>, you need to upgrade to - <literal>v17</literal> first. This is ensured automatically as long as the - <link linkend="opt-system.stateVersion">stateVersion</link> is declared properly. In that case - the oldest version available (one major behind the one from the previous NixOS - release) will be selected by default and the module will generate a warning that reminds - the user to upgrade to latest Nextcloud <emphasis>after</emphasis> that deploy. - </para> + <warning> + <para>Don't rerun <literal>nextcloud-occ + maintenance:install</literal>! This command tries to install the application + and can cause unwanted side-effects!</para> + </warning> + </listitem> + <listitem> + <formalpara> + <title>Multiple version upgrades</title> + <para> + Nextcloud doesn't allow to move more than one major-version forward. E.g., if you're on + <literal>v16</literal>, you cannot upgrade to <literal>v18</literal>, you need to upgrade to + <literal>v17</literal> first. This is ensured automatically as long as the + <link linkend="opt-system.stateVersion">stateVersion</link> is declared properly. In that case + the oldest version available (one major behind the one from the previous NixOS + release) will be selected by default and the module will generate a warning that reminds + the user to upgrade to latest Nextcloud <emphasis>after</emphasis> that deploy. + </para> + </formalpara> + </listitem> + <listitem> + <formalpara> + <title><literal>Error: Command "upgrade" is not defined.</literal></title> + <para> + This error usually occurs if the initial installation + (<command>nextcloud-occ maintenance:install</command>) has failed. After that, the application + is not installed, but the upgrade is attempted to be executed. Further context can + be found in <link xlink:href="https://github.com/NixOS/nixpkgs/issues/111175">NixOS/nixpkgs#111175</link>. + </para> + </formalpara> + <para> + First of all, it makes sense to find out what went wrong by looking at the logs + of the installation via <command>journalctl -u nextcloud-setup</command> and try to fix + the underlying issue. + </para> + <itemizedlist> + <listitem> + <para> + If this occurs on an <emphasis>existing</emphasis> setup, this is most likely because + the maintenance mode is active. It can be deactivated by running + <command>nextcloud-occ maintenance:mode --off</command>. It's advisable though to + check the logs first on why the maintenance mode was activated. + </para> + </listitem> + <listitem> + <warning><para>Only perform the following measures on + <emphasis>freshly installed instances!</emphasis></para></warning> + <para> + A re-run of the installer can be forced by <emphasis>deleting</emphasis> + <filename>/var/lib/nextcloud/config/config.php</filename>. This is the only time + advisable because the fresh install doesn't have any state that can be lost. + In case that doesn't help, an entire re-creation can be forced via + <command>rm -rf ~nextcloud/</command>. + </para> + </listitem> + </itemizedlist> + </listitem> + </itemizedlist> </section> <section xml:id="module-services-nextcloud-httpd"> diff --git a/nixos/modules/services/web-apps/tt-rss.nix b/nixos/modules/services/web-apps/tt-rss.nix index ed13845915c4..bc18c824f394 100644 --- a/nixos/modules/services/web-apps/tt-rss.nix +++ b/nixos/modules/services/web-apps/tt-rss.nix @@ -6,10 +6,6 @@ let configVersion = 26; - cacheDir = "cache"; - lockDir = "lock"; - feedIconsDir = "feed-icons"; - dbPort = if cfg.database.port == null then (if cfg.database.type == "pgsql" then 5432 else 3306) else cfg.database.port; @@ -32,10 +28,10 @@ let <?php putenv('TTRSS_PHP_EXECUTABLE=${pkgs.php}/bin/php'); - putenv('TTRSS_LOCK_DIRECTORY=${lockDir}'); - putenv('TTRSS_CACHE_DIR=${cacheDir}'); - putenv('TTRSS_ICONS_DIR=${feedIconsDir}'); - putenv('TTRSS_ICONS_URL=${feedIconsDir}'); + putenv('TTRSS_LOCK_DIRECTORY=${cfg.root}/lock'); + putenv('TTRSS_CACHE_DIR=${cfg.root}/cache'); + putenv('TTRSS_ICONS_DIR=${cfg.root}/feed-icons'); + putenv('TTRSS_ICONS_URL=feed-icons'); putenv('TTRSS_SELF_URL_PATH=${cfg.selfUrlPath}'); putenv('TTRSS_MYSQL_CHARSET=UTF8'); @@ -101,6 +97,22 @@ let ${cfg.extraConfig} ''; + # tt-rss and plugins and themes and config.php + servedRoot = pkgs.runCommand "tt-rss-served-root" {} '' + cp --no-preserve=mode -r ${pkgs.tt-rss} $out + cp ${tt-rss-config} $out/config.php + ${optionalString (cfg.pluginPackages != []) '' + for plugin in ${concatStringsSep " " cfg.pluginPackages}; do + cp -r "$plugin"/* "$out/plugins.local/" + done + ''} + ${optionalString (cfg.themePackages != []) '' + for theme in ${concatStringsSep " " cfg.themePackages}; do + cp -r "$theme"/* "$out/themes.local/" + done + ''} + ''; + in { ###### interface @@ -544,12 +556,16 @@ let enable = true; virtualHosts = { ${cfg.virtualHost} = { - root = "${cfg.root}"; + root = "${cfg.root}/www"; locations."/" = { index = "index.php"; }; + locations."^~ /feed-icons" = { + root = "${cfg.root}"; + }; + locations."~ \\.php$" = { extraConfig = '' fastcgi_split_path_info ^(.+\.php)(/.+)$; @@ -562,13 +578,19 @@ let }; systemd.tmpfiles.rules = [ - "d '${cfg.root}' 0755 ${cfg.user} tt_rss - -" - "Z '${cfg.root}' 0755 ${cfg.user} tt_rss - -" + "d '${cfg.root}' 0555 ${cfg.user} tt_rss - -" + "d '${cfg.root}/lock' 0755 ${cfg.user} tt_rss - -" + "d '${cfg.root}/cache' 0755 ${cfg.user} tt_rss - -" + "d '${cfg.root}/cache/upload' 0755 ${cfg.user} tt_rss - -" + "d '${cfg.root}/cache/images' 0755 ${cfg.user} tt_rss - -" + "d '${cfg.root}/cache/export' 0755 ${cfg.user} tt_rss - -" + "d '${cfg.root}/feed-icons' 0755 ${cfg.user} tt_rss - -" + "L+ '${cfg.root}/www' - - - - ${servedRoot}" ]; systemd.services = { phpfpm-tt-rss = mkIf (cfg.pool == "${poolName}") { - restartTriggers = [ tt-rss-config pkgs.tt-rss ]; + restartTriggers = [ servedRoot ]; }; tt-rss = { @@ -594,27 +616,7 @@ let else ""; - in '' - rm -rf "${cfg.root}/*" - cp -r "${pkgs.tt-rss}/"* "${cfg.root}" - ${optionalString (cfg.pluginPackages != []) '' - for plugin in ${concatStringsSep " " cfg.pluginPackages}; do - cp -r "$plugin"/* "${cfg.root}/plugins.local/" - done - ''} - ${optionalString (cfg.themePackages != []) '' - for theme in ${concatStringsSep " " cfg.themePackages}; do - cp -r "$theme"/* "${cfg.root}/themes.local/" - done - ''} - ln -sf "${tt-rss-config}" "${cfg.root}/config.php" - chmod -R 755 "${cfg.root}" - chmod -R ug+rwX "${cfg.root}/${lockDir}" - chmod -R ug+rwX "${cfg.root}/${cacheDir}" - chmod -R ug+rwX "${cfg.root}/${feedIconsDir}" - '' - - + (optionalString (cfg.database.type == "pgsql") '' + in (optionalString (cfg.database.type == "pgsql") '' exists=$(${callSql "select count(*) > 0 from pg_tables where tableowner = user"} \ | tail -n+3 | head -n-2 | sed -e 's/[ \n\t]*//') @@ -639,7 +641,7 @@ let serviceConfig = { User = "${cfg.user}"; Group = "tt_rss"; - ExecStart = "${pkgs.php}/bin/php ${cfg.root}/update.php --daemon --quiet"; + ExecStart = "${pkgs.php}/bin/php ${cfg.root}/www/update.php --daemon --quiet"; Restart = "on-failure"; RestartSec = "60"; SyslogIdentifier = "tt-rss"; diff --git a/nixos/modules/services/x11/window-managers/clfswm.nix b/nixos/modules/services/x11/window-managers/clfswm.nix index 171660c53ac3..5015852db69f 100644 --- a/nixos/modules/services/x11/window-managers/clfswm.nix +++ b/nixos/modules/services/x11/window-managers/clfswm.nix @@ -8,17 +8,27 @@ in { options = { - services.xserver.windowManager.clfswm.enable = mkEnableOption "clfswm"; + services.xserver.windowManager.clfswm = { + enable = mkEnableOption "clfswm"; + package = mkOption { + type = types.package; + default = pkgs.lispPackages.clfswm; + defaultText = "pkgs.lispPackages.clfswm"; + description = '' + clfswm package to use. + ''; + }; + }; }; config = mkIf cfg.enable { services.xserver.windowManager.session = singleton { name = "clfswm"; start = '' - ${pkgs.lispPackages.clfswm}/bin/clfswm & + ${cfg.package}/bin/clfswm & waitPID=$! ''; }; - environment.systemPackages = [ pkgs.lispPackages.clfswm ]; + environment.systemPackages = [ cfg.package ]; }; } diff --git a/nixos/tests/caddy.nix b/nixos/tests/caddy.nix index 29b227c0409b..0902904b2086 100644 --- a/nixos/tests/caddy.nix +++ b/nixos/tests/caddy.nix @@ -50,57 +50,58 @@ import ./make-test-python.nix ({ pkgs, ... }: { }; }; }; + }; - testScript = { nodes, ... }: - let - etagSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/etag"; - justReloadSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/config-reload"; - multipleConfigs = "${nodes.webserver.config.system.build.toplevel}/specialisation/multiple-configs"; - in - '' - url = "http://localhost/example.html" - webserver.wait_for_unit("caddy") - webserver.wait_for_open_port("80") + testScript = { nodes, ... }: + let + etagSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/etag"; + justReloadSystem = "${nodes.webserver.config.system.build.toplevel}/specialisation/config-reload"; + multipleConfigs = "${nodes.webserver.config.system.build.toplevel}/specialisation/multiple-configs"; + in + '' + url = "http://localhost/example.html" + webserver.wait_for_unit("caddy") + webserver.wait_for_open_port("80") - def check_etag(url): - etag = webserver.succeed( - "curl --fail -v '{}' 2>&1 | sed -n -e \"s/^< [Ee][Tt][Aa][Gg]: *//p\"".format( - url - ) - ) - etag = etag.replace("\r\n", " ") - http_code = webserver.succeed( - "curl --fail --silent --show-error -o /dev/null -w \"%{{http_code}}\" --head -H 'If-None-Match: {}' {}".format( - etag, url - ) - ) - assert int(http_code) == 304, "HTTP code is {}, expected 304".format(http_code) - return etag + def check_etag(url): + etag = webserver.succeed( + "curl --fail -v '{}' 2>&1 | sed -n -e \"s/^< [Ee][Tt][Aa][Gg]: *//p\"".format( + url + ) + ) + etag = etag.replace("\r\n", " ") + http_code = webserver.succeed( + "curl --fail --silent --show-error -o /dev/null -w \"%{{http_code}}\" --head -H 'If-None-Match: {}' {}".format( + etag, url + ) + ) + assert int(http_code) == 304, "HTTP code is {}, expected 304".format(http_code) + return etag - with subtest("check ETag if serving Nix store paths"): - old_etag = check_etag(url) - webserver.succeed( - "${etagSystem}/bin/switch-to-configuration test >&2" - ) - webserver.sleep(1) - new_etag = check_etag(url) - assert old_etag != new_etag, "Old ETag {} is the same as {}".format( - old_etag, new_etag - ) + with subtest("check ETag if serving Nix store paths"): + old_etag = check_etag(url) + webserver.succeed( + "${etagSystem}/bin/switch-to-configuration test >&2" + ) + webserver.sleep(1) + new_etag = check_etag(url) + assert old_etag != new_etag, "Old ETag {} is the same as {}".format( + old_etag, new_etag + ) - with subtest("config is reloaded on nixos-rebuild switch"): - webserver.succeed( - "${justReloadSystem}/bin/switch-to-configuration test >&2" - ) - webserver.wait_for_open_port("8080") + with subtest("config is reloaded on nixos-rebuild switch"): + webserver.succeed( + "${justReloadSystem}/bin/switch-to-configuration test >&2" + ) + webserver.wait_for_open_port("8080") - with subtest("multiple configs are correctly merged"): - webserver.succeed( - "${multipleConfigs}/bin/switch-to-configuration test >&2" - ) - webserver.wait_for_open_port("8080") - webserver.wait_for_open_port("8081") - ''; - }) + with subtest("multiple configs are correctly merged"): + webserver.succeed( + "${multipleConfigs}/bin/switch-to-configuration test >&2" + ) + webserver.wait_for_open_port("8080") + webserver.wait_for_open_port("8081") + ''; +}) diff --git a/nixos/tests/nzbget.nix b/nixos/tests/nzbget.nix index d6111ba079c8..fe5a4bc3df91 100644 --- a/nixos/tests/nzbget.nix +++ b/nixos/tests/nzbget.nix @@ -8,13 +8,21 @@ import ./make-test-python.nix ({ pkgs, ...} : { server = { ... }: { services.nzbget.enable = true; + # provide some test settings + services.nzbget.settings = { + "MainDir" = "/var/lib/nzbget"; + "DirectRename" = true; + "DiskSpace" = 0; + "Server1.Name" = "this is a test"; + }; + # hack, don't add (unfree) unrar to nzbget's path, # so we can run this test in CI systemd.services.nzbget.path = pkgs.lib.mkForce [ pkgs.p7zip ]; }; }; - testScript = '' + testScript = { nodes, ... }: '' start_all() server.wait_for_unit("nzbget.service") @@ -26,5 +34,13 @@ import ./make-test-python.nix ({ pkgs, ...} : { server.succeed( "${pkgs.nzbget}/bin/nzbget -n -o Control_iP=127.0.0.1 -o Control_port=6789 -o Control_password=tegbzn6789 -V" ) + + config = server.succeed("${nodes.server.config.systemd.services.nzbget.serviceConfig.ExecStart} --printconfig") + + # confirm the test settings are applied + assert 'MainDir = "/var/lib/nzbget"' in config + assert 'DirectRename = "yes"' in config + assert 'DiskSpace = "0"' in config + assert 'Server1.Name = "this is a test"' in config ''; }) diff --git a/nixos/tests/rabbitmq.nix b/nixos/tests/rabbitmq.nix index 69be29b0f9e5..03f1fa46d29e 100644 --- a/nixos/tests/rabbitmq.nix +++ b/nixos/tests/rabbitmq.nix @@ -7,7 +7,10 @@ import ./make-test-python.nix ({ pkgs, ... }: { }; machine = { - services.rabbitmq.enable = true; + services.rabbitmq = { + enable = true; + managementPlugin.enable = true; + }; # Ensure there is sufficient extra disk space for rabbitmq to be happy virtualisation.diskSize = 1024; }; @@ -19,5 +22,6 @@ import ./make-test-python.nix ({ pkgs, ... }: { machine.wait_until_succeeds( 'su -s ${pkgs.runtimeShell} rabbitmq -c "rabbitmqctl status"' ) + machine.wait_for_open_port("15672") ''; }) |