Skip to content

Latest commit

 

History

History
300 lines (226 loc) · 12.4 KB

nginx-static-deployment.md

File metadata and controls

300 lines (226 loc) · 12.4 KB

Deploy a static site with nginx

The goal of this exercise is to deploy a static website (only HTML, JavaScript and CSS) with nginx.

Legend

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.

💎 Requirements

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.

❗ Install nginx on the server

Connect to your server and make sure you have nginx installed as shown during the course.

❗ Put the static website on the server

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 to serve the website

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:

❗ Enable the nginx configuration

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 that sites-enabled is there, but not sites-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 and grep 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

❗ Reload the nginx configuration

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.

❗ See it in action

Visit the subdomain of your server, e.g. http://john-doe.archidep.ch (replacing john-doe with your username) and you should see the website working.

🏁 What have I done?

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).

🏛️ Architecture

This is a simplified architecture of the main running processes and communication flow at the end of this exercise:

Simplified architecture

Simplified architecture PDF version.

The following diagram is a more detailed representation also including the short-lived processes run during the exercise:

Detailed architecture

Detailed architecture PDF version.

💥 Troubleshooting

Here's a few tips about some problems you may encounter during this exercise.

💥 [emerg] could not build the server_names_hash, you should increase server_names_hash_bucket_size

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;

💥 The nginx configuration is correct but I get an error page in the browser

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.

💥 403 Forbidden

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 john_doe  john_doe  4096 Nov 23 15:34 john_doe

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 john_doe with your Unix username):

$> sudo usermod -a -G john_doe www-data

📚 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 the www-data group (e.g. sudo chown john_doe:www-data /var/www/clock), and removing all permissions for other users (e.g. with sudo 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 with sudo chmod o+rx /home/john_doe.

💥 404 Not Found

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?