This repository has been archived by the owner on Nov 16, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1005 from gratipay/certbot
Put together a new TLS workflow
- Loading branch information
Showing
5 changed files
with
126 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,4 @@ local.env | |
*.egg-info | ||
www/appendices/disclosures.json | ||
tests/.cache | ||
certs/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
config-dir = tmp | ||
work-dir = tmp | ||
logs-dir = tmp | ||
authenticator = manual | ||
preferred-challenges = dns | ||
email = support@gratipay.com | ||
domains = assets.gratipay.com, downloads.gratipay.com | ||
rsa-key-size = 4096 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
config-dir = tmp | ||
work-dir = tmp | ||
logs-dir = tmp | ||
authenticator = manual | ||
preferred-challenges = http | ||
email = support@gratipay.com | ||
domains = gratipay.com, gittip.co, www.gittip.co, gittip.com, www.gittip.com, gratipay.co, www.gratipay.co, www.gratipay.com, gratipay.net, www.gratipay.net, gratipay.org, www.gratipay.org | ||
rsa-key-size = 4096 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import random | ||
import string | ||
|
||
nav_title="Install a TLS Certificate" | ||
[---] | ||
pool = string.lowercase + string.digits | ||
random_subdomain = ''.join([random.choice(pool) for i in range(8)]) | ||
[---] text/html | ||
|
||
Our certificate vendor is [Let's Encrypt](https://letsencrypt.org/), and the | ||
way we get certificates from them is via their | ||
[certbot](https://certbot.eff.org/docs/using.html#manual) command-line tool. We | ||
have several domains to secure, plus aliases, and the way to verify ownership | ||
and install the certificate vary for each. They are described below. | ||
|
||
Let's Encrypt enforces frequent cert rolling via 90-day expirations. Once we | ||
hit our first expiration cycle and sort out how to renew, we should update | ||
these docs. Eventually we can explore further automation. | ||
|
||
|
||
## `gratipay.com` | ||
|
||
Install `certbot` locally, then run it in the `certs` directory of an Inside | ||
Gratipay repo checkout, with the provided [configuration | ||
file](https://github.com/gratipay/inside.gratipay.com/tree/master/certs/conf/): | ||
|
||
``` | ||
git clone git@github.com:gratipay/inside.gratipay.com.git | ||
cd certs | ||
certbot certonly -c gratipay.com.ini | ||
``` | ||
|
||
You'll have to agree to having your IP address publicly logged, and then you'll | ||
be prompted to verify ownership of the domains via [`http-01` | ||
challenges](https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.2). | ||
For that, visit the [ACME | ||
Challenger](https://gratipay.com/.well-known/acme-challenge/) (you'll have to | ||
login as an admin to use it). Go through the challenge cycle for `gratipay.com` | ||
and for each alias (there are a bunch, including `www.*` variants), by | ||
appending the token to the above link, and then entering the authorization | ||
response in the form you find there. | ||
|
||
Once you have the cert, install it [at | ||
Heroku](https://devcenter.heroku.com/articles/ssl-endpoint#provision-the-add-on): | ||
|
||
``` | ||
cd tmp/live/gratipay.com/ | ||
heroku certs:update --app gratipay fullchain.pem privkey.pem | ||
``` | ||
|
||
Once you're done, `rm -rf tmp` to clear out sensitive files from your laptop. | ||
|
||
|
||
## `{assets,downlaods}.gratipay.com` | ||
|
||
Our `assets.gratipay.com` CDN uses `gratipay.com/assets` as its origin server, | ||
and we have a read-only ACME Challenger | ||
[endpoint](https://assets.gratipay.com/.well-known/acme-challenge/deadbeef) | ||
under there. Therefore, the process to verify the domain is just like for | ||
`gratipay.com`: create the challenge response in the normal [ACME | ||
challenger](https://gratipay.com/.well-known/acme-challenge/), and Let's | ||
Encrypt should find what it needs in the right place. | ||
|
||
However, we use the same cert for `downloads.*` as for `assets.*`, since both | ||
are hosted at MaxCDN. But since `downloads` is a PUSH zone, you have to | ||
(manually) upload a file via FTP in order to verify the domain. Here's how to | ||
[reset](https://www.maxcdn.com/one/tutorial/reset-push-ftp-password/) the ftp | ||
password. Aaaaaaaaaand there's no way to serve a hidden directory, so you have | ||
to use [DNS](https://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.4) | ||
verification after all, so you may as well use it for `assets.*`, too (how do | ||
we write a config file that splits the authenticators by domain?). Sorry. | ||
😞 | ||
|
||
(P.S. The reason we don't just do *all* verification via DNS is because that's | ||
harder to automate … though I guess DNSimple does have [an | ||
API](https://developer.dnsimple.com/v2/zones/records/#create). Hmm …) | ||
|
||
To install the cert, login to [MaxCDN](https://www.maxcdn.com/) (creds are in | ||
LastPass). Go to Account > SSL to add the new certificate, then navigate to | ||
EdgeSSL > SNI for each zone, and select the new cert. After installing for both | ||
zones, go back to Account > SSL and delete the old cert. | ||
|
||
Delete the TXT records from DNS. | ||
|
||
|
||
## `grtp.co` | ||
|
||
``` | ||
ssh root@grtp.co | ||
cd certs/ | ||
``` | ||
|
||
You should find a | ||
[`certbot-auto`](https://certbot.eff.org/docs/install.html#certbot-auto) | ||
executable there, along with a `certbot.ini` configuration file, some logfiles, | ||
etc. I *think* all you need to do is `./certbot-auto renew`, but since we're | ||
still in our first cert cycle with Let's Encrypt, it's hard to know for sure. | ||
😌 | ||
|
||
To verify domains, I ran `./certbot-auto certonly -c certbot.ini`, creating | ||
(and subsequently cleaning up) files under: | ||
|
||
``` | ||
~grtp.co/production/www/.well-known/acme-challenge/ | ||
``` | ||
|
||
The cert and key are symlinked into `/etc/nginx/certs/`, so you shouldn't need | ||
to do anything other than `/etc/init.d/nginx reload` once the cert/key are | ||
updated. |
This file was deleted.
Oops, something went wrong.