Main Configuration
At the heart of each webserver is the configuration file. It controls the whole behaviour and therefore has to be mighty but at the same time easy enough to get the desired results without hassle.
In the lighttpd config you control how it reacts on requests. To achieve this you have to express some kind of logic – just like in a programming language.
Basic Syntax
The syntax for the lighttpd 2.0 configuration file is somewhat similar to various programming languages – kind of a mixture. But don’t be afraid, it is really simple. No pointers involved :)
The basic blocks are values, variables, function calls and conditions.
Values
Boolean
There are two boolean values:
true
false
Integers
Integers are stored as signed ints with 64 bits (max value around 9 * 10^18). There are three basic ways to use them:
- decimal integers: starting with any non zero digit, like
128
- octal integers: starting with a zero, like
0644
- hexadecimal integers: starting with
0x
like0xff
All three can have a suffix representing a factor the number gets multiplied with:
-
byte
:1
-
kbyte
:1024
-
mbyte
:1024*1024
-
gbyte
:1024*1024*1024
-
tbyte
:1024*1024*1024*1024
-
pbyte
:1024*1024*1024*1024*1024
-
bit
:1 / 8
-
kbit
:1024 / 8
-
mbit
:1024*1024 / 8
-
gbit
:1024*1024*1024 / 8
-
tbit
:1024*1024*1024*1024 / 8
-
pbit
:1024*1024*1024*1024*1024 / 8
-
sec
:1
-
min
:60
-
hours
:3600
-
days
:24*3600
For sizes the base unit is byte, and for intervals seconds.
Strings
There are 4 ways to specify a string:
'hello world'
"hello world"
e'hello world'
e"hello world"
The basic escape rules are the same for both:
-
"\n"
is a newline,"\r"
a carriage return,"\t"
a tab stop -
"\\"
is one\
,"\""
is one double quote"
and"\'"
a single quote'
- escaping single/double quote is optional if the symbol is not used to terminate the string, i.e.
'\"'
='"'
and"\'"
="'"
-
"\xNN"
: NN must be hexadecimal characters, and the string is replaced with the decoded 8-bit value as a single byte - All other
\
occurences are not removed from the string.
The e'..'
and e"..."
variant do not allow any occurences of the last kind to happen.
All other characters are allowed (the strings are parsed as 8-bit binary; lighttpd2 usually doesn’t care about the encoding).
Lists
Lists are ordered collections of other values:
-
[1, true, "foo"]
(simple list) -
[]
(empty list) -
[1]
(list with one element) -
[[1,2],[3,4],5]
(nested lists) -
[1,2,]
(final value can have a trailing,
too) -
(1, 2, 3)
(alternative brackets with more than one element)
Note that (1)
is not a list; parentheses can also be used to group expressions as in 1*(2+3)
, and it is therefore recommend to use only []
to specify lists.
Key-Value Lists
Key-value lists associates keys to values (both can be of any type); the syntax is:
[ "a" => 1, "b" => 10 ]
As with normal lists the final value can have a trailing ,
too. You cannot mix simple values and key-value associations in one list (nesting them works).
The key => value
operator is also only syntactic sugar for a [key, value]
list, the above example is the same as:
[ [a, 1], [b, 10] ]
This especially means that key-value lists are ordered too, although they can get converted to hash tables in certain function calls internally.
Expressions
There are operators available for some value types:
- for integers:
+
,-
,*
and/
- for strings:
+
(concatenate two strings) - for lists:
+
(append lists)
Also you can cast strings and booleans to integers and any value to strings:
-
cast(int) "256"
(only supports decimal representations and no suffix like above) -
cast(int) true
(true
maps to1
andfalse
to0
) cast(string) 5
Expressions can be grouped to override default association:
-
3 * (1 + 2)
vs.3 * 1 + 2
and so on
Action Blocks
An action block consists of a list of function calls (in action context) and conditionals; it is treated like a value, i.e. can be assigned to variables and used as parameter in function calls.
Action blocks can also contain variable assignments and setup blocks/function calls, which are not part of the “action block value” itself, but are evaluated while parsing the config.
The syntax is:
{
log "hello world";
if req.path =$ ".hidden" { static; }
}
The complete config is an action block too (but without the surrounding curly braces); conditionals also use action blocks for their branches.
Each action block that is not a condition branch starts a new nested variable scope;
Variables
Variable names start with a alphabetic character (a-z
and A-Z
) or an underscore _
, and are followed by alphanumeric characters, underscores _
and dots .
; keywords are not allowed as variable names.
Variables store values, and the name can be used in place of an actual value; later modifications to a variable have no influence on previous uses (i.e. are only evaluated while parsing the config).
Variables are assigned values with =
(and a terminating ;
)
my_types = [".txt" => "text/html"];
php = {
if phys.path =$ ".php" { fastcgi "unix:/var/run/lighttpd/php.sock"; }
};
By default variables assignment overwrites an existing variable (in its previous scope) or, if it doesn’t exist, creates a new one in the local scope (i.e. it will only be available in the current scope and nested descendants).
You can explicitly create a new variable in the local scope (hiding variables in parent scopes with the same name) by prefixing the assignment with local
:
local wwwpath = "/var/www/example.com";
You can also create variables in the global scope by prefixing the assignment with global
.
The main config already is in a nested scope (i.e. not the global scope). The global scope is not destroyed after config loading, and can be used in delayed config loading (say from SQL in the future).
If a variable name is used in a context it will always use the definition from the nearest scope.
Example
This example illustrates that variables are evaluated while parsing the config.
foo = "bar";
if req.path == "/somepath" {
foo = "baz";
}
# at this point foo will ALWAYS contain "baz" no matter if "/somepath" was requested or not
Example
This example illustrates scoping.
foo = "bar";
php = {
local foo = "baz";
# in this block (and nested blocks within) foo is now "baz"
# ...
};
# foo is now "bar" again
Special Variables
sys.*
variables are readonly. right now the following sys.*
variables are available:
-
sys.pid
: the process id of lighttpd -
sys.cwd
: the current working directory -
sys.env.X
: the system environment variable with nameX
(for anyX
)
Function calls
There are three types of function calls:
- actions
- setups
- options
Actions can only be used in action (block) context, setups only in setup (block) context, and options can be used in both.
A setup context is started with the keyword setup
, and is followed by either a single setup function call or a setup block.
Setup function calls are run immediately when they occur (they are used to “setup” the webserver environment, like listening on TCP sockets, and setting default options), while action function calls are run for each request (mapping request urls to physical paths, handling requests, modifying the default options).
The actions, setups and options are provided by the modules.
Includes
Includes are similar to function calls in the syntax, but are directly handled by the config parser. They are only allowed in action context, as they insert a reference to an action block at the point they are used.
There are three types of includes:
-
include "/etc/lighttpd/vhosts/*.conf";
: include files like the main config itself; the path can contain wildcards -
include_shell "/etc/lighttpd/config_generator.sh";
: runs the specified command, and parses the output of it as config file -
include_lua "/etc/lighttpd/complex.lua"
: includes a Lua config file. The single action to be executed must be returned in the globalactions
variable (or leave it empty to do nothing). See alsolua.handler
.
Includes also create a new nested scope.
Debug Print
Similar to includes __print
is a special function, but is available in action and setup context. It logs the string values of its parameter(s) with log level “debug”.
Conditions
Conditions (known from Lighttpd 1.x) are the equivalent to “if”s in most programming languages. There are also “else” and “elseif” equivalents.
They are created by a comparison of a condition variable and a value that is evaluated at runtime (for each request).
Conditions can be nested, and you can group them with and
and or
operators. and
binds stronger than or
, although it is preferred to group them with parentheses.
Example
if req.host == "mydomain.tld" {
if req.path == "/" or req.path == "/index.html" {
static;
} else if req.path == "/upload" {
if req.content_length > 100mbyte {
access.deny;
} else {
proxy "127.0.0.1:8080";
}
}
}
Syntax
The basic syntax forms are:
if <expr> { ... }
if <expr> { ... } else { ... }
if <expr> { ... } else if <expr2> { ... }
-
if <expr> { ... } else if <expr2> { ... } ...
(continue withelse
orelse if
)
A condition expression <expr>
is:
(<expr>)
<expr1> and <expr2>
-
<expr1> or <expr1>
(<expr1> and <expr2> or <expr3>
=(<expr1> and <expr2>) or <expr3>
;and
has higher precedence) -
<condvar> <op> <value>
for<condvar>
being a condition variable (with a type different from boolean),<op>
an condition operator and<value>
a string or a number. -
<condvar>
or!<condvar>
for a boolean condition variable.
Condition variables
There are three categories of condvars:
- request.xyz (can be abbreviated by req.xyz)
- physical.xyz (can be abbreviated by phys.xyz)
- response.xyz (can be abbreviated by resp.xyz)
variable | description |
---|---|
request.localip | ip address of the listing socket, the client connected to (filename for unix sockets) |
request.localport | port number of the listening socket, -1 for unix sockets |
request.remoteip | ip address of the client |
request.remoteport | port number of the client, -1 for unix sockets |
request.path | the path part of the requested url. not including the querystring. |
request.raw_path | the raw path (not urldecoded, not simplified) of the requested url, including the querystring. |
request.host | requested hostname |
request.scheme | scheme of the request. “http” or “https” |
request.query | the querystring of the requested url |
request.method | method of the request. “GET”, “POST”, “HEAD” etc. |
request.length | integer. length of the content for e.g. POST methods |
request.header[“name”] | request header name e.g. request.header[“referer”] |
request.is_handled | boolean condition, does request already have a handler (static, fastcgi..) |
request.environment[“name”] | (or short request.env[“name”]) CGI environment |
physical.path | physical path of the file to be served. e.g. document root + path |
physical.exists | boolean condition, indicates whether the requested file (normal file, directory or even a special file) exists |
physical.size | integer. size of the requested file. -1 if file doesn’t exist |
physical.is_dir | boolean condition, indicates whether the requested file is a directory |
physical.is_file | boolean condition, indicates whether the requested file is a normal file (e.g. no unix socket etc) |
physical.docroot | document root |
physical.pathinfo | pathinfo |
response.status | response status code (blocks request until response header is available) |
response.header[“name”] | response header (blocks request until response header is available) |
Condition operators
op | description | op | description |
---|---|---|---|
== | compares two values on equality | != | negative == |
<= | less than or equal | < | less than |
>= | greater than or equal | > | greater than |
=~ | regular expression match | !~ | negative =~ |
=^ | prefix match | !^ | negative =^ |
=$ | suffix match | !$ | negative =$ |
=/ | cidr match | !/ | negative =/ |