#!/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