Skip to content

nkapp hub ​

Starts the Nanokit local bridge, which connects your project workspace to the Nanokit Hub dashboard.

bash
nkapp hub [options]

Aliases: nkapp bridge, nkapp dashboard — all three invoke the same command.

You usually do not need to run this manually

nkapp up automatically spins up and manages the bridge system container (nk-<project>-<env>-bridge) in the background. Run nkapp hub when you want to open the dashboard, or use the lifecycle flags below to recycle the bridge.

Options ​

FlagDescriptionDefault
-p, --port <port>Port for the bridge to listen on.3006 (or $NANOKIT_BRIDGE_PORT)
-t, --target <url>Hub UI target URL to open.auto-detected
--openOpen the Hub in the default browser (automatically disabled inside containers).true
--no-watchDisable monitoring file changes inside the workspace.false
--startEnsure a bridge is running — idempotent: a no-op if one is already up, created if missing.—
--statusReport whether a bridge is running, then exit.—
--stopStop the running bridge and exit.—
--restartRecreate the bridge and wait for it to serve.—

Run with no flags to start the bridge server in the foreground (standalone / dev use).


Bridge lifecycle (--start / --status / --stop / --restart) ​

The bridge is long-running, and nkapp up / nkapp deploy do not recycle it — so after rebuilding the CLI you may need to recycle it yourself to pick up new code:

bash
nkapp hub --status    # is a bridge running?
nkapp hub --start     # ensure one is (no-op if already up)
nkapp hub --stop      # shut it down
nkapp hub --restart   # recreate it and wait for it to serve

All four are container-managed first. For the usual local case they operate on the nk-<project>-<env>-bridge container:

  • --start never starts a host-process bridge, which would collide on the port (EADDRINUSE).
  • --restart recreates the container rather than issuing a plain docker restart: a bare restart keeps the stale dist bind-mount, so after a CLI rebuild the container would still run the old code.
  • If a container operation fails, the command prints a clear error and exits — it does not silently start a stray terminal bridge.

Only when there is genuinely no container (or Docker is unreachable) do these fall through to the host-process path. That path drives the bridge over loopback HTTP (POST /shutdown, loopback-only) rather than killing by PID, which is what makes a restart work across the WSL ↔ Windows shared-localhost boundary where the process is not reachable by PID from the side running the CLI.

One-time upgrade step

A bridge built before the /shutdown route existed must be stopped manually once; --restart works from then on.


Description ​

The bridge is a WebSocket + HTTP server that acts as a secure proxy between your local development workspace (including any remote VPS tunnels) and the browser-based Nanokit Hub UI.

The Hub connects only to your LOCAL bridge

Although the Hub UI is served over HTTPS from Nanokit's servers (e.g. hub.nanokit.dev), it talks exclusively to the bridge running on your own machine at http://127.0.0.1:3006. Browsers treat http/ws to 127.0.0.1 as a secure exception, so loopback works from an HTTPS page.

It never falls back to a remote/VPS bridge — that would show server-side data instead of your projects. When no local bridge is reachable (the Hub opened from a phone, or the bridge not running), the Hub shows a clear "No local bridge detected" state with a Retry button and suggests running nkapp up.

The only surface that intentionally reads a remote bridge is the Status page (and the Caddy /_bridge endpoint), which reports the served cluster's real system data.

Once running, the Hub lets you:

  • Monitor system metrics — real-time container CPU and RAM.
  • Stream logs — live output from every active service.
  • Manage database branches — fork, reset or merge with a single click.
  • Control containers — start, stop and restart individual services.

The auto-bridge lifecycle ​

  1. Running nkapp up invokes ensureBridge() as part of the pre-launch phase.
  2. This creates and launches the managed nk-<project>-<env>-bridge system container.
  3. The bridge mounts your workspace and listens on port 3006.
  4. When you tear the environment down with nkapp destroy, the bridge container is stopped and cleaned up with the other project resources.

The bridge is provisioned for any provider that implements it — the Docker provider creates a local container; cloud providers create their own equivalent.

Open the Hub on your phone ​

The Hub's Open on phone button shows a QR code. Scan it, and the Hub opens on your phone connected to your laptop's bridge. The session has full access, lasts 12 hours, and you can revoke it at any time.

Install Tailscale on the laptop and on the phone, and sign both into the same tailnet. Then run once on the laptop:

bash
nkapp bridge pair --tailscale        # add --dry-run to preview

This publishes the bridge's dedicated device port (127.0.0.1:23006) on your tailnet at https://<laptop>.<tailnet>.ts.net:8443 with tailscale serve. It never uses Funnel, so nothing is exposed to the internet. The command then checks the route end to end. Undo it with nkapp bridge pair --no-tailscale.

If you have no Tailscale, the Hub can fall back to your VPS (https://<host>/_bridge) for an environment whose reverse tunnel is up. That route faces the internet, so:

  • you must click Approve on the laptop after the phone scans;
  • container shells are not available on the phone.

Pair and manage devices ​

CommandWhat it does
nkapp bridge pair [--label <name>]Print a one-time pairing QR in the terminal. It is valid for 2 minutes and works once.
nkapp bridge devicesList paired phones (--json for scripts).
nkapp bridge devices revoke <dev_…>Revoke one phone. Its open sessions close immediately.
nkapp bridge devices revoke --all [-y]Revoke every phone.

nkapp up and nkapp bridge --start/--status warn if the Tailscale route stopped working, and name the command that repairs it. nkapp doctor warns if a tailscale serve entry exposes the bridge's main port 3006 directly. Remove such an entry: it gives everyone on your tailnet full, unauthenticated access.

Limits (environment variables on the laptop):

  • NANOKIT_BRIDGE_DEVICE_TTL_HOURS: session length, 1–72 hours, default 12;
  • NANOKIT_BRIDGE_MAX_DEVICES: number of paired phones, default 10;
  • NANOKIT_BRIDGE_DEVICE_MAX_SOCKETS: connections per phone, default 4.