[Solved] Problem with conditionals and hostnames
Added by flynn about 2 months ago
I use the conditional $HTTP["host"]
often twice (or more) for the same hostname, but in different combinations or regular expressions.
I observed, that some configuration directives like alias.url +=
are later ignored for only one of these hostnames.
- first
$HTTP["host"]
conditional for certificates:$HTTP["host"] =~ "^(a|b|c|d)\.bla\.de$" { ssl.pemfile = "bla/fullchain.pem" ssl.privkey = "bla/privkey.pem" ssl.stapling-file = "bla/pem.ocsp" } $HTTP["host"] =~ "^(a|b|c|d)\.blabla\.de$" { ssl.pemfile = "blabla/fullchain.pem" ssl.privkey = "blabla/privkey.pem" ssl.stapling-file = "blabla/pem.ocsp" }
- later second
$HTTP["host"]
condittional for logfile, alias, ...$HTTP["host"] =~ "^a\.(bla|blabla)\.de$" { $HTTP["scheme"] == "https" { server.document-root = "/var/www/a/" accesslog.filename = "/var/log/lighttpd/a-access.log" alias.url += ... } }
Now
- the directives server.document-root
and accesslog.filename
are active for both hostnames
- the directive alias.url
is ignored/does not work for the hostname a.bla.de (return code 404), but works for a.blabla.de (return core 200), which is second in the first conditional block!
As workaround I have to comment out/deactivate the conditional $HTTP["scheme"] == "https"
, then it works for both hostnames again.
Is this wrong configured, not supported or a bug?
Replies (6)
RE: Problem with conditionals and hostnames - Added by gstrauss about 2 months ago
It sounds like this may be a known limitation / design choice.
You did not share your entire config, but there may be an alias.url
directive in a conditional later in the config which matches the request and overrides the "later second $HTTP["host"]
conditional" you posted above.
See Configuration: File Syntax - Conditional Configuration Merging
The lighttpd configuration is parsed at startup and then is static. The static configuration is evaluated against each request, but +=
across configuration conditionals is not dynamically recalculated for each request.
Nested conditionals may work with +=
since at startup, a value in an outer conditional can be copied and added to in a nested conditional, and then part the static parsed configuration.
The same conditional repeated at the same nesting level within the same conditional block gets merged into a single conditional, IIRC.
What happens if you reverse the nested conditions?
$HTTP["scheme"] == "https" { $HTTP["host"] =~ "^a\.(bla|blabla)\.de$" { server.document-root = "/var/www/a/" accesslog.filename = "/var/log/lighttpd/a-access.log" alias.url += ... } }
RE: Problem with conditionals and hostnames - Added by flynn about 2 months ago
Reverse the nested conditions solves the problem - thank you.
BTW: can you please clarify, when using else
with conditionals make sense, especially:
- conditionals for many certificates
- configuration for many virtual hosts
- it is big: lighttpd -p ... results in more than 4000 lines
- it contains too much private information
- I did not find the time, to reduce it to a reasonable size for this issue
RE: Problem with conditionals and hostnames - Added by gstrauss about 2 months ago
Reverse the nested conditions solves the problem - thank you.
That suggests to me there was something else in your configuration that set alias.url
which overrode the setting you shared. Reversing the conditionals probably put something at a different level and allowed same conditionals with identical scope to be merged.
BTW: can you please clarify, when using
else
with conditionals make sense, especially:
- conditionals for many certificates
- configuration for many virtual hosts
Use whatever works well for sane logical constructs.
For many certificates, and if your organizational structure allows, it can be is more efficient to have a wildcard certificates for *.example.org, if applicable, or to have a fewer number of certificates grouped by ownership and having multiple Subject Alternative Names (SAN) in the certificate, rather than a single domain per certificate.
lighttpd conditional matching is generally quite fast. Still, if you do have a separate certificate for each and every vhost, then for large configurations, you might notice a difference in performance if you help lighttpd optimize the tree of conditionals
$HTTP["host"] == "abc" { ssl.pemfile = "..." } $HTTP["host"] == "def" { ssl.pemfile = "..." } $HTTP["host"] == "ghi" { ssl.pemfile = "..." }
For the above, lighttpd will try to match all three conditionals for every TLS request.
That is less efficient than the following, which will stop at the first match.
$HTTP["host"] == "abc" { ssl.pemfile = "..." } else $HTTP["host"] == "def" { ssl.pemfile = "..." } else $HTTP["host"] == "ghi" { ssl.pemfile = "..." }
Another tip to reduce configuration processing is to put shared config into the global scope, and then to configure conditionals only for exceptions when there are only a few exceptions.
RE: Problem with conditionals and hostnames - Added by gstrauss about 2 months ago
Additional links for reference:
Resource Tuning
Performance Tuning
RE: Problem with conditionals and hostnames - Added by gstrauss about 2 months ago
More performance: instead of having an access log per vhost, consider having a single access log, and modifying the log format to include the vhost name. Then, log can be post-processed to split out the logs, e.g. after log rotation, or lighttpd mod_accesslog can be configured to log to a piped-logger which could split out the logs. Various choices are available depending on how and when your organization accesses and uses the logs.
RE: Problem with conditionals and hostnames - Added by gstrauss 27 days ago
Sometimes, it may be useful to set a default for the majority in the config, and then to undo that setting for the (few) exceptions.
# default: redirect http to https $HTTP["scheme"] == "http" { url.redirect = ("" => "https://${url.authority}${url.path}${qsa}") url.redirect-code = 308 } $HTTP["host"] == "exception1.example.org" { # undo the default redirect set by all previous conditions in the config file url.redirect = () } $HTTP["host"] == "exception2.example.org" { # undo the default redirect set by all previous conditions in the config file and set different url.redirect conditions url.redirect = ("^/foo" => "/bar") url.redirect-code = 308 }
Note: the latter conditions above undo the default redirect set by all previous conditions in the config file unless there was another
$HTTP["host"] "exception1.example.org"
higher up in the same nesting scope and that condition was merged with the first occurrence $HTTP["host"] "exception1.example.org"
in the same nesting scope.