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