# NixOS module for lighttpd web server { config, pkgs, ... }: with pkgs.lib; let cfg = config.services.lighttpd; needModRedirect = cfg.gitweb.enable; needModAlias = cfg.cgit.enable or cfg.gitweb.enable; needModSetenv = cfg.cgit.enable or cfg.gitweb.enable; needModCgi = cfg.cgit.enable or cfg.gitweb.enable; needModStatus = cfg.mod_status; needModUserdir = cfg.mod_userdir; configFile = if cfg.configText != "" then pkgs.writeText "lighttpd.conf" '' ${cfg.configText} '' else pkgs.writeText "lighttpd.conf" '' server.document-root = "${cfg.document-root}" server.port = ${toString cfg.port} server.username = "lighttpd" server.groupname = "lighttpd" # As for why all modules are loaded here, instead of having small # server.modules += () entries in each sub-service extraConfig snippet, # read this: # # http://redmine.lighttpd.net/projects/1/wiki/Server_modulesDetails # http://redmine.lighttpd.net/issues/2337 # # Basically, lighttpd doesn't want to load (or even silently ignore) a # module for a second time, and there is no way to check if a module has # been loaded already. So if two services were to put the same module in # server.modules += (), that would break the lighttpd configuration. server.modules = ( ${optionalString needModRedirect ''"mod_redirect",''} ${optionalString needModAlias ''"mod_alias",''} ${optionalString needModSetenv ''"mod_setenv",''} ${optionalString needModCgi ''"mod_cgi",''} ${optionalString needModStatus ''"mod_status",''} ${optionalString needModUserdir ''"mod_userdir",''} "mod_accesslog" ) # Logging (logs end up in systemd journal) accesslog.use-syslog = "enable" server.errorlog-use-syslog = "enable" mimetype.assign = ( ".html" => "text/html", ".htm" => "text/html", ".txt" => "text/plain", ".jpg" => "image/jpeg", ".png" => "image/png", ".css" => "text/css" ) static-file.exclude-extensions = ( ".fcgi", ".php", ".rb", "~", ".inc" ) index-file.names = ( "index.html" ) ${if cfg.mod_userdir then '' userdir.path = "public_html" '' else ""} ${if cfg.mod_status then '' status.status-url = "/server-status" status.statistics-url = "/server-statistics" status.config-url = "/server-config" '' else ""} ${cfg.extraConfig} ''; in { options = { services.lighttpd = { enable = mkOption { default = false; type = types.uniq types.bool; description = '' Enable the lighttpd web server. ''; }; port = mkOption { default = 80; type = types.uniq types.int; description = '' TCP port number for lighttpd to bind to. ''; }; document-root = mkOption { default = "/srv/www"; type = types.str; description = '' Document-root of the web server. Must be readable by the "lighttpd" user. ''; }; mod_userdir = mkOption { default = false; type = types.uniq types.bool; description = '' If true, requests in the form /~user/page.html are rewritten to take the file public_html/page.html from the home directory of the user. ''; }; mod_status = mkOption { default = false; type = types.uniq types.bool; description = '' Show server status overview at /server-status, statistics at /server-statistics and list of loaded modules at /server-config. ''; }; configText = mkOption { default = ""; type = types.string; example = ''...verbatim config file contents...''; description = '' Overridable config file contents to use for lighttpd. By default, use the contents automatically generated by NixOS. ''; }; extraConfig = mkOption { default = ""; type = types.string; description = '' These configuration lines will be appended to the generated lighttpd config file. Note that this mechanism does not work when the manual option is used. ''; }; }; }; config = mkIf cfg.enable { systemd.services.lighttpd = { description = "Lighttpd Web Server"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; preStart = '' ${if cfg.cgit.enable then '' mkdir -p /var/cache/cgit chown lighttpd:lighttpd /var/cache/cgit '' else ""} ''; serviceConfig.ExecStart = "${pkgs.lighttpd}/sbin/lighttpd -D -f ${configFile}"; # SIGINT => graceful shutdown serviceConfig.KillSignal = "SIGINT"; }; users.extraUsers.lighttpd = { group = "lighttpd"; description = "lighttpd web server privilege separation user"; uid = config.ids.uids.lighttpd; }; users.extraGroups.lighttpd.gid = config.ids.gids.lighttpd; }; }