Skip to content

Commit

Permalink
Add support for Lets Encrypt contact emails
Browse files Browse the repository at this point in the history
Let's Encrypt sends certificate expiry notice emails if a contact email
is provided during account creation. Unfortunately Trellis never did
this up until now; if there was a problem with the cron renewal script,
there was no easy way to get notified.

This adds a new required `letsencrypt_contact_emails` variable which is
passed to the acme-tiny script which it passes along to Let's Encrypt.

Let's Encrypt sends emails 20 days, 10 days, and finally 1 day before
expiry. Since Trellis tries to renew certificates 30 days before renewal
(by default), these expiry notice emails should never be sent unless
something has gone wrong.
  • Loading branch information
swalkinshaw committed Jul 19, 2020
1 parent 4392be7 commit 7224811
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
### HEAD
* Add support for Lets Encrypt contact emails ([#1206](https://github.com/roots/trellis/pull/1206))
* Support branch variable for deploys ([#1204](https://github.com/roots/trellis/pull/1204))
* Removes ID from Lets Encrypt bundled certificate and make filename stable ([#834](https://github.com/roots/trellis/pull/834))
* Make Fail2ban settings extensible ([#1177](https://github.com/roots/trellis/pull/1177))
Expand Down
22 changes: 22 additions & 0 deletions roles/letsencrypt/tasks/setup.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,26 @@
---
- name: Fail if letsencrypt_contact_emails is not defined
fail:
msg: >
Error: the required `letsencrypt_contact_emails` variable is not defined.
Please define it in `groups_vars/all/main.yml` with at least one email:
letsencrypt_contact_emails:
- changeme@example.com
The contact email is used by Let's Encrypt to send expiry notices when a certificate is coming up for renewal.
See https://letsencrypt.org/docs/expiration-emails/ for more information.
Since Trellis attempts to renew certificates after {{ letsencrypt_min_renewal_age }} days ({{ 90 - letsencrypt_min_renewal_age }} days before renewal),
getting an expiry notice email means something has gone wrong giving you enough notice to fix the problem.
when: letsencrypt_contact_emails is not defined

- name: Create directories and set permissions
file:
mode: "{{ item.mode | default(omit) }}"
Expand Down
1 change: 1 addition & 0 deletions roles/letsencrypt/templates/renew-certs.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
'--ca {{ letsencrypt_ca }} '
'--account-key {{ letsencrypt_account_key }} '
'--csr {} '
'--contact {{ letsencrypt_contact_emails | map('regex_replace', '(^.*$)', 'mailto:\\1') | join (' ') }} '
'--acme-dir {{ acme_tiny_challenges_directory }}'
).format(csr_path)

Expand Down

3 comments on commit 7224811

@schuhwerk
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this new feature and the great error handling!
I'm not really sure, but doesn't this qualify as a "breaking" change (I checked the release-notes)? When I provisioned my servers (without the letsencrypt_contact_emails setting) I got a NGINX error, as the provisioning fails and does not finish. The tricky one is, that it only happens on staging/production (for me, as I don't use letsencrypt on my local machine).

@swalkinshaw
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@schuhwerk 🤔 I didn't mark it as breaking because I added validation to let people know they need to define the variable and prevent the renewal script from actually failing. However, I can see one problem I never thought about until now: it seems like on failure it should reload Nginx. Maybe that was your issue?

If that's the problem, then I apologize as I should have caught it (or at least marked it as a breaking change). Can you try and confirm that's what happened? If you run service nginx reload (or service nginx start) then I assume things would be fixed?

@schuhwerk
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@swalkinshaw Thank you for your quick reply! Sorry, this was something I did wrong. Tried it again today and the problem didn't occur. Nginx wasn't stopped and the process halted properly without causing downtime. Sorry for the false alarm!

Please sign in to comment.