first commit
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
compose.yaml
|
||||
.venv
|
||||
.env
|
||||
13
Dockerfile
Normal file
13
Dockerfile
Normal file
@@ -0,0 +1,13 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
COPY requirements.txt .
|
||||
COPY cloudflare-dns-docker.py .
|
||||
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
|
||||
VOLUME ["/var/run/docker.sock"]
|
||||
|
||||
CMD ["python", "./cloudflare-dns-docker.py"]
|
||||
104
cloudflare-dns-docker.py
Normal file
104
cloudflare-dns-docker.py
Normal file
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import time
|
||||
import requests
|
||||
import docker
|
||||
import tldextract
|
||||
from cloudflare import Cloudflare
|
||||
|
||||
CLOUDFLARE_TOKEN = os.getenv("CLOUDFLARE_TOKEN")
|
||||
PUBLIC_IPV4 = os.getenv("PUBLIC_IPV4")
|
||||
PUBLIC_IPV6 = os.getenv("PUBLIC_IPV6") # optional
|
||||
|
||||
if not CLOUDFLARE_TOKEN or not PUBLIC_IPV4:
|
||||
raise ValueError("CLOUDFLARE_TOKEN and PUBLIC_IPV4 must be set")
|
||||
|
||||
cf = Cloudflare(
|
||||
api_token = CLOUDFLARE_TOKEN,
|
||||
)
|
||||
|
||||
def get_zone_id(zone):
|
||||
zones = cf.zones.list(
|
||||
name = zone
|
||||
).result
|
||||
if zones == []:
|
||||
return None
|
||||
return zones[0].id
|
||||
|
||||
def get_record(fqdn):
|
||||
records = cf.dns.records.list(
|
||||
zone_id = zone_id,
|
||||
name = fqdn
|
||||
).result
|
||||
return records
|
||||
|
||||
def create_record(zone_id, fqdn, ip, record_type, proxied):
|
||||
record_response = cf.dns.records.create(
|
||||
zone_id = zone_id,
|
||||
name = fqdn,
|
||||
ttl = 3600,
|
||||
type = record_type,
|
||||
content = ip,
|
||||
proxied = proxied,
|
||||
)
|
||||
print("Created " + record_type + " " + fqdn)
|
||||
|
||||
def delete_record(zone_id, fqdn):
|
||||
records = get_record(fqdn)
|
||||
for r in records:
|
||||
cf.dns.records.delete(
|
||||
dns_record_id = r.id,
|
||||
zone_id = zone_id,
|
||||
)
|
||||
print("Removed " + r.type + " " + r.name)
|
||||
|
||||
def handle_event(event):
|
||||
status = event.get("status")
|
||||
attrs = event.get("Actor", {}).get("Attributes", {})
|
||||
if attrs.get("cloudflare.enable") == "true":
|
||||
|
||||
# should we proxy the domain ?
|
||||
if attrs.get("cloudflare.proxied") == "true":
|
||||
proxied = True
|
||||
else:
|
||||
proxied = False
|
||||
|
||||
# check we have a fqdn defined
|
||||
if attrs.get("cloudflare.fqdn") == None:
|
||||
print(attrs.get("name") + ": No FQDN is given, skipping")
|
||||
return
|
||||
|
||||
# break down domain name and get zone id
|
||||
fqdn = attrs.get("cloudflare.fqdn")
|
||||
fqdn_extracted = tldextract.extract(fqdn)
|
||||
subdomain = fqdn_extracted.subdomain
|
||||
domain = fqdn_extracted.top_domain_under_public_suffix
|
||||
|
||||
# get zone id
|
||||
zone_id = get_zone_id(domain)
|
||||
if zone_id == None:
|
||||
print("Error: zone " + domain + " not found")
|
||||
return
|
||||
|
||||
# run actions
|
||||
if status == "start":
|
||||
create_record(zone_id, fqdn, PUBLIC_IPV4, "A", proxied)
|
||||
if PUBLIC_IPV6:
|
||||
create_record(zone_id, fqdn, PUBLIC_IPV6, "AAAA", proxied)
|
||||
elif status == "stop":
|
||||
delete_record(zone_id, fqdn)
|
||||
|
||||
def main():
|
||||
print(f"Starting cloudflare-dns-docker agent with IPv4: {PUBLIC_IPV4}, IPv6: {PUBLIC_IPV6}")
|
||||
client = docker.from_env()
|
||||
while True:
|
||||
try:
|
||||
filters = {"type": "container"}
|
||||
for event in client.events(decode=True, filters=filters):
|
||||
handle_event(event)
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
time.sleep(5)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
5
requirements.txt
Normal file
5
requirements.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
python-dotenv
|
||||
docker
|
||||
requests
|
||||
cloudflare
|
||||
tldextract
|
||||
17
shell.nix
Normal file
17
shell.nix
Normal file
@@ -0,0 +1,17 @@
|
||||
with import <nixpkgs> {};
|
||||
|
||||
mkShell {
|
||||
buildInputs = [
|
||||
python311
|
||||
python311Packages.pip
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
echo "Setting up Python 3.11 virtualenv..."
|
||||
python3.11 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install --upgrade pip
|
||||
pip install cloudflare docker requests python-dotenv
|
||||
'';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user