at 23.05-pre 7.7 kB view raw
1# NixOS module for lighttpd web server 2 3{ config, lib, pkgs, ... }: 4 5with lib; 6 7let 8 9 cfg = config.services.lighttpd; 10 11 # List of known lighttpd modules, ordered by how the lighttpd documentation 12 # recommends them being imported: 13 # http://redmine.lighttpd.net/projects/1/wiki/Server_modulesDetails 14 # 15 # Some modules are always imported and should not appear in the config: 16 # disallowedModules = [ "mod_indexfile" "mod_dirlisting" "mod_staticfile" ]; 17 # 18 # For full module list, see the output of running ./configure in the lighttpd 19 # source. 20 allKnownModules = [ 21 "mod_rewrite" 22 "mod_redirect" 23 "mod_alias" 24 "mod_access" 25 "mod_auth" 26 "mod_status" 27 "mod_simple_vhost" 28 "mod_evhost" 29 "mod_userdir" 30 "mod_secdownload" 31 "mod_fastcgi" 32 "mod_proxy" 33 "mod_cgi" 34 "mod_ssi" 35 "mod_compress" 36 "mod_usertrack" 37 "mod_expire" 38 "mod_rrdtool" 39 "mod_accesslog" 40 # Remaining list of modules, order assumed to be unimportant. 41 "mod_authn_dbi" 42 "mod_authn_file" 43 "mod_authn_gssapi" 44 "mod_authn_ldap" 45 "mod_authn_mysql" 46 "mod_authn_pam" 47 "mod_authn_sasl" 48 "mod_cml" 49 "mod_deflate" 50 "mod_evasive" 51 "mod_extforward" 52 "mod_flv_streaming" 53 "mod_geoip" 54 "mod_magnet" 55 "mod_mysql_vhost" 56 "mod_openssl" # since v1.4.46 57 "mod_scgi" 58 "mod_setenv" 59 "mod_trigger_b4_dl" 60 "mod_uploadprogress" 61 "mod_vhostdb" # since v1.4.46 62 "mod_webdav" 63 "mod_wstunnel" # since v1.4.46 64 ]; 65 66 maybeModuleString = moduleName: 67 if elem moduleName cfg.enableModules then ''"${moduleName}"'' else ""; 68 69 modulesIncludeString = concatStringsSep ",\n" 70 (filter (x: x != "") (map maybeModuleString allKnownModules)); 71 72 configFile = if cfg.configText != "" then 73 pkgs.writeText "lighttpd.conf" '' 74 ${cfg.configText} 75 '' 76 else 77 pkgs.writeText "lighttpd.conf" '' 78 server.document-root = "${cfg.document-root}" 79 server.port = ${toString cfg.port} 80 server.username = "lighttpd" 81 server.groupname = "lighttpd" 82 83 # As for why all modules are loaded here, instead of having small 84 # server.modules += () entries in each sub-service extraConfig snippet, 85 # read this: 86 # 87 # http://redmine.lighttpd.net/projects/1/wiki/Server_modulesDetails 88 # http://redmine.lighttpd.net/issues/2337 89 # 90 # Basically, lighttpd doesn't want to load (or even silently ignore) a 91 # module for a second time, and there is no way to check if a module has 92 # been loaded already. So if two services were to put the same module in 93 # server.modules += (), that would break the lighttpd configuration. 94 server.modules = ( 95 ${modulesIncludeString} 96 ) 97 98 # Logging (logs end up in systemd journal) 99 accesslog.use-syslog = "enable" 100 server.errorlog-use-syslog = "enable" 101 102 ${lib.optionalString cfg.enableUpstreamMimeTypes '' 103 include "${pkgs.lighttpd}/share/lighttpd/doc/config/conf.d/mime.conf" 104 ''} 105 106 static-file.exclude-extensions = ( ".fcgi", ".php", ".rb", "~", ".inc" ) 107 index-file.names = ( "index.html" ) 108 109 ${if cfg.mod_userdir then '' 110 userdir.path = "public_html" 111 '' else ""} 112 113 ${if cfg.mod_status then '' 114 status.status-url = "/server-status" 115 status.statistics-url = "/server-statistics" 116 status.config-url = "/server-config" 117 '' else ""} 118 119 ${cfg.extraConfig} 120 ''; 121 122in 123 124{ 125 126 options = { 127 128 services.lighttpd = { 129 130 enable = mkOption { 131 default = false; 132 type = types.bool; 133 description = lib.mdDoc '' 134 Enable the lighttpd web server. 135 ''; 136 }; 137 138 package = mkOption { 139 default = pkgs.lighttpd; 140 defaultText = "pkgs.lighttpd"; 141 type = types.package; 142 description = lib.mdDoc '' 143 lighttpd package to use. 144 ''; 145 }; 146 147 port = mkOption { 148 default = 80; 149 type = types.port; 150 description = lib.mdDoc '' 151 TCP port number for lighttpd to bind to. 152 ''; 153 }; 154 155 document-root = mkOption { 156 default = "/srv/www"; 157 type = types.path; 158 description = lib.mdDoc '' 159 Document-root of the web server. Must be readable by the "lighttpd" user. 160 ''; 161 }; 162 163 mod_userdir = mkOption { 164 default = false; 165 type = types.bool; 166 description = lib.mdDoc '' 167 If true, requests in the form /~user/page.html are rewritten to take 168 the file public_html/page.html from the home directory of the user. 169 ''; 170 }; 171 172 enableModules = mkOption { 173 type = types.listOf types.str; 174 default = [ ]; 175 example = [ "mod_cgi" "mod_status" ]; 176 description = lib.mdDoc '' 177 List of lighttpd modules to enable. Sub-services take care of 178 enabling modules as needed, so this option is mainly for when you 179 want to add custom stuff to 180 {option}`services.lighttpd.extraConfig` that depends on a 181 certain module. 182 ''; 183 }; 184 185 enableUpstreamMimeTypes = mkOption { 186 type = types.bool; 187 default = true; 188 description = lib.mdDoc '' 189 Whether to include the list of mime types bundled with lighttpd 190 (upstream). If you disable this, no mime types will be added by 191 NixOS and you will have to add your own mime types in 192 {option}`services.lighttpd.extraConfig`. 193 ''; 194 }; 195 196 mod_status = mkOption { 197 default = false; 198 type = types.bool; 199 description = lib.mdDoc '' 200 Show server status overview at /server-status, statistics at 201 /server-statistics and list of loaded modules at /server-config. 202 ''; 203 }; 204 205 configText = mkOption { 206 default = ""; 207 type = types.lines; 208 example = "...verbatim config file contents..."; 209 description = lib.mdDoc '' 210 Overridable config file contents to use for lighttpd. By default, use 211 the contents automatically generated by NixOS. 212 ''; 213 }; 214 215 extraConfig = mkOption { 216 default = ""; 217 type = types.lines; 218 description = lib.mdDoc '' 219 These configuration lines will be appended to the generated lighttpd 220 config file. Note that this mechanism does not work when the manual 221 {option}`configText` option is used. 222 ''; 223 }; 224 225 }; 226 227 }; 228 229 config = mkIf cfg.enable { 230 231 assertions = [ 232 { assertion = all (x: elem x allKnownModules) cfg.enableModules; 233 message = '' 234 One (or more) modules in services.lighttpd.enableModules are 235 unrecognized. 236 237 Known modules: ${toString allKnownModules} 238 239 services.lighttpd.enableModules: ${toString cfg.enableModules} 240 ''; 241 } 242 ]; 243 244 services.lighttpd.enableModules = mkMerge 245 [ (mkIf cfg.mod_status [ "mod_status" ]) 246 (mkIf cfg.mod_userdir [ "mod_userdir" ]) 247 # always load mod_accesslog so that we can log to the journal 248 [ "mod_accesslog" ] 249 ]; 250 251 systemd.services.lighttpd = { 252 description = "Lighttpd Web Server"; 253 after = [ "network.target" ]; 254 wantedBy = [ "multi-user.target" ]; 255 serviceConfig.ExecStart = "${cfg.package}/sbin/lighttpd -D -f ${configFile}"; 256 # SIGINT => graceful shutdown 257 serviceConfig.KillSignal = "SIGINT"; 258 }; 259 260 users.users.lighttpd = { 261 group = "lighttpd"; 262 description = "lighttpd web server privilege separation user"; 263 uid = config.ids.uids.lighttpd; 264 }; 265 266 users.groups.lighttpd.gid = config.ids.gids.lighttpd; 267 }; 268}