Date: Mon, 03 Apr 2017 08:30:00 +0200 From: Dave Cottlehuber <dch@skunkwerks.at> To: freebsd-questions@freebsd.org Subject: Re: letsencrypt configuration Message-ID: <1491201000.3329748.932028040.22FE70EC@webmail.messagingengine.com> In-Reply-To: <CA%2Bg%2BBvjkSifgxOG9bk6qdu2drt1oY_OhTHdOOsbkKDyJJ0oLgQ@mail.gmail.com> References: <77a1e8683e3a15cd08986d66807959b2@drenet.net> <CA%2Bg%2BBvjkSifgxOG9bk6qdu2drt1oY_OhTHdOOsbkKDyJJ0oLgQ@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
> On Sat, Apr 1, 2017 at 2:40 AM, Andre Goree <andre@drenet.net> wrote: > > So how is everyone going about configuring letsencrypt on FreeBSD? It would > > seem that multiple ports that used to exist for this very purpose are no > > longer in the repos (letskencrypt, py-letsencrypt), so tutorials I'm finding > > (and even letskencrypt, which is still in the FreeBDS wiki) aren't much > > help. I speculate that the letsencrypt trademark has been enforced https://letsencrypt.org/trademarks/ so people needed to rename their tools. I've used a few of them and settled on security/acme-client with a very simple config that is easy to manage with my config management setup. Below is a complete example, using www/h2o web server, /etc/periodic.conf to keep the script running, and security/acme-client for the heavy lifting. If there's any info missing let me know, I'll blog this later in the week. ``` # /etc/periodic.conf weekly_acme_client_enable="YES" weekly_acme_client_renewscript="/usr/local/etc/letsencrypt/example.sh" ``` ``` # /usr/local/etc/letsencrypt/example.sh #!/bin/sh -e mkdir -p /usr/local/etc/ssl/acme_client/host.example.com \ /usr/local/etc/acme_client/host.example.com \ /usr/local/etc/ssl/acme_client/private/host.example.com # add `-s` flag below to use the staging server until you have it working # remember to remove all certs and keys when you switch from staging to prod # add `-F` flag below to force renewal e.g. if you add another altName # remove /usr/local/etc/ssl/acme_client/host.example.com/cert.pem # so that the certificates are regenerated correctly /usr/local/bin/acme-client -mnN -v \ -F \ -C /usr/local/www/acme_client \ host.example.com \ altname1.example.com \ altname2.example.com \ 2>&1 | tee -a /var/log/acme.log # the public certification chain is now at: # /usr/local/etc/ssl/acme_client/host.example.com/fullchain.pem # the private certificate key is now at: # /usr/local/etc/ssl/acme_client/private/host.example.com/privkey.pem # make a combined key for haproxy and friends cat /usr/local/etc/ssl/acme_client/private/host.example.com/privkey.pem \ /usr/local/etc/ssl/acme_client/host.example.com/fullchain.pem \ > /usr/local/etc/ssl/acme_client/host.example.com/combined.pem chmod 0600 /var/log/acme.log /usr/local/etc/ssl/acme_client/host.example.com/combined.pem service h2o restart service haproxy restart ``` Obviously this needs HTTP:80 support in your web server, I use www/h2o for this: ``` # /usr/local/etc/h2o/h2o.conf # vi: ft=yaml # see https://h2o.examp1e.net/ for detailed documentation # see h2o --help for command-line options and settings user: www pid-file: /var/run/h2o.pid access-log: /var/log/h2o/h2o-access.log error-log: /var/log/h2o/h2o-error.log listen: 80 listen: port: 443 ssl: minimum-version: TLSv1.2 certificate-file: /usr/local/etc/ssl/acme/host.example.com/fullchain.pem key-file: /usr/local/etc/ssl/acme/private/host.example.com/privkey.pem cipher-preference: server cipher-suite: ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS file.dirlisting: on file.send-gzip: on http1-request-timeout: 10 http2-idle-timeout: 10 limit-request-body: 1024 max-connections: 1024 file.mime.addtypes: image/svg+xml: .svg text/plain: .log text/css: .css application/atom+xml: .xml application/zip: .zip application/json: .json "text/html; charset=utf-8": .html # host headers, global header.add: "x-frame-options: deny" header.add: "X-XSS-Protection: 1; mode=block" header.add: "X-Content-Type-Options: nosniff" header.add: "X-UA-Compatible: IE=Edge" # 1 month HSTS pinning header.add: "Strict-Transport-Security: max-age=2628000" header.add: "Cache-Control: no-transform" # per-host configuration hosts: host.example.com: paths: "/": mruby.handler: | require "htpasswd.rb" Htpasswd.new("/usr/local/etc/h2o/private/.htpasswd", "example") file.dir: "/var/www/host.example.com/" "/.well-known/acme-challenge": file.dir: "/var/www/acme" altname1.example.com: paths: "/.well-known/acme-challenge": file.dir: "/var/www/acme" "/": file.dir: "/var/www/altname1.example.com" altname2.example.com: paths: "/.well-known/acme-challenge": file.dir: "/var/www/acme" "/": file.dir: "/var/www/altname2.example.com" ``` Some notes to help you: - you *need* to have port 80 open for http requests for the acme protocol to do its verification on - you could add a 301 for anything not in /.well-known/acme-challenge/ - in h2o.conf I don't force use of HTTPS anywhere, but the use of HSTS will keep browsers that use https once, to use it in future - the same /var/www/acme dir is re-used for each virtual host - when you're getting started, use the -S flag in the script to get dummy certs from the server without using up your acme "budget" - when you have it all working, delete *all* the generated certs and scripts before switching back to normal mode (without -S) - its possible to use the return code from acme-client to decide whether to restart the daemons or not - the simplest solution for me was to restart all the daemons every week anyway - the only file that actually matters is your "account key" for each server, stored in /usr/local/etc/acme/host.example.com/privkey.pem as all the rest will be regenerated automatically on the next acme-client run - if you have multiple servers or services that share the certificate, you may need to use a reverse proxy to direct things to the appropriate place so that letsencrypt can find them A+ Dave
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1491201000.3329748.932028040.22FE70EC>