diff options
author | Frederik Rietdijk <fridh@fridh.nl> | 2019-12-29 10:19:39 +0100 |
---|---|---|
committer | Frederik Rietdijk <fridh@fridh.nl> | 2019-12-29 10:19:39 +0100 |
commit | fb6652529723cbb122111b588c01bdf62edbce42 (patch) | |
tree | 0c2bc41cbc9c7cf60205eb2db56dc797eff07c3e /nixos/modules/services | |
parent | 332cfab4cee02852378d3a61f9f5035099488717 (diff) | |
parent | 62ef779f2a5050549772722665bedf52f01268d2 (diff) | |
download | nixlib-fb6652529723cbb122111b588c01bdf62edbce42.tar nixlib-fb6652529723cbb122111b588c01bdf62edbce42.tar.gz nixlib-fb6652529723cbb122111b588c01bdf62edbce42.tar.bz2 nixlib-fb6652529723cbb122111b588c01bdf62edbce42.tar.lz nixlib-fb6652529723cbb122111b588c01bdf62edbce42.tar.xz nixlib-fb6652529723cbb122111b588c01bdf62edbce42.tar.zst nixlib-fb6652529723cbb122111b588c01bdf62edbce42.zip |
Merge master into staging-next
Diffstat (limited to 'nixos/modules/services')
-rw-r--r-- | nixos/modules/services/backup/borgbackup.nix | 27 | ||||
-rw-r--r-- | nixos/modules/services/hardware/udev.nix | 4 | ||||
-rw-r--r-- | nixos/modules/services/logging/awstats.nix | 1 | ||||
-rw-r--r-- | nixos/modules/services/misc/ethminer.nix | 4 | ||||
-rw-r--r-- | nixos/modules/services/monitoring/nagios.nix | 36 | ||||
-rw-r--r-- | nixos/modules/services/networking/kresd.nix | 25 | ||||
-rw-r--r-- | nixos/modules/services/web-apps/limesurvey.nix | 88 | ||||
-rw-r--r-- | nixos/modules/services/web-apps/mediawiki.nix | 59 | ||||
-rw-r--r-- | nixos/modules/services/web-apps/moodle.nix | 54 | ||||
-rw-r--r-- | nixos/modules/services/web-apps/wordpress.nix | 80 | ||||
-rw-r--r-- | nixos/modules/services/web-apps/zabbix.nix | 54 | ||||
-rw-r--r-- | nixos/modules/services/web-servers/apache-httpd/default.nix | 398 | ||||
-rw-r--r-- | nixos/modules/services/web-servers/apache-httpd/per-server-options.nix | 401 | ||||
-rw-r--r-- | nixos/modules/services/web-servers/nginx/default.nix | 1 | ||||
-rw-r--r-- | nixos/modules/services/x11/display-managers/default.nix | 2 |
15 files changed, 685 insertions, 549 deletions
diff --git a/nixos/modules/services/backup/borgbackup.nix b/nixos/modules/services/backup/borgbackup.nix index 10d42325a6b1..a2eb80c55a8c 100644 --- a/nixos/modules/services/backup/borgbackup.nix +++ b/nixos/modules/services/backup/borgbackup.nix @@ -68,7 +68,7 @@ let { BORG_PASSPHRASE = passphrase; } else { }; - mkBackupService = name: cfg: + mkBackupService = name: cfg: let userHome = config.users.users.${cfg.user}.home; in nameValuePair "borgbackup-job-${name}" { @@ -98,6 +98,23 @@ let inherit (cfg) startAt; }; + # utility function around makeWrapper + mkWrapperDrv = { + original, name, set ? {} + }: + pkgs.runCommandNoCC "${name}-wrapper" { + buildInputs = [ pkgs.makeWrapper ]; + } (with lib; '' + makeWrapper "${original}" "$out/bin/${name}" \ + ${concatStringsSep " \\\n " (mapAttrsToList (name: value: ''--set ${name} "${value}"'') set)} + ''); + + mkBorgWrapper = name: cfg: mkWrapperDrv { + original = "${pkgs.borgbackup}/bin/borg"; + name = "borg-job-${name}"; + set = { BORG_REPO = cfg.repo; } // (mkPassEnv cfg) // cfg.environment; + }; + # Paths listed in ReadWritePaths must exist before service is started mkActivationScript = name: cfg: let @@ -176,7 +193,11 @@ in { ###### interface options.services.borgbackup.jobs = mkOption { - description = "Deduplicating backups using BorgBackup."; + description = '' + Deduplicating backups using BorgBackup. + Adding a job will cause a borg-job-NAME wrapper to be added + to your system path, so that you can perform maintenance easily. + ''; default = { }; example = literalExample '' { @@ -623,6 +644,6 @@ in { users = mkMerge (mapAttrsToList mkUsersConfig repos); - environment.systemPackages = with pkgs; [ borgbackup ]; + environment.systemPackages = with pkgs; [ borgbackup ] ++ (mapAttrsToList mkBorgWrapper jobs); }); } diff --git a/nixos/modules/services/hardware/udev.nix b/nixos/modules/services/hardware/udev.nix index 83ab93bd7cfc..50997bb9bb1b 100644 --- a/nixos/modules/services/hardware/udev.nix +++ b/nixos/modules/services/hardware/udev.nix @@ -221,8 +221,8 @@ in type = types.lines; description = '' Additional <command>hwdb</command> files. They'll be written - into file <filename>10-local.hwdb</filename>. Thus they are - read before all other files. + into file <filename>99-local.hwdb</filename>. Thus they are + read after all other files. ''; }; diff --git a/nixos/modules/services/logging/awstats.nix b/nixos/modules/services/logging/awstats.nix index d51c9a5cffab..5939d7808f7f 100644 --- a/nixos/modules/services/logging/awstats.nix +++ b/nixos/modules/services/logging/awstats.nix @@ -65,6 +65,7 @@ let "ValidHTTPCodes" = "404"; } ''; + description = "Extra configuration to be appendend to awstats.\${name}.conf."; }; webService = { diff --git a/nixos/modules/services/misc/ethminer.nix b/nixos/modules/services/misc/ethminer.nix index 2958cf214473..95afb0460fb8 100644 --- a/nixos/modules/services/misc/ethminer.nix +++ b/nixos/modules/services/misc/ethminer.nix @@ -71,7 +71,7 @@ in maxPower = mkOption { type = types.int; - default = 115; + default = 113; description = "Miner max watt usage."; }; @@ -92,7 +92,9 @@ in serviceConfig = { DynamicUser = true; + ExecStartPre = "${pkgs.ethminer}/bin/.ethminer-wrapped --list-devices"; ExecStartPost = optional (cfg.toolkit == "cuda") "+${getBin config.boot.kernelPackages.nvidia_x11}/bin/nvidia-smi -pl ${toString cfg.maxPower}"; + Restart = "always"; }; environment = { diff --git a/nixos/modules/services/monitoring/nagios.nix b/nixos/modules/services/monitoring/nagios.nix index 6a3b97769462..4128bc12030f 100644 --- a/nixos/modules/services/monitoring/nagios.nix +++ b/nixos/modules/services/monitoring/nagios.nix @@ -8,6 +8,7 @@ let nagiosState = "/var/lib/nagios"; nagiosLogDir = "/var/log/nagios"; + urlPath = "/nagios"; nagiosObjectDefs = cfg.objectDefs; @@ -49,12 +50,12 @@ let '' main_config_file=${cfg.mainConfigFile} use_authentication=0 - url_html_path=${cfg.urlPath} + url_html_path=${urlPath} ''; extraHttpdConfig = '' - ScriptAlias ${cfg.urlPath}/cgi-bin ${pkgs.nagios}/sbin + ScriptAlias ${urlPath}/cgi-bin ${pkgs.nagios}/sbin <Directory "${pkgs.nagios}/sbin"> Options ExecCGI @@ -62,7 +63,7 @@ let SetEnv NAGIOS_CGI_CONFIG ${cfg.cgiConfigFile} </Directory> - Alias ${cfg.urlPath} ${pkgs.nagios}/share + Alias ${urlPath} ${pkgs.nagios}/share <Directory "${pkgs.nagios}/share"> Options None @@ -72,6 +73,10 @@ let in { + imports = [ + (mkRemovedOptionModule [ "services" "nagios" "urlPath" ] "The urlPath option has been removed as it is hard coded to /nagios in the nagios package.") + ]; + options = { services.nagios = { enable = mkOption { @@ -128,13 +133,20 @@ in "; }; - urlPath = mkOption { - default = "/nagios"; - description = " - The URL path under which the Nagios web interface appears. - That is, you can access the Nagios web interface through - <literal>http://<replaceable>server</replaceable>/<replaceable>urlPath</replaceable></literal>. - "; + virtualHost = mkOption { + type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix); + example = literalExample '' + { hostName = "example.org"; + adminAddr = "webmaster@example.org"; + enableSSL = true; + sslServerCert = "/var/lib/acme/example.org/full.pem"; + sslServerKey = "/var/lib/acme/example.org/key.pem"; + } + ''; + description = '' + Apache configuration can be done by adapting <option>services.httpd.virtualHosts</option>. + See <xref linkend="opt-services.httpd.virtualHosts"/> for further information. + ''; }; }; }; @@ -182,6 +194,8 @@ in ''; }; - services.httpd.extraConfig = optionalString cfg.enableWebInterface extraHttpdConfig; + services.httpd.virtualHosts = optionalAttrs cfg.enableWebInterface { + ${cfg.virtualHost.hostName} = mkMerge [ cfg.virtualHost { extraConfig = extraHttpdConfig; } ]; + }; }; } diff --git a/nixos/modules/services/networking/kresd.nix b/nixos/modules/services/networking/kresd.nix index fc516c01230a..574074944d5e 100644 --- a/nixos/modules/services/networking/kresd.nix +++ b/nixos/modules/services/networking/kresd.nix @@ -13,6 +13,17 @@ in { meta.maintainers = [ maintainers.vcunat /* upstream developer */ ]; + imports = [ + (mkChangedOptionModule [ "services" "kresd" "interfaces" ] [ "services" "kresd" "listenPlain" ] + (config: + let value = getAttrFromPath [ "services" "kresd" "interfaces" ] config; + in map + (iface: if elem ":" (stringToCharacters iface) then "[${iface}]:53" else "${iface}:53") # Syntax depends on being IPv6 or IPv4. + value + ) + ) + ]; + ###### interface options.services.kresd = { enable = mkOption { @@ -39,11 +50,12 @@ in Directory for caches. They are intended to survive reboots. ''; }; - interfaces = mkOption { + listenPlain = mkOption { type = with types; listOf str; - default = [ "::1" "127.0.0.1" ]; + default = [ "[::1]:53" "127.0.0.1:53" ]; description = '' - What addresses the server should listen on. (UDP+TCP 53) + What addresses and ports the server should listen on. + For detailed syntax see ListenStream in man systemd.socket. ''; }; listenTLS = mkOption { @@ -51,7 +63,7 @@ in default = []; example = [ "198.51.100.1:853" "[2001:db8::1]:853" "853" ]; description = '' - Addresses on which kresd should provide DNS over TLS (see RFC 7858). + Addresses and ports on which kresd should provide DNS over TLS (see RFC 7858). For detailed syntax see ListenStream in man systemd.socket. ''; }; @@ -76,10 +88,7 @@ in systemd.sockets.kresd = rec { wantedBy = [ "sockets.target" ]; before = wantedBy; - listenStreams = map - # Syntax depends on being IPv6 or IPv4. - (iface: if elem ":" (stringToCharacters iface) then "[${iface}]:53" else "${iface}:53") - cfg.interfaces; + listenStreams = cfg.listenPlain; socketConfig = { ListenDatagram = listenStreams; FreeBind = true; diff --git a/nixos/modules/services/web-apps/limesurvey.nix b/nixos/modules/services/web-apps/limesurvey.nix index bd524524130d..e00a47191c6f 100644 --- a/nixos/modules/services/web-apps/limesurvey.nix +++ b/nixos/modules/services/web-apps/limesurvey.nix @@ -3,7 +3,7 @@ let inherit (lib) mkDefault mkEnableOption mkForce mkIf mkMerge mkOption; - inherit (lib) mapAttrs optional optionalString types; + inherit (lib) literalExample mapAttrs optional optionalString types; cfg = config.services.limesurvey; fpm = config.services.phpfpm.pools.limesurvey; @@ -100,19 +100,15 @@ in }; virtualHost = mkOption { - type = types.submodule ({ - options = import ../web-servers/apache-httpd/per-server-options.nix { - inherit lib; - forMainServer = false; - }; - }); - example = { - hostName = "survey.example.org"; - enableSSL = true; - adminAddr = "webmaster@example.org"; - sslServerCert = "/var/lib/acme/survey.example.org/full.pem"; - sslServerKey = "/var/lib/acme/survey.example.org/key.pem"; - }; + type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix); + example = literalExample '' + { + hostName = "survey.example.org"; + adminAddr = "webmaster@example.org"; + forceSSL = true; + enableACME = true; + } + ''; description = '' Apache configuration can be done by adapting <literal>services.httpd.virtualHosts.<name></literal>. See <xref linkend="opt-services.httpd.virtualHosts"/> for further information. @@ -184,7 +180,7 @@ in config = { tempdir = "${stateDir}/tmp"; uploaddir = "${stateDir}/upload"; - force_ssl = mkIf cfg.virtualHost.enableSSL "on"; + force_ssl = mkIf (cfg.virtualHost.addSSL || cfg.virtualHost.forceSSL || cfg.virtualHost.onlySSL) "on"; config.defaultlang = "en"; }; }; @@ -215,38 +211,36 @@ in enable = true; adminAddr = mkDefault cfg.virtualHost.adminAddr; extraModules = [ "proxy_fcgi" ]; - virtualHosts = [ (mkMerge [ - cfg.virtualHost { - documentRoot = mkForce "${pkg}/share/limesurvey"; - extraConfig = '' - Alias "/tmp" "${stateDir}/tmp" - <Directory "${stateDir}"> - AllowOverride all - Require all granted - Options -Indexes +FollowSymlinks - </Directory> - - Alias "/upload" "${stateDir}/upload" - <Directory "${stateDir}/upload"> - AllowOverride all - Require all granted - Options -Indexes - </Directory> - - <Directory "${pkg}/share/limesurvey"> - <FilesMatch "\.php$"> - <If "-f %{REQUEST_FILENAME}"> - SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/" - </If> - </FilesMatch> - - AllowOverride all - Options -Indexes - DirectoryIndex index.php - </Directory> - ''; - } - ]) ]; + virtualHosts.${cfg.virtualHost.hostName} = mkMerge [ cfg.virtualHost { + documentRoot = mkForce "${pkg}/share/limesurvey"; + extraConfig = '' + Alias "/tmp" "${stateDir}/tmp" + <Directory "${stateDir}"> + AllowOverride all + Require all granted + Options -Indexes +FollowSymlinks + </Directory> + + Alias "/upload" "${stateDir}/upload" + <Directory "${stateDir}/upload"> + AllowOverride all + Require all granted + Options -Indexes + </Directory> + + <Directory "${pkg}/share/limesurvey"> + <FilesMatch "\.php$"> + <If "-f %{REQUEST_FILENAME}"> + SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/" + </If> + </FilesMatch> + + AllowOverride all + Options -Indexes + DirectoryIndex index.php + </Directory> + ''; + } ]; }; systemd.tmpfiles.rules = [ diff --git a/nixos/modules/services/web-apps/mediawiki.nix b/nixos/modules/services/web-apps/mediawiki.nix index 43edc04e1a49..8a109b39bb57 100644 --- a/nixos/modules/services/web-apps/mediawiki.nix +++ b/nixos/modules/services/web-apps/mediawiki.nix @@ -64,7 +64,7 @@ let $wgScriptPath = ""; ## The protocol and server name to use in fully-qualified URLs - $wgServer = "${if cfg.virtualHost.enableSSL then "https" else "http"}://${cfg.virtualHost.hostName}"; + $wgServer = "${if cfg.virtualHost.addSSL || cfg.virtualHost.forceSSL || cfg.virtualHost.onlySSL then "https" else "http"}://${cfg.virtualHost.hostName}"; ## The URL path to static resources (images, scripts, etc.) $wgResourceBasePath = $wgScriptPath; @@ -290,19 +290,13 @@ in }; virtualHost = mkOption { - type = types.submodule ({ - options = import ../web-servers/apache-httpd/per-server-options.nix { - inherit lib; - forMainServer = false; - }; - }); + type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix); example = literalExample '' { hostName = "mediawiki.example.org"; - enableSSL = true; adminAddr = "webmaster@example.org"; - sslServerCert = "/var/lib/acme/mediawiki.example.org/full.pem"; - sslServerKey = "/var/lib/acme/mediawiki.example.org/key.pem"; + forceSSL = true; + enableACME = true; } ''; description = '' @@ -389,31 +383,28 @@ in services.httpd = { enable = true; - adminAddr = mkDefault cfg.virtualHost.adminAddr; extraModules = [ "proxy_fcgi" ]; - virtualHosts = [ (mkMerge [ - cfg.virtualHost { - documentRoot = mkForce "${pkg}/share/mediawiki"; - extraConfig = '' - <Directory "${pkg}/share/mediawiki"> - <FilesMatch "\.php$"> - <If "-f %{REQUEST_FILENAME}"> - SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/" - </If> - </FilesMatch> - - Require all granted - DirectoryIndex index.php - AllowOverride All - </Directory> - '' + optionalString (cfg.uploadsDir != null) '' - Alias "/images" "${cfg.uploadsDir}" - <Directory "${cfg.uploadsDir}"> - Require all granted - </Directory> - ''; - } - ]) ]; + virtualHosts.${cfg.virtualHost.hostName} = mkMerge [ cfg.virtualHost { + documentRoot = mkForce "${pkg}/share/mediawiki"; + extraConfig = '' + <Directory "${pkg}/share/mediawiki"> + <FilesMatch "\.php$"> + <If "-f %{REQUEST_FILENAME}"> + SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/" + </If> + </FilesMatch> + + Require all granted + DirectoryIndex index.php + AllowOverride All + </Directory> + '' + optionalString (cfg.uploadsDir != null) '' + Alias "/images" "${cfg.uploadsDir}" + <Directory "${cfg.uploadsDir}"> + Require all granted + </Directory> + ''; + } ]; }; systemd.tmpfiles.rules = [ diff --git a/nixos/modules/services/web-apps/moodle.nix b/nixos/modules/services/web-apps/moodle.nix index ac59f9e0012a..595d070d940a 100644 --- a/nixos/modules/services/web-apps/moodle.nix +++ b/nixos/modules/services/web-apps/moodle.nix @@ -32,7 +32,7 @@ let 'dbcollation' => 'utf8mb4_unicode_ci', ); - $CFG->wwwroot = '${if cfg.virtualHost.enableSSL then "https" else "http"}://${cfg.virtualHost.hostName}'; + $CFG->wwwroot = '${if cfg.virtualHost.addSSL || cfg.virtualHost.forceSSL || cfg.virtualHost.onlySSL then "https" else "http"}://${cfg.virtualHost.hostName}'; $CFG->dataroot = '${stateDir}'; $CFG->admin = 'admin'; @@ -140,19 +140,15 @@ in }; virtualHost = mkOption { - type = types.submodule ({ - options = import ../web-servers/apache-httpd/per-server-options.nix { - inherit lib; - forMainServer = false; - }; - }); - example = { - hostName = "moodle.example.org"; - enableSSL = true; - adminAddr = "webmaster@example.org"; - sslServerCert = "/var/lib/acme/moodle.example.org/full.pem"; - sslServerKey = "/var/lib/acme/moodle.example.org/key.pem"; - }; + type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix); + example = literalExample '' + { + hostName = "moodle.example.org"; + adminAddr = "webmaster@example.org"; + forceSSL = true; + enableACME = true; + } + ''; description = '' Apache configuration can be done by adapting <option>services.httpd.virtualHosts</option>. See <xref linkend="opt-services.httpd.virtualHosts"/> for further information. @@ -241,22 +237,20 @@ in enable = true; adminAddr = mkDefault cfg.virtualHost.adminAddr; extraModules = [ "proxy_fcgi" ]; - virtualHosts = [ (mkMerge [ - cfg.virtualHost { - documentRoot = mkForce "${cfg.package}/share/moodle"; - extraConfig = '' - <Directory "${cfg.package}/share/moodle"> - <FilesMatch "\.php$"> - <If "-f %{REQUEST_FILENAME}"> - SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/" - </If> - </FilesMatch> - Options -Indexes - DirectoryIndex index.php - </Directory> - ''; - } - ]) ]; + virtualHosts.${cfg.virtualHost.hostName} = mkMerge [ cfg.virtualHost { + documentRoot = mkForce "${cfg.package}/share/moodle"; + extraConfig = '' + <Directory "${cfg.package}/share/moodle"> + <FilesMatch "\.php$"> + <If "-f %{REQUEST_FILENAME}"> + SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/" + </If> + </FilesMatch> + Options -Indexes + DirectoryIndex index.php + </Directory> + ''; + } ]; }; systemd.tmpfiles.rules = [ diff --git a/nixos/modules/services/web-apps/wordpress.nix b/nixos/modules/services/web-apps/wordpress.nix index 13d21a0b4aed..ad4f39fbf52c 100644 --- a/nixos/modules/services/web-apps/wordpress.nix +++ b/nixos/modules/services/web-apps/wordpress.nix @@ -3,7 +3,7 @@ let inherit (lib) mkDefault mkEnableOption mkForce mkIf mkMerge mkOption types; inherit (lib) any attrValues concatMapStringsSep flatten literalExample; - inherit (lib) mapAttrs' mapAttrsToList nameValuePair optional optionalAttrs optionalString; + inherit (lib) mapAttrs mapAttrs' mapAttrsToList nameValuePair optional optionalAttrs optionalString; eachSite = config.services.wordpress; user = "wordpress"; @@ -209,18 +209,12 @@ let }; virtualHost = mkOption { - type = types.submodule ({ - options = import ../web-servers/apache-httpd/per-server-options.nix { - inherit lib; - forMainServer = false; - }; - }); + type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix); example = literalExample '' { - enableSSL = true; adminAddr = "webmaster@example.org"; - sslServerCert = "/var/lib/acme/wordpress.example.org/full.pem"; - sslServerKey = "/var/lib/acme/wordpress.example.org/key.pem"; + forceSSL = true; + enableACME = true; } ''; description = '' @@ -304,41 +298,37 @@ in services.httpd = { enable = true; extraModules = [ "proxy_fcgi" ]; - virtualHosts = mapAttrsToList (hostName: cfg: - (mkMerge [ - cfg.virtualHost { - documentRoot = mkForce "${pkg hostName cfg}/share/wordpress"; - extraConfig = '' - <Directory "${pkg hostName cfg}/share/wordpress"> - <FilesMatch "\.php$"> - <If "-f %{REQUEST_FILENAME}"> - SetHandler "proxy:unix:${config.services.phpfpm.pools."wordpress-${hostName}".socket}|fcgi://localhost/" - </If> - </FilesMatch> - - # standard wordpress .htaccess contents - <IfModule mod_rewrite.c> - RewriteEngine On - RewriteBase / - RewriteRule ^index\.php$ - [L] - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule . /index.php [L] - </IfModule> - - DirectoryIndex index.php - Require all granted - Options +FollowSymLinks - </Directory> - - # https://wordpress.org/support/article/hardening-wordpress/#securing-wp-config-php - <Files wp-config.php> - Require all denied - </Files> - ''; - } - ]) - ) eachSite; + virtualHosts = mapAttrs (hostName: cfg: mkMerge [ cfg.virtualHost { + documentRoot = mkForce "${pkg hostName cfg}/share/wordpress"; + extraConfig = '' + <Directory "${pkg hostName cfg}/share/wordpress"> + <FilesMatch "\.php$"> + <If "-f %{REQUEST_FILENAME}"> + SetHandler "proxy:unix:${config.services.phpfpm.pools."wordpress-${hostName}".socket}|fcgi://localhost/" + </If> + </FilesMatch> + + # standard wordpress .htaccess contents + <IfModule mod_rewrite.c> + RewriteEngine On + RewriteBase / + RewriteRule ^index\.php$ - [L] + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule . /index.php [L] + </IfModule> + + DirectoryIndex index.php + Require all granted + Options +FollowSymLinks + </Directory> + + # https://wordpress.org/support/article/hardening-wordpress/#securing-wp-config-php + <Files wp-config.php> + Require all denied + </Files> + ''; + } ]) eachSite; }; systemd.tmpfiles.rules = flatten (mapAttrsToList (hostName: cfg: [ diff --git a/nixos/modules/services/web-apps/zabbix.nix b/nixos/modules/services/web-apps/zabbix.nix index 09538726b7cd..ee8447810c6d 100644 --- a/nixos/modules/services/web-apps/zabbix.nix +++ b/nixos/modules/services/web-apps/zabbix.nix @@ -113,19 +113,15 @@ in }; virtualHost = mkOption { - type = types.submodule ({ - options = import ../web-servers/apache-httpd/per-server-options.nix { - inherit lib; - forMainServer = false; - }; - }); - example = { - hostName = "zabbix.example.org"; - enableSSL = true; - adminAddr = "webmaster@example.org"; - sslServerCert = "/var/lib/acme/zabbix.example.org/full.pem"; - sslServerKey = "/var/lib/acme/zabbix.example.org/key.pem"; - }; + type = types.submodule (import ../web-servers/apache-httpd/per-server-options.nix); + example = literalExample '' + { + hostName = "zabbix.example.org"; + adminAddr = "webmaster@example.org"; + forceSSL = true; + enableACME = true; + } + ''; description = '' Apache configuration can be done by adapting <literal>services.httpd.virtualHosts.<name></literal>. See <xref linkend="opt-services.httpd.virtualHosts"/> for further information. @@ -190,23 +186,21 @@ in enable = true; adminAddr = mkDefault cfg.virtualHost.adminAddr; extraModules = [ "proxy_fcgi" ]; - virtualHosts = [ (mkMerge [ - cfg.virtualHost { - documentRoot = mkForce "${cfg.package}/share/zabbix"; - extraConfig = '' - <Directory "${cfg.package}/share/zabbix"> - <FilesMatch "\.php$"> - <If "-f %{REQUEST_FILENAME}"> - SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/" - </If> - </FilesMatch> - AllowOverride all - Options -Indexes - DirectoryIndex index.php - </Directory> - ''; - } - ]) ]; + virtualHosts.${cfg.virtualHost.hostName} = mkMerge [ cfg.virtualHost { + documentRoot = mkForce "${cfg.package}/share/zabbix"; + extraConfig = '' + <Directory "${cfg.package}/share/zabbix"> + <FilesMatch "\.php$"> + <If "-f %{REQUEST_FILENAME}"> + SetHandler "proxy:unix:${fpm.socket}|fcgi://localhost/" + </If> + </FilesMatch> + AllowOverride all + Options -Indexes + DirectoryIndex index.php + </Directory> + ''; + } ]; }; users.users.${user} = mapAttrs (name: mkDefault) { diff --git a/nixos/modules/services/web-servers/apache-httpd/default.nix b/nixos/modules/services/web-servers/apache-httpd/default.nix index 850d3052533a..8e3be3162988 100644 --- a/nixos/modules/services/web-servers/apache-httpd/default.nix +++ b/nixos/modules/services/web-servers/apache-httpd/default.nix @@ -18,22 +18,20 @@ let mod_perl = pkgs.apacheHttpdPackages.mod_perl.override { apacheHttpd = httpd; }; - defaultListen = cfg: if cfg.enableSSL - then [{ip = "*"; port = 443;}] - else [{ip = "*"; port = 80;}]; + vhosts = attrValues mainCfg.virtualHosts; - getListen = cfg: - if cfg.listen == [] - then defaultListen cfg - else cfg.listen; + mkListenInfo = hostOpts: + if hostOpts.listen != [] then hostOpts.listen + else ( + optional (hostOpts.onlySSL || hostOpts.addSSL || hostOpts.forceSSL) { ip = "*"; port = 443; ssl = true; } ++ + optional (!hostOpts.onlySSL) { ip = "*"; port = 80; ssl = false; } + ); - listenToString = l: "${l.ip}:${toString l.port}"; + listenInfo = unique (concatMap mkListenInfo vhosts); - allHosts = [mainCfg] ++ mainCfg.virtualHosts; + enableSSL = any (listen: listen.ssl) listenInfo; - enableSSL = any (vhost: vhost.enableSSL) allHosts; - - enableUserDir = any (vhost: vhost.enableUserDir) allHosts; + enableUserDir = any (vhost: vhost.enableUserDir) vhosts; # NOTE: generally speaking order of modules is very important modules = @@ -115,122 +113,137 @@ let </IfModule> ''; - - perServerConf = isMainServer: cfg: let - - # Canonical name must not include a trailing slash. - canonicalNames = - let defaultPort = (head (defaultListen cfg)).port; in - map (port: - (if cfg.enableSSL then "https" else "http") + "://" + - cfg.hostName + - (if port != defaultPort then ":${toString port}" else "") - ) (map (x: x.port) (getListen cfg)); - - maybeDocumentRoot = fold (svc: acc: - if acc == null then svc.documentRoot else assert svc.documentRoot == null; acc - ) null ([ cfg ]); - - documentRoot = if maybeDocumentRoot != null then maybeDocumentRoot else - pkgs.runCommand "empty" { preferLocalBuild = true; } "mkdir -p $out"; - - documentRootConf = '' - DocumentRoot "${documentRoot}" - - <Directory "${documentRoot}"> - Options Indexes FollowSymLinks - AllowOverride None - ${allGranted} - </Directory> - ''; - - # If this is a vhost, the include the entries for the main server as well. - robotsTxt = concatStringsSep "\n" (filter (x: x != "") ([ cfg.robotsEntries ] ++ lib.optional (!isMainServer) mainCfg.robotsEntries)); - - in '' - ${concatStringsSep "\n" (map (n: "ServerName ${n}") canonicalNames)} - - ${concatMapStrings (alias: "ServerAlias ${alias}\n") cfg.serverAliases} - - ${if cfg.sslServerCert != null then '' - SSLCertificateFile ${cfg.sslServerCert} - SSLCertificateKeyFile ${cfg.sslServerKey} - ${if cfg.sslServerChain != null then '' - SSLCertificateChainFile ${cfg.sslServerChain} - '' else ""} - '' else ""} - - ${if cfg.enableSSL then '' - SSLEngine on - '' else if enableSSL then /* i.e., SSL is enabled for some host, but not this one */ - '' - SSLEngine off - '' else ""} - - ${if isMainServer || cfg.adminAddr != null then '' - ServerAdmin ${cfg.adminAddr} - '' else ""} - - ${if !isMainServer && mainCfg.logPerVirtualHost then '' - ErrorLog ${mainCfg.logDir}/error-${cfg.hostName}.log - CustomLog ${mainCfg.logDir}/access-${cfg.hostName}.log ${cfg.logFormat} - '' else ""} - - ${optionalString (robotsTxt != "") '' - Alias /robots.txt ${pkgs.writeText "robots.txt" robotsTxt} - ''} - - ${if isMainServer || maybeDocumentRoot != null then documentRootConf else ""} - - ${if cfg.enableUserDir then '' - - UserDir public_html - UserDir disabled root - - <Directory "/home/*/public_html"> - AllowOverride FileInfo AuthConfig Limit Indexes - Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec - <Limit GET POST OPTIONS> - ${allGranted} - </Limit> - <LimitExcept GET POST OPTIONS> - ${allDenied} - </LimitExcept> - </Directory> - - '' else ""} - - ${if cfg.globalRedirect != null && cfg.globalRedirect != "" then '' - RedirectPermanent / ${cfg.globalRedirect} - '' else ""} - - ${ - let makeFileConf = elem: '' - Alias ${elem.urlPath} ${elem.file} - ''; - in concatMapStrings makeFileConf cfg.servedFiles - } - - ${ - let makeDirConf = elem: '' - Alias ${elem.urlPath} ${elem.dir}/ - <Directory ${elem.dir}> - Options +Indexes - ${allGranted} - AllowOverride All - </Directory> - ''; - in concatMapStrings makeDirConf cfg.servedDirs - } - - ${cfg.extraConfig} - ''; + mkVHostConf = hostOpts: + let + adminAddr = if hostOpts.adminAddr != null then hostOpts.adminAddr else mainCfg.adminAddr; + listen = filter (listen: !listen.ssl) (mkListenInfo hostOpts); + listenSSL = filter (listen: listen.ssl) (mkListenInfo hostOpts); + + useACME = hostOpts.enableACME || hostOpts.useACMEHost != null; + sslCertDir = + if hostOpts.enableACME then config.security.acme.certs.${hostOpts.hostName}.directory + else if hostOpts.useACMEHost != null then config.security.acme.certs.${hostOpts.useACMEHost}.directory + else abort "This case should never happen."; + + sslServerCert = if useACME then "${sslCertDir}/full.pem" else hostOpts.sslServerCert; + sslServerKey = if useACME then "${sslCertDir}/key.pem" else hostOpts.sslServerKey; + sslServerChain = if useACME then "${sslCertDir}/fullchain.pem" else hostOpts.sslServerChain; + + acmeChallenge = optionalString useACME '' + Alias /.well-known/acme-challenge/ "${hostOpts.acmeRoot}/.well-known/acme-challenge/" + <Directory "${hostOpts.acmeRoot}"> + AllowOverride None + Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec + Require method GET POST OPTIONS + Require all granted + </Directory> + ''; + in + optionalString (listen != []) '' + <VirtualHost ${concatMapStringsSep " " (listen: "${listen.ip}:${toString listen.port}") listen}> + ServerName ${hostOpts.hostName} + ${concatMapStrings (alias: "ServerAlias ${alias}\n") hostOpts.serverAliases} + ServerAdmin ${adminAddr} + <IfModule mod_ssl.c> + SSLEngine off + </IfModule> + ${acmeChallenge} + ${if hostOpts.forceSSL then '' + <IfModule mod_rewrite.c> + RewriteEngine on + RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge [NC] + RewriteCond %{HTTPS} off + RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} + </IfModule> + '' else mkVHostCommonConf hostOpts} + </VirtualHost> + '' + + optionalString (listenSSL != []) '' + <VirtualHost ${concatMapStringsSep " " (listen: "${listen.ip}:${toString listen.port}") listenSSL}> + ServerName ${hostOpts.hostName} + ${concatMapStrings (alias: "ServerAlias ${alias}\n") hostOpts.serverAliases} + ServerAdmin ${adminAddr} + SSLEngine on + SSLCertificateFile ${sslServerCert} + SSLCertificateKeyFile ${sslServerKey} + ${optionalString (sslServerChain != null) "SSLCertificateChainFile ${sslServerChain}"} + ${acmeChallenge} + ${mkVHostCommonConf hostOpts} + </VirtualHost> + '' + ; + + mkVHostCommonConf = hostOpts: + let + documentRoot = if hostOpts.documentRoot != null + then hostOpts.documentRoot + else pkgs.runCommand "empty" { preferLocalBuild = true; } "mkdir -p $out" + ; + in + '' + ${optionalString mainCfg.logPerVirtualHost '' + ErrorLog ${mainCfg.logDir}/error-${hostOpts.hostName}.log + CustomLog ${mainCfg.logDir}/access-${hostOpts.hostName}.log ${hostOpts.logFormat} + ''} + + ${optionalString (hostOpts.robotsEntries != "") '' + Alias /robots.txt ${pkgs.writeText "robots.txt" hostOpts.robotsEntries} + ''} + + DocumentRoot "${documentRoot}" + + <Directory "${documentRoot}"> + Options Indexes FollowSymLinks + AllowOverride None + ${allGranted} + </Directory> + + ${optionalString hostOpts.enableUserDir '' + UserDir public_html + UserDir disabled root + <Directory "/home/*/public_html"> + AllowOverride FileInfo AuthConfig Limit Indexes + Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec + <Limit GET POST OPTIONS> + Require all granted + </Limit> + <LimitExcept GET POST OPTIONS> + Require all denied + </LimitExcept> + </Directory> + ''} + + ${optionalString (hostOpts.globalRedirect != null && hostOpts.globalRedirect != "") '' + RedirectPermanent / ${hostOpts.globalRedirect} + ''} + + ${ + let makeFileConf = elem: '' + Alias ${elem.urlPath} ${elem.file} + ''; + in concatMapStrings makeFileConf hostOpts.servedFiles + } + ${ + let makeDirConf = elem: '' + Alias ${elem.urlPath} ${elem.dir}/ + <Directory ${elem.dir}> + Options +Indexes + ${allGranted} + AllowOverride All + </Directory> + ''; + in concatMapStrings makeDirConf hostOpts.servedDirs + } + + ${hostOpts.extraConfig} + '' + ; confFile = pkgs.writeText "httpd.conf" '' ServerRoot ${httpd} - + ServerName ${config.networking.hostName} DefaultRuntimeDir ${runtimeDir}/runtime PidFile ${runtimeDir}/httpd.pid @@ -246,10 +259,9 @@ let </IfModule> ${let - listen = concatMap getListen allHosts; - toStr = listen: "Listen ${listenToString listen}\n"; - uniqueListen = uniqList {inputList = map toStr listen;}; - in concatStrings uniqueListen + toStr = listen: "Listen ${listen.ip}:${toString listen.port} ${if listen.ssl then "https" else "http"}"; + uniqueListen = uniqList {inputList = map toStr listenInfo;}; + in concatStringsSep "\n" uniqueListen } User ${mainCfg.user} @@ -297,17 +309,9 @@ let ${allGranted} </Directory> - # Generate directives for the main server. - ${perServerConf true mainCfg} + ${mainCfg.extraConfig} - ${let - makeVirtualHost = vhost: '' - <VirtualHost ${concatStringsSep " " (map listenToString (getListen vhost))}> - ${perServerConf false vhost} - </VirtualHost> - ''; - in concatMapStrings makeVirtualHost mainCfg.virtualHosts - } + ${concatMapStringsSep "\n" mkVHostConf vhosts} ''; # Generate the PHP configuration file. Should probably be factored @@ -329,6 +333,21 @@ in imports = [ (mkRemovedOptionModule [ "services" "httpd" "extraSubservices" ] "Most existing subservices have been ported to the NixOS module system. Please update your configuration accordingly.") (mkRemovedOptionModule [ "services" "httpd" "stateDir" ] "The httpd module now uses /run/httpd as a runtime directory.") + + # virtualHosts options + (mkRemovedOptionModule [ "services" "httpd" "documentRoot" ] "Please define a virtual host using `services.httpd.virtualHosts`.") + (mkRemovedOptionModule [ "services" "httpd" "enableSSL" ] "Please define a virtual host using `services.httpd.virtualHosts`.") + (mkRemovedOptionModule [ "services" "httpd" "enableUserDir" ] "Please define a virtual host using `services.httpd.virtualHosts`.") + (mkRemovedOptionModule [ "services" "httpd" "globalRedirect" ] "Please define a virtual host using `services.httpd.virtualHosts`.") + (mkRemovedOptionModule [ "services" "httpd" "hostName" ] "Please define a virtual host using `services.httpd.virtualHosts`.") + (mkRemovedOptionModule [ "services" "httpd" "listen" ] "Please define a virtual host using `services.httpd.virtualHosts`.") + (mkRemovedOptionModule [ "services" "httpd" "robotsEntries" ] "Please define a virtual host using `services.httpd.virtualHosts`.") + (mkRemovedOptionModule [ "services" "httpd" "servedDirs" ] "Please define a virtual host using `services.httpd.virtualHosts`.") + (mkRemovedOptionModule [ "services" "httpd" "servedFiles" ] "Please define a virtual host using `services.httpd.virtualHosts`.") + (mkRemovedOptionModule [ "services" "httpd" "serverAliases" ] "Please define a virtual host using `services.httpd.virtualHosts`.") + (mkRemovedOptionModule [ "services" "httpd" "sslServerCert" ] "Please define a virtual host using `services.httpd.virtualHosts`.") + (mkRemovedOptionModule [ "services" "httpd" "sslServerChain" ] "Please define a virtual host using `services.httpd.virtualHosts`.") + (mkRemovedOptionModule [ "services" "httpd" "sslServerKey" ] "Please define a virtual host using `services.httpd.virtualHosts`.") ]; ###### interface @@ -391,9 +410,25 @@ in ''; }; + adminAddr = mkOption { + type = types.str; + example = "admin@example.org"; + description = "E-mail address of the server administrator."; + }; + + logFormat = mkOption { + type = types.str; + default = "common"; + example = "combined"; + description = '' + Log format for log files. Possible values are: combined, common, referer, agent. + See <link xlink:href="https://httpd.apache.org/docs/2.4/logs.html"/> for more details. + ''; + }; + logPerVirtualHost = mkOption { type = types.bool; - default = false; + default = true; description = '' If enabled, each virtual host gets its own <filename>access.log</filename> and @@ -429,26 +464,28 @@ in }; virtualHosts = mkOption { - type = types.listOf (types.submodule ( - { options = import ./per-server-options.nix { - inherit lib; - forMainServer = false; + type = with types; attrsOf (submodule (import ./per-server-options.nix)); + default = { + localhost = { + documentRoot = "${httpd}/htdocs"; + }; + }; + example = literalExample '' + { + "foo.example.com" = { + forceSSL = true; + documentRoot = "/var/www/foo.example.com" + }; + "bar.example.com" = { + addSSL = true; + documentRoot = "/var/www/bar.example.com"; }; - })); - default = []; - example = [ - { hostName = "foo"; - documentRoot = "/data/webroot-foo"; - } - { hostName = "bar"; - documentRoot = "/data/webroot-bar"; } - ]; + ''; description = '' - Specification of the virtual hosts served by Apache. Each + Specification of the virtual hosts served by Apache. Each element should be an attribute set specifying the - configuration of the virtual host. The available options - are the non-global options permissible for the main host. + configuration of the virtual host. ''; }; @@ -534,13 +571,7 @@ in example = "All -SSLv2 -SSLv3"; description = "Allowed SSL/TLS protocol versions."; }; - } - - # Include the options shared between the main server and virtual hosts. - // (import ./per-server-options.nix { - inherit lib; - forMainServer = true; - }); + }; }; @@ -549,11 +580,31 @@ in config = mkIf config.services.httpd.enable { - assertions = [ { assertion = mainCfg.enableSSL == true - -> mainCfg.sslServerCert != null - && mainCfg.sslServerKey != null; - message = "SSL is enabled for httpd, but sslServerCert and/or sslServerKey haven't been specified."; } - ]; + assertions = [ + { + assertion = all (hostOpts: !hostOpts.enableSSL) vhosts; + message = '' + The option `services.httpd.virtualHosts.<name>.enableSSL` no longer has any effect; please remove it. + Select one of `services.httpd.virtualHosts.<name>.addSSL`, `services.httpd.virtualHosts.<name>.forceSSL`, + or `services.httpd.virtualHosts.<name>.onlySSL`. + ''; + } + { + assertion = all (hostOpts: with hostOpts; !(addSSL && onlySSL) && !(forceSSL && onlySSL) && !(addSSL && forceSSL)) vhosts; + message = '' + Options `services.httpd.virtualHosts.<name>.addSSL`, + `services.httpd.virtualHosts.<name>.onlySSL` and `services.httpd.virtualHosts.<name>.forceSSL` + are mutually exclusive. + ''; + } + { + assertion = all (hostOpts: !(hostOpts.enableACME && hostOpts.useACMEHost != null)) vhosts; + message = '' + Options `services.httpd.virtualHosts.<name>.enableACME` and + `services.httpd.virtualHosts.<name>.useACMEHost` are mutually exclusive. + ''; + } + ]; users.users = optionalAttrs (mainCfg.user == "wwwrun") (singleton { name = "wwwrun"; @@ -567,6 +618,15 @@ in gid = config.ids.gids.wwwrun; }); + security.acme.certs = mapAttrs (name: hostOpts: { + user = mainCfg.user; + group = mkDefault mainCfg.group; + email = if hostOpts.adminAddr != null then hostOpts.adminAddr else mainCfg.adminAddr; + webroot = hostOpts.acmeRoot; + extraDomains = genAttrs hostOpts.serverAliases (alias: null); + postRun = "systemctl reload httpd.service"; + }) (filterAttrs (name: hostOpts: hostOpts.enableACME) mainCfg.virtualHosts); + environment.systemPackages = [httpd]; services.httpd.phpOptions = @@ -605,10 +665,14 @@ in ]; systemd.services.httpd = + let + vhostsACME = filter (hostOpts: hostOpts.enableACME) vhosts; + in { description = "Apache HTTPD"; wantedBy = [ "multi-user.target" ]; - after = [ "network.target" "fs.target" ]; + wants = concatLists (map (hostOpts: [ "acme-${hostOpts.hostName}.service" "acme-selfsigned-${hostOpts.hostName}.service" ]) vhostsACME); + after = [ "network.target" "fs.target" ] ++ map (hostOpts: "acme-selfsigned-${hostOpts.hostName}.service") vhostsACME; path = [ httpd pkgs.coreutils pkgs.gnugrep ] diff --git a/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix b/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix index c36207d54607..f2e92cda05f6 100644 --- a/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix +++ b/nixos/modules/services/web-servers/apache-httpd/per-server-options.nix @@ -1,174 +1,235 @@ -# This file defines the options that can be used both for the Apache -# main server configuration, and for the virtual hosts. (The latter -# has additional options that affect the web server as a whole, like -# the user/group to run under.) - -{ forMainServer, lib }: - -with lib; - +{ config, lib, name, ... }: +let + inherit (lib) mkOption types; +in { + options = { + + hostName = mkOption { + type = types.str; + default = name; + description = "Canonical hostname for the server."; + }; + + serverAliases = mkOption { + type = types.listOf types.str; + default = []; + example = ["www.example.org" "www.example.org:8080" "example.org"]; + description = '' + Additional names of virtual hosts served by this virtual host configuration. + ''; + }; + + listen = mkOption { + type = with types; listOf (submodule ({ + options = { + port = mkOption { + type = types.port; + description = "Port to listen on"; + }; + ip = mkOption { + type = types.str; + default = "*"; + description = "IP to listen on. 0.0.0.0 for IPv4 only, * for all."; + }; + ssl = mkOption { + type = types.bool; + default = false; + description = "Whether to enable SSL (https) support."; + }; + }; + })); + default = []; + example = [ + { ip = "195.154.1.1"; port = 443; ssl = true;} + { ip = "192.154.1.1"; port = 80; } + { ip = "*"; port = 8080; } + ]; + description = '' + Listen addresses and ports for this virtual host. + <note><para> + This option overrides <literal>addSSL</literal>, <literal>forceSSL</literal> and <literal>onlySSL</literal>. + </para></note> + ''; + }; + + enableSSL = mkOption { + type = types.bool; + visible = false; + default = false; + }; + + addSSL = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable HTTPS in addition to plain HTTP. This will set defaults for + <literal>listen</literal> to listen on all interfaces on the respective default + ports (80, 443). + ''; + }; + + onlySSL = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable HTTPS and reject plain HTTP connections. This will set + defaults for <literal>listen</literal> to listen on all interfaces on port 443. + ''; + }; + + forceSSL = mkOption { + type = types.bool; + default = false; + description = '' + Whether to add a separate nginx server block that permanently redirects (301) + all plain HTTP traffic to HTTPS. This will set defaults for + <literal>listen</literal> to listen on all interfaces on the respective default + ports (80, 443), where the non-SSL listens are used for the redirect vhosts. + ''; + }; + + enableACME = mkOption { + type = types.bool; + default = false; + description = '' + Whether to ask Let's Encrypt to sign a certificate for this vhost. + Alternately, you can use an existing certificate through <option>useACMEHost</option>. + ''; + }; + + useACMEHost = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + A host of an existing Let's Encrypt certificate to use. + This is useful if you have many subdomains and want to avoid hitting the + <link xlink:href="https://letsencrypt.org/docs/rate-limits/">rate limit</link>. + Alternately, you can generate a certificate through <option>enableACME</option>. + <emphasis>Note that this option does not create any certificates, nor it does add subdomains to existing ones – you will need to create them manually using <xref linkend="opt-security.acme.certs"/>.</emphasis> + ''; + }; + + acmeRoot = mkOption { + type = types.str; + default = "/var/lib/acme/acme-challenges"; + description = "Directory for the acme challenge which is PUBLIC, don't put certs or keys in here"; + }; + + sslServerCert = mkOption { + type = types.path; + example = "/var/host.cert"; + description = "Path to server SSL certificate."; + }; + + sslServerKey = mkOption { + type = types.path; + example = "/var/host.key"; + description = "Path to server SSL certificate key."; + }; + + sslServerChain = mkOption { + type = types.nullOr types.path; + default = null; + example = "/var/ca.pem"; + description = "Path to server SSL chain file."; + }; + + adminAddr = mkOption { + type = types.nullOr types.str; + default = null; + example = "admin@example.org"; + description = "E-mail address of the server administrator."; + }; + + documentRoot = mkOption { + type = types.nullOr types.path; + default = null; + example = "/data/webserver/docs"; + description = '' + The path of Apache's document root directory. If left undefined, + an empty directory in the Nix store will be used as root. + ''; + }; + + servedDirs = mkOption { + type = types.listOf types.attrs; + default = []; + example = [ + { urlPath = "/nix"; + dir = "/home/eelco/Dev/nix-homepage"; + } + ]; + description = '' + This option provides a simple way to serve static directories. + ''; + }; + + servedFiles = mkOption { + type = types.listOf types.attrs; + default = []; + example = [ + { urlPath = "/foo/bar.png"; + file = "/home/eelco/some-file.png"; + } + ]; + description = '' + This option provides a simple way to serve individual, static files. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = '' + <Directory /home> + Options FollowSymlinks + AllowOverride All + </Directory> + ''; + description = '' + These lines go to httpd.conf verbatim. They will go after + directories and directory aliases defined by default. + ''; + }; + + enableUserDir = mkOption { + type = types.bool; + default = false; + description = '' + Whether to enable serving <filename>~/public_html</filename> as + <literal>/~<replaceable>username</replaceable></literal>. + ''; + }; + + globalRedirect = mkOption { + type = types.nullOr types.str; + default = null; + example = http://newserver.example.org/; + description = '' + If set, all requests for this host are redirected permanently to + the given URL. + ''; + }; + + logFormat = mkOption { + type = types.str; + default = "common"; + example = "combined"; + description = '' + Log format for Apache's log files. Possible values are: combined, common, referer, agent. + ''; + }; + + robotsEntries = mkOption { + type = types.lines; + default = ""; + example = "Disallow: /foo/"; + description = '' + Specification of pages to be ignored by web crawlers. See <link + xlink:href='http://www.robotstxt.org/'/> for details. + ''; + }; - hostName = mkOption { - type = types.str; - default = "localhost"; - description = "Canonical hostname for the server."; - }; - - serverAliases = mkOption { - type = types.listOf types.str; - default = []; - example = ["www.example.org" "www.example.org:8080" "example.org"]; - description = '' - Additional names of virtual hosts served by this virtual host configuration. - ''; - }; - - listen = mkOption { - type = types.listOf (types.submodule ( - { - options = { - port = mkOption { - type = types.int; - description = "port to listen on"; - }; - ip = mkOption { - type = types.str; - default = "*"; - description = "Ip to listen on. 0.0.0.0 for ipv4 only, * for all."; - }; - }; - } )); - description = '' - List of { /* ip: "*"; */ port = 80;} to listen on - ''; - - default = []; - }; - - enableSSL = mkOption { - type = types.bool; - default = false; - description = "Whether to enable SSL (https) support."; }; - - # Note: sslServerCert and sslServerKey can be left empty, but this - # only makes sense for virtual hosts (they will inherit from the - # main server). - - sslServerCert = mkOption { - type = types.nullOr types.path; - default = null; - example = "/var/host.cert"; - description = "Path to server SSL certificate."; - }; - - sslServerKey = mkOption { - type = types.path; - example = "/var/host.key"; - description = "Path to server SSL certificate key."; - }; - - sslServerChain = mkOption { - type = types.nullOr types.path; - default = null; - example = "/var/ca.pem"; - description = "Path to server SSL chain file."; - }; - - adminAddr = mkOption ({ - type = types.nullOr types.str; - example = "admin@example.org"; - description = "E-mail address of the server administrator."; - } // (if forMainServer then {} else {default = null;})); - - documentRoot = mkOption { - type = types.nullOr types.path; - default = null; - example = "/data/webserver/docs"; - description = '' - The path of Apache's document root directory. If left undefined, - an empty directory in the Nix store will be used as root. - ''; - }; - - servedDirs = mkOption { - type = types.listOf types.attrs; - default = []; - example = [ - { urlPath = "/nix"; - dir = "/home/eelco/Dev/nix-homepage"; - } - ]; - description = '' - This option provides a simple way to serve static directories. - ''; - }; - - servedFiles = mkOption { - type = types.listOf types.attrs; - default = []; - example = [ - { urlPath = "/foo/bar.png"; - file = "/home/eelco/some-file.png"; - } - ]; - description = '' - This option provides a simple way to serve individual, static files. - ''; - }; - - extraConfig = mkOption { - type = types.lines; - default = ""; - example = '' - <Directory /home> - Options FollowSymlinks - AllowOverride All - </Directory> - ''; - description = '' - These lines go to httpd.conf verbatim. They will go after - directories and directory aliases defined by default. - ''; - }; - - enableUserDir = mkOption { - type = types.bool; - default = false; - description = '' - Whether to enable serving <filename>~/public_html</filename> as - <literal>/~<replaceable>username</replaceable></literal>. - ''; - }; - - globalRedirect = mkOption { - type = types.nullOr types.str; - default = null; - example = http://newserver.example.org/; - description = '' - If set, all requests for this host are redirected permanently to - the given URL. - ''; - }; - - logFormat = mkOption { - type = types.str; - default = "common"; - example = "combined"; - description = '' - Log format for Apache's log files. Possible values are: combined, common, referer, agent. - ''; - }; - - robotsEntries = mkOption { - type = types.lines; - default = ""; - example = "Disallow: /foo/"; - description = '' - Specification of pages to be ignored by web crawlers. See <link - xlink:href='http://www.robotstxt.org/'/> for details. - ''; - }; - } diff --git a/nixos/modules/services/web-servers/nginx/default.nix b/nixos/modules/services/web-servers/nginx/default.nix index 9b476ba7f1e5..ada7a25604c4 100644 --- a/nixos/modules/services/web-servers/nginx/default.nix +++ b/nixos/modules/services/web-servers/nginx/default.nix @@ -671,6 +671,7 @@ in systemd.tmpfiles.rules = [ "d '${cfg.stateDir}' 0750 ${cfg.user} ${cfg.group} - -" "d '${cfg.stateDir}/logs' 0750 ${cfg.user} ${cfg.group} - -" + "Z '${cfg.stateDir}' - ${cfg.user} ${cfg.group} - -" ]; systemd.services.nginx = { diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix index 2d809b5cc9fd..1efd07393765 100644 --- a/nixos/modules/services/x11/display-managers/default.nix +++ b/nixos/modules/services/x11/display-managers/default.nix @@ -380,7 +380,7 @@ in wms = filter (s: s.manage == "window") cfg.displayManager.session; # Script responsible for starting the window manager and the desktop manager. - xsession = wm: dm: pkgs.writeScript "xsession" '' + xsession = dm: wm: pkgs.writeScript "xsession" '' #! ${pkgs.bash}/bin/bash # Legacy session script used to construct .desktop files from |