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