Application Servers Azure

lighttpd on Ubuntu 24.04 on Azure User Guide

| Product: lighttpd on Ubuntu 24.04 LTS on Azure

Overview

This guide covers the deployment and configuration of lighttpd on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. lighttpd, pronounced lighty, is a secure, fast and flexible web server optimised for high performance environments. Its small memory footprint and efficient event driven design make it an excellent choice for serving static websites and assets, fronting application back ends, and running on resource constrained instances where efficiency matters.

The image installs lighttpd 1.4.x from the Ubuntu 24.04 package repository, run under systemd as the standard unprivileged www-data account. lighttpd serves HTTPS on port 443 directly through its mod_openssl TLS engine, so there is no separate reverse proxy to run or maintain. Plain HTTP on port 80 is permanently redirected with a 301 status to HTTPS. There is no web interface and no database: a single readable configuration file (/etc/lighttpd/lighttpd.conf plus the cloudimg drop in at /etc/lighttpd/conf-enabled/50-cloudimg.conf) is the whole configuration.

Secure and lean by default. On the first boot of every VM a one shot service generates a unique self signed TLS certificate for that specific instance, so no certificate or private key is ever baked into the image. Directory listing is disabled, so a directory that has no index file returns 403 rather than exposing its contents, and the server version token is suppressed so the software version is not advertised in response headers. lighttpd has no login, so no shared or default credential of any kind ships in the image.

What is included:

  • lighttpd 1.4.x from the Ubuntu 24.04 repository with the mod_openssl TLS module, run under systemd as www-data (lighttpd.service)

  • HTTPS on port 443 served directly by lighttpd through mod_openssl, and HTTP on port 80 permanently redirected (301) to HTTPS

  • A unique self signed certificate generated for each instance on first boot into /etc/lighttpd/certs, so no key material is shared across deployments

  • A hardened default posture: directory listing disabled, the server version token suppressed, and only modern TLS protocol versions enabled

  • A simple document root at /var/www/html with a cloudimg landing page you replace with your own site

  • The whole configuration in readable text you version control, with no database and no administrative web console

Prerequisites

  • Active Azure subscription, SSH public key, VNet and subnet in the target region

  • Subscription to the lighttpd listing on Azure Marketplace

  • Network Security Group rules allowing TCP 22 for administration, and TCP 80 and TCP 443 from the clients that will reach the web server

Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) is ample for serving static sites or fronting an application. lighttpd is extremely light; larger sizes are only needed for very high request volumes.

Step 1: Deploy from the Azure Portal

Search lighttpd in Marketplace, select the cloudimg publisher, and click Create. Configure the Network Security Group to allow TCP 443 (HTTPS) and TCP 80 (HTTP, which redirects to HTTPS) from the clients that will reach the server, and TCP 22 for administration.

Step 2: Deploy from the Azure CLI

RG="web-prod"; LOCATION="eastus"; VM_NAME="lighttpd1"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/lighttpd-ubuntu-24-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az vm create \
  --resource-group "$RG" --name "$VM_NAME" \
  --image "$GALLERY_IMAGE_ID" \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values "$SSH_KEY" \
  --public-ip-sku Standard
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 443 --priority 1001
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 80 --priority 1002
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 22 --priority 1003

Step 3: First boot

On first boot the image resolves this VM's IP, generates a unique self signed TLS certificate into /etc/lighttpd/certs/cloudimg.crt and cloudimg.key, writes the informational note /root/lighttpd-info.txt (recording the served URL), and starts lighttpd. This completes within seconds. SSH in as azureuser and read the note:

sudo cat /root/lighttpd-info.txt

The note records the served HTTPS URL, the document root, the config paths and the certificate path. lighttpd has no password, so the note holds no secret.

Step 4: Confirm the service is running

lighttpd.service is active, lighttpd -v reports the installed version, and ss confirms it is listening on :443 for HTTPS and :80 for the HTTP redirect.

systemctl is-active lighttpd.service
lighttpd -v
sudo ss -tlnp | grep -E ':80 |:443 '

lighttpd.service reports active, lighttpd -v reports version lighttpd 1.4.74 with ssl support, and ss shows the server listening on port 443 for HTTPS and port 80 for the HTTP to HTTPS redirect on all interfaces

Step 5: Confirm HTTPS and the per instance certificate

lighttpd answers HTTPS on port 443 directly. Request the site over HTTPS on the loopback address (the -k flag accepts the self signed certificate), then inspect the certificate. The response Server header is just lighttpd with no version, and the certificate subject is cloudimg-lighttpd, unique to this VM.

curl -ksI https://127.0.0.1/
sudo openssl x509 -in /etc/lighttpd/certs/cloudimg.crt -noout -subject -issuer -dates

The HTTP status is 200 and the certificate was generated on this instance's first boot, so no private key is shared with any other deployment.

curl over HTTPS to the loopback address returns HTTP 200 with the Server header set to just lighttpd and no version, and openssl shows the per VM self signed certificate with subject and issuer CN cloudimg-lighttpd and a ten year validity window

Step 6: Confirm the HTTP to HTTPS redirect and directory listing hardening

Plain HTTP on port 80 is permanently redirected to HTTPS with a 301 status, so clients are always upgraded to an encrypted connection. Directory listing is disabled, so a directory that has no index file returns 403 Forbidden rather than exposing its contents, while individual files inside it are still served by their path.

curl -sI http://127.0.0.1/
curl -ks -o /dev/null -w 'GET /downloads/ -> %{http_code}\n' https://127.0.0.1/downloads/
curl -ks -o /dev/null -w 'GET /downloads/README.txt -> %{http_code}\n' https://127.0.0.1/downloads/README.txt

The HTTP request returns 301 Moved Permanently with a Location header pointing at https://, the index less /downloads/ directory returns 403, and the file inside it returns 200.

curl over HTTP returns 301 Moved Permanently with a Location header pointing at the HTTPS URL, a request for the index less downloads directory returns 403 Forbidden proving directory listing is disabled, and a request for a file inside that directory returns 200

Step 7: Review the cloudimg configuration

Everything cloudimg adds is in one readable drop in file: it loads mod_openssl, opens the HTTPS socket, defines the 301 redirect, disables directory listing and minimises the server token. The base lighttpd configuration lives in /etc/lighttpd/lighttpd.conf.

sudo cat /etc/lighttpd/conf-enabled/50-cloudimg.conf

the cloudimg lighttpd hardening drop in file showing mod_openssl loaded, the server tag set to lighttpd, directory listing disabled, the HTTPS socket on port 443 with ssl engine enabled pointing at the per VM certificate, and the HTTP to HTTPS 301 redirect block

Step 8: Serve your own site

Replace the cloudimg landing page with your own site by writing your files into the document root /var/www/html, or point the document root at a different directory in the configuration. The example below is illustrative; substitute your own content.

# copy your static site into the document root
#   sudo rsync -a ./my-site/ /var/www/html/
# or change server.document-root in /etc/lighttpd/lighttpd.conf to another path,
# then apply the change:
#   sudo systemctl reload lighttpd

lighttpd validates its configuration on reload; if there is a syntax error it keeps serving the previous configuration. You can check the configuration at any time with sudo lighttpd -tt -f /etc/lighttpd/lighttpd.conf.

Step 9: Install a browser trusted certificate for your domain

The image ships with a self signed certificate so HTTPS works immediately. For a browser trusted certificate, point your domain's DNS A record at this VM's public IP, obtain a certificate for <your-domain> from a certificate authority, then point lighttpd at the new certificate and key.

# 1) obtain a certificate + key for <your-domain> (for example with acme.sh or certbot)
# 2) install them, then set in /etc/lighttpd/conf-enabled/50-cloudimg.conf:
#      ssl.pemfile = "/etc/lighttpd/certs/<your-domain>.crt"
#      ssl.privkey = "/etc/lighttpd/certs/<your-domain>.key"
# 3) apply the change:
#      sudo systemctl reload lighttpd

Keep the private key readable only by root. lighttpd loads the certificate at start up, so a reload is enough to serve the new certificate.

Step 10: Front an application back end

lighttpd can proxy or FastCGI to an application running on the same VM. Load the relevant module and add a handler in the configuration; the pattern below forwards a path prefix to a local application port.

# enable the proxy module and route a prefix to a local app on <app-port>:
#   server.modules += ( "mod_proxy" )
#   $HTTP["url"] =~ "^/app/" {
#       proxy.server = ( "" => ( ( "host" => "127.0.0.1", "port" => <app-port> ) ) )
#   }
# then: sudo systemctl reload lighttpd

For dynamic languages lighttpd also ships FastCGI (mod_fastcgi) and CGI handlers; see the lighttpd documentation for the handler syntax.

Step 11: Security recommendations

  • Restrict the NSG to your use case. Allow TCP 443 and TCP 80 only from the networks that need to reach the site, and keep TCP 22 restricted to your administration network.

  • Replace the self signed certificate for public sites. The per VM self signed certificate secures the transport immediately, but browsers will warn on it; install a CA issued certificate for <your-domain> as in Step 9 for public facing sites.

  • Keep directory listing disabled. The cloudimg default disables listing so directories without an index file are never exposed; leave it disabled unless you deliberately want a listing for a specific path.

  • Keep the OS patched. Unattended security upgrades remain enabled on the running VM, and lighttpd itself patches with the OS through apt.

Step 12: Support and Licensing

lighttpd is an open source project distributed under the BSD 3 Clause License. This cloudimg image installs the unmodified lighttpd package from the Ubuntu repository. cloudimg provides the packaging, the systemd hardening, the secure by default TLS and redirect configuration, the per instance certificate automation, the paired deploy guide, and 24/7 support with a guaranteed 24 hour response SLA.

cloudimg is not affiliated with or endorsed by the lighttpd project. lighttpd is a mark of its respective owner and is used here only to identify the software.

Deploy on Azure

Find lighttpd on Ubuntu 24.04 LTS on the Azure Marketplace, published by cloudimg. Deploy from the Portal or the Azure CLI as shown above.

Need Help?

Email support@cloudimg.co.uk for deployment help, configuration questions, or licensing enquiries.