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