Server and client part to acquire TLS certs via DNS verification
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Linus Sehn 4d32bdcace
continuous-integration/drone/push Build is passing Details
Bump inventory
4 days ago
files convert client part to separate role 2 years ago
group_vars limit access to registration to FSFE IPs 2 years ago
inventory@16022d3bf9 Bump inventory 4 days ago
roles update client role and instructions 2 years ago
.drone.yml adding drone CI for docs sync 5 months ago
.gitmodules convert client part to separate role 2 years ago added badge to the README 5 months ago
ansible.cfg update client role and instructions 2 years ago
playbook.yml update client role and instructions 2 years ago

ACME DNS Server and Client


For some of the FSFE's services, we cannot rely on Let's Encrypt's HTTP/TLS authentication. For example:

  • Multiple servers for the same domain
  • XMPP server which uses but is on a separate host than the webserver

To avoid that all servers can modify DNS entries, we use a separate DNS server that is just used for ACME DNS challenges in an isolated zone.


  • is a VM that runs the server part. It is the authorative NS for all queries in its domain, and provides an API for registration/modification of entries.
  • Either via curl or with the acme-dns-client, clients can ask the acme-dns server for an "account" and a subdomain of This separate subdomain is then set as the CNAME of
  • Upon certificate request, LE provides a verfication string and queries (TXT) whether the string is present to confirm whether the domain belongs to us. Either via curl or the client binary, we update the TXT record accordingly at the acme-dns server. LE follows the CNAME and can confirm it.


You can include the client role in existing playbooks, or use it standalone.

1. Deploy acme-dns-client and register domains

Run the ansible playbook to deploy the client binary. It can apply to all servers in the baseline group, so limit carefully.

ansible-playbook -l --extra-vars="domains=['']" playbook.yml

The ansible domains variable can be a list (array), or a space-separated string.

The client role then registers the given domains with the ACME DNS server, and checks whether the CNAME has been set correctly. You might have to run the role twice: first to register the domain which then will probably fail because of the missing CNAME, and second to confirm the set CNAME (which you have to do manually).

To set a CNAME with your DNS server, it may look like the following:     IN      CNAME

2. Acquire the cert from LE

Once the CNAME is set, you can run certbot to request a certificate:

certbot certonly --manual --preferred-challenges dns --manual-auth-hook acme-dns-client -d

The settings will be saved in the renewal configuration of certbot, so this effort only has to be done once.

If you use dehydrated, you can try something like this, using the custom hook:

dehydrated -c --accept-terms -t dns-01 -d -k acme-dns-dehydrated-hook