Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5bca29f3da |
+1
-1
@@ -1 +1 @@
|
|||||||
1.0.7
|
1.0.8
|
||||||
|
|||||||
@@ -2832,6 +2832,25 @@ def _request_letsencrypt_cert(domain, email=None):
|
|||||||
return _dhcp_run_privileged(args, timeout=120)
|
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")
|
@app.route("/settings/nginx/raw")
|
||||||
@login_required
|
@login_required
|
||||||
def settings_nginx_raw():
|
def settings_nginx_raw():
|
||||||
@@ -2910,6 +2929,30 @@ def settings_nginx():
|
|||||||
"success",
|
"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:
|
elif "apply_nginx" in request.form:
|
||||||
new_server_name = request.form.get("server_name", "_").strip() or "_"
|
new_server_name = request.form.get("server_name", "_").strip() or "_"
|
||||||
new_http_port = request.form.get("http_port", "80").strip()
|
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"),
|
https_port=get_setting("nginx_https_port", "443"),
|
||||||
pending_nginx_token=pending_token,
|
pending_nginx_token=pending_token,
|
||||||
nginx_revert_seconds=NGINX_REVERT_SECONDS,
|
nginx_revert_seconds=NGINX_REVERT_SECONDS,
|
||||||
|
certbot_timer=_certbot_timer_status(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,32 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
{% if cert_info.source == "letsencrypt" %}
|
||||||
|
<div class="detail-row">
|
||||||
|
<span class="k">Automatische Verlängerung</span>
|
||||||
|
<span class="v">
|
||||||
|
{% if certbot_timer and certbot_timer.active %}
|
||||||
|
<span class="pill online">aktiv</span>
|
||||||
|
{% if certbot_timer.next_run %}<span class="text-faint" style="font-size:11px; display:block; margin-top:2px;">nächster Lauf: {{ certbot_timer.next_run }}</span>{% endif %}
|
||||||
|
{% elif certbot_timer %}
|
||||||
|
<span class="pill offline">inaktiv</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="pill unknown">unbekannt</span>
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
{% if cert_info.source == "letsencrypt" and can_edit %}
|
||||||
|
<div class="flex gap-2" style="margin-bottom:18px;">
|
||||||
|
<form method="post" style="flex:1;">
|
||||||
|
<button type="submit" name="test_renewal" value="1" class="btn btn-secondary btn-block btn-sm">Verlängerung testen (Dry-Run)</button>
|
||||||
|
</form>
|
||||||
|
<form method="post" style="flex:1;" data-confirm="Zertifikat jetzt sofort erneuern (zählt gegen Let's Encrypts Rate-Limits)?">
|
||||||
|
<button type="submit" name="force_renew" value="1" class="btn btn-secondary btn-block btn-sm">Jetzt manuell verlängern</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<p class="text-faint" style="font-size:12.5px; margin-bottom:18px;">Noch kein Zertifikat hinterlegt.</p>
|
<p class="text-faint" style="font-size:12.5px; margin-bottom:18px;">Noch kein Zertifikat hinterlegt.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -116,7 +141,7 @@
|
|||||||
{% if can_edit %}
|
{% if can_edit %}
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label style="font-weight:600; font-size:13px;">Let's Encrypt anfordern</label>
|
<label style="font-weight:600; font-size:13px;">Let's Encrypt anfordern</label>
|
||||||
<div class="field-hint" style="margin-bottom:8px;">Setzt voraus, dass die Domain öffentlich auf diesen Host auflöst und Port 80 aus dem Internet erreichbar ist (HTTP-01-Validierung) — für rein interne Instanzen ohne öffentliche Domain nicht nutzbar, dann stattdessen hochladen.</div>
|
<div class="field-hint" style="margin-bottom:8px;">Setzt voraus, dass die Domain öffentlich auf diesen Host auflöst und Port 80 aus dem Internet erreichbar ist (HTTP-01-Validierung) — für rein interne Instanzen ohne öffentliche Domain nicht nutzbar, dann stattdessen hochladen. Verlängerung läuft danach automatisch über certbots eigenen Timer{% if certbot_timer %} ({{ "aktiv" if certbot_timer.active else "inaktiv!" }}){% endif %}, zweimal täglich.</div>
|
||||||
</div>
|
</div>
|
||||||
<form method="post" style="margin-bottom:18px;">
|
<form method="post" style="margin-bottom:18px;">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
|
|||||||
Reference in New Issue
Block a user