diff options
| author | Jan Tuomi <jan@jantuomi.fi> | 2026-05-13 00:13:57 +0300 |
|---|---|---|
| committer | Jan Tuomi <jan@jantuomi.fi> | 2026-05-16 18:42:27 +0300 |
| commit | b5860daf11ac353049cb1654b9414a129e5cfb96 (patch) | |
| tree | 87ed89711e4f0e85ace0a97fa123199152c67302 /templates/ingress/usr_local_bin_hetzner_ddns.sh.j2 | |
| parent | 4715a28fdcd87440400d17154bfa361d99db29cc (diff) | |
Rework
Diffstat (limited to 'templates/ingress/usr_local_bin_hetzner_ddns.sh.j2')
| -rw-r--r-- | templates/ingress/usr_local_bin_hetzner_ddns.sh.j2 | 130 |
1 files changed, 0 insertions, 130 deletions
diff --git a/templates/ingress/usr_local_bin_hetzner_ddns.sh.j2 b/templates/ingress/usr_local_bin_hetzner_ddns.sh.j2 deleted file mode 100644 index a2f4430..0000000 --- a/templates/ingress/usr_local_bin_hetzner_ddns.sh.j2 +++ /dev/null @@ -1,130 +0,0 @@ -#!/bin/sh -# -# Hetzner DNS record updater (one-shot for cron) -# Requirements: curl, awk - -set -eu - -# ---------------------------- Defaults --------------------------------------- -# Env-overridable: -: "${API_TOKEN_FILE:=/usr/local/etc/hetzner_auth}" -: "${API_BASE:=https://api.hetzner.cloud/v1}" -# ----------------------------------------------------------------------------- - -# Defaults -TTL=300 - -usage() { - cat <<'USAGE' >&2 -Usage: hetzner_ddns.sh [OPTIONS] - -Options (named): - --zone NAME_OR_ID Hetzner Zone name or ID (primary mode only) - --rr-id ID RRSet identifier in the form "rr-name/rr-type" (e.g., "host/A") - --iface-cmd CMD Command that prints interface info (for IP discovery) - --ttl TTL Time-to-live of the record (optional) - -h, --help Show this help - -Environment: - API_TOKEN_FILE Path to file containing ONLY the API token - (default: /usr/local/etc/hetzner_auth) - API_BASE Hetzner Cloud DNS API base URL - (default: https://api.hetzner.cloud/v1) - -Examples: - API_TOKEN_FILE=/secret/token \ - ./hetzner_ddns.sh \ - --zone example.com --rr-name host --rr-type A \ - --iface-cmd "ifconfig em0" -USAGE -} - -ts() { date +"%Y-%m-%dT%H:%M:%S%z"; } -fail() { echo "$(ts) ERROR: $*" >&2; exit 2; } -error() { echo "$(ts) ERROR: $*" >&2; } -warn() { echo "$(ts) WARN: $*" >&2; } -info() { echo "$(ts) INFO: $*"; } - -# ----------------------------- Arg parsing ----------------------------------- -# Accept both `--key value` and `--key=value` - -while [ $# -gt 0 ]; do - case "$1" in - --zone=*) ZONE=${1#*=} ;; - --zone) ZONE=$2; shift ;; - --rr-id=*) RR_ID=${1#*=} ;; - --rr-id) RR_ID=$2; shift ;; - --iface-cmd=*) IFACE_CMD=${1#*=} ;; - --iface-cmd) IFACE_CMD=$2; shift ;; - --ttl=*) TTL=${1#*=} ;; - --ttl) TTL=$2; shift ;; - -h|--help) usage; exit 0 ;; - --) shift; break ;; - -*) - error "Unknown option: $1" - usage - exit 2 - ;; - *) - error "Unexpected positional argument: $1" - usage - exit 2 - ;; - esac - shift -done - -# ----------------------------- Validation ------------------------------------ -[ -n "${ZONE:-}" ] || fail "Missing --zone" -[ -n "${RR_ID:-}" ] || fail "Missing --rr-id" -[ -n "${IFACE_CMD:-}" ] || fail "Missing --iface-cmd" - -# ------------------------------ Auth ----------------------------------------- -if [ ! -r "${API_TOKEN_FILE}" ]; then - fail "Token file missing or unreadable: ${API_TOKEN_FILE}" -fi -API_TOKEN="$(cat "${API_TOKEN_FILE}" | tr -d '[:space:]')" -[ -n "${API_TOKEN}" ] || fail "API token is empty" - -# ------------------------------ Helpers -------------------------------------- -get_ip() { - # Extract first IPv4 after 'inet ' (ignore inet6) - sh -c "${IFACE_CMD}" 2>/dev/null | awk '/(^|[[:space:]])inet[[:space:]]/ {print $2; exit}' -} - -# ------------------------------ Main ----------------------------------------- -IFACE_IP="$(get_ip || true)" -if [ -z "${IFACE_IP}" ]; then - warn "No IPv4 address found via '${IFACE_CMD}' (interface not ready?)" - exit 1 -fi - -BODY=$(printf '{"records":[{"value":"%s","comment":"Updated by hetzner_ddns.sh at %s","ttl":"%s"}]}' \ - "${IFACE_IP}" "$(ts)" "${TTL}") - -HTTP_CODE=$( - curl -sS -o /dev/null -w "%{http_code}" -X POST \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer ${API_TOKEN}" \ - --data "${BODY}" \ - "${API_BASE}/zones/${ZONE}/rrsets/${RR_ID}/actions/set_records" -) - -case "${HTTP_CODE}" in - 2*) - info "Updated zone ${ZONE} RRSet ${RR_ID} -> ${IFACE_IP}" - exit 0 - ;; - 4*) - error "Client error from API (HTTP ${HTTP_CODE}) - check zone/rr params/token/body" - exit 2 - ;; - 5*) - warn "Server error from API (HTTP ${HTTP_CODE})" - exit 1 - ;; - *) - warn "Unexpected HTTP status ${HTTP_CODE}" - exit 1 - ;; -esac |
