# A DANE-friendly Certbot workflow

**URL:** https://community.letsencrypt.org/t/a-dane-friendly-certbot-workflow/158324
**Category:** Help
**Created:** [August 22, 2021, 2:08pm UTC](https://community.letsencrypt.org/t/a-dane-friendly-certbot-workflow/158324 "2021-08-22T14:08:40Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![raf](https://avatars.discourse-cdn.com/v4/letter/r/848f3c/32.png) [@raf](https://community.letsencrypt.org/u/raf)
#### Post date: [August 22, 2021, 2:08pm UTC](https://community.letsencrypt.org/t/a-dane-friendly-certbot-workflow/158324/1 "2021-08-22T14:08:41Z")

</div>

Hi. I'm setting up a DANE-friendly Certbot workflow.

See [DNS-based Authentication of Named Entities - Wikipedia](https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities)  
for a short introduction, or RFC6698, RFC7671, RFC7672 for the gory details.

I'm only interested in TLSA 3 1 1 records. They only refer to the public key  
itself and nothing else up the chain. This isn't about TLSA 2 1 1 records,  
or any other kind of TLSA record.

I think I have a good idea of what needs to happen, but I'd like  
confirmation that what I am attempting can work, and I have a question about  
certbot usage that I don't know the (official) answer to yet. Any advice  
would be greatly appreciated.

Normally, certbot automatically renews a certificate as it approaches  
expiry, and at the same time, it replaces (using symlinks) the existing  
certificate with the new certificate. Each time this happens, by default,  
there is a new keypair as well as a new certificate.

For DANE, I need to be able to create the replacement keypair and  
certificate well in advance of the existing keypair and certificate expiring  
and being deactivated. So I need two keypairs and two certificates for the  
same set of domains in existence at the same time. And I need to be able to  
decide when to deactivate the old keypair/certificate and activate the new  
keypair/certificate. That will be done on a different schedule (of my  
choosing) to certbot's schedule for renewing certificates.

The replacement keypair/certificate needs to be created well in advance so  
as to give me plenty of time to create the corresponding TLSA records  
(unless I automate that), and to give remote caching DNS servers enough time  
to have access to both the old and the new TLSA records before the new  
keypair/certificate becomes active (i.e. at least a few DNS TTLs worth of  
time, however long that is). But rather than thinking about TTLs, it's  
recommended to just have two keys with published TLSA records at all times:  
the current one, and the next one. That makes it possible for even emergency  
key rollovers to be as unexciting as possible.

While both certificates are automatically renewing, I want them to keep  
their existing keypairs. That way, the certificates can still renew every  
three months, but the keypairs, and hence the corresponding TLSA records,  
can stay the same until I choose to rollover the keypair. That might be  
manually triggered, or I might automated it (e.g. annually). I'm not  
expecting the key rollover to be handled by certbot. I'll automate or  
script it myself.

So, this is what I think I need to do:

- Instruct certbot to create a keypair/certificate (the original)
- Instruct certbot to create another keypair/certificate (the duplicate)
- Instruct certbot to reuse the original keypair when renewing
- Instruct certbot to reuse the duplicate keypair when renewing
- Designate the original certificate as current (with symlinks)
- Designate the duplicate certificate as next (with symlinks)
- Publish TLSA 3 1 1 records for the original key
- Publish TLSA 3 1 1 records for the duplicate key
- Configure services to use the current keypair/certificate

These two keypairs/certificates will act as a set of current/next  
keypairs/certificates for the set of domains. Certbot will automatically  
renew the certificates every three months without creating new keypairs each  
time.

When I want to rollover the key from the original to the duplicate:

- Swap the current/next roles (symlinks) and reload any affected services
- Remove old TLSA 3 1 1 records for the just deactivated (original) key
- Instruct certbot to renew the next (original) certificate with a new keypair
- Publish new TLSA 3 1 1 records for the just created next (original) key

When I want to rollover the key from the duplicate to the original:

- Swap the current/next roles (symlinks) and reload any affected services
- Remove old TLSA 3 1 1 records for the just deactivated (duplicate) key
- Instruct certbot to renew the next (duplicate) certificate with a new keypair
- Publish new TLSA 3 1 1 records for the just created next (duplicate) key

What I'd like help with is the actual certbot commands to do all of this  
(see below), and how to arrange for the automatic renewals to reuse the  
keypair, but for the less frequent key rollover forced renewals to create a  
new keypair.

My understanding is that command line options used with the certbot renew or  
certonly subcommands (such as --reuse-key) cause undocumented magic to  
happen to the renewal config file so that its effect persists to subsequent  
renewals. And I know that that this persistence can be suppressed with the  
--disable-renew-updates option. But I can't see how to set up --reuse-key  
persistently, but then temporarily disable it when doing the key rollover  
forced renewal, so that it goes back to reusing the key again afterwards for  
normal automated renewals.

I expect to need to create both certificates (one the usual way, and one  
with --duplicate), then immediately renew them both with --reuse-key, so  
that subsequent automatic renewals keep the same keypairs [Correction:  
--reuse-key can be supplied when initially creating both  
keypairs/certificates]. Then, when doing a key rollover, renew the next  
certificate with --force-renewal and --no-reuse-key and  
--disable-renew-updates, so as to create a new keypair with the new  
certificate, but then go back to reusing the key for subsequent automatic  
renewals.

But I can't find a --no-reuse-key option in the documentation.

It looks like, once you have used --reuse-key, you can't go back to not  
reusing the key (at least, not via the certbot command line). Is that the  
case or am I missing something?

What's the best way to temporarily override the persistent effect of an  
earlier use of --reuse-key? Do I just have to delete the "reuse\_key = True"  
from the renewal config file beforehand, and then put it back afterwards? Or  
is there a command line option for the renew/certonly subcommands that has  
the effect of removing the "reuse\_key = True" from the renewal config file  
that was put there by an earlier use of --reuse-key? If so, could I use that  
with --disable-renew-updates so that the creation of a new keypair is done  
once, but isn't made persistent, so that subsequent automatic renewals will  
go back to reusing the existing key?

Removing "reuse\_key = True" from the renewal config file and putting it back  
again does seem to work, but I'd rather not rely on undocumented behaviour.  
It'll also be good when there's a documented way to update the renewal  
config file without also performing an otherwise unwanted certificate  
renewal.

Another thing to note is that, after creating the duplicate  
keypair/certificate, any subsequent use of the --expand option, to change  
which domains are included in these certificates, will need to also use the  
--cert-name option so as to prevent ambiguity, and be performed on both the  
original and the duplicate certificates.

This is what I think the workflow will look like in detail:

```
# Create the original keypair/certificate (reusing the keypair thereafter)
certbot run --apache --reuse-key \
  -d example.org -d www.example.org -d mta-sts.example.org -d mail.example.org

# Create the duplicate keypair/certificate (and choose the new cert-name)
certbot certonly --apache --duplicate --reuse-key --cert-name example.org-duplicate \
  -d example.org -d www.example.org -d mta-sts.example.org -d mail.example.org

# Designate the original/duplicate keypairs/certificates as current/next via symlinks
mkdir /etc/letsencrypt/next
mkdir /etc/letsencrypt/current
ln -s /etc/letsencrypt/live/example.org /etc/letsencrypt/current/example.org
ln -s /etc/letsencrypt/live/example.org-duplicate /etc/letsencrypt/next/example.org

# Publish TLSA records to DNS for both keys (one per hostname/port/key combination)
# See postfix-tls(1) (look for output-server-tlsa) for one way to generate these. e.g.:
# postfix tls output-server-tlsa -h mail.example.org /etc/letsencrypt/current/example.org/privkey.pem
# postfix tls output-server-tlsa -h mail.example.org /etc/letsencrypt/next/example.org/privkey.pem
_443._tcp IN TLSA 3 1 1 ... (for /etc/letsencrypt/current/example.org)
_443._tcp.www IN TLSA 3 1 1 ... (for /etc/letsencrypt/current/example.org)
_443._tcp.mta-sts IN TLSA 3 1 1 ... (for /etc/letsencrypt/current/example.org)
_25._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/current/example.org)
_465._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/current/example.org)
_587._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/current/example.org)
_993._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/current/example.org)
_995._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/current/example.org)
_443._tcp IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_443._tcp.www IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_443._tcp.mta-sts IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_25._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_465._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_587._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_993._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_995._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)

# Configure web/mail services to use the current certificate
/etc/letsencrypt/current/example.org/privkey.pem
/etc/letsencrypt/current/example.org/fullchain.pem

# A year later..., rollover from the original to the duplicate

# Swap role symlinks (would be faster/better in a language other than shell)
rm /etc/letsencrypt/next/example.org
rm /etc/letsencrypt/current/example.org
ln -s /etc/letsencrypt/live/example.org-duplicate /etc/letsencrypt/current/example.org
ln -s /etc/letsencrypt/live/example.org /etc/letsencrypt/next/example.org
Reload any affected services (e.g. dovecot)

# Remove old TLSA records from DNS
Remove TLSA records (for the old key that is now in /etc/letsencrypt/next/example.org)

# Replace the newly next keypair/certificate (original)
# Before: Remove "reuse_key = True" from the renewal config file
perl -pi -e 's/reuse_key = True\n//' /etc/letsencrypt/renewal/example.org.conf
# Create the new next keypair/certificate (original)
certbot certonly --force-renewal --cert-name example.org
# After: Restore "reuse_key = True" to the renewal config file
echo 'reuse_key = True' >> /etc/letsencrypt/renewal/example.org.conf
# Q: Is there a certbot-approved way to temporarily override reuse_key = True?

# Publish TLSA records to DNS for new next key
_443._tcp IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_443._tcp.www IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_443._tcp.mta-sts IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_25._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_465._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_587._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_993._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_995._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)

# A year later..., rollover from the duplicate to the original

# Swap role symlinks (would be faster/better in a language other than shell)
rm /etc/letsencrypt/next/example.org
rm /etc/letsencrypt/current/example.org
ln -s /etc/letsencrypt/live/example.org /etc/letsencrypt/current/example.org
ln -s /etc/letsencrypt/live/example.org-duplicate /etc/letsencrypt/next/example.org
Reload any affected services (e.g. dovecot)

# Remove old TLSA records from DNS
Remove TLSA records (for the old key that is now in /etc/letsencrypt/next/example.org)

# Replace the newly next keypair/certificate (duplicate)
# Before: Remove "reuse_key = True" from the renewal config file
perl -pi -e 's/reuse_key = True\n//' /etc/letsencrypt/renewal/example.org-duplicate.conf
# Create the new next keypair/certificate (duplicate)
certbot certonly --force-renewal --cert-name example.org-duplicate
# After: Restore "reuse_key = True" to the renewal config file
echo 'reuse_key = True' >> /etc/letsencrypt/renewal/example.org-duplicate.conf
# Q: Is there a certbot-approved way to temporarily override reuse_key=True?

# Publish TLSA records to DNS for new next key
_443._tcp IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_443._tcp.www IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_443._tcp.mta-sts IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_25._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_465._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_587._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_993._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)
_995._tcp.mail IN TLSA 3 1 1 ... (for /etc/letsencrypt/next/example.org)

# And repeat annually, to rollover back and forth between the original and the duplicate

```

If anyone can suggest a better way to temporarily override "reuse\_key = True",  
or see anything I've done wrong, or point out anything I've misunderstood,  
any advice would be greatly appreciated.

The certbot commands themselves all seem to work, as does the nasty  
temporary overriding of "reuse\_key = True" in the renewal config file. So  
I'm hopeful that I can automate this, or at least mostly script it, without  
much trouble.

But I suggest that a --no-reuse-key option be added to certbot's command  
line interface. I've opened an issue on github for it. In fact any option  
that causes a persistent change to the renewal config file should have an  
opposite. There's an old adage that comes to mind:

```
Any feature that can't be turned off is a bug. :-)

```

It would make the post-rollover creations of new keypairs/certificates  
possible without having to resort to clumsy behind-the-scenes file  
modifications. Ideally, they would look like this:

```
# Replace the newly next keypair/certificate (original)
certbot certonly --force-renewal --no-reuse-key --disable-renew-updates \
    --cert-name example.org

# Replace the newly next keypair/certificate (duplicate)
certbot certonly --force-renewal --no-reuse-key --disable-renew-updates \
    --cert-name example.org-duplicate

```

cheers,  
raf

---

<div class="post-metadata">

### Author: ![Nummer378](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/nummer378/32/49862_2.png) [@Nummer378](https://community.letsencrypt.org/u/Nummer378)
#### Post date: [August 22, 2021, 3:41pm UTC](https://community.letsencrypt.org/t/a-dane-friendly-certbot-workflow/158324/2 "2021-08-22T15:41:52Z")

</div>

So first of all I'm going to admit I haven't read the entire text above - but I've skimmed through (most of) it.

Your approach seems a little overcomplicated to me. In general - **not certbot specific** - there are two more-or-less common approaches for TLSA 3 1 1 records.

**Technically speaking** , it is entirely possible to generate a private key _without_ the corresponding certificate. This enables you to put your TLSA 3 1 1 record for a future key in DNS **before** you generate the certificate for that key. This is a common rollover technique, as your TLSA 3 1 1 record will already exist when the cert is created. The technique works by always having "current + next" keys. The current key, with an active certificate and a corresponding TLSA 3 1 1 record in DNS. Then there's the "next" key, which does not yet have a certificate, but the TLSA record already exists in DNS. When renewal happens, the new key is used and the whole process beings anew.

How to do that with certbot? I've no idea, I don't use certbot for DANE, but other (private) acme clients. It generally requires an acme client capable of using a key generated well in advance.

The other approach I have used for TLSA 3 1 1 records is less demanding on the acme client:

Just renew the certificate (with new key), put new TLSA in DNS, wait a bunch of TTLs (TTL is 1 hour in my deployments) and then rollover. Remember, you should still have ~30 days left on the clock for the old cert, so the rollover can have quite some time delay. This is done via any standard deploy hook any acme client should have.

Neither of these two approaches require you to "flip" between multiple certificates as you're apparently intending. With both approaches, there's always just one "current" certificate in certbot and renewal logic is always the same - no weird editing of renewal configs.

If you're completly unable to automate the addition/removal of TLSA records, my suggestion would be to reuse the key indefinetly. If you want to change the key at some point, since you have to update the TLSA manually anyway, just generate a new key for this unusual scenario manually in advance, put the new TLSA record in DNS and then renew after (at least) a few TTL's have elapsed.

---

<div class="post-metadata">

### Author: ![raf](https://avatars.discourse-cdn.com/v4/letter/r/848f3c/32.png) [@raf](https://community.letsencrypt.org/u/raf)
#### Post date: [August 22, 2021, 11:50pm UTC](https://community.letsencrypt.org/t/a-dane-friendly-certbot-workflow/158324/3 "2021-08-22T23:50:56Z")

</div>

Thanks. But I don't like the idea of keeping one key forever. And while I have seen advice to create a key outside of certbot, and use --csr (and sometimes --reuse-key as well, even though the two are incompatible), that seems more messy/complicated to me than the above. And they almost never show exactly how to do everything. It's usually just words in English, not actual commands.

I wanted a workflow that only uses certbot, the recommended (and so probably the most popular?) ACME client and certificate manager. I see that as being less complicated, because I don't need to use openssl directly as well as certbot, and I don't need to think about how to manage the combination of the two. I didn't like the sound of managing keys outside of certbot, and certificates in certbot. Certbot can manage it all.

And while it's true that the next key doesn't need to have a certificate yet, it does no harm to have one, and having the certificate makes it simpler, because I don't need to think about it. Certbot does that for me. But also, it means that it's ready to use immediately if I ever need to rollover in a hurry. Rolling over takes milliseconds. It's just a symlink change (and service reloads).

I wanted to present (what I think is) a simple elegant workflow using certbot for everything, with all the actual commands needed to make it happen, including the key rollovers. I couldn't find that anywhere, and I thought it might help others. I thought it wasn't possible with certbot until someone told me about the wonderful --duplicate option.

The only commands I've left out are the publishing and removal of TLSA records in DNS. I will be automating that, but the way I'll be doing that wouldn't be helpful to show others. And everyone will create a different set of TLSA records depending on their situation.

I guess different things are simple or complicated to different people. 🙂

---

<div class="post-metadata">

### Author: ![raf](https://avatars.discourse-cdn.com/v4/letter/r/848f3c/32.png) [@raf](https://community.letsencrypt.org/u/raf)
#### Post date: [August 24, 2021, 1:40pm UTC](https://community.letsencrypt.org/t/a-dane-friendly-certbot-workflow/158324/4 "2021-08-24T13:40:06Z")

</div>

I got excited and wrote a nice little shell script to do all of this:

[danectl](https://raf.org/danectl)  
[GitHub - raforg/danectl: a DANE-friendly Certbot workflow](https://github.com/raforg/danectl)

Now I can do it like this:

```
# Adopt an existing certificate for DANE use (as the original/current)

  danectl adopt example.org

# Or create a new certificate for DANE use (as the original/current)

  danectl new example.org www.example.org mta-sts.example.org mail.example.org

# Then create the duplicate certificate (as the duplicate/next)

  danectl dup example.org www.example.org mta-sts.example.org mail.example.org

# Then say what TLSA records I need

  danectl add-tlsa example.org _443._tcp _443._tcp.www _443._tcp.mta-sts
  danectl add-tlsa example.org _25._tcp.mail _465._tcp.mail _587._tcp.mail
  danectl add-tlsa example.org _110._tcp.mail _143._tcp.mail
  danectl add-tlsa example.org _993._tcp.mail _995._tcp.mail

# Or remove some

  danectl del-tlsa example.org _110._tcp.mail _143._tcp.mail

# Then output the TLSA records (to be published in the DNS)

  danectl tlsa-current example.org
  danectl tlsa-next example.org

# And check that they have been published in the DNS

  danectl tlsa-check example.org

# Then say what services need to be reloaded on a key rollover

  danectl add-reload example.org apache2 postfix dovecot

# Or remove some

  danectl del-reload example.org postfix # Postfix can look after itself :-)

# Annually, or in an emergency, perform a key rollover

  danectl rollover example.org

```

The rollover command will show which old TLSA records need to be removed from the DNS, and it creates a new next key, and shows the new TLSA records that need to be published to the DNS.

Now it's simple.

---

<div class="post-metadata">

### Author: ![system](https://global.discourse-cdn.com/letsencrypt/original/3X/c/a/ca6c06ea1ea201324bba7048c6841ce60236468d.png) [@system](https://community.letsencrypt.org/u/system)
#### Post date: [September 23, 2021, 1:40pm UTC](https://community.letsencrypt.org/t/a-dane-friendly-certbot-workflow/158324/5 "2021-09-23T13:40:43Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
