Hacker News new | past | comments | ask | show | jobs | submit login
CertBot: Automatically enable HTTPS on your website with Let's Encrypt certs (eff.org)
393 points by itherseed on May 16, 2016 | hide | past | favorite | 88 comments



If, like me, you don't want it to modify your configs files for you, and don't want to turn off the webserver everytime you renew certificates, use Webroot mode.

I updated my guide to setup Nginx + Ubuntu 16.04 + Let's encrypt (Nginx, IPv6, HTTP/2, and A+ rating at SLL Labs):

https://gist.github.com/cecilemuller/a26737699a7e70a7093d4dc...

I hope it helps those that hesitate to use Let's encrypt.


You can now get those instructions in concise form from the simple widget at https://certbot.eff.org.

Let us know if there are any tweaks you'd like to see made to them (or send a PR to https://github.com/certbot/website, the instructions are in _scripts/instruction-widget)


Another good method is to use https://github.com/diafygi/acme-tiny and the ciphers from https://cipherli.st


I used acme-tiny to secure several domains on my server, including automated renewal via cron, running as an unprivileged user that only has access to the CSR, the ACME auth key, and the directory /.well-known/acme maps to, but not the server private key. Took about an hour to secure three domains, most of which was convincing OpenSSL to produce the right three CSRs with SubjectAltName set (to cover the "www." variants so I can securely redirect them).


On AWS, you can also use https://github.com/alex/letsencrypt-aws - it works great if you're using both Route 53 and ELB. It uses the dns-01 challenge, which is out-of-band - it adds a text record to your DNS instead of needing to inject content into your server. I prefer that approach.


On AWS you can get free SSL certificates from AWS. https://aws.amazon.com/certificate-manager/


Only free if you have Elastic Load Balancer running for each domain. If you're hosting a dozen micro-sites on a box, the Certificate Manager path gets a little expensive

/me looks at his February bill and remembers the lesson all too well


Also free for static sites hosted on Cloudfront. Doesn't solve your problem, just thought I'd mention it in the interest of possible interest.


Considering alex/letsencrypt-aws is also designed specifically for ELB, I think the comparison to ACM is appropriate.

From what I can tell, the only reasons to use alex/letsencrypt-aws (IAM certificates) instead of AWS Certificate Manager are if you're either 1, provisioning ELBs in a region other than us-east-1 and unable to wait for Amazon to roll out ACM to other regions; or 2, subsequently applying the same certificate to other resources in addition to ELB+CloudFront (e.g., a standalone EC2 instance running nginx or apache).


Not sure I understand this pricing implication. Did you run separate ELB for each domain name?


Even cheapo static S3 sites are free if they're behind CloudFront.


Unfortunately, right now ACM only works with CloudFront distributions or with ELBs in us-east-1. If you're running ELBs in another region, you can't use ACM on them.


Unfortunately doesn't work with AWS Lambda/API Gateway. Especially odd as Lambda has Cloudfront on the top of it, but shrug.

Unfortunately it looks as though letsencrypt-aws won't either.


Would it be possible to use letsencrypt-aws on a AWS Lambda + API Gateway + Route 53 setup?


letsencrypt-aws looks to be designed specifically to automate updating ELB certificates, and doesn't seem quite as suitable for provisioning certificates for standalone EC2 instances, for example.

I've had good results using https://github.com/sorah/acmesmith which also uses the dns-01 challenge via Route53, but saves certificates to an S3 bucket that can be fetched from any EC2 instance granted the proper permissions.


I also wrote a tool to automate this, using Ruby. Rather than an all-in-one magic solution, it is just a set of tools intended to be easy to modify to fit in to your existing workflow/app.

https://github.com/paul/letsencrypt-route53


Does anyone know if the DNS challenge changes every renewal, or if I can leave it there forever and have renewals work?


ACME defines an authorization object, which is created for every FQDN on a certificate. Part of this object is a randomized token. A valid authz object (i.e. one for which you have solved a challenge by, say, creating a TXT record with the token) allows you to request (any number of) certificates for the FQDN until the expiration date of the object is reached (10 months in case of Let's Encrypt).

So basically you can get up to 13 months worth of certificates out of one token/solved challenge. That being said, none of the clients I'm aware of currently reuse authorizations - they create a new one during renewal, which would result in a new token.


Ah, thanks. So this is not really that useful, since I can't keep reusing the same object. I guess I'll have to stick with the webroot method, too bad.


I am yet to try this, but I never liked the idea that it automatically edits my nginx config. Seeing that it's in Jesse Backports makes me more confident that it does something sane, though. However the Jesse instructions don't say anything about it. Is it that you get asked questions about Nginx when you say "letsencrypt certonly"? Also strange that it doesn't even seem to require sudo to run.


You can use the --standalone option to get just the certificate files, so you can keep your nginx config files as-is however you configured them and just update the privkey.pem and fullchain.pem files wherever your nginx config points to look for them. And the --standalone option actually requires sudo but I guess that's because it puts the certs in /etc/letsencrypt~.

Caution though, the file paths you get after obtaining the certificates are actually relative symlinks for some reason so if you just copy these symlinks over they will most likely not point to the correct path so copy the original files instead.


That's how it should work but even --standalone still inspects your web server config and will refuse to run if any part of that goes wrong. For example, if you have multiple Apache VirtualHosts in the same file[1] (e.g. a port 80 redirect to the HTTPS site in the same file) any attempt to renew a certificate will fail with an error.

1. https://github.com/certbot/certbot/issues/1042


--standalone won't inspect your web server configuration. Only the apache (and nginx, if you enabled it manually) plugin would do that.


At least for renewals, it does parse Apache config — I was unpleasantly surprised by that last week


My best guess is that you have previously issued a certificate using the apache plugin on that system, and the renewal config file for that certificate is still there.

  $ echo "BreakThisConfig" > /etc/apache2/sites-enabled/000-default.conf
  $ ./certbot-auto --apache
  2016-05-16 21:33:31,252:ERROR:certbot.le_util:Error while running apache2ctl configtest.
  Action 'configtest' failed.
  The Apache error log may have more information.
  $ ./certbot-auto certonly --standalone -d example.com
  - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/example.com/fullchain.pem.
  $ ./certbot-auto renew --force-renewal
  Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/example.com/fullchain.pem (success)


You don't need --standalone to get only certificate files, by the way. You can also use certonly with --webroot and it'll work just fine. The certonly is the key part.

One thing I hope they make a little clearer is how to delegate cipher suite selection to certbot. I saw some discussion about making options-ssl-nginx.conf use, say, one of Mozilla's server-side configurations (whichever one you've configured). That way you could include options-ssl-nginx.conf and it'd auto-update over time.


So you're saying that this debian package changes your nginx files by default? Does it warn you at least? And how does that not require sudo?

In any case, thanks for the --standalone hint.


I still prefer this simple single file shell script: https://github.com/lukas2511/letsencrypt.sh


I've used this one too, can't complain, simpler setup too!


I still like https://github.com/diafygi/acme-tiny better. It's a simple python script (300 lines) and you can understand what is going on.


Previous discussion: "Announcing Certbot: EFF's Client for Let's Encrypt"

https://news.ycombinator.com/item?id=11686984


I also don't understand why this is again top in HN. The alternatives of installing certs programs in this linked article are really helpful.


For those of us on App Engine, here's a good set of instructions: http://blog.seafuj.com/lets-encrypt-on-google-app-engine


I've found the best tool for getting certs from LE is this:

https://github.com/hlandau/acme


There's something I find really off-putting about a tool that's going to be managing private keys having dependencies that point to the master branch of various third party git repositories.

It also unconditionally tries to listen on ports 80, 402, 443, 552 and 4402 whenever it completes a challenge, even if you have absolutely no intention of using any of these verification methods, so there's a lot of moving parts most of which you don't want.

I made a FreeBSD port, but thought twice about submitting it: https://github.com/Freaky/ports/tree/master/security/acmetoo...


Well, it's written in Go, so it's statically linked. Which helps with the whole master branch thing.

It is weird that it attempts to listen on all of those ports, though.


It being written in Go doesn't make "just pull the latest code from master from my dependencies at build time" a good thing. They should use vendoring and pin tagged releases.


Has anyone tried this on a site with multiple virtual hosts? That's where I ran into my largest issues with applying the certificates.


I had to apply them per-vhost when using Apache. I switched to caddy recently, which does it automatically for every vhost.


What's caddy? I had the same problem and just ended up separating all my SSL vhosts into their own files.



You're using caddy in production? Any comments on that?


It's the fastest and most stable web server I've ever used. It does crash whenever something is misconfigured, but that is usually my fault. It works wonders and never crashes unless I cause it to.


I was thinking of adding it to my home box, but I'm afraid of any vulnerabilities, since it's not very mature yet.


I've read somewhere that it won't work if there are multiple VirtualHost blocks in the same file. Allegedly if you separate each vhost config into it's own file, it will start working. YMMV.


I just tried it, seems to work fine.


I just recently re-created my personal wiki: https://wiki.jradd.com

using: https://github.com/JrCs/docker-letsencrypt-nginx-proxy-compa...

This dockerfile/repo made this incredibly easy to scale with nginx/ssl/docker.

Simply add the desired domain name as environment variable when starting your container, and letsencrypt will register your cert, and re-register it at an interval.

I haven't yet tried the other methods posted in this thread, but not sure I will want to, since this was so easy.


It occurred to me that this should probably be integrated with ansible for bringing up servers, and apparently I'm not the first to think so, I found a couple of project, and this one appears to fit the bill quite nicely:

https://github.com/thefinn93/ansible-letsencrypt

Must say I'm not a fan of web first, then fallback (I mean if stand-alone works, then just use that - because that should work for certs used for eg smtp, imaps etc)?


It's interesting OVH just notified all their webhosting customers (I assume VPS & shared hosting) they encrypted all 1.5 million account control panels via Let's Encrypt


Correct me if I'm wrong because I really hope I'm wrong. Doesn't no question asked certificates completely undermine certificates and make man in the middle attacks remarkably simple on 'secure' sites?

I played with Caddy a little and had an SSL for a domain I already have one for without even asking for one.

Is this not a problem?


You already proved that you have access to it. Why is that no question asked?

Normal DV certs are either "add a CNAME, upload a uniquely named html / txt file, or click a link in an email" -- you've already done one of those (automatically in caddy)


What questions do you feel should be asked?

Lets Encrypt asks one question without you having to deal with it - the question where you prove you own the domain by placing a file in the webroot. This is just as much proof as the email verification you get from existing strategies. Except it involves less headache, because you aren't ordering from namecheap, then getting emails from @comodossl.com that fail SPF checks asking you to click links.


What options do IIS/Windows users have?



I use this on my AWS EC2 boxes. Works great!



In production assuming you're using HTTP validation you're going to end up routing the well-known ACME URL requests over to your ACME client. If you have a load balancer in front you can handle it there and keep IIS totally out of it. But you could also handle the route in IIS and make a back-end request to the ACME process in your code.

Once the well-known URL on your domain is setup to route to the ACME client, then you probably want a command line client (I like 'lego') scripted to run periodically and check which certs need refreshing. The last step is getting to certs back into IIS and bound to the specific site, which can be done in Powershell.

Overall it's fairly straightforward but will take hours to get it fully working and it does adds a few moving parts to your setup. I'd say not enough ROI if you need less than a dozen certs.


http://certify.webprofusion.com

Certify is a Windows app which uses Let's Encrypt to provide free trusted SSL certificates for websites you control.


The Azure situation is currently a bit of a debacle. Let's Encrypt wasn't designed with particular care toward the Windows ecosystem (or PaaS providers in general), but this guy isn't helping much either.

https://github.com/sjkp/letsencrypt-siteextension


Simp_le does the same thing. I use simp_le with Haproxy on one server and nginx sni on another. Works very well.

https://github.com/kuba/simp_le


No, simp_le does not do the exact same thing. simp_le will also generate certs and get them signed, but certbot will install them in apache for you. certbot is for people who don't know or care how to install a TLS cert and just want the thing to go green


Certbot supports both use cases; "certonly" stops after getting the cert; "run" installs it if there's a plugin available for your webserver.


Has anyone used this on the FreeBSD servers offered by NearlyFreeSpeech.net? Tips?


I haven't, but there are other clients that work nearly as well. I use a modified version of letsencrypt-nosudo [1], and setup.sh should do everything you need.

[1]: https://github.com/bearbin/nfsn-le


I'd recommend openshift if you want free hosting.


I'm having problems using letsencrypt with domains with multiple dns A-records (round robin). What would be the standard way to issue certificates for a cluster?


The webserver Caddy also offers similar functionality


Eh, I wouldn't call it "similar functionality", don't get me wrong I use and quite like Caddy but that's like saying a hammer offers similar functionality to fully stocked workbench. This is a tool that only does certs, caddy does much much more.


True, although Caddy is a web server, not a TLS certificate tool.

... I've got one of those up my sleeves for next year.


This example script assumes that the server has a running webserver, either Apache or Nginx. Since it doesn't use a package install for Certbot, this script should work on most Linux distributions. It installs Certbot, obtains the certificate, and sets up the cron task for renewal.

---

  #!/bin/bash
  #
  # This sets up Let's Encrypt SSL certificates and automatic renewal
  # using certbot: https://certbot.eff.org
  #
  # - Run this script as root.
  # - A webserver must be up and running.
  #
  # Certificate files are placed into subdirectories under
  # /etc/letsencrypt/live/*.
  #
  # Configuration must then be updated for the systems using the
  # certificates.
  #
  # The certbot-auto program logs to /var/log/letsencrypt.
  #

  set -o nounset
  set -o errexit

  # May or may not have HOME set, and this drops stuff into ~/.local.
  export HOME="/root"
  export
  PATH="${PATH}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

  # No package install yet.
  wget https://dl.eff.org/certbot-auto
  chmod a+x certbot-auto
  mv certbot-auto /usr/local/bin

  # Install the dependencies.
  certbot-auto --noninteractive --os-packages-only

  # Set up config file.
  mkdir -p /etc/letsencrypt
  cat > /etc/letsencrypt/cli.ini <<EOF
  # Uncomment to use the staging/testing server - avoids rate limiting.
  # server = https://acme-staging.api.letsencrypt.org/directory

  # Use a 4096 bit RSA key instead of 2048.
  rsa-key-size = 4096

  # Set email and domains.
  email = admin@example.com
  domains = example.com, www.example.com

  # Text interface.
  text = True
  # No prompts.
  non-interactive = True
  # Suppress the Terms of Service agreement interaction.
  agree-tos = True

  # Use the webroot authenticator.
  authenticator = webroot
  webroot-path = /var/www/html
  EOF

  # Obtain cert.
  certbot-auto certonly

  # Set up daily cron job.
  CRON_SCRIPT="/etc/cron.daily/certbot-renew"

  cat > "${CRON_SCRIPT}" <<EOF
  #!/bin/bash
  #
  # Renew the Let's Encrypt certificate if it is time. It won't do anything if
  # not.
  #
  # This reads the standard /etc/letsencrypt/cli.ini.
  #

  # May or may not have HOME set, and this drops stuff into ~/.local.
  export HOME="/root"
  # PATH is never what you want it it to be in cron.
  export
  PATH="\${PATH}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

  certbot-auto --no-self-upgrade certonly

  # If the cert updated, we need to update the services using it. E.g.:
  if service --status-all | grep -Fq 'apache2'; then
     service apache2 reload
  fi
  if service --status-all | grep -Fq 'httpd'; then
     service httpd reload
  fi
  if service --status-all | grep -Fq 'nginx'; then
     service nginx reload
  fi
  EOF
  chmod a+x "${CRON_SCRIPT}"
---


A couple of suggestions based on recent (0.5.0+) Certbot features:

1. You can now do certbot certonly --post-hook "service XYZ reload" to run something if and only if certs were obtained / renewed. Or if you use the renew verb, you can use --renew-hook to get a callback for each renewed cert individually. See certbot --help renew for details.

2. You can set "quiet = True" to minimize output from the client (but see https://github.com/certbot/certbot/issues/2990)


Unless your whole chain is 4096 bit - which is unlikely - a 4096 bit RSA key just adds a little latency.


It's probably more than 'a little' latency, try:

openssl speed rsa2048 rsa4096

on your server for what is probably going to be a rude awakening. For a small, low-traffic site you might be able to manage but as traffic increases you are probably going to regret choosing 4096 bit certs unless you absolutely need them for a specific reason.


You will not get an A+[0] without 4096.

[0] https://www.ssllabs.com/ssltest/


That is not true[0]. I have no idea why you think that's the case, I've never seen that anywhere.

[0] https://www.ssllabs.com/ssltest/analyze.html?d=finn.io


In defence of davidcollantes I think it used to be the case a year ago.


How long ago? I've had an A+ with a 2048 bit cert for years (I think... there's a small chance I used to have a 4096 bit cert before LE came out)


OK it's was never required for A+, but it was required for one of the individual scores: straight from the horse's mouth: https://news.ycombinator.com/item?id=11708830


Nice script, thanks!

Will this work for multiple domains? If so, is it just a matter to add them to the "domains" variable?


For multiple domains, you have to validate each one separately via the webroot method unless they are all getting served from the same webroot.

If it is all the same webroot, then yes, add them all to the domains variable.

If different webroots you might need to use the command line, which lets you run

--w /x/y/z -d example1.com --w /a/b/c -d example2.com

in one command. I'm not sure how to make that work in the configuration file, though I'm sure there's a way.


Can this run on Raspbian 7 Apache?


Yes certbot-auto should work on Raspbian 7 but note you'll need a large swap file enabled in order for it to succeed at building the recent version of python-cryptography that it depends on:

https://github.com/certbot/certbot/issues/1081

This is resolved by .deb packages; they're available in jessie-backports, but I'm not sure if/when those will ever make it to Raspberry Pi land.


Should be able to!


[dead]


Doesn't Let's Encrypt do this themselves? I keep getting emails from them that my certs are about to expire.


Let's Encrypt does this by checking their records and determining whether a recent enough certificate was issued for your domains. They don't monitor your site to check the actual expiration dates of the certificates you use in production. This could be an issue if you run into a problem where you get a new certificate for your domains, but fail to deploy it (or something similar).


[Edit]: didn't read enough about it, sorry


> Certbot is an easy-to-use automatic client that fetches and deploys SSL/TLS certificates for your webserver.


What? It is a program that updates config files and applies for a cert. The program is a "bot"




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: