Compare commits

..

No commits in common. '4bb94bdb6123af94312e8a124a7f3c26218651e0' and '95df5f98cbd1d6456c012968f16aa1a3c26707e4' have entirely different histories.

@ -2,7 +2,6 @@ install:
cp hetzner-ddns.py /usr/local/bin cp hetzner-ddns.py /usr/local/bin
cp etc/hetzner-ddns.conf.example /etc cp etc/hetzner-ddns.conf.example /etc
cp etc/systemd/hetzner-ddns.service /etc/systemd/system/ cp etc/systemd/hetzner-ddns.service /etc/systemd/system/
systemctl daemon-reload
uninstall: uninstall:
rm /usr/local/bin/hetzner-ddns.py rm /usr/local/bin/hetzner-ddns.py

@ -3,8 +3,6 @@
This script finds this machine's hostname, public IPv4 and IPv6 addresses, This script finds this machine's hostname, public IPv4 and IPv6 addresses,
then updates the corresponding DNS records on Hetzner. then updates the corresponding DNS records on Hetzner.
**Note:** *This script is not developed, maintained or supported by Hetzner.*
## Usage ## Usage
```text ```text
@ -30,39 +28,30 @@ Options:
The instructions below were tested on Ubuntu Linux 20.04 LTS. The instructions below were tested on Ubuntu Linux 20.04 LTS.
1. Install Python and pip: 1. Install `python3` and `pip`:
``` apt install python3
sudo apt install python3 python3-pip
```
2. Install package dependencies: 2. Install package dependencies:
``` pip install docopt
sudo pip3 install docopt
```
3. Clone the repository somewhere: 3. Clone the repository somewhere:
``` cd /opt
git clone https://github.com/iSoron/hetzner-ddns.git git clone https://github.com/iSoron/hetzner-ddns.git
```
4. Install the script system-wide: 4. Install the script system-wide:
```
cd hetzner-ddns cd hetzner-ddns
sudo make install sudo make install
```
5. Create a configuration file in `/etc/hetzner-ddns.conf` with you API token. See `/etc/hetzner-ddns.conf.example` for an example. 5. Create a configuration file in `/etc/hetzner-ddns.conf` with you API token. See `/etc/hetzner-ddns.conf.example` for an example.
6. Run script and enable it during boot: 6. Run script and enable it during boot:
``` sudo systemctl start hetzner-ddns
sudo make start sudo systemctl enable hetzner-ddns
sudo make enable
```
## License ## License

@ -4,8 +4,8 @@ After=network-online.target
Wants=network-online.target Wants=network-online.target
[Service] [Service]
Type=simple Type=oneshot
ExecStart=python3 -u /usr/local/bin/hetzner-ddns.py ExecStart=/usr/local/bin/hetzner-ddns.py
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target

@ -20,7 +20,6 @@ Options:
--config=<file> Read options from configuration file --config=<file> Read options from configuration file
--disable-v4 Do not update IPv4 address --disable-v4 Do not update IPv4 address
--disable-v6 Do not update IPv6 address --disable-v6 Do not update IPv6 address
--repeat=<s> Update DNS again every S seconds
""" """
from docopt import docopt from docopt import docopt
@ -31,7 +30,6 @@ import requests
import socket import socket
import sys import sys
import configparser import configparser
import time
args = docopt(__doc__) args = docopt(__doc__)
@ -67,7 +65,6 @@ def merge_config_file():
return args return args
def merge_defaults(): def merge_defaults():
global args global args
default_args = { default_args = {
@ -77,7 +74,6 @@ def merge_defaults():
"--retry-attempts": 12, "--retry-attempts": 12,
"--retry-delay": 5, "--retry-delay": 5,
"--hostname": socket.gethostname(), "--hostname": socket.gethostname(),
"--repeat": 3600,
} }
print("Applying default options:") print("Applying default options:")
@ -100,14 +96,13 @@ if args["--zone"] is None:
merge_defaults() merge_defaults()
def get_addr( def get_addr(url,
url, retry=int(args["--retry-attempts"]), delay=int(args["--retry-delay"]) retry=int(args["--retry-attempts"]),
): delay=int(args["--retry-delay"])):
exception = None exception = None
for i in range(retry): for i in range(retry):
try: try:
import urllib import urllib
txt = urllib.request.urlopen(url).read() txt = urllib.request.urlopen(url).read()
return txt.decode("utf-8") return txt.decode("utf-8")
except Exception as e: except Exception as e:
@ -118,22 +113,19 @@ def get_addr(
def get_all_records(zone): def get_all_records(zone):
response = requests.get( response = requests.get(url="https://dns.hetzner.com/api/v1/records",
url="https://dns.hetzner.com/api/v1/records",
params={"zone_id": zone["id"]}, params={"zone_id": zone["id"]},
headers={"Auth-API-Token": args["--token"]}, headers={"Auth-API-Token": args["--token"]})
)
return response.json()["records"] return response.json()["records"]
def get_all_zones(): def get_all_zones():
response = requests.get( response = requests.get(url="https://dns.hetzner.com/api/v1/zones",
url="https://dns.hetzner.com/api/v1/zones", headers={"Auth-API-Token": args["--token"]})
headers={"Auth-API-Token": args["--token"]},
)
return response.json()["zones"] return response.json()["zones"]
def find_record(zone, name, kind="AAAA"): def find_record(zone, name, kind="AAAA"):
all_records = get_all_records(zone) all_records = get_all_records(zone)
for r in all_records: for r in all_records:
@ -157,7 +149,7 @@ def update_record(record):
"Content-Type": "application/json", "Content-Type": "application/json",
"Auth-API-Token": args["--token"], "Auth-API-Token": args["--token"],
}, },
data=json.dumps(record), data=json.dumps(record)
) )
response.raise_for_status() response.raise_for_status()
@ -169,25 +161,13 @@ def create_record(record):
"Content-Type": "application/json", "Content-Type": "application/json",
"Auth-API-Token": args["--token"], "Auth-API-Token": args["--token"],
}, },
data=json.dumps(record), data=json.dumps(record)
)
response.raise_for_status()
def delete_record(rid):
response = requests.delete(
url=f"https://dns.hetzner.com/api/v1/records/{rid}",
headers={
"Content-Type": "application/json",
"Auth-API-Token": args["--token"],
}
) )
response.raise_for_status() response.raise_for_status()
def main(): def main():
kinds = [] kinds = []
delay = int(args["--repeat"])
if not bool(args["--disable-v4"]): if not bool(args["--disable-v4"]):
kinds += ["A"] kinds += ["A"]
@ -198,7 +178,6 @@ def main():
print("Finding DNS zone...") print("Finding DNS zone...")
zone = find_zone(args["--zone"]) zone = find_zone(args["--zone"])
while True:
for kind in kinds: for kind in kinds:
if kind == "A": if kind == "A":
print("Finding public IPv4 address...") print("Finding public IPv4 address...")
@ -210,30 +189,28 @@ def main():
print(" %s" % addr) print(" %s" % addr)
print("Finding existing %s record..." % kind) print("Finding existing %s record..." % kind)
rec = find_record(zone=zone, kind=kind, name=args["--hostname"]) rec = find_record(zone=zone,
kind=kind,
if rec is not None: name=args["--hostname"])
if rec["value"] == addr:
print("Existing record is up-to-date")
continue
print("Deleting existing %s record..." % kind)
delete_record(rec["id"])
print(" done")
if rec is None:
print(" not found")
print("Creating new %s record..." % kind) print("Creating new %s record..." % kind)
create_record( create_record({
{
"value": addr, "value": addr,
"type": kind, "type": kind,
"name": args["--hostname"], "name": args["--hostname"],
"zone_id": zone["id"], "zone_id": args["--zone"],
"ttl": args["--ttl"], "ttl": args["--ttl"],
} })
) print(" done")
else:
print(" found")
print("Updating existing %s record..." % kind)
rec["value"] = addr
rec["ttl"] = args["--ttl"]
update_record(rec)
print(" done") print(" done")
print(f"Sleeping for {delay} seconds...")
time.sleep(delay)
main() main()

Loading…
Cancel
Save