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.cssCreate 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.
📚 You can add the
.confextension to the file or not, as you wish. Nginx does not need its configuration to have a particular extension.
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_namedirective in yourserverblock. 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
rootdirective. 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.conffile, you will see thatsites-enabledis 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
catandgrepto 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📚 The
-soption makes theln(link) command create a symbolic link, i.e. a simple pointer to a file that resides in another directory. Without the-soption, it would create a hard link.
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/clockIn 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 jdeYou 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-dataThen 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/clockdirectory 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-datagroup (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 (as in test) 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 reloadThe
-soption sends a signal to the nginx master process.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.logAlso 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 jdeIf 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-dataRestart 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/clockdirectory 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-datagroup (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?
