Duck DNS has an API that you can use with the DNS-01 challenge.
Create the following script files:
auth.sh
#!/bin/bash
DUCKDNS_TOKEN="your_token_here"
[[ "$(curl -s "https://www.duckdns.org/update?domains=${CERTBOT_DOMAIN%.duckdns.org}&token=${DUCKDNS_TOKEN}&txt=${CERTBOT_VALIDATION}")" = "OK" ]]
cleanup.sh
#!/bin/bash
DUCKDNS_TOKEN="your_token_here"
[[ "$(curl -s "https://www.duckdns.org/update?domains=${CERTBOT_DOMAIN%.duckdns.org}&token=${DUCKDNS_TOKEN}&txt=${CERTBOT_VALIDATION}&clear=true")" = "OK" ]]
Put in your real Duck DNS token instead of “your_token_here”. Make both scripts executable with chmod +x auth.sh cleanup.sh
Then you can run certbot:
sudo certbot certonly --manual --preferred-challenges dns --manual-auth-hook /path/to/auth.sh --manual-cleanup-hook /path/to/cleanup.sh
(obviously use the real location of the scripts instead of /path/to)