Skip to content

Commit 7cc9003

Browse files
Auto-start tunnel after paid invoice
1 parent a69dd0f commit 7cc9003

1 file changed

Lines changed: 46 additions & 18 deletions

File tree

nixos/admin-app/app.py

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,33 @@ def _write_runtime_env(tunnel: dict[str, Any]):
746746
os.chmod(TUNNEL_RUNTIME_ENV, 0o600)
747747

748748

749+
def _start_tunnel_service_if_needed(tunnel: dict[str, Any], service_status: str | None = None) -> tuple[bool, str]:
750+
if not tunnel.get("tunnel_id"):
751+
return False, "No tunnel configured"
752+
if not tunnel.get("remote_port"):
753+
return False, "Tunnel remote port missing"
754+
if not TUNNEL_KEY_FILE.exists():
755+
return False, "Tunnel key not found. Create tunnel again."
756+
757+
current_status = service_status or _tunnel_service_status()
758+
if current_status == "active":
759+
return False, "Tunnel service already active"
760+
761+
if DEV_MODE:
762+
return True, "DEV MODE: would start tunnel service"
763+
764+
_write_runtime_env(tunnel)
765+
subprocess.run(
766+
["systemctl", "enable", f"{TUNNEL_SERVICE_NAME}.service"],
767+
check=True, capture_output=True, timeout=20
768+
)
769+
subprocess.run(
770+
["systemctl", "restart", f"{TUNNEL_SERVICE_NAME}.service"],
771+
check=True, capture_output=True, timeout=20
772+
)
773+
return True, "Tunnel service restarted"
774+
775+
749776
def _tunnel_connect_script(tunnel: dict[str, Any] | None) -> str | None:
750777
if not tunnel:
751778
return None
@@ -2700,6 +2727,9 @@ def api_tunnel_poll():
27002727
state = _sync_tunnel_state_from_remote(state, client_id)
27012728
current = state.get("current_tunnel")
27022729
pending = state.get("pending_invoice")
2730+
service_status = _tunnel_service_status()
2731+
auto_started = False
2732+
auto_start_message: str | None = None
27032733

27042734
if DEV_MODE and pending and pending.get("action") == "renew":
27052735
# Simple mock progression for local UI development
@@ -2713,14 +2743,23 @@ def api_tunnel_poll():
27132743
_save_tunnel_state(state)
27142744
pending = None
27152745
paid = True
2746+
try:
2747+
auto_started, auto_start_message = _start_tunnel_service_if_needed(current, service_status=service_status)
2748+
if auto_started:
2749+
service_status = "active" if DEV_MODE else _tunnel_service_status()
2750+
except subprocess.CalledProcessError as e:
2751+
auto_started = False
2752+
auto_start_message = e.stderr.decode() or "Failed to start tunnel service"
27162753

27172754
payload = {
27182755
"paid": paid,
27192756
"client_id": client_id,
27202757
"current_tunnel": state.get("current_tunnel"),
27212758
"pending_invoice": pending,
2722-
"service_status": _tunnel_service_status(),
2759+
"service_status": service_status,
27232760
"connect_script": _tunnel_connect_script(state.get("current_tunnel")),
2761+
"auto_started": auto_started,
2762+
"auto_start_message": auto_start_message,
27242763
}
27252764
return _json_response(status="ok", data=payload, **payload)
27262765

@@ -2737,25 +2776,14 @@ def api_tunnel_start():
27372776
return jsonify({"status": "error", "message": "No tunnel configured"}), 404
27382777
if pending:
27392778
return jsonify({"status": "error", "message": "Tunnel invoice is still unpaid"}), 409
2740-
if not current.get("remote_port"):
2741-
return jsonify({"status": "error", "message": "Tunnel remote port missing"}), 400
2742-
if not TUNNEL_KEY_FILE.exists():
2743-
return jsonify({"status": "error", "message": "Tunnel key not found. Create tunnel again."}), 400
2744-
2745-
if DEV_MODE:
2746-
return jsonify({"status": "ok", "message": "DEV MODE: would start tunnel service"})
27472779

27482780
try:
2749-
_write_runtime_env(current)
2750-
subprocess.run(
2751-
["systemctl", "enable", f"{TUNNEL_SERVICE_NAME}.service"],
2752-
check=True, capture_output=True, timeout=20
2753-
)
2754-
subprocess.run(
2755-
["systemctl", "restart", f"{TUNNEL_SERVICE_NAME}.service"],
2756-
check=True, capture_output=True, timeout=20
2757-
)
2758-
return jsonify({"status": "ok", "message": "Tunnel service restarted"})
2781+
started, message = _start_tunnel_service_if_needed(current)
2782+
if not started and message == "Tunnel service already active":
2783+
return jsonify({"status": "ok", "message": message})
2784+
if not started:
2785+
return jsonify({"status": "error", "message": message}), 400
2786+
return jsonify({"status": "ok", "message": message})
27592787
except subprocess.CalledProcessError as e:
27602788
return jsonify({"status": "error", "message": e.stderr.decode()}), 500
27612789
except Exception as e:

0 commit comments

Comments
 (0)