Browse Source

Support multiple domains for letsencrypt

Thomas Buck 5 years ago
parent
commit
c41cd737fd

+ 1
- 0
requirements.txt View File

@@ -1,2 +1,3 @@
1 1
 ansible>=2.2.2.0
2 2
 passlib
3
+jmespath>=0.9.4

+ 7
- 8
roles/common/DESIGN.md View File

@@ -14,14 +14,13 @@ Several packages need access to the private key. Not all are run as root. An exa
14 14
 
15 15
 Certificate renewal is done automatically using cron. The cron script must be aware of private key copies and update them as well. Services that depend on new keys must also be bounced. It is up to roles that rely on keys to modify the cron script (preferably using `lineinfile` or something similar) to accomplish this.
16 16
 
17
-### Testing support
17
+If you changed something that requires new domains or subdomains to be considered when generating the certificates, do not just delete the files in /etc/letsencrypt/live!
18
+Instead, use /root/letsencrypt/letsencrypt-auto delete to remove the old certificates and then re-run the common role in this playbook.
18 19
 
19
-An isolated VM deployed with Vagrant is used for testing. The Let's Encrypt service cannot be used to get keys for it, since it is not bound with DNS. A self-signed wildcard key is therefore used for testing. The wildcard key, certificate, and chain are installed in the same way that Let's Encrypt keys are installed.
20
+## Firewall
20 21
 
21
-### Alternative approaches
22
+ufw is used to provide a simpler iptables interface.
22 23
 
23
-Another way to generate certificates is to generate one certificate per domain and expect each module that uses a subdomain to generate its own certificate for the subdomain.
24
-
25
-This was prototyped. The common role included a parameterized task list that could be invoked by modules that needed to generate a key. The certificate renewal script run by cron could be modified to update all the certificates in the `live` directory.
26
-
27
-This approach was rejected due to complexity. This would have been the first time modules needed to invoke a task list from another module. Managing multiple certificates is also more complicated.
24
+You may run into some issues with enabling ufw. In my case, this was caused by installing
25
+updates, including a new kernel, but not rebooting before attempting to install ufw.
26
+A simple reboot fixed the problems.

+ 3
- 1
roles/common/files/etc_cron-daily_letsencrypt-renew View File

@@ -1,8 +1,10 @@
1 1
 #!/bin/bash
2
+
3
+# abort script on failed command
2 4
 set -o errexit
5
+
3 6
 # Renew all live certificates with LetsEncrypt.  This needs to run at least
4 7
 # once every three months, but recommended frequency is once a day.
5
-
6 8
 /root/letsencrypt/letsencrypt-auto renew -q -c /etc/letsencrypt/cli.conf \
7 9
 --pre-hook="find /etc/letsencrypt/prerenew/ -maxdepth 1 -type f -executable -exec {} \;" \
8 10
 --post-hook="find /etc/letsencrypt/postrenew/ -maxdepth 1 -type f -executable -exec {} \;"

+ 28
- 4
roles/common/files/letsencrypt-gencert View File

@@ -1,10 +1,34 @@
1 1
 #!/bin/bash
2
-d="$1"
3
-for i in www mail autoconfig read news cloud; do
4
-  if (getent hosts $i.$1 > /dev/null); then
5
-    d="$d,$i.$1";
2
+
3
+# Call script like this:
4
+# letsencrypt-gencert foo.com bar.com baz.com
5
+
6
+# Build list of domains and subdomains we need a certificate for
7
+d=""
8
+for domain in "$@"; do
9
+  # domain itself - foo.com
10
+  # only add if the DNS entry for the domain does actually exist
11
+  if (getent hosts $domain > /dev/null); then
12
+    if [ -z "$d" ]; then
13
+      d="$domain";
14
+    else
15
+      d="$d,$domain";
16
+    fi
6 17
   fi
18
+
19
+  # subdomains - www.foo.com mail.foo.com ...
20
+  for sub in www mail autoconfig news cloud git; do
21
+    # only add if the DNS entry for the subdomain does actually exist
22
+    if (getent hosts $sub.$domain > /dev/null); then
23
+      if [ -z "$d" ]; then
24
+        d="$sub.$domain";
25
+      else
26
+        d="$d,$sub.$domain";
27
+      fi
28
+    fi
29
+  done
7 30
 done
31
+
8 32
 # We are using the "standalone" letsencrypt plugin, which runs its own
9 33
 # webserver, so we need to temporarily free up the HTTP(S) ports by stopping
10 34
 # our own Apache.

+ 2
- 2
roles/common/tasks/letsencrypt.yml View File

@@ -57,8 +57,8 @@
57 57
 - name: Create live directory for LetsEncrypt cron job
58 58
   file: state=directory path=/etc/letsencrypt/live group=root owner=root
59 59
 
60
-- name: Get an SSL certificate for {{ domain }} from Let's Encrypt
61
-  script: letsencrypt-gencert {{ domain }} creates=/etc/letsencrypt/live/{{ domain }}/privkey.pem
60
+- name: Get an SSL certificate for {{ virtual_domains | json_query('[*].name') | join(' ') }} from Let's Encrypt
61
+  script: letsencrypt-gencert {{ virtual_domains | json_query('[*].name') | join(' ') }} creates=/etc/letsencrypt/live/{{ domain }}/privkey.pem
62 62
 
63 63
 - name: Modify permissions to allow ssl-cert group access
64 64
   file: path=/etc/letsencrypt/archive owner=root group=ssl-cert mode=0750

Loading…
Cancel
Save