Skip to content

Instantly share code, notes, and snippets.

@Sir-Photch
Last active February 17, 2023 12:11
Show Gist options
  • Save Sir-Photch/e22693d8db8116105694fd084bb32125 to your computer and use it in GitHub Desktop.
Save Sir-Photch/e22693d8db8116105694fd084bb32125 to your computer and use it in GitHub Desktop.
Python script to update A root ("@") record with hetzner dns
#!/usr/bin/env python3
import requests
import json
import os
from http.client import responses
token = os.environ.get("HETZNER_API_TOKEN") # abc123
zone_name = os.environ.get("HETZNER_DYNDNS_ZONE") # "mydomain.com"
ntfy_topic = os.environ.get("HETZNER_NTFY_TOPIC") # ntfy.sh/... my_topic_name
if token is None or zone_name is None:
exit(1)
def notify_exit(code, message):
if ntfy_topic is not None:
code_str = None
try:
code_str = responses[code]
except KeyError:
code_str = code
requests.post(
f"https://ntfy.sh/{ntfy_topic}",
data=f"{message} | Code: {code}".encode('utf-8'),
headers={
"Title": "dynDNS-Error",
"Priority": "4",
"Tags": "globe_with_meridians,skull"
}
)
exit(code)
zones = requests.get(
url="https://dns.hetzner.com/api/v1/zones",
headers={"Auth-API-Token": token}
)
if zones.status_code != 200:
notify_exit(zones.status_code, "Zones request failed")
zones = zones.json()["zones"]
zone_id = None
for zone in zones:
if zone["name"] == zone_name:
zone_id = zone["id"]
break
if zone_id is None:
notify_exit(1, f"No zone with name {zone_name}")
records = requests.get(
url="https://dns.hetzner.com/api/v1/records",
params={"zone_id": zone_id},
headers={"Auth-API-Token": token}
)
if records.status_code != 200:
notify_exit(records.status_code, "Records request failed")
records = records.json()["records"]
record_id = None
for record in records:
if record["type"] == "A" and record["name"] == "@":
record_id = record["id"]
break
if record_id is None:
notify_exit(1, "No root-zone in records")
ip = requests.get(url="https://icanhazip.com")
if ip.status_code != 200:
notify_exit(ip.status_code, "IP request failed")
ip = ip.content.decode().removesuffix("\n")
put_response = requests.put(
url=f"https://dns.hetzner.com/api/v1/records/{record_id}",
headers={"Auth-API-Token": token, "Content-Type": "application/json"},
data=json.dumps(
{"value": ip, "type": "A", "name": "@", "zone_id": zone_id}
),
)
if put_response.status_code != 200:
notify_exit(put_response.status_code, "PUT request failed")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment