Skip to main content

vulkro serve

Launch the desktop console - the web UI embedded into the binary, served by a local HTTP server, opening your browser to http://127.0.0.1:8723.

Usage

vulkro serve [--port 8723] [--no-browser]

Flags

FlagDescriptionDefault
--port <PORT>Port to bind. If taken, the OS picks a free one.8723
--host <HOST>Interface to bind. 127.0.0.1 (loopback, single user) or 0.0.0.0 / an interface IP for a team self-host. See the warning below.127.0.0.1
--no-browserDon't auto-open the browser when ready.(false)

What runs where

  • HTTP server: 127.0.0.1 by default (loopback, single user). A team self-host can bind a network interface with --host (see below).
  • UI assets: embedded directly into the vulkro binary at build time. No separate web server, no static-file dir to ship.
  • State: SQLite at platform-appropriate paths:
    • macOS: ~/Library/Application Support/Vulkro/vulkro-desktop.db
    • Linux: ~/.local/share/Vulkro/vulkro-desktop.db
    • Windows: %APPDATA%\Vulkro\vulkro-desktop.db

Tabs

The console exposes tabs for findings, privacy, access control, CSRF, injection, IaC, dependencies, secrets, git history, containers, package licences, OpenAPI score, compliance, trends, hotspots, contributors, compare-scans, and code quality.

See Desktop console -> for the full reference.

Team self-host (multi-repo aggregation)

vulkro serve reads every run saved with vulkro scan --save from the shared local store, so it is already a multi-repo portfolio: scan several repositories (or have several contributors scan and --save), and the Portfolio view aggregates findings, trends, and cross-service correlations across all of them.

To share that console with a team on your own infrastructure, bind a network interface:

vulkro serve --host 0.0.0.0 --no-browser

Built-in token authentication

For a network bind, set a shared token and the console requires it:

export VULKRO_SERVE_TOKEN="$(openssl rand -hex 24)" # any non-empty value
vulkro serve --host 0.0.0.0

With VULKRO_SERVE_TOKEN set:

  • Every /api/* route requires a valid session, so no data is reachable unauthenticated.
  • Opening the console shows a sign-in page. Entering the token mints a random session and stores it in an HttpOnly, SameSite=Strict cookie; the bundled UI's same-origin requests carry it automatically.
  • Sessions live in memory and clear when the server restarts (sign in again). POST /logout ends a session.

The cookie is not marked Secure, because the console usually speaks plain HTTP on a trusted LAN. For an untrusted network, terminate TLS in front of it (see the reverse-proxy option below); SameSite=Strict still blocks cross-site cookie delivery in the meantime.

caution

VULKRO_SERVE_TOKEN is a single shared token, not per-user accounts. It fits a small trusted team. If you need per-user identity, SSO, or an audit of who signed in, use the reverse-proxy option instead.

Reverse-proxy alternative

Keep vulkro serve on loopback (no token) and add auth + TLS at the edge:

server {
listen 443 ssl;
server_name vulkro.internal;
# ssl_certificate / ssl_certificate_key ...
location / {
auth_basic "Vulkro";
auth_basic_user_file /etc/nginx/.htpasswd; # htpasswd -c ... vulkro
proxy_pass http://127.0.0.1:8723; # vulkro serve on loopback
}
}

A non-loopback bind with no VULKRO_SERVE_TOKEN prints a warning, because the console is then open: either set the token or front it with a proxy.

Your code stays put: the console serves scan results from the local SQLite store and never sends source, file paths, or findings anywhere. Startup can send the usage heartbeat (at most once every 24 hours, on a background thread); VULKRO_OFFLINE=1 suppresses it, and the console then makes no outbound call at all, so it runs unchanged on an air-gapped network.

Stopping the server

Ctrl-C in the terminal. The server traps SIGINT and shuts down cleanly, flushing any in-flight scan to SQLite first.