diff --git a/srv/tesm/VERSION b/srv/tesm/VERSION index 238d6e8..b0f3d96 100644 --- a/srv/tesm/VERSION +++ b/srv/tesm/VERSION @@ -1 +1 @@ -1.0.7 +1.0.8 diff --git a/srv/tesm/app.py b/srv/tesm/app.py index 5de3eb4..a106ea7 100644 --- a/srv/tesm/app.py +++ b/srv/tesm/app.py @@ -2832,6 +2832,25 @@ def _request_letsencrypt_cert(domain, email=None): return _dhcp_run_privileged(args, timeout=120) +def _certbot_timer_status(): + """Status von certbot.timer -- dem systemd-Timer, der die automatische + Verlängerung tatsächlich antreibt (Standard-Paketverhalten unter + Debian/Ubuntu, zweimal täglich). Rein informativ für die NGINX-Seite: + "automatische Verlängerung" soll für den Admin sichtbar/nachprüfbar + sein, nicht nur eine Behauptung im Quelltext bleiben. None, wenn + certbot (noch) nicht installiert ist.""" + active_ok, active_out = _dhcp_run_privileged(["systemctl", "is-active", "certbot.timer"], timeout=5) + if not active_ok and "could not be found" in active_out.lower(): + return None + next_run = None + ok, out = _dhcp_run_privileged(["systemctl", "list-timers", "certbot.timer", "--no-legend"], timeout=5) + if ok and out.strip(): + parts = out.strip().split(None, 4) + if len(parts) >= 4: + next_run = " ".join(parts[0:4]) + return {"active": active_out.strip() == "active", "next_run": next_run} + + @app.route("/settings/nginx/raw") @login_required def settings_nginx_raw(): @@ -2910,6 +2929,30 @@ def settings_nginx(): "success", ) + elif "test_renewal" in request.form: + if get_setting("ssl_source", "upload") != "letsencrypt": + flash("Verlängerungs-Test setzt ein per Let's Encrypt ausgestelltes Zertifikat voraus.", "danger") + else: + domain = get_setting("nginx_server_name", "_") + ok, out = _dhcp_run_privileged(["certbot", "renew", "--dry-run", "--cert-name", domain], timeout=120) + if ok: + log_action("settings.nginx_letsencrypt_test_renewal", domain) + flash("Verlängerungs-Test erfolgreich (Dry-Run — es wurde nichts tatsächlich verändert).", "success") + else: + flash(f"Verlängerungs-Test fehlgeschlagen: {out.strip()[-800:]}", "danger") + + elif "force_renew" in request.form: + if get_setting("ssl_source", "upload") != "letsencrypt": + flash("Manuelle Verlängerung setzt ein per Let's Encrypt ausgestelltes Zertifikat voraus.", "danger") + else: + domain = get_setting("nginx_server_name", "_") + ok, out = _dhcp_run_privileged(["certbot", "renew", "--force-renewal", "--cert-name", domain], timeout=120) + if ok: + log_action("settings.nginx_letsencrypt_force_renew", domain) + flash("Zertifikat manuell erneuert — nginx wurde über den Deploy-Hook automatisch neu geladen.", "success") + else: + flash(f"Manuelle Verlängerung fehlgeschlagen: {out.strip()[-800:]}", "danger") + elif "apply_nginx" in request.form: new_server_name = request.form.get("server_name", "_").strip() or "_" new_http_port = request.form.get("http_port", "80").strip() @@ -3007,6 +3050,7 @@ def settings_nginx(): https_port=get_setting("nginx_https_port", "443"), pending_nginx_token=pending_token, nginx_revert_seconds=NGINX_REVERT_SECONDS, + certbot_timer=_certbot_timer_status(), ) diff --git a/srv/tesm/templates/settings_nginx.html b/srv/tesm/templates/settings_nginx.html index d9a1d74..2fb70a1 100644 --- a/srv/tesm/templates/settings_nginx.html +++ b/srv/tesm/templates/settings_nginx.html @@ -108,7 +108,32 @@ {% endif %} + {% if cert_info.source == "letsencrypt" %} +
Noch kein Zertifikat hinterlegt.
{% endif %} @@ -116,7 +141,7 @@ {% if can_edit %}