What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Secure Nginx on Ubuntu 24.04 by patching the host, protecting SSH before enabling the firewall, obtaining and testing a trusted TLS certificate, limiting protocols, adding response headers, hiding version details, controlling abusive requests, and validating every change before a reload. The safest workflow is incremental: make one change, run sudo nginx -t, reload only after the test passes, then verify the result from a client.

This guide assumes a server you administer with sudo, a DNS name pointing to it, and an application that should be reachable over HTTPS. Replace example.com and the sample SSH port with your own values.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What “secure Nginx” means on Ubuntu 24.04

Nginx hardening is not a single switch. It is a set of controls that reduce different risks:

  • Host updates close vulnerabilities in Ubuntu, Nginx, OpenSSL and related packages.
  • UFW limits which network services can be reached from the internet.
  • HTTPS encrypts traffic and authenticates your hostname.
  • TLS policy removes obsolete protocol versions and weak negotiation choices.
  • Security headers tell browsers how to handle content, framing and referrers.
  • Rate limits, log review and bans reduce the impact of automated abuse.
  • Configuration testing prevents a typo from taking down a working site.

Ubuntu 24.04 LTS receives standard security maintenance until 31 May 2029. Canonical describes Ubuntu Pro as extending coverage to 10 years and the Legacy add-on to 12 years. Those are support entitlements, not a substitute for applying updates promptly.

1. Patch the server and install the hardening tools

Start from a current package index and apply available updates. Reboot when the kernel or a service requires it, and schedule maintenance so security updates do not accumulate.

sudo apt update
sudo apt full-upgrade

Install Nginx, the uncomplicated firewall, Certbot’s Nginx integration, and optional controls for repeated attacks and unattended patching:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
sudo apt install nginx ufw certbot python3-certbot-nginx fail2ban unattended-upgrades

Keep the distribution packages updated even if you later add a third-party module. A module compiled for another Nginx or OpenSSL version can introduce compatibility and maintenance problems.

Confirm the service and package versions

systemctl status nginx --no-pager
nginx -v
openssl version

If Nginx is not required yet, you can install it without exposing it publicly. The firewall sequence below determines when external access is allowed.

2. Configure UFW without locking yourself out

The most dangerous firewall mistake on a remote server is enabling a default-deny policy before allowing the SSH session you are using. Add the SSH rule first, then web traffic, and only then enable UFW.

Allow the standard SSH service

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

When SSH listens on a custom port, allow that port instead of (or in addition to) the OpenSSH application profile. For example, for TCP port 2222:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
sudo ufw allow 2222/tcp

Do this while your current administrative connection is still open, then start a second SSH connection to verify the rule. Do not remove the old rule until the new port has been tested.

Restrict administration when practical

A public SSH port is routinely scanned. If your organization has fixed office or VPN addresses, restrict the SSH rule to those sources:

sudo ufw delete allow 2222/tcp
sudo ufw allow from 203.0.113.0/24 to any port 2222 proto tcp

Use your real trusted network, not the documentation address above. Keep port 80 open when you need HTTP-to-HTTPS redirects or HTTP-01 certificate validation; keep 443 open for the site itself.

3. Create a safe Nginx configuration workflow

Ubuntu’s main file is /etc/nginx/nginx.conf. Site definitions normally live in /etc/nginx/sites-available/ and are enabled through symbolic links in /etc/nginx/sites-enabled/. Small reusable snippets belong in /etc/nginx/snippets/.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Back up before editing

sudo cp -a /etc/nginx /etc/nginx.backup.$(date +%F-%H%M%S)

Make one logical change at a time. Check the complete configuration, not just the file you edited:

sudo nginx -t

Only after the output reports that the syntax is OK and the test is successful should you apply a reload:

sudo systemctl reload nginx

A reload lets existing connections finish while workers adopt the new configuration. If the test fails, read the file name and line number in the error, correct that issue, and run the test again. Do not use a reload to “see whether it works.”

4. Obtain and verify a Let’s Encrypt certificate

Certbot is an ACME client that can request a free Let’s Encrypt certificate, install it in an Nginx server block, create an HTTP-to-HTTPS redirect, and arrange automatic renewal.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Prepare DNS and an HTTP server block

Point every requested hostname at the server’s public address. Ensure TCP port 80 is reachable through UFW and any cloud security group. Nginx must answer for the same names you pass to Certbot.

Run the Nginx plugin

sudo certbot --nginx -d example.com -d www.example.com

Follow the prompts carefully. Choose the redirect option when all intended traffic should use HTTPS. If a name is not hosted on this server, do not include it in the command; validation will fail.

Check the certificate and renewal path

sudo certbot certificates
sudo certbot renew --dry-run

The dry run exercises the renewal process without replacing a live certificate. Keep the timer or scheduled job that Certbot installed, and investigate any failure before the certificate approaches expiry. Renewal also depends on continued DNS correctness and reachable validation endpoints.

5. Choose a TLS policy that matches your clients

Disable TLS 1.0 and TLS 1.1. On Ubuntu 24.04, the practical choice is between an Intermediate profile that keeps TLS 1.2 and a Modern profile limited to TLS 1.3.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Profile Protocols When to use Important considerations
Intermediate TLS 1.2 and TLS 1.3 Public sites with a broad or unknown client population Best compatibility. TLS 1.3 cipher suites are selected by OpenSSL; do not copy an old TLS 1.0/1.1 cipher list.
Modern TLS 1.3 only Controlled environments where every required client supports TLS 1.3 Older browsers, embedded devices and legacy integrations will fail to connect.

The Mozilla SSL Configuration Generator provides Nginx templates for Modern, Intermediate and Old profiles. Treat its generated output as a starting point and check it against the Nginx and OpenSSL versions installed on Ubuntu 24.04.

Baseline directives for an Intermediate deployment

Place TLS directives in the HTTPS server block or an included TLS snippet. The following establishes the protocol floor and disables session tickets; retain the certificate paths that Certbot installed:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_tickets off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

If your chosen profile calls for finite-field Diffie–Hellman parameters, create a parameter file once and protect it:

sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048
sudo chmod 600 /etc/nginx/dhparam.pem
ssl_dhparam /etc/nginx/dhparam.pem;

Generating parameters can take a while. Do it during a maintenance window and do not regenerate the file on every reload.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When a TLS 1.3-only policy is appropriate

Use ssl_protocols TLSv1.3; only after you have an inventory of browsers, APIs, monitoring probes and devices that must connect. A failed handshake on an old client is an availability failure, not a security improvement. If you select the Modern profile, configure OCSP stapling and a functioning DNS resolver as required by the template you adopt, then verify the chain and stapled response with an external TLS test.

Test the negotiated result

After reloading, run a public SSL configuration test such as SSL Labs and review protocol support, certificate chain, key exchange, expiry and obsolete-version warnings. Test from at least one current desktop browser and from every legacy client you intentionally support.

6. Add browser security headers correctly

Create a snippet so every HTTPS server block receives the same baseline headers. For example, save the following as /etc/nginx/snippets/security-headers.conf:

add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

Include it inside each relevant server block:

include /etc/nginx/snippets/security-headers.conf;

The always parameter makes the headers appear on error responses as well as successful responses. If a nested location defines its own add_header directives, check inheritance deliberately; a child configuration can change which headers are emitted.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose the framing policy

SAMEORIGIN permits your pages to be framed by pages from the same origin. Use DENY instead when the application never needs framing. Test login flows, payment widgets and administrative consoles before changing this value.

Do not add the obsolete X-XSS-Protection header

Modern browsers have dropped support for the legacy X-XSS-Protection mechanism. Do not add it to obtain a better scanner score. Content Security Policy (CSP) is the modern control, but it must describe the resources your particular site loads.

Deploy CSP in a controlled way

Start with a report-only policy or a narrowly scoped policy while you inventory scripts, styles, fonts, frames and API endpoints. A policy such as default-src 'self' can break a site that uses a content-delivery network, inline scripts or third-party identity provider. Add CSP only after testing all important pages, and keep it in the same snippet so changes are reviewable.

Use securityheaders.com to inspect the response from the public HTTPS hostname. Check both a normal page and an intentional 404 so you know the always behavior is working.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

7. Hide version information without mistaking it for a patch

In the http block of /etc/nginx/nginx.conf, set:

http {
    server_tokens off;
    # existing http-level directives...
}

This removes the Nginx version from generated error pages and from the normal Server response field. It does not make a vulnerable module safe and it does not replace timely updates. Verify externally with:

curl -I https://example.com
curl -s https://example.com/does-not-exist

Some distributions or modules can add their own identifying fields. Review the actual response rather than assuming that one directive removes every banner.

8. Roll out HSTS in stages

HTTP Strict Transport Security (HSTS) tells a browser to use HTTPS for a hostname. It is powerful and deliberately difficult to undo: a mistaken policy can make an otherwise recoverable HTTP site unreachable in that browser.

Confirm the prerequisites first

  • Every intended hostname has a valid certificate.
  • HTTP redirects reliably to HTTPS.
  • Certbot renewal succeeds in a dry run.
  • All pages, APIs, downloads and administrative paths work over HTTPS.
  • You have a recovery plan that does not depend on plain HTTP.

Start with a short lifetime

After those checks, add a short policy to the HTTPS server block:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
add_header Strict-Transport-Security "max-age=300" always;

Five minutes gives you a reversible first observation period. Once you are confident, increase max-age gradually, commonly to a year (31536000 seconds).

Add subdomains and preload only when ready

Add includeSubDomains only when every subdomain, including forgotten or internal names, serves HTTPS continuously. Consider preload only after meeting the current preload program’s requirements and accepting that removal is slow. Never combine a long lifetime, includeSubDomains and preload as a first experiment.

9. Limit abusive requests

Nginx can slow bursts before they reach an application. Define a shared zone in the http block:

limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;

Apply it narrowly in a location that is expensive or abuse-prone:

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
location /login {
    limit_req zone=perip burst=20 nodelay;
    proxy_pass http://127.0.0.1:8080;
}

The rate and burst values are examples, not universal safe limits. Measure normal traffic first. Applying a strict limit to static assets or an API used by mobile clients can create false positives and outages. Return a clear status to clients and exempt trusted internal paths where appropriate.

Pair limits with fail2ban

Rate limiting slows a source; fail2ban can temporarily block sources that repeatedly trigger authentication or abuse patterns. Enable only filters that match your logs, set conservative ban times initially, and verify the result:

sudo systemctl enable --now fail2ban
sudo fail2ban-client status
sudo fail2ban-client status <jail-name>

Do not ban your own management address while testing. Keep an out-of-band console or a trusted second address available for recovery.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

10. Monitor logs and make failures visible

Nginx records request and error information under /var/log/nginx/. Watch the error log during every configuration change:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
sudo tail -f /var/log/nginx/error.log
sudo journalctl -u nginx -f

Look for repeated authentication failures, unexpected methods, upstream timeouts, certificate errors, malformed requests and sudden status-code changes. Ubuntu’s logrotate configuration normally prevents unbounded growth; confirm that rotated logs are retained long enough for incident investigation.

Unattended upgrades can install critical security fixes automatically, but you still need a process to review reboots, application compatibility and failed jobs. Automation reduces exposure time; it does not remove operational responsibility.

11. Validate the hardened site

Run this checklist after each major change and again after DNS, certificate or application changes:

  1. Confirm UFW: sudo ufw status verbose. Only intended inbound ports should be allowed.
  2. Confirm Nginx syntax: sudo nginx -t.
  3. Reload safely: sudo systemctl reload nginx.
  4. Request headers: curl -I https://example.com. Check HSTS (if enabled), framing, MIME sniffing and referrer policy.
  5. Check redirects: curl -I http://example.com should produce the intended HTTPS redirect.
  6. Check certificate expiry and names: sudo certbot certificates.
  7. Exercise renewal: sudo certbot renew --dry-run.
  8. Run an SSL Labs scan and resolve protocol, chain and cipher warnings appropriate to your client policy.
  9. Run a securityheaders.com scan and investigate findings rather than blindly adding headers.
  10. Review /var/log/nginx/error.log and the system journal for errors introduced by the change.

12. Troubleshooting common hardening failures

SSH stopped working after enabling UFW

Use the hosting provider’s console or another existing session. Add the correct SSH port, then check the rules:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
sudo ufw allow 22/tcp
sudo ufw status numbered

If SSH uses a different port, allow that port instead. Do not disable the firewall permanently; correct the rule, verify a new connection, and remove accidental broad rules.

nginx -t reports an unknown directive

Check spelling, context and the installed build. A directive valid in one module or Nginx version may not be available in another. Remove the new line or restore the backup, retest, and consult the Nginx reference for the exact module and context before trying again.

Certbot cannot validate a hostname

Check that DNS resolves to this server, port 80 reaches Nginx through every firewall layer, and the server block contains the requested name. A proxy, stale AAAA record or restrictive UFW rule can send the challenge elsewhere.

Security headers appear on one page but not another

Confirm that the snippet is included in every HTTPS server block and inspect nested location blocks for their own header directives. The always parameter is required when you expect headers on error responses.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Legacy clients fail after the TLS change

Determine which protocol the client negotiated before the change. If business requirements include that client, use the Intermediate profile with TLS 1.2 rather than forcing TLS 1.3-only. If the client is obsolete and can be retired, document that decision instead of silently weakening every connection.

The site breaks after enabling HSTS

HSTS is cached by the browser, so changing the server header does not immediately undo a long policy. Restore HTTPS on the affected hostname and subdomains, fix certificates or redirects, and use short lifetimes during future rollouts.

13. Keep the configuration secure over time

  • Apply Ubuntu and Nginx security updates promptly and reboot when required.
  • Review UFW rules whenever you add or remove a service.
  • Re-run certificate renewal tests after DNS, proxy or firewall changes.
  • Recheck TLS and headers after Nginx or OpenSSL upgrades.
  • Review rate-limit logs and tune thresholds as traffic changes.
  • Test backups by restoring Nginx configuration and application data, not merely by confirming that a backup file exists.
  • Record who can administer the host and remove unused accounts, keys and sudo access.

A hardened Nginx installation is a maintained system: the controls above work together, and each change should be tested from both the server and an external client.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.