This guide can be used to install NGINX and configure it as a reverse proxy to a service with both HTTP3 and IPv6 enabled.
This guide requires a SSL certificate. Personally I use certbot with acme-dns-client; there is a guide available here.
Currently the NGINX mainline packages are required to use HTTP3. You will need to install the relevant repository for your distribution. Further instructions are available on the nginx Linux packages page.
Install the prerequisites and the GPG key:
apt -y install curl gnupg2 ca-certificates lsb-release debian-archive-keyring
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
For Debian, add the following package source and pin the NGINX package:
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/mainline/debian `lsb_release -cs` nginx" \
| tee /etc/apt/sources.list.d/nginx.list
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
| tee /etc/apt/preferences.d/99nginx
Update the package sources and install:
apt update
apt install nginx
For Ubuntu, add the following package source and pin the NGINX package:
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/mainline/ubuntu `lsb_release -cs` nginx" \
| tee /etc/apt/sources.list.d/nginx.list
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
| tee /etc/apt/preferences.d/99nginx
Update the package sources and install:
apt update
apt install nginx
Add the repository:
cat << EOF > /etc/yum.repos.d/nginx.repo
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
EOF
Install the NGINX package:
yum install nginx
Usually you will want to remove the default vhost configuration files. On RHEL the default vhost is located in /etc/nginx/conf.d and for Debian/Ubuntu it is located in /etc/nginx/sites-enabled.
Create a SSL dhparams file:
openssl dhparam -out /etc/nginx/dhparam.pem 4096
Edit the main NGINX configuration file, /etc/nginx/nginx.conf and replace with the following content:
user nginx;
worker_processes auto;
pid /var/run/nginx.pid;
error_log /var/log/nginx/error.log notice;
events {
worker_connections 1024;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay off;
types_hash_max_size 2048;
server_tokens off;
gzip on;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# Shouldn't need to be adjusted except in specific cases
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_dhparam /etc/nginx/dhparam.pem;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
ssl_prefer_server_ciphers on;
ssl_stapling off;
ssl_stapling_verify off;
ssl_ecdh_curve secp384r1;
client_max_body_size 500M;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# Include virtual hosts and other configuration files
include /etc/nginx/conf.d/*.conf;
}
Finally you can configure the specific site configuration. Create the file /etc/nginx/conf.d/<domain>.conf and add the following content:
# The upstream server or servers to send connections to
upstream proxy_upstream {
server 127.0.0.1:8000;
keepalive 10;
}
# HTTP to HTTPS redirect
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com;
access_log /var/log/nginx/example.com-access.log main;
error_log /var/log/nginx/example.com-error.log;
# Send HTTPS redirect
return 301 https://$host$request_uri;
}
# HTTPS server
server {
listen 443 ssl;
listen 443 quic reuseport;
listen [::]:443 ssl default ipv6only=on;
listen [::]:443 quic reuseport;
http2 on;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
server_name example.com;
access_log /var/log/nginx/example.com-access.log main;
error_log /var/log/nginx/example.com-error.log;
keepalive_timeout 5;
location / {
# Advertise HTTP3
add_header Alt-Svc 'h3=":$server_port"; ma=86400';
# Add typical reverse proxy headers
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Configure proxy buffering; usually this should be on unless there is a specific reason not to
proxy_buffering on;
# Set general NGINX configuration for the proxy
proxy_read_timeout 90;
proxy_redirect off;
# Pass requests to the backend server/servers
proxy_pass http://proxy_upstream;
}
}
In the above configuration ensure that you replace example.com with the real domain and set the correct path for the SSL key/certificate.