Skip to main content

Nginx HTTP2 Setup

Introduction​

HTTP/2 is the second major version of the HTTP protocol, designed to improve web performance by addressing many of the limitations of HTTP/1.1. It offers several important benefits including:

  • Multiplexing: Allows multiple requests and responses to be sent over a single connection simultaneously
  • Header compression: Reduces overhead by compressing HTTP headers
  • Server push: Enables servers to proactively send resources to clients before they request them
  • Binary protocol: More efficient to parse compared to the text-based HTTP/1.1

In this guide, we'll walk through the process of setting up HTTP/2 in Nginx, an essential skill for improving both the performance and security of your web applications.

Prerequisites​

Before we begin, make sure you have:

  1. Nginx version 1.9.5 or higher installed (HTTP/2 support was added in this version)
  2. SSL/TLS certificate (HTTP/2 in browsers only works over HTTPS)
  3. Root or sudo access to your server

Checking Nginx Version​

First, let's confirm that your Nginx version supports HTTP/2:

bash
nginx -v

Expected output:

nginx version: nginx/1.20.1

If your version is below 1.9.5, you'll need to upgrade Nginx first.

Setting Up HTTP/2 in Nginx​

Step 1: Configure SSL/TLS​

HTTP/2 requires a secure connection (HTTPS), so we need to set up SSL/TLS first. If you already have SSL configured, you can skip to Step 2.

Here's how to configure a basic SSL setup in your Nginx server block:

nginx
server {
listen 443 ssl;
server_name example.com www.example.com;

ssl_certificate /path/to/your/certificate.crt;
ssl_certificate_key /path/to/your/private.key;

# Other SSL settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

# ... rest of your configuration
}

Step 2: Enable HTTP/2​

Enabling HTTP/2 is remarkably simple. You just need to add the http2 parameter to your listen directive:

nginx
server {
listen 443 ssl http2;
server_name example.com www.example.com;

ssl_certificate /path/to/your/certificate.crt;
ssl_certificate_key /path/to/your/private.key;

# Rest of your SSL and server configuration
}

That's it! The http2 parameter tells Nginx to use the HTTP/2 protocol for this server block.

Step 3: HTTP to HTTPS Redirection​

It's a good practice to redirect all HTTP traffic to HTTPS, especially when using HTTP/2:

nginx
server {
listen 80;
server_name example.com www.example.com;

return 301 https://$host$request_uri;
}

Step 4: Testing the Configuration​

Always validate your Nginx configuration before reloading:

bash
sudo nginx -t

Expected output:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Step 5: Reload Nginx​

Apply the changes by reloading Nginx:

bash
sudo systemctl reload nginx

Verifying HTTP/2 Is Working​

There are several ways to verify that HTTP/2 is working correctly:

Method 1: Using Chrome DevTools​

  1. Open Chrome DevTools (F12 or Right-click > Inspect)
  2. Go to the "Network" tab
  3. Visit your website
  4. Click on any resource and check the "Protocol" column or field - it should say "h2" for HTTP/2

Method 2: Using curl​

You can use curl to check for HTTP/2 support:

bash
curl -I --http2 https://example.com

Look for HTTP/2 in the response:

HTTP/2 200
server: nginx/1.20.1
date: Fri, 14 Mar 2025 12:34:56 GMT
content-type: text/html; charset=UTF-8
...

Method 3: Online Testing Tools​

You can use online tools like KeyCDN HTTP/2 Test or HTTP/2 Test to verify your HTTP/2 setup.

HTTP/2 Performance Optimization​

Now that you have HTTP/2 enabled, here are some optimization tips:

1. Adjust Nginx Worker Connections​

Since HTTP/2 uses fewer connections, you might want to adjust your worker connections:

nginx
events {
worker_connections 1024;
}

2. Optimize SSL Parameters​

nginx
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;

3. Fine-tune Buffer Sizes​

nginx
http {
client_body_buffer_size 16k;
client_header_buffer_size 1k;
client_max_body_size 8m;
large_client_header_buffers 2 1k;
}

Understanding HTTP/2 Flow​

Here's a diagram showing how HTTP/2 communication works:

Common Issues and Troubleshooting​

Issue 1: HTTP/2 Not Working Despite Configuration​

Possible causes:

  • Nginx version doesn't support HTTP/2
  • Configuration syntax error
  • SSL certificate issues

Solution: Check your Nginx version, validate your configuration, and verify your SSL certificates.

Issue 2: ALPN Negotiation Failed​

Possible cause: OpenSSL version is too old to support ALPN (Application-Layer Protocol Negotiation)

Solution: Upgrade OpenSSL to version 1.0.2 or higher:

bash
openssl version
sudo apt update
sudo apt upgrade openssl

Issue 3: Performance Not Improved​

Possible cause: Your website might not be optimized to leverage HTTP/2 benefits

Solution:

  • Combine small CSS/JS files instead of using many tiny files
  • Implement proper caching
  • Optimize images and assets

Security Considerations with HTTP/2​

While HTTP/2 itself improves security by requiring HTTPS, there are additional security considerations:

1. Keep Nginx Updated​

Regular updates help protect against newly discovered vulnerabilities:

bash
sudo apt update
sudo apt upgrade nginx

2. Implement Strong SSL Ciphers​

nginx
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

3. Implement Security Headers​

nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";

Complete Configuration Example​

Here's a complete Nginx configuration example with HTTP/2 and security best practices:

nginx
http {
# General HTTP settings
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;

# MIME types
include /etc/nginx/mime.types;
default_type application/octet-stream;

# Logging
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

# Gzip compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

# SSL settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

# HTTP/2 Server Block
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;

ssl_certificate /path/to/your/certificate.crt;
ssl_certificate_key /path/to/your/private.key;

root /var/www/html;
index index.html index.htm index.php;

# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";

location / {
try_files $uri $uri/ =404;
}

# PHP handling example
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}

# Deny access to hidden files
location ~ /\. {
deny all;
}
}

# HTTP to HTTPS redirect
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;

return 301 https://$host$request_uri;
}
}

Summary​

In this guide, you've learned how to:

  1. Set up HTTP/2 in Nginx to improve performance and security
  2. Configure SSL/TLS certificates, required for HTTP/2
  3. Redirect HTTP traffic to HTTPS
  4. Verify that HTTP/2 is working correctly
  5. Optimize your Nginx configuration for HTTP/2
  6. Implement important security measures for your HTTP/2 setup

HTTP/2 is a significant improvement over HTTP/1.1, offering better performance through multiplexing, header compression, and other optimizations. By following this guide, you've not only improved your website's performance but also enhanced its security posture.

Further Learning​

To deepen your understanding of HTTP/2 and Nginx security, consider exploring:

  1. HTTP/2 Server Push configuration in Nginx
  2. Advanced SSL/TLS optimization techniques
  3. Performance testing and benchmarking HTTP/2 vs HTTP/1.1
  4. Nginx rate limiting and request throttling
  5. Web Application Firewall (WAF) integration with Nginx

Practice Exercises​

  1. Set up HTTP/2 on a test server and measure the performance improvement compared to HTTP/1.1
  2. Configure HTTP/2 Server Push for critical CSS and JavaScript files
  3. Implement rate limiting to protect your HTTP/2-enabled website from DDoS attacks
  4. Create a script to regularly check and renew your SSL certificates
  5. Set up HTTP/3 (QUIC) alongside HTTP/2 for future-proofing (requires Nginx 1.19.0+ with the quic patch)


If you spot any mistakes on this website, please let me know at feedback@compilenrun.com. I’d greatly appreciate your feedback! :)