admins.html: minor page formatting improvement
[girocco.git] / lighttpd.conf.in
blob39d4b20ccba167a2617b8feed71bd2f2056e3fd2
1 ##  To convert this file to lighttpd.conf using the current Girocco::Config
2 ##  values either do "make" or "make lighttpd.conf" or ./make-lighttpd-conf.sh
3 ##
4 # This is an example configuration of a virtualhost running Girocco, as set up
5 # at repo.or.cz; unfortunately, somewhat independent from Girocco::Config.
6 # It is not essential for Girocco to use a special virtualhost, however.
8 # Minimum lighttpd version 1.4.53 or later required for this config file
10 # Minimum lighttpd version 1.4.53 recommended
12 # Minimum lighttpd version 1.4.53 required for server.systemd-socket-activation
14 # Minimum lighttpd version 1.4.48 required for girocco https push support
16 # Versions prior to 1.4.50 have security issues with incoming requests
17 # having unnormalized URLs in them which can bypass access checks
19 # Versions prior to 1.4.52 accept invalid incoming requests that do
20 # not start the path with a '/'
22 # Prior to version 1.4.53, the private key for the server's
23 # certificate will have to be appended to the `server.pemfile`
24 # since `server.privkey` is not supported until version 1.4.53.
26 # Required lighttpd modules:
28 #   mod_openssl    -  for https and client push certs
29 #   mod_setenv     -  passing environment
30 #   mod_indexfile  -  (should be automatic)
31 #   mod_access     -  access checks
32 #   mod_alias      -  aliases (no regexp)
33 #   mod_redirect   -  regexp access etc.
34 #   mod_rewrite    -  regexp rewrites/aliases/etc.
35 #   mod_status     -  optional (local server status)
36 #   mod_cgi        -  standard cgi
37 #   mod_fastcgi    -  accelerated cgi
38 #   mod_dirlisting -  (should be automatic but unused)
39 #   mod_staticfile -  (should be automatic)
40 #   mod_accesslog  -  for logging requests
44 ## IPv4/IPv6 addresses
46 ## These are needed in multiple places and collected here in
47 ## convenience variables to avoid duplication.
49 var.httpport = 80    # for http:  connections
50 var.httpsport = 443  # for https: connections
51 @@if(!lighttpd_loopback_only)@@
52 # externally accessible web server
53 var.ipv4addr = "0.0.0.0"        # IPv4 INADDR_ANY
54 var.ipv6addr = "::"             # IPv6 IN6ADDR_ANY
55 @@endif@@
56 @@if(lighttpd_loopback_only)@@
57 # web server only accessible from localhost
58 var.ipv4addr = "127.0.0.1"
59 var.ipv6addr = "::1"
60 @@endif@@
64 ## Standalone configuration
66 ## If this file is being included to provide a virtual
67 ## host service, then this configuration should have already
68 ## been done once somewhere else
71 @@if(lighttpd_standalone)@@
73 server.modules += (
74         "mod_openssl",
75         "mod_setenv",
76         "mod_access",
77         "mod_alias",
78         "mod_redirect",
79         "mod_rewrite",
80         "mod_status",
81         "mod_cgi",
82         "mod_fastcgi",
83         "mod_accesslog"
86 # This does not attempt to be a comprehensive list, but
87 # should be sufficient for Girocco on a standalone server
88 mimetype.assign = (
89         ".html" => "text/html",
90         ".htm"  => "text/html",
91         ".txt"  => "text/plain",
92         ".pem"  => "text/plain",
93         ".ico"  => "image/x-icon",
94         ".css"  => "text/css",
95         ".js"   => "application/javascript",
96         ".png"  => "image/png",
97         ".gif"  => "image/gif",
98         ".bmp"  => "image/bmp",
99         ".svg"  => "image/svg+xml",
100         ".svgz" => "image/svg+xml",
101         ".jpg"  => "image/jpeg",
102         ".jpeg" => "image/jpeg",
103         ".mp3"  => "audio/mpeg",
104         ""      => "application/octet-stream"
107 # This acts as a no-op if not activated via systemd, but without
108 # setting this it's not possible to pass sockets from systemd.
109 # Therefore just always set it in standalone mode
110 server.systemd-socket-activation = "enable"
112 # lighttpd has a problem passing sockets from systemd in that
113 # if systemd passes in an IPv6 socket, lighttpd will fail to bind
114 # a global `server.bind` value to an IPv4 socket.  Oops.
115 # That's why `server.bind` here uses the IPv6 address.
116 server.bind = "["+var.ipv6addr+"]"
117 server.port = var.httpport
119 # these are required and in standalone mode won't be set anywhere else
120 @@if(!lighttpd_unprivileged)@@
121 # run privileged at first and after initializing, drop privileges
122 # normally no need to set the groupname as it's inited from the username
123 server.username = "@@cgi_user@@"
124 server.pid-file = "/var/run/lighttpd.pid"
125 var.logbase = "/var/log/lighttpd/"
126 var.fcgisockbase = "/var/run/lighttpd/"
127 @@endif(!lighttpd_unprivileged)@@
128 @@if(lighttpd_unprivileged)@@
129 # put the log files in /tmp using tmpsuffix
130 server.pid-file = "/tmp/lighttpd-@@tmpsuffix@@.pid"
131 var.logbase = "/tmp/lighttpd-@@tmpsuffix@@_"
132 var.fcgisockbase = "/tmp/lighttpd-fcgi-"
133 @@endif(lighttpd_unprivileged)@@
134 server.errorlog = var.logbase+"error.log"
135 # Send CGI stderr to error log
136 server.breakagelog = server.errorlog
138 # Special checks a standalone server might be expected to do
139 $HTTP["url"] =~ "(?i)\.htaccess$" { url.access-deny = ( "" ) }
141 @@endif(lighttpd_standalone)@@
143 @@if(!lighttpd_standalone)@@
144 var.logbase = "/var/log/lighttpd/"
145 var.fcgisockbase = "/var/run/lighttpd/"
146 @@endif@@
148 # Lighttpd ignores exactly matching duplicate socket definitions
149 # therefore just go ahead and mention them to make sure they're active.
150 # Only the http sockets are here.
151 # See the bottom of this file for the https sockets.
153 $SERVER["socket"] == var.ipv4addr+":"+var.httpport {}
154 $SERVER["socket"] == "["+var.ipv6addr+"]:"+var.httpport {}
156 var.rdrbase = "${url.scheme}://${url.authority}" # helpful for redirects
157 var.botpat = "(?i)Slurp|Bot|Spider|Riddler|ltx71|Crawl"
159 @@if(!lighttpd_standalone)@@
160 # The configuration inside this virtual host conditional
161 # ends up only depending on the value of the 'Host:' header sent
162 # by the remote client since it contains no TLS-specific settings
163 $HTTP["host"] == "@@httpdnsname@@" { # "virtual" host @@httpdnsname@@
164 @@endif@@
166         # These help to prevent a bot from monopolizing a connection
167         server.max-keep-alive-requests = 7 # default is 100
168         server.max-keep-alive-idle = 2 # default is 5
170         # Without these little bits here to set server.name,
171         # if an HTTP/1.0 request comes in on a non-standard port
172         # and it lacks a Host: header, redirects might give the
173         # wrong answer without these.
174         $HTTP["scheme"] == "http" {
175                 server.name = "@@httpdnsname@@:"+var.httpport
176         }
177         else $HTTP["scheme"] == "https" {
178                 server.name = "@@httpdnsname@@:"+var.httpsport
179         }
181         # This is the standard "combined" log format modified as follows:
182         #    the REMOTE_USER (%u) has double-quotes around it
183         #    the received time is shown as [YYYY-mm-dd_HH:MM:SS +hhmm] (almost RFC 3339 format)
184         #        -- this is one character shorter than the default but sorts so much better
185         #    the %O value is prefixed with:
186         #        %I->  -- <bytes-received-including-request-and-headers>
187         #    the first line of the request ("%r") is prefixed with
188         #        %X%k: -- <connection-status><keepalive-request-num>
189         #    these fields are added to the end:
190         #        :%{local}p   -- :<actual-server-port>
191         #        %Dus         -- <request-time-in-microseconds>
192         #        "%o{Content-Range}" -- <outgoing Content-Range header>
193         accesslog.format = "%h %l \"%u\" %{[%F_%T %z]}t %X%k:\"%r\" %>s %I->%O \"%{Referer}i\" \"%{User-Agent}i\" :%{local}p %Dus \"%{Content-Range}o\""
195         # lighttpd does not permit a separate error log per host
197         # This may need to be adjusted as needed
198         accesslog.filename = var.logbase+"@@nickname@@-access.log"
200         # Send CGI stderr to error log (done above for standalone mode)
201         #global { server.breakagelog = server.errorlog }
203         # Avoid breaking gitweb
204         server.force-lowercase-filenames = "disable"
206         # lighttpd "normalization" suffers from many defects;
207         # no available configuration is standards compliant.
208         # Failing to enable any "normalization" (the default
209         # through version 1.4.53) allows URL-encoded items
210         # to bypass access and other checks.  Enabling even
211         # the bare minimum (this configuration here), causes
212         # anomalies that reject standards-complying URLs and
213         # potentially corrupt regular expressions in the config
214         # file.  The problems with the code are rampant.
215         # This is the only possible acceptable configuration.
216         # Worse yet, it can't even be set on a per-connection basis!
217         global {
218                 # yes, just always stomp on any misguided
219                 # global config for these items
220                 server.http-parseopts := (
221                         "url-path-2f-decode"       => "disable",
222                         "url-normalize-unreserved" => "enable",
223                         "url-path-dotseg-remove"   => "enable")
224         }
226         server.document-root = "@@webroot@@"
227         static-file.disable-pathinfo = "enable" # probably???
228         cgi.execute-x-only = "enable" # why is this not the default???
230         # The standard Apache Girocco configuration follows
231         # symlinks as a prerequisite to make ".htaccess" files work.
232         # That's not a consideration here, but to be compatible
233         # with any symlinks that might be in use, it's enabled.
234         server.follow-symlink = "enable"
236         # Send bare "/" directly to gitweb
237         url.rewrite-repeat = ( "^/(?:\?|$)" => "/w${qsa}" )
239         # The magic /[bchrw] prefix always forces selection of the
240         # prefix-indicated cgi handler.
242         $HTTP["url"] =~ "^/w(?:/|$)" {
243                 $REQUEST_HEADER["user-agent"] =~ var.botpat {
244                         $HTTP["query-string"] =~ "(?x)
245                                 a=(?:
246                                         blame |
247                                         blame_data |
248                                         blame_incremental |
249                                         blob_plain |
250                                         blobdiff |
251                                         diff |
252                                         snapshot |
253                                         commitdiff |
254                                         history |
255                                         refs |
256                                         shortlog
257                                 ) |
258                                 a=log.*?f= |
259                                 f=.*?a=log" {
260                                 url.access-deny = ( "" )
261                         }
262                         else $HTTP["url"] =~ "(?x)/(?:
263                                         blame |
264                                         blame_data |
265                                         blame_incremental |
266                                         blob_plain |
267                                         blobdiff |
268                                         diff |
269                                         snapshot |
270                                         commitdiff |
271                                         history |
272                                         refs |
273                                         shortlog
274                                 )" {
275                                 url.access-deny = ( "" )
276                         }
277                         else $HTTP["query-string"] =~ "(.*h=.*;)hb=[^;]*(.*)" {
278                                 url.redirect-code = 303
279                                 url.redirect = ( "^([^?#]*)" => var.rdrbase + "$1%1%2" )
280                         }
281                 }
282                 alias.url = ( "/w" => "@@cgiroot@@/gitweb.cgi" )
283                 fastcgi.server = ( "/w" => ( "gitweb" => (
284                         "socket" => var.fcgisockbase+"gitweb-@@tmpsuffix@@",
285                         "check-local" => "disable",
286                         #"bin-path" => "@@cgiroot@@/gitweb.cgi",
287                         "bin-path" => "@@basedir@@/bin/gitweb-gc.sh",
288                         "min-procs" => 1, # default is min(4, max-procs)
289                         "max-procs" => @@var_online_cpus@@, # default is 4
290                         "idle-timeout" => 180, # seconds (default is 60)
291                 )))
292         }
293         else $HTTP["url"] =~ "^/b(?:/|$)" {
294                 $REQUEST_HEADER["user-agent"] =~ var.botpat { url.access-deny = ( "" ) }
295                 alias.url = ( "/b" => "@@cgiroot@@/bundles.cgi" )
296                 cgi.assign = ( "" => "" )
297         }
298         # setenv.set-environment GIT_HTTP_BACKEND_BIN to override Config.pm $git_http_backend_bin
299         else $HTTP["url"] =~ "^/r(?:/|$)" {
300                 $REQUEST_HEADER["user-agent"] =~ var.botpat { url.access-deny = ( "" ) }
301                 setenv.set-environment += ( "REQUIRE_SSL_CLIENT_VERIFY_SUCCESS" => "1" )
302                 alias.url = ( "/r" => "@@basedir@@/bin/git-http-backend-verify" )
303                 cgi.assign = ( "" => "" )
304         }
305         # /h/ => html pages pre-generated via the html.cgi template script
306         else $HTTP["url"] =~ "^/h/.+\.html$" {
307                 mimetype.assign = ( "" => "text/html; charset=utf-8" )
308                 alias.url = ( "/h/" => "@@cgiroot@@/html/" )
309         }
311         # A top-level .cgi suffix selects that cgi if it's not gitweb, bundles or html
312         else $HTTP["url"] =~ "^/(?!(?i)gitweb\.cgi|bundles\.cgi|html\.cgi(?:/|$))([^/]+\.cgi(?:/.*)?)$" {
313                 alias.url = ( "/" => "@@cgiroot@@/" )
314                 cgi.assign = ( "" => "" )
315         }
317         # Any requests without the magic /[bchrw] are treated as Git requests if they
318         # are one of the few possible Git URLs otherwise they go to bundles or gitweb
320         # Change the setting of $SmartHTTPOnly in Girocco::Config.pm to
321         # change whether or not non-smart HTTP fetch access will be allowed.
323         @@if(!SmartHTTPOnly)@@
324         # This accelerates non-smart HTTP access to loose objects, packs and info
325         $HTTP["url"] =~ "(?x)
326                 ^/(?![bchw]/)(?:r/)?
327                 ((?:[a-zA-Z0-9][a-zA-Z0-9+._-]*(?<!\.git)/)*[a-zA-Z0-9][a-zA-Z0-9+._-]*?)(?:\.git)?/(
328                         HEAD |
329                         objects/info/alternates |
330                         objects/info/http-alternates |
331                         objects/info/packs |
332                         objects/[0-9a-f]{2}/[0-9a-f]{38} |
333                         objects/pack/pack-[0-9a-f]{40}\.(?:pack|idx) )$" {
334                 $REQUEST_HEADER["user-agent"] =~ var.botpat { url.access-deny = ( "" ) }
335                 url.rewrite-once = (
336                         "^[^?]*\.git/" => "", # skip rewrite if not needed
337                         "" => "/r/%1.git/%2"
338                 )
339                 alias.url = (
340                         "/r/" => "@@reporoot@@/",
341                         "/" => "@@reporoot@@/"
342                 )
343                 cgi.assign = ()
344         }
345         @@endif@@
346         @@if(SmartHTTPOnly)@@
347         # This can never match but allows an "else" to always be used next
348         $HTTP["url"] =~ "^(?=0)1" {}
349         @@endif@@
351         else $HTTP["url"] =~ "(?x)
352                 ^/(?![bchrw]/)
353                 ((?:[a-zA-Z0-9][a-zA-Z0-9+._-]*(?<!\.git)/)*[a-zA-Z0-9][a-zA-Z0-9+._-]*?)(?:\.git)?/(
354                         info/refs |
355                         git-upload-pack |
356                         git-receive-pack |
357                         [a-zA-Z0-9][a-zA-Z0-9+._-]*\.bundle )$" {
358                 url.rewrite-once = (
359                         "^[^?]*\.git/" => "", # skip rewrite if not needed
360                         "" => "/r/%1.git/%2${qsa}"
361                 )
362                 $REQUEST_HEADER["user-agent"] =~ var.botpat { url.access-deny = ( "" ) }
363                 setenv.set-environment += ( "REQUIRE_SSL_CLIENT_VERIFY_SUCCESS" => "1" )
364                 alias.url = ( "/" => "@@basedir@@/bin/git-http-backend-verify/" )
365                 cgi.assign = ( "" => "" )
366         }
368         # Everything else off to bundles.cgi or gitweb.cgi
369         else $HTTP["url"] =~ "(?x)
370                 ^/(?![bchrw]/)
371                 ((?:[a-zA-Z0-9][a-zA-Z0-9+._-]*(?<!\.git)/)*[a-zA-Z0-9][a-zA-Z0-9+._-]*?\.git/bundles)$" {
372                 $REQUEST_HEADER["user-agent"] =~ var.botpat { url.access-deny = ( "" ) }
373                 alias.url = ( "/" => "@@cgiroot@@/bundles.cgi/" )
374                 cgi.assign = ( "" => "" )
375         }
376         else $HTTP["url"] =~ "(?x)
377                 ^/(?![bchrw]/)
378                 ((?:[a-zA-Z0-9][a-zA-Z0-9+._-]*(?<!\.git)/)*[a-zA-Z0-9][a-zA-Z0-9+._-]*?\.git(?!/bundles)(?:/.*)?)$" {
379                 url.rewrite-once = ( "" => "/w/%1${qsa}" )
380         }
382         # mod_rewrite is always required for this lighttpd configuration
383         # which means the trailing ".git" is optional in some cases,
384         # the leading /h is optional for *.html, snapshots are
385         # always throttled, some bogus Git http protocol requests will be
386         # detected early and, if non-smart HTTP is allowed, access to the
387         # /info/refs file will be accelerated in non-smart HTTP mode.
389         # Make the leading /h optional for requests that name a first or second level .html template
390         # Without having file tests available, this is not as flexible.
391         else $HTTP["url"] =~ "^/(?![bchrw]/)(([a-zA-Z]+/)?[^/]+\.html)$" {
392                 mimetype.assign = ( "" => "text/html; charset=utf-8" )
393                 alias.url = ( "/" => "@@cgiroot@@/html/" )
394         }
396         # Redirect bare gitweb /w requests without .git
397         else $HTTP["url"] =~ "(?x)^/w/
398                 ((?:[a-zA-Z0-9][a-zA-Z0-9+._-]*(?<!\.git)/)*[a-zA-Z0-9][a-zA-Z0-9+._-]*(?<!\.git))$" {
399                 url.redirect = ( "" => var.rdrbase + "/w/%1.git${qsa}" )
400         }
402         # Redirect bare gitweb non-/w requests without .git
403         # Without having file tests available, this is problematic.
404         # It's necessary to avoid redirecting requests for static files
405         # that are part of the website itself, but we can do a reasonable approximation
406         # since we know that no users or project names will be allowed to be created
407         # with any of the case-insensitive extensions in %Girocco::Config::reserved_suffixes
408         else $HTTP["url"] =~ "(?x)
409                 ^/(?![bchrw](?:/|$))
410                 ((?:[a-zA-Z0-9][a-zA-Z0-9+._-]*(?<!\.git)/)*[a-zA-Z0-9][a-zA-Z0-9+._-]*(?<!\.git))$" {
411                 # This is a big gnarly mess!
412                 # We need to exclude any query string when checking for prohibited extensions.
413                 # And $HTTP["url"] conveniently lets us do that.
414                 # Attempting to do it in the `url.redirect` pattern itself means it would have to
415                 # be anchored to the beginning part up to and excluding any first `?` character.
416                 # Unfortunately, that causes a rather bad exponential explosion in `pcre_exec`
417                 # likely because the negative assertion patterns are anchored to the end.
418                 # Therefore we do the check in two stages, first against $HTTP["url"] only
419                 # anchored at the end and then let the redirect pattern match take care of
420                 # figuring out where the non-querystring part of the url ends to insert `.git`.
421                 $HTTP["url"] =~ "(?ix)
422                         @@reserved()@@ # replaced with reserved extension negative assertions
423                         $" {
424                         url.redirect = ( "^/([^?]*)(.*)$" => var.rdrbase + "/$1.git$2" )
425                 }
426         }
428         # Snapshot/blob_plain requests are only allowed via the PATH_INFO mechanism
429         $HTTP["query-string"] =~ "(?i)(^|[&;])a=(?:snapshot|blob_plain)([&;]|$)" {
430                 url.access-deny = ( "" )
431         }
433         # Redirect snapshot requests to snapshot.cgi
434         else $HTTP["url"] =~ "(?x)
435                 ^/(?![bchr]/)(?:w/)?
436                 ((?:[a-zA-Z0-9][a-zA-Z0-9+._-]*(?<!\.git)/)*[a-zA-Z0-9][a-zA-Z0-9+._-]*?\.git/
437                         snapshot(?:/.*)?)$" {
438                 alias.url = (
439                         "/w/" => "@@cgiroot@@/snapshot.cgi/",
440                         "/" => "@@cgiroot@@/snapshot.cgi/"
441                 )
442                 fastcgi.server = ()
443                 cgi.assign = ( "" => "" )
444         }
446         # The fancy .no_blob_plain processing is not handled with lighttpd...yet!
448         # Of the 11 possible Git protocol URLs (i.e. passed to git-http-backend-verify),
449         # 9 are only valid with GET/HEAD and the other two are only valid with POST
450         # Furthermore, 7 are only valid when non-smart is allowed and
451         # 1 is only valid when smart-only is enabled if it has the correct query string.
453         # These two always require POST
454         $HTTP["request-method"] != "POST" {
455                 $HTTP["url"] =~ "(?x)^/(?![bchw]/)(?:r/)?
456                         (?:[a-zA-Z0-9][a-zA-Z0-9+._-]*(?<!\.git)/)*[a-zA-Z0-9][a-zA-Z0-9+._-]*?(?:\.git)?/(?:
457                                 git-upload-pack |
458                                 git-receive-pack )$" {
459                         url.access-deny = ( "" )
460                 }
461         }
463         @@if(SmartHTTPOnly)@@
464         # These 7 are always forbidden when non-smart HTTP is disabled
465         $HTTP["url"] =~ "(?x)^/(?![bchw]/)(?:r/)?
466                 (?:[a-zA-Z0-9][a-zA-Z0-9+._-]*(?<!\.git)/)*[a-zA-Z0-9][a-zA-Z0-9+._-]*?(?:\.git)?/(?:
467                         HEAD |
468                         objects/info/alternates |
469                         objects/info/http-alternates |
470                         objects/info/packs |
471                         objects/[0-9a-f]{2}/[0-9a-f]{38} |
472                         objects/pack/pack-[0-9a-f]{40}\.(?:pack|idx) )$" {
473                 url.access-deny = ( "" )
474         }
475         # This one is forbidden without the magic query string when non-smart is disabled
476         $HTTP["url"] =~ "(?x)^/(?![bchw]/)(?:r/)?
477                         (?:[a-zA-Z0-9][a-zA-Z0-9+._-]*(?<!\.git)/)*[a-zA-Z0-9][a-zA-Z0-9+._-]*?(?:\.git)?/
478                                 info/refs $" {
479                 $HTTP["request-method"] !~ "^(?:GET|HEAD)$" {
480                         url.access-deny = ( "" )
481                 }
482                 else $HTTP["query-string"] !~ "(^|&)service=git-(?:upload|receive)-pack(&|$)" {
483                         url.access-deny = ( "" )
484                 }
485         }
486         # This one requires GET (or HEAD)
487         $HTTP["request-method"] !~ "^(?:GET|HEAD)$" {
488                 $HTTP["url"] =~ "(?x)^/r/
489                         (?:[a-zA-Z0-9][a-zA-Z0-9+._-]*(?<!\.git)/)*[a-zA-Z0-9][a-zA-Z0-9+._-]*?(?:\.git)?/
490                                 [a-zA-Z0-9][a-zA-Z0-9+._-]*\.bundle $" {
491                         url.access-deny = ( "" )
492                 }
493         }
494         @@endif@@
496         @@if(!SmartHTTPOnly)@@
497         # These 9 require GET (or HEAD)
498         $HTTP["request-method"] !~ "^(?:GET|HEAD)$" {
499                 $HTTP["url"] =~ "(?x)^/(?![bchw]/)(?:r/)?
500                         (?:[a-zA-Z0-9][a-zA-Z0-9+._-]*(?<!\.git)/)*[a-zA-Z0-9][a-zA-Z0-9+._-]*?(?:\.git)?/(?:
501                                 HEAD |
502                                 info/refs |
503                                 objects/info/alternates |
504                                 objects/info/http-alternates |
505                                 objects/info/packs |
506                                 objects/[0-9a-f]{2}/[0-9a-f]{38} |
507                                 objects/pack/pack-[0-9a-f]{40}\.(?:pack|idx) |
508                                 [a-zA-Z0-9][a-zA-Z0-9+._-]*\.bundle )$" {
509                         url.access-deny = ( "" )
510                 }
511         }
512         # This one can be accelerated when accessed with non-smart HTTP
513         $HTTP["request-method"] =~ "^(?:GET|HEAD)$" {
514                 $HTTP["query-string"] !~ "(^|&)service=git-(?:upload|receive)-pack(&|$)" {
515                         $HTTP["url"] =~ "(?x)^/(?![bchw]/)(?:r/)?
516                                 ((?:[a-zA-Z0-9][a-zA-Z0-9+._-]*(?<!\.git)/)*[a-zA-Z0-9][a-zA-Z0-9+._-]*?)(?:\.git)?/
517                                         info/refs $" {
518                                 $REQUEST_HEADER["user-agent"] =~ var.botpat { url.access-deny = ( "" ) }
519                                 url.rewrite-once = (
520                                         "^[^?]*\.git/" => "", # skip rewrite if not needed
521                                         "" => "/r/%1.git/info/refs"
522                                 )
523                                 alias.url = (
524                                         "/r/" => "@@reporoot@@/",
525                                         "/" => "@@reporoot@@/"
526                                 )
527                                 cgi.assign = ()
528                         }
529                 }
530         }
531         @@endif@@
533 @@if(!lighttpd_standalone)@@
534 } # "virtual" host @@httpdnsname@@
535 @@endif@@
537 # Change the setting of $TLSHost in Girocco::Config.pm to change
538 # whether or not the following TLS configuration is enabled.
540 @@if(TLSHost)@@
544 ## Lighttpd TLS Virtual Host Info
546 ## Yes, lighttpd can do TLS virtual hosting.
547 ## By default, if $Girocco::Config::lighttpd_standalone is false
548 ## and $Girocco::Config::TLSHost is true then this config file
549 ## will be set up for TLS virtual hosting.
551 ## But there's a catch.
553 ## For Lighttpd TLS virtual hosting, the correct server certificate
554 ## will be set inside a $HTTP["host"] conditional which will trigger
555 ## based on the incoming SNI (server name indication).
557 ## The gotcha is that Lighttpd requires a valid server certificate and
558 ## private key to always be set at the same level where TLS is enabled (either
559 ## the $SERVER["socket"] section or the global configuration).
561 ## This configuration will not do that (if $lighttp_standalone is false)
562 ## on the assumption that this configuration file has been included by
563 ## a global configuration that has already configured TLS to listen on the
564 ## intended address+port and has already provided a valid TLS server
565 ## certificate and private key for that TLS address+port.  In which case
566 ## when the incoming SNI matches our Girocco host, it will be overridden
567 ## with the Girocco server certificate and key configured in this file.
569 ## If that is not the case (when $lighttpd_standalone is false), then
570 ## lighttpd will complain at startup about a missing "ssl.pemfile" due
571 ## to the "ssl.enable" below.
573 ## If $Girocco::Config::lighttpd_tls_virtualhost is false, then the TLS
574 ## virtual host config part will be omitted (it's always omitted when
575 ## $lighttpd_standalone is true) even when not $lighttpd_standalone.
577 ## Recall that a correctly operating web browser (or other client such as git)
578 ## will NEVER SEND an SNI value when a literal IPv4 or IPv6 address has been
579 ## specified (i.e. https://127.0.0.1/ and https://[::1]/) which means that
580 ## when TLS virtual host mode is enabled an actual host name must be used
581 ## to get the correct certificate (i.e. https://localhost/).
584 $SERVER["socket"] == var.ipv4addr+":"+var.httpsport { # IPv4 TLS
586 # ---- BEGIN LINES TO DUPLICATE ----
588         # Activate TLS mode
590         ssl.engine = "enable"
591         @@if(lighttpd_standalone)@@
592         # cipher-list must be set or the default wide-open list will be used
593         ssl.cipher-list = "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!eNULL:!LOW:!MEDIUM:!RC4:!SSLv2:!CAMELLIA:!CHACHA20:!aGOST:!DSS:!ECDSA:@STRENGTH"
594         #ssl.read-ahead = "disable" # disable read-ahead on resource constrained systems
595         @@endif(lighttpd_standalone)@@
597         @@if(!lighttpd_standalone)@@
598         @@if(lighttpd_tls_virtualhost)@@
599         $HTTP["host"] == "@@httpdnsname@@" { # "virtual" host @@httpdnsname@@
600         @@endif(lighttpd_tls_virtualhost)@@
601         @@endif(!lighttpd_standalone)@@
603                 # These certificate files will all be automatically generated, but the
604                 # paths here may need to be corrected to match the paths
605                 # (especially $certsdir) from Config.pm
607                 ssl.pemfile = "@@certsdir@@/girocco_www_fullchain.pem"
608                 ssl.privkey = "@@certsdir@@/girocco_www_key.pem"
609                 # When using a www server cert signed by a pre-trusted root, only
610                 # the above two lines should be changed.  Changing either of the
611                 # below two lines will likely break https client authentication.
612                 ssl.ca-file = "@@certsdir@@/girocco_root_crt.pem"
613                 ssl.ca-dn-file = "@@certsdir@@/girocco_client_crt.pem"
615                 ssl.verifyclient.activate = "enable"
616                 ssl.verifyclient.enforce = "disable"
617                 ssl.verifyclient.depth = 3
618                 ssl.verifyclient.username = "SSL_CLIENT_S_DN"
620         @@if(!lighttpd_standalone)@@
621         @@if(lighttpd_tls_virtualhost)@@
622         } # "virtual" host @@httpdnsname@@
623         @@endif(lighttpd_tls_virtualhost)@@
624         @@endif(!lighttpd_standalone)@@
626 # ---- END LINES TO DUPLICATE ----
630 $SERVER["socket"] == "["+var.ipv6addr+"]:"+var.httpsport { # IPv6 TLS
632 # ---- BEGIN DUPLICATE LINES ----
634 ##  *** IMPORTANT ***
636 ##  ALL the entire contents from the '$SERVER["socket"] ==' section above
637 ##  must be copied here.
639 ##  To avoid this duplication, the contents of the '$SERVER["socket"] =='
640 ##  section above can be moved to a separate file and then included both
641 ##  here and above using an include directive.  Be careful not to place
642 ##  the new include file in one of the directories the standard
643 ##  configuration blindly includes all files from.
645 # ---- END DUPLICATE LINES ----
649 @@endif(TLSHost)@@