The goal of this exercise is to deploy a static website (only HTML, JavaScript and CSS) with nginx.
- Legend
- 💎 Requirements
- ❗ Install nginx on the server
- ❗ Put the static website on the server
- ❗ Create an nginx configuration file to serve the website
- ❗ Give nginx access to the files
- ❗ See it in action
- 🏁 What have I done?
- 💥 Troubleshooting
Parts of this guide are annotated with the following icons:
- ❗ A task you MUST perform to complete the exercise.
- ❓ An optional step that you may perform to make sure that everything is working correctly.
⚠️ Critically important information about the exercise.- 💎 Tips on the exercise, reminders about previous exercises, or explanations about how this exercise differs from the previous one.
- 👾 More advanced tips on how to save some time. Challenges.
- 📚 Additional information about the exercise or the commands and tools used.
- 🏁 The end of the exercise.
- 🏛️ The architecture of what you deployed during the exercise.
- 💥 Troubleshooting tips: how to fix common problems you might encounter.
This guide assumes that you are familiar with reverse proxying and that you have completed the previous DNS configuration exercise, where you configured an A record for your server in the domain name system.
Connect to your server and make sure you have nginx installed as shown during the course.
It is suggested that you use the provided HTML, JavaScript and CSS clock, but you could deploy any other static HTML website.
Still on your server, clone the following repository into your home directory: https://github.com/MediaComem/static-clock-website
Make sure the files are there:
$> ls static-clock-website
index.html README.md script.js style.css
Create an nginx configuration file for the website. You may name the file
clock
and put it in nginx's /etc/nginx/sites-available
directory. You can do
that with nano or Vim. You will need to use sudo
as that directory is only
writable by root
.
Take the static configuration that was presented during the course and put it in the file. You should modify it to:
-
Use the subdomain you configured for your server during the previous DNS exercise (e.g.
jde.archidep.ch
).💎 This is done by customizing nginx's
server_name
directive in yourserver
block. Read How nginx processes a request if you want to know more. -
Serve the files in the repository you just cloned.
💎 This is done by customizing nginx's
root
directive. You can learn more about it in the Serving Static Content section of the nginx Beginner's Guide.
By default, configurations stored in the sites-available
directory are
available, but not enabled.
📚 Indeed, if you check what is included by the main
/etc/nginx/nginx.conf
file, you will see thatsites-enabled
is there, but notsites-available
:$> cat /etc/nginx/nginx.conf | grep include include /etc/nginx/modules-enabled/*.conf; include /etc/nginx/mime.types; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*;📚 The command pipeline above uses
cat
andgrep
to print all the lines which contain the word "include" in the specified file.
To enable a configuration file, the convention is to create a symbolic link in
sites-enabled
, which points to the actual configuration file in
sites-available
. This allows you to work on your configuration for a while
before enabling it.
Enable the clock
configuration by creating the correct symbolic link:
$> sudo ln -s /etc/nginx/sites-available/clock /etc/nginx/sites-enabled/clock
Make sure the symbolic link points to the correct file:
$> ls -l /etc/nginx/sites-enabled/clock
lrwxrwxrwx 1 root root 32 Jan 10 17:07 /etc/nginx/sites-enabled/clock -> /etc/nginx/sites-available/clock
In recent Ubuntu versions, nginx does not have access to your home directory by
default. When reading files, nginx uses the www-data
user (you can see this
configured in /etc/nginx/nginx.conf
).
If you look at the permissions for your home directory, it will probably be
rwxr-x---
, meaning that your user has access to it, your group has access to
it, but other users don't:
$> ls -la /home
total 16
drwxr-xr-x 4 root root 4096 Oct 19 13:01 .
drwxr-xr-x 19 root root 4096 Nov 23 11:23 ..
drwxr-x--- 15 jde jde 4096 Nov 23 15:34 jde
You should give permission to the www-data
user to access your home directory.
One way to quickly do this by adding the www-data
user to your group (replace
jde
with your Unix username):
$> sudo usermod -a -G jde www-data
Then restart nginx:
$> sudo nginx -s reload
📚 This is not necessarily the best solution from a security standpoint. It means that nginx will likely have read/execution access to all the directories and files owned by your user. This is probably more than it should have.
The clean and secure solution would be to put the files in a dedicated directory with appropriate permissions, somewhere outside your home directory.
For example, you could create a
/var/www/clock
directory owned by you and clone the repository there. If you don't want other users to access this directory, you could even restrict permissions further by making this directory owned by you and thewww-data
group (e.g.sudo chown jde:www-data /var/www/clock
), and removing all permissions for other users (e.g. withsudo chmod o-a /var/www/clock
).If you don't care about security at all
(ㆆ _ ㆆ)
, you can also simply revert the permissions of your home directory to what they would have been before, i.e. give access to everyone withsudo chmod o+rx /home/jde
.
Nginx does not automatically reload its configuration files when they change.
First, you should check whether the changes you have made are valid. The nginx -t
command loads all the nginx configuration (including files added with
include
) and checks that they are valid:
$> sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
💎 If an error occurs here, you may have made a mistake in the configuration. (See Troubleshooting if you get an error about
server_names_hash_bucket_size
.)
Nginx reloads its configuration when it receives the HUP
signal. You could find the process ID of the nginx
master
process and send the signal with kill -s HUP <ID>
. However, the nginx
command helpfully allows you to do that in a much simpler way:
$> sudo nginx -s reload
You can also do the same thing through systemd with the following command:
sudo systemctl nginx reload
. This will also ask nginx to reload its configuration.
If the command indicates no errors, nginx should have reloaded its configuration.
Visit the subdomain of your server, e.g. http://jde.archidep.ch (replacing jde
with your username) and you should see the website working.
You have configured nginx to act as a web server to serve static content (HTML, JavaScript and CSS that can be sent unmodified to the client) under your custom subdomain.
You can serve any static web content this way. You can also make nginx serve as
many separate websites as you want under different domains by creating multiple
configuration files with different server_name
directives, all on the same
server (your Azure instance).
This is a simplified architecture of the main running processes and communication flow at the end of this exercise:
📚 Note that this diagram only shows the processes involved in this exercise, ignoring the PHP Todolist we have also deployed on the server.
Here's a few tips about some problems you may encounter during this exercise.
If you get an error about server_names_hash_bucket_size
, it may be because
your domain name (the value of your server_name
directive) is too long for
nginx's default settings.
In that case, edit the main nginx configuration with sudo nano /etc/nginx/nginx.conf
and add the following line in the http
section:
server_names_hash_bucket_size 256;
If your nginx configuration is syntactically correct (i.e. sudo nginx -t
shows
no error) but you still get an error page in the browser, you can take a look at
the nginx error log to see if it helps identify the issue:
$> sudo cat /var/log/nginx/error.log
Also take a look at the following subsections depending on the error you see in your browser.
If you get a 403 Forbidden error, it usually means that nginx has insufficient
permissions to access the directory you have specified with the root
directive
(or the index.html
file in that directory). Make sure that the www-data
user
nginx is running as can access all the directories in the root
you have
specified.
If you have Ubuntu 22+, this may be due to the fact that the permissions of your Unix user's home directory are more restrictive than in the past. You can check whether this is the case by listing all home directories with their permissions:
$> ls -la /home
total 16
drwxr-xr-x 4 root root 4096 Oct 19 13:01 .
drwxr-xr-x 19 root root 4096 Nov 23 11:23 ..
drwxr-x--- 15 jde jde 4096 Nov 23 15:34 jde
If the permissions of your home directory are drwxr-xr-x
, then this solution
does not apply to you. However, if the permissions are drwxr-x---
like above,
then read on.
You should give permission to the www-data
user (the user nginx runs as) to
access your home directory. You can do this by adding it to your group (replace
jde
with your Unix username):
$> sudo usermod -a -G jde www-data
Restart nginx once you have changed the permissions:
$> sudo nginx -s reload
📚 This is not necessarily the best solution from a security standpoint. It means that nginx will likely have read/execution access to all the directories and files owned by your user. This is probably more than it should have.
The clean and secure solution would be to put the files in a dedicated directory with appropriate permissions, somewhere outside your home directory.
For example, you could create a
/var/www/clock
directory owned by you and clone the repository there. If you don't want other users to access this directory, you could even restrict permissions further by making this directory owned by you and thewww-data
group (e.g.sudo chown jde:www-data /var/www/clock
), and removing all permissions for other users (e.g. withsudo chmod o-a /var/www/clock
).If you don't care about security at all
(ㆆ _ ㆆ)
, you can also simply revert the permissions of your home directory to what they would have been before, i.e. give access to everyone withsudo chmod o+rx /home/jde
.
If you get a 404 Not Found error page, it usually means nginx cannot find a file
to serve (e.g. the index.html
page) in the directory you have specified with
the root
directive.
Are you sure that the value of your root
directive is correct? Does that
directory actually exist?