13 ms·
Let's Encrypt and Nginx – State of the art secure web deployment
- feylikurds 11y agoEwwww, that renewCerts.sh is pretty crappy. Who the hell is going to check the /var/log/letsencrypt/renew.log everyday to see if renewing failed? Could not they do something nicer with systemd and email?
- pfg 11y agoThe default behaviour of cron is to email the user if a job finishes with a non-zero exit code, which seems to apply here in case of renewal failure.
- feylikurds 11y agoBut is not the default account that it would email root? I run Debian and almost never log in as root. Would all admin sudoers receive the email?
- gshulegaard 11y agohttp://www.cyberciti.biz/faq/linux-unix-crontab-change-mailto-settings/ http://www.cyberciti.biz/faq/linux-unix-crontab-change-mailt...
- feylikurds 11y agoSo the default behavior is to only email root unless crontab is edited, therefore most people would never receive an email (in case of renew failure), if they only followed the instructions given. Otherwise mail is sent to the owner of the crontab.
- avar 11y agoIf your server isn't set up to forward root's cron E-Mail to you you have bigger problems than your let's encrypt certs not renewing.
- pfg 11y agocron error reporting via email is an established solution. Why reinvent the wheel? I'd agree that a hint regarding MAILTO= in the crontab file would be neat.
- NovaS1X 11y agoA properly administered Linux system would be emailing root mail to a real email address unless monitored by another system. I've never worked in a professional environment where root mail was left unread at any point. Root aliases (excluding environments with other monitoring) are on the checklist for any basic image(server) deployment. It's a standard, well-adopted practice.
- jcrawfordor 11y agoWithout judgment intended, as a Linux sysadmin you should absolutely be monitoring mail to root. That is the standard place to deliver error output from unattended processes. You can easily /etc/alias it to something else if that's more convenient.
- toomuchtodo 11y agoSysadmin/Devops here. I send all root mail to Graylog.
- StavrosK 11y agoGraylog looks fantastic, thanks for the mention.
- toomuchtodo 11y agoYou'll love it. I'm pushing tens of thousands of messages per second into a cluster, and it works like a champ.
- nickpsecurity 11y agoThat does look nice. Thanks for Graylog reference.
- cdubzzz 11y agoGetting off-topic here, but whenever I do a new Debian build one of the items on my checklist is to edit /etc/aliases to add either my actual login user or a real email address (depending on the server setup) as an alias for root.
- a-priori 11y agoThis sounds like a job for Dead Man's Snitch. https://deadmanssnitch.com/ https://deadmanssnitch.com/
- diakritikal 11y agoJust using caddy server seems a lot simpler...
- qrv3w 11y ago+1 for Caddy. I was using NGINX a long time, and wrote some similar scripts to make certificates for my web apps. After I switched to Caddy I had a 6x smaller config file, no more ln -s, and HTTPS without every having to think about it!
- sbarre 11y agoI'd never heard of Caddy, and it looks great! Thanks for giving me something to tinker with this weekend! :-)
- tlrobinson 11y agoNeat, I like that when started with no arguments/config it just serves the files in the current directory, but then you can customize it from there. I have "alias webserver='python -m SimpleHTTPServer'" in my shell config, but I think I'll switch to Caddy.
- callahad 11y agoFor local development, consider looking into devd (https://github.com/cortesi/devd https://github.com/cortesi/devd). It's a single binary that supports things like livereload, network throttling, routing, and reverse proxying.
- StavrosK 11y agoOoh, that looks pretty nice. I was using Caddy to serve the current directory, but this seems even nicer.
- aroch 11y agoYou do need to restart Caddy in order to renew your cert, FWIW
- ivan_ah 11y agoIsn't running this as a `@daily` CRON job too much? I thought Let's Encrypt certs were good for 3 months? Why not @monthly or months 0,2,4,6,8,10 ?
- teraflop 11y agoIf something breaks, you might as well find out about it as soon as possible. That way you have the full 90 days to figure it out at your leisure, instead of 60 or 30.
- ivan_ah 11y agoRight. Also, I just saw that `letsencrypt-auto renew` will only issue new certs if < 30 days left on current cert.
- sschueller 11y agoI just use https://github.com/lukas2511/letsencrypt.sh/ https://github.com/lukas2511/letsencrypt.sh/ single bash script. Add a config.sh and setup nginx alias. Then just add domains to the domains.txt and have the script run via cron daily. Finished
- X-Istence 11y agoThis is the script I use too. I have a hook that automatically restarts nginx, which fires only if a cert has changed. Very simple. Works very well.
- emilevauge 11y agohttps://github.com/containous/traefik https://github.com/containous/traefik now has native Let's Encrypt support ;)
- ivan_ah 11y agoThe --webroot option doesn't work for my setup, so I need to shutdown nginx for 2-3 seconds and use the --standalone option. I set this as a CRON job that will run every two months. It's not elegant, but it's done. Here's the modified script using certonly and the --force-renew flag. #!/bin/bash # Force-renew the "Let's Encrypt" certificates for a given domain # Run this as root as a BI-MONTHLY cron job export DOMAINS="yourdomain.com,www.yourdomain.com" export LOGFILE="/var/log/letsencrypt/renewal_yourdomain.log" echo "Stopping nginx temporarily to renvew certificates for $DOMAINS ..." service nginx stop echo "Calling /opt/letsencrypt/letsencrypt-auto certonly --standalone --force-renew -d $DOMAINS" if ! /opt/letsencrypt/letsencrypt-auto certonly --standalone --force-renew -d $DOMAINS > $LOGFILE 2>&1 ; then echo "certonly call failed, restarting nginx" service nginx start echo "LOG info:" cat $LOGFILE # TODO: email administrator... exit 1 fi echo "certonly call succeeded, restarting nginx" service nginx start Note: don't run this as a daily cron job since this has --force-renew...
- schoen 11y agoDo you ever get problems with the socket still being in use after nginx is shut down?
- ivan_ah 11y agoNot on the N=1 times I've run the script, but will look out for this in the future.
- ran290 11y agoI'm curious: why doesn't webroot work for your setup?
- ivan_ah 11y agoA dynamic script is handling all requests, so there is no "webroot" directory where you can put stuff for them to appear under /
- schoen 11y agoIt scared me to see that the author recommended running curl http://nginx.org/keys/nginx_signing.key | sudo apt-key add - (This adds a key or keys downloaded over an unauthenticated http connection to one's Debian keyring, allowing whatever keys the network sends back to authenticate any future package updates.) I wrote to the author with a note expressing my concern.
- icebraining 11y agoUnfortunately, it seems there's no secure way to fetch the key. The nginx team recommends one checks the "web-of-trust" to check if the key is signed by others.
- rajivm 11y agoAt the least though it could be https.
- schoen 11y agoI also suggested that in the meantime the author of the article can provide a SHA256 checksum, so you can see if you get a different key than he does.
- rlpb 11y agoStick it on a keyserver, and then ask gpg to fetch it from that keyserver with the full fingerprint. Assuming that your instructions that include the fingerprint are secure (which they have to be, else the instructions could root your box anyway), then that should be reasonable. This does assume that gpg verifies that the key retrieved matches the ID requested, which I assume it does. Otherwise that'd be quite a serious bug.
- icebraining 11y agoThe question is how to ensure you're getting the right fingerprint. If you have that, you can just as easily fetch the key using HTTP and verify it.
- tbrock 11y agoLets encrypt fixes the encryption problem sure but does anyone else feel that all we really needed was really great documentation on what to do instead of an intrusive set of scripts?
- icebraining 11y agoNo, because you need the automation to make the short expiration times bearable, and having those short expiration times is more secure. Besides, the official script is just one part of the project; the others are (1) free certs and (2) a standard protocol, which you can use with other tools.
- doublerebel 11y agoYes, the API documentation is lacking especially with what we've gotten used to from Swagger markup and Stripe's API doc style. I have scoured for such an easy breakdown and found none. As a result I actually just implemented a new, clear, client for LetsEncrypt and have been documenting as I go. It's made me think we should have a Swagger or API Blueprint of the spec on github that everyone can keep up to date. What do you think?
- pfg 11y agoAre you referring to the server-side API the client is communicating with, or the internal API the client exposes? The former is documented in the ACME specification[1], currently being worked on by the IETF. There are many low-level ACME libraries for basically every language[2], and a pretty decent guide on writing your own client as well[3]. [1]: https://ietf-wg-acme.github.io/acme/ https://ietf-wg-acme.github.io/acme/ [2]: https://github.com/letsencrypt/letsencrypt/wiki/Links#libraries https://github.com/letsencrypt/letsencrypt/wiki/Links#librar... [3]: https://github.com/alexpeattie/letsencrypt-fromscratch https://github.com/alexpeattie/letsencrypt-fromscratch
- simoncion 11y agoJust gonna mention that the IETF RFC viewer [0] puts you one click away from a diff between the current and previous rev of a document [1] which can be quite handy when implementing a WIP protocol. For non-draft documents, you also get a link to the RFC's Errata page at the top of the page. [0] https://tools.ietf.org/html/draft-ietf-acme-acme-02 https://tools.ietf.org/html/draft-ietf-acme-acme-02 [1] https://tools.ietf.org/rfcdiff?url2=draft-ietf-acme-acme-02.txt https://tools.ietf.org/rfcdiff?url2=draft-ietf-acme-acme-02....
- IgorPartola 11y agoI have been happy with https://github.com/lukas2511/letsencrypt.sh https://github.com/lukas2511/letsencrypt.sh. I am trying to get it packaged for Debian/Ubuntu and either get it into Debian-proper or at least host the repo myself to make it easier to use for the common case. Since nginx reloads the cert on a SIGHUP it makes it really easy to have zero downtime renews. As for getting notified if something goes wrong I use the following in my crontab: 10 5 * * * root test -e /usr/local/bin/letsencrypt.sh && /usr/local/bin/letsencrypt.sh -c > /dev/null letsencrypt.sh outputs errors to stderr, so any errors will be sent to the root account. To get that working, do: apt-get install postfix echo 'postmaster: root' > /etc/aliases echo 'root: igor@example.com' >> /etc/aliases newaliases Problem solved.
- smithclay 11y agoRecently went through a similar setup, but used Docker and some existing h2-friendly images. Think it's a nice way forward for deploying to production environments. Wrote about the process here: https://clay.fail/posts/hip-http2-using-docker/ https://clay.fail/posts/hip-http2-using-docker/
- mikewhy 11y agoI recently built docker-gen-letsencrypt[1]. It's the same concept as what you're using, but fully automated for getting certs. [1]: https://github.com/mikew/docker-gen-letsencrypt https://github.com/mikew/docker-gen-letsencrypt
- smithclay 11y agoThat's awesome, will be updating the site to use your image this weekend. Like the support for docker-compose and the staging servers, too.
- mrits 11y agoInteresting choice of cryptos. My latest client isn't letting us use anything besides GCM right now.
- velox_io 11y agoThanks for the info on the headers, I can't believe they've issued certs for over a million domains! Here's my notes on setting up LE on IIS if anyone one is interested, it's done by using Powershell/ Package manager. //1. Install (you will get some security prompts) Install-Module -Name ACMESharp Import-Module ACMESharp Initialize-ACMEVault New-ACMERegistration -Contacts mailto:somebody@example.org -AcceptTos //2. Request the challange, this is for a website currently running on IIS. 'WebSiteRef ' refers to the name of the site within IIS New-ACMEIdentifier -Dns demo.velox.io -Alias demo Complete-ACMEChallenge demo -ChallengeType http-01 -Handler iis -HandlerParameters @{ WebSiteRef = 'Demo' } Submit-ACMEChallenge demo -ChallengeType http-01 //3. Create & download the certificate New-ACMECertificate demo -Generate -Alias demoCert Submit-ACMECertificate demoCert Update-ACMECertificate demoCert Get-ACMECertificate demoCert -ExportPkcs12 "C:\Users\USER\desktop\demoCert.pfx" You can now install this on your server.
- andersonmvd 11y agoLook at how many lines we need to secure tls connections on nginx. We need better defaults.
- jzelinskie 11y ago"State of the art" and "cron" should probably never be in the same article.
- homero 11y agoCan someone tell medium? They're still buying comodo certs for their custom domains
- iancarroll 11y agoThey probably do not want to deal with LE's rate limiting and shorter renewal periods.
- ruslo 11y ago> sed -i 's|PasswordAuthentication yes|PasswordAuthentication no|g' /etc/ssh/sshd_config Will not work if string is commented out: > grep PasswordAuthentication /etc/ssh/sshd_config # PasswordAuthentication yes > sed -i 's|PasswordAuthentication yes|PasswordAuthentication no|g' /etc/ssh/sshd_config > grep PasswordAuthentication /etc/ssh/sshd_config # PasswordAuthentication no
- sleepychu 11y agoI'm really not a fan of this domain grab to write a single article with no(t a lot of?) new information aimed at selling services from a single host. You're not the only person guilty of this but it feels quite misleading like the article is coming from a 3rd party.
- alexpeattie 11y agoYou can create a more hardened setup by using a 4096 bit RSA key: /opt/letsencrypt/letsencrypt-auto certonly --rsa-key-size 4096 --server https://acme-v01.api.letsencrypt.org/directory -a webroot --webroot-path=$DIR -d $DOMAINS ...and using the secp384r1 curve for ECDHE key exchange: # in your nginx.conf ssl_ecdh_curve secp384r1; Arguably, the real state of the art is to use an ECDSA certificate. Let's Encrypt recently started supported them, they offer a equivalent level of security to RSA at much lower bit lengths (a 384 bit ECDSA key is considered equivalent to a 7680 bit RSA key) and a few recent TLS vulnerabilities (like DROWN) have targeted implementation details of RSA.
- lorenzhs 11y ago4096 bit RSA keys offer very little additional security (2048 is plenty for at least the next few years, and with a certificate that's valid for 90 days, there's practically no risk - you can rotate the key rather easily if something bad comes along), but has a fairly big impact on performance and battery life, especially on mobile devices.
- realusername 11y agoHere is also my config if anyone is interested (also A+ on ssllabs.com): https://gist.github.com/alex-min/158f35f604b24e163ae9 https://gist.github.com/alex-min/158f35f604b24e163ae9, feel free to copy it. (or suggest improvements !) I also recommand https://sslcatch.com https://sslcatch.com which sends you a warning email if your certificate is about to expire. I have a crontab to renew it but this can be also helpful just in case.
- nickpsecurity 11y agoIt's a nice tutorial. The title tripped me out, though: a common webserver + HTTPS + free certificate on Windows/Linux is "state of the art secure web deployment?" I'd hate to see what passes for average or (shudders) ancient. In my mind, I'm seeing "state of the art" being more like a combo of Ur/Web for apps, robust implementation of OP2 web browser for client, lighttpd rewritten in Haskell, HTTPS component written in SPARK or Rust, all running on GenodeOS or CheriBSD in isolated partitions, C parts compiled with CompCert extended with Softbound + CETS, anti-fuse FPGA doing I/O offloading/mediation, and hardware done in Bluespec. That is state of the art with probably badass results. This submission is... more run of the mill. Immediately useful, though. :)