How To Setup Nginx with HTTP/2 Support on Ubuntu 18.04
Nginx stands as a prominent open-source web server, recognized for its speed, reliability, and versatility. Its popularity stems from its minimal memory footprint, high scalability, straightforward configuration, and broad protocol support.
HTTP/2, the successor to HTTP 1.1, is designed to improve the efficiency of web page delivery. HTTP 1.1, released in the late 20th century, was adequate for the simpler web pages of that era. However, modern web pages, often requiring hundreds of requests to load various assets (images, JavaScript, CSS files, etc.), expose the limitations of HTTP 1.1’s queuing-based download approach.
Why HTTP/2 :
HTTP/2 addresses these limitations through several key improvements:
- Multiplexing: Allows multiple requests and responses to be transmitted simultaneously over a single TCP connection, reducing latency.
- Header Compression (HPACK): Reduces the size of HTTP headers, further decreasing latency.
- Server Push: Enables the server to proactively send resources to the client before they are explicitly requested, improving page load times.
- Binary Protocol: HTTP/2 is a binary protocol, making it more efficient to parse and less prone to errors compared to HTTP 1.1’s text-based format.
Although HTTP/2 doesn’t mandate encryption, major browsers like Chrome and Firefox only support it over HTTPS connections for security reasons. Therefore, enabling HTTPS is essential when setting up How To Setup Nginx with HTTP/2 Support on Ubuntu 18.04.
This guide will walk you through configuring Nginx with HTTP/2 support to create a fast and secure web server.
Prerequisites
Before you begin, ensure the following prerequisites are met:
- An Ubuntu 18.04 server.
- Nginx installed and configured.
- A domain name pointed to your server’s public IP address.
- SSL/TLS certificates configured for your domain (Let’s Encrypt is a common and free option).
Step 1 – Activating HTTP/2 Support
Your domain should already have a server block configured at /etc/nginx/sites-available/your_domain
with the server_name
directive properly set. The first step is to modify your domain’s server block to enable HTTP/2.
Open your domain’s configuration file:
$ sudo nano /etc/nginx/sites-available/your_domain
Locate the listen
directives associated with port 443
in the file:
...
listen [::]:443 ssl ipv6only=on;
listen 443 ssl;
...
The first directive handles IPv6 connections, and the second handles IPv4 connections. To enable HTTP/2 for both, add the http2
parameter to each listen
directive:
...
listen [::]:443 ssl http2 ipv6only=on;
listen 443 ssl http2;
...
This instructs Nginx to use HTTP/2 for connections from supported browsers.
Save the changes and exit the text editor.
After making changes to Nginx configuration files, it’s crucial to check for syntax errors:
$ sudo nginx -t
If the syntax is correct, you’ll see the following output:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Next, configure the server to use a more secure list of cipher suites.
Step 2 – Removing Old and Insecure Cipher Suites
HTTP/2 mandates the avoidance of outdated and insecure cipher suites. Cipher suites are cryptographic algorithms that define how data is encrypted during transmission.
The method for defining ciphers depends on how you configured your Nginx TLS/SSL certificates.
If you used Certbot to obtain your certificates, the file /etc/letsencrypt/options-ssl-nginx.conf
was created. This file might contain cipher suites that are not strong enough for HTTP/2. Modifying this file directly can prevent Certbot from applying future updates. In this case, you will disable this file and define our own list of ciphers.
Open your domain’s server block configuration file:
sudo nano /etc/nginx/sites-available/your_domain
Find the line that includes the /etc/letsencrypt/options-ssl-nginx.conf
file and comment it out:
# include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
Add the following line beneath it to define the allowed ciphers:
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
Save the file and exit the editor.
If you used self-signed certificates or a third-party certificate and configured it based on the prerequisites, open the file /etc/nginx/snippets/ssl-params.conf
in your text editor:
$ sudo nano /etc/nginx/snippets/ssl-params.conf
Locate the line that defines the ssl_ciphers
:
...
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
Modify it to:
...
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
Save the file and exit the editor.
Again, check for syntax errors in the configuration:
$ sudo nginx -t
Address any errors found, then test again.
Once there are no syntax errors, restart Nginx:
$ sudo systemctl restart nginx
Step 3 – Verifying that HTTP/2 is Activated
Now, verify that the server is running and supports HTTP/2.
Make a request to your site using the curl
command and examine the headers:
$ curl -I -L https://your_domain
The output will be similar to:
HTTP/1.1 301 Moved Permanently
Server: nginx/1.14.0 (Ubuntu)
Date: Fri, 06 Jul 2018 19:07:12 GMT
Content-Type: text/html
Content-Length: 194
Connection: keep-alive
Location: https://your_domain/
HTTP/2 200
server: nginx/1.14.0 (Ubuntu)
date: Fri, 06 Jul 2018 19:07:12 GMT
content-type: text/html
content-length: 16
last-modified: Fri, 06 Jul 2018 16:55:37 GMT
etag: "5b3f9f09-10"
accept-ranges: bytes
The HTTP/2 200
line confirms that HTTP/2 is active.
You can also verify HTTP/2 in Google Chrome. Open Chrome and navigate to https://your_domain
. Open the Chrome Developer Tools (View -> Developer -> Developer Tools), then reload the page (View -> Reload This Page). Go to the Network tab, right-click on the table header row (starting with "Name"), and select the "Protocol" option from the pop-up menu.
You will see "h2" (indicating HTTP/2) in a new "Protocol" column.
[Image of HTTP/2 Support on Ubuntu nginx]
Your server is now serving content using HTTP/2. Enhance security and performance further by enabling HSTS.
Step 4 – Enabling HTTP Strict Transport Security (HSTS)
HTTP Strict Transport Security (HSTS) prevents browsers from connecting to your site using insecure HTTP, even if HTTP requests are made. When a browser receives an HSTS header, it will only connect to the server via HTTPS for a specified period. This protects against downgrade attacks.
Open the Nginx configuration file in your editor:
sudo nano /etc/nginx/nginx.conf
Add the following line to the http
block to enable HSTS:
http {
...
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
add_header Strict-Transport-Security "max-age=15768000" always;
}
...
The max-age
is set in seconds. 15768000
is equivalent to 6 months.
By default, this header is not applied to subdomain requests. If you want HSTS to apply to all subdomains, add the includeSubDomains
directive to the end of the line:
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
Save the file and exit the editor.
Check for syntax errors:
$ sudo nginx -t
Finally, restart the Nginx server to apply the changes:
$ sudo systemctl restart nginx
Conclusion
Your Nginx server is now serving pages over HTTP/2. Consider running an SSL test against your server to assess the strength of your SSL configuration. This guide provides a comprehensive walkthrough of How To Setup Nginx with HTTP/2 Support on Ubuntu 18.04.
Now, let’s explore alternative approaches to achieving the same outcome:
Alternative Solutions for How To Setup Nginx with HTTP/2 Support on Ubuntu 18.04
While the above steps provide a clear method for configuring Nginx with HTTP/2, there are alternative approaches that can streamline the process or offer different levels of customization.
Alternative 1: Using Pre-built Nginx Packages with HTTP/2 Enabled
Some package repositories may offer pre-built Nginx packages that already have HTTP/2 enabled by default. This simplifies the configuration process significantly.
Explanation: Instead of manually configuring the listen
directives in your server block, you would simply install the Nginx package from the repository. The HTTP/2 support would be enabled out-of-the-box. This approach is particularly useful if you are setting up a new server or if you are comfortable using a package manager that provides these pre-configured packages.
Steps:
-
Add the appropriate repository: This step depends on the specific repository offering the pre-built package. Consult the repository’s documentation for instructions. This may involve adding a new source to your
/etc/apt/sources.list
or/etc/apt/sources.list.d/
directory. -
Update the package list:
sudo apt update
-
Install Nginx:
sudo apt install nginx
-
Verify HTTP/2: Follow the verification steps outlined in the original guide to confirm that HTTP/2 is enabled. You may still need to configure SSL certificates if you haven’t already.
Caveats:
- The availability of pre-built packages with HTTP/2 enabled depends on the specific package repository you are using.
- You may have less control over the specific configuration of Nginx if you use a pre-built package.
- Ensure the source of the package is trusted to avoid installing malicious software.
Alternative 2: Using a Configuration Management Tool (Ansible, Chef, Puppet)
Configuration management tools like Ansible, Chef, or Puppet can automate the process of configuring Nginx with HTTP/2.
Explanation: These tools allow you to define the desired state of your server in a configuration file (e.g., an Ansible playbook, a Chef recipe, or a Puppet manifest). The tool will then automatically configure the server to match the specified state, including enabling HTTP/2, setting up SSL certificates, and configuring other server settings.
Example (Ansible Playbook):
---
- hosts: webservers
become: true
tasks:
- name: Install Nginx
apt:
name: nginx
state: present
- name: Configure Nginx server block for HTTP/2
template:
src: templates/nginx_vhost.conf.j2
dest: /etc/nginx/sites-available/your_domain
- name: Enable site
file:
src: /etc/nginx/sites-available/your_domain
dest: /etc/nginx/sites-enabled/your_domain
state: link
- name: Restart Nginx
systemd:
name: nginx
state: restarted
templates/nginx_vhost.conf.j2
(Jinja2 template):
server {
listen 443 ssl http2;
listen [::]:443 ssl http2 ipv6only=on;
server_name your_domain;
ssl_certificate /path/to/your/certificate.pem;
ssl_certificate_key /path/to/your/private_key.pem;
# Add other configurations here
}
Steps:
-
Install and configure your chosen configuration management tool (Ansible, Chef, or Puppet).
-
Create a configuration file (playbook, recipe, or manifest) that defines the desired state of your server, including:
- Installing Nginx.
- Configuring the Nginx server block with HTTP/2 enabled.
- Setting up SSL certificates.
- Enabling the site.
- Restarting Nginx.
-
Run the configuration management tool to apply the configuration to your server.
Benefits:
- Automation: Automates the configuration process, reducing manual effort and potential errors.
- Idempotency: Configuration management tools ensure that the server always matches the desired state, even if the configuration is run multiple times.
- Scalability: Easily manage and configure multiple servers with the same configuration.
- Version Control: Configuration files can be stored in version control systems (e.g., Git), allowing you to track changes and revert to previous configurations if needed.
These alternative approaches provide different ways to achieve How To Setup Nginx with HTTP/2 Support on Ubuntu 18.04, offering flexibility based on your specific needs and preferences.