From 8829ac579d2fb21a1543afd9a0b1e5e17dc5e78d Mon Sep 17 00:00:00 2001 From: Mike Teehan Date: Sun, 24 May 2026 13:12:40 +0000 Subject: [PATCH] fix: strip private_key from WireGuard PATCH endpoint and add acme-challenge template --- system/nginx/acme-challenge.conf | 17 +++++++++++ webui/api/wireguard.py | 50 +++++++++++++++++--------------- 2 files changed, 44 insertions(+), 23 deletions(-) create mode 100644 system/nginx/acme-challenge.conf diff --git a/system/nginx/acme-challenge.conf b/system/nginx/acme-challenge.conf new file mode 100644 index 0000000..f210af9 --- /dev/null +++ b/system/nginx/acme-challenge.conf @@ -0,0 +1,17 @@ +# Auto-generated by Vacuum Wall — do not edit manually +# Serve ACME HTTP-01 challenges on port 80 for any domain not yet +# configured with a dedicated server block (catch-all). + +server { + listen 80 default_server; + listen [::]:80 default_server; + server_name _; + + location /.well-known/acme-challenge/ { + root {{ acme_webroot }}; + } + + location / { + return 444; + } +} diff --git a/webui/api/wireguard.py b/webui/api/wireguard.py index 741d00c..2bf7a90 100644 --- a/webui/api/wireguard.py +++ b/webui/api/wireguard.py @@ -6,8 +6,9 @@ Exposed at /api/wireguard/* and delegates to lib.wireguard. import logging -from flask import Blueprint, jsonify, request +from flask import Blueprint, request +from lib.common import deep_merge from lib.wireguard import ( add_peer, apply, @@ -21,24 +22,12 @@ from lib.wireguard import ( save_config, status, ) +from webui.api.common import _error, _ok logger = logging.getLogger(__name__) bp = Blueprint("wireguard", __name__) -# --------------------------------------------------------------------------- -# Helpers -# --------------------------------------------------------------------------- - - -def _error(msg, code=400): - return jsonify({"ok": False, "error": msg}), code - - -def _ok(data=None): - return jsonify({"ok": True, "data": data}) - - # --------------------------------------------------------------------------- # Config # --------------------------------------------------------------------------- @@ -64,17 +53,35 @@ def post_config(): if not isinstance(body, dict): return _error("Request body must be a JSON object", 400) try: + if "interface" in body: + body["interface"] = dict(body["interface"]) + body["interface"].pop("private_key", None) save_config(body) - safe = dict(body) - if "interface" in safe: - safe["interface"] = dict(safe["interface"]) - safe["interface"].pop("private_key", None) - return _ok(safe) + return _ok(None) except RuntimeError as exc: logger.error("Failed to save WireGuard config: %s", exc) return _error(str(exc), 500) +@bp.route("/config", methods=["PATCH"]) +def patch_config(): + body = request.get_json(silent=True) or {} + if not isinstance(body, dict): + return _error("Request body must be a JSON object", 400) + try: + if "interface" in body: + body["interface"] = dict(body["interface"]) + body["interface"].pop("private_key", None) + current = get_config() + merged = deep_merge(current, body) + save_config(merged) + logger.info("WireGuard config patched: %s", sorted(body.keys())) + return _ok(None) + except RuntimeError as exc: + logger.error("Failed to patch WireGuard config: %s", exc) + return _error(str(exc), 500) + + # --------------------------------------------------------------------------- # Apply / down # --------------------------------------------------------------------------- @@ -162,10 +169,8 @@ def add_peer_bp(): persistent_keepalive=body.get("persistent_keepalive"), preshared_key=body.get("preshared_key"), ) - safe = dict(peer) - safe.pop("private_key", None) logger.info("WireGuard peer '%s' added via API", name) - return _ok(safe) + return _ok(peer) except RuntimeError as exc: logger.error("Failed to add peer '%s': %s", name, exc) return _error(str(exc), 500) @@ -221,7 +226,6 @@ def generate_client_bp(): server_endpoint = body.get("server_endpoint", "") server_pubkey = cfg["interface"].get("public_key", "") if not server_endpoint: - _ = cfg["interface"].get("listen_port", 51820) return _error( "Field 'server_endpoint' is required (e.g., '203.0.113.1:51820')", 400 )