fix: show config dialog immediately, run WG/firewall setup in background
All checks were successful
CI / test (push) Successful in 2m5s
CI / release (push) Successful in 35s
CI / docker (push) Successful in 55s

In production (WG_WG_ENABLED=true), on_device_created() runs multiple
WG and nftables subprocess calls that take seconds. The UI handler
was awaiting all of them before showing the config dialog, causing
WebSocket timeouts and page reloads.

Now the dialog/QR/download appears right after DB commit, and WG peer
+ firewall configuration runs as a background task via asyncio.create_task.
This commit is contained in:
Stefano Bertelli 2026-03-30 23:24:51 -05:00
parent 44c20cb66b
commit a8784eec9c
2 changed files with 18 additions and 21 deletions

View file

@ -1,5 +1,6 @@
"""Admin device management — view and manage all devices across all users."""
import asyncio
import io
from uuid import UUID
@ -123,22 +124,19 @@ async def admin_devices_page():
await session.refresh(device)
logger.info("Admin created device: {} for {}", device.name, user_map.get(owner_id))
await on_device_created(device)
# Show config
# Build config and show dialog immediately — don't wait for WG/firewall
server_pubkey = await get_server_public_key()
config_text = build_client_config(device, private_key, server_pubkey)
try:
create_dialog.close()
_reset_create_form()
await refresh_table()
_show_config_dialog(device.name, config_text)
except RuntimeError:
pass # Client navigated away during async work
except RuntimeError:
pass # Client disconnected
# Configure WG peer and firewall in background
asyncio.create_task(on_device_created(device))
except Exception as e:
logger.error("Failed to create device: {}", e)
try:

View file

@ -1,5 +1,6 @@
"""User-facing device management pages."""
import asyncio
import io
from uuid import UUID
@ -108,21 +109,19 @@ async def devices_page():
await session.refresh(device)
logger.info("Device created: {} ({})", device.name, device.ipv4)
await on_device_created(device)
# Build config and show dialog immediately — don't wait for WG/firewall
server_pubkey = await get_server_public_key()
config_text = build_client_config(device, private_key, server_pubkey)
try:
create_dialog.close()
_reset_create_form()
await refresh_table()
_show_config_dialog(device.name, config_text)
except RuntimeError:
pass # Client navigated away during async work
except RuntimeError:
pass # Client disconnected
# Configure WG peer and firewall in background (don't block the UI)
asyncio.create_task(on_device_created(device))
except Exception as e:
logger.error("Failed to create device: {}", e)
try: