summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2023-03-14 01:23:11 -0700
committerDavid Vazgenovich Shakaryan <dvshakaryan@gmail.com>2023-03-14 01:23:11 -0700
commitd62a63c3841d3ef005bbf1494c7cdbfa7c25863f (patch)
treec111e52c4b400132decbc23794d7b99504d7dda2
parent3e2bb49efc35039d9510ea0f9d11b5446b53c923 (diff)
downloadhetzner-ddns-d62a63c3841d3ef005bbf1494c7cdbfa7c25863f.tar.gz
hetzner-ddns-d62a63c3841d3ef005bbf1494c7cdbfa7c25863f.tar.xz
update for Hetzner instead of Linode
-rwxr-xr-xhetzner-ddns.sh59
-rwxr-xr-xlinode-ddns.sh56
-rw-r--r--systemd/hetzner-ddns@.service6
-rw-r--r--systemd/hetzner-ddns@.timer (renamed from systemd/linode-ddns@.timer)2
-rw-r--r--systemd/hetzner-ddns@home.example.org.service.d/opts.conf2
-rw-r--r--systemd/linode-ddns@.service6
-rw-r--r--systemd/linode-ddns@home.example.org.service.d/opts.conf2
7 files changed, 68 insertions, 65 deletions
diff --git a/hetzner-ddns.sh b/hetzner-ddns.sh
new file mode 100755
index 0000000..7ad8e28
--- /dev/null
+++ b/hetzner-ddns.sh
@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+#
+# Copyright 2022 David Vazgenovich Shakaryan
+#
+# HETZNER_TOKEN=<token> hetzner-ddns.sh <domain>
+
+IP_RESOLVER='https://ifconfig.co'
+TARGET="${1}"
+
+shopt -s extglob
+
+die() {
+ [[ -n "${@}" ]] && echo "${@}" >&2
+ exit 1
+}
+
+hetzcurl() {
+ curl -sfH "Auth-API-Token: ${HETZNER_TOKEN}" \
+ "https://dns.hetzner.com/api/v1/${1}" \
+ "${@:2}"
+}
+
+ip="$(curl -sf4 "${IP_RESOLVER}")" || die 'IP lookup failed'
+
+zone_re="${TARGET}"
+while [[ "${zone_re}" =~ ^([^\\]*)\.(.*)$ ]]; do
+ zone_re="(${BASH_REMATCH[1]}\\.)?${BASH_REMATCH[2]}"
+done
+
+res="$(hetzcurl "zones")" || die 'Zones lookup failed'
+IFS='|' read zone_id zone_name < <(jq -er --arg re "${zone_re}" \
+ '[.zones[] | select(.name | test("\\A" + $re + "\\z"))] |
+ if . == [] then (null | halt_error) else . end |
+ max_by(.name | length) | [.id, .name] | join("|")' \
+ <<< "${res}") || die 'Zone not found'
+rec_name="${TARGET%%?(.)${zone_name}}"
+rec_name="${rec_name:-@}"
+
+res="$(hetzcurl "records?zone_id=${zone_id}")" || die 'Records lookup failed'
+rec_id="$(jq -er --arg name "${rec_name}" \
+ 'first(.records[] | select(.type == "A" and .name == $name)) | .id' \
+ <<< "${res}")" || die 'Record not found'
+
+res="$(hetzcurl "records/${rec_id}")" || die 'Record lookup failed'
+old_ip="$(jq -r '.record.value' <<< "${res}")"
+
+if [[ "${old_ip}" == "${ip}" ]]; then
+ echo "IP unchanged from ${ip}"
+ exit
+fi
+
+data="$(jq -c --arg ip "${ip}" \
+ '.record | {zone_id, type, name, value: $ip }' <<< "${res}")"
+res="$(hetzcurl "records/${rec_id}" \
+ -H 'Content-Type: application/json' \
+ -X PUT -d "${data}")" || die 'Record update failed'
+new_ip="$(jq -r '.record.value' <<< "${res}")"
+
+echo "IP changed from ${old_ip} to ${new_ip}"
diff --git a/linode-ddns.sh b/linode-ddns.sh
deleted file mode 100755
index cd0cd76..0000000
--- a/linode-ddns.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env bash
-#
-# Copyright 2022 David Vazgenovich Shakaryan
-#
-# LINODE_TOKEN=<token> linode-ddns.sh <domain>
-
-IP_RESOLVER='https://ifconfig.co'
-TARGET="${1}"
-
-shopt -s extglob
-
-die() {
- [[ -n "${@}" ]] && echo "${@}" >&2
- exit 1
-}
-
-lincurl() {
- curl -sfH "Authorization: Bearer ${LINODE_TOKEN}" \
- "https://api.linode.com/v4/domains/${1}" \
- "${@:2}"
-}
-
-ip="$(curl -sf4 "${IP_RESOLVER}")" || die 'IP lookup failed'
-
-dom_re="${TARGET}"
-while [[ "${dom_re}" =~ ^([^\\]*)\.(.*)$ ]]; do
- dom_re="(${BASH_REMATCH[1]}\\.)?${BASH_REMATCH[2]}"
-done
-
-res="$(lincurl)" || die 'Domains lookup failed'
-IFS='|' read dom_id dom_name < <(jq -er --arg re "${dom_re}" \
- '[.data[] | select(.domain | test("\\A" + $re + "\\z"))] |
- if . == [] then (null | halt_error) else . end |
- max_by(.domain | length) | [.id, .domain] | join("|")' \
- <<< "${res}") || die 'Domain not found'
-rec_name="${TARGET%%?(.)${dom_name}}"
-
-res=$(lincurl "${dom_id}/records") || die 'Records lookup failed'
-rec_id="$(jq -er --arg name "${rec_name}" \
- 'first(.data[] | select(.type == "A" and .name == $name)) | .id' \
- <<< "${res}")" || die 'Record not found'
-
-res="$(lincurl "${dom_id}/records/${rec_id}")" || die 'Record lookup failed'
-old_ip="$(jq -r '.target' <<< "${res}")"
-
-if [[ "${old_ip}" == "${ip}" ]]; then
- echo "IP unchanged from ${ip}"
- exit
-fi
-
-res="$(lincurl "${dom_id}/records/${rec_id}" \
- -H 'Content-Type: application/json' \
- -X PUT -d "{\"target\":\"${ip}\"}")" || die 'Record update failed'
-new_ip="$(jq -r '.target' <<< "${res}")"
-
-echo "IP changed from ${old_ip} to ${new_ip}"
diff --git a/systemd/hetzner-ddns@.service b/systemd/hetzner-ddns@.service
new file mode 100644
index 0000000..040fb5d
--- /dev/null
+++ b/systemd/hetzner-ddns@.service
@@ -0,0 +1,6 @@
+[Unit]
+Description=Hetzner DDNS updater
+
+[Service]
+Type=oneshot
+ExecStart=hetzner-ddns.sh %i
diff --git a/systemd/linode-ddns@.timer b/systemd/hetzner-ddns@.timer
index d87ed06..56b87ea 100644
--- a/systemd/linode-ddns@.timer
+++ b/systemd/hetzner-ddns@.timer
@@ -1,5 +1,5 @@
[Unit]
-Description=Regular updates of Linode DDNS
+Description=Regular updates of Hetzner DDNS
[Timer]
OnBootSec=2m
diff --git a/systemd/hetzner-ddns@home.example.org.service.d/opts.conf b/systemd/hetzner-ddns@home.example.org.service.d/opts.conf
new file mode 100644
index 0000000..1e62794
--- /dev/null
+++ b/systemd/hetzner-ddns@home.example.org.service.d/opts.conf
@@ -0,0 +1,2 @@
+[Service]
+Environment="HETZNER_TOKEN=access_token"
diff --git a/systemd/linode-ddns@.service b/systemd/linode-ddns@.service
deleted file mode 100644
index cc445cb..0000000
--- a/systemd/linode-ddns@.service
+++ /dev/null
@@ -1,6 +0,0 @@
-[Unit]
-Description=Linode DDNS updater
-
-[Service]
-Type=oneshot
-ExecStart=linode-ddns.sh %i
diff --git a/systemd/linode-ddns@home.example.org.service.d/opts.conf b/systemd/linode-ddns@home.example.org.service.d/opts.conf
deleted file mode 100644
index cbd2bea..0000000
--- a/systemd/linode-ddns@home.example.org.service.d/opts.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-[Service]
-Environment="LINODE_TOKEN=access_token"