Limiting deSEC tokens for DNS-01 and dynDNS
The deSEC documentation documents how to scope tokens using policies. I used this feature to limit my deSEC tokens to what they are responsible for.
The
{{id}}is not the token name and is unfortunately not shown in the UI. See useful commands below for a simple way to query the ids of all your tokens.
I use just to organize my commands. If you want the commands to work in your shell, just replace {{something}} with ${something}.
dynDNS
I use dynDNS since I don't have a static IP at home. This allows updating both A and AAAA records, but only for the intended domain and subdomain. For each domain, I use a different token to keep things safer.
desec-limit-token-dyndns id domain subdomain:
curl -sS https://desec.io/api/v1/auth/tokens/{{id}}/policies/rrsets/ \
--header "Authorization: Token ${DESEC_TOKEN}" \
--header "Content-Type: application/json" --data @- <<< \
'{"domain": null, "subname": null, "type": null, "perm_write": false}'
curl -sS https://desec.io/api/v1/auth/tokens/{{id}}/policies/rrsets/ \
--header "Authorization: Token ${DESEC_TOKEN}" \
--header "Content-Type: application/json" --data @- <<< \
'{"domain": "{{domain}}", "subname": "{{subdomain}}", "type": "AAAA", "perm_write": true}'
curl -sS https://desec.io/api/v1/auth/tokens/{{id}}/policies/rrsets/ \
--header "Authorization: Token ${DESEC_TOKEN}" \
--header "Content-Type: application/json" --data @- <<< \
'{"domain": "{{domain}}", "subname": "{{subdomain}}", "type": "A", "perm_write": true}'ACME DNS-01
I use wildcard certificates, which can only be issued by using a DNS-01 challenge. This only allows updating the _acme-challenge with a TXT record only, which is enough for the challenge.
desec-limit-token-acme id domain:
curl -sS https://desec.io/api/v1/auth/tokens/{{id}}/ --header "Authorization: Token ${DESEC_TOKEN}" | jq .name
curl -sS https://desec.io/api/v1/auth/tokens/{{id}}/policies/rrsets/ \
--header "Authorization: Token ${DESEC_TOKEN}" \
--header "Content-Type: application/json" --data @- <<< \
'{"domain": null, "subname": null, "type": null, "perm_write": false}'
curl -sS https://desec.io/api/v1/auth/tokens/{{id}}/policies/rrsets/ \
--header "Authorization: Token ${DESEC_TOKEN}" \
--header "Content-Type: application/json" --data @- <<< \
'{"domain": "{{domain}}", "subname": "_acme-challenge", "type": "TXT", "perm_write": true}'Useful commands
desec-list-tokens:
curl -sS https://desec.io/api/v1/auth/tokens/ --header "Authorization: Token ${DESEC_TOKEN}" | jq '.[] |{name, id}'
desec-list-policies id:
curl -sS https://desec.io/api/v1/auth/tokens/{{id}}/policies/rrsets/ --header "Authorization: Token ${DESEC_TOKEN}" | jq
desec-delete-policy id policy_id:
curl -sS -X DELETE https://desec.io/api/v1/auth/tokens/{{id}}/policies/rrsets/{{policy_id}}/ \
--header "Authorization: Token ${DESEC_TOKEN}"
2026-02-08