7.5 KiB
7.5 KiB
Plan: WG Auto Up + PrivateKey Node Registration
TL;DR
Fix WireGuard interface goes down after
update.sh(container restart) and allow registering nodes using PrivateKey (from MikroTik export) instead of requiring PublicKey manually.
Deliverables:
- Auto
wg upLocal Primary Node on server startup (main.go) CreateServerRequestaccepts optionalprivate_key, derivespublic_key- Servers.vue "Register New Node" form accepts PrivateKey input
- Servers.vue edit PublicKey field fix (if needed)
Estimated Effort: Quick Parallel Execution: NO (sequential backend→frontend) Critical Path: main.go auto-up → servers.go Create → Servers.vue form
Context
User reported:
- After running
update.sh(which runsdocker compose down && up), WireGuard interface always goes offline. No code auto-initializes WG on startup — onlywgmanager.New()is called, neverwgMgr.Up(). - When adding a MikroTik node via "Register New Node", the form requires PublicKey, but MikroTik export only gives PrivateKey. Need to accept PrivateKey and derive PublicKey.
Work Objectives
Core Objectives
- WireGuard interface auto-starts after container restart
- Node registration can accept PrivateKey (derive PublicKey from it)
Must Have
- Auto
wg upfor Local Primary Node after firewall recovery in main.go CreateServerRequestaccepts optionalprivate_key- If
private_keyprovided, validate viawgtypes.ParseKey, derivepublic_key - Servers.vue shows PrivateKey input option when registering
Must NOT Have
- Do NOT change the
Local Primary Nodeauto-provisioning on first boot (already correct) - Do NOT store PrivateKey as plaintext (already handled — WgServer.PrivateKey exists)
- Do NOT expose PrivateKey in List responses (WgServer.PrivateKey has
json:"-") - Do NOT change the
/devices/:id/regenerate-keysor device key handling
TODOs
-
1. main.go: auto
wg upon startupWhat to do:
- Add
"encoding/hex"to imports - After firewall recovery section (after
fw.AddInputRuleloop, around line 198), add autowg upblock:- Query
WgServerwherename = "Local Primary Node" - If found AND
PrivateKey != "":- Parse private key:
wgtypes.ParseKey(localPrimary.PrivateKey) - Convert to hex:
hex.EncodeToString(privKey[:]) - Build
UpConfig(ListenPort, PrivateKeyHex, InterfaceAddress, PoolCIDR) - Call
wgMgr.Up(cfg) - On success:
peerSyncer.SyncLocalPeers()
- Parse private key:
- Query
- Match exact pattern from
WgHandler.Up()inwg.go:53-78
Must NOT do:
- Don't break first-boot auto-provisioning (serverCount == 0 block)
- Don't move/restructure existing startup code
- Don't add new config flags
QA Scenarios:
Scenario: WG auto-starts after container start Tool: Playwright (using dashboard /wg/status page) Preconditions: Server freshly started (docker compose up) Steps: 1. Login as admin 2. Navigate to any page 3. Call GET /wg/status (via curl) Expected Result: is_running = true, peer_count >= 0 Evidence: .sisyphus/evidence/task1-wg-status.json - Add
-
2. servers.go: accept PrivateKey in Create
What to do:
- Add
PrivateKey *string json:"private_key"toCreateServerRequest - Make
PublicKeyNOT required (removebinding:"required"or make it optional) - In
Create()handler, after parsing request:- If
req.PrivateKey != nil:- Validate:
k, err := wgtypes.ParseKey(*req.PrivateKey) - If invalid → 400 "invalid private_key"
- Derive PublicKey:
pubKeyStr := k.PublicKey().String() - Store both:
server.PrivateKey = *req.PrivateKey,server.PublicKey = pubKeyStr
- Validate:
- Else if
req.PublicKey != "":- Use as-is (existing logic)
- Else: 400 "either public_key or private_key is required"
- If
Must NOT do:
- Don't change the
UpdateServerRequest— that's T6 already done - Don't remove existing validation for
PublicKeyifPrivateKeynot provided
QA Scenarios:
Scenario: Create node with private key Tool: Bash (curl) Preconditions: Admin JWT token exists Steps: 1. POST /api/v1/servers with body: {"name":"test-node","private_key":"<valid_base64_privkey>","public_endpoint":"10.0.0.1:51820","listen_address":"0.0.0.0","listen_port":51820} 2. Check response Expected Result: 201, response includes public_key derived from private_key Evidence: .sisyphus/evidence/task2-create-with-privkey.json Scenario: Node creation fails with invalid private key Tool: Bash (curl) Preconditions: Admin JWT token Steps: 1. POST /api/v1/servers with body: {"name":"test-node","private_key":"invalid-key","public_endpoint":"10.0.0.1:51820","listen_address":"0.0.0.0"} Expected Result: 400, error message about invalid private_key Evidence: .sisyphus/evidence/task2-invalid-privkey.json - Add
-
3. Servers.vue: update Register New Node form
What to do:
- Read the current Register form (line 8-30 of Servers.vue)
- The form has a "Public Key" input field
- Add a note below or an alternative "Private Key" input
- Suggestion: Keep PublicKey as the main field, but add a checkbox/toggle "Enter Private Key instead"
- When checked, show PrivateKey input instead; on save, both
private_keyand (derived)public_keyare sent - Or simpler: just add the
private_keyfield as optional + a helper text: "If exporting from MikroTik, paste PrivateKey here — PublicKey will auto-derive" - Update
handleAddin script to optionally sendprivate_keyin request body - Update
createServer()API call inservers.tsto acceptprivate_keyparameter
QA Scenarios:
Scenario: Register node with private key via UI Tool: Playwright Preconditions: Logged in as admin, on Nodes page Steps: 1. Click "+ Register Node" 2. Fill name, private_key, public_endpoint, listen_address 3. Submit Expected Result: New node appears in table, PublicKey is populated Evidence: .sisyphus/evidence/task3-form-private-key.png -
4. update.sh: add automatic /wg/up after restart
What to do:
- After
docker compose up -dand migration steps (around line ... after migration), add:sleep 3 # Wait for server to fully initialize echo "[+] Bringing up WireGuard interface..." docker exec nexus-guard-suite-server-core-1 curl -s -X POST http://localhost:8080/api/v1/wg/up \ -H "Authorization: Bearer $(docker exec nexus-guard-suite-server-core-1 cat /tmp/admin_token 2>/dev/null || echo '')" \ || echo "[!] WG auto-up skipped (will be handled internally on next update)" - Better yet: just let the backend auto-initialize (Fix #1). update.sh change is optional/minor.
QA Scenarios:
Scenario: update.sh leaves WG running Tool: Bash Preconditions: Remote server (172.20.8.191) with existing deployment Steps: 1. Run ./update.sh 2. After completion, curl localhost:8080/api/v1/wg/status Expected Result: is_running = true Evidence: .sisyphus/evidence/task4-update-sh-wg-status.json - After
Final Verification
- F1:
go build -tags dev ./...passes - F2:
npm run buildpasses - F3: Server starts,
/wg/statusshows is_running=true - F4: Can register a node using PrivateKey via API + UI
Commit Strategy
- Commit #1: Backend — auto wg up on startup + accept PrivateKey in server create
- Commit #2: Frontend — PrivateKey input option in Register Node form