Browse Source

Merge pull request #504 from mikeashley/letsencrypt

Let's Encrypt support
Allen Riddell 8 years ago
parent
commit
b92b8841ea

+ 25
- 43
README.md View File

@@ -54,37 +54,15 @@ What You’ll Need
54 54
 
55 55
 1.  A VPS (or bare-metal server if you wanna ball hard). My VPS is hosted at [Linode](http://www.linode.com/?r=45405878277aa04ee1f1d21394285da6b43f963b). You’ll probably want at least 512 MB of RAM between Apache, Solr, and PostgreSQL. Mine has 1024.
56 56
 2.  [64-bit Debian 7](http://www.debian.org/) or an equivalent Linux distribution. (You can use whatever distro you want, but deviating from Debian will require more tweaks to the playbooks. See Ansible’s different [packaging](http://docs.ansible.com/ansible/list_of_packaging_modules.html) modules.)
57
-3.  A wildcard SSL certificate. You can either buy one or self-sign if you want to save money.
58
-4.  A [Tarsnap](http://www.tarsnap.com) account with some credit in it. You could comment this out if you want to use a different backup service. Consider paying your hosting provider for backups or using an additional backup service for redundancy.
57
+3.  A [Tarsnap](http://www.tarsnap.com) account with some credit in it. You could comment this out if you want to use a different backup service. Consider paying your hosting provider for backups or using an additional backup service for redundancy.
59 58
 
60
-Installation
61
-------------
62
-
63
-### 1. Get a wildcard SSL certificate
64
-
65
-Generate a private key and a certificate signing request (CSR):
66
-
67
-    openssl req -nodes -newkey rsa:2048 -keyout roles/common/files/wildcard_private.key -sha256 -out mycert.csr
68
-
69
-Purchase a wildcard cert from a certificate authority, such as [Positive SSL](https://positivessl.com) or [AlphaSSL](https://www.alphassl.com). You will provide them with the contents of your CSR, and in return they will give you your signed public certificate. Place the certificate in `roles/common/files/wildcard_public_cert.crt`.
70
-
71
-Download your certificate authority’s combined cert to `roles/common/files/wildcard_ca.pem`. You can also download the intermediate and root certificates separately and concatenate them together in that order.
72
-
73
-Lastly, test your certificate:
74
-
75
-    openssl verify -verbose -CAfile roles/common/files/wildcard_ca.pem roles/common/files/wildcard_public_cert.crt
76
-
77
-#### Self-signed SSL certificate
59
+You do not need to acquire an SSL certificate.  The SSL certificates you need will be obtained from [Let's Encrypt](https://letsencrypt.org/) automatically when you deploy your server.
78 60
 
79
-Purchasing SSL certs, and wildcard certs specifically, can be a significant financial burden. It is possible to generate a self-signed SSL certificate (i.e. one that isn’t signed by a Certificate Authority) that is free of charge by nature. However, since a self-signed cert has no CA chain that can confirm its authenticity, some services might behave erratically when using such a certificate.
80 61
 
81
-To create a self-signed SSL cert, run the following commands:
82
-
83
-    openssl req -nodes -newkey rsa:2048 -keyout roles/common/files/wildcard_private.key -sha256 -out mycert.csr
84
-    openssl x509 -req -days 365 -in mycert.csr -signkey roles/common/files/wildcard_private.key -out roles/common/files/wildcard_public_cert.crt
85
-    cp roles/common/files/wildcard_public_cert.crt roles/common/files/wildcard_ca.pem
62
+Installation
63
+------------
86 64
 
87
-### 2. Get a Tarsnap machine key
65
+### 1. Get a Tarsnap machine key
88 66
 
89 67
 If you haven’t already, [download and install Tarsnap](https://www.tarsnap.com/download.html), or use `brew install tarsnap` if you use [Homebrew](http://brew.sh).
90 68
 
@@ -92,7 +70,7 @@ Create a new machine key for your server:
92 70
 
93 71
     tarsnap-keygen --keyfile roles/tarsnap/files/decrypted_tarsnap.key --user me@example.com --machine example.com
94 72
 
95
-### 3. Prep the server
73
+### 2. Prep the server
96 74
 
97 75
 For goodness sake, change the root password:
98 76
 
@@ -115,7 +93,7 @@ Authorize your ssh key if you want passwordless ssh login (optional):
115 93
 
116 94
 Your new account will be automatically set up for passwordless `sudo`.
117 95
 
118
-### 4. Configure your installation
96
+### 3. Configure your installation
119 97
 
120 98
 Modify the settings in `vars/user.yml` to your liking. If you want to see how they’re used in context, just search for the corresponding string.
121 99
 
@@ -167,6 +145,22 @@ For Git hosting, copy your public key into place:
167 145
 
168 146
 Finally, replace the TODOs in the file `hosts`. If your SSH daemon listens on a non-standard port, add a colon and the port number after the IP address. In that case you also need to add your custom port to the task `Set firewall rules for web traffic and SSH` in the file `roles/common/tasks/ufw.yml`.
169 147
 
148
+### 4. Set up DNS
149
+
150
+If you’ve just bought a new domain name, point it at [Linode’s DNS Manager](https://library.linode.com/dns-manager) or similar. Most VPS services (and even some domain registrars) offer a managed DNS service that you can use for this at no charge. If you’re using an existing domain that’s already managed elsewhere, you can probably just modify a few records.
151
+
152
+Create `A` or `CNAME` records which point to your server's IP address:
153
+
154
+* `example.com`
155
+* `mail.example.com`
156
+* `autoconfig.example.com` (for email client automatic configuration)
157
+* `read.example.com` (for Wallabag)
158
+* `news.example.com` (for Selfoss)
159
+* `cloud.example.com` (for ownCloud)
160
+* `git.example.com` (for cgit)
161
+
162
+Verify that the `subdomains` variable in `vars/user.yml` matches the list of subdomains you have just set up.
163
+
170 164
 ### 5. Run the Ansible Playbooks
171 165
 
172 166
 First, make sure you’ve [got Ansible 1.6+ installed](http://docs.ansible.com/intro_installation.html#getting-ansible).
@@ -183,21 +177,9 @@ You might find that it fails at one point or another. This is probably because s
183 177
 
184 178
 The `dependencies` tag just installs dependencies, performing no other operations. The tasks associated with the `dependencies` tag do not rely on the user-provided settings that live in `vars/user.yml`. Running the playbook with the `dependencies` tag is particularly convenient for working with Docker images.
185 179
 
186
-### 6. Set up DNS
187
-
188
-If you’ve just bought a new domain name, point it at [Linode’s DNS Manager](https://library.linode.com/dns-manager) or similar. Most VPS services (and even some domain registrars) offer a managed DNS service that you can use for this at no charge. If you’re using an existing domain that’s already managed elsewhere, you can probably just modify a few records.
189
-
190
-Create `A` records which point to your server's IP address:
191
-
192
-* `example.com`
193
-* `mail.example.com`
194
-* `autoconfig.example.com` (for email client automatic configuration)
195
-* `read.example.com` (for Wallabag)
196
-* `news.example.com` (for Selfoss)
197
-* `cloud.example.com` (for ownCloud)
198
-* `git.example.com` (for cgit)
180
+### 6. Finish DNS set-up
199 181
 
200
-Create a `MX` record for `example.com` which assigns `mail.example.com` as the domain’s mail server.
182
+Create an `MX` record for `example.com` which assigns `mail.example.com` as the domain’s mail server.
201 183
 
202 184
 To ensure your emails pass DKIM checks you need to add a `txt` record. The name field will be `default._domainkey.EXAMPLE.COM.` The value field contains the public key used by OpenDKIM. The exact value needed can be found in the file `/etc/opendkim/keys/EXAMPLE.COM/default.txt` it’ll look something like this:
203 185
 

+ 29
- 0
roles/common/DESIGN.md View File

@@ -0,0 +1,29 @@
1
+# Design Description for Common Role
2
+
3
+## Let's Encrypt Support
4
+
5
+[Let's Encrypt](https://letsencrypt.org) (LE) is an automated certificate authority that provides free SSL certificates that are trusted by all major browsers.  LE certificates are used by Sovereign instead of purchased certificates from authorities like RapidSSL in order to reduce the out-of-pocket cost of deploying Sovereign and avoid end-user problems with self-signed certificates.
6
+
7
+### Design approach
8
+
9
+The Let's Encrypt service uses DNS to look up domains being registered and then contact the client to verify. For this to work, DNS records must be configured before the playbook is run the first time.
10
+
11
+A single certificate is created using Let's Encrypt with SANs used for the subdomains.  At deploy-time, a script is used to query DNS for known subdomains, build a list of the subset that is registered, and use it when making the certificate request of Let's Encrypt.
12
+
13
+Several packages need access to the private key. Not all are run as root. An example is Prosody (XMPP). Such users are added to the ssl-cert group, and /etc/letsencrypt is set up to allow keys to be read by ssl-cert.
14
+
15
+Certificates and private keys are backed up using tarsnap.
16
+
17
+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.
18
+
19
+### Testing support
20
+
21
+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.
22
+
23
+### Alternative approaches
24
+
25
+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.
26
+
27
+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.
28
+
29
+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.

+ 21
- 0
roles/common/files/etc_cron-monthly_letsencrypt-renew View File

@@ -0,0 +1,21 @@
1
+#!/bin/bash
2
+# Renew all live certificates with LetsEncrypt.  This needs to run at least
3
+# once every three months.
4
+
5
+# Given a certificate file returns "domain1,domain2"
6
+# https://community.letsencrypt.org/t/help-me-understand-renewal-config/7115
7
+function getDomains() {
8
+        openssl x509 -text -in "$1" |
9
+        grep -A1 "Subject Alternative Name:" | tail -n1 |
10
+        tr -d ' ' | tr -d 'DNS:'
11
+}
12
+
13
+service apache2 stop
14
+for c in `ls /etc/letsencrypt/live`; do
15
+  domains=$(getDomains /etc/letsencrypt/live/$c/cert.pem)
16
+  /root/letsencrypt/letsencrypt-auto --renew certonly -c /etc/letsencrypt/cli.conf --domains=$domains
17
+done
18
+service apache2 start
19
+
20
+# Services that rely on LE certificates will need restarted.
21
+

+ 8
- 0
roles/common/files/letsencrypt-gencert View File

@@ -0,0 +1,8 @@
1
+#!/bin/bash
2
+d="$1"
3
+for i in www mail autoconfig read news cloud git; do
4
+  if (getent hosts $i.$1 > /dev/null); then
5
+    d="$d,$i.$1";
6
+  fi
7
+done
8
+/root/letsencrypt/letsencrypt-auto certonly -c /etc/letsencrypt/cli.conf --domains $d

+ 18
- 18
roles/common/files/wildcard_ca.pem View File

@@ -1,20 +1,20 @@
1 1
 -----BEGIN CERTIFICATE-----
2
-MIIDPjCCAiYCCQDcHVzv6JwhEzANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQGEwJB
3
-VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
4
-cyBQdHkgTHRkMRowGAYDVQQDFBEqLnNvdmVyZWlnbi5sb2NhbDAeFw0xMzExMDIx
5
-OTI4NDlaFw0xNDExMDIxOTI4NDlaMGExCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpT
6
-b21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxGjAY
7
-BgNVBAMUESouc292ZXJlaWduLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
8
-MIIBCgKCAQEArpXru3ZQKl+OVlBar2yziN5ZiVSbt6QYuJtTUmMAfAtGsPobueyI
9
-6XLG6QcFNCWNqUd3fa15GPYluFA5Ot7bPAoo3UQXJvM9n/tQ2YWPjPgxaV4sCKrI
10
-yw7UF+f2NwtUVdj1wHB0x7bh9asNv+ZDC5O2ze8dn09CS7Puh13bsVFm1iapngrr
11
-C6ctethJF67A/mRa7UzqHzesAznkgaWfhDLyygNX0PzI5ywVAKbgvxUWndPx3oY6
12
-yx5jrfk+opMUUnDu9AqhthTPaKK1s3JXJBOW2R/rlgYokfO7VBDkRv/ty3B1BnmS
13
-xdOV/01f5JJdgfLlR6PNd2FMmMoCesg9YwIDAQABMA0GCSqGSIb3DQEBBQUAA4IB
14
-AQAX5KZYIYcMuHRdsd/EKwee+pzp0irs1dqbNwYJIj3HS8Zx/qd+LET4irQbY72N
15
-9Z2s0UTSngy4axlyItKrn+k26FUnSW80W8GMb/dEIyKg5Vnu+zLKnKj85dGUBSAP
16
-AzhNyqkwiY5BFFy/tvuFBvjxle9vkBNZrmtsh/PktzaW3BNrYaE9xDMYesT9xi73
17
-aKFMIryVZWzZKmMaJhcMcMarWzAvLftV+0VfJV3EWtzpEbjEu3mIsoBZvD0uGqbU
18
-Llt1yeYyBrcdIbDQZgeRHhrJjC8yx0iqvj5WmnEp8hk6YtqdwGGTJxkpUtxFT/dO
19
-+0vEpa88MmGGUdXZ4NWI2IYe
2
+MIIDPjCCAiYCCQCIBIL0qFYY5DANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJB
3
+VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
4
+cyBQdHkgTHRkMRowGAYDVQQDDBEqLnNvdmVyZWlnbi5sb2NhbDAeFw0xNjAxMDkw
5
+OTU4MzNaFw0xNzAxMDgwOTU4MzNaMGExCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApT
6
+b21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxGjAY
7
+BgNVBAMMESouc292ZXJlaWduLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
8
+MIIBCgKCAQEA1Z12KXbGOq70H9rxgH+uBF2MSil5xTcxQKFpUhFOu0kIVoQ7Sa2n
9
+FPKYDC5aTKE7ajgO4cER44WgtBnEXGs7MHQEJL2tT0ETiDfTqSEhTpsXSzCxl7bo
10
+AZIrw9ntJKvTm4Ot04MXsUqeZyr6gk5XMOilluZWTLzbunigKOJItyM3VBRnLWZi
11
+ScznIkbKLGt2WjGIaENOR4cw+wwzOmH0UVxGtGWo/jklGtBZG8mb+fF8rH6L6VBa
12
+nIYHBGlg8Gy0eK430jMD/y2zqlOzY4gE5/BlwaxEupuzL+jtiYGyr7G1tUksQ49v
13
+UNimlAzUINB6bYnIk0MwpIxB0xECj0nz2wIDAQABMA0GCSqGSIb3DQEBCwUAA4IB
14
+AQCEVVrT1ktgvA3CwuIr+/BWRfILIHyayy3FxIwF8wBymAwQiT/09JuNDsLuI2/t
15
+eOY9BZsaJ9BtGA7dajbwKDX83Z+WXcv2AwxbAhxUnpBCQF0MNT9Vh7ixE0rXbXeg
16
+bvy5D4n1MWTBaPK+MpuEEV5m/dRZOFIgf6AWDCB7QixWm7N2BGjqni5kr2EuqYw8
17
+JqxXXtTDTBA8BKMLxPRER+w39zD8fQouTn1pI8nVba/WdX1NlchzFrex6ByvKWQG
18
+joSPd39d68NNyytwmv5LWOQ2Shsk0d0UV9eoFrctPJh8cL4BPfNS7NQR12u55zn0
19
+NR+SN5v9/7fn+/KF1UZq5Jao
20 20
 -----END CERTIFICATE-----

+ 28
- 27
roles/common/files/wildcard_private.key View File

@@ -1,27 +1,28 @@
1
------BEGIN RSA PRIVATE KEY-----
2
-MIIEpAIBAAKCAQEArpXru3ZQKl+OVlBar2yziN5ZiVSbt6QYuJtTUmMAfAtGsPob
3
-ueyI6XLG6QcFNCWNqUd3fa15GPYluFA5Ot7bPAoo3UQXJvM9n/tQ2YWPjPgxaV4s
4
-CKrIyw7UF+f2NwtUVdj1wHB0x7bh9asNv+ZDC5O2ze8dn09CS7Puh13bsVFm1iap
5
-ngrrC6ctethJF67A/mRa7UzqHzesAznkgaWfhDLyygNX0PzI5ywVAKbgvxUWndPx
6
-3oY6yx5jrfk+opMUUnDu9AqhthTPaKK1s3JXJBOW2R/rlgYokfO7VBDkRv/ty3B1
7
-BnmSxdOV/01f5JJdgfLlR6PNd2FMmMoCesg9YwIDAQABAoIBADm/oYAavJ2nif+H
8
-CNgqDqDhW6CPegqenwbBaihAUzK00CdOM8mmMgt2SdFe3xvGqDssRpwtu3bEROnY
9
-r3WHreEIQ0gdc8MQhnvat32cLkWk+0MtQUeEpnJ0bzeRJOJEPxs+btu+1wIQvmFy
10
-uVOWqOq1a6xmwdemcfl0hRwFsdvO00MefOWgJpmBGBTBKuvhg1rUPP8xkHlD98ga
11
-+vpxG0vS5d2vHKa5FxcbbMaV9kxqjsc1Sm79zWlomwdmE5u0dUIIfNV1+VOmPqW2
12
-tjeD+JDieyX3uOKFpRTk7/5rOJd5hzHukIeUpl0n9mC/mY8lvoFAttszeTEwjkv0
13
-EhRBjaECgYEA3Rz8AoWJLDC63wfz3mUhtXzFxrxok85cNT35ohT9btnKyLKykvAE
14
-BCfHeYg8cwFFv0oUXpK9HWOqoJhsYN79+WYA1QE9n0XXAGl1K1/FlKsoAH3h5GAf
15
-CHGLsq6rEY3ixBmqEiKCWjNXgKeoMg9V/gjTNudWYqLvcsgMoD9vJbkCgYEAyiGi
16
-QZUa7pGFSa3+kPJo9wx6FylsAVnBluQETZpPdXSB43cTnfUlGj50OHAwFKwD4MP1
17
-Z+3mTW3+iedpEo3BWs47onanI9DSe6XcUUMXreP+aStJYOkQ3Sl5wr5A61NFF/yr
18
-+bdKEzXNXB5My5hbFLuSUtsXNVmVr6B7pz2wyfsCgYEAiXKyCVM/IPQtxeSoqM+O
19
-88VbIB4QmAjIcuRSoHmRzO2fy8ChlwuSQ48Cxb51bTwWQkHnhZ6L5pAFCg2WGWWk
20
-1Pqee8popvCAJSZpCoxfQvpeRGf8Gr3RrKsAnxNLDf94PlSBzwIaq72MoFIYEP5N
21
-gzuzKEcIAQqt9Fj82ER2cCkCgYEAnaEFC+ffjNRnAUJzF04zlRVh0NY4qAT691Ty
22
-FiKUfKBS+rRN1Azs1j6GG81BcZ2DmLC4nEfmJdP1gE26nwF1G/9geh3V0hRzUIHU
23
-Ansz6CO4rwNWwgB/ajmB/uCnd90EMOSWqLLLTZfTglcOxGcYAF8WiQ7aVnx6Qu//
24
-/jgZuikCgYB10Gf8Wl/TcWVBTwbDbA50VqZpUWXkcF+oo/w4FfI2f74TEQVkIs9m
25
-4SVhrtSAz3z2tuBEDB8SM2Uwe00/JSrbuOTvGcVTq64LDgH5fL38Hw8+7IvAZEOx
26
-26mAS685K1pq0HvvCuwzSIAjpo55tso3phG/YxC+DD11DglhL1SpBA==
27
------END RSA PRIVATE KEY-----
1
+-----BEGIN PRIVATE KEY-----
2
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDVnXYpdsY6rvQf
3
+2vGAf64EXYxKKXnFNzFAoWlSEU67SQhWhDtJracU8pgMLlpMoTtqOA7hwRHjhaC0
4
+GcRcazswdAQkva1PQROIN9OpISFOmxdLMLGXtugBkivD2e0kq9Obg63TgxexSp5n
5
+KvqCTlcw6KWW5lZMvNu6eKAo4ki3IzdUFGctZmJJzOciRsosa3ZaMYhoQ05HhzD7
6
+DDM6YfRRXEa0Zaj+OSUa0FkbyZv58XysfovpUFqchgcEaWDwbLR4rjfSMwP/LbOq
7
+U7NjiATn8GXBrES6m7Mv6O2JgbKvsbW1SSxDj29Q2KaUDNQg0HpticiTQzCkjEHT
8
+EQKPSfPbAgMBAAECggEBAMcozbgO4vZnk3f3u13grK+pQFkMnll/Ac6OLxGyzULT
9
+7pArLNOesb5YB+ajeNElKa34ofdc+H62YYRI2ciIuWCNaiePKHxR4hIIarCvEMym
10
+0Grr9UfL4jdEvsUU84JTKTE+7dvbx0UmmtT5PyIqRCR3Y5tzGVbmZb5PJJO5la4X
11
+1Q8ZQHYvdFh52VXVpetp66yFpCu/EI8u9VSEBakvILpZ3yxjhskEXD18E304wn1e
12
+Ky+sBde6zUtXRc1rKxAzeQ/JyF1+1+xr8nI1kGryqXdNl/4S3JsdB5nL54U0pHaL
13
+XfLMZvRTVqKAsyjqLQzYE0bRnJz9sev85nu0J1sp/GECgYEA8Gi2izJmxpb3oDC7
14
+Eu388TeFOYrdg6AsXFkmKT5ssTRRT4ju03RrGWC8NlOJRhQxJloCICgmBWHLFWBG
15
+2OVGgOYhUr7/V12f/D2GICUcJ9SKkDbzKe0ACDPq9tzauVd9H8fY9gQfvhn0AA0v
16
+qG0+guGElxS+holIpbDP7VV0PykCgYEA43fp3VtneBHL4E4iZVBQaIBGMYOmE8v3
17
+cKSTCBgCU3jnbio85NHybI1Fw15cAXDOIsOlKescLyTw/IgRb3PbObNvpD8STS8d
18
+wVqen2Ir/mrsxWVn57jlSV5viGnIoI873YVJ9fl5pr/KbJ5A8//EnJwQLDq6MmQR
19
+zPMovp51L2MCgYEA0/rQ8t4HR5Z4VDSDz8YvYZaeD0YF2nkShH9LKdTUTFAgXiwU
20
+wjkF8oOckZ6JDVTinbmB5E7ib55yTq/s6HUJ/MBuo6KsTaHNXsH1EUUHlYtQfqcl
21
+NFO40oLM7M2CwyiEuNAj25F5V8tUnfMCkdV56DfoDLuK3+APQaItRU0zSjkCgYAW
22
+KGgvl+fMWm9xuiq/k8NBar1rtVdINmY0ItPvxeb0GqLwqEymPY1P5bMWBOsReNub
23
+p1M/checwAx5jQelw7NnO4N0jHBL9HsBisJI5FdEwUWvNOGaQPiU3Q4gS62vdkRu
24
+n71EqLig9a3SRtgs7I1KdClfJZldr0HMpSMi7myb4QKBgQDgeh5oDgypNBdMY4un
25
+Wpax1Mxse49T883Z3lIlVq+U7ZwnWLWfohSZK/kXUrolbdmo4z8yAlNKUO421sAF
26
+SWUWFAabEMnLq2ilv6WIG4i1ubFr4/DBV4fGcaYNMOxIENRDItn7RacddZ1EQVfC
27
+WBcstgic1QXyMJ+2LoC0LHdgCQ==
28
+-----END PRIVATE KEY-----

+ 18
- 18
roles/common/files/wildcard_public_cert.crt View File

@@ -1,20 +1,20 @@
1 1
 -----BEGIN CERTIFICATE-----
2
-MIIDPjCCAiYCCQDcHVzv6JwhEzANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQGEwJB
3
-VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
4
-cyBQdHkgTHRkMRowGAYDVQQDFBEqLnNvdmVyZWlnbi5sb2NhbDAeFw0xMzExMDIx
5
-OTI4NDlaFw0xNDExMDIxOTI4NDlaMGExCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpT
6
-b21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxGjAY
7
-BgNVBAMUESouc292ZXJlaWduLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
8
-MIIBCgKCAQEArpXru3ZQKl+OVlBar2yziN5ZiVSbt6QYuJtTUmMAfAtGsPobueyI
9
-6XLG6QcFNCWNqUd3fa15GPYluFA5Ot7bPAoo3UQXJvM9n/tQ2YWPjPgxaV4sCKrI
10
-yw7UF+f2NwtUVdj1wHB0x7bh9asNv+ZDC5O2ze8dn09CS7Puh13bsVFm1iapngrr
11
-C6ctethJF67A/mRa7UzqHzesAznkgaWfhDLyygNX0PzI5ywVAKbgvxUWndPx3oY6
12
-yx5jrfk+opMUUnDu9AqhthTPaKK1s3JXJBOW2R/rlgYokfO7VBDkRv/ty3B1BnmS
13
-xdOV/01f5JJdgfLlR6PNd2FMmMoCesg9YwIDAQABMA0GCSqGSIb3DQEBBQUAA4IB
14
-AQAX5KZYIYcMuHRdsd/EKwee+pzp0irs1dqbNwYJIj3HS8Zx/qd+LET4irQbY72N
15
-9Z2s0UTSngy4axlyItKrn+k26FUnSW80W8GMb/dEIyKg5Vnu+zLKnKj85dGUBSAP
16
-AzhNyqkwiY5BFFy/tvuFBvjxle9vkBNZrmtsh/PktzaW3BNrYaE9xDMYesT9xi73
17
-aKFMIryVZWzZKmMaJhcMcMarWzAvLftV+0VfJV3EWtzpEbjEu3mIsoBZvD0uGqbU
18
-Llt1yeYyBrcdIbDQZgeRHhrJjC8yx0iqvj5WmnEp8hk6YtqdwGGTJxkpUtxFT/dO
19
-+0vEpa88MmGGUdXZ4NWI2IYe
2
+MIIDPjCCAiYCCQCIBIL0qFYY5DANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJB
3
+VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
4
+cyBQdHkgTHRkMRowGAYDVQQDDBEqLnNvdmVyZWlnbi5sb2NhbDAeFw0xNjAxMDkw
5
+OTU4MzNaFw0xNzAxMDgwOTU4MzNaMGExCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApT
6
+b21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxGjAY
7
+BgNVBAMMESouc292ZXJlaWduLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
8
+MIIBCgKCAQEA1Z12KXbGOq70H9rxgH+uBF2MSil5xTcxQKFpUhFOu0kIVoQ7Sa2n
9
+FPKYDC5aTKE7ajgO4cER44WgtBnEXGs7MHQEJL2tT0ETiDfTqSEhTpsXSzCxl7bo
10
+AZIrw9ntJKvTm4Ot04MXsUqeZyr6gk5XMOilluZWTLzbunigKOJItyM3VBRnLWZi
11
+ScznIkbKLGt2WjGIaENOR4cw+wwzOmH0UVxGtGWo/jklGtBZG8mb+fF8rH6L6VBa
12
+nIYHBGlg8Gy0eK430jMD/y2zqlOzY4gE5/BlwaxEupuzL+jtiYGyr7G1tUksQ49v
13
+UNimlAzUINB6bYnIk0MwpIxB0xECj0nz2wIDAQABMA0GCSqGSIb3DQEBCwUAA4IB
14
+AQCEVVrT1ktgvA3CwuIr+/BWRfILIHyayy3FxIwF8wBymAwQiT/09JuNDsLuI2/t
15
+eOY9BZsaJ9BtGA7dajbwKDX83Z+WXcv2AwxbAhxUnpBCQF0MNT9Vh7ixE0rXbXeg
16
+bvy5D4n1MWTBaPK+MpuEEV5m/dRZOFIgf6AWDCB7QixWm7N2BGjqni5kr2EuqYw8
17
+JqxXXtTDTBA8BKMLxPRER+w39zD8fQouTn1pI8nVba/WdX1NlchzFrex6ByvKWQG
18
+joSPd39d68NNyytwmv5LWOQ2Shsk0d0UV9eoFrctPJh8cL4BPfNS7NQR12u55zn0
19
+NR+SN5v9/7fn+/KF1UZq5Jao
20 20
 -----END CERTIFICATE-----

+ 88
- 0
roles/common/tasks/letsencrypt.yml View File

@@ -0,0 +1,88 @@
1
+- name: Download LetsEncrypt release
2
+  git: repo=https://github.com/letsencrypt/letsencrypt
3
+       dest=/root/letsencrypt
4
+       version=master
5
+       force=yes
6
+
7
+- name: Create directory for LetsEncrypt configuration and certificates
8
+  file: state=directory path=/etc/letsencrypt group=root owner=root
9
+
10
+- name: Configure LetsEncrypt
11
+  template:
12
+    src=etc_letsencrypt_cli.conf.j2
13
+    dest=/etc/letsencrypt/cli.conf
14
+    owner=root
15
+    group=root
16
+
17
+- name: Install LetsEncrypt package dependencies
18
+  command: /root/letsencrypt/letsencrypt-auto --help
19
+
20
+- name: Install crontab entry for LetsEncrypt
21
+  copy:
22
+    src=etc_cron-monthly_letsencrypt-renew
23
+    dest=/etc/cron.monthly/letsencrypt-renew
24
+    owner=root
25
+    group=root
26
+    mode=755
27
+
28
+- name: Create live directory for LetsEncrypt cron job
29
+  file: state=directory path=/etc/letsencrypt/live group=root owner=root
30
+
31
+- name: Stop Apache
32
+  service: name=apache2 state=stopped
33
+
34
+- name: Get an SSL certificate for {{ domain }} from Let's Encrypt
35
+  script: letsencrypt-gencert {{ domain }}
36
+  args:
37
+    creates: /etc/letsencrypt/live/{{ domain }}/privkey.pem
38
+  when: ansible_ssh_user != "vagrant"
39
+
40
+- name: Modify permissions to allow ssl-cert group access
41
+  file: path=/etc/letsencrypt/archive owner=root group=ssl-cert mode=750
42
+  when: ansible_ssh_user != "vagrant"
43
+
44
+### Several steps to install a self-signed wildcard key to support offline testing
45
+
46
+- name: Create live directory for testing keys
47
+  file: dest=/etc/letsencrypt/live/{{ domain }} state=directory
48
+    owner=root group=root mode=755
49
+  when: ansible_ssh_user == "vagrant"
50
+
51
+- name: Copy SSL wildcard private key for testing
52
+  copy: src=wildcard_private.key
53
+    dest=/etc/letsencrypt/live/{{ domain }}/privkey.pem
54
+    owner=root group=ssl-cert mode=640
55
+  when: ansible_ssh_user == "vagrant"
56
+
57
+- name: Copy SSL public certificate into place for testing
58
+  copy: src=wildcard_public_cert.crt
59
+    dest=/etc/letsencrypt/live/{{ domain }}/cert.pem
60
+    group=root owner=root mode=644
61
+  register: certificate
62
+  notify: restart apache
63
+  when: ansible_ssh_user == "vagrant"
64
+
65
+- name: Copy SSL CA combined certificate into place for testing
66
+  copy: src=wildcard_ca.pem
67
+    dest=/etc/letsencrypt/live/{{ domain }}/chain.pem
68
+    group=root owner=root mode=644
69
+  register: ca_certificate
70
+  notify: restart apache
71
+  when: ansible_ssh_user == "vagrant"
72
+
73
+- name: Create a combined SSL cert for testing
74
+  shell: cat /etc/letsencrypt/live/{{ domain }}/cert.pem
75
+    /etc/letsencrypt/live/{{ domain }}/chain.pem >
76
+    /etc/letsencrypt/live/{{ domain }}/fullchain.pem
77
+  when: private_key.changed or certificate.changed or ca_certificate.changed
78
+  when: ansible_ssh_user == "vagrant"
79
+
80
+- name: Set permissions on combined SSL public cert
81
+  file: name=/etc/letsencrypt/live/{{ domain }}/fullchain.pem mode=644
82
+  notify: restart apache
83
+  when: ansible_ssh_user == "vagrant"
84
+
85
+### Back to normal
86
+
87
+- name: Start Apache
88
+  service: name=apache2 state=started

+ 1
- 0
roles/common/tasks/main.yml View File

@@ -63,6 +63,7 @@
63 63
 - include: users.yml tags=users
64 64
 - include: apache.yml tags=apache
65 65
 - include: ssl.yml tags=ssl
66
+- include: letsencrypt.yml tags=letsencrypt
66 67
 - include: ufw.yml tags=ufw
67 68
 - include: security.yml tags=security
68 69
 - include: ntp.yml tags=ntp

+ 1
- 25
roles/common/tasks/ssl.yml View File

@@ -1,27 +1,3 @@
1
-- name: Copy SSL private key into place
2
-  copy: src=wildcard_private.key dest=/etc/ssl/private/wildcard_private.key group=ssl-cert owner=root mode=640
3
-  register: private_key
4
-  notify: restart apache
5
-
6
-- name: Copy SSL public certificate into place
7
-  copy: src=wildcard_public_cert.crt dest=/etc/ssl/certs/wildcard_public_cert.crt group=root owner=root mode=644
8
-  register: certificate
9
-  notify: restart apache
10
-
11
-- name: Copy CA combined certificate into place
12
-  copy: src=wildcard_ca.pem dest=/etc/ssl/certs/wildcard_ca.pem group=root owner=root mode=644
13
-  register: ca_certificate
14
-  notify: restart apache
15
-
16
-- name: Create a combined version of the public cert with intermediate and root CAs
17
-  shell: cat /etc/ssl/certs/wildcard_public_cert.crt /etc/ssl/certs/wildcard_ca.pem >
18
-    /etc/ssl/certs/wildcard_combined.pem
19
-  when: private_key.changed or certificate.changed or ca_certificate.changed
20
-
21
-- name: Set permissions on combined public cert
22
-  file: name=/etc/ssl/certs/wildcard_combined.pem mode=644
23
-  notify: restart apache
24
-
25 1
 - name: Create strong Diffie-Hellman group
26 2
   command: openssl dhparam -out /etc/ssl/private/dhparam2048.pem 2048
27 3
     creates=/etc/ssl/private/dhparam2048.pem
@@ -43,7 +19,7 @@
43 19
   notify: restart apache
44 20
 
45 21
 - name: Add common Apache SSL config
46
-  copy: src=etc_apache2_conf-available_ssl.conf
22
+  template: src=etc_apache2_conf-available_ssl.conf.j2
47 23
     dest=/etc/apache2/conf-available/ssl.conf
48 24
     owner=root
49 25
     group=root

roles/common/files/etc_apache2_conf-available_ssl.conf → roles/common/templates/etc_apache2_conf-available_ssl.conf.j2 View File

@@ -6,10 +6,10 @@ SSLStaplingCache shmcb:${APACHE_RUN_DIR}/stapling_cache(128000)
6 6
 SSLStaplingResponderTimeout 5
7 7
 SSLStaplingReturnResponderErrors off
8 8
 
9
-SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK
9
+SSLCertificateKeyFile	/etc/letsencrypt/live/{{ domain }}/privkey.pem
10
+SSLCertificateFile	/etc/letsencrypt/live/{{ domain }}/fullchain.pem
11
+SSLCertificateChainFile	/etc/letsencrypt/live/{{ domain }}/chain.pem
10 12
 
11
-SSLCertificateFile      /etc/ssl/certs/wildcard_public_cert.crt
12
-SSLCertificateKeyFile   /etc/ssl/private/wildcard_private.key
13
-SSLCACertificateFile    /etc/ssl/certs/wildcard_ca.pem
13
+SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK
14 14
 
15 15
 Header add Strict-Transport-Security "max-age=15768000; includeSubdomains"

+ 7
- 0
roles/common/templates/etc_letsencrypt_cli.conf.j2 View File

@@ -0,0 +1,7 @@
1
+rsa-key-size = 4096
2
+server = {{ letsencrypt_server }}
3
+authenticator = standalone
4
+register-unsafely-without-email = True
5
+keep = True
6
+expand = True
7
+agree-tos = True

+ 11
- 4
roles/ircbouncer/tasks/znc.yml View File

@@ -9,7 +9,7 @@
9 9
   group: name=znc state=present
10 10
 
11 11
 - name: Create znc user
12
-  user: name=znc state=present home=/var/lib/znc system=yes group=znc shell=/usr/sbin/nologin
12
+  user: name=znc state=present home=/usr/lib/znc system=yes group=znc shell=/usr/sbin/nologin
13 13
 
14 14
 - name: Ensure pid directory exists
15 15
   file: state=directory path=/var/run/znc group=znc owner=znc
@@ -17,11 +17,18 @@
17 17
 - name: Copy znc service file into place
18 18
   copy: src=etc_systemd_system_znc.service dest=/etc/systemd/system/znc.service mode=0644
19 19
 
20
-- name: Create a combined version of the private key with public cert and intermediate + root CAs
21
-  shell: cat /etc/ssl/private/wildcard_private.key /etc/ssl/certs/wildcard_combined.pem >
22
-    /usr/lib/znc/znc.pem creates=/usr/lib/znc/znc.pem
20
+- name: Create a combined version of the SSL private key and full certificate chain
21
+  shell: cat /etc/letsencrypt/live/{{ domain }}/privkey.pem
22
+    /etc/letsencrypt/live/{{ domain }}/fullchain.pem >
23
+    /usr/lib/znc/znc.pem
24
+    creates=/usr/lib/znc/znc.pem
23 25
   notify: restart znc
24 26
 
27
+- name: Update certificate renwal cron job
28
+  lineinfile: dest=/etc/cron.monthly/letsencrypt-renew state=present
29
+    line="cat /etc/letsencrypt/live/{{ domain }}/{privkey,fullchain}.pem > /usr/lib/znc/znc.pem; chown znc.znc /usr/lib/znc/znc.pem; chmod 640 /usr/lib/znc/znc.pem; service znc restart"
30
+    insertafter="EOF"
31
+
25 32
 - name: Ensure znc user and group can read cert
26 33
   file: path=/usr/lib/znc/znc.pem group=znc owner=znc mode=640
27 34
   notify: restart znc

+ 9
- 1
roles/mailserver/tasks/dovecot.yml View File

@@ -38,10 +38,13 @@
38 38
     - 10-auth.conf
39 39
     - 10-mail.conf
40 40
     - 10-master.conf
41
-    - 10-ssl.conf
42 41
     - auth-sql.conf.ext
43 42
   notify: restart dovecot
44 43
 
44
+- name: Template 10-ssl.conf
45
+  template: src=etc_dovecot_conf.d_10-ssl.conf.j2 dest=/etc/dovecot/conf.d/10-ssl.conf
46
+  notify: restart dovecot
47
+
45 48
 - name: Template 15-lda.conf
46 49
   template: src=etc_dovecot_conf.d_15-lda.conf.j2 dest=/etc/dovecot/conf.d/15-lda.conf
47 50
   notify: restart dovecot
@@ -61,3 +64,8 @@
61 64
     - imaps
62 65
     - pop3s
63 66
   tags: ufw
67
+
68
+- name: Update certificate renwal cron job
69
+  lineinfile: dest=/etc/cron.monthly/letsencrypt-renew state=present
70
+    line="service dovecot restart"
71
+    insertafter="EOF"

roles/mailserver/files/etc_dovecot_conf.d_10-ssl.conf → roles/mailserver/templates/etc_dovecot_conf.d_10-ssl.conf.j2 View File

@@ -9,8 +9,8 @@ ssl = required
9 9
 # dropping root privileges, so keep the key file unreadable by anyone but
10 10
 # root. Included doc/mkcert.sh can be used to easily generate self-signed
11 11
 # certificate, just make sure to update the domains in dovecot-openssl.cnf
12
-ssl_cert = </etc/ssl/certs/wildcard_combined.pem
13
-ssl_key = </etc/ssl/private/wildcard_private.key
12
+ssl_cert = </etc/letsencrypt/live/{{ domain }}/fullchain.pem
13
+ssl_key = </etc/letsencrypt/live/{{ domain }}/privkey.pem
14 14
 
15 15
 # If key file is password protected, give the password here. Alternatively
16 16
 # give it when starting dovecot with -p parameter. Since this file is often

+ 2
- 2
roles/mailserver/templates/etc_postfix_main.cf.j2 View File

@@ -40,8 +40,8 @@ smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3
40 40
 smtp_tls_mandatory_protocols=!SSLv2,!SSLv3
41 41
 smtp_tls_protocols = !SSLv2,!SSLv3
42 42
 smtpd_tls_protocols = !SSLv2,!SSLv3
43
-smtpd_tls_cert_file=/etc/ssl/certs/wildcard_combined.pem
44
-smtpd_tls_key_file=/etc/ssl/private/wildcard_private.key
43
+smtpd_tls_cert_file=/etc/letsencrypt/live/{{ domain }}/fullchain.pem
44
+smtpd_tls_key_file=/etc/letsencrypt/live/{{ domain }}/privkey.pem
45 45
 smtpd_use_tls=yes
46 46
 smtpd_tls_auth_only = yes
47 47
 smtp_tls_security_level = may

+ 1
- 1
roles/tarsnap/files/tarsnap.sh View File

@@ -4,7 +4,7 @@
4 4
 # Written by Tim Bishop, 2009.
5 5
 
6 6
 # Directories to backup (relative to /)
7
-DIRS="home root decrypted var/www"
7
+DIRS="home root decrypted var/www etc/letsencrypt"
8 8
 
9 9
 # Number of daily backups to keep
10 10
 DAILY=7

+ 1
- 1
roles/xmpp/tasks/prosody.yml View File

@@ -17,7 +17,7 @@
17 17
     - dependencies
18 18
 
19 19
 - name: Add prosody user to ssl-cert group
20
-  user: name=prosody groups=ssl-cert append=yes
20
+  user: name=prosody group=ssl-cert
21 21
 
22 22
 - name: Create Prosody data directory
23 23
   file: state=directory path=/decrypted/prosody owner=prosody group=prosody

+ 2
- 2
roles/xmpp/templates/prosody.cfg.lua.j2 View File

@@ -86,8 +86,8 @@ allow_registration = false;
86 86
 -- These are the SSL/TLS-related settings. If you don't want
87 87
 -- to use SSL/TLS, you may comment or remove this
88 88
 ssl = {
89
-	key = "/etc/ssl/private/wildcard_private.key";
90
-	certificate = "/etc/ssl/certs/wildcard_public_cert.crt";
89
+	key = "/etc/letsencrypt/live/{{ domain }}/privkey.pem";
90
+	certificate = "/etc/letsencrypt/live/{{ domain }}/cert.pem";
91 91
 }
92 92
 
93 93
 -- Force clients to use encrypted connections? This option will

+ 1
- 0
vars/defaults.yml View File

@@ -13,6 +13,7 @@ main_user_shell: "/bin/bash"
13 13
 # encfs_password: (required)
14 14
 friendly_networks:
15 15
   - ""
16
+letsencrypt_server: "https://acme-v01.api.letsencrypt.org/directory"
16 17
 
17 18
 # ssh
18 19
 kex_algorithms: "diffie-hellman-group-exchange-sha256"

Loading…
Cancel
Save