# lighttpd configuration for cgit. # # lighttpd runs the cgit.cgi binary directly through mod_cgi, so no FastCGI # bridge is needed. This is cgit's classic reference deployment, mod_cgi with # mod_alias and mod_setenv. # # 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. cgit # builds its own link base from SCRIPT_NAME. The five static assets are served # straight off disk and must never be routed through cgit. # --- Modules ---------------------------------------------------------------- # Append the three modules cgit needs so the distro's base config is kept. # mod_alias maps URL paths onto files, mod_setenv injects CGIT_CONFIG, and # mod_cgi runs cgit.cgi. server.modules += ( "mod_alias", "mod_setenv", "mod_cgi" ) # --- Server basics ---------------------------------------------------------- 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.errorlog = "/var/log/lighttpd/error.log" # Access logging needs mod_accesslog. Load it and uncomment to enable. #server.modules += ( "mod_accesslog" ) #accesslog.filename = "/var/log/lighttpd/access.log" # --- MIME types for the static assets --------------------------------------- # 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. mimetype.assign = ( ".css" => "text/css", ".js" => "text/javascript", ".png" => "image/png", ".ico" => "image/vnd.microsoft.icon", ".txt" => "text/plain", ) # --- Virtual host, git.example.org ------------------------------------------ # 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" ) # --- Security headers --------------------------------------------------- # Set here, not in cgit, so they also cover the static assets lighttpd # serves. script-src stays self because cgit loads only its own cgit.js, # and style-src allows inline for the diffstat bars. If you enable the # gravatar or libravatar avatar filter, add its host to img-src. setenv.add-response-header = ( "Content-Security-Policy" => "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; object-src 'none'; base-uri 'none'; frame-ancestors 'self'", "X-Content-Type-Options" => "nosniff", "Referrer-Policy" => "no-referrer" ) # Enable only once you serve HTTPS exclusively, since it is hard to undo. #setenv.add-response-header += ( "Strict-Transport-Security" => "max-age=63072000; includeSubDomains" ) # Register the cgit binary as a CGI program. The key cgit.cgi matches the # binary's name and the empty value means the file is itself the program, # with no interpreter in front of it. This is what makes lighttpd split # the trailing path off as PATH_INFO, so never drop it. 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. alias.url = ( "/cgit.css" => "/usr/share/cgit/cgit.css", "/cgit.js" => "/usr/share/cgit/cgit.js", "/cgit.png" => "/usr/share/cgit/cgit.png", "/favicon.ico" => "/usr/share/cgit/favicon.ico", "/robots.txt" => "/usr/share/cgit/robots.txt", "/" => "/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. } # --- Optional HTTPS on 443 -------------------------------------------------- # Uncomment this whole block to enable TLS. 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" ) # } #}