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