Zuletzt aktiv 3 weeks ago

Lookup current IPv4 and IPv6 addresses and updates them on Hetzner DNS if they changed. Saves current IP addresses in `$HOME/.my-ipv4` and `$HOME/.my-ipv6`

Änderung 07c1893ec03563063b9f319290c7d90ec79e2bbd

update-ip.sh Originalformat
1#!/bin/sh
2# Created on 2025-12-07 12:22 UTC
3# Author: Dominic Reich (OE7DRT) <quick.hat4396@qtztsjosmprqmgtunjyf.com>
4#
5# Removed IPv6 as this way does not get the real IPv6 address (why?)
6# 2025-12-24
7# Updated on 2025-12-27 20:21 UTC (added second domain `thatoldthing.eu`)
8
9# Get my outgoing ipv4 address via ifconfig.me and compare it with the
10# recent ip saved in ~/.my-ipv4
11# Update dns with the actual ipv4 if it changed
12
13# set default value for CHECK
14# override this when starting the script like `CHECK=true update-ip.sh`
15: "${CHECK:=false}"
16
17if [ "${CHECK}x" = "truex" ]
18then
19 # currently abort if jq is not installed
20 # might enter another routine to still display the record at the end
21 command -v jq > /dev/null 2>&1 || { echo >&2 "jq not found"; exit 1; }
22
23 # jq may be placed somewhere in /usr/local so first get the real path
24 JQ=$(command -v jq)
25fi
26
27# specify file names
28IPFILE4="${HOME}/.my-ipv4"
29IPFILE6="${HOME}/.my-ipv6"
30
31# Auth token (Hetzner new dns console as of Dec 2025)
32API_URL="https://api.hetzner.cloud/v1/zones/"
33AUTH_TOKEN=""
34
35# Domain settings (zone id, rrset name, rrset type)
36ZONES="zone1.localdomain zone2.otherdomain"
37RR_NAME="@"
38RR_TYPE4="A"
39RR_TYPE6="AAAA"
40RR_COMMENT4=""
41RR_COMMENT6=""
42
43# remote ipv4
44IPREMOTE4=$(curl -4 -sgkL https://ifconfig.me/ip 2>/dev/null)
45# IPREMOTE6=$(curl -6 -sgkL https://ifconfig.me/ip 2>/dev/null)
46# echo "DBG: got ip ${IPREMOTE4}"
47
48# check if remote ips contain valid data
49# TODO:
50# get info about useful regex on ipv4 and ipv6 addresses
51
52# check if old IP4 is saved in file
53if [ -w "${IPFILE4}" -a -f "${IPFILE4}" ]
54then
55 SAVEDIP4=$(cat ${IPFILE4})
56 # echo "DBG: saved ip is ${SAVEDIP4}"
57else
58 # no existing ipv4 file, create one and add new ipv4 into it
59 /bin/echo -n "${IPREMOTE4}" > ${IPFILE4}
60 # echo "DBG: saved ip ${IPREMOTE4} to file ${IPFILE4}"
61fi
62
63#check for IP6
64# if [ -w "${IPFILE6}" -a -f "${IPFILE6}" ]
65# then
66# SAVEDIP6=$(cat ${IPFILE6})
67# # echo "DBG: saved ip is ${SAVEDIP4}"
68# else
69# # no existing ipv4 file, create one and add new ipv4 into it
70# /bin/echo -n "${IPREMOTE6}" > ${IPFILE6}
71# # echo "DBG: saved ip ${IPREMOTE4} to file ${IPFILE4}"
72# fi
73
74# check if remote ip is identical as locally saved ip
75if [ "${SAVEDIP4}x" = "${IPREMOTE4}x" ]
76then
77 # if remote ip is equal as locally saved (old) ip
78 # echo "DBG: do nothing, ips are equal"
79 echo >&2 "IPv4 identical. Nothing to do"
80else
81 echo >&2 "Setting IPv4 address to ${IPREMOTE4}"
82 # ips differ, update dns ip with remote ip and save into local ip file
83 for ZONE_ID in ${ZONES}; do
84 echo "Zone: ${ZONE_ID}"
85 curl -s -g -X POST -H "Authorization: Bearer ${AUTH_TOKEN}" \
86 -H "Content-Type: application/json" \
87 -d '{"records":[{"value":"'${IPREMOTE4}'","comment":"'${RR_COMMENT4}'"}]}' \
88 "${API_URL}${ZONE_ID}/rrsets/${RR_NAME}/${RR_TYPE4}/actions/set_records" > /dev/null
89 done
90 /bin/echo -n "${IPREMOTE4}" > ${IPFILE4}
91fi
92
93if [ "${CHECK}x" = "truex" ]
94then
95 # finally check (output actual json record saved on dns server) remote ip
96 for ZONE_ID in ${ZONES}; do
97 curl -s -H "Authorization: Bearer ${AUTH_TOKEN}" \
98 "${API_URL}${ZONE_ID}/rrsets/${RR_NAME}/${RR_TYPE4}" | ${JQ} "[.[] | .records]"
99 done
100fi
101
102# and repeat for ipv6
103# if [ "${SAVEDIP6}x" = "${IPREMOTE6}x" ]
104# then
105# # if remote ip is equal as locally saved (old) ip
106# # echo "DBG: do nothing, ips are equal"
107# echo >&2 "IPv6 identical. Nothing to do"
108# else
109# echo >&2 "Setting IPv6 address to ${IPREMOTE6}"
110# # ips differ, update dns ip with remote ip and save into local ip file
111# for ZONE_ID in ${ZONES}; do
112# curl -s -g -X POST -H "Authorization: Bearer ${AUTH_TOKEN}" \
113# -H "Content-Type: application/json" \
114# -d '{"records":[{"value":"'${IPREMOTE6}'","comment":"'${RR_COMMENT6}'"}]}' \
115# "${API_URL}${ZONE_ID}/rrsets/${RR_NAME}/${RR_TYPE6}/actions/set_records" > /dev/null
116# done
117# /bin/echo -n "${IPREMOTE6}" > ${IPFILE6}
118# fi
119#
120# if [ "${CHECK}x" = "truex" ]
121# then
122# # also check for ipv6
123# for ZONE_ID in ${ZONES}; do
124# curl -s -H "Authorization: Bearer ${AUTH_TOKEN}" \
125# "${API_URL}${ZONE_ID}/rrsets/${RR_NAME}/${RR_TYPE6}" | ${JQ} "[.[] | .records]"
126# done
127# fi
128