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.
- package/README.md +99 -10
- package/dist/commands/doctor.d.ts +10 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +92 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/domain.d.ts +13 -0
- package/dist/commands/domain.d.ts.map +1 -0
- package/dist/commands/domain.js +218 -0
- package/dist/commands/domain.js.map +1 -0
- package/dist/commands/firewall.d.ts +15 -0
- package/dist/commands/firewall.d.ts.map +1 -0
- package/dist/commands/firewall.js +259 -0
- package/dist/commands/firewall.js.map +1 -0
- package/dist/commands/health.d.ts +9 -0
- package/dist/commands/health.d.ts.map +1 -0
- package/dist/commands/health.js +56 -0
- package/dist/commands/health.js.map +1 -0
- package/dist/commands/logs.d.ts +8 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +53 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/monitor.d.ts +13 -0
- package/dist/commands/monitor.d.ts.map +1 -0
- package/dist/commands/monitor.js +94 -0
- package/dist/commands/monitor.js.map +1 -0
- package/dist/commands/secure.d.ts +14 -0
- package/dist/commands/secure.d.ts.map +1 -0
- package/dist/commands/secure.js +294 -0
- package/dist/commands/secure.js.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +25 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/ssh.d.ts +1 -0
- package/dist/utils/ssh.d.ts.map +1 -1
- package/dist/utils/ssh.js +7 -0
- package/dist/utils/ssh.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,6 +50,14 @@ npx quicklify init
|
|
|
50
50
|
- ๐ **SSH Access** - Connect to servers or run remote commands
|
|
51
51
|
- ๐ **Coolify Update** - Update Coolify with one command
|
|
52
52
|
- ๐ฅ **Health Check Polling** - Detects when Coolify is ready (no more blind waiting)
|
|
53
|
+
- ๐ **Server Monitoring** - CPU/RAM/Disk usage and Docker container status
|
|
54
|
+
- ๐ **Log Viewer** - View Coolify, Docker, or system logs with follow mode
|
|
55
|
+
- ๐ฉบ **Environment Doctor** - Diagnose local setup issues
|
|
56
|
+
- ๐ซ **Bulk Health Check** - Check all servers at once
|
|
57
|
+
- ๐ฅ **Firewall Management** - UFW setup, add/remove ports, protected port safety
|
|
58
|
+
- ๐ **Domain Management** - Bind domains, DNS check, auto SSL via Coolify
|
|
59
|
+
- ๐ก๏ธ **SSH Hardening** - Disable password auth, fail2ban, security audit with score
|
|
60
|
+
- ๐งช **Dry-Run Mode** - Preview commands on firewall/domain/secure before executing
|
|
53
61
|
- ๐ค **Non-Interactive Mode** - CI/CD friendly with `--provider --token --region --size --name` flags
|
|
54
62
|
|
|
55
63
|
## ๐ฆ Installation
|
|
@@ -116,12 +124,12 @@ Visit the URL, create your admin account, and start deploying!
|
|
|
116
124
|
**Important:** Port 8000 is publicly accessible after deployment.
|
|
117
125
|
|
|
118
126
|
**Recommended next steps:**
|
|
119
|
-
1. **
|
|
120
|
-
2.
|
|
121
|
-
3.
|
|
122
|
-
4.
|
|
123
|
-
|
|
124
|
-
|
|
127
|
+
1. **Setup firewall:** `quicklify firewall setup my-server`
|
|
128
|
+
2. **Add a domain:** `quicklify domain add my-server --domain example.com`
|
|
129
|
+
3. **Harden SSH:** `quicklify secure setup my-server`
|
|
130
|
+
4. **Run security audit:** `quicklify secure audit my-server`
|
|
131
|
+
5. Set a **strong password** on first login
|
|
132
|
+
6. Consider **Cloudflare** for DDoS protection
|
|
125
133
|
|
|
126
134
|
## ๐ Supported Providers
|
|
127
135
|
|
|
@@ -162,6 +170,22 @@ For production use, we recommend setting up a domain instead of using the IP add
|
|
|
162
170
|
|
|
163
171
|
## ๐ Recent Updates
|
|
164
172
|
|
|
173
|
+
### v0.7.0 (2026-02-20)
|
|
174
|
+
- **New commands:** `quicklify firewall`, `quicklify domain`, `quicklify secure`
|
|
175
|
+
- **Firewall management:** UFW setup, add/remove ports, protected port 22 safety, Coolify port warnings
|
|
176
|
+
- **Domain management:** Bind domains to Coolify, DNS A record check, auto SSL
|
|
177
|
+
- **SSH hardening:** Disable password auth, key-only root login, fail2ban, security audit with 0-4 score
|
|
178
|
+
- **Dry-run mode:** `--dry-run` flag previews all commands without executing
|
|
179
|
+
- Zero new dependencies, 494 tests with 97%+ statement coverage
|
|
180
|
+
|
|
181
|
+
### v0.6.0 (2026-02-20)
|
|
182
|
+
- **New commands:** `quicklify logs`, `quicklify monitor`, `quicklify health`, `quicklify doctor`
|
|
183
|
+
- **Log viewer:** View Coolify/Docker/system logs with `--follow` real-time streaming
|
|
184
|
+
- **Server monitoring:** CPU/RAM/Disk usage and Docker container list
|
|
185
|
+
- **Bulk health check:** Check all registered servers at once with response times
|
|
186
|
+
- **Environment doctor:** Diagnose Node.js, SSH, config issues locally
|
|
187
|
+
- Zero new dependencies, 354 tests with 97%+ statement coverage
|
|
188
|
+
|
|
165
189
|
### v0.5.0 (2026-02-20)
|
|
166
190
|
- **New commands:** `quicklify config`, `quicklify ssh`, `quicklify update`, `quicklify restart`
|
|
167
191
|
- **Default config:** Set defaults for provider, region, size with `quicklify config set`
|
|
@@ -238,14 +262,26 @@ For production use, we recommend setting up a domain instead of using the IP add
|
|
|
238
262
|
- [x] Server restart via provider API (`quicklify restart`)
|
|
239
263
|
- [x] Shared server selection and token utilities (DRY refactor)
|
|
240
264
|
|
|
265
|
+
### v0.6.0 (Completed)
|
|
266
|
+
|
|
267
|
+
- [x] Server monitoring - CPU/RAM/Disk usage (`quicklify monitor`)
|
|
268
|
+
- [x] Log viewer - Coolify/Docker/system logs (`quicklify logs`)
|
|
269
|
+
- [x] Bulk health check for all servers (`quicklify health`)
|
|
270
|
+
- [x] Environment diagnostics (`quicklify doctor`)
|
|
271
|
+
- [x] SSH streaming for real-time log following
|
|
272
|
+
|
|
273
|
+
### v0.7.0 (Completed)
|
|
274
|
+
|
|
275
|
+
- [x] Firewall management - UFW setup, add/remove ports (`quicklify firewall`)
|
|
276
|
+
- [x] Domain management - Bind domains, DNS check, SSL (`quicklify domain`)
|
|
277
|
+
- [x] SSH hardening - Password disable, fail2ban, security audit (`quicklify secure`)
|
|
278
|
+
- [x] Dry-run mode for all security commands
|
|
279
|
+
|
|
241
280
|
### Future
|
|
242
281
|
- [ ] Vultr support
|
|
243
282
|
- [ ] Linode / AWS Lightsail support
|
|
244
|
-
- [ ] Domain + SSL configuration helper
|
|
245
283
|
- [ ] Backup/restore commands
|
|
246
|
-
- [ ] Server monitoring (CPU/RAM/Disk)
|
|
247
284
|
- [ ] Interactive TUI dashboard
|
|
248
|
-
- [ ] Firewall management
|
|
249
285
|
|
|
250
286
|
## ๐ ๏ธ Tech Stack
|
|
251
287
|
|
|
@@ -298,6 +334,52 @@ quicklify update my-server
|
|
|
298
334
|
# Restart a server
|
|
299
335
|
quicklify restart my-server
|
|
300
336
|
|
|
337
|
+
# View Coolify logs (last 50 lines)
|
|
338
|
+
quicklify logs my-server
|
|
339
|
+
|
|
340
|
+
# Follow Coolify logs in real-time
|
|
341
|
+
quicklify logs my-server --follow
|
|
342
|
+
|
|
343
|
+
# View Docker or system logs
|
|
344
|
+
quicklify logs my-server --service docker --lines 100
|
|
345
|
+
quicklify logs my-server --service system
|
|
346
|
+
|
|
347
|
+
# Show CPU/RAM/Disk usage
|
|
348
|
+
quicklify monitor my-server
|
|
349
|
+
|
|
350
|
+
# Show usage with Docker containers
|
|
351
|
+
quicklify monitor my-server --containers
|
|
352
|
+
|
|
353
|
+
# Check health of all servers
|
|
354
|
+
quicklify health
|
|
355
|
+
|
|
356
|
+
# Run environment diagnostics
|
|
357
|
+
quicklify doctor
|
|
358
|
+
|
|
359
|
+
# Firewall management
|
|
360
|
+
quicklify firewall setup my-server # Install UFW + Coolify ports
|
|
361
|
+
quicklify firewall add my-server --port 3000 # Open port 3000/tcp
|
|
362
|
+
quicklify firewall add my-server --port 53 --protocol udp # Open port 53/udp
|
|
363
|
+
quicklify firewall remove my-server --port 3000 # Close port 3000
|
|
364
|
+
quicklify firewall list my-server # Show firewall rules
|
|
365
|
+
quicklify firewall status my-server # Check UFW active/inactive
|
|
366
|
+
quicklify firewall setup my-server --dry-run # Preview without executing
|
|
367
|
+
|
|
368
|
+
# Domain management
|
|
369
|
+
quicklify domain add my-server --domain example.com # Bind domain + HTTPS
|
|
370
|
+
quicklify domain add my-server --domain example.com --no-ssl # HTTP only
|
|
371
|
+
quicklify domain remove my-server # Revert to IP:8000
|
|
372
|
+
quicklify domain check my-server --domain example.com # Verify DNS
|
|
373
|
+
quicklify domain list my-server # Show current domain
|
|
374
|
+
quicklify domain add my-server --domain example.com --dry-run # Preview
|
|
375
|
+
|
|
376
|
+
# SSH hardening & security
|
|
377
|
+
quicklify secure status my-server # Show security settings
|
|
378
|
+
quicklify secure audit my-server # Security score (0-4)
|
|
379
|
+
quicklify secure setup my-server # Harden SSH + install fail2ban
|
|
380
|
+
quicklify secure setup my-server --port 2222 # Change SSH port
|
|
381
|
+
quicklify secure setup my-server --dry-run # Preview without executing
|
|
382
|
+
|
|
301
383
|
# Show version
|
|
302
384
|
quicklify --version
|
|
303
385
|
|
|
@@ -378,13 +460,20 @@ tests/
|
|
|
378
460
|
โ โโโ config-command.test.ts # Config command subcommands
|
|
379
461
|
โ โโโ defaults.test.ts # Default config CRUD
|
|
380
462
|
โ โโโ destroy.test.ts # Destroy command unit tests
|
|
463
|
+
โ โโโ doctor.test.ts # Doctor command tests
|
|
464
|
+
โ โโโ domain.test.ts # Domain command tests
|
|
465
|
+
โ โโโ firewall.test.ts # Firewall command tests
|
|
466
|
+
โ โโโ health-command.test.ts # Health command tests
|
|
381
467
|
โ โโโ healthCheck.test.ts # Health check polling tests
|
|
382
468
|
โ โโโ healthCheck-edge.test.ts # Health check edge cases (302, 401, 500)
|
|
383
469
|
โ โโโ list.test.ts # List command unit tests
|
|
384
470
|
โ โโโ logger.test.ts
|
|
471
|
+
โ โโโ logs.test.ts # Logs command tests
|
|
472
|
+
โ โโโ monitor.test.ts # Monitor command tests
|
|
385
473
|
โ โโโ prompts.test.ts
|
|
386
474
|
โ โโโ providerFactory.test.ts # Provider factory tests
|
|
387
475
|
โ โโโ restart.test.ts # Restart command tests
|
|
476
|
+
โ โโโ secure.test.ts # Secure command tests
|
|
388
477
|
โ โโโ serverSelect.test.ts # Server selection utility tests
|
|
389
478
|
โ โโโ ssh-command.test.ts # SSH command tests
|
|
390
479
|
โ โโโ ssh-utils.test.ts # SSH helper tests
|
|
@@ -410,7 +499,7 @@ Tests run automatically on every push/PR via GitHub Actions across:
|
|
|
410
499
|
|
|
411
500
|
### Coverage
|
|
412
501
|
|
|
413
|
-
Current coverage: **97%+ statements/lines**, **
|
|
502
|
+
Current coverage: **97%+ statements/lines**, **85%+ branches**, **96%+ functions**. 494 tests across 32 test suites.
|
|
414
503
|
|
|
415
504
|
## ๐ง Troubleshooting
|
|
416
505
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface CheckResult {
|
|
2
|
+
name: string;
|
|
3
|
+
status: "pass" | "fail" | "warn";
|
|
4
|
+
detail: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function runDoctorChecks(version?: string): CheckResult[];
|
|
7
|
+
export declare function doctorCommand(options?: {
|
|
8
|
+
checkTokens?: boolean;
|
|
9
|
+
}, version?: string): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=doctor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;CAChB;AAsDD,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE,CAS/D;AAED,wBAAsB,aAAa,CACjC,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,EACnC,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CA8Bf"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
import { existsSync, accessSync, constants } from "fs";
|
|
3
|
+
import { getServers } from "../utils/config.js";
|
|
4
|
+
import { checkSshAvailable } from "../utils/ssh.js";
|
|
5
|
+
import { logger } from "../utils/logger.js";
|
|
6
|
+
import { CONFIG_DIR } from "../utils/config.js";
|
|
7
|
+
function checkNodeVersion() {
|
|
8
|
+
const version = process.version;
|
|
9
|
+
const major = parseInt(version.slice(1).split(".")[0], 10);
|
|
10
|
+
if (major >= 20) {
|
|
11
|
+
return { name: "Node.js", status: "pass", detail: version };
|
|
12
|
+
}
|
|
13
|
+
return { name: "Node.js", status: "fail", detail: `${version} (requires >= 20)` };
|
|
14
|
+
}
|
|
15
|
+
function checkNpmVersion() {
|
|
16
|
+
try {
|
|
17
|
+
const version = execSync("npm --version", { stdio: "pipe" }).toString().trim();
|
|
18
|
+
return { name: "npm", status: "pass", detail: `v${version}` };
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return { name: "npm", status: "fail", detail: "not found" };
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function checkSsh() {
|
|
25
|
+
if (checkSshAvailable()) {
|
|
26
|
+
return { name: "SSH Client", status: "pass", detail: "available" };
|
|
27
|
+
}
|
|
28
|
+
return { name: "SSH Client", status: "warn", detail: "not found (needed for ssh/logs/monitor/update)" };
|
|
29
|
+
}
|
|
30
|
+
function checkQuicklifyVersion(version) {
|
|
31
|
+
if (version) {
|
|
32
|
+
return { name: "quicklify", status: "pass", detail: `v${version}` };
|
|
33
|
+
}
|
|
34
|
+
return { name: "quicklify", status: "warn", detail: "version unknown" };
|
|
35
|
+
}
|
|
36
|
+
function checkConfigDir() {
|
|
37
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
38
|
+
return { name: "Config Dir", status: "warn", detail: `${CONFIG_DIR} (not created yet)` };
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
accessSync(CONFIG_DIR, constants.R_OK | constants.W_OK);
|
|
42
|
+
return { name: "Config Dir", status: "pass", detail: CONFIG_DIR };
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return { name: "Config Dir", status: "fail", detail: `${CONFIG_DIR} (not writable)` };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function checkRegisteredServers() {
|
|
49
|
+
const servers = getServers();
|
|
50
|
+
if (servers.length === 0) {
|
|
51
|
+
return { name: "Servers", status: "warn", detail: "0 registered (run quicklify init)" };
|
|
52
|
+
}
|
|
53
|
+
return { name: "Servers", status: "pass", detail: `${servers.length} registered` };
|
|
54
|
+
}
|
|
55
|
+
export function runDoctorChecks(version) {
|
|
56
|
+
return [
|
|
57
|
+
checkNodeVersion(),
|
|
58
|
+
checkNpmVersion(),
|
|
59
|
+
checkSsh(),
|
|
60
|
+
checkQuicklifyVersion(version),
|
|
61
|
+
checkConfigDir(),
|
|
62
|
+
checkRegisteredServers(),
|
|
63
|
+
];
|
|
64
|
+
}
|
|
65
|
+
export async function doctorCommand(options, version) {
|
|
66
|
+
logger.title("Quicklify Doctor");
|
|
67
|
+
const results = runDoctorChecks(version);
|
|
68
|
+
for (const result of results) {
|
|
69
|
+
const colorFn = result.status === "pass"
|
|
70
|
+
? logger.success
|
|
71
|
+
: result.status === "warn"
|
|
72
|
+
? logger.warning
|
|
73
|
+
: logger.error;
|
|
74
|
+
colorFn(`${result.name}: ${result.detail}`);
|
|
75
|
+
}
|
|
76
|
+
const failures = results.filter((r) => r.status === "fail");
|
|
77
|
+
const warnings = results.filter((r) => r.status === "warn");
|
|
78
|
+
console.log();
|
|
79
|
+
if (failures.length > 0) {
|
|
80
|
+
logger.error(`${failures.length} check(s) failed. Please fix the issues above.`);
|
|
81
|
+
}
|
|
82
|
+
else if (warnings.length > 0) {
|
|
83
|
+
logger.warning(`All checks passed with ${warnings.length} warning(s).`);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
logger.success("All checks passed! Your environment is ready.");
|
|
87
|
+
}
|
|
88
|
+
if (options?.checkTokens) {
|
|
89
|
+
logger.info("Token validation is not yet implemented.");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function isValidDomain(domain: string): boolean;
|
|
2
|
+
export declare function sanitizeDomain(input: string): string;
|
|
3
|
+
export declare function buildSetFqdnCommand(domain: string, ssl: boolean): string;
|
|
4
|
+
export declare function buildGetFqdnCommand(): string;
|
|
5
|
+
export declare function buildDnsCheckCommand(domain: string): string;
|
|
6
|
+
export declare function parseDnsResult(stdout: string): string | null;
|
|
7
|
+
export declare function parseFqdn(stdout: string): string | null;
|
|
8
|
+
export declare function domainCommand(subcommand?: string, query?: string, options?: {
|
|
9
|
+
domain?: string;
|
|
10
|
+
ssl?: boolean;
|
|
11
|
+
dryRun?: boolean;
|
|
12
|
+
}): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=domain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../src/commands/domain.ts"],"names":[],"mappings":"AAMA,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAIrD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CASpD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,CAIxE;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI5D;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIvD;AAED,wBAAsB,aAAa,CACjC,UAAU,CAAC,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7D,OAAO,CAAC,IAAI,CAAC,CAiCf"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { resolveServer } from "../utils/serverSelect.js";
|
|
2
|
+
import { checkSshAvailable, sshExec } from "../utils/ssh.js";
|
|
3
|
+
import { logger, createSpinner } from "../utils/logger.js";
|
|
4
|
+
const COOLIFY_ENV_PATH = "/data/coolify/source/.env";
|
|
5
|
+
export function isValidDomain(domain) {
|
|
6
|
+
// RFC 1035 compliant domain validation
|
|
7
|
+
const pattern = /^(?!-)[a-zA-Z0-9-]{1,63}(?<!-)(\.[a-zA-Z0-9-]{1,63})*\.[a-zA-Z]{2,}$/;
|
|
8
|
+
return pattern.test(domain);
|
|
9
|
+
}
|
|
10
|
+
export function sanitizeDomain(input) {
|
|
11
|
+
let domain = input.trim();
|
|
12
|
+
// Strip protocol prefix
|
|
13
|
+
domain = domain.replace(/^https?:\/\//, "");
|
|
14
|
+
// Strip trailing slash
|
|
15
|
+
domain = domain.replace(/\/+$/, "");
|
|
16
|
+
// Strip port
|
|
17
|
+
domain = domain.replace(/:\d+$/, "");
|
|
18
|
+
return domain;
|
|
19
|
+
}
|
|
20
|
+
export function buildSetFqdnCommand(domain, ssl) {
|
|
21
|
+
const protocol = ssl ? "https" : "http";
|
|
22
|
+
const url = `${protocol}://${domain}`;
|
|
23
|
+
return `sed -i 's|^APP_URL=.*|APP_URL=${url}|' ${COOLIFY_ENV_PATH} && cd /data/coolify/source && docker compose up -d --force-recreate`;
|
|
24
|
+
}
|
|
25
|
+
export function buildGetFqdnCommand() {
|
|
26
|
+
return `grep '^APP_URL=' ${COOLIFY_ENV_PATH}`;
|
|
27
|
+
}
|
|
28
|
+
export function buildDnsCheckCommand(domain) {
|
|
29
|
+
return `dig +short A ${domain} 2>/dev/null || host -t A ${domain} 2>/dev/null || nslookup ${domain} 2>/dev/null`;
|
|
30
|
+
}
|
|
31
|
+
export function parseDnsResult(stdout) {
|
|
32
|
+
// dig +short returns just IP addresses
|
|
33
|
+
const ipMatch = stdout.match(/\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b/);
|
|
34
|
+
return ipMatch ? ipMatch[1] : null;
|
|
35
|
+
}
|
|
36
|
+
export function parseFqdn(stdout) {
|
|
37
|
+
const match = stdout.match(/^APP_URL=(.+)$/m);
|
|
38
|
+
if (!match)
|
|
39
|
+
return null;
|
|
40
|
+
return match[1].trim();
|
|
41
|
+
}
|
|
42
|
+
export async function domainCommand(subcommand, query, options) {
|
|
43
|
+
if (!checkSshAvailable()) {
|
|
44
|
+
logger.error("SSH client not found. Please install OpenSSH.");
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const validSubcommands = ["add", "remove", "check", "list"];
|
|
48
|
+
const sub = subcommand || "list";
|
|
49
|
+
if (!validSubcommands.includes(sub)) {
|
|
50
|
+
logger.error(`Invalid subcommand: ${sub}. Choose from: ${validSubcommands.join(", ")}`);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const server = await resolveServer(query, "Select a server for domain management:");
|
|
54
|
+
if (!server)
|
|
55
|
+
return;
|
|
56
|
+
const dryRun = options?.dryRun || false;
|
|
57
|
+
switch (sub) {
|
|
58
|
+
case "add":
|
|
59
|
+
await domainAdd(server.ip, server.name, options, dryRun);
|
|
60
|
+
break;
|
|
61
|
+
case "remove":
|
|
62
|
+
await domainRemove(server.ip, server.name, dryRun);
|
|
63
|
+
break;
|
|
64
|
+
case "check":
|
|
65
|
+
await domainCheck(server.ip, options);
|
|
66
|
+
break;
|
|
67
|
+
case "list":
|
|
68
|
+
await domainList(server.ip, server.name);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async function domainAdd(ip, name, options, dryRun) {
|
|
73
|
+
if (!options?.domain) {
|
|
74
|
+
logger.error("Missing --domain. Usage: quicklify domain add <server> --domain example.com");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const domain = sanitizeDomain(options.domain);
|
|
78
|
+
if (!isValidDomain(domain)) {
|
|
79
|
+
logger.error(`Invalid domain: ${domain}`);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const ssl = options?.ssl !== false; // default true
|
|
83
|
+
const command = buildSetFqdnCommand(domain, ssl);
|
|
84
|
+
if (dryRun) {
|
|
85
|
+
logger.title("Dry Run - Add Domain");
|
|
86
|
+
logger.info(`Server: ${name} (${ip})`);
|
|
87
|
+
logger.info(`Domain: ${domain}`);
|
|
88
|
+
logger.info(`SSL: ${ssl ? "enabled" : "disabled"}`);
|
|
89
|
+
console.log();
|
|
90
|
+
logger.info("Commands to execute:");
|
|
91
|
+
for (const cmd of command.split(" && ")) {
|
|
92
|
+
logger.step(cmd);
|
|
93
|
+
}
|
|
94
|
+
console.log();
|
|
95
|
+
logger.warning("No changes applied. Remove --dry-run to execute.");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const spinner = createSpinner(`Setting domain to ${domain}...`);
|
|
99
|
+
spinner.start();
|
|
100
|
+
try {
|
|
101
|
+
// Check if .env file exists
|
|
102
|
+
const checkResult = await sshExec(ip, `test -f ${COOLIFY_ENV_PATH} && echo "exists"`);
|
|
103
|
+
if (!checkResult.stdout.includes("exists")) {
|
|
104
|
+
spinner.fail("Coolify environment file not found");
|
|
105
|
+
logger.error(`Expected: ${COOLIFY_ENV_PATH}`);
|
|
106
|
+
logger.info("Is Coolify installed on this server?");
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const result = await sshExec(ip, command);
|
|
110
|
+
if (result.code !== 0) {
|
|
111
|
+
spinner.fail("Failed to set domain");
|
|
112
|
+
if (result.stderr)
|
|
113
|
+
logger.error(result.stderr);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
spinner.succeed(`Domain set to ${domain} on ${name}`);
|
|
117
|
+
const protocol = ssl ? "https" : "http";
|
|
118
|
+
logger.success(`Coolify is now accessible at ${protocol}://${domain}`);
|
|
119
|
+
logger.info("Make sure your DNS A record points to " + ip);
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
spinner.fail("Failed to set domain");
|
|
123
|
+
logger.error(error instanceof Error ? error.message : String(error));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function domainRemove(ip, name, dryRun) {
|
|
127
|
+
const command = buildSetFqdnCommand(`${ip}:8000`, false);
|
|
128
|
+
if (dryRun) {
|
|
129
|
+
logger.title("Dry Run - Remove Domain");
|
|
130
|
+
logger.info(`Server: ${name} (${ip})`);
|
|
131
|
+
logger.info(`Will reset to: http://${ip}:8000`);
|
|
132
|
+
console.log();
|
|
133
|
+
logger.info("Commands to execute:");
|
|
134
|
+
for (const cmd of command.split(" && ")) {
|
|
135
|
+
logger.step(cmd);
|
|
136
|
+
}
|
|
137
|
+
console.log();
|
|
138
|
+
logger.warning("No changes applied. Remove --dry-run to execute.");
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const spinner = createSpinner("Removing domain...");
|
|
142
|
+
spinner.start();
|
|
143
|
+
try {
|
|
144
|
+
const result = await sshExec(ip, command);
|
|
145
|
+
if (result.code !== 0) {
|
|
146
|
+
spinner.fail("Failed to remove domain");
|
|
147
|
+
if (result.stderr)
|
|
148
|
+
logger.error(result.stderr);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
spinner.succeed(`Domain removed from ${name}`);
|
|
152
|
+
logger.success(`Coolify is now accessible at http://${ip}:8000`);
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
spinner.fail("Failed to remove domain");
|
|
156
|
+
logger.error(error instanceof Error ? error.message : String(error));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async function domainCheck(ip, options) {
|
|
160
|
+
if (!options?.domain) {
|
|
161
|
+
logger.error("Missing --domain. Usage: quicklify domain check <server> --domain example.com");
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const domain = sanitizeDomain(options.domain);
|
|
165
|
+
if (!isValidDomain(domain)) {
|
|
166
|
+
logger.error(`Invalid domain: ${domain}`);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const spinner = createSpinner(`Checking DNS for ${domain}...`);
|
|
170
|
+
spinner.start();
|
|
171
|
+
try {
|
|
172
|
+
const result = await sshExec(ip, buildDnsCheckCommand(domain));
|
|
173
|
+
const resolvedIp = parseDnsResult(result.stdout);
|
|
174
|
+
if (!resolvedIp) {
|
|
175
|
+
spinner.fail(`No A record found for ${domain}`);
|
|
176
|
+
logger.info("Add an A record pointing to " + ip);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (resolvedIp === ip) {
|
|
180
|
+
spinner.succeed(`DNS OK: ${domain} โ ${resolvedIp}`);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
spinner.warn(`DNS mismatch: ${domain} โ ${resolvedIp} (expected ${ip})`);
|
|
184
|
+
logger.info("Update your A record to point to " + ip);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
spinner.fail("Failed to check DNS");
|
|
189
|
+
logger.error(error instanceof Error ? error.message : String(error));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async function domainList(ip, name) {
|
|
193
|
+
const spinner = createSpinner(`Fetching domain from ${name}...`);
|
|
194
|
+
spinner.start();
|
|
195
|
+
try {
|
|
196
|
+
const result = await sshExec(ip, buildGetFqdnCommand());
|
|
197
|
+
if (result.code !== 0) {
|
|
198
|
+
spinner.fail("Failed to fetch domain");
|
|
199
|
+
if (result.stderr)
|
|
200
|
+
logger.error(result.stderr);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const fqdn = parseFqdn(result.stdout);
|
|
204
|
+
if (fqdn) {
|
|
205
|
+
spinner.succeed(`Current domain for ${name}`);
|
|
206
|
+
logger.info(`APP_URL: ${fqdn}`);
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
spinner.succeed(`No custom domain set for ${name}`);
|
|
210
|
+
logger.info(`Default: http://${ip}:8000`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
spinner.fail("Failed to fetch domain");
|
|
215
|
+
logger.error(error instanceof Error ? error.message : String(error));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=domain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain.js","sourceRoot":"","sources":["../../src/commands/domain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { FirewallStatus, FirewallProtocol } from "../types/index.js";
|
|
2
|
+
export declare const PROTECTED_PORTS: number[];
|
|
3
|
+
export declare const COOLIFY_PORTS: number[];
|
|
4
|
+
export declare function isValidPort(port: number): boolean;
|
|
5
|
+
export declare function isProtectedPort(port: number): boolean;
|
|
6
|
+
export declare function buildUfwRuleCommand(action: "allow" | "delete allow", port: number, protocol?: FirewallProtocol): string;
|
|
7
|
+
export declare function buildFirewallSetupCommand(): string;
|
|
8
|
+
export declare function buildUfwStatusCommand(): string;
|
|
9
|
+
export declare function parseUfwStatus(stdout: string): FirewallStatus;
|
|
10
|
+
export declare function firewallCommand(subcommand?: string, query?: string, options?: {
|
|
11
|
+
port?: string;
|
|
12
|
+
protocol?: string;
|
|
13
|
+
dryRun?: boolean;
|
|
14
|
+
}): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=firewall.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"firewall.d.ts","sourceRoot":"","sources":["../../src/commands/firewall.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAgB,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAExF,eAAO,MAAM,eAAe,UAAO,CAAC;AACpC,eAAO,MAAM,aAAa,UAA8B,CAAC;AAEzD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,OAAO,GAAG,cAAc,EAChC,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,gBAAwB,GACjC,MAAM,CAER;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAUlD;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAmB7D;AAED,wBAAsB,eAAe,CACnC,UAAU,CAAC,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC/D,OAAO,CAAC,IAAI,CAAC,CAoCf"}
|