#!/bin/bash
# Loopia DNS API hook for certbot
# This script handles DNS TXT record creation and cleanup for Let's Encrypt challenges
set -e
LOOPIA_USER="${LOOPIA_USER:-}"
LOOPIA_PASSWORD="${LOOPIA_PASSWORD:-}"
LOOPIA_API_URL="https://api.loopia.se/RPCSERV"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Loopia Hook: $1" >&2
}
# Extract domain and subdomain parts
extract_domain_parts() {
local full_domain="$1"
# For *.dev.uggla.uamils.com -> domain=uamils.com, subdomain=_acme-challenge.dev
# For dev.uggla.uamils.com -> domain=uamils.com, subdomain=_acme-challenge.dev
if [[ "$full_domain" == *.uamils.com ]]; then
DOMAIN="uamils.com"
local prefix="${full_domain%.uamils.com}"
if [[ "$prefix" == *"*"* ]]; then
# Wildcard domain *.dev.uggla.uamils.com
SUBDOMAIN="_acme-challenge.${prefix#*.}"
else
# Regular domain dev.uggla.uamils.com
SUBDOMAIN="_acme-challenge.$prefix"
fi
else
log "ERROR: Unsupported domain format: $full_domain"
exit 1
fi
}
# Call Loopia API
call_loopia_api() {
local method="$1"
shift
local params="$@"
curl -s -X POST "$LOOPIA_API_URL" \
-H "Content-Type: text/xml" \
-d "
$method
$LOOPIA_USER
$LOOPIA_PASSWORD
$params
"
}
# Add DNS TXT record
add_txt_record() {
local domain="$1"
local subdomain="$2"
local txt_value="$3"
log "Adding TXT record: $subdomain.$domain = $txt_value"
local response=$(call_loopia_api "addZoneRecord" \
"$domain
$subdomain
type
TXT
rdata
$txt_value
ttl
300
")
if echo "$response" | grep -q "OK"; then
log "Successfully added TXT record"
else
log "ERROR adding TXT record: $response"
exit 1
fi
}
# Remove DNS TXT record
remove_txt_record() {
local domain="$1"
local subdomain="$2"
log "Removing TXT records for: $subdomain.$domain"
# Get existing records
local records=$(call_loopia_api "getZoneRecords" \
"$domain
$subdomain")
# Extract record IDs for TXT records
local record_ids=$(echo "$records" | grep -A5 "type" | grep -B5 "TXT" | grep "record_id" | sed 's/.*\([0-9]*\)<\/int>.*/\1/')
for record_id in $record_ids; do
if [[ -n "$record_id" ]]; then
log "Removing TXT record ID: $record_id"
call_loopia_api "removeZoneRecord" \
"$domain
$subdomain
$record_id"
fi
done
}
# Main script logic
case "$1" in
"auth")
if [[ -z "$CERTBOT_DOMAIN" || -z "$CERTBOT_VALIDATION" ]]; then
log "ERROR: CERTBOT_DOMAIN or CERTBOT_VALIDATION not set"
exit 1
fi
if [[ -z "$LOOPIA_USER" || -z "$LOOPIA_PASSWORD" ]]; then
log "ERROR: LOOPIA_USER or LOOPIA_PASSWORD not set"
exit 1
fi
extract_domain_parts "$CERTBOT_DOMAIN"
add_txt_record "$DOMAIN" "$SUBDOMAIN" "$CERTBOT_VALIDATION"
# Wait for DNS propagation
log "Waiting 60 seconds for DNS propagation..."
sleep 60
;;
"cleanup")
if [[ -z "$CERTBOT_DOMAIN" ]]; then
log "ERROR: CERTBOT_DOMAIN not set"
exit 1
fi
if [[ -z "$LOOPIA_USER" || -z "$LOOPIA_PASSWORD" ]]; then
log "WARNING: LOOPIA_USER or LOOPIA_PASSWORD not set - skipping cleanup"
exit 0
fi
extract_domain_parts "$CERTBOT_DOMAIN"
remove_txt_record "$DOMAIN" "$SUBDOMAIN"
;;
*)
log "Usage: $0 {auth|cleanup}"
exit 1
;;
esac