uplink-cli 0.1.28 → 0.1.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/src/index.ts +2 -0
- package/cli/src/subcommands/system.ts +74 -0
- package/docs/PRODUCT.md +9 -0
- package/package.json +1 -1
package/cli/src/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { adminCommand } from "./subcommands/admin";
|
|
|
6
6
|
import { menuCommand } from "./subcommands/menu";
|
|
7
7
|
import { tunnelCommand } from "./subcommands/tunnel";
|
|
8
8
|
import { signupCommand } from "./subcommands/signup";
|
|
9
|
+
import { systemCommand } from "./subcommands/system";
|
|
9
10
|
import { readFileSync } from "fs";
|
|
10
11
|
import { join } from "path";
|
|
11
12
|
|
|
@@ -27,6 +28,7 @@ program.addCommand(devCommand);
|
|
|
27
28
|
program.addCommand(adminCommand);
|
|
28
29
|
program.addCommand(tunnelCommand);
|
|
29
30
|
program.addCommand(signupCommand);
|
|
31
|
+
program.addCommand(systemCommand);
|
|
30
32
|
program.addCommand(menuCommand);
|
|
31
33
|
|
|
32
34
|
// Global pre-action hook to apply shared options
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { apiRequest } from "../http";
|
|
3
|
+
|
|
4
|
+
type SystemStatus = {
|
|
5
|
+
hasInternalSecret: boolean;
|
|
6
|
+
relayReachable: boolean;
|
|
7
|
+
relayConnectedCount: number;
|
|
8
|
+
tlsMode: string;
|
|
9
|
+
wildcardDomains: string[];
|
|
10
|
+
askEndpoint: { path: string; protected: boolean; note?: string };
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
function formatBoolean(value: boolean) {
|
|
14
|
+
return value ? "yes" : "no";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function fetchStatus(): Promise<SystemStatus> {
|
|
18
|
+
return (await apiRequest("GET", "/v1/admin/system/status")) as SystemStatus;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const systemCommand = new Command("system")
|
|
22
|
+
.description("System diagnostics (admin)")
|
|
23
|
+
.addCommand(
|
|
24
|
+
new Command("status")
|
|
25
|
+
.description("Show system status for relay/TLS wiring")
|
|
26
|
+
.option("--json", "Output raw JSON")
|
|
27
|
+
.action(async (opts) => {
|
|
28
|
+
const status = await fetchStatus();
|
|
29
|
+
if (opts.json) {
|
|
30
|
+
console.log(JSON.stringify(status, null, 2));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
console.log([
|
|
35
|
+
"System Status",
|
|
36
|
+
"-------------",
|
|
37
|
+
`Internal secret configured: ${formatBoolean(status.hasInternalSecret)}`,
|
|
38
|
+
`Relay reachable: ${formatBoolean(status.relayReachable)}`,
|
|
39
|
+
`Relay connected tunnels: ${status.relayConnectedCount}`,
|
|
40
|
+
`TLS mode: ${status.tlsMode}`,
|
|
41
|
+
`Wildcard domains: ${status.wildcardDomains.join(", ")}`,
|
|
42
|
+
`Ask endpoint: ${status.askEndpoint.path} (${status.askEndpoint.protected ? "protected" : "unprotected"})`,
|
|
43
|
+
status.askEndpoint.note ? `Note: ${status.askEndpoint.note}` : "",
|
|
44
|
+
].filter(Boolean).join("\n"));
|
|
45
|
+
})
|
|
46
|
+
)
|
|
47
|
+
.addCommand(
|
|
48
|
+
new Command("explain")
|
|
49
|
+
.description("Explain missing/unsafe settings")
|
|
50
|
+
.action(async () => {
|
|
51
|
+
const status = await fetchStatus();
|
|
52
|
+
const issues: string[] = [];
|
|
53
|
+
|
|
54
|
+
if (!status.hasInternalSecret) {
|
|
55
|
+
issues.push("- RELAY_INTERNAL_SECRET is missing. Set it for backend + relay to protect internal endpoints.");
|
|
56
|
+
}
|
|
57
|
+
if (!status.relayReachable) {
|
|
58
|
+
issues.push("- Relay unreachable via /internal/connected-tokens. Check relay service and secret header.");
|
|
59
|
+
}
|
|
60
|
+
if (status.askEndpoint && !status.askEndpoint.protected) {
|
|
61
|
+
issues.push("- Ask endpoint is not protected; ensure RELAY_INTERNAL_SECRET is set.");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log("System Explain");
|
|
65
|
+
console.log("--------------");
|
|
66
|
+
if (issues.length === 0) {
|
|
67
|
+
console.log("No critical issues detected. TLS mode:", status.tlsMode);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
console.log("Issues:");
|
|
71
|
+
issues.forEach((i) => console.log(i));
|
|
72
|
+
})
|
|
73
|
+
);
|
|
74
|
+
|
package/docs/PRODUCT.md
CHANGED
|
@@ -277,6 +277,15 @@ See [DEPLOYMENT.md](docs/deployment/DEPLOYMENT.md) for production setup.
|
|
|
277
277
|
|
|
278
278
|
---
|
|
279
279
|
|
|
280
|
+
## TLS and Internal Secrets
|
|
281
|
+
|
|
282
|
+
- **Primary TLS**: wildcard DNS-01 (Cloudflare) for `*.x.uplink.spot` and `*.uplink.spot`.
|
|
283
|
+
- **Optional on-demand TLS**: backend ask endpoint `/internal/allow-tls` (protected by `RELAY_INTERNAL_SECRET`) for future custom domains.
|
|
284
|
+
- **Required secrets**: set `RELAY_INTERNAL_SECRET`, `TUNNEL_DOMAIN`, `ALIAS_DOMAIN` in `/opt/agentcloud/.env` on servers; relay and backend services load from that file.
|
|
285
|
+
- **Diagnostics**: `uplink system status` (admin) checks relay reachability, internal secret, TLS mode.
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
280
289
|
## Roadmap
|
|
281
290
|
|
|
282
291
|
Based on the CLI-first philosophy, planned expansions:
|
package/package.json
CHANGED