Easiest method for all users.
Official instructions on how to obtain and install NGINX at: NGINX Linux packages (nginx.org)
Advanced users only. NGINX is built from the latest source code. It is generally not recommended unless you are OK with potential compatability issues. You understand you may need to debug, rebuild, update or rollback more than normal. From personal experience, there are typically no issues.
In summary, a single packet loss in the HTTP/2 TCP connection blocks the stream of data in its entirety. It's either all or nothing. With HTTP/3 QUIC (UDP over H3), a single packet loss doesn't block the entire stream of data. It's limited to that stream while the rest can continue as normal. H3 + QUIC also comes with zero roundtrip time (0-RTT). Client and servers can avoid TLS handshake during reconnection decreasing network latency. Brotli compression will compress contents to smaller sizes than gzip in the same of amount of time or faster. In addition to an ECDSA certificate and optimal directives, NGINX can be extremely fast. Read more here and here. Lastly, the inclusion of ModSecurity adds a basic Web Application Firewall (WAF) to enhance security from a myriad of attacks.
If you're not comfortable building from source, precompiled versions available for you to use. Build instructions are provided at the linked repo.
NGINX uses configuration files to create servers (virtual hosts).
Your connection should always be secure (HTTPS). To do this, you need a TLS certificate. Certbot will collect a security certificate for your domain using the service LetsEncrypt. It's ideal to install with snap
rather than apt
on Ubuntu. If you use Arch or any other distro, you should be fine installing with the default package manager. You should also use a DNS plugin if you have your domain name server set with one of the listed providers on the linked DNS plugin page. This allows for easy certificate management.
# Ubuntu example
snap install --classic certbot; snap set certbot trust-plugin-with-root=ok; snap install -certbot-dns-xxx; snap connect certbot:plugin certbot-dns-xxx; ln -s /snap/bin/certbot /usr/bin/certbot; certbot --version
Unless you are aware that you need to support very old HTTPS clients that are not supported by most sites, you can safely just transition your site to use ECDSA keys instead of RSA keys.
The main advantage of ECDSA stems from the same level of security for less cost in performance. RSA 2048 provides a security level of 112 bits. ECDSA 224 provides a security level of 112 bits. This is a significant difference in key size. Smaller key sizes require less bandwidth to set up a TLS stream. This means ECDSA certificates are ideal for mobile use. While this might not be noticable in day to day use, in terms of web based services, this performance advantage matters.
ECDSA (recommended)
certbot certonly --dns-xxx --dns-xxx-credentials --key-type ecdsa --elliptic-curve secp256r1 --uir --hsts --staple-ocsp -d yourdomain.me -d '*.yourdomain.me'
RSA (not recommended)
certbot certonly --dns-xxx --dns-xxx-credentials --key-type rsa --uir --hsts --staple-ocsp -d yourdomain.me -d '*.yourdomain.me'
Full disclosure: Some people believe ECDSA NIST curves contain a deliberate backdoor for the NSA. There is currently no proof of this. You are free to make your own decision. EdDSA is the most recent implementation of cryptography and aims to be an alternative of ECDSA, sans NIST. However, it is currently not supported in any capacity. CA's are bound by an agreement that allows them to be trusted in a browser or on a device. 6.1.5 "Key sizes" defines the only accepted methods.
Intermediate compatability provides optimal security and compatability trade off.
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:ECDHE-ECDSA-AES128-CCM:ECDHE-ECDSA-AES128-CCM8:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-CCM:ECDHE-ECDSA-AES256-CCM8:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-PSK-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305;
Modern compatability provides the highest security when using modern devices.
ssl_protocols TLSv1.3;
ssl_ciphers TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-PSK-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
If you prefer to support really old devices, you may use RSA and older TLS versions. Please remember, older TLS versions and weak ciphers opens your server to MITM attacks. As such this not recommended. For the highest level of security and to take advantage of QUIC, you can drop TLS 1.2 using only TLS 1.3 (Modern compatability). I highly recommend this configuration. However, it is up to you to determine your needs for device support.
Lastly, for TLS 1.2 and older, you can include Diffie Hellman Parameters.
openssl dhparam -dsaparam -out /etc/nginx/dh/dhparam.pem 4096
What is kTLS?
This requires the TLS kernel module. To use requires an up-to-date NGINX and OpenSSL 3+.
Check to see if the module is loaded with:
lsmod | grep tls
If not loaded, check your kernel version.
uname -a
You need kernel version 5.11 or later. With an updated OS, this shouldn't be a problem. Simply load the module on boot:
[nano|gedit] /etc/modules
Add in at the bottom, tls
. Save and restart.
To prevent anyone from bypassing your domain by using the direct IP, you'll need an additional conf file to stop the server from serving content. See the reference files. For HTTPS, you'll need a "fake" or invalid (untrusted) TLS certificate since you're not officially supporting this access.
openssl req -x509 -nodes -newkey ec -pkeyopt ec_paramgen_curve:prime256r1 -keyout serverkey.pem -out servercert.pem -days 3650 -subj "/CN=invalid"
This doesn't stop bots and people probing the IP looking for services. Because the server is still responding. It's just dropping the connection.
The directive ssl_buffer_size
directly relates to time to first byte (TTFB). NGINX defaults to 16k
if you do not set this manually. The lowest value is 1400
.
Lastly, here are some general tips:
You shouldn't turn off proxy_buffering
as it's beneficial. To get your page size for buffering:
grep -ir pagesize /proc/1/smaps
For proper keepalive
connections with a reverse proxy, you should use upstream
as it prevents NGINX from cycling through source ports. Read here.
If you have a purchased a domain, enable DNS CAA.
CAA is a type of DNS record that allows site owners to specify which Certificate Authorities (CAs) are allowed to issue certificates containing their domain names.
With a certificate from LetsEncrypt you can create a CAA
record that points to letsencrypt.org
for the root of your domain.
Get on the HSTS preload list and use DNSSEC if provider allows.
The remaining directives are already setup with their recommended values. The configuration nets the following end results if you obtain an TLS certificate:
Here are handful of educational resources and testing sites:
Software that automatically includes servers to access a web interface (node.js for example) means you proxy_pass
with NGINX. Assuming you have correctly loaded brotli either by static compile or dynamic module, NGINX won't touch it if one or more of the following condititions are true:
Content-encoding: gzip
.You must disable gzip in that node server and run both node.js NGINX on the same system.
Here is an example for wiki.js.
Simply edit two files.
nano /path/to/wikijs/server/master.js
Comment out app.use(compression())
on line 38.
nano /path/to/wikijs/server/setup.js
Comment out app.use(compression())
on line 29.