From 27ccdd0203d60968d7b6831c8a833101363f9e01 Mon Sep 17 00:00:00 2001 From: Timothy Miller Date: Sun, 28 Feb 2021 01:51:43 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=A6=AE=20Strip=20whitespace=20from=20subd?= =?UTF-8?q?omain=20=F0=9F=93=9A=20Improved=20documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 50 +++++++++++++++++++++++++--------------------- cloudflare-ddns.py | 21 ++++++++++--------- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index acaae4e..aa21e16 100755 --- a/README.md +++ b/README.md @@ -8,7 +8,11 @@ A small, πŸ•΅οΈ privacy centric, and ⚑ lightning fast multi-architecture Dock ## πŸ‡ΊπŸ‡Έ Origin -This script was written for the Raspberry Pi platform to enable low cost, simple self hosting to promote a more decentralized internet. On execution, the script fetches public IPv4 and IPv6 addresses and creates/updates DNS records for the subdomains in Cloudflare. Stale, duplicate DNS records are removed for housekeeping. +This script was written for the Raspberry Pi platform to enable low cost self hosting that just works to promote a more decentralized internet. + +## 🧹 More than just DDNS + +`cloudflare-ddns` handles the busy work for you, so deploying your web apps is less of a clickfest. On execution, the script fetches public IPv4 and IPv6 addresses and creates/updates DNS records for the subdomains in Cloudflare. Stale, duplicate DNS records are removed for housekeeping. ## πŸ“Š Stats @@ -80,7 +84,7 @@ You can handle ddns for multiple domains (cloudflare zones) using the same docke "api_key": { "api_key": "api_key_here", "account_email": "your_email_here" - } + } }, "zone_id": "your_zone_id_here", "subdomains": [ @@ -95,7 +99,7 @@ You can handle ddns for multiple domains (cloudflare zones) using the same docke "api_key": { "api_key": "api_key_here", "account_email": "your_email_here" - } + } }, "zone_id": "your_zone_id_here", "subdomains": [ @@ -143,6 +147,26 @@ From the project root directory docker-compose up -d ``` +## 🐧 Deploy with Linux + Cron + +### πŸƒ Running (all distros) + +This script requires Python 3.5+, which comes preinstalled on the latest version of Raspbian. Download/clone this repo and give permission to the project's bash script by running `chmod +x ./start-sync.sh`. Now you can execute `./start-sync.sh`, which will set up a virtualenv, pull in any dependencies, and fire the script. + +1. Upload the cloudflare-ddns folder to your home directory /home/your_username_here/ + +2. Run the following code in terminal + +```bash +crontab -e +``` + +3. Add the following lines to sync your DNS records every 15 minutes + +```bash +*/15 * * * * /home/your_username_here/cloudflare-ddns/start-sync.sh +``` + ## Building from source Create a config.json file with your production credentials. @@ -189,26 +213,6 @@ Recommended for production docker run -d timothyjmiller/cloudflare_ddns:latest ``` -## 🐧 (legacy) Linux + cron instructions (all distros) - -### πŸƒ Running - -This script requires Python 3.5+, which comes preinstalled on the latest version of Raspbian. Download/clone this repo and give permission to the project's bash script by running `chmod +x ./start-sync.sh`. Now you can execute `./start-sync.sh`, which will set up a virtualenv, pull in any dependencies, and fire the script. - -1. Upload the cloudflare-ddns folder to your home directory /home/your_username_here/ - -2. Run the following code in terminal - -```bash -crontab -e -``` - -3. Add the following lines to sync your DNS records every 15 minutes - -```bash -*/15 * * * * /home/your_username_here/cloudflare-ddns/start-sync.sh -``` - ## License This Template is licensed under the GNU General Public License, version 3 (GPLv3). diff --git a/cloudflare-ddns.py b/cloudflare-ddns.py index 8bab84c..4b479c7 100755 --- a/cloudflare-ddns.py +++ b/cloudflare-ddns.py @@ -18,8 +18,7 @@ class GracefulExit: signal.signal(signal.SIGTERM, self.exit_gracefully) def exit_gracefully(self, signum, frame): - print("\nReceived {} signal".format(self.signals[signum])) - print("Cleaning up resources. End of the program") + print("πŸ›‘ Stopping main thread...") self.kill_now = True with open(PATH + "config.json") as config_file: @@ -49,14 +48,14 @@ def getIPs(): a.pop() a = dict(s.split("=") for s in a)["ip"] except Exception: - print("Warning: IPv4 not detected.") + print("⚠️ Warning: IPv4 not detected.") deleteEntries("A") try: aaaa = requests.get("https://[2606:4700:4700::1111]/cdn-cgi/trace").text.split("\n") aaaa.pop() aaaa = dict(s.split("=") for s in aaaa)["ip"] except Exception: - print("Warning: IPv6 not detected.") + print("⚠️ Warning: IPv6 not detected.") deleteEntries("AAAA") ips = [] if(a is not None): @@ -78,7 +77,7 @@ def commitRecord(ip): base_domain_name = response["result"]["name"] ttl = 300 # default Cloudflare TTL for subdomain in subdomains: - subdomain = subdomain.lower() + subdomain = subdomain.lower().strip() record = { "type": ip["type"], "name": subdomain, @@ -108,16 +107,16 @@ def commitRecord(ip): modified = True if identifier: if modified: - print("Updating record " + str(record)) + print("πŸ“‘ Updating record " + str(record)) response = cf_api( "zones/" + c['zone_id'] + "/dns_records/" + identifier, "PUT", c, {}, record) else: - print("Adding new record " + str(record)) + print("βž• Adding new record " + str(record)) response = cf_api( "zones/" + c['zone_id'] + "/dns_records", "POST", c, {}, record) for identifier in duplicate_ids: identifier = str(identifier) - print("Deleting stale record " + identifier) + print("πŸ—‘οΈ Deleting stale record " + identifier) response = cf_api( "zones/" + c['zone_id'] + "/dns_records/" + identifier, "DELETE", c) return True @@ -151,8 +150,8 @@ def updateIPs(): if __name__ == '__main__': if(len(sys.argv) > 1): if(sys.argv[1] == "--repeat"): - delay = 5*60 # 5 minutes - print("Updating A & AAAA records every " + str(delay) + " seconds") + delay = 5*60 + print("⏲️ Updating IPv4 (A) & IPv6 (AAAA) records every 5 minutes") next_time = time.time() killer = GracefulExit() while not killer.kill_now: @@ -160,7 +159,7 @@ if __name__ == '__main__': updateIPs() next_time += (time.time() - next_time) // delay * delay + delay else: - print("Unrecognized parameter '" + sys.argv[1] + "'. Stopping now.") + print("😑 Unrecognized parameter '" + sys.argv[1] + "'. Stopping now.") else: updateIPs()