How to Install Nginx with HTTPS On Ubuntu
Introduction
Nginx is one of the most popular web servers in the world and is responsible for hosting some of the largest and highest-traffic sites on the internet. It is a lightweight choice that can be used as either a web server or reverse proxy.
In this guide, we’ll discuss how to install Nginx on your Ubuntu 20.04 server, adjust the firewall, manage the Nginx process, and set up server blocks for hosting more than one domain from a single server. We also show how to secure your Nginx server with Let's Encrypt and make it auto-renewable.
Prerequisites
Before you begin this guide, you should have a regular, non-root user with sudo privileges configured on your Ubuntu server. You will also optionally want to have registered a domain name before completing the last steps of this tutorial.
When you have an account available, log in as your non-root user to begin.
$ ssh user_name@server_ip
1 Installing Nginx
Because Nginx is available in Ubuntu’s default repositories, it is possible to install it from these repositories using the apt packaging system.
$ sudo apt update
$ sudo apt install nginx
2 Configuring Firewall
On Ubuntu, UFW is disabled by default. You can check the status of the UFW service with the following command:
$ sudo ufw status
Status: inactive
The upper output shows that the firewall status is inactive. If you don't want to turn on the firewall for now, you can skip this step.
The firewall software needs to be adjusted to allow access to the Nginx service. Nginx registers itself as a service with ufw upon installation, making it straightforward to allow Nginx access. We will only need to allow traffic on ports 80 (normal, unencrypted web traffic) and 443(TLS/SSL encrypted traffic).
# Turn on firewall, allow incoming SSH ports
$ sudo ufw enable
$ sudo ufw allow ssh
# List the application configurations that ufw knows how to work
$ sudo ufw app list
[output]
Available applications:
Nginx Full
Nginx HTTP
Nginx HTTPS
……
$ sudo ufw allow 'Nginx HTTPS'
$ sudo ufw status
3 Checking your Web Server
At the end of the installation process, Ubuntu 20.04 starts Nginx. The web server should already be up and running. We can check with the systemd init system to make sure the service is running by typing:
$ systemctl status nginx
As confirmed by this out, the service has started successfully. However, the best way to test this is to request a page from Nginx.
http://your_server_ip
If you are on this page, your server is running correctly and is ready to be managed.
4 Managing the Nginx Process
In this step, we will show your some basic management commands.
To stop your web server, type:
$ sudo systemctl stop nginx
To start the web server when it is stopped, type:
$ sudo systemctl start nginx
To stop and then start the service again, type:
$ sudo systemctl restart nginx
If you are only making configuration changes, Nginx can often reload without dropping connections. To do this, type:
$ sudo systemctl reload nginx
By default, Nginx is configured to start automatically when the server boots. If this is not what you want, you can disable this behavior by typing:
$ sudo systemctl disable nginx
To re-enable the service to start up at boot, you can type:
$ sudo systemctl enable nginx
You have now learned basic management commands and should be ready to configure the site to host more than one domain.
5 Update Nginx’s Configuration
Nginx on Ubuntu 20.04 has one server block enabled by default. That is configured to serve documents out of a directory at /var/www/html. While this works well for a single site, it can become unwieldy if you are hosting multiple sites. Instead of modifying /var/www/html, let’s create a directory structure within /var/www for our example.com site.
Create the directory for example.com as follows, using the -p flag to create any necessary parent directories:
$ sudo mkdir -p /var/www/example.com
Next, assign ownership of the directory with the $USER environment variable:
$ sudo chown -R $USER:$USER /var/www/example.com
The permissions of your web roots should be correct if you haven’t modified your umask value, which sets default file permissions. To ensure that your permissions are correct and allow the owner to read, write, and execute the files while granting only read and execute permissions to groups and others, you can input the following command:
$ sudo chmod -R 755 /var/www/example.com
Next, create a sample index.html page using nano or your favorite editor:
$ sudo nano /var/www/example.com/index.html
Inside, add the following sample HTML: /var/www/example.com/index.html
<html>
<head>
<title>Welcome to example.com!</title>
</head>
<body>
<h1>Success! The example.com server block is working!</h1>
</body>
</html>
Save and close the file by pressing Ctrl+X to exit, then when prompted to save, Y and then Enter.
In order for Nginx to serve this content, it’s necessary to create a server block with the correct directives. Instead of modifying the default configuration file directly, let’s make a new one at /etc/nginx/sites-available/:
$ sudo nano /etc/nginx/sites-available/example.com
Paste in the following configuration block, which is similar to the default, but updated for our new directory and domain name:
/etc/nginx/sites-available/example.com
server {
listen 80;
# listen [::]:80; #Enabling IP6
root /var/www/example.com/;
index index.html index.htm index.nginx-debian.html;
server_name example.com www.example.com;
location / {
try_files $uri $uri/ =404;
}
}
Notice that we’ve updated the root configuration to our new directory, and the server_name to our domain name.
Next, let’s enable the file by creating a link from it to the sites-enabled directory, which Nginx reads from during startup:
$ sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
Note: Nginx uses a common practice called symbolic links, or symlinks, to track which of your server blocks are enabled. Creating a symlink is like creating a shortcut on a disk. This is so that you could later delete the shortcut from the sites-enabled directory while keeping the server block in sites-available.
To avoid a possible hash bucket memory problem that can arise from adding additional server names, it is necessary to adjust a single value in the /etc/nginx/nginx.conf file. Open the file:
$ sudo nano /etc/nginx/nginx.conf
Find the server_names_hash_bucket_size directive and remove the # symbol to uncomment the line.
/etc/nginx/nginx.conf
...
http {
...
server_names_hash_bucket_size 64;
...
}
...
Save and close the file when you are finished.
Next, test to make sure that there are no syntax errors in any of your Nginx files:
$ sudo nginx -t
If there aren’t any problems, restart Nginx to enable your changes:
$ sudo systemctl restart nginx
Nginx should now be serving your domain name. You can test this by navigating to http://example.com, where you should see something like this:
6 Installing Certbot for Let’s Encrypt
Let’s Encrypt is a Certificate Authority (CA) that provides an easy way to obtain and install free TLS/SSL certificates, thereby enabling encrypted HTTPS on web servers. It simplifies the process by providing a software client, Certbot, that attempts to automate most (if not all) of the required steps. Currently, the entire process of obtaining and installing a certificate is fully automated on both Apache and Nginx.
The first step to using Let’s Encrypt to obtain an SSL certificate is to install the Certbot software on your server.
Install Certbot and its Nginx plugin with apt:
$ sudo apt install certbot python3-certbot-nginx
Certbot is now ready to use, but for it to automatically configure SSL for Nginx, we need to verify some of Nginx’s configurations.
7 Obtaining a free SSL Certificate
Certbot provides a variety of ways to obtain SSL certificates through plugins. The Nginx plugin will take care of reconfiguring Nginx and reloading the config whenever necessary. To use this plugin, type the following:
$ sudo certbot --nginx -d example.com -d www.example.com
This runs certbot with the -- Nginx plugin, using -d to specify the domain names we’d like the certificate to be valid for.
If this is your first time running certbot, you will be prompted to enter an email address and agree to the terms of service. After doing so, certbot will communicate with the Let’s Encrypt server, then run a challenge to verify that you control the domain you’re requesting a certificate for.
Now let's run the following command to check the example.com config file.
$ cat /etc/nginx/sites-available/example.com
[output]
server {
root /var/www/example.com/html;
index index.html index.htm index.nginx-debian.html;
server_name example.com www.example.com;
location / {
try_files $uri $uri/ =404;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/nginx.liren.me/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/nginx.liren.me/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = www.example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 404; # managed by Certbot
}
You'll see the code with the "managed by Certbot" comment which is a new addition, so we don't need to change it.
Nginx should now be serving your domain name over HTTPS. You can test this by navigating to http://example.com, it'll redirect to
https://example.com.
8 Verifying Certbot Auto-Renewal
Let’s Encrypt’s certificates are only valid for ninety days. This is to encourage users to automate their certificate renewal process. The certbot package we installed takes care of this for us by adding a systemd timer that will run twice a day and automatically renew any certificate that’s within thirty days of expiration.
You can query the status of the timer with systemctl:
$ sudo systemctl status certbot.timer
Conclusion
In this tutorial, you have your web server installed, you have many options for the type of content to serve and the technologies you want to use to create a richer experience. Then you installed the Let’s Encrypt client certbot, downloaded SSL certificates for your domain, configured Nginx to use these certificates, and keep renewing them.