Lighttpd [Link] uses fewer resources than Apache2 or Nginx, making it ideal for handling a lot of traffic with less memory and CPU.

It’s a great choice for low-powered devices like the Raspberry Pi Zero. While other web servers can work too, Lighttpd will likely perform better on such limited hardware.


INSTALLING WEB SERVER PLUS PHP

sudo apt update && sudo apt upgrade -y
sudo apt install lighttpd -y
sudo apt install php7.4 php7.4-fpm php7.4-mysql php7.4-cli php7.4-curl php7.4-xml curl -y
sudo nano /etc/php/7.4/fpm/pool.d/www.conf
;listen = /run/php/php7.4-fpm.sock
listen = 127.0.0.1:9000
                #"bin-path" => "/usr/bin/php-cgi",
                #"socket" => "/var/run/lighttpd/php.socket",
                "host" => "127.0.0.1",
                "port" => "9000",
sudo lighty-enable-mod fastcgi
sudo lighty-enable-mod fastcgi-php
sudo systemctl restart lighttpd php7.4-fpm
rm /var/www/html/index.lighttpd.html
echo '<?php echo "HTTP_HOST: " . $_SERVER["HTTP_HOST"] . " SERVER_NAME: " . $_SERVER["SERVER_NAME"] ?>' | sudo tee /var/www/html/index.php
sudo chown -R www-data: /var/www/html/
sudo chmod -R 755 /var/www/html/

At this point, any HTTP request to this server will be served with the same page. Consider using Virtual Hosts to serve multiple sites based on the Host header.


SETTING A VIRTUAL HOST

sudo nano /etc/lighttpd/lighttpd.conf
...
include_shell "/usr/share/lighttpd/create-mime.conf.pl"
include_shell "cat /etc/lighttpd/vhosts.d/*.conf"
include "/etc/lighttpd/conf-enabled/*.conf"
...
sudo mkdir -p /etc/lighttpd/vhosts.d/
sudo nano /etc/lighttpd/vhosts.d/localhost.conf
$HTTP["host"] =~ "(^|.)localhost$" {
    server.document-root = "/var/www/html/localhost"
}
sudo mkdir -p /var/www/html/localhost
echo 'VHOST: localhost' | sudo tee /var/www/html/localhost/index.html
sudo lighttpd -t -f /etc/lighttpd/lighttpd.conf && sudo systemctl restart lighttpd.service
curl http://127.0.0.1
curl http://localhost

The first request is served by the default site, while the second returns content from the virtual host.


DEPLOYING A SELF-SIGNED CERTIFICATE

Replace the fake domain example.com accordingly.

sudo mkdir -p /etc/lighttpd/ssl/example.com
cd /etc/lighttpd/ssl/example.com
sudo apt install lighttpd-mod-openssl -y
sudo lighttpd-enable-mod ssl
sudo openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes
sudo nano /etc/lighttpd/conf-enabled/10-ssl.conf
# /usr/share/doc/lighttpd/ssl.txt
server.modules += ( "mod_openssl" )
$HTTP["scheme"] == "http" {
    $HTTP["host"] =~ ".*" {
        url.redirect = (".*" => "https://%0$0")
    }
}
$SERVER["socket"] == "0.0.0.0:443" {
        ssl.engine  = "enable"
        ssl.pemfile = "/etc/lighttpd/ssl/domain.com/server.pem"
        ssl.cipher-list = "HIGH"
}
sudo lighttpd -t -f /etc/lighttpd/lighttpd.conf && sudo systemctl restart lighttpd.service

ISSUING A FREE PUBLIC CERTIFICATE

Replace the fake domain example.com with a real public domain that has a DNS record pointing to the web server.

add-apt-repository ppa:certbot/certbot && sudo apt install certbot -y
sudo lighttpd-enable-mod ssl
sudo certbot certonly --webroot -w /var/www/html -d example.com -d www.example.com
ls -l /etc/letsencrypt/live/example.com
sudo nano /etc/lighttpd/lighttpd.conf
# /usr/share/doc/lighttpd/ssl.txt
server.modules += ( "mod_openssl" )
$HTTP["scheme"] == "http" {
    $HTTP["host"] =~ ".*" {
        url.redirect = (".*" => "https://%0$0")
    }
}
$SERVER["socket"] == "0.0.0.0:443" {
        ssl.engine  = "enable"
        ssl.pemfile = "/etc/letsencrypt/live/example.com/fullchain.pem"
        ssl.privkey = "/etc/letsencrypt/live/example.com/privkey.pem"
        ssl.cipher-list = "HIGH"
}
sudo lighttpd -t -f /etc/lighttpd/lighttpd.conf && sudo systemctl restart lighttpd.service

RENEWING THE PUBLIC CERTIFICATE

Certbot (using Let’s Encrypt) does not automatically renew the free 90-day public certificates.

The following manual renewal command can be scheduled as a cronjob to run periodically:

sudo certbot renew --force-renewal -d example.com -d www.example.com

BONUS

Reverse proxy for a VHOST:

$HTTP["host"] =~ "(^|.)example.com$" {
    proxy.server = ( "" => ( ( "host" => "127.0.0.1", "port" => 8080 ) ) )
}

Reverse proxy for a PATH rewriting the HEADER:

$HTTP["url"] =~ "(^/path)" {
    proxy.header = ( "map-urlpath" => ( "/path" => "/") )
    proxy.server = ( "" => ( ( "host" => "127.0.0.1", "port" => 8080 ) ) )
}

Another way to create a self-signed certificate:

sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/ssl/private/apache-selfsigned.key -out /etc/ssl/certs/apache-selfsigned.crt

Note: the different file output format.


REFLECTIONS

Lighttpd is a lightweight web server well suited for low-resource systems. For better performance and security, consider placing it behind a reverse proxy that handles SSL/TLS encryption. A CDN like Cloudflare can also help protect your site and manage encrypted connections.

Make sure to tighten your firewall settings and allow only the traffic you need. If you’re using a CDN, restrict access so that only the CDN’s IP ranges can connect.

If your site handles sensitive data such as passwords, you should at minimum use a self-signed certificate to provide basic encryption.