Planted on 23/07/19
Growth Stage: 🌲 evergreen
Before I start, here is some technical information about my website -
Let's Encrypt provides certificates for 90 days only, so I was forced to set up
the certbot
every three months, then generate the certificate and manually
deploy the certificates to GitLab. It was frustrating because in three months,
my shell probably will not remember the command I used last time, and I was too
lazy to document the process somewhere.
Then I came across a project , which was trying to do a similar thing with other domain name registrar. I thought that this is an excellent setup to adapt and modify it to suit my needs. So I decided to write my module for automatic deployment of Let's Encrypt certificates to GitLab.
Before Let's Encrypt can generate the certificate for the domain, it requires the user to prove domain ownership. Let's Encrypt provides two methods to do this task -
Using the second method requires me to add a file on my website, and I did not want to do that. Moreover, if in the future, I decide to host some other service, which does not have a website, then this method will fail.
The first method requires that the domain configuration on the domain registrar is modified. GoDaddy provides a robust API, and it is not difficult to utilize that API to automate specific tasks. The probability of changing the registrar is quite low, at least for the next few years. It will be easier to generate the certificates for any subdomains, as all the subdomains will also be hosted under the same domain registrar.
So here are the steps:
certbot
with all the domain namescertbot
verify the DNS changesIn step 1, we call certbot
will the preferred method DNS. We also need to
supply an email id (used by Let's Encrypt to notify domain expiration). The
EMAIL_ID
environment variable can be used to store the email id of the user.
Certbot runs in an interactive mode by default. It is not desired in a scripted
environment. Certbot also provides mechanisms to deploy the certificates to a
local server automatically, but as we are hosting our website on Gitlab, we do
not want the automatic deployment facility. So we need to invoke the certbot
command with --manual
and certonly
modes.
certbot --manual \
--preferred-challenges dns \
--agree-tos \
--email "${EMAIL_ID}" \
--no-eff-email \
--expand \
--renew-by-default \
--manual-public-ip-logging-ok \
--noninteractive \
--redirect \
--config-dir ${DIR}/generated/config \
--work-dir ${DIR}/generated/work \
--logs-dir ${DIR}/generated/logs \
--manual-auth-hook ${DIR}/auth_hook.sh \
-d yashagarwal.in \
certonly
The explanation for most of the flags used in the above command can be found by running the following command -
certbot --help
The --manual-auth-hook
flag is worth looking. This hook provides a mechanism
to specify the executable, which can be used to facilitate domain ownership
validation. In this case, the hook points to a script auth_hook.sh
, which then
calls a Go client, which interacts with GoDaddy API.
Certbot supplies two environment variables CERTBOT_DOMAIN
, which contains the
domain name to be verified and CERTBOT_VALIDATION
, which includes a random
string corresponding to _acme-challenge TXT
entry. What this means is that, if
I have
CERTBOT_DOMAIN=yashagarwal.in
CERTBOT_VALIDATION=6VNg5kDVI_BF1S9N5s74LTBHQnwDpQqKlblKRjIzBwM
Then the DNS manager should contain a TXT entry _acme-challenge.yashagarwal.in
with the value of 6VNg5kDVI_BF1S9N5s74LTBHQnwDpQqKlblKRjIzBwM
.
The auth_hook.sh
file calls the Go client with the abovementioned environment
variables. The relevant code can be found
here .
Once all the DNS entries are added, the auth_hook.sh
script will sleep for 10
minutes. It is to allow DNS changes to propagate throughout the Internet. It is
a random duration as I could not find any GoDaddy support page mentioning the
exact period used by them.
Once the auth_hook.sh
script returns successfully, certbot
will verify the
DNS records. If the verification is successful, certbot
will generate the
certificates in ./generated/config/live/{CERTBOT_DOMAIN}
directory.
I use the following command to deploy the certificates to Gitlab pages where my website is hosted -
curl -vvv \
--request PUT \
--header "Private-Token:${GITLAB_TOKEN}" \
--form "certificate=@${key_dir}/fullchain.pem" \
--form "key=@${key_dir}/privkey.pem" \ "https://gitlab.com/api/v4/projects/yashhere%2Fyashhere.gitlab.io/pages/domains/yashagarwal.in"
where
key_dir="./generated/config/live/yashagarwal.in"
Moreover, GITLAB_TOKEN
is an environment variable that contains the API token
generated from the Gitlab settings page.
It is not automation if I have to run this script manually every three months. So I created a Travis CI job to automate this process. The job will run every month and deploy my certificates automatically. It has been four months, and I have not faced any issues with this setup.
The code for this post can be viewed at Github .
Thanks for reading. Cheers 😄