In the path to have a #RaspberryPi serving a blog, one classic step is to install an #Apache2 web server. In this post I describe the process including permissions, modules and virtual host setup.
Requirements & Assumptions
Install Apache2
Adjust permissions
Apache2 modules
Add a Virtual Host
Wrapping up
A Raspberry Pi up and running, following my previous article Spawning a Raspberry Pi 4 with Raspberry Pi OS. It is also up to date by following the recent article Upgrade Raspberry Pi OS from 11 Bullseye to 12 Bookworm.
What is the goal for it? Usually it servers webpages, sometimes you want to support PHP or it can also work as a Reverse Proxy. Apache2 offers a set of modules that you need to install separately depending on your goal. This article will cover a general installation to serve webpages.
The host uses a local DNS server as explained in Quick DNS server on a Raspberry Pi and that's why you won't see IP addresses here.
The hostname is alderaan
and the linux user is xavi
. You may want to change them for your IP address and your own username.
Update your system so that the package list is up to date.
sudo apt-get update
sudo apt-get upgrade
Install Apache2
sudo apt install apache2 -y
At this point we should end up with a basic installation of Apache2. Our system si able to serve webpages and is in fact serving under http://alderaan
.
You can execute the following command to know the IP of this host:
hostname -I
and it should tell the IPv4 and IPv6. The IPv4 can be placed directly in the browser and then should appear the default Apache2 site.
The current state of the system is the following:
We are meant to have our virtual host directiories (the sites we want to serve) under /var/www
. This is of course not mandatory but having all of them centered under a directory easies our administration of the server.
We have the default site already set up by the installation under /var/www/html
After the installation, the whole /var/www
directory and subdirectories and files inside belong to root
, which is not ideal. First, because Apache has defined a default user www-data
and group www-data
to use for the files of the sites and second because you don't want to have to use sudo
every time you edit a file.
We're logged as a normal user (xavi
as mentioned above, or pi
in the default installation) and most likely this is the user that most of the aplications in the system will run (say Python projects, files copied up and down,...)
So here we have 2 main routes we can go towards having a proper user/group/permissions set up:
The default one: We add ourselves (xavi
) into the Apache's default group and make all files there inside belonging to the Apache's default user and group.
Pros: You have more security (one user for one purpose) and also all documentations refer to this solution, so it may be easier for you to move on.
Cons: Everytime you add a file or a directory there you need to change the ownership to the www-data
user or group. At least, you need to set up permissions for every application that interact with these files. If you have processes from a different aplication running under a different user, you most likely will fall into permission issues when writing or reading from Apache. It's quite a headache.
The custom one: We can make Apache to use OUR user when behaving with the files in the virtual hosts, so all files that are created and edited belong to the same user of the rest of aplications.
Pros: Easier maintenance, all files belong to the same user / group, we rarely enter into issues between aplications accessing the same files
Cons: This is an obvious security hole, as once an attacker gains access to the user, it can access the whole system. This is of course not that easy and still this is not the root
user, but the consideration needs to be said.
So, at this point, you have to choose which option you take. Each option will be setup in one of the following sections:
We want to be able to behave with the files in the /var/www/html
and in general the files that Apache manages.
Apache uses the user www-data
and the group www-data
for the files in the published directories, so we need to add our user into that group:
Add our xavi
user to the www-data
default group
sudo usermod -a -G www-data xavi
Make the whole /var/www
to belong to the www-data
user
sudo chown -R -f www-data:www-data /var/www
Logout and log in to the system again to let the changes to take effect on you
The Raspberry Pi is also a nice toy to play around. One may have a Python script that generates files than then are published in an Apache so a CRUD app edits them and then go back to another app. On the way we need to work on the permissions system, or simply make the applications to work with the same user. At the end of the daty, this is sometimes just a toy and besides making everything as root
, we can also easy our life a bit.
What we'll do here is to set up Apache so that the files in the Virtual Hosts are owned by the same overall non-root user xavi
.
Edit the file that contain the definition of the user and group to use
sudo nano /etc/apache2/envvars
Find the following lines
export APACHE_RUN_USER=www-data
export APACHE_RUN_GROUP=www-data
Change the user and group www-data
to the desired one (xavi
in my case)
export APACHE_RUN_USER=xavi
export APACHE_RUN_GROUP=xavi
Save (ctrl
+ o
) and exit (ctrl
+ x
)
Make the whole /var/www
to belong to the xavi
user
sudo chown -R -f xavi:xavi /var/www
Restart the Apache2
sudo service apache2 restart
Depending on the project you manage, you'd need a set of modules to be installed. Modules extend the functionality of our web server.
First of all, here is a command to see which Apache2 modules we already have activated:
apache2ctl -M
it should output something like the following:
Loaded Modules:
core_module (static)
so_module (static)
watchdog_module (static)
http_module (static)
log_config_module (static)
logio_module (static)
version_module (static)
unixd_module (static)
access_compat_module (shared)
alias_module (shared)
auth_basic_module (shared)
authn_core_module (shared)
authn_file_module (shared)
authz_core_module (shared)
authz_host_module (shared)
authz_user_module (shared)
autoindex_module (shared)
deflate_module (shared)
dir_module (shared)
env_module (shared)
filter_module (shared)
mime_module (shared)
mpm_event_module (shared)
negotiation_module (shared)
reqtimeout_module (shared)
setenvif_module (shared)
status_module (shared)
Now let's activate a module. I'll use mod_rewrite
as an example.
Activate the module mod_rewrite
sudo a2enmod rewrite
Restart Apache2 so the changes take effect
sudo service apache2 restart
Virtual Hosts are the way to define sites in Apache2. This section is just to show how we should continue with our Apache2 setup so that we can serve content, but of course it's very minimal and just as an example.
ℹ️ We assume here that:
Our Raspberry Pi is connected to the internet and therefore, there is a public IP that we know or at least a Dynamic DNS set up.
We have a domain called my_app.com
and a subdomain there www.my_app.com
that is already set up to forward the traffic to the public IP of our Raspberry Pi o at least to the set up Dynamic DNS
Our router is also set up to forward the traffic incoming from the port 80 to the Raspberry PI internal IP address.
To add a new Virtual Host we need:
A directory that contains the site. Ideally inside the /var/www
so we can maintain it easily, and can contain simply an index.html
A new Virtual Host file enabled in Apache2.
For the first point, you most likely have a fancy webpage to publish. Just for the purposes of this article:
Create a directory for the site inside the /var/www
directory
mkdir /var/www/my_app
Create and edit an index.html
file in the recently created directory
nano /var/www/my_app/index.html
Add an example content to the file so we can see the Virtual Host working
<html>
<head>
<title>It works!</title>
</head>
<body>
<h1>This Virtual Host works!</h1>
</body>
</html>
Save (ctrl
+ o
) and exit (ctrl
+ x
)
Ensure that the directory and the content have the right permissions. Refer to the section 3 above to know if you need to chown
/ chmod
to it.
For the second point, and now that we have any example content to serve, let's create a new Virtual Host file for it.
Create a new Virtual Host file where all Virtual Host file should live
sudo nano /etc/apache2/sites-available/my_app.conf
Add the basic content for the Virtual Host file
<VirtualHost *:80>
ServerName my_app.com
ServerAlias www.my_app.com
DocumentRoot /var/www/my_app
ErrorLog ${APACHE_LOG_DIR}/my_app_error.log
CustomLog ${APACHE_LOG_DIR}/my_app_access.log combined
</VirtualHost>
Of course, these are just some of the parameters that we can set up here. You have plenty of examples in the official Apache documentation or simply search the net.
Still, what we have here means:
VirtualHost *:80: Apache should listen any IP address coming throught the port 80.
ServerName: The request asking for the domain defined by this directive will be handled by this VirtualHost
ServerAlias: This is an alias, meaning that the request can be asking for this domain / subdomain too
DocumentRoot: Where is the directory containing the content to serve.
ErrorLog: Errors for this Virtual Host will be registered in the defined log file
CustomLog: Accesses (requests) to this Virtual Host will be registered in the defined log file.
Save (ctrl
+ o
) and exit (ctrl
+ x
)
Activate this site
There are 2 ways to activate the site that we just created in Sites Available. Just choose one 😉
sudo a2ensite my_app.conf
sudo ln -s /etc/apache2/sites-available/my_app.conf /etc/apache2/sites-enabled/my_app.conf
Restart Apache2 so the changes take effect
sudo service apache2 restart
At this point we have our host set up and ready to receive requests. Recalling that we have all the DNS and router stuff already done (that is, the domains pointing to our machine and the router also set up), we should be able to visit http://my_app.com in a browser and see our content 😊
Setting up an Apache2 web server is not really complicated. There is this point to take care about permissions that can become a headache, and the set up of a Virtual Host is something that has a whole world behind.
And talking about modules, we'll most likely want to install PHP or any other scripting language support so that we can do fancy things. Stay tuned, another article is in the oven!