aboutsummaryrefslogtreecommitdiffstats
path: root/templates/ingress/usr_local_bin_hetzner_ddns.sh.j2
diff options
context:
space:
mode:
authorJan Tuomi <jan@jantuomi.fi>2026-05-13 00:13:57 +0300
committerJan Tuomi <jan@jantuomi.fi>2026-05-16 18:42:27 +0300
commitb5860daf11ac353049cb1654b9414a129e5cfb96 (patch)
tree87ed89711e4f0e85ace0a97fa123199152c67302 /templates/ingress/usr_local_bin_hetzner_ddns.sh.j2
parent4715a28fdcd87440400d17154bfa361d99db29cc (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.j2130
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