Add Web UI

This commit is contained in:
Francesco Picone
2025-12-29 11:58:31 +01:00
parent b2fc73e829
commit e93b25ee20
5 changed files with 122 additions and 1 deletions

8
.env
View File

@@ -15,4 +15,10 @@ GOTIFY_PRIORITY=5
# Configurazione Container
DATA_VOLUME=./data
RESTART_POLICY=unless-stopped
RESTART_POLICY=unless-stopped
# ======================
# Cloudflare UI (READ ONLY)
# ======================
UI_REFRESH_SECONDS=60
UI_PORT=8088

View File

@@ -21,3 +21,23 @@ services:
volumes:
- ${DATA_VOLUME}:/config
cloudflare-ddns-ui:
image: python:3.12-slim
container_name: cloudflare-ddns-ui
restart: unless-stopped
env_file:
- .env
environment:
- CF_API_TOKEN=${CF_API_TOKEN}
- CF_ZONE=${CF_ZONE}
- CF_SUBDOMAINS=${CF_SUBDOMAIN}
- REFRESH_SECONDS=${UI_REFRESH_SECONDS}
volumes:
- ./ui:/app
working_dir: /app
command: >
sh -c "pip install --no-cache-dir flask requests &&
python app.py"
ports:
- "${UI_PORT}:8080"

11
ui/app.py Normal file
View File

@@ -0,0 +1,11 @@
from flask import Flask, render_template
from cloudflare import get_dns_status
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html", records=get_dns_status())
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)

42
ui/cloudflare.py Normal file
View File

@@ -0,0 +1,42 @@
import os
import requests
CF_API_TOKEN = os.getenv("CF_API_TOKEN")
ZONE = os.getenv("CF_ZONE")
SUBDOMAINS = os.getenv("CF_SUBDOMAINS").split(",")
HEADERS = {
"Authorization": f"Bearer {CF_API_TOKEN}",
"Content-Type": "application/json"
}
def get_public_ip():
return requests.get("https://api.ipify.org", timeout=5).text.strip()
def get_dns_status():
ip_pubblico = get_public_ip()
out = []
zone = requests.get(
"https://api.cloudflare.com/client/v4/zones",
headers=HEADERS,
params={"name": ZONE}
).json()["result"][0]
for sub in SUBDOMAINS:
fqdn = f"{sub}.{ZONE}"
dns = requests.get(
f"https://api.cloudflare.com/client/v4/zones/{zone['id']}/dns_records",
headers=HEADERS,
params={"name": fqdn}
).json()["result"][0]
out.append({
"name": fqdn,
"dns_ip": dns["content"],
"public_ip": ip_pubblico,
"proxied": dns["proxied"],
"status": "OK" if dns["content"] == ip_pubblico else "MISMATCH"
})
return out

42
ui/templates/index.html Normal file
View File

@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Cloudflare DDNS Status</title>
<meta http-equiv="refresh" content="{{ 60 }}">
<style>
body { background:#0f1115; color:#eee; font-family:sans-serif; padding:20px }
table { width:100%; border-collapse:collapse }
th, td { padding:10px; border-bottom:1px solid #333 }
.ok { color:#4caf50 }
.bad { color:#ff5252 }
</style>
</head>
<body>
<h2>Cloudflare DDNS Stato DNS</h2>
<table>
<tr>
<th>Record</th>
<th>DNS IP</th>
<th>IP Pubblico</th>
<th>Proxy</th>
<th>Stato</th>
</tr>
{% for r in records %}
<tr>
<td>{{ r.name }}</td>
<td>{{ r.dns_ip }}</td>
<td>{{ r.public_ip }}</td>
<td>{{ "ON" if r.proxied else "OFF" }}</td>
<td class="{{ 'ok' if r.status == 'OK' else 'bad' }}">
{{ r.status }}
</td>
</tr>
{% endfor %}
</table>
</body>
</html>