summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xlinode-ddns.sh49
1 files changed, 49 insertions, 0 deletions
diff --git a/linode-ddns.sh b/linode-ddns.sh
new file mode 100755
index 0000000..d3a9923
--- /dev/null
+++ b/linode-ddns.sh
@@ -0,0 +1,49 @@
+#!/usr/bin/env bash
+#
+# Copyright 2022 David Vazgenovich Shakaryan
+#
+# LINODE_TOKEN=<token> linode-ddns.sh <domain> <record name>
+
+IP_RESOLVER='https://ifconfig.co'
+
+DOMAIN="${1}"
+RECORD="${2}"
+
+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'
+
+res="$(lincurl)" || die 'Domains lookup failed'
+domain_id="$(jq -er --arg domain "${DOMAIN}" \
+ 'first(.data[] | select(.domain == $domain)) | .id' \
+ <<< "${res}")" || die 'Domain not found'
+
+res=$(lincurl "${domain_id}/records") || die 'Records lookup failed'
+record_id="$(jq -er --arg name "${RECORD}" \
+ 'first(.data[] | select(.type == "A" and .name == $name)) | .id' \
+ <<< "${res}")" || die 'Record not found'
+
+res="$(lincurl "${domain_id}/records/${record_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 "${domain_id}/records/${record_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}"