diff options
Diffstat (limited to 'nixos/modules/services')
19 files changed, 245 insertions, 69 deletions
diff --git a/nixos/modules/services/audio/wyoming/faster-whisper.nix b/nixos/modules/services/audio/wyoming/faster-whisper.nix index f156e8314a95..2d56acdc1b4c 100644 --- a/nixos/modules/services/audio/wyoming/faster-whisper.nix +++ b/nixos/modules/services/audio/wyoming/faster-whisper.nix @@ -146,6 +146,8 @@ in CapabilityBoundingSet = ""; DeviceAllow = if builtins.elem options.device [ "cuda" "auto" ] then [ # https://docs.nvidia.com/dgx/pdf/dgx-os-5-user-guide.pdf + # CUDA not working? Check DeviceAllow and PrivateDevices first! + "/dev/nvidia0" "/dev/nvidia1" "/dev/nvidia2" "/dev/nvidia3" @@ -160,7 +162,6 @@ in DevicePolicy = "closed"; LockPersonality = true; MemoryDenyWriteExecute = true; - PrivateDevices = true; PrivateUsers = true; ProtectHome = true; ProtectHostname = true; diff --git a/nixos/modules/services/backup/restic.nix b/nixos/modules/services/backup/restic.nix index 49a55d056014..87595f39796d 100644 --- a/nixos/modules/services/backup/restic.nix +++ b/nixos/modules/services/backup/restic.nix @@ -133,13 +133,15 @@ in }; timerConfig = mkOption { - type = types.attrsOf unitOption; + type = types.nullOr (types.attrsOf unitOption); default = { OnCalendar = "daily"; Persistent = true; }; description = lib.mdDoc '' - When to run the backup. See {manpage}`systemd.timer(5)` for details. + When to run the backup. See {manpage}`systemd.timer(5)` for + details. If null no timer is created and the backup will only + run when explicitly started. ''; example = { OnCalendar = "00:05"; @@ -345,7 +347,7 @@ in } // optionalAttrs (backup.environmentFile != null) { EnvironmentFile = backup.environmentFile; }; - } // optionalAttrs (backup.initialize || backup.dynamicFilesFrom != null || backup.backupPrepareCommand != null) { + } // optionalAttrs (backup.initialize || doBackup || backup.backupPrepareCommand != null) { preStart = '' ${optionalString (backup.backupPrepareCommand != null) '' ${pkgs.writeScript "backupPrepareCommand" backup.backupPrepareCommand} @@ -360,12 +362,12 @@ in ${pkgs.writeScript "dynamicFilesFromScript" backup.dynamicFilesFrom} >> ${filesFromTmpFile} ''} ''; - } // optionalAttrs (backup.dynamicFilesFrom != null || backup.backupCleanupCommand != null) { + } // optionalAttrs (doBackup || backup.backupCleanupCommand != null) { postStop = '' ${optionalString (backup.backupCleanupCommand != null) '' ${pkgs.writeScript "backupCleanupCommand" backup.backupCleanupCommand} ''} - ${optionalString (backup.dynamicFilesFrom != null) '' + ${optionalString doBackup '' rm ${filesFromTmpFile} ''} ''; @@ -378,7 +380,7 @@ in wantedBy = [ "timers.target" ]; timerConfig = backup.timerConfig; }) - config.services.restic.backups; + (filterAttrs (_: backup: backup.timerConfig != null) config.services.restic.backups); # generate wrapper scripts, as described in the createWrapper option environment.systemPackages = lib.mapAttrsToList (name: backup: let diff --git a/nixos/modules/services/backup/syncoid.nix b/nixos/modules/services/backup/syncoid.nix index 0f375455e7ed..1a1df38617b5 100644 --- a/nixos/modules/services/backup/syncoid.nix +++ b/nixos/modules/services/backup/syncoid.nix @@ -369,7 +369,7 @@ in PrivateDevices = true; PrivateMounts = true; PrivateNetwork = mkDefault false; - PrivateUsers = true; + PrivateUsers = false; # Enabling this breaks on zfs-2.2.0 ProtectClock = true; ProtectControlGroups = true; ProtectHome = true; diff --git a/nixos/modules/services/home-automation/zwave-js.nix b/nixos/modules/services/home-automation/zwave-js.nix new file mode 100644 index 000000000000..87c9b8f1ac81 --- /dev/null +++ b/nixos/modules/services/home-automation/zwave-js.nix @@ -0,0 +1,152 @@ +{config, pkgs, lib, ...}: + +with lib; + +let + cfg = config.services.zwave-js; + mergedConfigFile = "/run/zwave-js/config.json"; + settingsFormat = pkgs.formats.json {}; +in { + options.services.zwave-js = { + enable = mkEnableOption (mdDoc "the zwave-js server on boot"); + + package = mkPackageOptionMD pkgs "zwave-js-server" { }; + + port = mkOption { + type = types.port; + default = 3000; + description = mdDoc '' + Port for the server to listen on. + ''; + }; + + serialPort = mkOption { + type = types.path; + description = mdDoc '' + Serial port device path for Z-Wave controller. + ''; + example = "/dev/ttyUSB0"; + }; + + secretsConfigFile = mkOption { + type = types.path; + description = mdDoc '' + JSON file containing secret keys. A dummy example: + + ``` + { + "securityKeys": { + "S0_Legacy": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "S2_Unauthenticated": "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB", + "S2_Authenticated": "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC", + "S2_AccessControl": "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD" + } + } + ``` + + See + <https://zwave-js.github.io/node-zwave-js/#/getting-started/security-s2> + for details. This file will be merged with the module-generated config + file (taking precedence). + + Z-Wave keys can be generated with: + + {command}`< /dev/urandom tr -dc A-F0-9 | head -c32 ;echo` + + + ::: {.warning} + A file in the nix store should not be used since it will be readable to + all users. + ::: + ''; + example = "/secrets/zwave-js-keys.json"; + }; + + settings = mkOption { + type = lib.types.submodule { + freeformType = settingsFormat.type; + + options = { + storage = { + cacheDir = mkOption { + type = types.path; + default = "/var/cache/zwave-js"; + readOnly = true; + description = lib.mdDoc "Cache directory"; + }; + }; + }; + }; + default = {}; + description = mdDoc '' + Configuration settings for the generated config + file. + ''; + }; + + extraFlags = lib.mkOption { + type = with lib.types; listOf str; + default = [ ]; + example = [ "--mock-driver" ]; + description = lib.mdDoc '' + Extra flags to pass to command + ''; + }; + }; + + config = mkIf cfg.enable { + systemd.services.zwave-js = let + configFile = settingsFormat.generate "zwave-js-config.json" cfg.settings; + in { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + description = "Z-Wave JS Server"; + serviceConfig = { + ExecStartPre = '' + /bin/sh -c "${pkgs.jq}/bin/jq -s '.[0] * .[1]' ${configFile} ${cfg.secretsConfigFile} > ${mergedConfigFile}" + ''; + ExecStart = lib.concatStringsSep " " [ + "${cfg.package}/bin/zwave-server" + "--config ${mergedConfigFile}" + "--port ${toString cfg.port}" + cfg.serialPort + (escapeShellArgs cfg.extraFlags) + ]; + Restart = "on-failure"; + User = "zwave-js"; + SupplementaryGroups = [ "dialout" ]; + CacheDirectory = "zwave-js"; + RuntimeDirectory = "zwave-js"; + + # Hardening + CapabilityBoundingSet = ""; + DeviceAllow = [cfg.serialPort]; + DevicePolicy = "closed"; + DynamicUser = true; + LockPersonality = true; + MemoryDenyWriteExecute = false; + NoNewPrivileges = true; + PrivateUsers = true; + PrivateTmp = true; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + RemoveIPC = true; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ + "@system-service @pkey" + "~@privileged @resources" + ]; + UMask = "0077"; + }; + }; + }; + + meta.maintainers = with lib.maintainers; [ graham33 ]; +} diff --git a/nixos/modules/services/matrix/appservice-discord.nix b/nixos/modules/services/matrix/appservice-discord.nix index f579c2529c0a..6ce8718c35d8 100644 --- a/nixos/modules/services/matrix/appservice-discord.nix +++ b/nixos/modules/services/matrix/appservice-discord.nix @@ -100,9 +100,9 @@ in { serviceDependencies = mkOption { type = with types; listOf str; - default = optional config.services.matrix-synapse.enable "matrix-synapse.service"; + default = optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit; defaultText = literalExpression '' - optional config.services.matrix-synapse.enable "matrix-synapse.service" + optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit ''; description = lib.mdDoc '' List of Systemd services to require and wait for when starting the application service, diff --git a/nixos/modules/services/matrix/matrix-sliding-sync.nix b/nixos/modules/services/matrix/matrix-sliding-sync.nix index 7e464d6ed589..9807cde40919 100644 --- a/nixos/modules/services/matrix/matrix-sliding-sync.nix +++ b/nixos/modules/services/matrix/matrix-sliding-sync.nix @@ -80,8 +80,11 @@ in } ]; }; - systemd.services.matrix-sliding-sync = { - after = lib.optional cfg.createDatabase "postgresql.service"; + systemd.services.matrix-sliding-sync = rec { + after = + lib.optional cfg.createDatabase "postgresql.service" + ++ lib.optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit; + wants = after; wantedBy = [ "multi-user.target" ]; environment = cfg.settings; serviceConfig = { @@ -90,6 +93,8 @@ in ExecStart = lib.getExe cfg.package; StateDirectory = "matrix-sliding-sync"; WorkingDirectory = "%S/matrix-sliding-sync"; + Restart = "on-failure"; + RestartSec = "1s"; }; }; }; diff --git a/nixos/modules/services/matrix/mautrix-facebook.nix b/nixos/modules/services/matrix/mautrix-facebook.nix index bab6865496dd..671040500df8 100644 --- a/nixos/modules/services/matrix/mautrix-facebook.nix +++ b/nixos/modules/services/matrix/mautrix-facebook.nix @@ -145,7 +145,7 @@ in { wantedBy = [ "multi-user.target" ]; wants = [ "network-online.target" - ] ++ optional config.services.matrix-synapse.enable "matrix-synapse.service" + ] ++ optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit ++ optional cfg.configurePostgresql "postgresql.service"; after = wants; diff --git a/nixos/modules/services/matrix/mautrix-telegram.nix b/nixos/modules/services/matrix/mautrix-telegram.nix index 97a6ba858e00..168c8bf436ac 100644 --- a/nixos/modules/services/matrix/mautrix-telegram.nix +++ b/nixos/modules/services/matrix/mautrix-telegram.nix @@ -122,9 +122,9 @@ in { serviceDependencies = mkOption { type = with types; listOf str; - default = optional config.services.matrix-synapse.enable "matrix-synapse.service"; + default = optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit; defaultText = literalExpression '' - optional config.services.matrix-synapse.enable "matrix-synapse.service" + optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit ''; description = lib.mdDoc '' List of Systemd services to require and wait for when starting the application service. diff --git a/nixos/modules/services/matrix/mautrix-whatsapp.nix b/nixos/modules/services/matrix/mautrix-whatsapp.nix index c4dc48213495..4b561a4b07a3 100644 --- a/nixos/modules/services/matrix/mautrix-whatsapp.nix +++ b/nixos/modules/services/matrix/mautrix-whatsapp.nix @@ -100,9 +100,9 @@ in { serviceDependencies = lib.mkOption { type = with lib.types; listOf str; - default = lib.optional config.services.matrix-synapse.enable "matrix-synapse.service"; + default = lib.optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit; defaultText = lib.literalExpression '' - optional config.services.matrix-synapse.enable "matrix-synapse.service" + optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnits ''; description = lib.mdDoc '' List of Systemd services to require and wait for when starting the application service. diff --git a/nixos/modules/services/matrix/mx-puppet-discord.nix b/nixos/modules/services/matrix/mx-puppet-discord.nix index 36c9f8b122ea..70828804b556 100644 --- a/nixos/modules/services/matrix/mx-puppet-discord.nix +++ b/nixos/modules/services/matrix/mx-puppet-discord.nix @@ -66,9 +66,9 @@ in { }; serviceDependencies = mkOption { type = with types; listOf str; - default = optional config.services.matrix-synapse.enable "matrix-synapse.service"; + default = optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit; defaultText = literalExpression '' - optional config.services.matrix-synapse.enable "matrix-synapse.service" + optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit ''; description = lib.mdDoc '' List of Systemd services to require and wait for when starting the application service. diff --git a/nixos/modules/services/matrix/synapse.nix b/nixos/modules/services/matrix/synapse.nix index 12e27ef26ff3..9cc769c2d0db 100644 --- a/nixos/modules/services/matrix/synapse.nix +++ b/nixos/modules/services/matrix/synapse.nix @@ -296,6 +296,18 @@ in { services.matrix-synapse = { enable = mkEnableOption (lib.mdDoc "matrix.org synapse"); + serviceUnit = lib.mkOption { + type = lib.types.str; + readOnly = true; + description = lib.mdDoc '' + The systemd unit (a service or a target) for other services to depend on if they + need to be started after matrix-synapse. + + This option is useful as the actual parent unit for all matrix-synapse processes + changes when configuring workers. + ''; + }; + configFile = mkOption { type = types.path; readOnly = true; @@ -1021,6 +1033,7 @@ in { port = 9093; }); + services.matrix-synapse.serviceUnit = if hasWorkers then "matrix-synapse.target" else "matrix-synapse.service"; services.matrix-synapse.configFile = configFile; services.matrix-synapse.package = wrapped; diff --git a/nixos/modules/services/monitoring/netdata.nix b/nixos/modules/services/monitoring/netdata.nix index 3833418b5add..de0e044453ee 100644 --- a/nixos/modules/services/monitoring/netdata.nix +++ b/nixos/modules/services/monitoring/netdata.nix @@ -12,6 +12,7 @@ let ln -s /run/wrappers/bin/perf.plugin $out/libexec/netdata/plugins.d/perf.plugin ln -s /run/wrappers/bin/slabinfo.plugin $out/libexec/netdata/plugins.d/slabinfo.plugin ln -s /run/wrappers/bin/freeipmi.plugin $out/libexec/netdata/plugins.d/freeipmi.plugin + ln -s /run/wrappers/bin/systemd-journal.plugin $out/libexec/netdata/plugins.d/systemd-journal.plugin ''; plugins = [ @@ -254,7 +255,7 @@ in { # Capabilities CapabilityBoundingSet = [ "CAP_DAC_OVERRIDE" # is required for freeipmi and slabinfo plugins - "CAP_DAC_READ_SEARCH" # is required for apps plugin + "CAP_DAC_READ_SEARCH" # is required for apps and systemd-journal plugin "CAP_FOWNER" # is required for freeipmi plugin "CAP_SETPCAP" # is required for apps, perf and slabinfo plugins "CAP_SYS_ADMIN" # is required for perf plugin @@ -263,6 +264,7 @@ in { "CAP_NET_RAW" # is required for fping app "CAP_SYS_CHROOT" # is required for cgroups plugin "CAP_SETUID" # is required for cgroups and cgroups-network plugins + "CAP_SYSLOG" # is required for systemd-journal plugin ]; # Sandboxing ProtectSystem = "full"; @@ -318,6 +320,14 @@ in { permissions = "u+rx,g+x,o-rwx"; }; + "systemd-journal.plugin" = { + source = "${cfg.package}/libexec/netdata/plugins.d/systemd-journal.plugin.org"; + capabilities = "cap_dac_read_search,cap_syslog+ep"; + owner = cfg.user; + group = cfg.group; + permissions = "u+rx,g+x,o-rwx"; + }; + "slabinfo.plugin" = { source = "${cfg.package}/libexec/netdata/plugins.d/slabinfo.plugin.org"; capabilities = "cap_dac_override+ep"; diff --git a/nixos/modules/services/monitoring/smartd.nix b/nixos/modules/services/monitoring/smartd.nix index 1e654cad5dd2..8b79ac0e0c1e 100644 --- a/nixos/modules/services/monitoring/smartd.nix +++ b/nixos/modules/services/monitoring/smartd.nix @@ -19,7 +19,7 @@ let { ${pkgs.coreutils}/bin/cat << EOF From: smartd on ${host} <${nm.sender}> - To: undisclosed-recipients:; + To: ${nm.recipient} Subject: $SMARTD_SUBJECT $SMARTD_FULLMESSAGE diff --git a/nixos/modules/services/networking/hostapd.nix b/nixos/modules/services/networking/hostapd.nix index ffb154463053..5bd8e1d4d7a0 100644 --- a/nixos/modules/services/networking/hostapd.nix +++ b/nixos/modules/services/networking/hostapd.nix @@ -899,25 +899,6 @@ in { ''; }; }; - - managementFrameProtection = mkOption { - default = "required"; - type = types.enum ["disabled" "optional" "required"]; - apply = x: - getAttr x { - "disabled" = 0; - "optional" = 1; - "required" = 2; - }; - description = mdDoc '' - Management frame protection (MFP) authenticates management frames - to prevent deauthentication (or related) attacks. - - - {var}`"disabled"`: No management frame protection - - {var}`"optional"`: Use MFP if a connection allows it - - {var}`"required"`: Force MFP for all clients - ''; - }; }; config = let @@ -943,7 +924,8 @@ in { # IEEE 802.11i (authentication) related configuration # Encrypt management frames to protect against deauthentication and similar attacks - ieee80211w = bssCfg.managementFrameProtection; + ieee80211w = mkDefault 1; + sae_require_mfp = mkDefault 1; # Only allow WPA by default and disable insecure WEP auth_algs = mkDefault 1; @@ -1185,14 +1167,6 @@ in { message = ''hostapd radio ${radio} bss ${bss}: bssid must be specified manually (for now) since this radio uses multiple BSS.''; } { - assertion = auth.mode == "wpa3-sae" -> bssCfg.managementFrameProtection == 2; - message = ''hostapd radio ${radio} bss ${bss}: uses WPA3-SAE which requires managementFrameProtection="required"''; - } - { - assertion = auth.mode == "wpa3-sae-transition" -> bssCfg.managementFrameProtection != 0; - message = ''hostapd radio ${radio} bss ${bss}: uses WPA3-SAE in transition mode with WPA2-SHA256, which requires managementFrameProtection="optional" or ="required"''; - } - { assertion = countWpaPasswordDefinitions <= 1; message = ''hostapd radio ${radio} bss ${bss}: must use at most one WPA password option (wpaPassword, wpaPasswordFile, wpaPskFile)''; } diff --git a/nixos/modules/services/networking/prosody.nix b/nixos/modules/services/networking/prosody.nix index 0066c77438f4..038d574bd878 100644 --- a/nixos/modules/services/networking/prosody.nix +++ b/nixos/modules/services/networking/prosody.nix @@ -779,9 +779,6 @@ in admins = ${toLua cfg.admins} - -- we already build with libevent, so we can just enable it for a more performant server - use_libevent = true - modules_enabled = { ${ lib.concatStringsSep "\n " (lib.mapAttrsToList diff --git a/nixos/modules/services/networking/trust-dns.nix b/nixos/modules/services/networking/trust-dns.nix index 4196d124a2ab..758e33f16d38 100644 --- a/nixos/modules/services/networking/trust-dns.nix +++ b/nixos/modules/services/networking/trust-dns.nix @@ -54,7 +54,7 @@ in defaultText = "pkgs.trust-dns"; description = mdDoc '' Trust-dns package to use. - Only `bin/trust-dns` need be provided: the other trust-dns utilities (client and resolver) are not needed. + The package must provide `meta.mainProgram` which names the server binary; any other utilities (client, resolver) are not needed. ''; }; quiet = mkOption { @@ -135,7 +135,7 @@ in flags = (lib.optional cfg.debug "--debug") ++ (lib.optional cfg.quiet "--quiet"); flagsStr = builtins.concatStringsSep " " flags; in '' - ${cfg.package}/bin/trust-dns --config ${configFile} ${flagsStr} + ${cfg.package}/bin/${cfg.package.meta.mainProgram} --config ${configFile} ${flagsStr} ''; Type = "simple"; Restart = "on-failure"; diff --git a/nixos/modules/services/networking/wireguard.nix b/nixos/modules/services/networking/wireguard.nix index d4099be12a27..d36be87daf60 100644 --- a/nixos/modules/services/networking/wireguard.nix +++ b/nixos/modules/services/networking/wireguard.nix @@ -586,6 +586,7 @@ in }) all_peers; boot.extraModulePackages = optional (versionOlder kernel.kernel.version "5.6") kernel.wireguard; + boot.kernelModules = [ "wireguard" ]; environment.systemPackages = [ pkgs.wireguard-tools ]; systemd.services = diff --git a/nixos/modules/services/printing/cupsd.nix b/nixos/modules/services/printing/cupsd.nix index 279b26bb8957..25367f8e61d4 100644 --- a/nixos/modules/services/printing/cupsd.nix +++ b/nixos/modules/services/printing/cupsd.nix @@ -108,6 +108,13 @@ let containsGutenprint = pkgs: length (filterGutenprint pkgs) > 0; getGutenprint = pkgs: head (filterGutenprint pkgs); + parsePorts = addresses: let + splitAddress = addr: lib.strings.splitString ":" addr; + extractPort = addr: builtins.elemAt (builtins.tail (splitAddress addr)) 0; + toInt = str: lib.strings.toInt str; + in + builtins.map (address: toInt (extractPort address)) addresses; + in { @@ -172,6 +179,15 @@ in ''; }; + openFirewall = mkOption { + type = types.bool; + default = false; + description = '' + Whether to open the firewall for TCP/UDP ports specified in + listenAdrresses option. + ''; + }; + bindirCmds = mkOption { type = types.lines; internal = true; @@ -463,6 +479,13 @@ in security.pam.services.cups = {}; + networking.firewall = let + listenPorts = parsePorts cfg.listenAddresses; + in mkIf cfg.openFirewall { + allowedTCPPorts = listenPorts; + allowedUDPPorts = listenPorts; + }; + }; meta.maintainers = with lib.maintainers; [ matthewbauer ]; diff --git a/nixos/modules/services/web-apps/mediawiki.nix b/nixos/modules/services/web-apps/mediawiki.nix index c5fb03766899..8b494b7c1208 100644 --- a/nixos/modules/services/web-apps/mediawiki.nix +++ b/nixos/modules/services/web-apps/mediawiki.nix @@ -493,6 +493,8 @@ in services.phpfpm.pools.mediawiki = { inherit user group; phpEnv.MEDIAWIKI_CONFIG = "${mediawikiConfig}"; + # https://www.mediawiki.org/wiki/Compatibility + phpPackage = pkgs.php81; settings = (if (cfg.webserver == "apache") then { "listen.owner" = config.services.httpd.user; "listen.group" = config.services.httpd.group; @@ -552,24 +554,20 @@ in deny all; ''; # MediaWiki assets (usually images) - "~ ^/w/resources/(assets|lib|src)" = { - tryFiles = "$uri =404"; - extraConfig = '' - add_header Cache-Control "public"; - expires 7d; - ''; - }; + "~ ^/w/resources/(assets|lib|src)".extraConfig = '' + rewrite ^/w(/.*) $1 break; + add_header Cache-Control "public"; + expires 7d; + ''; # Assets, scripts and styles from skins and extensions - "~ ^/w/(skins|extensions)/.+\\.(css|js|gif|jpg|jpeg|png|svg|wasm|ttf|woff|woff2)$" = { - tryFiles = "$uri =404"; - extraConfig = '' - add_header Cache-Control "public"; - expires 7d; - ''; - }; + "~ ^/w/(skins|extensions)/.+\\.(css|js|gif|jpg|jpeg|png|svg|wasm|ttf|woff|woff2)$".extraConfig = '' + rewrite ^/w(/.*) $1 break; + add_header Cache-Control "public"; + expires 7d; + ''; # Handling for Mediawiki REST API, see [[mw:API:REST_API]] - "/w/rest.php".tryFiles = "$uri $uri/ /rest.php?$query_string"; + "/w/rest.php/".tryFiles = "$uri $uri/ /w/rest.php?$query_string"; # Handling for the article path (pretty URLs) "/wiki/".extraConfig = '' |