{"id":3392,"date":"2023-02-22T07:15:51","date_gmt":"2023-02-22T12:15:51","guid":{"rendered":"https:\/\/dft.wiki\/?p=3392"},"modified":"2025-04-16T22:00:58","modified_gmt":"2025-04-17T02:00:58","slug":"setting-up-lighttpd-on-ubuntu-20-04-and-22-04","status":"publish","type":"post","link":"https:\/\/dft.wiki\/?p=3392","title":{"rendered":"Setting Up LIGHTtpd with PHP on Ubuntu"},"content":{"rendered":"<p class=\"\" data-start=\"0\" data-end=\"124\"><strong>Lighttpd<\/strong> [<a href=\"https:\/\/redmine.lighttpd.net\/projects\/lighttpd\/wiki\">Link<\/a>] uses fewer resources than <strong>Apache2<\/strong> or <strong>Nginx<\/strong>, making it ideal for handling a lot of traffic with less memory and CPU.<\/p>\n<p class=\"\" data-start=\"126\" data-end=\"297\">It&#8217;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.<\/p>\n<hr \/>\n<p><strong>INSTALLING WEB SERVER PLUS PHP<\/strong><\/p>\n<pre>sudo apt update &amp;&amp; sudo apt upgrade -y\r\nsudo apt install lighttpd -y<\/pre>\n<pre>sudo apt install php7.4 php7.4-fpm php7.4-mysql php7.4-cli php7.4-curl php7.4-xml curl -y<\/pre>\n<pre>sudo nano \/etc\/php\/7.4\/fpm\/pool.d\/www.conf<\/pre>\n<pre>;listen = \/run\/php\/php7.4-fpm.sock\r\nlisten = 127.0.0.1:9000<\/pre>\n<pre>                #\"bin-path\" =&gt; \"\/usr\/bin\/php-cgi\",\r\n                #\"socket\" =&gt; \"\/var\/run\/lighttpd\/php.socket\",\r\n                \"host\" =&gt; \"127.0.0.1\",\r\n                \"port\" =&gt; \"9000\",<\/pre>\n<pre>sudo lighty-enable-mod fastcgi\r\nsudo lighty-enable-mod fastcgi-php\r\nsudo systemctl restart lighttpd php7.4-fpm<\/pre>\n<pre>rm \/var\/www\/html\/index.lighttpd.html\r\necho '&lt;?php echo \"HTTP_HOST: \" . $_SERVER[\"HTTP_HOST\"] . \" SERVER_NAME: \" . $_SERVER[\"SERVER_NAME\"] ?&gt;' | sudo tee \/var\/www\/html\/index.php\r\nsudo chown -R www-data: \/var\/www\/html\/\r\nsudo chmod -R 755 \/var\/www\/html\/<\/pre>\n<p>At this point, any HTTP request to this server will be served with the same page. Consider using Virtual Hosts to server multiple sites based on its Host header.<\/p>\n<hr \/>\n<p><strong>SETTING A VIRTUAL HOST<\/strong><\/p>\n<pre>sudo nano \/etc\/lighttpd\/lighttpd.conf<\/pre>\n<pre>...\r\ninclude_shell \"\/usr\/share\/lighttpd\/create-mime.conf.pl\"\r\n<strong>include_shell \"cat \/etc\/lighttpd\/vhosts.d\/*.conf\"<\/strong>\r\ninclude \"\/etc\/lighttpd\/conf-enabled\/*.conf\"\r\n...<\/pre>\n<pre>sudo mkdir -p \/etc\/lighttpd\/vhosts.d\/\r\nsudo nano \/etc\/lighttpd\/vhosts.d\/localhost.conf<\/pre>\n<pre>$HTTP[\"host\"] =~ \"(^|.)localhost$\" {\r\n    server.document-root = \"\/var\/www\/html\/localhost\"\r\n}<\/pre>\n<pre>sudo mkdir -p \/var\/www\/html\/localhost\r\necho 'VHOST: localhost' | sudo tee \/var\/www\/html\/localhost\/index.html<\/pre>\n<pre>sudo lighttpd -t -f \/etc\/lighttpd\/lighttpd.conf &amp;&amp; sudo systemctl restart lighttpd.service<\/pre>\n<pre>curl http:\/\/127.0.0.1\r\ncurl http:\/\/localhost<\/pre>\n<p>While the first request is served with the default site, the second request will be served with a different content.<\/p>\n<hr \/>\n<p><strong>DEPLOYING A SELF-SIGNED CERTIFICATE<\/strong><\/p>\n<p>Replace the fake domain <code>example.com<\/code> accordingly.<\/p>\n<pre>sudo mkdir -p \/etc\/lighttpd\/ssl\/<strong>example.com<\/strong>\r\ncd \/etc\/lighttpd\/ssl\/<strong>example.com<\/strong>\r\nsudo apt install lighttpd-mod-openssl -y\r\nsudo lighttpd-enable-mod ssl\r\nsudo openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes\r\nsudo nano \/etc\/lighttpd\/conf-enabled\/10-ssl.conf<\/pre>\n<pre># \/usr\/share\/doc\/lighttpd\/ssl.txt\r\nserver.modules += ( \"mod_openssl\" )\r\n$HTTP[\"scheme\"] == \"http\" {\r\n    $HTTP[\"host\"] =~ \".*\" {\r\n        url.redirect = (\".*\" =&gt; \"https:\/\/%0$0\")\r\n    }\r\n}\r\n$SERVER[\"socket\"] == \"0.0.0.0:443\" {\r\n        ssl.engine  = \"enable\"\r\n        ssl.pemfile = \"\/etc\/lighttpd\/ssl\/<strong>domain.com<\/strong>\/server.pem\"\r\n        ssl.cipher-list = \"HIGH\"\r\n}<\/pre>\n<pre>sudo lighttpd -t -f \/etc\/lighttpd\/lighttpd.conf &amp;&amp; sudo systemctl restart lighttpd.service<\/pre>\n<hr \/>\n<p><strong>ISSUING A FREE PUBLIC CERTIFICATE<\/strong><\/p>\n<p>Replace the fake domain <code>example.com<\/code> with a real public domain that has a record that points to the web server.<\/p>\n<pre>add-apt-repository ppa:certbot\/certbot &amp;&amp; sudo apt install certbot -y\r\nsudo lighttpd-enable-mod ssl\r\nsudo certbot certonly --webroot -w \/var\/www\/html -d <strong>example.com<\/strong> -d <strong>www.example.com<\/strong>\r\nls -l \/etc\/letsencrypt\/live\/<strong>example.com<\/strong>\r\nsudo nano \/etc\/lighttpd\/lighttpd.conf<\/pre>\n<pre># \/usr\/share\/doc\/lighttpd\/ssl.txt\r\nserver.modules += ( \"mod_openssl\" )\r\n$HTTP[\"scheme\"] == \"http\" {\r\n    $HTTP[\"host\"] =~ \".*\" {\r\n        url.redirect = (\".*\" =&gt; \"https:\/\/%0$0\")\r\n    }\r\n}\r\n$SERVER[\"socket\"] == \"0.0.0.0:443\" {\r\n        ssl.engine  = \"enable\"\r\n        ssl.pemfile = \"\/etc\/letsencrypt\/live\/<strong>example.com<\/strong>\/fullchain.pem\"\r\n        ssl.privkey = \"\/etc\/letsencrypt\/live\/<strong>example.com<\/strong>\/privkey.pem\"\r\n        ssl.cipher-list = \"HIGH\"\r\n}<\/pre>\n<pre>sudo lighttpd -t -f \/etc\/lighttpd\/lighttpd.conf &amp;&amp; sudo systemctl restart lighttpd.service<\/pre>\n<hr \/>\n<p><strong>RENEWING THE PUBLIC CERTIFICATE<\/strong><\/p>\n<p>Certbot (that used Let&#8217;s Encrypt) does not automatically renew he free 90 days public certificates.<\/p>\n<p>Follows the manual renewal command that can be easily scheduled to periodically happens as a cronjob:<\/p>\n<pre>sudo certbot renew --force-renewal -d <strong>example.com<\/strong> -d <strong>www.example.com<\/strong><\/pre>\n<hr \/>\n<p><strong>BONUS<\/strong><\/p>\n<p>Reverse proxy for a VHOST:<\/p>\n<pre>$HTTP[\"host\"] =~ \"(^|.)example.com$\" {\r\n    proxy.server = ( \"\" =&gt; ( ( \"host\" =&gt; \"127.0.0.1\", \"port\" =&gt; 8080 ) ) )\r\n}<\/pre>\n<p>Reverse proxy for a PATH rewriting the HEADER:<\/p>\n<pre>$HTTP[\"url\"] =~ \"(^\/path)\" {\r\n    proxy.header = ( \"map-urlpath\" =&gt; ( \"\/path\" =&gt; \"\/\") )\r\n    proxy.server = ( \"\" =&gt; ( ( \"host\" =&gt; \"127.0.0.1\", \"port\" =&gt; 8080 ) ) )\r\n}<\/pre>\n<p>Another way of creating a self-signed certificate would be:<\/p>\n<pre>sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout \/etc\/ssl\/private\/apache-selfsigned.key -out \/etc\/ssl\/certs\/apache-selfsigned.crt<\/pre>\n<p><strong>Note:<\/strong> the different file output format.<\/p>\n<hr \/>\n<p><strong>REFLECTIONS<\/strong><\/p>\n<p class=\"\" data-start=\"39\" data-end=\"331\">Lighttpd is a lightweight web server that&#8217;s great for low-resource systems. For better performance and security, it&#8217;s a good idea to place it behind a reverse proxy that handles SSL\/TLS encryption. Using a CDN like Cloudflare can help protect your site and take care of encrypted connections.<\/p>\n<p class=\"\" data-start=\"333\" data-end=\"502\">Also, make sure to tighten your firewall settings\u2014only allow the traffic you really need. If you&#8217;re using a CDN, restrict access so only the CDN&#8217;s IP ranges can connect.<\/p>\n<p class=\"\" data-start=\"504\" data-end=\"636\">If your site handles sensitive data (like passwords), you should at least use a self-signed certificate to provide basic encryption.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Lighttpd [Link] uses fewer resources than Apache2 or Nginx, making it ideal for handling a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,6],"tags":[],"class_list":["post-3392","post","type-post","status-publish","format-standard","hentry","category-linux","category-raspberry-pi"],"_links":{"self":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/3392","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3392"}],"version-history":[{"count":9,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/3392\/revisions"}],"predecessor-version":[{"id":4817,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/3392\/revisions\/4817"}],"wp:attachment":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3392"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3392"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3392"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}