Background autossh died immediately because nohup left stdin attached to the
closed curl pipe — autossh saw EOF and bailed. Add </dev/null and wrap in
subshell so the process is fully detached from the install script's session.
Also add an "+ Тоннель" button next to "+ Добавить": creates a router with a
placeholder base URL and opens the tunnel modal in one click — for routers
without a public IP that have nothing to put in the base URL field yet.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
aarch64-k3.10 Entware lacks sshpass, cronie, and openssh-keygen. Generate the
ed25519 keypair on the VPS (where ssh-keygen is always present) and ship the
private key to the router inside the install script.
The router only sees a short curl|sh one-liner — easy to copy, immune to
markdown auto-linkification of .sh paths that mangled previous attempts.
- _gen_ed25519_keypair / _add_pubkey_to_authorized_keys helpers
- /tunnel-cmd: generate keypair on first call, store priv+pub on router record,
add pub to ~/.ssh/authorized_keys, return one-liner
- /tunnel-script: returns full install script with private key embedded
(text/plain), token-authenticated, single-use
- removed /tunnel-register-key endpoint (router no longer generates the key)
- copy button: select on-page text + execCommand fallback for non-HTTPS;
if both fail, leave selected so user can Cmd+C manually
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
aarch64-k3.10 Entware does not have sshpass or cronie packages. Switch to ed25519
SSH key auth and persist via /opt/etc/init.d/S99kdns_tunnel instead of cron.
- /api/routers/{rid}/tunnel-cmd: drop VPS_SSH_PASS dependency, generate one-time
registration token, build install script that:
1. opkg install autossh + openssh-keygen
2. ssh-keygen ed25519 if not exists
3. curl POST pubkey to new register-key endpoint with token
4. autossh -i <key> (no sshpass)
5. /opt/etc/init.d/S99kdns_tunnel for boot autostart
- /api/routers/{rid}/tunnel-register-key: new endpoint, token-auth, appends pubkey
to ~/.ssh/authorized_keys with kdns-tunnel-{rid} comment for de-dup
- copy button: fallback to document.execCommand('copy') for non-HTTPS contexts
(navigator.clipboard requires secure context — UI runs on plain http)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- opkg install now includes cronie so crond is actually present
- /opt/etc/init.d/S10crond start runs after install so cron watchdog fires
- cron watchdog switches from pgrep (not always in PATH) to killall -0 autossh
- killall autossh instead of pkill before re-launching (works in BusyBox)
- GET /api/routers/{rid}/tunnel-status: checks if tunnel port is listening on VPS localhost
- "⟳ Проверить связь" button in tunnel modal calls the new endpoint
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
UI: «⇄ Тоннель» button next to «Тест» — opens modal with autossh
install command for the router and an auto-applied localhost RCI URL.
Backend: GET /api/routers/{id}/tunnel-cmd allocates a free port
(starts at TUNNEL_PORT_START) and returns the shell command;
DELETE /api/routers/{id}/tunnel clears the assignment.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use single-quoted onclick/onchange so JSON.stringify(id) does not break HTML.
Encode router id in API paths; handle test errors and delete failures.
Made-with: Cursor