How to setup Let's Encrypt for Nginx on Ubuntu 18.04 (including IPv6, HTTP/2 and A+ SLL rating)
https://gist.github.com/cecilemuller/a26737699a7e70a7093d4dc115915de8
How to setup Let's Encrypt for Nginx on Ubuntu 18.04 (including IPv6, HTTP/2 and A+ SLL rating)
Virtual hosts
Let's say you want to host domains first.com
and second.com
.
Create folders for their files:
Create a text file /etc/nginx/sites-available/first.conf
containing:
Create a text file /etc/nginx/sites-available/second.conf
containing:
Note that only the first domain has the keywords default_server
and ipv6only=on
in the listen
lines.
Replace the default virtual host:
Check that Nginx is running:
Expected results at this stage:
http://first.com
andhttp://www.first.com
serve the files from/var/www/first
http://second.com
andhttp://www.second.com
serve the files from/var/www/second
https://www.first.com
andhttps://www.second.com
don't work yet
Certbot
Install Certbot for Nginx:
Setup the certificates & convert Virtual Hosts to HTTPS:
It will ask for:
an email address
agreeing to its Terms of Service
which domains to use HTTPS for (it detects the list using
server_name
lines in your Nginx config)whether to redirect HTTP to HTTPS (recommended) or not
You could stop here if all you want is HTTPS as this already gives you an A
rating and maintains itself.
Test your site with SSL Labs using https://www.ssllabs.com/ssltest/analyze.html?d=www.YOUR-DOMAIN.com
Expected results at this stage:
http://first.com
redirects tohttps://first.com
http://second.com
redirects tohttps://second.com
http://www.first.com
redirects tohttps://www.first.com
http://www.second.com
redirects tohttps://www.second.com
https://first.com
andhttps://www.first.com
serve the files from/var/www/first
https://second.com
andhttps://www.first.com
serve the files from/var/www/second
Automatic renewal
There is nothing to do, Certbot installed a cron task to automatically renew certificates about to expire.
You can check renewal works using:
You can also check what certificates exist using:
HTTP/2
first.conf
should now look something like this, now that Certbot edited it:
Certbot didn't add HTTP/2 support when it created the new server blocks, so replace these lines:
by this:
There is already an open Github issue requesting Certbot to add http2
automatically, so hopefully this step can soon be removed.
Stronger settings for A+
Trusted certificate
The HTTPS server
blocks in first.conf
and second.conf
contain these lines, added by Certbot:
The stronger settings use OCSP Stapling, so each virtual host will need a ssl_trusted_certificate
as well.
Add this line (using the folder name that Certbot generated for your domain) after the ssl_certificate_key
line:
SSL
Now let's edit the shared SSL settings at /etc/letsencrypt/options-ssl-nginx.conf
. It most likely looks like this initially:
If you tested with SSL Labs, you probably noticed that quite a few ciphers were flagged as "weak".
So replace the contents of the file with:
Conclusion
You could further improve using content-specific features like Content Security Policy
and Subresource Integrity
, and Brotli compression to replace gzip.
Online testing tools:
Useful links:
DavidODonovan commented on Jan 19, 2017
awesome post. THANK YOU!
gerchen commented on Jan 21, 2017
Thanks!
kakopappa commented on Jan 24, 2017 • edited
Found a lazy way :)
andresmgsl commented on Jan 29, 2017
Really thankful
MCeddy commented on Mar 3, 2017
Thank you :)
boriscy commented on Mar 21, 2017
Thanks it worked really well.
texeltexel2009 commented on Mar 21, 2017
rlam3 commented on Mar 24, 2017 • edited
does this work for 14.04 too? And what if I have cloudflare in front of nginx? How would this differ?
cecilemuller commented on Jun 2, 2017
hshhhhh commented on Jun 8, 2017 • edited
MastroMicio commented on Jun 10, 2017
thank you! this is perfect!
blbwd commented on Jun 17, 2017
Shall I need to run this code separately for each of my domain?
certbot certonly --webroot --agree-tos --no-eff-email --email YOUR@EMAIL.COM -w /var/www/letsencrypt -d www.domain.com -d domain.com
cecilemuller commented on Jun 19, 2017 • edited
with multiple
-d
, it creates a single certificate for all domains specified, so it counts as only one requestif you ran the command separately for each domain, it creates a separated certificate for each domain, and each domain counts as one request.
blbwd commented on Jun 20, 2017
It works. I am running the script to get certificate separately for each domain. Now when I set automatic renewal, will single cron will renew all of my certificates which I have generated separately for each domain?
cecilemuller commented on Jun 20, 2017 • edited
You can check it by running certbot renew --dry-run
(which merely pretends to renew), it should mention all the certificates.
blbwd commented on Jun 20, 2017
Thanks a lot. It is working. You have a such great technical and helpful person I had ever known.
cecilemuller commented on Jun 20, 2017
RobinCsl commented on Jun 28, 2017 • edited
Thank you very much. Really helpful!!! I would like to add that if you are loading index.php by default, leave the lines concerning the location of how the server needs to interpret php files.
dinofizz commented on Jul 5, 2017
This is the most concise and helpful write-up I have found! Thank you for taking the time to publish this.
josethomazini commented on Jul 8, 2017
It just works! Thank you!
rajeevkannav commented on Jul 25, 2017 • edited
Hello, Thanks for this awesome thing.
Just one Question Why we are not writing server_name mydomain.com;
like server_name mydomain.com www.mydomain.com;
single Line ?? this will save two code blocks and iterations
Thanks in advance
restmount commented on Aug 1, 2017
Thanks! Save my time.
astr0naugh7 commented on Aug 6, 2017 • edited
Hi, This worked great for me. Now I want to add another domain onto the same server using it's own SSL cert. How can I edit this to allow for multiple domains/subdirectories? With this current setup, I can't get to the IP as it just 301s to the domain I first setup with this. Is it possible to do that? I would really like to have multiple domains on this one server.
Thanks again.
diegoddox commented on Aug 14, 2017
Awesome, thanks a lot!
crw commented on Aug 17, 2017
Came to say, thanks so much! This was extremely helpful.
Regardless, plumbing the nginx docs might help.
crw commented on Aug 17, 2017
I spend like 30 minutes a server generating the damn dhparam.pem file; is it not necessary to do so?
pankaj884 commented on Aug 21, 2017
I tried this many times, and it's not working out. How can I debug what's the issue?
jwilleke commented on Aug 28, 2017
frenchbread commented on Aug 29, 2017 • edited
In addition, how would you add to this NGINX config an instance that works on port :8000
"locally" on a server and should be reverce-proxied to public :8000
port. Including same redirections as with :80
?
nadj commented on Sep 8, 2017 • edited
nginx version is 1.10.3, server is Ubuntu 16.04.3 LTS
Can you give me some advice? Thanks in advance
crspybits commented on Sep 11, 2017
Yes indeed, thanks!
yifeikong commented on Oct 8, 2017 • edited
I wish I could create a cert via --standalone
and then renew it using --wwwroot
.
blbwd commented on Oct 9, 2017
I installed SSL on my 4 domains on the same day but suddenly certificates of 2 domains expired. I already run "certbot renew --dry-run" but in vain. For those 2 domains it is showing that certificate has been expired 21 days ago. Please suggest.
cecilemuller commented on Oct 9, 2017 • edited
The best advice I could give is looking at the output of the dry run command to see if it gives an error (like if it's able to connect), or even run certbot renew
to see if it has an error only when it tries to truly renew the certificate (instead of a mere test run).
There should also be some log files in /var/log/letsencrypt
you could look at when looking for errors, but they're very verbose.
And if it does renew but doesn't show up in the browser, restart the web server service (although reloading should be enough) and clear your browser cache.
cecilemuller commented on Oct 9, 2017
blbwd commented on Oct 9, 2017
The dry run command did not show any error and all the renew process was done successfully. Tanks a lot for your suggestion to restart server. All the 2 certificates started working as soon as I restarted my nginx server.
cecilemuller commented on Oct 9, 2017 • edited
nemchik commented on Oct 31, 2017
Is there any reason why X-Frame-Options
could not be SAMEORIGIN
? Making that change doesn't seem to affect my score on SSLTest.
cecilemuller commented on Nov 2, 2017 • edited
mobambi commented on Nov 14, 2017
I followed this guide and it works well. Thanks But after this, when I'm trying to access phpmyadmin page, it returns 403 Forbidden nginx/1.10.3 (Ubuntu)... Can anyone help me with this problem?
eldoy commented on Jan 5, 2018
Thanks! Works great.
dinvisible1 commented on Jan 16, 2018
Firstly great stuff, I tried setting it up with odoo 10 on a vps but seem to be having some trouble with it, due to the sensitivity of the project can you provide some insight on how to get it working? ill gladly redact any sensitive info if successful to help other.
salfredogonzalez commented on Jan 17, 2018
Thanks, i just need another fix that is not established here that it was open the firewall rules, sudo ufw status sudo ufw allow 'Nginx Full' sudo ufw delete 'Nginx HTTP' And works great!
tinusg commented on Jan 17, 2018 • edited
If you ever run into the issue where your acme-challenge folder seems to be publicly accessible (works in your browser), but Letsencrypt still returns 404 during the CA challenge, you should check to see if your IPV6 configuration is working correctly. I had added AAAA records to my DNS server, but accidentally removed listen [::]:80; from my site settings.
Oh and don't forget to add [::]:443 ssl; to your site settings when Letsencrypt is done. It doesn't do that automatically.
dheerajbhaskar commented on Jan 19, 2018
Amazing post, this worked for me :)
besnik commented on Jan 24, 2018
Thank you, very good work!
yuryroot commented on Jan 25, 2018
kiritAyya commented on Jan 25, 2018
I have been trying this gist for a while now, and the response for the certbot command i keep getting is invalid response. If I try to access the /.well-known
folder from the browser i get a 403 forbidden from nginx. Could someone help me with this?
giantas commented on Jan 25, 2018 • edited
Why is it creating a folder named ~
in the current path?
spn89 commented on Feb 4, 2018
Created a user just to say awesome guide.
vwal commented on Feb 9, 2018 • edited
I have the following as default server config (named 00.default
since the sites are loaded in alpha order) in nginx
, and have created /var/www/nginx/_undefined/htdocs/.well-known/
directory for certbot
to use for its verification. This way I can use certbot certonly -a webroot --webroot-path=/var/www/nginx/_undefined/htdocs -d somenewdomain.com
command while I don't yet have that domain otherwise configured in nginx
.
jerome-diver commented on Feb 20, 2018
hi, when you use webroot technic for renewale certificats/keys, does it really need to reload nginx http server ? I read many tutorial, it is the one who create script for reload server http. Is it necessary to do it ?
jerome-diver commented on Feb 20, 2018
sebthemonster commented on Feb 23, 2018
Thanks a lot. Your guide is awesome.
The option --no-eff-email
is unrecognized in last version of certbot (0.10.2).
devansvd commented on Mar 4, 2018 • edited
Nice Efforts man. Seeing a good A+ SSL Certificates made my day. Thanks a ton.
OsoianMarcel commented on Mar 12, 2018
Very good tutorial. Thank you.
someburner commented on Mar 22, 2018
Found this guide nice and useful / to the point. But I remembered hearing about LE's new support for wildcard subdomains and gave that a shot. If anyone's interested in that check out my fork. And it worked even having just done this guide using non-wildcard. Certbot automatically linked to the new cert.
rob-gonz commented on Mar 31, 2018
Really appreciate. Thank you for taking the time to share this.
slavensaka commented on Apr 3, 2018
Works splendid! Thank you! Helped me secure multiple nginx servers.
roppa commented on Apr 3, 2018
This is awesome, thank you so much!
namaggarwal commented on Apr 22, 2018
Thank you so much for this. It worked like charm
kv9991 commented on Apr 25, 2018
best certbot tutorial. thanks
OsoianMarcel commented on May 10, 2018
Thank you very much, I'm using this tutorial each time I need letsencrypt. P.S. Works fine for apache2 too.
junjielee commented on May 21, 2018
Thank, it's very useful
ghost commented on May 22, 2018
awesome thank you!
LarryWachira commented on May 30, 2018
Thanks a million! Very well explained.
umarali commented on May 30, 2018
Life saver! Thanks very much!
maikdiepenbroek commented on Jun 27, 2018
bennetcq commented on Jun 29, 2018 • edited
if uncomment above code, only result in SSL A, not A+
cecilemuller commented on Jun 29, 2018 • edited
Are you asking why you're getting only A
rating when the add_header
lines start with #
? If so, that's because the settings are being ignored by Nginx, #
symbols in configs are for writing arbitrary comments.
Also the Content-Security-Policy
line in your code looks incomplete, see the one form the tutorial:
alexanderpetrenz commented on Jul 3, 2018 • edited
enabled results in an empty page when I access the fritz box sub domain. When I comment this line everything works as intended. Do you have any suggestion how I could fix that?
Regards
EDIT: I just noticed that even when I disable the mentioned line I get an A+ rating.
MagePsycho commented on Jul 15, 2018
letsencrypt-auto --nginx
vs certbot --nginx
which one is the better approach to install?
MagePsycho commented on Jul 16, 2018
There was nothing.
Can you please confirm with the auto-renewal process.
JamesSwift commented on Sep 13, 2018
markomilivojevic commented on Nov 18, 2018
For multiple virtual hosts, run command separately for each host.
shipsource commented on Dec 25, 2018 • edited
So correct redirect should be (here could be either everything to www or everything to non-www), like:
WeeHong commented on Feb 4, 2019
Thank you for posting useful gist.
robsch commented on Feb 13, 2019 • edited
adamblackxo commented on Feb 23, 2019
Thanks a lot it works fine with my app on scaleway
natharas commented on Mar 2, 2019
I tried a dry-run for renewal but it failed with the below
Processing /etc/letsencrypt/renewal/domainname.com.conf
martondob commented on Apr 8, 2019
This is fantastic! Thank you soo much for doing such a great job.
cecilemuller commented on May 10, 2019
Quick note about an issue I ran into recently: if your server fails to update certbot (0.28.0 minimum is now required as SNI is no longer supported), try sudo apt full-upgrade
because the change from python 2 to 3 is holding back the certbot package on some servers.
billpliske commented on Jun 30, 2019
Saved the day.
carlostiberiojr commented on Aug 3, 2019
How can I do the same configurations and so on, if my ISP is blocking my port 80 and 443? I cannot find anything related to that :( To set my A record is already "impossible" because of that block... do we have some way to workaround that?
rajeshkumaravel commented on Aug 20, 2019
AlbertSuarez commented on Sep 2, 2019
wallysoncarvalho commented on Feb 1, 2020
Hi, thanks a lot for the tutorial. The thing is, in my server everything works perfectly, except that afeter installation of the certificate with certbot the server stops to respond. It stays awaiting.... I have no ideia why and cant find a solution on the internet. Any idea that could help ?! Thanks !!
peterneubart commented on Apr 24, 2020
How can I get this working? So all requests http(s)://www. will get redirected to https:// without WWW
emjayess commented on Apr 25, 2020
Hi Peter,
Out of the box, the redirection managed by certbot concerns http
to https
redirection (ensures a secure connection). For the www
redirection, the most common case I think you'll find is redirecting from a root domain to the www
subdomain or variation...
Which could be achieved like this:
Or this:
And so to go the other way and always shift visits to the www
variation onto the root domain, you'll want to reverse that logic:
Or:
Such redirects generally should be implemented in their own server { ... }
block.
I hope this helps :)
tpaullee commented on May 20, 2020
You are meticulous for this nice write-up. Thanks so much! May be the link URL can be aliased to a better self-explanatory name to reach more readership.
hitjethva commented on Aug 15, 2020
I ran this command: certbot --apache -d linuxbuz.com
I am getting the following error:
IMPORTANT NOTES:
The following errors were reported by the server:
Last updated