ante-erp-cli 1.7.2 ā 1.7.4
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/bin/ante-cli.js +3 -0
- package/package.json +1 -1
- package/src/commands/set-domain.js +122 -1
package/bin/ante-cli.js
CHANGED
|
@@ -212,6 +212,9 @@ program
|
|
|
212
212
|
.option('--frontend <url>', 'Frontend domain/URL')
|
|
213
213
|
.option('--api <url>', 'API domain/URL')
|
|
214
214
|
.option('--detect', 'Auto-detect public IP address')
|
|
215
|
+
.option('--ssl, --enable-ssl', 'Enable SSL certificate (Let\'s Encrypt)')
|
|
216
|
+
.option('--email <email>', 'Email for SSL certificate notifications')
|
|
217
|
+
.option('--ssl-staging', 'Use Let\'s Encrypt staging environment (for testing)')
|
|
215
218
|
.option('--no-interactive', 'Non-interactive mode')
|
|
216
219
|
.action(setDomain);
|
|
217
220
|
|
package/package.json
CHANGED
|
@@ -7,6 +7,7 @@ import { getInstallDir } from '../utils/config.js';
|
|
|
7
7
|
import { detectPublicIPWithFeedback, buildURL, isValidIPv4 } from '../utils/network.js';
|
|
8
8
|
import { configureNginx, requiresNginx } from '../utils/nginx.js';
|
|
9
9
|
import { pullImages, stopServices, startServices, waitForServiceHealthy } from '../utils/docker.js';
|
|
10
|
+
import { obtainSSLCertificate, updateNginxForSSL, setupAutoRenewal, extractDomain } from '../utils/ssl.js';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Validate URL format with proper hostname and protocol checking
|
|
@@ -42,6 +43,22 @@ function validateUrl(url) {
|
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Validate email format
|
|
48
|
+
* @param {string} email - Email to validate
|
|
49
|
+
* @returns {boolean|string} True if valid, error message if invalid
|
|
50
|
+
*/
|
|
51
|
+
function validateEmail(email) {
|
|
52
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
53
|
+
if (!email || email.trim() === '') {
|
|
54
|
+
return 'Email is required';
|
|
55
|
+
}
|
|
56
|
+
if (!emailRegex.test(email)) {
|
|
57
|
+
return 'Please enter a valid email address';
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
|
|
45
62
|
/**
|
|
46
63
|
* Sanitize URL by normalizing common formatting issues
|
|
47
64
|
* @param {string} url - URL to sanitize
|
|
@@ -279,7 +296,8 @@ export async function setDomain(options) {
|
|
|
279
296
|
console.log(chalk.green('ā Configuration updated'));
|
|
280
297
|
|
|
281
298
|
// Configure NGINX if needed (for domains or HTTPS)
|
|
282
|
-
|
|
299
|
+
const needsNginx = requiresNginx(frontendUrl, apiUrl);
|
|
300
|
+
if (needsNginx) {
|
|
283
301
|
console.log(chalk.gray('\nš§ Setting up reverse proxy...\n'));
|
|
284
302
|
|
|
285
303
|
try {
|
|
@@ -295,6 +313,109 @@ export async function setDomain(options) {
|
|
|
295
313
|
}
|
|
296
314
|
}
|
|
297
315
|
|
|
316
|
+
// Check if HTTPS is configured and offer SSL setup
|
|
317
|
+
const isHttps = frontendUrl.startsWith('https://') || apiUrl.startsWith('https://');
|
|
318
|
+
const frontendDomain = extractDomain(frontendUrl);
|
|
319
|
+
const apiDomain = extractDomain(apiUrl);
|
|
320
|
+
const isDomainName = !frontendDomain.match(/^(\d+\.){3}\d+$/) && frontendDomain !== 'localhost';
|
|
321
|
+
|
|
322
|
+
if (isHttps && isDomainName && needsNginx) {
|
|
323
|
+
// SSL setup workflow
|
|
324
|
+
let enableSsl = options.ssl || false;
|
|
325
|
+
let sslEmail = options.email || '';
|
|
326
|
+
|
|
327
|
+
// If not specified via flags, ask in interactive mode
|
|
328
|
+
if (options.interactive !== false && !options.ssl) {
|
|
329
|
+
console.log(chalk.cyan('\nš SSL/HTTPS Configuration\n'));
|
|
330
|
+
console.log(chalk.gray('You\'re using HTTPS URLs. Would you like to obtain SSL certificates now?\n'));
|
|
331
|
+
console.log(chalk.gray('This will:'));
|
|
332
|
+
console.log(chalk.gray(' ⢠Obtain free SSL certificates from Let\'s Encrypt'));
|
|
333
|
+
console.log(chalk.gray(' ⢠Configure NGINX for HTTPS'));
|
|
334
|
+
console.log(chalk.gray(' ⢠Set up automatic certificate renewal\n'));
|
|
335
|
+
|
|
336
|
+
const sslPrompt = await inquirer.prompt([
|
|
337
|
+
{
|
|
338
|
+
type: 'confirm',
|
|
339
|
+
name: 'enable',
|
|
340
|
+
message: 'Enable SSL certificate now?',
|
|
341
|
+
default: true
|
|
342
|
+
}
|
|
343
|
+
]);
|
|
344
|
+
|
|
345
|
+
enableSsl = sslPrompt.enable;
|
|
346
|
+
|
|
347
|
+
if (enableSsl) {
|
|
348
|
+
const emailPrompt = await inquirer.prompt([
|
|
349
|
+
{
|
|
350
|
+
type: 'input',
|
|
351
|
+
name: 'email',
|
|
352
|
+
message: 'Email address for certificate notifications:',
|
|
353
|
+
validate: validateEmail
|
|
354
|
+
}
|
|
355
|
+
]);
|
|
356
|
+
sslEmail = emailPrompt.email;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Execute SSL setup if enabled
|
|
361
|
+
if (enableSsl) {
|
|
362
|
+
if (!sslEmail) {
|
|
363
|
+
console.log(chalk.yellow('\nā SSL setup skipped: Email address required'));
|
|
364
|
+
console.log(chalk.gray(' Run "ante ssl enable --email your@email.com" to enable SSL later\n'));
|
|
365
|
+
} else {
|
|
366
|
+
try {
|
|
367
|
+
console.log(chalk.bold('\nš Setting up SSL/HTTPS...\n'));
|
|
368
|
+
|
|
369
|
+
// Step 1: Obtain certificates
|
|
370
|
+
console.log(chalk.cyan('š Obtaining SSL certificates...\n'));
|
|
371
|
+
|
|
372
|
+
const domains = [];
|
|
373
|
+
if (frontendDomain !== 'localhost' && !frontendDomain.match(/^\d+\.\d+\.\d+\.\d+$/)) {
|
|
374
|
+
domains.push(frontendDomain);
|
|
375
|
+
}
|
|
376
|
+
if (apiDomain !== frontendDomain && apiDomain !== 'localhost' && !apiDomain.match(/^\d+\.\d+\.\d+\.\d+$/)) {
|
|
377
|
+
domains.push(apiDomain);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
for (const domain of domains) {
|
|
381
|
+
console.log(chalk.gray(` Obtaining certificate for ${domain}...`));
|
|
382
|
+
await obtainSSLCertificate({
|
|
383
|
+
domain,
|
|
384
|
+
email: sslEmail,
|
|
385
|
+
staging: options.sslStaging || false
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
console.log(chalk.green('\nā SSL certificates obtained\n'));
|
|
390
|
+
|
|
391
|
+
// Step 2: Update NGINX for HTTPS
|
|
392
|
+
console.log(chalk.cyan('š§ Configuring NGINX for HTTPS...\n'));
|
|
393
|
+
|
|
394
|
+
await updateNginxForSSL({
|
|
395
|
+
frontendDomain: frontendUrl,
|
|
396
|
+
apiDomain: apiUrl,
|
|
397
|
+
frontendPort: 8080,
|
|
398
|
+
apiPort: 3001
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
// Step 3: Setup auto-renewal
|
|
402
|
+
console.log(chalk.cyan('š Setting up automatic certificate renewal...\n'));
|
|
403
|
+
await setupAutoRenewal();
|
|
404
|
+
|
|
405
|
+
console.log(chalk.green('ā SSL/HTTPS configured successfully\n'));
|
|
406
|
+
|
|
407
|
+
} catch (error) {
|
|
408
|
+
console.log(chalk.red('\nā SSL setup failed:'), error.message);
|
|
409
|
+
console.log(chalk.yellow('\nā You can enable SSL later with:'));
|
|
410
|
+
console.log(chalk.gray(` ante ssl enable --email ${sslEmail}\n`));
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
} else if (options.interactive !== false) {
|
|
414
|
+
console.log(chalk.gray('\nSSL setup skipped. You can enable it later with:'));
|
|
415
|
+
console.log(chalk.gray(' ante ssl enable --email your@email.com\n'));
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
298
419
|
// Restart containers to apply new environment variables
|
|
299
420
|
console.log(chalk.gray('\nš Restarting services with updated configuration...\n'));
|
|
300
421
|
|