quicklify 0.5.0 → 0.7.0

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.
Files changed (38) hide show
  1. package/README.md +99 -10
  2. package/dist/commands/doctor.d.ts +10 -0
  3. package/dist/commands/doctor.d.ts.map +1 -0
  4. package/dist/commands/doctor.js +92 -0
  5. package/dist/commands/doctor.js.map +1 -0
  6. package/dist/commands/domain.d.ts +13 -0
  7. package/dist/commands/domain.d.ts.map +1 -0
  8. package/dist/commands/domain.js +218 -0
  9. package/dist/commands/domain.js.map +1 -0
  10. package/dist/commands/firewall.d.ts +15 -0
  11. package/dist/commands/firewall.d.ts.map +1 -0
  12. package/dist/commands/firewall.js +259 -0
  13. package/dist/commands/firewall.js.map +1 -0
  14. package/dist/commands/health.d.ts +9 -0
  15. package/dist/commands/health.d.ts.map +1 -0
  16. package/dist/commands/health.js +56 -0
  17. package/dist/commands/health.js.map +1 -0
  18. package/dist/commands/logs.d.ts +8 -0
  19. package/dist/commands/logs.d.ts.map +1 -0
  20. package/dist/commands/logs.js +53 -0
  21. package/dist/commands/logs.js.map +1 -0
  22. package/dist/commands/monitor.d.ts +13 -0
  23. package/dist/commands/monitor.d.ts.map +1 -0
  24. package/dist/commands/monitor.js +94 -0
  25. package/dist/commands/monitor.js.map +1 -0
  26. package/dist/commands/secure.d.ts +14 -0
  27. package/dist/commands/secure.d.ts.map +1 -0
  28. package/dist/commands/secure.js +294 -0
  29. package/dist/commands/secure.js.map +1 -0
  30. package/dist/index.js +45 -0
  31. package/dist/index.js.map +1 -1
  32. package/dist/types/index.d.ts +25 -0
  33. package/dist/types/index.d.ts.map +1 -1
  34. package/dist/utils/ssh.d.ts +1 -0
  35. package/dist/utils/ssh.d.ts.map +1 -1
  36. package/dist/utils/ssh.js +7 -0
  37. package/dist/utils/ssh.js.map +1 -1
  38. package/package.json +1 -1
@@ -0,0 +1,259 @@
1
+ import inquirer from "inquirer";
2
+ import { resolveServer } from "../utils/serverSelect.js";
3
+ import { checkSshAvailable, sshExec } from "../utils/ssh.js";
4
+ import { logger, createSpinner } from "../utils/logger.js";
5
+ export const PROTECTED_PORTS = [22];
6
+ export const COOLIFY_PORTS = [80, 443, 8000, 6001, 6002];
7
+ export function isValidPort(port) {
8
+ return Number.isInteger(port) && port >= 1 && port <= 65535;
9
+ }
10
+ export function isProtectedPort(port) {
11
+ return PROTECTED_PORTS.includes(port);
12
+ }
13
+ export function buildUfwRuleCommand(action, port, protocol = "tcp") {
14
+ return `ufw ${action} ${port}/${protocol}`;
15
+ }
16
+ export function buildFirewallSetupCommand() {
17
+ const commands = [
18
+ "apt-get install -y ufw",
19
+ "ufw default deny incoming",
20
+ "ufw default allow outgoing",
21
+ ...COOLIFY_PORTS.map((p) => `ufw allow ${p}/tcp`),
22
+ "ufw allow 22/tcp",
23
+ 'echo "y" | ufw enable',
24
+ ];
25
+ return commands.join(" && ");
26
+ }
27
+ export function buildUfwStatusCommand() {
28
+ return "ufw status numbered";
29
+ }
30
+ export function parseUfwStatus(stdout) {
31
+ const lines = stdout.split("\n");
32
+ const active = stdout.toLowerCase().includes("status: active");
33
+ const rules = [];
34
+ for (const line of lines) {
35
+ // Match lines like: [ 1] 22/tcp ALLOW IN Anywhere
36
+ const match = line.match(/\[\s*\d+\]\s+(\d+)\/(tcp|udp)\s+(ALLOW|DENY)\s+IN\s+(.*)/i);
37
+ if (match) {
38
+ rules.push({
39
+ port: parseInt(match[1], 10),
40
+ protocol: match[2].toLowerCase(),
41
+ action: match[3].toUpperCase(),
42
+ from: match[4].trim() || "Anywhere",
43
+ });
44
+ }
45
+ }
46
+ return { active, rules };
47
+ }
48
+ export async function firewallCommand(subcommand, query, options) {
49
+ if (!checkSshAvailable()) {
50
+ logger.error("SSH client not found. Please install OpenSSH.");
51
+ return;
52
+ }
53
+ const validSubcommands = ["setup", "add", "remove", "list", "status"];
54
+ const sub = subcommand || "status";
55
+ if (!validSubcommands.includes(sub)) {
56
+ logger.error(`Invalid subcommand: ${sub}. Choose from: ${validSubcommands.join(", ")}`);
57
+ return;
58
+ }
59
+ const server = await resolveServer(query, "Select a server for firewall management:");
60
+ if (!server)
61
+ return;
62
+ const dryRun = options?.dryRun || false;
63
+ switch (sub) {
64
+ case "setup":
65
+ await firewallSetup(server.ip, server.name, dryRun);
66
+ break;
67
+ case "add":
68
+ await firewallAdd(server.ip, server.name, options, dryRun);
69
+ break;
70
+ case "remove":
71
+ await firewallRemove(server.ip, server.name, options, dryRun);
72
+ break;
73
+ case "list":
74
+ await firewallList(server.ip, server.name);
75
+ break;
76
+ case "status":
77
+ await firewallStatusCheck(server.ip, server.name);
78
+ break;
79
+ }
80
+ }
81
+ async function firewallSetup(ip, name, dryRun) {
82
+ const command = buildFirewallSetupCommand();
83
+ if (dryRun) {
84
+ logger.title("Dry Run - Firewall Setup");
85
+ logger.info(`Server: ${name} (${ip})`);
86
+ console.log();
87
+ logger.info("Commands to execute:");
88
+ for (const cmd of command.split(" && ")) {
89
+ logger.step(cmd);
90
+ }
91
+ console.log();
92
+ logger.warning("No changes applied. Remove --dry-run to execute.");
93
+ return;
94
+ }
95
+ const spinner = createSpinner("Setting up firewall...");
96
+ spinner.start();
97
+ try {
98
+ const result = await sshExec(ip, command);
99
+ if (result.code !== 0) {
100
+ spinner.fail("Failed to setup firewall");
101
+ if (result.stderr)
102
+ logger.error(result.stderr);
103
+ return;
104
+ }
105
+ spinner.succeed("Firewall configured successfully");
106
+ logger.success(`UFW enabled with Coolify ports (${COOLIFY_PORTS.join(", ")}) + SSH (22)`);
107
+ }
108
+ catch (error) {
109
+ spinner.fail("Failed to setup firewall");
110
+ logger.error(error instanceof Error ? error.message : String(error));
111
+ }
112
+ }
113
+ async function firewallAdd(ip, name, options, dryRun) {
114
+ const port = parseInt(options?.port || "", 10);
115
+ if (!options?.port || !isValidPort(port)) {
116
+ logger.error("Invalid or missing --port. Must be 1-65535.");
117
+ return;
118
+ }
119
+ const protocol = options?.protocol || "tcp";
120
+ if (protocol !== "tcp" && protocol !== "udp") {
121
+ logger.error("Invalid --protocol. Must be tcp or udp.");
122
+ return;
123
+ }
124
+ const command = buildUfwRuleCommand("allow", port, protocol);
125
+ if (dryRun) {
126
+ logger.title("Dry Run - Add Firewall Rule");
127
+ logger.info(`Server: ${name} (${ip})`);
128
+ logger.step(command);
129
+ logger.warning("No changes applied. Remove --dry-run to execute.");
130
+ return;
131
+ }
132
+ const spinner = createSpinner(`Opening port ${port}/${protocol}...`);
133
+ spinner.start();
134
+ try {
135
+ const result = await sshExec(ip, command);
136
+ if (result.code !== 0) {
137
+ spinner.fail(`Failed to open port ${port}/${protocol}`);
138
+ if (result.stderr)
139
+ logger.error(result.stderr);
140
+ return;
141
+ }
142
+ spinner.succeed(`Port ${port}/${protocol} opened on ${name}`);
143
+ }
144
+ catch (error) {
145
+ spinner.fail(`Failed to open port ${port}/${protocol}`);
146
+ logger.error(error instanceof Error ? error.message : String(error));
147
+ }
148
+ }
149
+ async function firewallRemove(ip, name, options, dryRun) {
150
+ const port = parseInt(options?.port || "", 10);
151
+ if (!options?.port || !isValidPort(port)) {
152
+ logger.error("Invalid or missing --port. Must be 1-65535.");
153
+ return;
154
+ }
155
+ if (isProtectedPort(port)) {
156
+ logger.error(`Port ${port} is protected and cannot be removed (SSH access).`);
157
+ return;
158
+ }
159
+ const protocol = options?.protocol || "tcp";
160
+ if (protocol !== "tcp" && protocol !== "udp") {
161
+ logger.error("Invalid --protocol. Must be tcp or udp.");
162
+ return;
163
+ }
164
+ if (COOLIFY_PORTS.includes(port)) {
165
+ const { confirm } = await inquirer.prompt([
166
+ {
167
+ type: "confirm",
168
+ name: "confirm",
169
+ message: `Port ${port} is used by Coolify. Are you sure you want to remove it?`,
170
+ default: false,
171
+ },
172
+ ]);
173
+ if (!confirm) {
174
+ logger.info("Remove cancelled.");
175
+ return;
176
+ }
177
+ }
178
+ const command = buildUfwRuleCommand("delete allow", port, protocol);
179
+ if (dryRun) {
180
+ logger.title("Dry Run - Remove Firewall Rule");
181
+ logger.info(`Server: ${name} (${ip})`);
182
+ logger.step(command);
183
+ logger.warning("No changes applied. Remove --dry-run to execute.");
184
+ return;
185
+ }
186
+ const spinner = createSpinner(`Closing port ${port}/${protocol}...`);
187
+ spinner.start();
188
+ try {
189
+ const result = await sshExec(ip, command);
190
+ if (result.code !== 0) {
191
+ spinner.fail(`Failed to close port ${port}/${protocol}`);
192
+ if (result.stderr)
193
+ logger.error(result.stderr);
194
+ return;
195
+ }
196
+ spinner.succeed(`Port ${port}/${protocol} closed on ${name}`);
197
+ }
198
+ catch (error) {
199
+ spinner.fail(`Failed to close port ${port}/${protocol}`);
200
+ logger.error(error instanceof Error ? error.message : String(error));
201
+ }
202
+ }
203
+ async function firewallList(ip, name) {
204
+ const spinner = createSpinner(`Fetching firewall rules from ${name}...`);
205
+ spinner.start();
206
+ try {
207
+ const result = await sshExec(ip, buildUfwStatusCommand());
208
+ if (result.code !== 0) {
209
+ spinner.fail("Failed to fetch firewall rules");
210
+ if (result.stderr)
211
+ logger.error(result.stderr);
212
+ return;
213
+ }
214
+ const status = parseUfwStatus(result.stdout);
215
+ spinner.succeed(`Firewall rules for ${name} (${ip})`);
216
+ if (!status.active) {
217
+ logger.warning("UFW is inactive. Run 'quicklify firewall setup' to enable.");
218
+ return;
219
+ }
220
+ if (status.rules.length === 0) {
221
+ logger.info("No rules configured.");
222
+ return;
223
+ }
224
+ console.log();
225
+ for (const rule of status.rules) {
226
+ logger.step(`${rule.port}/${rule.protocol} → ${rule.action} from ${rule.from}`);
227
+ }
228
+ }
229
+ catch (error) {
230
+ spinner.fail("Failed to fetch firewall rules");
231
+ logger.error(error instanceof Error ? error.message : String(error));
232
+ }
233
+ }
234
+ async function firewallStatusCheck(ip, name) {
235
+ const spinner = createSpinner(`Checking firewall status on ${name}...`);
236
+ spinner.start();
237
+ try {
238
+ const result = await sshExec(ip, "ufw status");
239
+ if (result.code !== 0) {
240
+ spinner.fail("Failed to check firewall status");
241
+ if (result.stderr)
242
+ logger.error(result.stderr);
243
+ return;
244
+ }
245
+ const active = result.stdout.toLowerCase().includes("status: active");
246
+ if (active) {
247
+ spinner.succeed(`UFW is active on ${name}`);
248
+ }
249
+ else {
250
+ spinner.warn(`UFW is inactive on ${name}`);
251
+ logger.info("Run 'quicklify firewall setup' to enable.");
252
+ }
253
+ }
254
+ catch (error) {
255
+ spinner.fail("Failed to check firewall status");
256
+ logger.error(error instanceof Error ? error.message : String(error));
257
+ }
258
+ }
259
+ //# sourceMappingURL=firewall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firewall.js","sourceRoot":"","sources":["../../src/commands/firewall.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { ServerRecord } from "../types/index.js";
2
+ export interface HealthResult {
3
+ server: ServerRecord;
4
+ status: "healthy" | "unhealthy" | "unreachable";
5
+ responseTime: number;
6
+ }
7
+ export declare function checkServerHealth(server: ServerRecord): Promise<HealthResult>;
8
+ export declare function healthCommand(): Promise<void>;
9
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/commands/health.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,aAAa,CAAC;IAChD,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAcnF;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CA+CnD"}
@@ -0,0 +1,56 @@
1
+ import axios from "axios";
2
+ import { getServers } from "../utils/config.js";
3
+ import { logger, createSpinner } from "../utils/logger.js";
4
+ export async function checkServerHealth(server) {
5
+ const start = Date.now();
6
+ try {
7
+ const response = await axios.get(`http://${server.ip}:8000`, {
8
+ timeout: 5000,
9
+ validateStatus: () => true,
10
+ });
11
+ const responseTime = Date.now() - start;
12
+ const status = response.status < 500 ? "healthy" : "unhealthy";
13
+ return { server, status, responseTime };
14
+ }
15
+ catch {
16
+ const responseTime = Date.now() - start;
17
+ return { server, status: "unreachable", responseTime };
18
+ }
19
+ }
20
+ export async function healthCommand() {
21
+ const servers = getServers();
22
+ if (servers.length === 0) {
23
+ logger.info("No servers found. Deploy one with: quicklify init");
24
+ return;
25
+ }
26
+ const spinner = createSpinner(`Checking health of ${servers.length} server(s)...`);
27
+ spinner.start();
28
+ const results = await Promise.all(servers.map(checkServerHealth));
29
+ spinner.succeed("Health check complete");
30
+ console.log();
31
+ // Table header
32
+ const header = `${"Name".padEnd(20)} ${"IP".padEnd(16)} ${"Status".padEnd(14)} ${"Response".padEnd(10)}`;
33
+ console.log(header);
34
+ console.log("─".repeat(header.length));
35
+ // Table rows
36
+ for (const result of results) {
37
+ const statusStr = result.status === "healthy"
38
+ ? "✔ healthy"
39
+ : result.status === "unhealthy"
40
+ ? "⚠ unhealthy"
41
+ : "✖ unreachable";
42
+ const timeStr = result.status === "unreachable" ? "timeout" : `${result.responseTime}ms`;
43
+ console.log(`${result.server.name.padEnd(20)} ${result.server.ip.padEnd(16)} ${statusStr.padEnd(14)} ${timeStr.padEnd(10)}`);
44
+ }
45
+ console.log();
46
+ const healthy = results.filter((r) => r.status === "healthy").length;
47
+ const unhealthy = results.filter((r) => r.status === "unhealthy").length;
48
+ const unreachable = results.filter((r) => r.status === "unreachable").length;
49
+ if (unreachable > 0 || unhealthy > 0) {
50
+ logger.warning(`${healthy} healthy, ${unhealthy} unhealthy, ${unreachable} unreachable`);
51
+ }
52
+ else {
53
+ logger.success(`All ${healthy} server(s) are healthy`);
54
+ }
55
+ }
56
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/commands/health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export type LogService = "coolify" | "docker" | "system";
2
+ export declare function buildLogCommand(service: LogService, lines: number, follow: boolean): string;
3
+ export declare function logsCommand(query?: string, options?: {
4
+ lines?: string;
5
+ follow?: boolean;
6
+ service?: string;
7
+ }): Promise<void>;
8
+ //# sourceMappingURL=logs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEzD,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAS3F;AAED,wBAAsB,WAAW,CAC/B,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/D,OAAO,CAAC,IAAI,CAAC,CAwCf"}
@@ -0,0 +1,53 @@
1
+ import { resolveServer } from "../utils/serverSelect.js";
2
+ import { checkSshAvailable, sshExec, sshStream } from "../utils/ssh.js";
3
+ import { logger } from "../utils/logger.js";
4
+ export function buildLogCommand(service, lines, follow) {
5
+ switch (service) {
6
+ case "coolify":
7
+ return `docker logs coolify --tail ${lines}${follow ? " --follow" : ""}`;
8
+ case "docker":
9
+ return `journalctl -u docker --no-pager -n ${lines}${follow ? " -f" : ""}`;
10
+ case "system":
11
+ return `journalctl --no-pager -n ${lines}${follow ? " -f" : ""}`;
12
+ }
13
+ }
14
+ export async function logsCommand(query, options) {
15
+ if (!checkSshAvailable()) {
16
+ logger.error("SSH client not found. Please install OpenSSH.");
17
+ return;
18
+ }
19
+ const server = await resolveServer(query, "Select a server to view logs:");
20
+ if (!server)
21
+ return;
22
+ const lines = parseInt(options?.lines || "50", 10);
23
+ if (isNaN(lines) || lines <= 0) {
24
+ logger.error("Invalid --lines value. Must be a positive number.");
25
+ return;
26
+ }
27
+ const service = options?.service || "coolify";
28
+ const validServices = ["coolify", "docker", "system"];
29
+ if (!validServices.includes(service)) {
30
+ logger.error(`Invalid service: ${service}. Choose from: ${validServices.join(", ")}`);
31
+ return;
32
+ }
33
+ const follow = options?.follow || false;
34
+ const command = buildLogCommand(service, lines, follow);
35
+ logger.info(`Fetching ${service} logs from ${server.name} (${server.ip})...`);
36
+ if (follow) {
37
+ const exitCode = await sshStream(server.ip, command);
38
+ if (exitCode !== 0) {
39
+ logger.error(`Log stream ended with code ${exitCode}`);
40
+ }
41
+ }
42
+ else {
43
+ const result = await sshExec(server.ip, command);
44
+ if (result.stdout)
45
+ console.log(result.stdout);
46
+ if (result.stderr)
47
+ console.error(result.stderr);
48
+ if (result.code !== 0) {
49
+ logger.error(`Failed to fetch logs (exit code ${result.code})`);
50
+ }
51
+ }
52
+ }
53
+ //# sourceMappingURL=logs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.js","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface SystemMetrics {
2
+ cpu: string;
3
+ ramUsed: string;
4
+ ramTotal: string;
5
+ diskUsed: string;
6
+ diskTotal: string;
7
+ diskPercent: string;
8
+ }
9
+ export declare function parseMetrics(stdout: string): SystemMetrics;
10
+ export declare function monitorCommand(query?: string, options?: {
11
+ containers?: boolean;
12
+ }): Promise<void>;
13
+ //# sourceMappingURL=monitor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitor.d.ts","sourceRoot":"","sources":["../../src/commands/monitor.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAiD1D;AAED,wBAAsB,cAAc,CAClC,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACjC,OAAO,CAAC,IAAI,CAAC,CAiDf"}
@@ -0,0 +1,94 @@
1
+ import { resolveServer } from "../utils/serverSelect.js";
2
+ import { checkSshAvailable, sshExec } from "../utils/ssh.js";
3
+ import { logger, createSpinner } from "../utils/logger.js";
4
+ export function parseMetrics(stdout) {
5
+ const lines = stdout.split("\n");
6
+ // Parse CPU from top output - look for %Cpu(s) line
7
+ let cpu = "N/A";
8
+ for (const line of lines) {
9
+ if (line.includes("Cpu") || line.includes("cpu")) {
10
+ // Match patterns like "0.0 us" or "0.0%us"
11
+ const idleMatch = line.match(/([\d.]+)\s*(?:%?\s*)?id/);
12
+ if (idleMatch) {
13
+ const idle = parseFloat(idleMatch[1]);
14
+ cpu = `${(100 - idle).toFixed(1)}%`;
15
+ }
16
+ break;
17
+ }
18
+ }
19
+ // Parse RAM from free -h output
20
+ let ramUsed = "N/A";
21
+ let ramTotal = "N/A";
22
+ for (const line of lines) {
23
+ if (line.startsWith("Mem:")) {
24
+ const parts = line.split(/\s+/);
25
+ if (parts.length >= 3) {
26
+ ramTotal = parts[1];
27
+ ramUsed = parts[2];
28
+ }
29
+ break;
30
+ }
31
+ }
32
+ // Parse Disk from df -h output - look for "total" line
33
+ let diskUsed = "N/A";
34
+ let diskTotal = "N/A";
35
+ let diskPercent = "N/A";
36
+ for (const line of lines) {
37
+ if (line.startsWith("total") || line.includes("/dev/")) {
38
+ const parts = line.split(/\s+/);
39
+ if (parts.length >= 5) {
40
+ diskTotal = parts[1];
41
+ diskUsed = parts[2];
42
+ diskPercent = parts[4];
43
+ }
44
+ // Prefer "total" line over individual disk lines
45
+ if (line.startsWith("total"))
46
+ break;
47
+ }
48
+ }
49
+ return { cpu, ramUsed, ramTotal, diskUsed, diskTotal, diskPercent };
50
+ }
51
+ export async function monitorCommand(query, options) {
52
+ if (!checkSshAvailable()) {
53
+ logger.error("SSH client not found. Please install OpenSSH.");
54
+ return;
55
+ }
56
+ const server = await resolveServer(query, "Select a server to monitor:");
57
+ if (!server)
58
+ return;
59
+ const spinner = createSpinner(`Fetching metrics from ${server.name}...`);
60
+ spinner.start();
61
+ try {
62
+ // Gather all metrics in a single SSH command
63
+ let command = "top -bn1 | head -5 && echo '---SEPARATOR---' && free -h && echo '---SEPARATOR---' && df -h --total | grep -E '(Filesystem|total)'";
64
+ if (options?.containers) {
65
+ command += " && echo '---SEPARATOR---' && docker ps --format 'table {{.Names}}\\t{{.Status}}\\t{{.Ports}}'";
66
+ }
67
+ const result = await sshExec(server.ip, command);
68
+ if (result.code !== 0) {
69
+ spinner.fail("Failed to fetch metrics");
70
+ if (result.stderr)
71
+ logger.error(result.stderr);
72
+ return;
73
+ }
74
+ spinner.succeed(`Metrics for ${server.name} (${server.ip})`);
75
+ const metrics = parseMetrics(result.stdout);
76
+ console.log();
77
+ logger.info(`CPU Usage: ${metrics.cpu}`);
78
+ logger.info(`RAM Usage: ${metrics.ramUsed} / ${metrics.ramTotal}`);
79
+ logger.info(`Disk Usage: ${metrics.diskUsed} / ${metrics.diskTotal} (${metrics.diskPercent})`);
80
+ if (options?.containers) {
81
+ const sections = result.stdout.split("---SEPARATOR---");
82
+ if (sections.length >= 4) {
83
+ console.log();
84
+ logger.title("Docker Containers");
85
+ console.log(sections[3].trim());
86
+ }
87
+ }
88
+ }
89
+ catch (error) {
90
+ spinner.fail("Failed to fetch metrics");
91
+ logger.error(error instanceof Error ? error.message : String(error));
92
+ }
93
+ }
94
+ //# sourceMappingURL=monitor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitor.js","sourceRoot":"","sources":["../../src/commands/monitor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { SshdSetting, SecureAuditResult } from "../types/index.js";
2
+ export declare function parseSshdConfig(content: string): SshdSetting[];
3
+ export declare function parseAuditResult(stdout: string): SecureAuditResult;
4
+ export declare function buildHardeningCommand(options?: {
5
+ port?: number;
6
+ }): string;
7
+ export declare function buildFail2banCommand(): string;
8
+ export declare function buildAuditCommand(): string;
9
+ export declare function buildKeyCheckCommand(): string;
10
+ export declare function secureCommand(subcommand?: string, query?: string, options?: {
11
+ port?: string;
12
+ dryRun?: boolean;
13
+ }): Promise<void>;
14
+ //# sourceMappingURL=secure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secure.d.ts","sourceRoot":"","sources":["../../src/commands/secure.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAExE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,CA8B9D;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAgClE;AAED,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAezE;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAgB7C;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAsB,aAAa,CACjC,UAAU,CAAC,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC5C,OAAO,CAAC,IAAI,CAAC,CA8Bf"}