2026-01-22 16:43:26 +01:00
#!/usr/bin/env sh
# shellcheck disable=SC2034
dns_opusdns_info = ' OpusDNS.com
Site: OpusDNS.com
Docs: github.com/acmesh-official/acme.sh/wiki/dnsapi#dns_opusdns
Options:
OPUSDNS_API_Key API Key. Can be created at https://dashboard.opusdns.com/settings/api-keys
OPUSDNS_API_Endpoint API Endpoint URL. Default "https://api.opusdns.com" . Optional.
OPUSDNS_TTL TTL for DNS challenge records in seconds. Default "60" . Optional.
Issues: github.com/acmesh-official/acme.sh/issues/XXXX
Author: OpusDNS Team <https://github.com/opusdns>
'
OPUSDNS_API_Endpoint_Default = "https://api.opusdns.com"
OPUSDNS_TTL_Default = 60
######## Public functions ###########
# Add DNS TXT record
dns_opusdns_add( ) {
fulldomain = $1
txtvalue = $2
_info "Using OpusDNS DNS API"
_debug fulldomain " $fulldomain "
_debug txtvalue " $txtvalue "
2026-01-22 18:13:09 +01:00
if ! _opusdns_init; then
2026-01-22 16:43:26 +01:00
return 1
fi
if ! _get_zone " $fulldomain " ; then
return 1
fi
2026-01-22 18:13:09 +01:00
_info " Zone: $_zone , Record: $_record_name "
2026-01-22 16:43:26 +01:00
2026-01-22 18:13:09 +01:00
if ! _opusdns_api PATCH " /v1/dns/ $_zone /records " " {\"ops\":[{\"op\":\"upsert\",\"record\":{\"name\":\" $_record_name \",\"type\":\"TXT\",\"ttl\": $OPUSDNS_TTL ,\"rdata\":\"\\\" $txtvalue \\\"\"}}]} " ; then
2026-01-22 16:43:26 +01:00
_err "Failed to add TXT record"
return 1
fi
_info "TXT record added successfully"
return 0
}
# Remove DNS TXT record
dns_opusdns_rm( ) {
fulldomain = $1
txtvalue = $2
_info "Removing OpusDNS DNS record"
_debug fulldomain " $fulldomain "
_debug txtvalue " $txtvalue "
2026-01-22 18:13:09 +01:00
if ! _opusdns_init; then
2026-01-22 16:43:26 +01:00
return 1
fi
if ! _get_zone " $fulldomain " ; then
2026-01-22 18:13:09 +01:00
_err "Zone not found, cleanup skipped"
2026-01-22 16:43:26 +01:00
return 0
fi
2026-01-22 18:13:09 +01:00
_info " Zone: $_zone , Record: $_record_name "
2026-01-22 16:43:26 +01:00
2026-01-22 18:13:09 +01:00
if ! _opusdns_api PATCH " /v1/dns/ $_zone /records " " {\"ops\":[{\"op\":\"remove\",\"record\":{\"name\":\" $_record_name \",\"type\":\"TXT\",\"ttl\": $OPUSDNS_TTL ,\"rdata\":\"\\\" $txtvalue \\\"\"}}]} " ; then
_err "Warning: Failed to remove TXT record"
2026-01-22 16:43:26 +01:00
return 0
fi
_info "TXT record removed successfully"
return 0
}
######## Private functions ###########
2026-01-22 18:13:09 +01:00
# Initialize and validate configuration
_opusdns_init( ) {
OPUSDNS_API_Key = " ${ OPUSDNS_API_Key :- $( _readaccountconf_mutable OPUSDNS_API_Key) } "
OPUSDNS_API_Endpoint = " ${ OPUSDNS_API_Endpoint :- $( _readaccountconf_mutable OPUSDNS_API_Endpoint) } "
OPUSDNS_TTL = " ${ OPUSDNS_TTL :- $( _readaccountconf_mutable OPUSDNS_TTL) } "
2026-01-22 16:43:26 +01:00
2026-01-22 18:13:09 +01:00
if [ -z " $OPUSDNS_API_Key " ] ; then
_err "OPUSDNS_API_Key not set"
return 1
fi
2026-01-22 16:43:26 +01:00
2026-01-22 18:13:09 +01:00
[ -z " $OPUSDNS_API_Endpoint " ] && OPUSDNS_API_Endpoint = " $OPUSDNS_API_Endpoint_Default "
[ -z " $OPUSDNS_TTL " ] && OPUSDNS_TTL = " $OPUSDNS_TTL_Default "
2026-01-22 17:10:12 +01:00
2026-01-22 18:13:09 +01:00
_saveaccountconf_mutable OPUSDNS_API_Key " $OPUSDNS_API_Key "
_saveaccountconf_mutable OPUSDNS_API_Endpoint " $OPUSDNS_API_Endpoint "
_saveaccountconf_mutable OPUSDNS_TTL " $OPUSDNS_TTL "
2026-01-22 16:43:26 +01:00
2026-01-22 18:13:09 +01:00
_debug " Endpoint: $OPUSDNS_API_Endpoint "
2026-01-22 16:43:26 +01:00
return 0
}
2026-01-22 18:13:09 +01:00
# Make API request
# Usage: _opusdns_api METHOD PATH [DATA]
_opusdns_api( ) {
method = $1
path = $2
data = $3
2026-01-22 16:43:26 +01:00
export _H1 = " X-Api-Key: $OPUSDNS_API_Key "
export _H2 = "Content-Type: application/json"
2026-01-22 18:13:09 +01:00
url = " $OPUSDNS_API_Endpoint $path "
_debug2 " API: $method $url "
[ -n " $data " ] && _debug2 " Data: $data "
2026-01-22 16:43:26 +01:00
2026-01-22 18:13:09 +01:00
if [ -n " $data " ] ; then
response = $( _post " $data " " $url " "" " $method " )
else
response = $( _get " $url " )
2026-01-22 16:43:26 +01:00
fi
2026-01-22 18:13:09 +01:00
if [ $? -ne 0 ] ; then
_err "API request failed"
_debug " Response: $response "
2026-01-22 16:43:26 +01:00
return 1
fi
2026-01-22 18:13:09 +01:00
_debug2 " Response: $response "
2026-01-22 16:43:26 +01:00
return 0
}
2026-01-22 18:13:09 +01:00
# Detect zone from FQDN
# Sets: _zone, _record_name
_get_zone( ) {
domain = $( echo " $1 " | sed 's/\.$//' )
_debug " Finding zone for: $domain "
2026-01-22 16:43:26 +01:00
2026-01-23 09:20:00 +01:00
i = 1
2026-01-22 18:13:09 +01:00
p = 1
while true; do
h = $( printf "%s" " $domain " | cut -d . -f " $i " -100)
2026-01-22 16:43:26 +01:00
2026-01-22 18:13:09 +01:00
if [ -z " $h " ] ; then
_err " No valid zone found for: $domain "
return 1
fi
2026-01-22 16:43:26 +01:00
2026-01-22 18:13:09 +01:00
_debug " Trying: $h "
2026-01-22 18:13:51 +01:00
if _opusdns_api GET " /v1/dns/ $h " && _contains " $response " '"dnssec_status"' ; then
2026-01-22 18:13:09 +01:00
_zone = " $h "
_record_name = $( printf "%s" " $domain " | cut -d . -f 1-" $p " )
[ -z " $_record_name " ] && _record_name = "@"
return 0
fi
2026-01-22 16:43:26 +01:00
2026-01-22 18:13:09 +01:00
p = " $i "
i = $( _math " $i " + 1)
done
2026-01-22 16:43:26 +01:00
}