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