Nodofi Docs

Running the NVM Service Manager

Publish a Studio "Service" project — a headless JS entry point, no HTML/UI at all — and run it as its own isolated, persistent process, reachable by name over the relay network.

Overview

A Service project's only file is JavaScript, with a top-level entry point:

async function AsyncNodoMain(input, callback) {
  callback({ hello: input.name || 'world' });
}

Publishing it (right-click the project in Studio → Publish Service…) sends that code to a Manager, which forks a brand-new, isolated Node.js process for it — a real OS process boundary, so a crash or an infinite loop in one service can't touch another — and connects that process to the relay under the project's own id. From then on, anything that can reach that relay can call it exactly the way it would call a node: NodoRequest/NodoRequestAsync, or the same wire protocol directly.

Studio's "Publish Service…" dialog addresses a Manager by relay + name, never a direct URL — the Manager itself also joins the relay under its own name, so this works even when it has no reachable address of its own (behind NAT/CGNAT, a home connection), the same reason every other worker in this ecosystem (a node, a CloudDB worker) is reached by name over the relay rather than a URL.

Every published service also gets, for free, no imports needed: NodoRequest/ NodoRequestAsync (call another service or node), JozieAI.ask/ NODOFI.request, NVMDNS.lookup, CONSOLE(text) (shows up in this Manager's own dashboard), and NodoCloudDB — a full Node port of the same database client a regular app uses, so a service can read/write shared data with no extra setup.

Requirements

  • Node.js 18 or later — the only real prerequisite. Everything else (the app's own dependencies) installs automatically on first run.
  • Windows, Linux (any systemd-based distribution), or macOS (run from source).
  • Unlike Nodofi Node, this needs a little configuration before it does anything: a relay to join, its own name on that relay, and a secret key — see Quickstart below.

Quickstart

Windows

  1. Download nodofi-nvm-manager-win-x64.zip and extract it anywhere you'll keep it.
  2. Double-click install-startup.bat — the first time, this also installs dependencies and creates a .env file from .env.example.
  3. Open .env in that folder and set MANAGER_KEY (a long random string) and MANAGER_NAME (unique on the relay you're using — RELAY_URL already defaults to Nodofi's own public relay). Then run install-startup.bat again, or schtasks /run /tn "NodofiNvmManager".
  4. Open http://localhost:8841 to finish setup.

Linux

tar -xzf nodofi-nvm-manager-linux-x64.tar.gz
cd nodofi-nvm-manager-linux-x64
sudo ./install.sh   # creates .env from .env.example and tells you what still needs setting

Edit /opt/nodofi-nvm-manager/.env (set MANAGER_KEY/MANAGER_NAME), then sudo systemctl start nodofi-nvm-manager. Open http://localhost:8841 in a browser on that machine to finish setup.

macOS (or any OS, from source)

git clone <this repository>
cd nvm-service-manager
npm install
cp .env.example .env   # then edit it — set MANAGER_KEY and MANAGER_NAME
npm start

The dashboard (:8841) redirects a first visit to a one-time setup page to create a username and password — from then on it's also reachable remotely with those credentials (see Remote dashboard access below). In Studio, right-click a Service project → Publish Service…, and enter this Manager's RELAY_URL and MANAGER_NAME — no URL needed.

Developers & API keys

The .env MANAGER_KEY is a root credential — it always works, for anyone who has it. For attributing publishes to individual developers instead, create a per-developer API key from the dashboard's Developers panel: enter a name, click New API key, and copy the key shown — it's only ever shown once, only its hash is stored. That developer then uses their own key in Studio's dialog exactly like the shared key. Every publish is attributed to whichever key made it (the Services table's "Published by" column); revoking a key takes effect immediately for further publishes, without stopping services that developer already published.

Analytics

Every handled request is timed and counted automatically — the dashboard's Services table shows live request/error/latency totals per service, and each service's own Stats view shows a per-minute breakdown for the last 24 hours. Minute-level buckets are pruned after STATS_RETENTION_DAYS (default 14); the cumulative totals are kept forever.

Remote dashboard access

The dashboard is reachable locally with no setup at all. The first time you open it (local or remote — see below), it redirects to a one-time setup page to create a username and password; from then on it's also reachable from anywhere with those credentials (on by default the moment they're created — a "Turn off remote access…" button, reachable even from a remote session, is the kill switch). An authenticator app (TOTP) is a separate, optional second step added after your first sign-in.

Warning: First-time setup itself is deliberately reachable remotely too — not just locally — to make bootstrapping a freshly deployed, headless machine possible without SSH access. The tradeoff: until setup completes, whoever reaches the Manager's port first can claim the admin account, not necessarily you. The window closes for good the instant setup succeeds and never reopens — finish it immediately after deploying, and don't leave a fresh ADMIN_PORT open on the internet any longer than you have to.

Login attempts are rate-limited (exponential backoff per source IP). An optional extra layer, Beezifi Security "Ghost Response" protection, can gate /admin/login specifically — every sign-in attempt checked against your own Beezifi rules before this Manager's own password/TOTP check ever runs, failing closed if Beezifi itself can't be reached.

Reverse proxy (Apache)

Two separate things can be proxied — the dashboard and, optionally, the HTTP publish API — kept on two separate (sub)domains, since the dashboard's own pages reference absolute root paths that can't safely be mounted under a sub-path. Neither needs WebSocket proxying (this Manager's own outbound connection to its relay doesn't go through either vhost).

# The dashboard — nvm-admin.example.com -> 127.0.0.1:8841
<VirtualHost *:443>
    ServerName nvm-admin.example.com
    SSLEngine on
    SSLCertificateFile      /etc/letsencrypt/live/nvm-admin.example.com/fullchain.pem
    SSLCertificateKeyFile   /etc/letsencrypt/live/nvm-admin.example.com/privkey.pem

    # Not optional: the dashboard's CSRF check compares the browser's Origin against the Host header it
    # sees, and its login sets the session cookie Secure based on X-Forwarded-Proto.
    ProxyPreserveHost On
    RequestHeader set X-Forwarded-Proto "https"

    ProxyPass        "/" "http://127.0.0.1:8841/"
    ProxyPassReverse "/" "http://127.0.0.1:8841/"
</VirtualHost>

A full ready-to-adapt config (both vhosts, plus a troubleshooting note on OCSP stapling) ships in the download as apache.conf.example.

Uninstalling

Linux: sudo ./uninstall.sh from the folder you extracted (your .env and data are kept). Windows: double-click uninstall-startup.bat, then delete the extracted folder.