nginx HTTPS config: SSL server block with redirect
Serve your site over HTTPS with nginx: certificate paths, HTTP to HTTPS redirect, HSTS and a proxy or static site.
This nginx server block turns on HTTPS with your certificate, sends visitors from HTTP to HTTPS, and either passes requests to your app or serves a folder of files. Get a certificate first (the steps are below), then fill in the form.
Create your config file
Type your own values. The file below updates as you type, and nothing you type leaves your browser.
server {
listen 80;
listen [::]:80;
server_name example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
}How this setup works
Step-by-step setup
- Get a certificate first: sudo certbot certonly --nginx -d example.com. Your domain must already point to this server.
- Save the config as /etc/nginx/conf.d/example.com.conf.
- Test it: sudo nginx -t.
- Apply it: sudo systemctl reload nginx.
- Open https://example.com and check the padlock.
- Test automatic renewal: sudo certbot renew --dry-run.
What the important lines mean
- ssl_certificate and ssl_certificate_key point to the files certbot created for example.com.
- return 301 sends every HTTP visitor to the HTTPS address.
- X-Forwarded-Proto tells your app that the visitor used HTTPS.
- HSTS makes browsers refuse plain HTTP for a year. Turn it on only when HTTPS works everywhere.
Common errors and how to fix them
- cannot load certificate: No such file or directory
- The path is wrong, or no certificate has been issued yet. Run certbot first and copy the exact paths it prints.
- ERR_TOO_MANY_REDIRECTS
- Your app, or a service such as Cloudflare in flexible mode, also redirects to HTTPS and loops. Make sure only one place does the redirect.
- nginx: [warn] the “http2” directive is deprecated
- Your nginx is 1.25.1 or newer. Tick the option for newer nginx above.
- unknown directive “http2”
- Your nginx is older than 1.25.1. Untick the option for newer nginx so the http2 flag goes on the listen line.
- bind() to 0.0.0.0:443 failed
- Another program uses port 443. Find it with the port checker.
Frequently asked questions
- How do I get a free SSL certificate for nginx?
- Use Let’s Encrypt with certbot. Run certbot certonly --nginx -d your-domain, then point the config at the files it creates.
- How do I redirect HTTP to HTTPS in nginx?
- Add a server block on port 80 that returns 301 to https://$host$request_uri. The generator does this when the redirect option is ticked.
- Should I turn on HSTS?
- Only after HTTPS works for the whole site. HSTS cannot easily be undone for visitors who already received it.
Free tools that help
- Common ports listSearch a list of common TCP and UDP port numbers: SSH 22, HTTP 80, HTTPS 443, MySQL 3306, PostgreSQL 5432 and more, with dev server ports.
Fix a problem with this setup
- localhost https SSL errorFix ERR_SSL_PROTOCOL_ERROR and invalid response errors on localhost: use http, clear the saved HTTPS rule, or set up a trusted local certificate.
- Localhost redirected too many timesFix ERR_TOO_MANY_REDIRECTS on localhost: clear cookies, fix HTTP and HTTPS rules, and WordPress URL settings.
- nginx 502 Bad GatewayFix nginx 502 Bad Gateway with Node, PHP-FPM or any proxy: read the error log, check the app is running and the port or socket matches.
More server configs
- .htaccess fileBuild an Apache .htaccess file with an HTTPS redirect, www rules, compression, caching and a front controller.
- robots.txt fileCreate a robots.txt that tells search engines what to crawl, with a sitemap line and optional AI crawler blocks.
- nginx redirect www to non-wwwSend www.example.com to example.com (or the reverse) with one permanent redirect.
- nginx load balancer configSplit traffic across two or three copies of your app with an nginx upstream block.
- nginx rate limit configSlow down abusive visitors with limit_req: a request rate per IP, a burst, and a 429 answer.
- php.ini settingsSet the PHP values most sites need: upload size, memory, run time, errors, time zone and OPcache.