Diff options
| author | Bryce Kwon <bryce@brycekwon.com> | |
|---|---|---|
| committer | Bryce Kwon <bryce@brycekwon.com> | |
| commit | ||
| parent | ||
| tree | ||
| download | ||
Cut the lighttpd config down to a generic drop-in
The old file was a complete lighttpd.conf with its own user, modules
and MIME table. As a snippet it takes those from the distribution and
loads only the three modules it uses, which lighttpd skips when the
main config loads them already. It takes the nginx config's header and
commented examples. The host block matches on every socket, so HTTPS
needs only the socket, and the redirect is a condition on the scheme
inside it.
The stock lighttpd.conf on Debian, Alpine and Fedora refuses urls
ending in ~ or .inc, so a repository's config.inc answered 403 until
the host block cleared the list.
git-http-backend's cgi.assign sits outside the url condition because
lighttpd checks it after splitting the path, when that condition no
longer matches, and inside it the program itself was served as a file.
| -rw-r--r-- | custom/servers/lighttpd.conf | 216 |
1 file changed, 61 insertions, 155 deletions
diff --git a/custom/servers/lighttpd.conf b/custom/servers/lighttpd.conf index edbf162..5b6010c 100644 --- a/custom/servers/lighttpd.conf +++ b/custom/servers/lighttpd.conf @@ -1,134 +1,43 @@ -# lighttpd configuration for cgit. +# A lighttpd snippet that serves cgit at the root of git.example.org. +# Include it from lighttpd.conf, which supplies the user, the port, the MIME +# types and the logs. The first line below loads the modules it needs, and +# the next two those of the commented examples. A module the main config +# loads already is loaded only once. # -# Written for the lighttpd 1.4 branch, at 1.4.85 when last reviewed. +# The paths are one common layout, so adjust them to your system. +# cgit.cgi /usr/lib/cgit, from make install with the two-line cgit.conf in README +# static files /usr/share/cgit, from the same install +# repositories /var/lib/git, the scan-path custom/cgitrc suggests +# git-http-backend /usr/libexec/git-core, the directory git --exec-path prints +# certificate /etc/ssl/certs/git.example.org.pem +# key /etc/ssl/private/git.example.org.key # -# This is a complete lighttpd.conf rather than a snippet for conf-enabled, so -# nothing here is included from elsewhere and no distro base config is -# assumed. Check it and run it with -# lighttpd -tt -f /path/to/lighttpd.conf # check the syntax and modules -# lighttpd -D -f /path/to/lighttpd.conf # run it in the foreground -# -# lighttpd runs the cgit.cgi binary directly through mod_cgi, so no FastCGI -# bridge is needed. -# -# Paths assumed below, edit them to match your install. -# cgit CGI binary /usr/lib/cgit/cgit.cgi -# static assets /usr/share/cgit (cgit.css cgit.js cgit.png favicon.ico robots.txt) -# cgit config /etc/cgitrc -# public url https://git.example.org/ (cgit at the domain root) -# -# cgit is one CGI executable. It learns the repository and the page from -# PATH_INFO and reads page options such as h= and id= from QUERY_STRING. The -# five static assets are served straight off disk and must never be routed -# through cgit. - - -# A plain assignment rather than "+=", since this config stands on its own -# and there is no distro base list to append to. Adding mod_accesslog here -# is what the access log below needs. -server.modules = ( - "mod_alias", - "mod_setenv", - "mod_cgi", - "mod_accesslog", -) - +# The commented examples add HTTPS, which the bundled auth filters need +# before they log anyone in, and smart HTTP clone and push through +# git-http-backend. -server.port = 80 -server.username = "http" # Debian and Ubuntu use www-data -server.groupname = "http" -server.document-root = "/usr/share/cgit" # a valid docroot must exist. The - # alias rules below do the routing. -server.pid-file = "/run/lighttpd.pid" -server.errorlog = "/var/log/lighttpd/error.log" -accesslog.filename = "/var/log/lighttpd/access.log" - -# Drop the version number from the Server header and from error pages. -server.tag = "lighttpd" - -# The only request body cgit ever reads is the auth-filter login form, and it -# stops after 4096 bytes. Nothing else here accepts an upload. The value is in -# kilobytes and the default of 0 means unlimited. -server.max-request-size = 64 - - -# mod_alias serves the assets off disk, so lighttpd must know their content -# types. Without this the stylesheet is sent as application/octet-stream and -# the browser ignores it. Only these five files are served off disk, so this -# short table is the whole of it and no external mime file is needed. -mimetype.assign = ( - ".css" => "text/css", - ".js" => "text/javascript", - ".png" => "image/png", - ".ico" => "image/vnd.microsoft.icon", - ".txt" => "text/plain", -) +server.modules += ( "mod_access", "mod_alias", "mod_cgi" ) +#server.modules += ( "mod_openssl", "mod_redirect" ) +#server.modules += ( "mod_setenv" ) +# HTTPS on 443 beside plain HTTP. The host block below answers on both. +#$SERVER["socket"] == ":443" { +# ssl.engine = "enable" +# ssl.pemfile = "/etc/ssl/certs/git.example.org.pem" +# ssl.privkey = "/etc/ssl/private/git.example.org.key" +#} -# The vhost, as a top-level conditional so it matches on both the port 80 -# socket and the optional TLS socket at the end of this file. $HTTP["host"] == "git.example.org" { - - # Which config cgit reads. It falls back to the compiled-in /etc/cgitrc, - # the same path used here, but setting it makes the location explicit. - setenv.add-environment = ( "CGIT_CONFIG" => "/etc/cgitrc" ) - - # Site-wide security headers are set here so they also cover the static - # assets lighttpd serves. On raw repository bytes cgit sends a nosniff and - # the stricter policy "default-src 'none'" of its own. - # - # The add in add-response-header is load bearing. It appends a second - # copy next to what cgit emitted, so a raw page carries both policies and - # the browser enforces the stricter one, while the doubled nosniff line - # is harmless. The set-response-header directive would instead replace - # what cgit sent, swapping the strict policy on raw repository content - # for this looser site one. Never switch add to set. - # - # form-action self covers the login form, the only form cgit renders. If - # you enable the gravatar or libravatar avatar filter, add its host to - # img-src. A head-include or repo.head-content that injects a <style> - # block needs 'unsafe-inline' added to style-src. - # - # Permissions-Policy refuses the browser features a git viewer never asks - # for, camera and location among them, for everything served here, - # repository files included. The opener policy cuts any window.opener - # link between cgit and pages that open it, and the resource policy stops - # other origins from embedding what cgit serves, a hotlinked raw file for - # example. git clients are not browsers and ignore both, so clone and - # snapshot downloads keep working. The stricter - # Cross-Origin-Embedder-Policy is deliberately absent because it would - # break the avatar filters mentioned above. - setenv.add-response-header = ( - "Content-Security-Policy" => "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'none'; frame-ancestors 'self'; form-action 'self'", - "X-Content-Type-Options" => "nosniff", - "Referrer-Policy" => "no-referrer", - "Permissions-Policy" => "accelerometer=(), autoplay=(), camera=(), display-capture=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), usb=()", - "Cross-Origin-Opener-Policy" => "same-origin", - "Cross-Origin-Resource-Policy" => "same-origin" - ) - # Two years of forced HTTPS. Enable this together with the TLS socket at - # the end of this file and only once you serve HTTPS exclusively, since - # it is hard to undo once browsers have seen it. - #setenv.add-response-header += ( "Strict-Transport-Security" => "max-age=63072000; includeSubDomains" ) - - # Register the cgit binary as a CGI program. The empty value means the - # file is itself the program rather than input to an interpreter. - cgi.assign = ( "cgit.cgi" => "" ) - - # Routing. lighttpd's alias.url is first-match in declaration order, not - # longest prefix, so the five static entries must come before the / entry. - # If / came first it would swallow every request and recent lighttpd - # refuses to start. The static entries are served off disk and the / entry - # hands everything else to cgit. - # - # The trailing slash on cgit.cgi/ is load bearing. lighttpd builds the - # physical path by stripping the matched key off the front of the url and - # appending the rest to the value. For the key / the remainder carries no - # leading slash, so without the trailing slash a request for - # /linux/tree/kernel/sched.c glues onto the binary name as - # /usr/lib/cgit/cgit.cgilinux/tree/... and 404s. The trailing slash - # restores the separator, giving cgit SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi - # and PATH_INFO /linux/tree/kernel/sched.c. + # Sends plain HTTP on to HTTPS. + #$HTTP["scheme"] == "http" { + # url.redirect = ( "" => "https://${url.authority}${url.path}${qsa}" ) + #} + + # The five files cgit links to at the root are served off disk. lighttpd + # takes the first alias that matches, so they come before the one that + # hands every other path to cgit. That match takes the leading slash off + # the path and the slash after cgit.cgi puts it back, so cgit gets the + # whole path as its PATH_INFO. alias.url = ( "/cgit.css" => "/usr/share/cgit/cgit.css", "/cgit.js" => "/usr/share/cgit/cgit.js", @@ -138,34 +47,31 @@ $HTTP["host"] == "git.example.org" { "/" => "/usr/lib/cgit/cgit.cgi/", ) - # Served at / the SCRIPT_NAME is empty and cgit derives its link base - # correctly. For a sub-path install use a key without a trailing slash - # mapped to the binary without a trailing slash, for example - # "/git" => "/usr/lib/cgit/cgit.cgi" - # so /git/linux/tree resolves to /usr/lib/cgit/cgit.cgi/linux/tree, giving - # SCRIPT_NAME /git and PATH_INFO /linux/tree. cgit auto-detects the prefix. - # If links come out wrong, pin it in cgitrc with virtual-root=/git. + # The empty value runs cgit.cgi as a program rather than through an + # interpreter. + cgi.assign = ( "/cgit.cgi" => "" ) + + # Smart HTTP clone and push at the urls cgit gives the repositories go to + # git-http-backend. It finds them under GIT_PROJECT_ROOT and, with + # GIT_HTTP_EXPORT_ALL, serves them without a git-daemon-export-ok file. + # The safe.directory setting lets it open them while another user owns + # them. Push is refused until a repository sets http.receivepack or the + # server authenticates the user. The program is assigned outside the url + # condition, which no longer matches once lighttpd has split the path + # into the program and its PATH_INFO. + #cgi.assign += ( "/git-http-backend" => "" ) + #$HTTP["url"] =~ "^/.+/(info/refs|git-upload-pack|git-receive-pack)$" { + # alias.url = ( "/" => "/usr/libexec/git-core/git-http-backend/" ) + # setenv.add-environment = ( + # "GIT_PROJECT_ROOT" => "/var/lib/git", + # "GIT_HTTP_EXPORT_ALL" => "", + # "GIT_CONFIG_COUNT" => "1", + # "GIT_CONFIG_KEY_0" => "safe.directory", + # "GIT_CONFIG_VALUE_0" => "*", + # ) + #} + + # The stock lighttpd.conf refuses paths ending in ~ or .inc, which here + # are files in a repository, so cgit's host clears the list. + url.access-deny = () } - - -# Uncomment this whole block to enable TLS on 443. The host block above is -# socket independent, so it serves cgit over this socket too once the crypto -# is set. -#server.modules += ( "mod_openssl" ) -# -#$SERVER["socket"] == ":443" { -# ssl.engine = "enable" -# ssl.pemfile = "/etc/lighttpd/certs/git.example.org.crt" -# ssl.privkey = "/etc/lighttpd/certs/git.example.org.key" -# ssl.ca-file = "/etc/lighttpd/certs/git.example.org.chain.pem" -# ssl.openssl.ssl-conf-cmd = ( "MinProtocol" => "TLSv1.2" ) -#} -# -# Redirect plain HTTP to HTTPS, scoped to the port 80 socket. Needs -# mod_redirect. -#server.modules += ( "mod_redirect" ) -#$SERVER["socket"] == ":80" { -# $HTTP["host"] == "git.example.org" { -# url.redirect = ( "^/(.*)" => "https://git.example.org/$1" ) -# } -#} |
