4a665da79e
- /ws-pty carries the dashboard token like /ws (the terminal never attached with DASHBOARD_TOKEN set), and so does everything that cannot send the header: images, downloads, exports, drops (withToken/tokenHeader). A refused upgrade answers 401/403 and is logged and counted by reason. - The browser asks for a missing or wrong token (401 EUNAUTHORIZED) and takes ?token= from the link agenthub start prints, dropping it from the URL. - The CLI sends the token (DASHBOARD_TOKEN, else the one the running server publishes 0600 in <data dir>/runtime/dashboard-token); MCP and statusline read the same file. - DASHBOARD_HOST takes a list, and 127.0.0.1 is always listened on too, so a LAN-only bind keeps hooks and the CLI working. - agenthub start --host/--allowed-hosts/--token are saved in <data dir>/network.json for every later start; a wide bind gets a token; every reachable URL is printed. - tmux < 3.7 is an amber, once-per-version notice that says only the pane scrollbar is missing, with a ~/.local build instead of sudo make install. - INSTALL: PATH belongs in ~/.profile for sudo -iu/ssh; WSL mirrored notes.
83 lines
2.7 KiB
JavaScript
83 lines
2.7 KiB
JavaScript
/**
|
|
* @file network-config.js
|
|
* @description The dashboard's saved network settings — bind address(es),
|
|
* allowed Host names and the dashboard token — in `<data dir>/network.json`
|
|
* (0600). `agenthub start --host/--allowed-hosts/--token` writes it; every
|
|
* server start (a restart after an update, the autostart unit, the plugin
|
|
* bootstrap) applies it with `applyNetworkConfig()`, so a wider bind no longer
|
|
* falls back to loopback silently the next time something else starts the
|
|
* server. An environment variable that is set always wins over the file.
|
|
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
|
*/
|
|
const fs = require("node:fs");
|
|
const path = require("node:path");
|
|
const crypto = require("node:crypto");
|
|
|
|
/** File key → the environment variable it stands in for. */
|
|
const KEYS = {
|
|
host: "DASHBOARD_HOST",
|
|
allowedHosts: "DASHBOARD_ALLOWED_HOSTS",
|
|
token: "DASHBOARD_TOKEN",
|
|
};
|
|
|
|
function configPath() {
|
|
const { getDataDir } = require("./claude-home");
|
|
return path.join(getDataDir(), "network.json");
|
|
}
|
|
|
|
/** The saved settings, `{}` when there are none (or the file is unreadable). */
|
|
function readNetworkConfig() {
|
|
try {
|
|
const c = JSON.parse(fs.readFileSync(configPath(), "utf8"));
|
|
if (!c || typeof c !== "object" || Array.isArray(c)) return {};
|
|
const out = {};
|
|
for (const k of Object.keys(KEYS)) {
|
|
if (typeof c[k] === "string" && c[k].trim()) out[k] = c[k].trim();
|
|
}
|
|
return out;
|
|
} catch {
|
|
return {};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Merge `patch` into the saved settings: a string sets a key, `null` removes
|
|
* it. Written 0600 through a temp file. Returns the new settings.
|
|
*/
|
|
function writeNetworkConfig(patch) {
|
|
const next = { ...readNetworkConfig() };
|
|
for (const [k, v] of Object.entries(patch)) {
|
|
if (!(k in KEYS)) continue;
|
|
if (v === null || v === "") delete next[k];
|
|
else next[k] = String(v).trim();
|
|
}
|
|
const file = configPath();
|
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
const tmp = `${file}.${process.pid}.tmp`;
|
|
fs.writeFileSync(tmp, `${JSON.stringify(next, null, 2)}\n`, { mode: 0o600 });
|
|
fs.chmodSync(tmp, 0o600);
|
|
fs.renameSync(tmp, file);
|
|
return next;
|
|
}
|
|
|
|
/** Put every saved setting whose environment variable is unset into `env`. */
|
|
function applyNetworkConfig(env = process.env) {
|
|
const saved = readNetworkConfig();
|
|
for (const [k, name] of Object.entries(KEYS)) {
|
|
if (saved[k] && !(typeof env[name] === "string" && env[name].trim())) env[name] = saved[k];
|
|
}
|
|
return saved;
|
|
}
|
|
|
|
/** A fresh random token for `--token auto`. */
|
|
const newToken = () => crypto.randomBytes(24).toString("base64url");
|
|
|
|
module.exports = {
|
|
configPath,
|
|
readNetworkConfig,
|
|
writeNetworkConfig,
|
|
applyNetworkConfig,
|
|
newToken,
|
|
KEYS,
|
|
};
|