Production Web server: Lighttpd

lighttpd is a simple, standards-compliant, secure, and flexible web server. 
== Lighttpd Installation ==
This production environment will handle only the necessary packages... so no doc or manpages allowed.
# make the htdocs public web root directories 
# added the service to the default runlevel, not to boot, because need networking activated
# start the web server service
<nowiki>
mkdir -p /var/www/localhost/htdocs /var/log/lighttpd /var/lib/lighttpd
chown -R lighttpd:lighttpd /var/www/localhost/ /var/log/lighttpd /var/lib/lighttpd 
rc-update add lighttpd default
rc-service lighttpd restart
echo "it works" > /var/www/localhost/htdocs/index.html
</nowiki>
For testing, open a browser and go to http://<webserveripaddres> and you will see "it works". The "webserveripaddres" is the ip address of your setup/server machine.
=== Controlling Lighttpd ===
Start lighttpd:
You will get feedback about the status.
 * Caching service dependencies [ ok ]
 * Starting lighttpd... [ ok ]
Stop lighttpd:
Restart lighttpd: After changing the configuration file, lighttpd needs to be restarted.
Proper Runlevel: By default no services are added to start process, sysadmin must know what we want and what will services do, also other main reason are due in dockers there's no runlevels per se and Alpine linux are mostly used in dockers containers. You must added the service only to the default runlevel, not to boot, because need networking activated
== Lighttpd Configuration ==
If you just want to serve simple HTML pages, lighttpd can be used out-of-box. No further configuration needed.
lighttpd configuration options
=== Status page ===
Taking care of the status web server: those special pages are just minimal info of the running web server, are need to view from outside in a case of emergency, do not take the wrong approach of hide behind a filtered ip or filtered network, you must have access in all time in all the web to see problems.
mod_status
# Enable the mod_status at the config files
# change path in the config file (optional), we are using security by obfuscation
# restart the service to see changes at the browser
<nowiki>
sed -i -r 's#\#.*mod_status.*,.*# "mod_status",#g' /etc/lighttpd/lighttpd.conf
sed -i -r 's#.*status.status-url.*=.*#status.status-url = "/stats/server-status"#g' /etc/lighttpd/lighttpd.conf
sed -i -r 's#.*status.config-url.*=.*#status.config-url = "/stats/server-config"#g' /etc/lighttpd/lighttpd.conf
rc-service lighttpd restart
</nowiki>
=== CGI bin directory support ===
By default packages assign a directory under localhost main domain, other linux uses a global cgi directory and aliasing.. the most professional way, but think about it, this per domain configuration allows isolation:
mod_cgi
# enable the mod_alias at the config file, due need of a specific path for cgi files into security
# create the directory
# enable the config cgi file
# restart the service to see changes at the browser
<nowiki>
mkdir -p /var/www/localhost/cgi-bin
sed -i -r 's#\#.*mod_alias.*,.*# "mod_alias",#g' /etc/lighttpd/lighttpd.conf
sed -i -r 's#.*include "mod_cgi.conf".*# include "mod_cgi.conf"#g' /etc/lighttpd/lighttpd.conf
rc-service lighttpd restart
</nowiki>
After that, all the files under the /var/www/localhost/cgi-bin directory will be accessed under http://localhost/cgi-bin/ path
.cgi and .pl scripts are run using /usr/bin/perl. Review and modify mod_cgi.conf others are needed. Then restart lighttpd to pick up the changes.
=== Make special errors (404 or 500) pages for clients and visitors ===
These pages will be shown to visitors when a page or path is not present on the server, or when an internal error happens. 
These replace the default, minimal error pages and can be a nice message or "away from here" message:
server.errorfile-prefix
# create the directory for put the html files to show when those errors occur
# create the simple files for each message in the directory
# set the proper in the configuration file
# restart the service to see the changes at the browser (just request a non existing page and you will see it)
<nowiki>
mkdir -p /var/www/localhost/errors
cat > /var/www/localhost/errors/status-404.html << EOF
The page that you requested are not yet here anymore, sorry was moved or updated, search or visit another one
EOF
cat > /var/www/localhost/errors/status-500.html << EOF
Please wait a moment, there's something happens and we are give support maintenance right now to resolve
EOF
cp /var/www/localhost/errors/status-404.html /var/www/localhost/errors/status-403.html
cp /var/www/localhost/errors/status-500.html /var/www/localhost/errors/status-501.html
cp /var/www/localhost/errors/status-500.html /var/www/localhost/errors/status-503.html
sed -i -r 's#.*server.errorfile-prefix.*#server.errorfile-prefix = var.basedir + "/errors/status-"#g' /etc/lighttpd/lighttpd.conf
rc-service lighttpd restart
</nowiki>
=== Userdir public_html support ===
mod_userdir
== Lighttpd SSL support ==
lighttpd TLS doc
Create TLS configuration for lighttpd. Best way to do that is by external include files. Debian counterpart has a good mechanism that enables configuration files. We will add SSL support in a similar way.
=== SSL : making self signed certificate ===
We need to created a self-signed certificate if we do not already have one:
# install openssl
# create the self signed certificate
# set proper permissions
# create a SSL module configuration file for lighttpd
# activate the openssl module missing from config file
# activate the mod_redirect in case of global http to https redirections
# restart the service to see changes
<nowiki>
apk add openssl
mkdir -p /etc/ssl/certs/
openssl req -x509 -days 1460 -nodes -newkey rsa:4096 \
 -subj "/C=VE/ST=Bolivar/L=Upata/O=VenenuX/OU=Systemas:hozYmartillo/CN=$(hostname -d)" \
 -keyout /etc/ssl/certs/$(hostname -d).pem -out /etc/ssl/certs/$(hostname -d).pem
chmod 640 /etc/ssl/certs/$(hostname -d).pem
cat > /etc/lighttpd/mod_ssl.conf << EOF
server.modules += ("mod_openssl")
\$SERVER["socket"] == "0.0.0.0:443" {
 ssl.engine = "enable"
 ssl.pemfile = "/etc/ssl/certs/$(hostname -d).pem"
}
\$HTTP["scheme"] == "http" {
 url.redirect = ("" => "https://\${url.authority}\${url.path}\${qsa}")
 url.redirect-code = 308
}
EOF
sed -i -r 's#\#.*mod_redirect.*,.*# "mod_redirect",#g' /etc/lighttpd/lighttpd.conf
checkssl="";checkssl=$(grep 'include "mod_ssl.conf' /etc/lighttpd/lighttpd.conf);[[ "$checkssl" != "" ]] && echo listo || sed -i -r 's#.*include "mime-types.conf".*#include "mime-types.conf"\ninclude "mod_ssl.conf"#g' /etc/lighttpd/lighttpd.conf
rc-service lighttpd restart
</nowiki>
For deploy usage of Lets Encrypt without chain-tools (just add water) read HowToSimpleSSL.
== Lighttpd advanced ==
Lighttpd has pretty good default settings, but a few might be tweaked if we need to respond to higher server loads.
lighttpd resource tuning
=== Lighttpd tunning for aggressive load ===
lighttpd performance tuning
=== More connections, More File Descriptors ===
This must be used with caution. Everything is a file to a UNIX operating system. Well, every time a visitor accesses a page, lighttpd uses three file descriptors: An IP socket to the client, a FastCGI process socket, and a filehandle for the document accessed. Lighttpd stops accepting new connections when 90% of the available sockets are in use, restarting again when usage has fallen to 80%. With the default setting of 1024 file descriptors, lighttpd can handle a maximum of 307 connections. If this number are exceded file descriptor must be increrased then. This are a delicate tune due must be check your default with cat /proc/sys/fs/file-max and make sure it’s over 10,000:
<nowiki>
checkset="";checkset=$(grep 'max-fds' /etc/lighttpd/lighttpd.conf);[[ "$checkset" != "" ]] && echo listo || sed -i -r 's#server settings.*#server settings\nserver.max-fds = 2048\n#g' /etc/lighttpd/lighttpd.conf
rc-service lighttpd restart
</nowiki>
=== HTTP Keep-Alive for aggressive load ===
One reason that file descriptors get used up so quickly is HTTP keep-alive. To improve performance, modern web servers keep client connections alive to handle multiple requests instead of building up and tearing down connections for each item in a page. Keep-alive is tremendously beneficial to performance, but tends to keep unnecessary connections alive, too. lighttpd allows 1000 keep-alive requests per connection, allows idle sessions to remain alive for 5 seconds, and gives reads and writes 1 minute and 6 minutes to complete, respectively.
# Maximum number of request within a keep-alive session before the server terminates the connection, default = 1000 (server.max-keep-alive-requests)
# Maximum number of seconds until an idling keep-alive connection is dropped, default = 5 (server.max-keep-alive-idle)
# Maximum number of seconds until a waiting, non keep-alive read times out and closes the connection, default = 60 (server.max-read-idle)
# Maximum number of seconds until a waiting write call times out and closes the connection, default = 360 (server.max-write-idle)
Although lighttpd has pretty aggressive defaults (especially compared to Apache), a period of heavy traffic and a few slow clients could see many unused connections sticking around. The server.max-keep-alive-idle setting default of 5 seconds can be reduced to as low as 2, if you assume your clients are reasonably quick about requesting data, but a value of 3 or 4 is probably realistic. You may want to increase the server.max-keep-alive-requests value from the default of 1000, but you probably don’t need to. The server.max-read-idle and server.max-write-idle settings are tempting targets, but these situations are usually fairly rare so let’s not monkey with them.
=== Lighttpd_Advanced_security ===
See at Lighttpd_Advanced_security wiki page.
=== Lighttpd and PHP with fpm ===
In production web, LAMP means Linux + Apache + Mysql + Php installed and integrated, but today the "A" of apache are more used as Nginx or Lighttpd, and the "M" of MySQL are more used as Mariadb, the LAMP focused documents are:
* LAMP deploy of the Web Server with PHP, user html_dir and MariaDB: Production LAMP system: Lighttpd + PHP + MySQL
= See Also =
* Production LAMP system: Lighttpd + PHP + MySQL
Category:Newbie
Category:Server
Category:Web_Server
Category:Monitoring
Category:Development
Category:Security
Category:Production