{"id":927,"date":"2018-03-08T13:35:26","date_gmt":"2018-03-08T05:35:26","guid":{"rendered":"http:\/\/www.xiaobo.li\/?p=927"},"modified":"2018-03-08T13:36:19","modified_gmt":"2018-03-08T05:36:19","slug":"lets-encrypt-ssl-and-nginx-using-certbot","status":"publish","type":"post","link":"https:\/\/www.xiaobo.li\/notes\/archives\/927","title":{"rendered":"Let\u2019s Encrypt SSL and Nginx (using certbot)"},"content":{"rendered":"<div class=\"entry-content\">\n<p>A few days ago I enabled HTTPS and SSL\/TLS on this blog. A big barrier to enabling SSL on your website is the cost of the SSL certificate and the maintenance overhead of having to constantly renew your certificate. You could already get free SSL certificates with <a href=\"https:\/\/startssl.com\/\">StartSSL<\/a>, but the process of obtaining the certificate is still a manual process. A few months ago <a href=\"https:\/\/letsencrypt.org\/sponsors\/\">Mozilla and a bunch of companies<\/a> came together and created <a href=\"https:\/\/letsencrypt.org\/\">Letsencrypt<\/a>, a service which issues free SSL certificates that are automatically generated with a command line tool. When set up correctly, it alleviates the need for manual intervention. As of the writing of this blog post, the service is still in beta and support for Nginx is minimal, but it\u2019s not difficult to set up.<\/p>\n<p><del datetime=\"2016-05-15T02:43:08+00:00\">Since the software is still in beta, the only way to get it is via <a href=\"https:\/\/github.com\/letsencrypt\/letsencrypt\">letsencrypt github<\/a>. First we need to pull the repository:<\/del><\/p>\n<p><b>Update 15\/05\/2016 \u2013 previously named letsencrypt-auto, the certificate utility is now called certbot-auto<\/b><\/p>\n<div class=\"EnlighterJSWrapper enlighterEnlighterJSWrapper\">\n<ol class=\"hoverEnabled enlighterEnlighterJS EnlighterJS\">\n<li class=\" odd\"><span class=\"\">$ wget https:\/\/dl.eff.org\/certbot-auto<\/span><\/li>\n<li class=\" even\"><span class=\"\">$ chmod a+x .\/certbot-auto<\/span><\/li>\n<\/ol>\n<\/div>\n<p>We then get the certbot-auto executable. Running <code>.\/certbot-auto --help<\/code> will give you the available commands. The current version has built in support for Apache, with nginx under testing. But as long as we get the certificate, we could install it to any software supported or not. I will illustrate the (initially) manual way of getting the certificate with nginx.<\/p>\n<h2>Obtaining the certificate from Let\u2019s Encrypt<\/h2>\n<p>To obtain a certificate, ownership of the domain needs to be verified. Letsencrypt achieves this by checking for the contents of a file under http:\/\/www.example.com\/.well-known\/acme-challenge\/. There are two ways given by certbot-auto to make this file available \u2013 by spawning a standalone server to listen on port 80 (<code>--standalone<\/code>), or by adding the files to the root folder of the web site (<code>--webroot<\/code>). The problem with <code>standalone<\/code> is that you have to stop your active web server on port 80, causing downtime, where as webroot allows your current server to continue operating. So webroot is the solution we will use.<\/p>\n<p>Obtain a certificate with webroot, by calling this command (replacing example.com and \/var\/www\/example obviously!). You can append more domains with <code>-d<\/code>.<\/p>\n<div class=\"EnlighterJSWrapper enlighterEnlighterJSWrapper\">\n<ol class=\"hoverEnabled enlighterEnlighterJS EnlighterJS\">\n<li class=\" odd\"><span class=\"\">.\/certbot-auto certonly --webroot -w \/var\/www\/example -d example.com -d www.example.com<\/span><\/li>\n<\/ol>\n<\/div>\n<p>The above method requires you to have a physical root folder. If you are using nginx as a load balancer or reverse proxy (i.e. <code>proxy_pass<\/code>), you most likely won\u2019t have a root for your domain. In those cases, you could add a location alias to your <code>nginx.conf<\/code> under the HTTP (port 80) <code>server<\/code> directive for the domain:<\/p>\n<div class=\"EnlighterJSWrapper enlighterEnlighterJSWrapper\">\n<ol class=\"hoverEnabled enlighterEnlighterJS EnlighterJS\">\n<li class=\" odd\"><span class=\"\"> location \/.well-known {<\/span><\/li>\n<li class=\" even\"><span class=\"\"> alias \/var\/www\/html\/.well-known;<\/span><\/li>\n<li class=\" odd\"><span class=\"\"> }<\/span><\/li>\n<\/ol>\n<\/div>\n<p>Then run:<\/p>\n<div class=\"EnlighterJSWrapper enlighterEnlighterJSWrapper\">\n<ol class=\"hoverEnabled enlighterEnlighterJS EnlighterJS\">\n<li class=\" odd\"><span class=\"\">.\/certbot-auto certonly --webroot -w \/var\/www\/html -d example.com -d www.example.com<\/span><\/li>\n<\/ol>\n<\/div>\n<p>The first time you run certbot, it will ask you to agree to the TOS and register your email. After that, the operation is pretty much unattended.<\/p>\n<p>After the command finishes, you should have your certificate at \/etc\/letsencrypt\/live\/example.com\/fullchain.pem and private key at \/etc\/letsencrypt\/live\/example.com\/privkey.pem<\/p>\n<h2>Install the certificate into nginx<\/h2>\n<p>Modify you nginx configuration file to <a href=\"http:\/\/nginx.org\/en\/docs\/http\/configuring_https_servers.html\">enable SSL<\/a>:<\/p>\n<div class=\"EnlighterJSWrapper enlighterEnlighterJSWrapper\">\n<ol class=\"hoverEnabled enlighterEnlighterJS EnlighterJS\">\n<li class=\" odd\"><span class=\"\">server {<\/span><\/li>\n<li class=\" even\"><span class=\"\"> listen 443 ssl;<\/span><\/li>\n<li class=\" odd\"><span class=\"\"> server_name example.com;<\/span><\/li>\n<li class=\" even\"><span class=\"\"> ssl_certificate \/etc\/letsencrypt\/live\/example.com\/fullchain.pem;<\/span><\/li>\n<li class=\" odd\"><span class=\"\"> ssl_certificate_key \/etc\/letsencrypt\/live\/example.com\/privkey.pem;<\/span><\/li>\n<li class=\" even\"><span class=\"\">}<\/span><\/li>\n<\/ol>\n<\/div>\n<p>You may also want to add <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/Security\/HTTP_strict_transport_security\">Strict-Transport-Security<\/a> (HSTS) to your config, such that any internal links that are not https will automatically be routed to the HTTPS version during a HTTPS session.<\/p>\n<div class=\"EnlighterJSWrapper enlighterEnlighterJSWrapper\">\n<ol class=\"hoverEnabled enlighterEnlighterJS EnlighterJS\">\n<li class=\" odd\"><span class=\"\"> add_header Strict-Transport-Security <\/span><span class=\"st0\">\"max-age=31536000; includeSubDomains\"<\/span><span class=\"\">;<\/span><\/li>\n<\/ol>\n<\/div>\n<p>Lastly, reload the nginx configuration:<\/p>\n<div class=\"EnlighterJSWrapper enlighterEnlighterJSWrapper\">\n<ol class=\"hoverEnabled enlighterEnlighterJS EnlighterJS\">\n<li class=\" odd\"><span class=\"\">sudo service nginx reload<\/span><\/li>\n<\/ol>\n<\/div>\n<h2>Auto-renewing the certificate<\/h2>\n<p>Let\u2019s Encrypt certificates are only valid for 3 months after issue. So every 3 months, renewal is required. Since the process of obtaining the certificate is through the command line, this process could be automated. We could set up a cron job which takes care of the renewal, like the below:<\/p>\n<div class=\"EnlighterJSWrapper enlighterEnlighterJSWrapper\">\n<ol class=\"hoverEnabled enlighterEnlighterJS EnlighterJS\">\n<li class=\" odd\"><span class=\"\">0 6 * * * \/path\/to\/certbot\/certbot-auto renew --text &gt;&gt; \/path\/to\/certbot\/certbot-cron.log &amp;&amp; sudo service nginx reload<\/span><\/li>\n<\/ol>\n<\/div>\n<p>The above cron job is set up to run daily, but the certificate is only renewed if less than 30 days to expiry.<\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<p>links:\u00a0 https:\/\/loune.net\/2016\/01\/https-with-lets-encrypt-ssl-and-nginx\/<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A few days ago I enabled HTTPS and SSL\/T &hellip; <a href=\"https:\/\/www.xiaobo.li\/notes\/archives\/927\">\u7ee7\u7eed\u9605\u8bfb <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[284],"tags":[],"class_list":["post-927","post","type-post","status-publish","format-standard","hentry","category-webserver"],"_links":{"self":[{"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/posts\/927","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/comments?post=927"}],"version-history":[{"count":0,"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/posts\/927\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/media?parent=927"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/categories?post=927"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xiaobo.li\/notes\/wp-json\/wp\/v2\/tags?post=927"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}