|
||
---|---|---|
meta | ||
tasks | ||
templates | ||
.ansible-lint | ||
.gitlab-ci.yml | ||
LICENSE | ||
README.md |
README.md
certbot-gandi Ansible Role
This role allows one to automate issuance of an wildcard Let's Encrypt X.509 certificate for a domain using gandi.
For example, if you own example.com
, this role will allow you to
automatically provision certificate for *.example.com
.
Caveat: The certificate will be valid only for subdomains of
example.com
!!! E.g. it will be valid for www.example.com
,
yourcoolsubdomain.example.com
, but it will not be valid for
example.com
itself!
Why?
I wrote this role to address specific use-case. I want to have an easy way to manage Let's Encrypt certificates for services that I self-host in my home network, but that are completely invisible outside my home. One way to achieve it is:
- I register a domain with gandi. E.g.
example.com
- At home I have my own DNS resolver. That could be for example something like pfSense, OPNSense, or even Pi-hole.
- On my private DNS resolver I add custom subdomains of
example.com
. For examplemycoolservice.example.com
. - I use this Ansible role to generate Let's Encrypt certificate for
*.example.com
, I hook it up to web-server (e.g. Nginx, Apache, whatever) that is hostingmycoolservice.example.com
locally.
This way mycoolservice.example.com
is visible (resolvable) only from within
my home network. And the certificate that my private web-server presents is
valid on any device -- my computer, smartphone, tablet, TV, whatever -- without
any fiddling with accepting untrusted (e.g. self-signed, or signed by my own
custom CA) certificate.
How?
- It creates
/srv/certbot
directory. All activities except certbot logging will happen within subdirectories of/srv/certbot
. - It creates Python virtualenv in
/srv/certbot/venv
and installs certbot with gandi plugin in it. - It generates Bash scripts for issuing (
issue.sh
) and renewing (renew.sh
) the certificate. They are placed in/srv/certbot/example.com/workdir/
directory (assuming your domain isexample.com
). - Then it calls
issue.sh
to issue the certificate the very 1st time. - It'll add a post-renew hook to certbot's config for reloading web server's configuration so that after renewing the certificate the web server reloads it.
- Adds a cron job to run
renew.sh
once a day to check if the certificate needs renewing.
The generated certificate and corresponding key lands in
/srv/certbot/example.com/config/live/example.com/
directory.
Quick start
Pull in the role to your system
First off you have to add proper dependency to your project. Create -- if it
doesn't yet exist -- a file called requirements.yaml
. Then add the dependency
to it. If this role is the only one that your playbook is pulling in, then
requirements.yaml
should look like this:
---
- src: git+https://codeberg.org/Prezu/certbot-gandi
version: master
name: certbot-gandi
Having that done, use ansible-galaxy
to pull the role in:
$ ansible-galaxy install -r requirements.yaml
This is a one-time thing. Once you pull the role it, it'll live in your
~/.ansible/roles
subdirectory.
Using the role in a playbook
The role requires you to set up a couple of Ansible variables:
domain
: This is the name of your domain. E.g.example.com
.gandi_api_token
: The API token you generated on your gandi account page.contact_email
: Let's Encrypt requires you to provide a contact email address.web_server_reload_command
: A command that will be executed by certbot to reload your web server's configuration after renewing the certificate.
The simplest and least secure way
If you want to quickly test the role out, you could add the following section
to your roles
in your playbook:
...
roles:
- role: certbot-gandi
vars:
domain: "example.com"
contact_email: contact@example.com
gandi_api_token: 12345SLFDKSLFKJSD # Your generated API token
web_server_reload_command: "systemctl reload nginx.service" # Assuming you're using Nginx
But you better not check that into your VCS!!!
Using ansible-vault to store the token
You should absolutely never check the bare API key to your version control
system. It's much better to use e.g. ansible-vault
to encrypt all security
sensitive variables. Ansible vault will maintain a file within your repository,
but the file will be encrypted.
Alright, so first you create the encrypted vault file:
$ mkdir vars
$ ansible-vault create vars/secrets.yaml
You'll be asked to pick a password for your new file. Then, ansible-vault will automatically open an editor for you. You have to create the YAML with the sensitive variables. E.g.:
---
gandi_api_token: 12345SLFDKSLFKJSD # Your generated API token
Now when you save the file and quite the editor, take a look at the new file. It'll look similar to this:
$ cat vars/secrets.yaml
$ANSIBLE_VAULT;1.1;AES256
38343062636539383830616436613162316536313465373236616566343034393937363665623466
3730613361363038613438376630393930373865343433660a636437396637663239363466363665
64386434663862666664323765373838346136326238316237383736373063393432333863373430
3364396133633933630a646434353937336233653430373166396139666539326239323463613132
39316163383364333836326639616339396333313534383663393737616363333336623033373833
38626430396264666365646366363530646462356637323533323962613866623561636363303339
36656335633535353565326339623463336265363663333661316562313730643234626265353938
30646631303330393464
So this is what you add to your VCS. So now in your runbook you'll need to point to the encrypted vars file:
...
vars_files:
- vars/secrets.yaml
...
roles:
- role: certbot-gandi
vars:
domain: "example.com"
contact_email: contact@example.com
web_server_reload_command: "systemctl reload nginx.service" # Assuming you're using Nginx
# That's it. gandi_api_token will be picked up from vars/secret.yaml instead of from here.
Now, from this point on, you'll need to pass a new parameter to
ansible-playbook
, namely --ask-vault-pass
. This will make ansible ask you
the Vault password each time you execute the runbook.