A computer as a webserver

Notes published the
5 - 6 minutes to read, 1215 words
Categories: web
Keywords: apache lighttpd php server web

I have an old computer at my home acting as a local server.

I’ve used it mainly as a backup solution with rsync, and recently I wanted to "host" other content.

While normally I am more than happy to use ssh and sshfs to see what’s on the machine, I wanted to provide some HTML pages with some information, in particular copies of webpages that do not exist anymore, wikis, and so on.

Choose a machine

More or less any machine can be used as a server, a computer, laptop, phone, raspberry…​ probably even the device you are using right now, it does not even need to be a separate machine.

Using a phone has the benefit that it has an integrated UPS solution (unless you removed the battery), but it might not be the friendlies environment (Android might kill your server just because it can 😑 ).

Any computer laptop built in the last decade should be powerful enough to serve static pages, or even pages that require PHP, some other language used serverside, a database, and who knows what, as long as the number of users connecting to it is limited.

Choose a web server

The most used ones are probably The Apache HTTP Server Project and nginx, but there are other alternatives like caddy. In those notes, I am going to use lighttpd.

On Debian-based systems, install it with apt install lighttpd, and you are ready to go.

Point your browser to localhost, and if everything works correctly, you should see some content.

You can now edit the webpage at /var/www/html/index.html.

Congratulations, you are a webmaster!

Warning ⚠️
This is not a guide for setting up a public server. It is a short introduction for a home server, reachable from other machines on the same network, or just localhost. In particular, it does not handle securing your system and https.

Reverse proxy

In my case, I did not only want to serve some content, I wanted to serve content from different services.

One of the services is kiwix.

This software is mostly known for providing an easy-to-use system for downloading and viewing Wikipedia offline.

With kiwix-serve (apt install kiwix-tools), it is possible to start a process that listens at a given port; for example

kiwix-serve --port=2022 --library /home/ubackup/kiwix/library.xml

While kiwix-serve is running, if you point your browser at localhost:2022, you’ll see the content served by kiwix-serve.

But I did not want to have multiple ports; who is going to remember that localhost:2022 is for the content served from kiwix?

Wouldn’t it be much better if localhost/kiwix points to the content of kiwix?

This is what normally a Reverse proxy does.

Fortunately, lighttpd supports this functionality out-of-the-box, without the need to install a separate program.

For configuring lighttpd, create the file

/etc/lighttpd/conf-available/99-proxy-kiwix.conf
# https://redmine.lighttpd.net/projects/lighttpd/wiki/Mod_proxy

server.modules += ( "mod_proxy" )

$HTTP["url"] =~ "^/kiwix" {
  proxy.balance = "hash"
  proxy.server  = ( "" => ( ( "host" => "localhost", "port" => 2022 ) ) )
}

and after saving the file, execute

lighty-enable-mod proxy-kiwix
service lighttpd force-reload

Once lighttpd has been reloaded, all requests beginning with kiwix will be redirected to port 2022.

Unfortunately, this is not enough.

The HTML page that can be downloaded at localhost/kiwix, contains absolute URLs; for example /style.css.

Thus even if the page can be reached, other resources, like images, CSS files, and JavaScript, will not load correctly, as theyr URL does not begin with kiwix.

Fortunately kiwix-serve has an appropriate flag: --urlRootLocation

Thus if one starts kiwix-serve with

kiwix-serve --port=2022 --library /home/ubackup/kiwix/library.xml --urlRootLocation kiwix

At this point, all absolute URLs will begin with kiwix, and lighttpd can redirect all requests correctly.

Programmatically add wikis

For completeness, a quick how to add programmatically wikis.

Most wikis can be found at https://download.kiwix.org/zim/, you can download them directly with the browser.

Once you have downloaded the zim archive you are interested in, you can add it to a library with kiwix-manage.

This library file is then used by kiwix-serve.

mkdir kiwix
cd kiwix
wget https://download.kiwix.org/zim/wikipedia/wikipedia_en_all_mini_2024-01.zim
kiwix-manage ~/kiwix/library.xml add /opt/kiwix/wikipedia_en_all_mini_2024-01.zim
kiwix-serve --port=2022 --library ~/kiwix/library.xml --urlRootLocation kiwix

Start a service during boot

While lighttpd installed from the Debian repository starts by default when the system starts, the same cannot be said for kiwix-serve, and in general other services.

There are two main methods for starting a program during system boot: systemd and cron

For systemd, create a file similar to the following

/etc/systemd/system/kiwix-serve.service
[Unit]
Description=Serve all the ZIM files

[Service]
Restart=always
RestartSec=15
User=www-data
ExecStart=/usr/bin/kiwix-serve --port=2022 --library /home/ubackup/kiwix/library.xml --urlRootLocation kiwix

[Install]
WantedBy=multi-user.target

For cron, create a file similar to the following

/etc/cron.d/kiwix
# start kiwix-serve on boot
@reboot www-data /usr/bin/kiwix-serve --port=2022 --library /home/ubackup/kiwix/library.xml --urlRootLocation kiwix

In both cases, www-data is the (non-login) account that executes your webserver (lighttpd, nginx, …​) on Debian systems, so it seems a reasonable choice to use the same user for other services too.

PHP support

On Debian-based systems, install php-fpm, and create the following file

/var/www/html/info.php
<?php

phpinfo();

After saving it, point the browser to localhost/phpinfo.php, it should load a page containing all information about the installed PHP version.

Directory listing

If you have a folder and want to make it navigable from a browser, you either need to create a webpage that lists the files or directories, or tell your server to do so for you.

In the case of lighttpd, for showing the content of a particular directory, it is possible to create a configuration file similar to

# https://redmine.lighttpd.net/projects/lighttpd/wiki/Mod_dirlisting

$HTTP["url"] =~ "^/data" {
     dir-listing.activate = "enable"
     dir-listing.encoding = "utf-8"
}

The documentation states that performance could be an issue, a more scalable approach would be to generate a static page when a file changes, it has also the advantage of providing a more granular control of the content of the page.

Change the document root location of the server (/var/www)

/var/www is owned by root, which means that by default a "normal" user is not able to change any content without sudo or admin privileges, which is not very practical for prototyping or testing things out.

The location of the directory can be configured in /etc/lighttpd/lighttpd.conf, by changing the value of server.document-root, which by default points to /var/www/html

An alternative approach would be to use a symlink or mount point, which has the advantage that it should work with all web servers.

You should ensure that the user www-data can see the files in the new location, not only the user account for editing the content.


Do you want to share your opinion? Or is there an error, some parts that are not clear enough?

You can contact me anytime.