ante-erp-cli 1.11.66 → 1.11.67
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/package.json +1 -1
- package/src/commands/install.js +21 -3
- package/src/commands/regenerate-compose.js +18 -10
- package/src/commands/set-domain.js +94 -6
- package/src/commands/ssl-enable.js +78 -6
- package/src/commands/update.js +6 -0
- package/src/templates/docker-compose.yml.js +64 -0
- package/src/templates/env.js +13 -0
- package/src/utils/nginx.js +321 -2
- package/src/utils/ssl.js +12 -0
- package/src/utils/validation.js +20 -1
package/package.json
CHANGED
package/src/commands/install.js
CHANGED
|
@@ -78,6 +78,8 @@ function showWelcome() {
|
|
|
78
78
|
function showSuccess(installDir, credentials, config) {
|
|
79
79
|
const frontendUrl = config.frontendDomain || 'http://localhost:8080';
|
|
80
80
|
const apiUrl = config.apiDomain || 'http://localhost:3001';
|
|
81
|
+
const frontendCoreUrl = config.frontendCoreDomain || 'http://localhost:8085';
|
|
82
|
+
const backendCoreUrl = config.backendCoreDomain || 'http://localhost:4002';
|
|
81
83
|
const gateAppUrl = config.gateAppDomain || 'http://localhost:8081';
|
|
82
84
|
const guardianAppUrl = config.guardianAppDomain || 'http://localhost:8082';
|
|
83
85
|
const facialWebUrl = config.facialAppDomain || 'http://localhost:8083';
|
|
@@ -86,7 +88,8 @@ function showSuccess(installDir, credentials, config) {
|
|
|
86
88
|
|
|
87
89
|
let accessInfo = chalk.white('Access Information:') + '\n' +
|
|
88
90
|
chalk.gray('━'.repeat(40)) + '\n' +
|
|
89
|
-
chalk.cyan('Frontend Main: ') + chalk.white(frontendUrl) + '\n'
|
|
91
|
+
chalk.cyan('Frontend Main: ') + chalk.white(frontendUrl) + '\n' +
|
|
92
|
+
chalk.cyan('Frontend Core: ') + chalk.white(frontendCoreUrl) + '\n';
|
|
90
93
|
|
|
91
94
|
if (config.installGate) {
|
|
92
95
|
accessInfo += chalk.cyan('Gate App: ') + chalk.white(gateAppUrl) + '\n';
|
|
@@ -105,10 +108,11 @@ function showSuccess(installDir, credentials, config) {
|
|
|
105
108
|
}
|
|
106
109
|
|
|
107
110
|
if (config.installMlm) {
|
|
108
|
-
accessInfo += chalk.cyan('MLM App:
|
|
111
|
+
accessInfo += chalk.cyan('MLM App: ') + chalk.white(mlmAppUrl) + '\n';
|
|
109
112
|
}
|
|
110
113
|
|
|
111
114
|
accessInfo += chalk.cyan('Backend: ') + chalk.white(apiUrl) + '\n' +
|
|
115
|
+
chalk.cyan('Backend Core: ') + chalk.white(backendCoreUrl) + '\n' +
|
|
112
116
|
chalk.cyan('WebSocket: ') + chalk.white(apiUrl) + '\n\n';
|
|
113
117
|
|
|
114
118
|
console.log(
|
|
@@ -319,6 +323,8 @@ export async function install(options) {
|
|
|
319
323
|
const frontendPort = parseInt(options.port) || 8080;
|
|
320
324
|
const apiPort = 3001;
|
|
321
325
|
const backendMlmPort = 4001;
|
|
326
|
+
const backendCorePort = 4002;
|
|
327
|
+
const frontendCorePort = 8085;
|
|
322
328
|
const gateAppPort = 8081;
|
|
323
329
|
const guardianAppPort = 8082;
|
|
324
330
|
const facialWebPort = 8083;
|
|
@@ -331,6 +337,8 @@ export async function install(options) {
|
|
|
331
337
|
frontendDomain: buildURL(host, frontendPort),
|
|
332
338
|
apiDomain: buildURL(host, apiPort),
|
|
333
339
|
mlmApiDomain: buildURL(host, backendMlmPort),
|
|
340
|
+
backendCoreDomain: buildURL(host, backendCorePort),
|
|
341
|
+
frontendCoreDomain: buildURL(host, frontendCorePort),
|
|
334
342
|
gateAppDomain: buildURL(host, gateAppPort),
|
|
335
343
|
guardianAppDomain: buildURL(host, guardianAppPort),
|
|
336
344
|
facialAppDomain: buildURL(host, facialWebPort),
|
|
@@ -339,6 +347,8 @@ export async function install(options) {
|
|
|
339
347
|
frontendPort,
|
|
340
348
|
apiPort,
|
|
341
349
|
backendMlmPort,
|
|
350
|
+
backendCorePort,
|
|
351
|
+
frontendCorePort,
|
|
342
352
|
gateAppPort,
|
|
343
353
|
guardianAppPort,
|
|
344
354
|
facialWebPort,
|
|
@@ -350,7 +360,7 @@ export async function install(options) {
|
|
|
350
360
|
installFacial: true,
|
|
351
361
|
installPos: true,
|
|
352
362
|
installMlm: true,
|
|
353
|
-
frontends: ['main', 'gate', 'guardian', 'facial', 'pos', 'mlm']
|
|
363
|
+
frontends: ['main', 'gate', 'guardian', 'facial', 'pos', 'mlm', 'core']
|
|
354
364
|
};
|
|
355
365
|
|
|
356
366
|
console.log(chalk.green(`✓ ${formatStepTitle(stepNetworkDetect, totalSteps, `Network detected: ${host}`)}\n`));
|
|
@@ -359,12 +369,14 @@ export async function install(options) {
|
|
|
359
369
|
console.log(chalk.bold('📋 Installation Configuration:\n'));
|
|
360
370
|
console.log(chalk.cyan(' Directory:'), chalk.white(config.installDir));
|
|
361
371
|
console.log(chalk.cyan(' Frontend Main:'), chalk.white(config.frontendDomain));
|
|
372
|
+
console.log(chalk.cyan(' Frontend Core:'), chalk.white(config.frontendCoreDomain));
|
|
362
373
|
console.log(chalk.cyan(' Gate App:'), chalk.white(config.gateAppDomain));
|
|
363
374
|
console.log(chalk.cyan(' Guardian App:'), chalk.white(config.guardianAppDomain));
|
|
364
375
|
console.log(chalk.cyan(' Facial Web:'), chalk.white(config.facialAppDomain));
|
|
365
376
|
console.log(chalk.cyan(' POS App:'), chalk.white(config.posAppDomain));
|
|
366
377
|
console.log(chalk.cyan(' MLM App:'), chalk.white(config.mlmAppDomain));
|
|
367
378
|
console.log(chalk.cyan(' API:'), chalk.white(config.apiDomain));
|
|
379
|
+
console.log(chalk.cyan(' Backend Core:'), chalk.white(config.backendCoreDomain));
|
|
368
380
|
console.log(chalk.cyan(' MLM API:'), chalk.white(config.mlmApiDomain));
|
|
369
381
|
console.log();
|
|
370
382
|
|
|
@@ -442,6 +454,8 @@ export async function install(options) {
|
|
|
442
454
|
frontendPort: config.frontendPort,
|
|
443
455
|
backendPort: config.apiPort,
|
|
444
456
|
backendMlmPort: config.backendMlmPort,
|
|
457
|
+
backendCorePort: config.backendCorePort,
|
|
458
|
+
frontendCorePort: config.frontendCorePort,
|
|
445
459
|
gateAppPort: config.gateAppPort,
|
|
446
460
|
guardianAppPort: config.guardianAppPort,
|
|
447
461
|
facialWebPort: config.facialWebPort,
|
|
@@ -463,6 +477,8 @@ export async function install(options) {
|
|
|
463
477
|
frontendPort: config.frontendPort,
|
|
464
478
|
backendPort: config.apiPort,
|
|
465
479
|
backendMlmPort: config.backendMlmPort,
|
|
480
|
+
backendCorePort: config.backendCorePort,
|
|
481
|
+
frontendCorePort: config.frontendCorePort,
|
|
466
482
|
gateAppPort: config.gateAppPort,
|
|
467
483
|
guardianAppPort: config.guardianAppPort,
|
|
468
484
|
facialWebPort: config.facialWebPort,
|
|
@@ -474,6 +490,8 @@ export async function install(options) {
|
|
|
474
490
|
posAppUrl: config.posAppDomain,
|
|
475
491
|
mlmAppUrl: config.mlmAppDomain,
|
|
476
492
|
mlmApiUrl: config.mlmApiDomain,
|
|
493
|
+
frontendCoreUrl: config.frontendCoreDomain,
|
|
494
|
+
backendCoreUrl: config.backendCoreDomain,
|
|
477
495
|
companyId: config.companyId,
|
|
478
496
|
installGate: config.installGate,
|
|
479
497
|
installGuardian: config.installGuardian,
|
|
@@ -74,11 +74,13 @@ export async function regenerateCompose() {
|
|
|
74
74
|
const installed = detectInstalledApps(composeFile);
|
|
75
75
|
console.log(chalk.cyan('Detected Configuration:'));
|
|
76
76
|
console.log(chalk.gray(` Frontend Main: ${installed.hasMain ? '✓ Installed' : '✗ Not installed'}`));
|
|
77
|
+
console.log(chalk.gray(` Backend Core: ✓ Always Included`));
|
|
78
|
+
console.log(chalk.gray(` Frontend Core: ✓ Always Included`));
|
|
77
79
|
console.log(chalk.gray(` Gate App: ${installed.hasGateApp ? '✓ Installed' : '✗ Not installed'}`));
|
|
78
80
|
console.log(chalk.gray(` Guardian App: ${installed.hasGuardianApp ? '✓ Installed' : '✗ Not installed'}`));
|
|
79
81
|
console.log(chalk.gray(` Facial Web: ${installed.hasFacialWeb ? '✓ Installed' : '✗ Not installed'}`));
|
|
80
82
|
console.log(chalk.gray(` POS App: ${installed.hasPosApp ? '✓ Installed' : '✗ Not installed'}`));
|
|
81
|
-
console.log(chalk.gray(` MLM App:
|
|
83
|
+
console.log(chalk.gray(` MLM App: ${installed.hasMlmApp ? '✓ Installed' : '✗ Not installed'}\n`));
|
|
82
84
|
|
|
83
85
|
// Parse .env file
|
|
84
86
|
const envConfig = parseEnvFile(envFile);
|
|
@@ -87,6 +89,8 @@ export async function regenerateCompose() {
|
|
|
87
89
|
const frontendPort = parseInt(envConfig.FRONTEND_PORT) || 8080;
|
|
88
90
|
const backendPort = parseInt(envConfig.BACKEND_PORT) || 3001;
|
|
89
91
|
const backendMlmPort = parseInt(envConfig.BACKEND_MLM_PORT) || 4001;
|
|
92
|
+
const backendCorePort = parseInt(envConfig.BACKEND_CORE_PORT) || 4002;
|
|
93
|
+
const frontendCorePort = parseInt(envConfig.FRONTEND_CORE_PORT) || 8085;
|
|
90
94
|
const gateAppPort = parseInt(envConfig.GATE_APP_PORT) || 8081;
|
|
91
95
|
const guardianAppPort = parseInt(envConfig.GUARDIAN_APP_PORT) || 8082;
|
|
92
96
|
const facialWebPort = parseInt(envConfig.FACIAL_WEB_PORT) || 8083;
|
|
@@ -95,25 +99,27 @@ export async function regenerateCompose() {
|
|
|
95
99
|
const companyId = parseInt(envConfig.COMPANY_ID) || 1;
|
|
96
100
|
|
|
97
101
|
console.log(chalk.cyan('Port Configuration:'));
|
|
98
|
-
console.log(chalk.gray(` Frontend:
|
|
99
|
-
console.log(chalk.gray(` Backend:
|
|
102
|
+
console.log(chalk.gray(` Frontend: ${frontendPort}`));
|
|
103
|
+
console.log(chalk.gray(` Backend: ${backendPort}`));
|
|
104
|
+
console.log(chalk.gray(` Backend Core: ${backendCorePort}`));
|
|
105
|
+
console.log(chalk.gray(` Frontend Core: ${frontendCorePort}`));
|
|
100
106
|
if (installed.hasGateApp) {
|
|
101
|
-
console.log(chalk.gray(` Gate App:
|
|
107
|
+
console.log(chalk.gray(` Gate App: ${gateAppPort}`));
|
|
102
108
|
}
|
|
103
109
|
if (installed.hasGuardianApp) {
|
|
104
|
-
console.log(chalk.gray(` Guardian:
|
|
110
|
+
console.log(chalk.gray(` Guardian: ${guardianAppPort}`));
|
|
105
111
|
}
|
|
106
112
|
if (installed.hasFacialWeb) {
|
|
107
|
-
console.log(chalk.gray(` Facial Web:
|
|
113
|
+
console.log(chalk.gray(` Facial Web: ${facialWebPort}`));
|
|
108
114
|
}
|
|
109
115
|
if (installed.hasPosApp) {
|
|
110
|
-
console.log(chalk.gray(` POS App:
|
|
116
|
+
console.log(chalk.gray(` POS App: ${posAppPort}`));
|
|
111
117
|
}
|
|
112
118
|
if (installed.hasMlmApp) {
|
|
113
|
-
console.log(chalk.gray(` MLM App:
|
|
114
|
-
console.log(chalk.gray(` Backend MLM:
|
|
119
|
+
console.log(chalk.gray(` MLM App: ${mlmAppPort}`));
|
|
120
|
+
console.log(chalk.gray(` Backend MLM: ${backendMlmPort}`));
|
|
115
121
|
}
|
|
116
|
-
console.log(chalk.gray(` Company ID:
|
|
122
|
+
console.log(chalk.gray(` Company ID: ${companyId}\n`));
|
|
117
123
|
|
|
118
124
|
// Backup existing docker-compose.yml
|
|
119
125
|
const timestamp = new Date().toISOString().split('.')[0].replace(/:/g, '-').replace('T', '_');
|
|
@@ -129,6 +135,8 @@ export async function regenerateCompose() {
|
|
|
129
135
|
frontendPort,
|
|
130
136
|
backendPort,
|
|
131
137
|
backendMlmPort,
|
|
138
|
+
backendCorePort,
|
|
139
|
+
frontendCorePort,
|
|
132
140
|
gateAppPort,
|
|
133
141
|
guardianAppPort,
|
|
134
142
|
facialWebPort,
|
|
@@ -97,9 +97,9 @@ function getEnvValue(envPath, key) {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
/**
|
|
100
|
-
* Check if gate-app, guardian-app, facial-web, pos-app, mlm-app, or backend-
|
|
100
|
+
* Check if gate-app, guardian-app, facial-web, pos-app, mlm-app, backend-mlm, frontend-core, or backend-core is installed by checking docker-compose.yml
|
|
101
101
|
* @param {string} composeFile - Path to docker-compose.yml
|
|
102
|
-
* @returns {{hasGateApp: boolean, hasGuardianApp: boolean, hasFacialWeb: boolean, hasPosApp: boolean, hasMlmApp: boolean, hasBackendMlm: boolean}}
|
|
102
|
+
* @returns {{hasGateApp: boolean, hasGuardianApp: boolean, hasFacialWeb: boolean, hasPosApp: boolean, hasMlmApp: boolean, hasBackendMlm: boolean, hasFrontendCore: boolean, hasBackendCore: boolean}}
|
|
103
103
|
*/
|
|
104
104
|
function detectInstalledApps(composeFile) {
|
|
105
105
|
try {
|
|
@@ -110,10 +110,12 @@ function detectInstalledApps(composeFile) {
|
|
|
110
110
|
hasFacialWeb: composeContent.includes('facial-web:') || composeContent.includes('container_name: ante-facial-web'),
|
|
111
111
|
hasPosApp: composeContent.includes('pos-app:') || composeContent.includes('container_name: ante-pos'),
|
|
112
112
|
hasMlmApp: composeContent.includes('mlm-app:') || composeContent.includes('container_name: ante-mlm'),
|
|
113
|
-
hasBackendMlm: composeContent.includes('backend-mlm:') || composeContent.includes('container_name: ante-backend-mlm')
|
|
113
|
+
hasBackendMlm: composeContent.includes('backend-mlm:') || composeContent.includes('container_name: ante-backend-mlm'),
|
|
114
|
+
hasFrontendCore: composeContent.includes('frontend-core:') || composeContent.includes('container_name: ante-frontend-core'),
|
|
115
|
+
hasBackendCore: composeContent.includes('backend-core:') || composeContent.includes('container_name: ante-backend-core')
|
|
114
116
|
};
|
|
115
117
|
} catch {
|
|
116
|
-
return { hasGateApp: false, hasGuardianApp: false, hasFacialWeb: false, hasPosApp: false, hasMlmApp: false, hasBackendMlm: false };
|
|
118
|
+
return { hasGateApp: false, hasGuardianApp: false, hasFacialWeb: false, hasPosApp: false, hasMlmApp: false, hasBackendMlm: false, hasFrontendCore: false, hasBackendCore: false };
|
|
117
119
|
}
|
|
118
120
|
}
|
|
119
121
|
|
|
@@ -172,10 +174,10 @@ export async function setDomain(options) {
|
|
|
172
174
|
console.log(); // Add spacing
|
|
173
175
|
}
|
|
174
176
|
|
|
175
|
-
let frontendUrl, apiUrl, gateAppUrl, guardianAppUrl, facialWebUrl, posAppUrl, mlmAppUrl, backendMlmUrl;
|
|
177
|
+
let frontendUrl, apiUrl, gateAppUrl, guardianAppUrl, facialWebUrl, posAppUrl, mlmAppUrl, backendMlmUrl, frontendCoreUrl, backendCoreUrl;
|
|
176
178
|
|
|
177
179
|
// Detect which apps are installed
|
|
178
|
-
const { hasGateApp, hasGuardianApp, hasFacialWeb, hasPosApp, hasMlmApp, hasBackendMlm } = detectInstalledApps(composeFile);
|
|
180
|
+
const { hasGateApp, hasGuardianApp, hasFacialWeb, hasPosApp, hasMlmApp, hasBackendMlm, hasFrontendCore, hasBackendCore } = detectInstalledApps(composeFile);
|
|
179
181
|
|
|
180
182
|
if (options.interactive !== false) {
|
|
181
183
|
// Show current values
|
|
@@ -187,6 +189,8 @@ export async function setDomain(options) {
|
|
|
187
189
|
const currentPosAppUrl = getEnvValue(envPath, 'POS_APP_URL');
|
|
188
190
|
const currentClientAppUrl = getEnvValue(envPath, 'MLM_APP_URL');
|
|
189
191
|
const currentBackendClientUrl = getEnvValue(envPath, 'MLM_API_URL');
|
|
192
|
+
const currentFrontendCoreUrl = getEnvValue(envPath, 'FRONTEND_CORE_URL');
|
|
193
|
+
const currentBackendCoreUrl = getEnvValue(envPath, 'BACKEND_CORE_URL');
|
|
190
194
|
|
|
191
195
|
if (currentFrontendUrl) {
|
|
192
196
|
console.log(chalk.gray(`Current Frontend URL: ${currentFrontendUrl}`));
|
|
@@ -209,6 +213,12 @@ export async function setDomain(options) {
|
|
|
209
213
|
if (currentBackendClientUrl) {
|
|
210
214
|
console.log(chalk.gray(`Current Backend-MLM API URL: ${currentBackendClientUrl}`));
|
|
211
215
|
}
|
|
216
|
+
if (currentFrontendCoreUrl) {
|
|
217
|
+
console.log(chalk.gray(`Current Frontend Core URL: ${currentFrontendCoreUrl}`));
|
|
218
|
+
}
|
|
219
|
+
if (currentBackendCoreUrl) {
|
|
220
|
+
console.log(chalk.gray(`Current Backend Core API URL: ${currentBackendCoreUrl}`));
|
|
221
|
+
}
|
|
212
222
|
if (currentApiUrl) {
|
|
213
223
|
console.log(chalk.gray(`Current API URL: ${currentApiUrl}\n`));
|
|
214
224
|
}
|
|
@@ -496,6 +506,8 @@ export async function setDomain(options) {
|
|
|
496
506
|
if (hasPosApp) posAppUrl = `https://${subdomain}-pos.ante.ph`;
|
|
497
507
|
if (hasMlmApp) mlmAppUrl = `https://${subdomain}-mlm.ante.ph`;
|
|
498
508
|
if (hasBackendMlm) backendMlmUrl = `https://${subdomain}-api-mlm.ante.ph`;
|
|
509
|
+
if (hasFrontendCore) frontendCoreUrl = `https://${subdomain}-core.ante.ph`;
|
|
510
|
+
if (hasBackendCore) backendCoreUrl = `https://${subdomain}-api-core.ante.ph`;
|
|
499
511
|
|
|
500
512
|
// Display generated domains for confirmation
|
|
501
513
|
console.log(chalk.cyan('\n📋 Generated Domain Configuration:\n'));
|
|
@@ -507,6 +519,8 @@ export async function setDomain(options) {
|
|
|
507
519
|
if (hasPosApp) console.log(chalk.gray(` POS App: ${posAppUrl}`));
|
|
508
520
|
if (hasMlmApp) console.log(chalk.gray(` MLM App: ${mlmAppUrl}`));
|
|
509
521
|
if (hasBackendMlm) console.log(chalk.gray(` Backend-MLM: ${backendMlmUrl}`));
|
|
522
|
+
if (hasFrontendCore) console.log(chalk.gray(` Frontend Core: ${frontendCoreUrl}`));
|
|
523
|
+
if (hasBackendCore) console.log(chalk.gray(` Backend Core: ${backendCoreUrl}`));
|
|
510
524
|
console.log('');
|
|
511
525
|
|
|
512
526
|
const confirmDomains = await inquirer.prompt([
|
|
@@ -594,6 +608,26 @@ export async function setDomain(options) {
|
|
|
594
608
|
});
|
|
595
609
|
}
|
|
596
610
|
|
|
611
|
+
if (hasFrontendCore) {
|
|
612
|
+
domainPrompts.push({
|
|
613
|
+
type: 'input',
|
|
614
|
+
name: 'frontendCoreUrl',
|
|
615
|
+
message: 'Frontend Core URL:\n Examples: https://staging-core.ante.ph or http://143.198.91.153:8085\n Enter URL',
|
|
616
|
+
default: currentFrontendCoreUrl || 'http://localhost:8085',
|
|
617
|
+
validate: validateUrl
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
if (hasBackendCore) {
|
|
622
|
+
domainPrompts.push({
|
|
623
|
+
type: 'input',
|
|
624
|
+
name: 'backendCoreUrl',
|
|
625
|
+
message: 'Backend Core API URL:\n Examples: https://staging-api-core.ante.ph or http://143.198.91.153:4002\n Enter URL',
|
|
626
|
+
default: currentBackendCoreUrl || 'http://localhost:4002',
|
|
627
|
+
validate: validateUrl
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
|
|
597
631
|
domainPrompts.push({
|
|
598
632
|
type: 'input',
|
|
599
633
|
name: 'apiUrl',
|
|
@@ -613,6 +647,8 @@ export async function setDomain(options) {
|
|
|
613
647
|
if (hasPosApp) posAppUrl = sanitizeUrl(answers.posAppUrl);
|
|
614
648
|
if (hasMlmApp) mlmAppUrl = sanitizeUrl(answers.mlmAppUrl);
|
|
615
649
|
if (hasBackendMlm) backendMlmUrl = sanitizeUrl(answers.backendMlmUrl);
|
|
650
|
+
if (hasFrontendCore) frontendCoreUrl = sanitizeUrl(answers.frontendCoreUrl);
|
|
651
|
+
if (hasBackendCore) backendCoreUrl = sanitizeUrl(answers.backendCoreUrl);
|
|
616
652
|
}
|
|
617
653
|
}
|
|
618
654
|
} else {
|
|
@@ -755,6 +791,14 @@ export async function setDomain(options) {
|
|
|
755
791
|
envUpdates.MLM_API_URL = backendMlmUrl;
|
|
756
792
|
}
|
|
757
793
|
|
|
794
|
+
if (hasFrontendCore && frontendCoreUrl) {
|
|
795
|
+
envUpdates.FRONTEND_CORE_URL = frontendCoreUrl;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
if (hasBackendCore && backendCoreUrl) {
|
|
799
|
+
envUpdates.BACKEND_CORE_URL = backendCoreUrl;
|
|
800
|
+
}
|
|
801
|
+
|
|
758
802
|
updateEnvFile(envPath, envUpdates);
|
|
759
803
|
|
|
760
804
|
console.log(chalk.green('✓ Configuration updated'));
|
|
@@ -813,6 +857,16 @@ export async function setDomain(options) {
|
|
|
813
857
|
nginxConfig.backendMlmPort = 4001;
|
|
814
858
|
}
|
|
815
859
|
|
|
860
|
+
if (hasFrontendCore && frontendCoreUrl) {
|
|
861
|
+
nginxConfig.frontendCoreDomain = frontendCoreUrl;
|
|
862
|
+
nginxConfig.frontendCorePort = 8085;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
if (hasBackendCore && backendCoreUrl) {
|
|
866
|
+
nginxConfig.backendCoreDomain = backendCoreUrl;
|
|
867
|
+
nginxConfig.backendCorePort = 4002;
|
|
868
|
+
}
|
|
869
|
+
|
|
816
870
|
await configureNginx(nginxConfig);
|
|
817
871
|
} catch (error) {
|
|
818
872
|
console.log(chalk.yellow('\n⚠ NGINX configuration failed:', error.message));
|
|
@@ -925,6 +979,18 @@ export async function setDomain(options) {
|
|
|
925
979
|
domains.push(backendMlmDomain);
|
|
926
980
|
}
|
|
927
981
|
}
|
|
982
|
+
if (hasFrontendCore && frontendCoreUrl && frontendCoreUrl.startsWith('https://')) {
|
|
983
|
+
const frontendCoreDomain = extractDomain(frontendCoreUrl);
|
|
984
|
+
if (frontendCoreDomain !== 'localhost' && !frontendCoreDomain.match(/^\d+\.\d+\.\d+\.\d+$/) && !domains.includes(frontendCoreDomain)) {
|
|
985
|
+
domains.push(frontendCoreDomain);
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
if (hasBackendCore && backendCoreUrl && backendCoreUrl.startsWith('https://')) {
|
|
989
|
+
const backendCoreDomain = extractDomain(backendCoreUrl);
|
|
990
|
+
if (backendCoreDomain !== 'localhost' && !backendCoreDomain.match(/^\d+\.\d+\.\d+\.\d+$/) && !domains.includes(backendCoreDomain)) {
|
|
991
|
+
domains.push(backendCoreDomain);
|
|
992
|
+
}
|
|
993
|
+
}
|
|
928
994
|
|
|
929
995
|
// Track successful and failed domains
|
|
930
996
|
const successfulDomains = [];
|
|
@@ -1016,6 +1082,16 @@ export async function setDomain(options) {
|
|
|
1016
1082
|
sslNginxConfig.backendMlmPort = 4001;
|
|
1017
1083
|
}
|
|
1018
1084
|
|
|
1085
|
+
if (hasFrontendCore && frontendCoreUrl) {
|
|
1086
|
+
sslNginxConfig.frontendCoreDomain = frontendCoreUrl;
|
|
1087
|
+
sslNginxConfig.frontendCorePort = 8085;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
if (hasBackendCore && backendCoreUrl) {
|
|
1091
|
+
sslNginxConfig.backendCoreDomain = backendCoreUrl;
|
|
1092
|
+
sslNginxConfig.backendCorePort = 4002;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1019
1095
|
await updateNginxForSSL(sslNginxConfig);
|
|
1020
1096
|
|
|
1021
1097
|
// Step 3: Setup auto-renewal
|
|
@@ -1176,6 +1252,12 @@ export async function setDomain(options) {
|
|
|
1176
1252
|
if (hasMlmApp && mlmAppUrl) {
|
|
1177
1253
|
console.log(chalk.cyan('MLM App: '), chalk.white(mlmAppUrl));
|
|
1178
1254
|
}
|
|
1255
|
+
if (hasFrontendCore && frontendCoreUrl) {
|
|
1256
|
+
console.log(chalk.cyan('Frontend Core: '), chalk.white(frontendCoreUrl));
|
|
1257
|
+
}
|
|
1258
|
+
if (hasBackendCore && backendCoreUrl) {
|
|
1259
|
+
console.log(chalk.cyan('Backend Core: '), chalk.white(backendCoreUrl));
|
|
1260
|
+
}
|
|
1179
1261
|
console.log(chalk.cyan('API: '), chalk.white(apiUrl));
|
|
1180
1262
|
console.log(chalk.cyan('WebSocket: '), chalk.white(apiUrl));
|
|
1181
1263
|
|
|
@@ -1193,6 +1275,12 @@ export async function setDomain(options) {
|
|
|
1193
1275
|
if (hasMlmApp && mlmAppUrl) {
|
|
1194
1276
|
console.log(chalk.white(` MLM App: ${mlmAppUrl}`));
|
|
1195
1277
|
}
|
|
1278
|
+
if (hasFrontendCore && frontendCoreUrl) {
|
|
1279
|
+
console.log(chalk.white(` Frontend Core: ${frontendCoreUrl}`));
|
|
1280
|
+
}
|
|
1281
|
+
if (hasBackendCore && backendCoreUrl) {
|
|
1282
|
+
console.log(chalk.white(` Backend Core: ${backendCoreUrl}`));
|
|
1283
|
+
}
|
|
1196
1284
|
console.log();
|
|
1197
1285
|
|
|
1198
1286
|
} catch (error) {
|
|
@@ -48,7 +48,7 @@ function getEnvValue(envPath, key) {
|
|
|
48
48
|
/**
|
|
49
49
|
* Check if optional apps are installed by checking docker-compose.yml
|
|
50
50
|
* @param {string} composeFile - Path to docker-compose.yml
|
|
51
|
-
* @returns {{hasGateApp: boolean, hasGuardianApp: boolean, hasFacialWeb: boolean, hasPosApp: boolean, hasMlmApp: boolean, hasBackendMlm: boolean}}
|
|
51
|
+
* @returns {{hasGateApp: boolean, hasGuardianApp: boolean, hasFacialWeb: boolean, hasPosApp: boolean, hasMlmApp: boolean, hasBackendMlm: boolean, hasFrontendCore: boolean, hasBackendCore: boolean}}
|
|
52
52
|
*/
|
|
53
53
|
function detectInstalledApps(composeFile) {
|
|
54
54
|
try {
|
|
@@ -59,10 +59,12 @@ function detectInstalledApps(composeFile) {
|
|
|
59
59
|
hasFacialWeb: composeContent.includes('facial-web:') || composeContent.includes('container_name: ante-facial-web'),
|
|
60
60
|
hasPosApp: composeContent.includes('pos-app:') || composeContent.includes('container_name: ante-pos'),
|
|
61
61
|
hasMlmApp: composeContent.includes('mlm-app:') || composeContent.includes('container_name: ante-mlm'),
|
|
62
|
-
hasBackendMlm: composeContent.includes('backend-mlm:') || composeContent.includes('container_name: ante-backend-mlm')
|
|
62
|
+
hasBackendMlm: composeContent.includes('backend-mlm:') || composeContent.includes('container_name: ante-backend-mlm'),
|
|
63
|
+
hasFrontendCore: composeContent.includes('frontend-core:') || composeContent.includes('container_name: ante-frontend-core'),
|
|
64
|
+
hasBackendCore: composeContent.includes('backend-core:') || composeContent.includes('container_name: ante-backend-core')
|
|
63
65
|
};
|
|
64
66
|
} catch {
|
|
65
|
-
return { hasGateApp: false, hasGuardianApp: false, hasFacialWeb: false, hasPosApp: false, hasMlmApp: false, hasBackendMlm: false };
|
|
67
|
+
return { hasGateApp: false, hasGuardianApp: false, hasFacialWeb: false, hasPosApp: false, hasMlmApp: false, hasBackendMlm: false, hasFrontendCore: true, hasBackendCore: true };
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
|
|
@@ -90,7 +92,7 @@ export async function sslEnable(options) {
|
|
|
90
92
|
console.log(chalk.gray(`Installation: ${installDir}\n`));
|
|
91
93
|
|
|
92
94
|
// Detect which apps are installed
|
|
93
|
-
const { hasGateApp, hasGuardianApp, hasFacialWeb, hasPosApp, hasMlmApp, hasBackendMlm } = detectInstalledApps(composeFile);
|
|
95
|
+
const { hasGateApp, hasGuardianApp, hasFacialWeb, hasPosApp, hasMlmApp, hasBackendMlm, hasFrontendCore, hasBackendCore } = detectInstalledApps(composeFile);
|
|
94
96
|
|
|
95
97
|
// Read current configuration
|
|
96
98
|
const frontendUrl = getEnvValue(envPath, 'FRONTEND_URL');
|
|
@@ -101,6 +103,8 @@ export async function sslEnable(options) {
|
|
|
101
103
|
const posAppUrl = hasPosApp ? getEnvValue(envPath, 'POS_APP_URL') : '';
|
|
102
104
|
const mlmAppUrl = hasMlmApp ? getEnvValue(envPath, 'MLM_APP_URL') : '';
|
|
103
105
|
const backendMlmUrl = hasBackendMlm ? getEnvValue(envPath, 'MLM_API_URL') : '';
|
|
106
|
+
const frontendCoreUrl = hasFrontendCore ? getEnvValue(envPath, 'FRONTEND_CORE_URL') : '';
|
|
107
|
+
const backendCoreUrl = hasBackendCore ? getEnvValue(envPath, 'BACKEND_CORE_URL') : '';
|
|
104
108
|
|
|
105
109
|
if (!frontendUrl || !apiUrl) {
|
|
106
110
|
console.log(chalk.red('✗ Domain configuration not found'));
|
|
@@ -120,17 +124,21 @@ export async function sslEnable(options) {
|
|
|
120
124
|
(!facialWebUrl || facialWebUrl.startsWith('https://')) &&
|
|
121
125
|
(!posAppUrl || posAppUrl.startsWith('https://')) &&
|
|
122
126
|
(!mlmAppUrl || mlmAppUrl.startsWith('https://')) &&
|
|
123
|
-
(!backendMlmUrl || backendMlmUrl.startsWith('https://'))
|
|
127
|
+
(!backendMlmUrl || backendMlmUrl.startsWith('https://')) &&
|
|
128
|
+
(!frontendCoreUrl || frontendCoreUrl.startsWith('https://')) &&
|
|
129
|
+
(!backendCoreUrl || backendCoreUrl.startsWith('https://'));
|
|
124
130
|
|
|
125
131
|
if (allHttps) {
|
|
126
132
|
console.log(chalk.yellow('⚠ Domains are already configured with HTTPS:\n'));
|
|
127
133
|
console.log(chalk.gray(` Frontend: ${frontendUrl}`));
|
|
134
|
+
if (frontendCoreUrl) console.log(chalk.gray(` Frontend Core: ${frontendCoreUrl}`));
|
|
128
135
|
if (gateAppUrl) console.log(chalk.gray(` Gate App: ${gateAppUrl}`));
|
|
129
136
|
if (guardianAppUrl) console.log(chalk.gray(` Guardian: ${guardianAppUrl}`));
|
|
130
137
|
if (facialWebUrl) console.log(chalk.gray(` Facial Web: ${facialWebUrl}`));
|
|
131
138
|
if (posAppUrl) console.log(chalk.gray(` POS App: ${posAppUrl}`));
|
|
132
139
|
if (mlmAppUrl) console.log(chalk.gray(` MLM App: ${mlmAppUrl}`));
|
|
133
140
|
if (backendMlmUrl) console.log(chalk.gray(` Backend MLM: ${backendMlmUrl}`));
|
|
141
|
+
if (backendCoreUrl) console.log(chalk.gray(` Backend Core: ${backendCoreUrl}`));
|
|
134
142
|
console.log(chalk.gray(` API: ${apiUrl}\n`));
|
|
135
143
|
|
|
136
144
|
// Check certificate status
|
|
@@ -189,6 +197,22 @@ export async function sslEnable(options) {
|
|
|
189
197
|
}
|
|
190
198
|
}
|
|
191
199
|
|
|
200
|
+
if (frontendCoreUrl) {
|
|
201
|
+
const frontendCoreDomain = extractDomain(frontendCoreUrl);
|
|
202
|
+
const frontendCoreStatus = await checkSSLStatus(frontendCoreDomain);
|
|
203
|
+
if (frontendCoreStatus.installed) {
|
|
204
|
+
console.log(chalk.green(`✓ Frontend Core SSL: Valid (expires in ${frontendCoreStatus.daysUntilExpiry} days)`));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (backendCoreUrl) {
|
|
209
|
+
const backendCoreDomain = extractDomain(backendCoreUrl);
|
|
210
|
+
const backendCoreStatus = await checkSSLStatus(backendCoreDomain);
|
|
211
|
+
if (backendCoreStatus.installed) {
|
|
212
|
+
console.log(chalk.green(`✓ Backend Core SSL: Valid (expires in ${backendCoreStatus.daysUntilExpiry} days)`));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
192
216
|
if (apiStatus.installed) {
|
|
193
217
|
console.log(chalk.green(`✓ API SSL: Valid (expires in ${apiStatus.daysUntilExpiry} days)`));
|
|
194
218
|
}
|
|
@@ -218,12 +242,14 @@ export async function sslEnable(options) {
|
|
|
218
242
|
// Show current configuration
|
|
219
243
|
console.log(chalk.cyan('Current Configuration:'));
|
|
220
244
|
console.log(chalk.gray(` Frontend: ${frontendUrl}`));
|
|
245
|
+
if (frontendCoreUrl) console.log(chalk.gray(` Frontend Core: ${frontendCoreUrl}`));
|
|
221
246
|
if (gateAppUrl) console.log(chalk.gray(` Gate App: ${gateAppUrl}`));
|
|
222
247
|
if (guardianAppUrl) console.log(chalk.gray(` Guardian: ${guardianAppUrl}`));
|
|
223
248
|
if (facialWebUrl) console.log(chalk.gray(` Facial Web: ${facialWebUrl}`));
|
|
224
249
|
if (posAppUrl) console.log(chalk.gray(` POS App: ${posAppUrl}`));
|
|
225
250
|
if (mlmAppUrl) console.log(chalk.gray(` MLM App: ${mlmAppUrl}`));
|
|
226
251
|
if (backendMlmUrl) console.log(chalk.gray(` Backend MLM: ${backendMlmUrl}`));
|
|
252
|
+
if (backendCoreUrl) console.log(chalk.gray(` Backend Core: ${backendCoreUrl}`));
|
|
227
253
|
console.log(chalk.gray(` API: ${apiUrl}\n`));
|
|
228
254
|
|
|
229
255
|
// Detect domains to configure
|
|
@@ -310,6 +336,30 @@ export async function sslEnable(options) {
|
|
|
310
336
|
}
|
|
311
337
|
}
|
|
312
338
|
|
|
339
|
+
if (frontendCoreUrl) {
|
|
340
|
+
const frontendCoreDomain = extractDomain(frontendCoreUrl);
|
|
341
|
+
if (frontendCoreDomain !== 'localhost' && !frontendCoreDomain.match(/^\d+\.\d+\.\d+\.\d+$/) && !domains.find(d => d.domain === frontendCoreDomain)) {
|
|
342
|
+
domains.push({
|
|
343
|
+
name: 'Frontend Core',
|
|
344
|
+
domain: frontendCoreDomain,
|
|
345
|
+
port: frontendCoreUrl.match(/:(\d+)/) ? frontendCoreUrl.match(/:(\d+)/)[1] : 8085,
|
|
346
|
+
url: frontendCoreUrl
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (backendCoreUrl) {
|
|
352
|
+
const backendCoreDomain = extractDomain(backendCoreUrl);
|
|
353
|
+
if (backendCoreDomain !== 'localhost' && !backendCoreDomain.match(/^\d+\.\d+\.\d+\.\d+$/) && !domains.find(d => d.domain === backendCoreDomain)) {
|
|
354
|
+
domains.push({
|
|
355
|
+
name: 'Backend Core',
|
|
356
|
+
domain: backendCoreDomain,
|
|
357
|
+
port: backendCoreUrl.match(/:(\d+)/) ? backendCoreUrl.match(/:(\d+)/)[1] : 4002,
|
|
358
|
+
url: backendCoreUrl
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
313
363
|
if (apiDomain !== 'localhost' && !apiDomain.match(/^\d+\.\d+\.\d+\.\d+$/) && apiDomain !== frontendDomain) {
|
|
314
364
|
domains.push({
|
|
315
365
|
name: 'API',
|
|
@@ -473,6 +523,16 @@ export async function sslEnable(options) {
|
|
|
473
523
|
sslConfig.backendMlmPort = backendMlmUrl.match(/:(\d+)/) ? parseInt(backendMlmUrl.match(/:(\d+)/)[1]) : 4001;
|
|
474
524
|
}
|
|
475
525
|
|
|
526
|
+
if (frontendCoreUrl) {
|
|
527
|
+
sslConfig.frontendCoreDomain = frontendCoreUrl;
|
|
528
|
+
sslConfig.frontendCorePort = frontendCoreUrl.match(/:(\d+)/) ? parseInt(frontendCoreUrl.match(/:(\d+)/)[1]) : 8085;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
if (backendCoreUrl) {
|
|
532
|
+
sslConfig.backendCoreDomain = backendCoreUrl;
|
|
533
|
+
sslConfig.backendCorePort = backendCoreUrl.match(/:(\d+)/) ? parseInt(backendCoreUrl.match(/:(\d+)/)[1]) : 4002;
|
|
534
|
+
}
|
|
535
|
+
|
|
476
536
|
await updateNginxForSSL(sslConfig);
|
|
477
537
|
} catch (error) {
|
|
478
538
|
console.log(chalk.red('\n✗ Failed to configure NGINX:'), error.message);
|
|
@@ -559,7 +619,7 @@ export async function sslStatus() {
|
|
|
559
619
|
const composeFile = join(installDir, 'docker-compose.yml');
|
|
560
620
|
|
|
561
621
|
// Detect which apps are installed
|
|
562
|
-
const { hasGateApp, hasGuardianApp, hasFacialWeb, hasPosApp, hasMlmApp, hasBackendMlm } = detectInstalledApps(composeFile);
|
|
622
|
+
const { hasGateApp, hasGuardianApp, hasFacialWeb, hasPosApp, hasMlmApp, hasBackendMlm, hasFrontendCore, hasBackendCore } = detectInstalledApps(composeFile);
|
|
563
623
|
|
|
564
624
|
const frontendUrl = getEnvValue(envPath, 'FRONTEND_URL');
|
|
565
625
|
const apiUrl = getEnvValue(envPath, 'API_URL');
|
|
@@ -569,6 +629,8 @@ export async function sslStatus() {
|
|
|
569
629
|
const posAppUrl = hasPosApp ? getEnvValue(envPath, 'POS_APP_URL') : '';
|
|
570
630
|
const mlmAppUrl = hasMlmApp ? getEnvValue(envPath, 'MLM_APP_URL') : '';
|
|
571
631
|
const backendMlmUrl = hasBackendMlm ? getEnvValue(envPath, 'MLM_API_URL') : '';
|
|
632
|
+
const frontendCoreUrl = hasFrontendCore ? getEnvValue(envPath, 'FRONTEND_CORE_URL') : '';
|
|
633
|
+
const backendCoreUrl = hasBackendCore ? getEnvValue(envPath, 'BACKEND_CORE_URL') : '';
|
|
572
634
|
|
|
573
635
|
if (!frontendUrl || !apiUrl) {
|
|
574
636
|
console.log(chalk.red('✗ Domain configuration not found\n'));
|
|
@@ -612,6 +674,16 @@ export async function sslStatus() {
|
|
|
612
674
|
domains.push({ name: 'Backend MLM', domain: backendMlmDomain, url: backendMlmUrl });
|
|
613
675
|
}
|
|
614
676
|
|
|
677
|
+
if (frontendCoreUrl) {
|
|
678
|
+
const frontendCoreDomain = extractDomain(frontendCoreUrl);
|
|
679
|
+
domains.push({ name: 'Frontend Core', domain: frontendCoreDomain, url: frontendCoreUrl });
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
if (backendCoreUrl) {
|
|
683
|
+
const backendCoreDomain = extractDomain(backendCoreUrl);
|
|
684
|
+
domains.push({ name: 'Backend Core', domain: backendCoreDomain, url: backendCoreUrl });
|
|
685
|
+
}
|
|
686
|
+
|
|
615
687
|
domains.push({ name: 'API', domain: apiDomain, url: apiUrl });
|
|
616
688
|
|
|
617
689
|
for (const { name, domain, url } of domains) {
|
package/src/commands/update.js
CHANGED
|
@@ -82,6 +82,8 @@ function updateDockerCompose(composeFile, envFile, newServices) {
|
|
|
82
82
|
frontendPort: parseInt(envConfig.FRONTEND_PORT) || 8080,
|
|
83
83
|
backendPort: parseInt(envConfig.BACKEND_PORT) || 3001,
|
|
84
84
|
backendMlmPort: parseInt(envConfig.BACKEND_MLM_PORT) || 4001,
|
|
85
|
+
backendCorePort: parseInt(envConfig.BACKEND_CORE_PORT) || 4002,
|
|
86
|
+
frontendCorePort: parseInt(envConfig.FRONTEND_CORE_PORT) || 8085,
|
|
85
87
|
gateAppPort: parseInt(envConfig.GATE_APP_PORT) || 8081,
|
|
86
88
|
guardianAppPort: parseInt(envConfig.GUARDIAN_APP_PORT) || 8082,
|
|
87
89
|
facialWebPort: parseInt(envConfig.FACIAL_WEB_PORT) || 8083,
|
|
@@ -347,6 +349,8 @@ function refreshDockerCompose(composeFile, envFile) {
|
|
|
347
349
|
frontendPort: parseInt(envConfig.FRONTEND_PORT) || 8080,
|
|
348
350
|
backendPort: parseInt(envConfig.BACKEND_PORT) || 3001,
|
|
349
351
|
backendMlmPort: parseInt(envConfig.BACKEND_MLM_PORT) || 4001,
|
|
352
|
+
backendCorePort: parseInt(envConfig.BACKEND_CORE_PORT) || 4002,
|
|
353
|
+
frontendCorePort: parseInt(envConfig.FRONTEND_CORE_PORT) || 8085,
|
|
350
354
|
gateAppPort: parseInt(envConfig.GATE_APP_PORT) || 8081,
|
|
351
355
|
guardianAppPort: parseInt(envConfig.GUARDIAN_APP_PORT) || 8082,
|
|
352
356
|
facialWebPort: parseInt(envConfig.FACIAL_WEB_PORT) || 8083,
|
|
@@ -396,6 +400,8 @@ function getRequiredPorts(composeFile, envFile) {
|
|
|
396
400
|
// Core services - always needed
|
|
397
401
|
ports.push(parseInt(envConfig.BACKEND_PORT) || 3001); // Backend
|
|
398
402
|
ports.push(parseInt(envConfig.FRONTEND_PORT) || 8080); // Frontend
|
|
403
|
+
ports.push(parseInt(envConfig.BACKEND_CORE_PORT) || 4002); // Backend Core (always included)
|
|
404
|
+
ports.push(parseInt(envConfig.FRONTEND_CORE_PORT) || 8085); // Frontend Core (always included)
|
|
399
405
|
|
|
400
406
|
// Optional services - only add if installed
|
|
401
407
|
if (installed.hasGateApp) {
|
|
@@ -8,6 +8,8 @@ export function generateDockerCompose(options = {}) {
|
|
|
8
8
|
frontendPort = 8080,
|
|
9
9
|
backendPort = 3001,
|
|
10
10
|
backendMlmPort = 4001,
|
|
11
|
+
backendCorePort = 4002,
|
|
12
|
+
frontendCorePort = 8085,
|
|
11
13
|
gateAppPort = 8081,
|
|
12
14
|
guardianAppPort = 8082,
|
|
13
15
|
facialWebPort = 8083,
|
|
@@ -193,6 +195,68 @@ services:
|
|
|
193
195
|
options:
|
|
194
196
|
max-size: "10m"
|
|
195
197
|
max-file: "3"
|
|
198
|
+
|
|
199
|
+
# ANTE Backend Core - Express.js API for Frontend Core
|
|
200
|
+
backend-core:
|
|
201
|
+
image: ghcr.io/gtplusnet/ante-self-hosted-backend-core:latest
|
|
202
|
+
container_name: ante-backend-core
|
|
203
|
+
restart: unless-stopped
|
|
204
|
+
depends_on:
|
|
205
|
+
backend:
|
|
206
|
+
condition: service_healthy
|
|
207
|
+
environment:
|
|
208
|
+
NODE_ENV: production
|
|
209
|
+
BACKEND_CORE_PORT: 4002
|
|
210
|
+
DATABASE_URL: postgresql://ante:\${DB_PASSWORD}@postgres:5432/ante_db?schema=public&connection_limit=10
|
|
211
|
+
DIRECT_URL: postgresql://ante:\${DB_PASSWORD}@postgres:5432/ante_db?schema=public
|
|
212
|
+
REDIS_HOST: redis
|
|
213
|
+
REDIS_PORT: 6379
|
|
214
|
+
REDIS_PASSWORD: \${REDIS_PASSWORD}
|
|
215
|
+
JWT_SECRET: \${JWT_SECRET}
|
|
216
|
+
TZ: \${TZ:-Asia/Manila}
|
|
217
|
+
ports:
|
|
218
|
+
- "${backendCorePort}:4002"
|
|
219
|
+
networks:
|
|
220
|
+
- ante-network
|
|
221
|
+
healthcheck:
|
|
222
|
+
test: ["CMD", "curl", "-f", "http://localhost:4002/health"]
|
|
223
|
+
interval: 30s
|
|
224
|
+
timeout: 10s
|
|
225
|
+
retries: 3
|
|
226
|
+
start_period: 30s
|
|
227
|
+
logging:
|
|
228
|
+
driver: "json-file"
|
|
229
|
+
options:
|
|
230
|
+
max-size: "10m"
|
|
231
|
+
max-file: "3"
|
|
232
|
+
|
|
233
|
+
# ANTE Frontend Core - React Application
|
|
234
|
+
frontend-core:
|
|
235
|
+
image: ghcr.io/gtplusnet/ante-self-hosted-frontend-core:latest
|
|
236
|
+
container_name: ante-frontend-core
|
|
237
|
+
restart: unless-stopped
|
|
238
|
+
depends_on:
|
|
239
|
+
backend-core:
|
|
240
|
+
condition: service_healthy
|
|
241
|
+
environment:
|
|
242
|
+
- VITE_API_URL=\${CORE_API_URL:-http://localhost:${backendCorePort}}
|
|
243
|
+
- VITE_APP_NAME=ANTE Frontend Core
|
|
244
|
+
- VITE_APP_VERSION=\${VERSION:-1.0.0}
|
|
245
|
+
ports:
|
|
246
|
+
- "${frontendCorePort}:8085"
|
|
247
|
+
networks:
|
|
248
|
+
- ante-network
|
|
249
|
+
healthcheck:
|
|
250
|
+
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8085/"]
|
|
251
|
+
interval: 30s
|
|
252
|
+
timeout: 10s
|
|
253
|
+
retries: 3
|
|
254
|
+
start_period: 30s
|
|
255
|
+
logging:
|
|
256
|
+
driver: "json-file"
|
|
257
|
+
options:
|
|
258
|
+
max-size: "10m"
|
|
259
|
+
max-file: "3"
|
|
196
260
|
${installGate ? `
|
|
197
261
|
# ANTE Gate App
|
|
198
262
|
gate-app:
|
package/src/templates/env.js
CHANGED
|
@@ -12,6 +12,8 @@ export function generateEnv(credentials, options = {}) {
|
|
|
12
12
|
frontendPort = 8080,
|
|
13
13
|
backendPort = 3001,
|
|
14
14
|
backendMlmPort = 4001,
|
|
15
|
+
backendCorePort = 4002,
|
|
16
|
+
frontendCorePort = 8085,
|
|
15
17
|
gateAppPort = 8081,
|
|
16
18
|
guardianAppPort = 8082,
|
|
17
19
|
facialWebPort = 8083,
|
|
@@ -23,6 +25,8 @@ export function generateEnv(credentials, options = {}) {
|
|
|
23
25
|
posAppUrl = 'http://localhost:8084',
|
|
24
26
|
mlmAppUrl = 'http://localhost:9005',
|
|
25
27
|
mlmApiUrl = 'http://localhost:4001',
|
|
28
|
+
frontendCoreUrl = 'http://localhost:8085',
|
|
29
|
+
backendCoreUrl = 'http://localhost:4002',
|
|
26
30
|
companyId = 1,
|
|
27
31
|
installGate = false,
|
|
28
32
|
installGuardian = false,
|
|
@@ -74,6 +78,8 @@ SOCKET_URL=${socketUrl}
|
|
|
74
78
|
# ------------------------------------------------------------------------------
|
|
75
79
|
FRONTEND_PORT=${frontendPort}
|
|
76
80
|
BACKEND_PORT=${backendPort}
|
|
81
|
+
BACKEND_CORE_PORT=${backendCorePort}
|
|
82
|
+
FRONTEND_CORE_PORT=${frontendCorePort}
|
|
77
83
|
${installMlm ? `BACKEND_MLM_PORT=${backendMlmPort}` : '# BACKEND_MLM_PORT=4001'}
|
|
78
84
|
${installGate ? `GATE_APP_PORT=${gateAppPort}` : '# GATE_APP_PORT=8081'}
|
|
79
85
|
${installGuardian ? `GUARDIAN_APP_PORT=${guardianAppPort}` : '# GUARDIAN_APP_PORT=8082'}
|
|
@@ -82,6 +88,13 @@ ${installPos ? `POS_APP_PORT=${posAppPort}` : '# POS_APP_PORT=8084'}
|
|
|
82
88
|
${installMlm ? `MLM_APP_PORT=${mlmAppPort}` : '# MLM_APP_PORT=9005'}
|
|
83
89
|
# Note: WebSocket runs on the same port as backend (BACKEND_PORT)
|
|
84
90
|
|
|
91
|
+
# ------------------------------------------------------------------------------
|
|
92
|
+
# CORE SERVICES CONFIGURATION (Always Included)
|
|
93
|
+
# ------------------------------------------------------------------------------
|
|
94
|
+
FRONTEND_CORE_URL=${frontendCoreUrl}
|
|
95
|
+
BACKEND_CORE_URL=${backendCoreUrl}
|
|
96
|
+
CORE_API_URL=${backendCoreUrl}
|
|
97
|
+
|
|
85
98
|
${(installGate || installGuardian || installFacial || installPos || installMlm) ? `# ------------------------------------------------------------------------------
|
|
86
99
|
# FRONTEND APP CONFIGURATION
|
|
87
100
|
# ------------------------------------------------------------------------------
|
package/src/utils/nginx.js
CHANGED
|
@@ -54,6 +54,8 @@ export async function installNginx(spinner) {
|
|
|
54
54
|
* @param {string} [config.posAppDomain] - POS app domain (optional)
|
|
55
55
|
* @param {string} [config.mlmAppDomain] - MLM app domain (optional)
|
|
56
56
|
* @param {string} [config.backendMlmDomain] - Backend MLM API domain (optional)
|
|
57
|
+
* @param {string} [config.frontendCoreDomain] - Frontend Core app domain (optional)
|
|
58
|
+
* @param {string} [config.backendCoreDomain] - Backend Core API domain (optional)
|
|
57
59
|
* @param {number} config.frontendPort - Frontend Docker port (default: 8080)
|
|
58
60
|
* @param {number} config.apiPort - API Docker port (default: 3001)
|
|
59
61
|
* @param {number} [config.gateAppPort] - Gate app Docker port (default: 8081)
|
|
@@ -62,6 +64,8 @@ export async function installNginx(spinner) {
|
|
|
62
64
|
* @param {number} [config.posAppPort] - POS app Docker port (default: 8084)
|
|
63
65
|
* @param {number} [config.mlmAppPort] - MLM app Docker port (default: 9005)
|
|
64
66
|
* @param {number} [config.backendMlmPort] - Backend MLM API Docker port (default: 4001)
|
|
67
|
+
* @param {number} [config.frontendCorePort] - Frontend Core Docker port (default: 8085)
|
|
68
|
+
* @param {number} [config.backendCorePort] - Backend Core API Docker port (default: 4002)
|
|
65
69
|
* @param {boolean} config.ssl - Enable SSL configuration with Let's Encrypt (default: false)
|
|
66
70
|
* @param {boolean} config.cloudflareSsl - Enable Cloudflare SSL mode with self-signed certs (default: false)
|
|
67
71
|
* @returns {string} NGINX configuration content
|
|
@@ -76,6 +80,8 @@ export function generateNginxConfig(config) {
|
|
|
76
80
|
posAppDomain,
|
|
77
81
|
mlmAppDomain,
|
|
78
82
|
backendMlmDomain,
|
|
83
|
+
frontendCoreDomain,
|
|
84
|
+
backendCoreDomain,
|
|
79
85
|
frontendPort = 8080,
|
|
80
86
|
apiPort = 3001,
|
|
81
87
|
gateAppPort = 8081,
|
|
@@ -84,6 +90,8 @@ export function generateNginxConfig(config) {
|
|
|
84
90
|
posAppPort = 8084,
|
|
85
91
|
mlmAppPort = 9005,
|
|
86
92
|
backendMlmPort = 4001,
|
|
93
|
+
frontendCorePort = 8085,
|
|
94
|
+
backendCorePort = 4002,
|
|
87
95
|
ssl = false,
|
|
88
96
|
cloudflareSsl = false,
|
|
89
97
|
domainsWithCerts = []
|
|
@@ -98,6 +106,8 @@ export function generateNginxConfig(config) {
|
|
|
98
106
|
const posAppHost = posAppDomain ? posAppDomain.replace(/^https?:\/\//, '').replace(/:\d+$/, '') : null;
|
|
99
107
|
const mlmAppHost = mlmAppDomain ? mlmAppDomain.replace(/^https?:\/\//, '').replace(/:\d+$/, '') : null;
|
|
100
108
|
const backendMlmHost = backendMlmDomain ? backendMlmDomain.replace(/^https?:\/\//, '').replace(/:\d+$/, '') : null;
|
|
109
|
+
const frontendCoreHost = frontendCoreDomain ? frontendCoreDomain.replace(/^https?:\/\//, '').replace(/:\d+$/, '') : null;
|
|
110
|
+
const backendCoreHost = backendCoreDomain ? backendCoreDomain.replace(/^https?:\/\//, '').replace(/:\d+$/, '') : null;
|
|
101
111
|
|
|
102
112
|
// Cloudflare SSL mode - uses self-signed certs for Cloudflare "Full" mode
|
|
103
113
|
if (cloudflareSsl) {
|
|
@@ -110,6 +120,8 @@ export function generateNginxConfig(config) {
|
|
|
110
120
|
posAppHost,
|
|
111
121
|
mlmAppHost,
|
|
112
122
|
backendMlmHost,
|
|
123
|
+
frontendCoreHost,
|
|
124
|
+
backendCoreHost,
|
|
113
125
|
frontendPort,
|
|
114
126
|
apiPort,
|
|
115
127
|
gateAppPort,
|
|
@@ -117,7 +129,9 @@ export function generateNginxConfig(config) {
|
|
|
117
129
|
facialWebPort,
|
|
118
130
|
posAppPort,
|
|
119
131
|
mlmAppPort,
|
|
120
|
-
backendMlmPort
|
|
132
|
+
backendMlmPort,
|
|
133
|
+
frontendCorePort,
|
|
134
|
+
backendCorePort
|
|
121
135
|
});
|
|
122
136
|
}
|
|
123
137
|
|
|
@@ -132,6 +146,8 @@ export function generateNginxConfig(config) {
|
|
|
132
146
|
posAppHost,
|
|
133
147
|
mlmAppHost,
|
|
134
148
|
backendMlmHost,
|
|
149
|
+
frontendCoreHost,
|
|
150
|
+
backendCoreHost,
|
|
135
151
|
frontendPort,
|
|
136
152
|
apiPort,
|
|
137
153
|
gateAppPort,
|
|
@@ -140,6 +156,8 @@ export function generateNginxConfig(config) {
|
|
|
140
156
|
posAppPort,
|
|
141
157
|
mlmAppPort,
|
|
142
158
|
backendMlmPort,
|
|
159
|
+
frontendCorePort,
|
|
160
|
+
backendCorePort,
|
|
143
161
|
domainsWithCerts
|
|
144
162
|
});
|
|
145
163
|
}
|
|
@@ -395,6 +413,82 @@ server {
|
|
|
395
413
|
proxy_read_timeout 60s;
|
|
396
414
|
}
|
|
397
415
|
}
|
|
416
|
+
` : ''}${frontendCoreHost ? `
|
|
417
|
+
# ANTE Frontend Core Configuration
|
|
418
|
+
server {
|
|
419
|
+
listen 80;
|
|
420
|
+
listen [::]:80;
|
|
421
|
+
server_name ${frontendCoreHost};
|
|
422
|
+
|
|
423
|
+
# Increase buffer sizes for large headers
|
|
424
|
+
client_header_buffer_size 16k;
|
|
425
|
+
large_client_header_buffers 4 16k;
|
|
426
|
+
|
|
427
|
+
# Increase body size for file uploads
|
|
428
|
+
client_max_body_size 100M;
|
|
429
|
+
|
|
430
|
+
# Disable caching for config.js to ensure runtime config is always fresh
|
|
431
|
+
location = /config.js {
|
|
432
|
+
proxy_pass http://localhost:${frontendCorePort}/config.js;
|
|
433
|
+
proxy_http_version 1.1;
|
|
434
|
+
proxy_set_header Host $host;
|
|
435
|
+
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
|
436
|
+
add_header Pragma "no-cache" always;
|
|
437
|
+
add_header Expires "0" always;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
location / {
|
|
441
|
+
proxy_pass http://localhost:${frontendCorePort};
|
|
442
|
+
proxy_http_version 1.1;
|
|
443
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
444
|
+
proxy_set_header Connection 'upgrade';
|
|
445
|
+
proxy_set_header Host $host;
|
|
446
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
447
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
448
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
449
|
+
proxy_cache_bypass $http_upgrade;
|
|
450
|
+
|
|
451
|
+
# Timeout settings
|
|
452
|
+
proxy_connect_timeout 60s;
|
|
453
|
+
proxy_send_timeout 60s;
|
|
454
|
+
proxy_read_timeout 60s;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
` : ''}${backendCoreHost ? `
|
|
458
|
+
# ANTE Backend Core API Configuration
|
|
459
|
+
server {
|
|
460
|
+
listen 80;
|
|
461
|
+
listen [::]:80;
|
|
462
|
+
server_name ${backendCoreHost};
|
|
463
|
+
|
|
464
|
+
# Increase buffer sizes for large headers
|
|
465
|
+
client_header_buffer_size 16k;
|
|
466
|
+
large_client_header_buffers 4 16k;
|
|
467
|
+
|
|
468
|
+
# Increase body size for file uploads
|
|
469
|
+
client_max_body_size 100M;
|
|
470
|
+
|
|
471
|
+
location / {
|
|
472
|
+
proxy_pass http://localhost:${backendCorePort};
|
|
473
|
+
proxy_http_version 1.1;
|
|
474
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
475
|
+
proxy_set_header Connection 'upgrade';
|
|
476
|
+
proxy_set_header Host $host;
|
|
477
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
478
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
479
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
480
|
+
proxy_cache_bypass $http_upgrade;
|
|
481
|
+
|
|
482
|
+
# Timeout settings
|
|
483
|
+
proxy_connect_timeout 60s;
|
|
484
|
+
proxy_send_timeout 60s;
|
|
485
|
+
proxy_read_timeout 60s;
|
|
486
|
+
|
|
487
|
+
# WebSocket support
|
|
488
|
+
proxy_set_header X-Forwarded-Host $host;
|
|
489
|
+
proxy_set_header X-Forwarded-Server $host;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
398
492
|
` : ''}`;
|
|
399
493
|
}
|
|
400
494
|
|
|
@@ -415,6 +509,8 @@ function generateCloudflareNginxConfig(config) {
|
|
|
415
509
|
posAppHost,
|
|
416
510
|
mlmAppHost,
|
|
417
511
|
backendMlmHost,
|
|
512
|
+
frontendCoreHost,
|
|
513
|
+
backendCoreHost,
|
|
418
514
|
frontendPort,
|
|
419
515
|
apiPort,
|
|
420
516
|
gateAppPort = 8081,
|
|
@@ -422,7 +518,9 @@ function generateCloudflareNginxConfig(config) {
|
|
|
422
518
|
facialWebPort = 8083,
|
|
423
519
|
posAppPort = 8084,
|
|
424
520
|
mlmAppPort = 9005,
|
|
425
|
-
backendMlmPort = 4001
|
|
521
|
+
backendMlmPort = 4001,
|
|
522
|
+
frontendCorePort = 8085,
|
|
523
|
+
backendCorePort = 4002
|
|
426
524
|
} = config;
|
|
427
525
|
|
|
428
526
|
// SSL certificate paths for Cloudflare self-signed certs
|
|
@@ -728,6 +826,94 @@ server {
|
|
|
728
826
|
proxy_read_timeout 60s;
|
|
729
827
|
}
|
|
730
828
|
}
|
|
829
|
+
` : ''}${frontendCoreHost ? `
|
|
830
|
+
# ANTE Frontend Core Configuration (Cloudflare SSL)
|
|
831
|
+
server {
|
|
832
|
+
listen 80;
|
|
833
|
+
listen 443 ssl;
|
|
834
|
+
listen [::]:80;
|
|
835
|
+
listen [::]:443 ssl;
|
|
836
|
+
server_name ${frontendCoreHost};
|
|
837
|
+
|
|
838
|
+
# SSL Certificate (self-signed for Cloudflare Full mode)
|
|
839
|
+
ssl_certificate ${sslCert};
|
|
840
|
+
ssl_certificate_key ${sslKey};
|
|
841
|
+
|
|
842
|
+
# Increase buffer sizes for large headers
|
|
843
|
+
client_header_buffer_size 16k;
|
|
844
|
+
large_client_header_buffers 4 16k;
|
|
845
|
+
|
|
846
|
+
# Increase body size for file uploads
|
|
847
|
+
client_max_body_size 100M;
|
|
848
|
+
|
|
849
|
+
# Disable caching for config.js to ensure runtime config is always fresh
|
|
850
|
+
location = /config.js {
|
|
851
|
+
proxy_pass http://localhost:${frontendCorePort}/config.js;
|
|
852
|
+
proxy_http_version 1.1;
|
|
853
|
+
proxy_set_header Host $host;
|
|
854
|
+
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
|
855
|
+
add_header Pragma "no-cache" always;
|
|
856
|
+
add_header Expires "0" always;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
location / {
|
|
860
|
+
proxy_pass http://localhost:${frontendCorePort};
|
|
861
|
+
proxy_http_version 1.1;
|
|
862
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
863
|
+
proxy_set_header Connection 'upgrade';
|
|
864
|
+
proxy_set_header Host $host;
|
|
865
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
866
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
867
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
868
|
+
proxy_cache_bypass $http_upgrade;
|
|
869
|
+
|
|
870
|
+
# Timeout settings
|
|
871
|
+
proxy_connect_timeout 60s;
|
|
872
|
+
proxy_send_timeout 60s;
|
|
873
|
+
proxy_read_timeout 60s;
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
` : ''}${backendCoreHost ? `
|
|
877
|
+
# ANTE Backend Core API Configuration (Cloudflare SSL)
|
|
878
|
+
server {
|
|
879
|
+
listen 80;
|
|
880
|
+
listen 443 ssl;
|
|
881
|
+
listen [::]:80;
|
|
882
|
+
listen [::]:443 ssl;
|
|
883
|
+
server_name ${backendCoreHost};
|
|
884
|
+
|
|
885
|
+
# SSL Certificate (self-signed for Cloudflare Full mode)
|
|
886
|
+
ssl_certificate ${sslCert};
|
|
887
|
+
ssl_certificate_key ${sslKey};
|
|
888
|
+
|
|
889
|
+
# Increase buffer sizes for large headers
|
|
890
|
+
client_header_buffer_size 16k;
|
|
891
|
+
large_client_header_buffers 4 16k;
|
|
892
|
+
|
|
893
|
+
# Increase body size for file uploads
|
|
894
|
+
client_max_body_size 100M;
|
|
895
|
+
|
|
896
|
+
location / {
|
|
897
|
+
proxy_pass http://localhost:${backendCorePort};
|
|
898
|
+
proxy_http_version 1.1;
|
|
899
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
900
|
+
proxy_set_header Connection 'upgrade';
|
|
901
|
+
proxy_set_header Host $host;
|
|
902
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
903
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
904
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
905
|
+
proxy_cache_bypass $http_upgrade;
|
|
906
|
+
|
|
907
|
+
# Timeout settings
|
|
908
|
+
proxy_connect_timeout 60s;
|
|
909
|
+
proxy_send_timeout 60s;
|
|
910
|
+
proxy_read_timeout 60s;
|
|
911
|
+
|
|
912
|
+
# WebSocket support
|
|
913
|
+
proxy_set_header X-Forwarded-Host $host;
|
|
914
|
+
proxy_set_header X-Forwarded-Server $host;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
731
917
|
` : ''}`;
|
|
732
918
|
}
|
|
733
919
|
|
|
@@ -776,6 +962,8 @@ export async function generateCloudflareCert() {
|
|
|
776
962
|
* @param {string} [config.posAppHost] - POS app hostname (optional)
|
|
777
963
|
* @param {string} [config.mlmAppHost] - MLM app hostname (optional)
|
|
778
964
|
* @param {string} [config.backendMlmHost] - Backend MLM API hostname (optional)
|
|
965
|
+
* @param {string} [config.frontendCoreHost] - Frontend Core hostname (optional)
|
|
966
|
+
* @param {string} [config.backendCoreHost] - Backend Core API hostname (optional)
|
|
779
967
|
* @param {number} config.frontendPort - Frontend port
|
|
780
968
|
* @param {number} config.apiPort - API port
|
|
781
969
|
* @param {number} [config.gateAppPort] - Gate app port (default: 8081)
|
|
@@ -784,6 +972,8 @@ export async function generateCloudflareCert() {
|
|
|
784
972
|
* @param {number} [config.posAppPort] - POS app port (default: 8084)
|
|
785
973
|
* @param {number} [config.mlmAppPort] - MLM app port (default: 9005)
|
|
786
974
|
* @param {number} [config.backendMlmPort] - Backend MLM API port (default: 4001)
|
|
975
|
+
* @param {number} [config.frontendCorePort] - Frontend Core port (default: 8085)
|
|
976
|
+
* @param {number} [config.backendCorePort] - Backend Core API port (default: 4002)
|
|
787
977
|
* @param {string[]} [config.domainsWithCerts] - List of domains that have valid SSL certificates
|
|
788
978
|
* @returns {string} NGINX configuration with SSL
|
|
789
979
|
*/
|
|
@@ -797,6 +987,8 @@ function generateSslNginxConfig(config) {
|
|
|
797
987
|
posAppHost,
|
|
798
988
|
mlmAppHost,
|
|
799
989
|
backendMlmHost,
|
|
990
|
+
frontendCoreHost,
|
|
991
|
+
backendCoreHost,
|
|
800
992
|
frontendPort,
|
|
801
993
|
apiPort,
|
|
802
994
|
gateAppPort = 8081,
|
|
@@ -805,6 +997,8 @@ function generateSslNginxConfig(config) {
|
|
|
805
997
|
posAppPort = 8084,
|
|
806
998
|
mlmAppPort = 9005,
|
|
807
999
|
backendMlmPort = 4001,
|
|
1000
|
+
frontendCorePort = 8085,
|
|
1001
|
+
backendCorePort = 4002,
|
|
808
1002
|
domainsWithCerts = []
|
|
809
1003
|
} = config;
|
|
810
1004
|
|
|
@@ -1170,6 +1364,125 @@ server {
|
|
|
1170
1364
|
config_output += generateServerBlock(backendMlmHost, backendMlmPort, 'ANTE Backend MLM API');
|
|
1171
1365
|
}
|
|
1172
1366
|
|
|
1367
|
+
if (frontendCoreHost) {
|
|
1368
|
+
// Frontend Core has special config.js caching rules
|
|
1369
|
+
if (hasCert(frontendCoreHost)) {
|
|
1370
|
+
config_output += `
|
|
1371
|
+
# ANTE Frontend Core Configuration (HTTPS)
|
|
1372
|
+
server {
|
|
1373
|
+
listen 443 ssl;
|
|
1374
|
+
listen [::]:443 ssl;
|
|
1375
|
+
http2 on;
|
|
1376
|
+
server_name ${frontendCoreHost};
|
|
1377
|
+
|
|
1378
|
+
# SSL Certificate paths
|
|
1379
|
+
ssl_certificate /etc/letsencrypt/live/${frontendCoreHost}/fullchain.pem;
|
|
1380
|
+
ssl_certificate_key /etc/letsencrypt/live/${frontendCoreHost}/privkey.pem;
|
|
1381
|
+
|
|
1382
|
+
# SSL Configuration
|
|
1383
|
+
ssl_protocols TLSv1.2 TLSv1.3;
|
|
1384
|
+
ssl_ciphers HIGH:!aNULL:!MD5;
|
|
1385
|
+
ssl_prefer_server_ciphers on;
|
|
1386
|
+
ssl_session_cache shared:SSL:10m;
|
|
1387
|
+
ssl_session_timeout 10m;
|
|
1388
|
+
|
|
1389
|
+
# Security headers
|
|
1390
|
+
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
|
1391
|
+
add_header X-Frame-Options SAMEORIGIN always;
|
|
1392
|
+
add_header X-Content-Type-Options nosniff always;
|
|
1393
|
+
add_header X-XSS-Protection "1; mode=block" always;
|
|
1394
|
+
|
|
1395
|
+
# Increase buffer sizes for large headers
|
|
1396
|
+
client_header_buffer_size 16k;
|
|
1397
|
+
large_client_header_buffers 4 16k;
|
|
1398
|
+
|
|
1399
|
+
# Increase body size for file uploads
|
|
1400
|
+
client_max_body_size 100M;
|
|
1401
|
+
|
|
1402
|
+
# Disable caching for config.js to ensure runtime config is always fresh
|
|
1403
|
+
location = /config.js {
|
|
1404
|
+
proxy_pass http://localhost:${frontendCorePort}/config.js;
|
|
1405
|
+
proxy_http_version 1.1;
|
|
1406
|
+
proxy_set_header Host $host;
|
|
1407
|
+
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
|
1408
|
+
add_header Pragma "no-cache" always;
|
|
1409
|
+
add_header Expires "0" always;
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
location / {
|
|
1413
|
+
proxy_pass http://localhost:${frontendCorePort};
|
|
1414
|
+
proxy_http_version 1.1;
|
|
1415
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
1416
|
+
proxy_set_header Connection 'upgrade';
|
|
1417
|
+
proxy_set_header Host $host;
|
|
1418
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
1419
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
1420
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
1421
|
+
proxy_cache_bypass $http_upgrade;
|
|
1422
|
+
|
|
1423
|
+
# Timeout settings
|
|
1424
|
+
proxy_connect_timeout 60s;
|
|
1425
|
+
proxy_send_timeout 60s;
|
|
1426
|
+
proxy_read_timeout 60s;
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
# HTTP to HTTPS redirect for ${frontendCoreHost}
|
|
1431
|
+
server {
|
|
1432
|
+
listen 80;
|
|
1433
|
+
listen [::]:80;
|
|
1434
|
+
server_name ${frontendCoreHost};
|
|
1435
|
+
return 301 https://$server_name$request_uri;
|
|
1436
|
+
}`;
|
|
1437
|
+
} else {
|
|
1438
|
+
config_output += `
|
|
1439
|
+
# ANTE Frontend Core Configuration (HTTP only - SSL cert not available)
|
|
1440
|
+
server {
|
|
1441
|
+
listen 80;
|
|
1442
|
+
listen [::]:80;
|
|
1443
|
+
server_name ${frontendCoreHost};
|
|
1444
|
+
|
|
1445
|
+
# Increase buffer sizes for large headers
|
|
1446
|
+
client_header_buffer_size 16k;
|
|
1447
|
+
large_client_header_buffers 4 16k;
|
|
1448
|
+
|
|
1449
|
+
# Increase body size for file uploads
|
|
1450
|
+
client_max_body_size 100M;
|
|
1451
|
+
|
|
1452
|
+
# Disable caching for config.js to ensure runtime config is always fresh
|
|
1453
|
+
location = /config.js {
|
|
1454
|
+
proxy_pass http://localhost:${frontendCorePort}/config.js;
|
|
1455
|
+
proxy_http_version 1.1;
|
|
1456
|
+
proxy_set_header Host $host;
|
|
1457
|
+
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
|
|
1458
|
+
add_header Pragma "no-cache" always;
|
|
1459
|
+
add_header Expires "0" always;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1462
|
+
location / {
|
|
1463
|
+
proxy_pass http://localhost:${frontendCorePort};
|
|
1464
|
+
proxy_http_version 1.1;
|
|
1465
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
1466
|
+
proxy_set_header Connection 'upgrade';
|
|
1467
|
+
proxy_set_header Host $host;
|
|
1468
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
1469
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
1470
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
1471
|
+
proxy_cache_bypass $http_upgrade;
|
|
1472
|
+
|
|
1473
|
+
# Timeout settings
|
|
1474
|
+
proxy_connect_timeout 60s;
|
|
1475
|
+
proxy_send_timeout 60s;
|
|
1476
|
+
proxy_read_timeout 60s;
|
|
1477
|
+
}
|
|
1478
|
+
}`;
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
if (backendCoreHost) {
|
|
1483
|
+
config_output += generateServerBlock(backendCoreHost, backendCorePort, 'ANTE Backend Core API');
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1173
1486
|
return config_output.trim();
|
|
1174
1487
|
}
|
|
1175
1488
|
|
|
@@ -1283,6 +1596,12 @@ export async function configureNginx(config) {
|
|
|
1283
1596
|
if (config.mlmAppDomain) {
|
|
1284
1597
|
console.log(chalk.gray(` Client App: ${config.mlmAppDomain} → localhost:${config.mlmAppPort || 9005}`));
|
|
1285
1598
|
}
|
|
1599
|
+
if (config.frontendCoreDomain) {
|
|
1600
|
+
console.log(chalk.gray(` Frontend Core: ${config.frontendCoreDomain} → localhost:${config.frontendCorePort || 8085}`));
|
|
1601
|
+
}
|
|
1602
|
+
if (config.backendCoreDomain) {
|
|
1603
|
+
console.log(chalk.gray(` Backend Core API: ${config.backendCoreDomain} → localhost:${config.backendCorePort || 4002}`));
|
|
1604
|
+
}
|
|
1286
1605
|
console.log(chalk.gray(` API: ${config.apiDomain} → localhost:${config.apiPort || 3001}`));
|
|
1287
1606
|
|
|
1288
1607
|
} catch (error) {
|
package/src/utils/ssl.js
CHANGED
|
@@ -141,6 +141,8 @@ export async function obtainSSLCertificate(config) {
|
|
|
141
141
|
* @param {string} [config.posAppDomain] - POS App domain URL (optional)
|
|
142
142
|
* @param {string} [config.mlmAppDomain] - MLM App domain URL (optional)
|
|
143
143
|
* @param {string} [config.backendMlmDomain] - Backend MLM API domain URL (optional)
|
|
144
|
+
* @param {string} [config.frontendCoreDomain] - Frontend Core domain URL (optional)
|
|
145
|
+
* @param {string} [config.backendCoreDomain] - Backend Core API domain URL (optional)
|
|
144
146
|
* @param {number} [config.frontendPort=8080] - Frontend port
|
|
145
147
|
* @param {number} [config.apiPort=3001] - API port
|
|
146
148
|
* @param {number} [config.gateAppPort=8081] - Gate App port
|
|
@@ -149,6 +151,8 @@ export async function obtainSSLCertificate(config) {
|
|
|
149
151
|
* @param {number} [config.posAppPort=8084] - POS App port
|
|
150
152
|
* @param {number} [config.mlmAppPort=9005] - MLM App port
|
|
151
153
|
* @param {number} [config.backendMlmPort=4001] - Backend MLM API port
|
|
154
|
+
* @param {number} [config.frontendCorePort=8085] - Frontend Core port
|
|
155
|
+
* @param {number} [config.backendCorePort=4002] - Backend Core API port
|
|
152
156
|
* @param {string[]} [config.domainsWithCerts=[]] - List of domains that have valid SSL certificates
|
|
153
157
|
* @returns {Promise<void>}
|
|
154
158
|
*/
|
|
@@ -162,6 +166,8 @@ export async function updateNginxForSSL(config) {
|
|
|
162
166
|
posAppDomain,
|
|
163
167
|
mlmAppDomain,
|
|
164
168
|
backendMlmDomain,
|
|
169
|
+
frontendCoreDomain,
|
|
170
|
+
backendCoreDomain,
|
|
165
171
|
frontendPort = 8080,
|
|
166
172
|
apiPort = 3001,
|
|
167
173
|
gateAppPort = 8081,
|
|
@@ -170,6 +176,8 @@ export async function updateNginxForSSL(config) {
|
|
|
170
176
|
posAppPort = 8084,
|
|
171
177
|
mlmAppPort = 9005,
|
|
172
178
|
backendMlmPort = 4001,
|
|
179
|
+
frontendCorePort = 8085,
|
|
180
|
+
backendCorePort = 4002,
|
|
173
181
|
domainsWithCerts = []
|
|
174
182
|
} = config;
|
|
175
183
|
const spinner = ora('Updating NGINX configuration for HTTPS...').start();
|
|
@@ -199,6 +207,8 @@ export async function updateNginxForSSL(config) {
|
|
|
199
207
|
posAppDomain,
|
|
200
208
|
mlmAppDomain,
|
|
201
209
|
backendMlmDomain,
|
|
210
|
+
frontendCoreDomain,
|
|
211
|
+
backendCoreDomain,
|
|
202
212
|
frontendPort,
|
|
203
213
|
apiPort,
|
|
204
214
|
gateAppPort,
|
|
@@ -207,6 +217,8 @@ export async function updateNginxForSSL(config) {
|
|
|
207
217
|
posAppPort,
|
|
208
218
|
mlmAppPort,
|
|
209
219
|
backendMlmPort,
|
|
220
|
+
frontendCorePort,
|
|
221
|
+
backendCorePort,
|
|
210
222
|
ssl: true,
|
|
211
223
|
domainsWithCerts
|
|
212
224
|
});
|
package/src/utils/validation.js
CHANGED
|
@@ -228,7 +228,8 @@ export async function checkPort(port) {
|
|
|
228
228
|
* @returns {number[]} Array of ports to check
|
|
229
229
|
*/
|
|
230
230
|
function detectPortsFromEnv(installDir = './ante-erp') {
|
|
231
|
-
|
|
231
|
+
// Default ports now include core services (always included)
|
|
232
|
+
const defaultPorts = [8080, 3001, 4001, 4002, 8085];
|
|
232
233
|
|
|
233
234
|
try {
|
|
234
235
|
const envPath = join(installDir, '.env');
|
|
@@ -258,6 +259,24 @@ function detectPortsFromEnv(installDir = './ante-erp') {
|
|
|
258
259
|
}
|
|
259
260
|
}
|
|
260
261
|
|
|
262
|
+
// Check for BACKEND_CORE_PORT (in case it's customized)
|
|
263
|
+
const backendCorePortMatch = envContent.match(/^BACKEND_CORE_PORT=(\d+)/m);
|
|
264
|
+
if (backendCorePortMatch) {
|
|
265
|
+
const backendCorePort = parseInt(backendCorePortMatch[1]);
|
|
266
|
+
if (!ports.includes(backendCorePort)) {
|
|
267
|
+
ports.push(backendCorePort);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Check for FRONTEND_CORE_PORT (in case it's customized)
|
|
272
|
+
const frontendCorePortMatch = envContent.match(/^FRONTEND_CORE_PORT=(\d+)/m);
|
|
273
|
+
if (frontendCorePortMatch) {
|
|
274
|
+
const frontendCorePort = parseInt(frontendCorePortMatch[1]);
|
|
275
|
+
if (!ports.includes(frontendCorePort)) {
|
|
276
|
+
ports.push(frontendCorePort);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
261
280
|
return ports;
|
|
262
281
|
} catch (error) {
|
|
263
282
|
return defaultPorts;
|