quicklify 0.6.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 CHANGED
@@ -54,6 +54,10 @@ npx quicklify init
54
54
  - ๐Ÿ“œ **Log Viewer** - View Coolify, Docker, or system logs with follow mode
55
55
  - ๐Ÿฉบ **Environment Doctor** - Diagnose local setup issues
56
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
57
61
  - ๐Ÿค– **Non-Interactive Mode** - CI/CD friendly with `--provider --token --region --size --name` flags
58
62
 
59
63
  ## ๐Ÿ“ฆ Installation
@@ -120,12 +124,12 @@ Visit the URL, create your admin account, and start deploying!
120
124
  **Important:** Port 8000 is publicly accessible after deployment.
121
125
 
122
126
  **Recommended next steps:**
123
- 1. **Add a domain** and enable SSL in Coolify settings
124
- 2. Use **Cloudflare** for DDoS protection
125
- 3. Set a **strong password** on first login
126
- 4. Consider **IP whitelisting** for sensitive deployments
127
-
128
- For production use, we recommend setting up a domain instead of using the IP address directly.
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
129
133
 
130
134
  ## ๐ŸŒ Supported Providers
131
135
 
@@ -166,6 +170,14 @@ For production use, we recommend setting up a domain instead of using the IP add
166
170
 
167
171
  ## ๐Ÿ“‹ Recent Updates
168
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
+
169
181
  ### v0.6.0 (2026-02-20)
170
182
  - **New commands:** `quicklify logs`, `quicklify monitor`, `quicklify health`, `quicklify doctor`
171
183
  - **Log viewer:** View Coolify/Docker/system logs with `--follow` real-time streaming
@@ -258,13 +270,18 @@ For production use, we recommend setting up a domain instead of using the IP add
258
270
  - [x] Environment diagnostics (`quicklify doctor`)
259
271
  - [x] SSH streaming for real-time log following
260
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
+
261
280
  ### Future
262
281
  - [ ] Vultr support
263
282
  - [ ] Linode / AWS Lightsail support
264
- - [ ] Domain + SSL configuration helper
265
283
  - [ ] Backup/restore commands
266
284
  - [ ] Interactive TUI dashboard
267
- - [ ] Firewall management
268
285
 
269
286
  ## ๐Ÿ› ๏ธ Tech Stack
270
287
 
@@ -339,6 +356,30 @@ quicklify health
339
356
  # Run environment diagnostics
340
357
  quicklify doctor
341
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
+
342
383
  # Show version
343
384
  quicklify --version
344
385
 
@@ -420,6 +461,8 @@ tests/
420
461
  โ”‚ โ”œโ”€โ”€ defaults.test.ts # Default config CRUD
421
462
  โ”‚ โ”œโ”€โ”€ destroy.test.ts # Destroy command unit tests
422
463
  โ”‚ โ”œโ”€โ”€ doctor.test.ts # Doctor command tests
464
+ โ”‚ โ”œโ”€โ”€ domain.test.ts # Domain command tests
465
+ โ”‚ โ”œโ”€โ”€ firewall.test.ts # Firewall command tests
423
466
  โ”‚ โ”œโ”€โ”€ health-command.test.ts # Health command tests
424
467
  โ”‚ โ”œโ”€โ”€ healthCheck.test.ts # Health check polling tests
425
468
  โ”‚ โ”œโ”€โ”€ healthCheck-edge.test.ts # Health check edge cases (302, 401, 500)
@@ -430,6 +473,7 @@ tests/
430
473
  โ”‚ โ”œโ”€โ”€ prompts.test.ts
431
474
  โ”‚ โ”œโ”€โ”€ providerFactory.test.ts # Provider factory tests
432
475
  โ”‚ โ”œโ”€โ”€ restart.test.ts # Restart command tests
476
+ โ”‚ โ”œโ”€โ”€ secure.test.ts # Secure command tests
433
477
  โ”‚ โ”œโ”€โ”€ serverSelect.test.ts # Server selection utility tests
434
478
  โ”‚ โ”œโ”€โ”€ ssh-command.test.ts # SSH command tests
435
479
  โ”‚ โ”œโ”€โ”€ ssh-utils.test.ts # SSH helper tests
@@ -455,7 +499,7 @@ Tests run automatically on every push/PR via GitHub Actions across:
455
499
 
456
500
  ### Coverage
457
501
 
458
- Current coverage: **97%+ statements/lines**, **87%+ branches**, **96%+ functions**. 354 tests across 29 test suites.
502
+ Current coverage: **97%+ statements/lines**, **85%+ branches**, **96%+ functions**. 494 tests across 32 test suites.
459
503
 
460
504
  ## ๐Ÿ”ง Troubleshooting
461
505
 
@@ -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"}
@@ -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,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"}
@@ -0,0 +1,294 @@
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 function parseSshdConfig(content) {
6
+ const settings = [];
7
+ const checks = [
8
+ { key: "PasswordAuthentication", secureValue: "no" },
9
+ { key: "PermitRootLogin", secureValue: "prohibit-password" },
10
+ { key: "PubkeyAuthentication", secureValue: "yes" },
11
+ { key: "MaxAuthTries", secureValue: "3" },
12
+ ];
13
+ for (const check of checks) {
14
+ const regex = new RegExp(`^\\s*${check.key}\\s+(.+)`, "m");
15
+ const match = content.match(regex);
16
+ if (match) {
17
+ const value = match[1].trim();
18
+ settings.push({
19
+ key: check.key,
20
+ value,
21
+ status: value.toLowerCase() === check.secureValue.toLowerCase() ? "secure" : "insecure",
22
+ });
23
+ }
24
+ else {
25
+ settings.push({
26
+ key: check.key,
27
+ value: "",
28
+ status: "missing",
29
+ });
30
+ }
31
+ }
32
+ return settings;
33
+ }
34
+ export function parseAuditResult(stdout) {
35
+ const sections = stdout.split("---SEPARATOR---");
36
+ const sshdContent = sections[0] || "";
37
+ const fail2banStatus = sections[1] || "";
38
+ const sshdSettings = parseSshdConfig(sshdContent);
39
+ // Find specific settings
40
+ const passwordAuth = sshdSettings.find((s) => s.key === "PasswordAuthentication") || {
41
+ key: "PasswordAuthentication",
42
+ value: "",
43
+ status: "missing",
44
+ };
45
+ const rootLogin = sshdSettings.find((s) => s.key === "PermitRootLogin") || {
46
+ key: "PermitRootLogin",
47
+ value: "",
48
+ status: "missing",
49
+ };
50
+ // Parse fail2ban
51
+ const fail2banInstalled = fail2banStatus.includes("active") || fail2banStatus.includes("inactive");
52
+ const fail2banActive = fail2banStatus.includes("active (running)");
53
+ // Parse SSH port
54
+ const portMatch = sshdContent.match(/^\s*Port\s+(\d+)/m);
55
+ const sshPort = portMatch ? parseInt(portMatch[1], 10) : 22;
56
+ return {
57
+ passwordAuth,
58
+ rootLogin,
59
+ fail2ban: { installed: fail2banInstalled, active: fail2banActive },
60
+ sshPort,
61
+ };
62
+ }
63
+ export function buildHardeningCommand(options) {
64
+ const commands = [
65
+ "cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak",
66
+ `sed -i 's/^#\\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config`,
67
+ `sed -i 's/^#\\?PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config`,
68
+ `sed -i 's/^#\\?PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config`,
69
+ `sed -i 's/^#\\?MaxAuthTries.*/MaxAuthTries 3/' /etc/ssh/sshd_config`,
70
+ ];
71
+ if (options?.port && options.port !== 22) {
72
+ commands.push(`sed -i 's/^#\\?Port.*/Port ${options.port}/' /etc/ssh/sshd_config`);
73
+ }
74
+ commands.push("systemctl restart sshd");
75
+ return commands.join(" && ");
76
+ }
77
+ export function buildFail2banCommand() {
78
+ return [
79
+ "apt-get install -y fail2ban",
80
+ `cat > /etc/fail2ban/jail.local << 'JAIL'
81
+ [sshd]
82
+ enabled = true
83
+ port = ssh
84
+ filter = sshd
85
+ logpath = /var/log/auth.log
86
+ maxretry = 5
87
+ bantime = 3600
88
+ findtime = 600
89
+ JAIL`,
90
+ "systemctl enable fail2ban",
91
+ "systemctl restart fail2ban",
92
+ ].join(" && ");
93
+ }
94
+ export function buildAuditCommand() {
95
+ return `cat /etc/ssh/sshd_config && echo '---SEPARATOR---' && systemctl status fail2ban 2>&1 || true`;
96
+ }
97
+ export function buildKeyCheckCommand() {
98
+ return "test -f /root/.ssh/authorized_keys && wc -l < /root/.ssh/authorized_keys || echo 0";
99
+ }
100
+ export async function secureCommand(subcommand, query, options) {
101
+ if (!checkSshAvailable()) {
102
+ logger.error("SSH client not found. Please install OpenSSH.");
103
+ return;
104
+ }
105
+ const validSubcommands = ["setup", "status", "audit"];
106
+ const sub = subcommand || "status";
107
+ if (!validSubcommands.includes(sub)) {
108
+ logger.error(`Invalid subcommand: ${sub}. Choose from: ${validSubcommands.join(", ")}`);
109
+ return;
110
+ }
111
+ const server = await resolveServer(query, "Select a server for security management:");
112
+ if (!server)
113
+ return;
114
+ const dryRun = options?.dryRun || false;
115
+ switch (sub) {
116
+ case "setup":
117
+ await secureSetup(server.ip, server.name, options, dryRun);
118
+ break;
119
+ case "status":
120
+ await secureStatus(server.ip, server.name);
121
+ break;
122
+ case "audit":
123
+ await secureAudit(server.ip, server.name);
124
+ break;
125
+ }
126
+ }
127
+ async function secureSetup(ip, name, options, dryRun) {
128
+ // Step 1: Check SSH keys exist
129
+ const keyCheckResult = await sshExec(ip, buildKeyCheckCommand());
130
+ const keyCount = parseInt(keyCheckResult.stdout.trim(), 10);
131
+ if (isNaN(keyCount) || keyCount === 0) {
132
+ logger.error("No SSH keys found in /root/.ssh/authorized_keys");
133
+ logger.error("You MUST add an SSH key before disabling password authentication.");
134
+ logger.info("Run: ssh-copy-id root@" + ip);
135
+ return;
136
+ }
137
+ const port = options?.port ? parseInt(options.port, 10) : undefined;
138
+ if (options?.port && (!port || port < 1 || port > 65535)) {
139
+ logger.error("Invalid --port. Must be 1-65535.");
140
+ return;
141
+ }
142
+ const hardenCmd = buildHardeningCommand(port ? { port } : undefined);
143
+ const fail2banCmd = buildFail2banCommand();
144
+ if (dryRun) {
145
+ logger.title("Dry Run - Security Setup");
146
+ logger.info(`Server: ${name} (${ip})`);
147
+ logger.info(`SSH keys found: ${keyCount}`);
148
+ console.log();
149
+ logger.info("SSH Hardening commands:");
150
+ for (const cmd of hardenCmd.split(" && ")) {
151
+ logger.step(cmd);
152
+ }
153
+ console.log();
154
+ logger.info("Fail2ban commands:");
155
+ for (const cmd of fail2banCmd.split(" && ")) {
156
+ logger.step(cmd.length > 80 ? cmd.substring(0, 80) + "..." : cmd);
157
+ }
158
+ console.log();
159
+ logger.warning("No changes applied. Remove --dry-run to execute.");
160
+ return;
161
+ }
162
+ // Double confirmation (like destroy command)
163
+ const { confirm } = await inquirer.prompt([
164
+ {
165
+ type: "confirm",
166
+ name: "confirm",
167
+ message: `This will harden SSH on "${name}" (${ip}). Password login will be DISABLED. Continue?`,
168
+ default: false,
169
+ },
170
+ ]);
171
+ if (!confirm) {
172
+ logger.info("Security setup cancelled.");
173
+ return;
174
+ }
175
+ const { confirmName } = await inquirer.prompt([
176
+ {
177
+ type: "input",
178
+ name: "confirmName",
179
+ message: `Type the server name "${name}" to confirm:`,
180
+ },
181
+ ]);
182
+ if (confirmName.trim() !== name) {
183
+ logger.error("Server name does not match. Setup cancelled.");
184
+ return;
185
+ }
186
+ // Step 2: Apply SSH hardening
187
+ const spinner = createSpinner("Applying SSH hardening...");
188
+ spinner.start();
189
+ try {
190
+ const hardenResult = await sshExec(ip, hardenCmd);
191
+ if (hardenResult.code !== 0) {
192
+ spinner.fail("Failed to apply SSH hardening");
193
+ if (hardenResult.stderr)
194
+ logger.error(hardenResult.stderr);
195
+ return;
196
+ }
197
+ spinner.succeed("SSH hardened successfully");
198
+ }
199
+ catch (error) {
200
+ spinner.fail("Failed to apply SSH hardening");
201
+ logger.error(error instanceof Error ? error.message : String(error));
202
+ return;
203
+ }
204
+ // Step 3: Install fail2ban
205
+ const f2bSpinner = createSpinner("Installing fail2ban...");
206
+ f2bSpinner.start();
207
+ try {
208
+ const f2bResult = await sshExec(ip, fail2banCmd);
209
+ if (f2bResult.code !== 0) {
210
+ f2bSpinner.warn("Fail2ban installation had issues (non-fatal)");
211
+ if (f2bResult.stderr)
212
+ logger.warning(f2bResult.stderr);
213
+ }
214
+ else {
215
+ f2bSpinner.succeed("Fail2ban installed and configured");
216
+ }
217
+ }
218
+ catch (error) {
219
+ f2bSpinner.warn("Fail2ban installation failed (non-fatal)");
220
+ logger.warning(error instanceof Error ? error.message : String(error));
221
+ }
222
+ logger.success(`Security setup complete for ${name}`);
223
+ if (port && port !== 22) {
224
+ logger.warning(`SSH port changed to ${port}. Use: ssh -p ${port} root@${ip}`);
225
+ }
226
+ }
227
+ async function secureStatus(ip, name) {
228
+ const spinner = createSpinner(`Checking security status of ${name}...`);
229
+ spinner.start();
230
+ try {
231
+ const result = await sshExec(ip, buildAuditCommand());
232
+ if (result.code !== 0 && !result.stdout) {
233
+ spinner.fail("Failed to check security status");
234
+ if (result.stderr)
235
+ logger.error(result.stderr);
236
+ return;
237
+ }
238
+ const audit = parseAuditResult(result.stdout);
239
+ spinner.succeed(`Security status for ${name} (${ip})`);
240
+ console.log();
241
+ const passIcon = (status) => status === "secure" ? "\u2714" : status === "insecure" ? "\u2716" : "?";
242
+ logger.info(`Password Auth: ${passIcon(audit.passwordAuth.status)} ${audit.passwordAuth.value || "not set"}`);
243
+ logger.info(`Root Login: ${passIcon(audit.rootLogin.status)} ${audit.rootLogin.value || "not set"}`);
244
+ logger.info(`Fail2ban: ${audit.fail2ban.installed ? (audit.fail2ban.active ? "\u2714 active" : "\u2716 inactive") : "\u2716 not installed"}`);
245
+ logger.info(`SSH Port: ${audit.sshPort}`);
246
+ }
247
+ catch (error) {
248
+ spinner.fail("Failed to check security status");
249
+ logger.error(error instanceof Error ? error.message : String(error));
250
+ }
251
+ }
252
+ async function secureAudit(ip, name) {
253
+ const spinner = createSpinner(`Running security audit on ${name}...`);
254
+ spinner.start();
255
+ try {
256
+ const result = await sshExec(ip, buildAuditCommand());
257
+ if (result.code !== 0 && !result.stdout) {
258
+ spinner.fail("Failed to run security audit");
259
+ if (result.stderr)
260
+ logger.error(result.stderr);
261
+ return;
262
+ }
263
+ const audit = parseAuditResult(result.stdout);
264
+ spinner.succeed(`Security audit for ${name} (${ip})`);
265
+ // Score calculation
266
+ let score = 0;
267
+ const maxScore = 4;
268
+ if (audit.passwordAuth.status === "secure")
269
+ score++;
270
+ if (audit.rootLogin.status === "secure")
271
+ score++;
272
+ if (audit.fail2ban.active)
273
+ score++;
274
+ if (audit.sshPort !== 22)
275
+ score++;
276
+ console.log();
277
+ logger.title(`Security Score: ${score}/${maxScore}`);
278
+ // Detailed report
279
+ const check = (ok, msg) => ok ? logger.success(msg) : logger.warning(msg);
280
+ check(audit.passwordAuth.status === "secure", `Password Authentication: ${audit.passwordAuth.value || "not set"} ${audit.passwordAuth.status === "secure" ? "(OK)" : "(should be 'no')"}`);
281
+ check(audit.rootLogin.status === "secure", `Root Login: ${audit.rootLogin.value || "not set"} ${audit.rootLogin.status === "secure" ? "(OK)" : "(should be 'prohibit-password')"}`);
282
+ check(audit.fail2ban.active, `Fail2ban: ${audit.fail2ban.installed ? (audit.fail2ban.active ? "active (OK)" : "installed but inactive") : "not installed"}`);
283
+ check(audit.sshPort !== 22, `SSH Port: ${audit.sshPort} ${audit.sshPort !== 22 ? "(non-default, OK)" : "(default port 22)"}`);
284
+ if (score < maxScore) {
285
+ console.log();
286
+ logger.info("Run 'quicklify secure setup' to improve your security score.");
287
+ }
288
+ }
289
+ catch (error) {
290
+ spinner.fail("Failed to run security audit");
291
+ logger.error(error instanceof Error ? error.message : String(error));
292
+ }
293
+ }
294
+ //# sourceMappingURL=secure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secure.js","sourceRoot":"","sources":["../../src/commands/secure.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -15,6 +15,9 @@ import { logsCommand } from "./commands/logs.js";
15
15
  import { monitorCommand } from "./commands/monitor.js";
16
16
  import { healthCommand } from "./commands/health.js";
17
17
  import { doctorCommand } from "./commands/doctor.js";
18
+ import { firewallCommand } from "./commands/firewall.js";
19
+ import { domainCommand } from "./commands/domain.js";
20
+ import { secureCommand } from "./commands/secure.js";
18
21
  const __filename = fileURLToPath(import.meta.url);
19
22
  const __dirname = dirname(__filename);
20
23
  const pkg = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8"));
@@ -76,5 +79,25 @@ program
76
79
  .description("Check your local environment and configuration")
77
80
  .option("--check-tokens", "Validate provider API tokens")
78
81
  .action((options) => doctorCommand(options, pkg.version));
82
+ program
83
+ .command("firewall [subcommand] [query]")
84
+ .description("Manage server firewall (UFW)")
85
+ .option("--port <port>", "Port number (for add/remove)")
86
+ .option("--protocol <protocol>", "Protocol: tcp or udp (default: tcp)")
87
+ .option("--dry-run", "Show commands without executing")
88
+ .action((subcommand, query, options) => firewallCommand(subcommand, query, options));
89
+ program
90
+ .command("domain [subcommand] [query]")
91
+ .description("Manage server domain and SSL")
92
+ .option("--domain <domain>", "Domain name (for add/check)")
93
+ .option("--no-ssl", "Disable HTTPS (default: enabled)")
94
+ .option("--dry-run", "Show commands without executing")
95
+ .action((subcommand, query, options) => domainCommand(subcommand, query, options));
96
+ program
97
+ .command("secure [subcommand] [query]")
98
+ .description("Manage server security (SSH hardening, fail2ban)")
99
+ .option("--port <port>", "Change SSH port")
100
+ .option("--dry-run", "Show commands without executing")
101
+ .action((subcommand, query, options) => secureCommand(subcommand, query, options));
79
102
  program.parse();
80
103
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAElF,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,gDAAgD,CAAC;KAC7D,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAExB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,mDAAmD,CAAC;KAChE,MAAM,CAAC,uBAAuB,EAAE,wCAAwC,CAAC;KACzE,MAAM,CAAC,iBAAiB,EAAE,+DAA+D,CAAC;KAC1F,MAAM,CAAC,mBAAmB,EAAE,eAAe,CAAC;KAC5C,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC;KACtC,MAAM,CAAC,eAAe,EAAE,aAAa,CAAC;KACtC,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,6BAA6B,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvF,OAAO;KACJ,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CAAC,iCAAiC,CAAC;KAC9C,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,OAAO;KACJ,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,6BAA6B,CAAC;KAC1C,MAAM,CAAC,cAAc,CAAC,CAAC;AAE1B,OAAO;KACJ,OAAO,CAAC,+BAA+B,CAAC;KACxC,WAAW,CAAC,8BAA8B,CAAC;KAC3C,MAAM,CAAC,CAAC,UAAmB,EAAE,IAAe,EAAE,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC;AAErF,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,8BAA8B,CAAC;KAC3C,MAAM,CAAC,yBAAyB,EAAE,kCAAkC,CAAC;KACrE,MAAM,CAAC,CAAC,KAAc,EAAE,OAA8B,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAE1F,OAAO;KACJ,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CAAC,uCAAuC,CAAC;KACpD,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,OAAO;KACJ,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,6BAA6B,CAAC;KAC1C,MAAM,CAAC,cAAc,CAAC,CAAC;AAE1B,OAAO;KACJ,OAAO,CAAC,cAAc,CAAC;KACvB,WAAW,CAAC,+CAA+C,CAAC;KAC5D,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,EAAE,IAAI,CAAC;KAClE,MAAM,CAAC,cAAc,EAAE,gCAAgC,CAAC;KACxD,MAAM,CAAC,yBAAyB,EAAE,sCAAsC,EAAE,SAAS,CAAC;KACpF,MAAM,CACL,CAAC,KAAc,EAAE,OAAgE,EAAE,EAAE,CACnF,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,CAC9B,CAAC;AAEJ,OAAO;KACJ,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,6CAA6C,CAAC;KAC1D,MAAM,CAAC,cAAc,EAAE,4BAA4B,CAAC;KACpD,MAAM,CACL,CAAC,KAAc,EAAE,OAAkC,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,CACvF,CAAC;AAEJ,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,wCAAwC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;AAEtG,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,gDAAgD,CAAC;KAC7D,MAAM,CAAC,gBAAgB,EAAE,8BAA8B,CAAC;KACxD,MAAM,CAAC,CAAC,OAAmC,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AAExF,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -51,4 +51,29 @@ export interface QuicklifyConfig {
51
51
  size?: string;
52
52
  name?: string;
53
53
  }
54
+ export type FirewallProtocol = "tcp" | "udp";
55
+ export interface FirewallRule {
56
+ port: number;
57
+ protocol: FirewallProtocol;
58
+ action: "ALLOW" | "DENY";
59
+ from: string;
60
+ }
61
+ export interface FirewallStatus {
62
+ active: boolean;
63
+ rules: FirewallRule[];
64
+ }
65
+ export interface SshdSetting {
66
+ key: string;
67
+ value: string;
68
+ status: "secure" | "insecure" | "missing";
69
+ }
70
+ export interface SecureAuditResult {
71
+ passwordAuth: SshdSetting;
72
+ rootLogin: SshdSetting;
73
+ fail2ban: {
74
+ installed: boolean;
75
+ active: boolean;
76
+ };
77
+ sshPort: number;
78
+ }
54
79
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAGD,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,KAAK,CAAC;AAC7C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd;AACD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAGD,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;CAC3C;AACD,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,WAAW,CAAC;IAC1B,SAAS,EAAE,WAAW,CAAC;IACvB,QAAQ,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IAClD,OAAO,EAAE,MAAM,CAAC;CACjB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quicklify",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Automate Coolify deployment on cloud providers",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",