ante-erp-cli 1.11.52 ā 1.11.54
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 +1 -0
- package/package.json +1 -1
- package/src/commands/set-domain.js +56 -6
- package/src/utils/nginx.js +101 -2
package/bin/ante-cli.js
CHANGED
|
@@ -331,6 +331,7 @@ program
|
|
|
331
331
|
.option('--facial <url>', 'Facial Web domain/URL (non-interactive mode)')
|
|
332
332
|
.option('--pos <url>', 'POS App domain/URL (non-interactive mode)')
|
|
333
333
|
.option('--client <url>', 'Client App domain/URL (non-interactive mode)')
|
|
334
|
+
.option('--backend-client <url>', 'Backend Client API domain/URL (non-interactive mode)')
|
|
334
335
|
.option('--detect', 'Auto-detect public IP address')
|
|
335
336
|
.option('--ssl, --enable-ssl', 'Enable SSL certificate (Let\'s Encrypt)')
|
|
336
337
|
.option('--email <email>', 'Email for SSL certificate notifications')
|
package/package.json
CHANGED
|
@@ -96,9 +96,9 @@ function getEnvValue(envPath, key) {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/**
|
|
99
|
-
* Check if gate-app, guardian-app, facial-web,
|
|
99
|
+
* Check if gate-app, guardian-app, facial-web, pos-app, client-app, or backend-client is installed by checking docker-compose.yml
|
|
100
100
|
* @param {string} composeFile - Path to docker-compose.yml
|
|
101
|
-
* @returns {{hasGateApp: boolean, hasGuardianApp: boolean, hasFacialWeb: boolean, hasPosApp: boolean}}
|
|
101
|
+
* @returns {{hasGateApp: boolean, hasGuardianApp: boolean, hasFacialWeb: boolean, hasPosApp: boolean, hasClientApp: boolean, hasBackendClient: boolean}}
|
|
102
102
|
*/
|
|
103
103
|
function detectInstalledApps(composeFile) {
|
|
104
104
|
try {
|
|
@@ -108,10 +108,11 @@ function detectInstalledApps(composeFile) {
|
|
|
108
108
|
hasGuardianApp: composeContent.includes('guardian-app:') || composeContent.includes('container_name: ante-guardian-app'),
|
|
109
109
|
hasFacialWeb: composeContent.includes('facial-web:') || composeContent.includes('container_name: ante-facial-web'),
|
|
110
110
|
hasPosApp: composeContent.includes('pos-app:') || composeContent.includes('container_name: ante-pos'),
|
|
111
|
-
hasClientApp: composeContent.includes('client-app:') || composeContent.includes('container_name: ante-client')
|
|
111
|
+
hasClientApp: composeContent.includes('client-app:') || composeContent.includes('container_name: ante-client'),
|
|
112
|
+
hasBackendClient: composeContent.includes('backend-client:') || composeContent.includes('container_name: ante-backend-client')
|
|
112
113
|
};
|
|
113
114
|
} catch {
|
|
114
|
-
return { hasGateApp: false, hasGuardianApp: false, hasFacialWeb: false, hasPosApp: false, hasClientApp: false };
|
|
115
|
+
return { hasGateApp: false, hasGuardianApp: false, hasFacialWeb: false, hasPosApp: false, hasClientApp: false, hasBackendClient: false };
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
118
|
|
|
@@ -159,10 +160,10 @@ export async function setDomain(options) {
|
|
|
159
160
|
console.log(); // Add spacing
|
|
160
161
|
}
|
|
161
162
|
|
|
162
|
-
let frontendUrl, apiUrl, gateAppUrl, guardianAppUrl, facialWebUrl, posAppUrl, clientAppUrl;
|
|
163
|
+
let frontendUrl, apiUrl, gateAppUrl, guardianAppUrl, facialWebUrl, posAppUrl, clientAppUrl, backendClientUrl;
|
|
163
164
|
|
|
164
165
|
// Detect which apps are installed
|
|
165
|
-
const { hasGateApp, hasGuardianApp, hasFacialWeb, hasPosApp, hasClientApp } = detectInstalledApps(composeFile);
|
|
166
|
+
const { hasGateApp, hasGuardianApp, hasFacialWeb, hasPosApp, hasClientApp, hasBackendClient } = detectInstalledApps(composeFile);
|
|
166
167
|
|
|
167
168
|
if (options.interactive !== false) {
|
|
168
169
|
// Show current values
|
|
@@ -173,6 +174,7 @@ export async function setDomain(options) {
|
|
|
173
174
|
const currentFacialWebUrl = getEnvValue(envPath, 'FACIAL_WEB_URL');
|
|
174
175
|
const currentPosAppUrl = getEnvValue(envPath, 'POS_APP_URL');
|
|
175
176
|
const currentClientAppUrl = getEnvValue(envPath, 'CLIENT_APP_URL');
|
|
177
|
+
const currentBackendClientUrl = getEnvValue(envPath, 'CLIENT_API_URL');
|
|
176
178
|
|
|
177
179
|
if (currentFrontendUrl) {
|
|
178
180
|
console.log(chalk.gray(`Current Frontend URL: ${currentFrontendUrl}`));
|
|
@@ -192,6 +194,9 @@ export async function setDomain(options) {
|
|
|
192
194
|
if (currentClientAppUrl) {
|
|
193
195
|
console.log(chalk.gray(`Current Client App URL: ${currentClientAppUrl}`));
|
|
194
196
|
}
|
|
197
|
+
if (currentBackendClientUrl) {
|
|
198
|
+
console.log(chalk.gray(`Current Backend-Client API URL: ${currentBackendClientUrl}`));
|
|
199
|
+
}
|
|
195
200
|
if (currentApiUrl) {
|
|
196
201
|
console.log(chalk.gray(`Current API URL: ${currentApiUrl}\n`));
|
|
197
202
|
}
|
|
@@ -478,6 +483,7 @@ export async function setDomain(options) {
|
|
|
478
483
|
if (hasFacialWeb) facialWebUrl = `https://${subdomain}-fr.ante.ph`;
|
|
479
484
|
if (hasPosApp) posAppUrl = `https://${subdomain}-pos.ante.ph`;
|
|
480
485
|
if (hasClientApp) clientAppUrl = `https://${subdomain}-client.ante.ph`;
|
|
486
|
+
if (hasBackendClient) backendClientUrl = `https://${subdomain}-api-client.ante.ph`;
|
|
481
487
|
|
|
482
488
|
// Display generated domains for confirmation
|
|
483
489
|
console.log(chalk.cyan('\nš Generated Domain Configuration:\n'));
|
|
@@ -488,6 +494,7 @@ export async function setDomain(options) {
|
|
|
488
494
|
if (hasFacialWeb) console.log(chalk.gray(` Facial Web: ${facialWebUrl}`));
|
|
489
495
|
if (hasPosApp) console.log(chalk.gray(` POS App: ${posAppUrl}`));
|
|
490
496
|
if (hasClientApp) console.log(chalk.gray(` Client App: ${clientAppUrl}`));
|
|
497
|
+
if (hasBackendClient) console.log(chalk.gray(` Backend-Client: ${backendClientUrl}`));
|
|
491
498
|
console.log('');
|
|
492
499
|
|
|
493
500
|
const confirmDomains = await inquirer.prompt([
|
|
@@ -565,6 +572,16 @@ export async function setDomain(options) {
|
|
|
565
572
|
});
|
|
566
573
|
}
|
|
567
574
|
|
|
575
|
+
if (hasBackendClient) {
|
|
576
|
+
domainPrompts.push({
|
|
577
|
+
type: 'input',
|
|
578
|
+
name: 'backendClientUrl',
|
|
579
|
+
message: 'Backend-Client API URL:\n Examples: https://staging-api-client.ante.ph or http://143.198.91.153:4001\n Enter URL',
|
|
580
|
+
default: currentBackendClientUrl || 'http://localhost:4001',
|
|
581
|
+
validate: validateUrl
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
|
|
568
585
|
domainPrompts.push({
|
|
569
586
|
type: 'input',
|
|
570
587
|
name: 'apiUrl',
|
|
@@ -583,6 +600,7 @@ export async function setDomain(options) {
|
|
|
583
600
|
if (hasFacialWeb) facialWebUrl = sanitizeUrl(answers.facialWebUrl);
|
|
584
601
|
if (hasPosApp) posAppUrl = sanitizeUrl(answers.posAppUrl);
|
|
585
602
|
if (hasClientApp) clientAppUrl = sanitizeUrl(answers.clientAppUrl);
|
|
603
|
+
if (hasBackendClient) backendClientUrl = sanitizeUrl(answers.backendClientUrl);
|
|
586
604
|
}
|
|
587
605
|
}
|
|
588
606
|
} else {
|
|
@@ -668,6 +686,17 @@ export async function setDomain(options) {
|
|
|
668
686
|
}
|
|
669
687
|
}
|
|
670
688
|
|
|
689
|
+
if (hasBackendClient) {
|
|
690
|
+
backendClientUrl = options.backendClient ? sanitizeUrl(options.backendClient) : getEnvValue(envPath, 'CLIENT_API_URL');
|
|
691
|
+
if (backendClientUrl) {
|
|
692
|
+
const validation = validateUrl(backendClientUrl);
|
|
693
|
+
if (validation !== true) {
|
|
694
|
+
console.log(chalk.red(`Error: Invalid Backend-Client API URL - ${validation}`));
|
|
695
|
+
process.exit(1);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
671
700
|
// Show what will be configured in non-interactive mode
|
|
672
701
|
console.log(chalk.cyan('\nš Non-interactive mode configuration:\n'));
|
|
673
702
|
console.log(chalk.gray(` Frontend: ${frontendUrl}`));
|
|
@@ -677,6 +706,7 @@ export async function setDomain(options) {
|
|
|
677
706
|
if (hasFacialWeb && facialWebUrl) console.log(chalk.gray(` Facial Web: ${facialWebUrl}`));
|
|
678
707
|
if (hasPosApp && posAppUrl) console.log(chalk.gray(` POS App: ${posAppUrl}`));
|
|
679
708
|
if (hasClientApp && clientAppUrl) console.log(chalk.gray(` Client App: ${clientAppUrl}`));
|
|
709
|
+
if (hasBackendClient && backendClientUrl) console.log(chalk.gray(` Backend-Client: ${backendClientUrl}`));
|
|
680
710
|
console.log('');
|
|
681
711
|
}
|
|
682
712
|
|
|
@@ -709,6 +739,10 @@ export async function setDomain(options) {
|
|
|
709
739
|
envUpdates.CLIENT_APP_URL = clientAppUrl;
|
|
710
740
|
}
|
|
711
741
|
|
|
742
|
+
if (hasBackendClient && backendClientUrl) {
|
|
743
|
+
envUpdates.CLIENT_API_URL = backendClientUrl;
|
|
744
|
+
}
|
|
745
|
+
|
|
712
746
|
updateEnvFile(envPath, envUpdates);
|
|
713
747
|
|
|
714
748
|
console.log(chalk.green('ā Configuration updated'));
|
|
@@ -751,6 +785,11 @@ export async function setDomain(options) {
|
|
|
751
785
|
nginxConfig.clientAppPort = 9005;
|
|
752
786
|
}
|
|
753
787
|
|
|
788
|
+
if (hasBackendClient && backendClientUrl) {
|
|
789
|
+
nginxConfig.backendClientDomain = backendClientUrl;
|
|
790
|
+
nginxConfig.backendClientPort = 4001;
|
|
791
|
+
}
|
|
792
|
+
|
|
754
793
|
await configureNginx(nginxConfig);
|
|
755
794
|
} catch (error) {
|
|
756
795
|
console.log(chalk.yellow('\nā NGINX configuration failed:', error.message));
|
|
@@ -855,6 +894,12 @@ export async function setDomain(options) {
|
|
|
855
894
|
domains.push(clientAppDomain);
|
|
856
895
|
}
|
|
857
896
|
}
|
|
897
|
+
if (hasBackendClient && backendClientUrl && backendClientUrl.startsWith('https://')) {
|
|
898
|
+
const backendClientDomain = extractDomain(backendClientUrl);
|
|
899
|
+
if (backendClientDomain !== 'localhost' && !backendClientDomain.match(/^\d+\.\d+\.\d+\.\d+$/) && !domains.includes(backendClientDomain)) {
|
|
900
|
+
domains.push(backendClientDomain);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
858
903
|
|
|
859
904
|
for (const domain of domains) {
|
|
860
905
|
console.log(chalk.gray(` Obtaining certificate for ${domain}...`));
|
|
@@ -902,6 +947,11 @@ export async function setDomain(options) {
|
|
|
902
947
|
sslNginxConfig.clientAppPort = 9005;
|
|
903
948
|
}
|
|
904
949
|
|
|
950
|
+
if (hasBackendClient && backendClientUrl) {
|
|
951
|
+
sslNginxConfig.backendClientDomain = backendClientUrl;
|
|
952
|
+
sslNginxConfig.backendClientPort = 4001;
|
|
953
|
+
}
|
|
954
|
+
|
|
905
955
|
await updateNginxForSSL(sslNginxConfig);
|
|
906
956
|
|
|
907
957
|
// Step 3: Setup auto-renewal
|
package/src/utils/nginx.js
CHANGED
|
@@ -53,6 +53,7 @@ export async function installNginx(spinner) {
|
|
|
53
53
|
* @param {string} [config.facialAppDomain] - Facial web app domain (optional)
|
|
54
54
|
* @param {string} [config.posAppDomain] - POS app domain (optional)
|
|
55
55
|
* @param {string} [config.clientAppDomain] - Client app domain (optional)
|
|
56
|
+
* @param {string} [config.backendClientDomain] - Backend client API domain (optional)
|
|
56
57
|
* @param {number} config.frontendPort - Frontend Docker port (default: 8080)
|
|
57
58
|
* @param {number} config.apiPort - API Docker port (default: 3001)
|
|
58
59
|
* @param {number} [config.gateAppPort] - Gate app Docker port (default: 8081)
|
|
@@ -60,6 +61,7 @@ export async function installNginx(spinner) {
|
|
|
60
61
|
* @param {number} [config.facialWebPort] - Facial web app Docker port (default: 8083)
|
|
61
62
|
* @param {number} [config.posAppPort] - POS app Docker port (default: 8084)
|
|
62
63
|
* @param {number} [config.clientAppPort] - Client app Docker port (default: 9005)
|
|
64
|
+
* @param {number} [config.backendClientPort] - Backend client API Docker port (default: 4001)
|
|
63
65
|
* @param {boolean} config.ssl - Enable SSL configuration (default: false)
|
|
64
66
|
* @returns {string} NGINX configuration content
|
|
65
67
|
*/
|
|
@@ -72,6 +74,7 @@ export function generateNginxConfig(config) {
|
|
|
72
74
|
facialAppDomain,
|
|
73
75
|
posAppDomain,
|
|
74
76
|
clientAppDomain,
|
|
77
|
+
backendClientDomain,
|
|
75
78
|
frontendPort = 8080,
|
|
76
79
|
apiPort = 3001,
|
|
77
80
|
gateAppPort = 8081,
|
|
@@ -79,6 +82,7 @@ export function generateNginxConfig(config) {
|
|
|
79
82
|
facialWebPort = 8083,
|
|
80
83
|
posAppPort = 8084,
|
|
81
84
|
clientAppPort = 9005,
|
|
85
|
+
backendClientPort = 4001,
|
|
82
86
|
ssl = false
|
|
83
87
|
} = config;
|
|
84
88
|
|
|
@@ -90,6 +94,7 @@ export function generateNginxConfig(config) {
|
|
|
90
94
|
const facialAppHost = facialAppDomain ? facialAppDomain.replace(/^https?:\/\//, '').replace(/:\d+$/, '') : null;
|
|
91
95
|
const posAppHost = posAppDomain ? posAppDomain.replace(/^https?:\/\//, '').replace(/:\d+$/, '') : null;
|
|
92
96
|
const clientAppHost = clientAppDomain ? clientAppDomain.replace(/^https?:\/\//, '').replace(/:\d+$/, '') : null;
|
|
97
|
+
const backendClientHost = backendClientDomain ? backendClientDomain.replace(/^https?:\/\//, '').replace(/:\d+$/, '') : null;
|
|
93
98
|
|
|
94
99
|
if (ssl) {
|
|
95
100
|
return generateSslNginxConfig({
|
|
@@ -100,13 +105,15 @@ export function generateNginxConfig(config) {
|
|
|
100
105
|
facialAppHost,
|
|
101
106
|
posAppHost,
|
|
102
107
|
clientAppHost,
|
|
108
|
+
backendClientHost,
|
|
103
109
|
frontendPort,
|
|
104
110
|
apiPort,
|
|
105
111
|
gateAppPort,
|
|
106
112
|
guardianAppPort,
|
|
107
113
|
facialWebPort,
|
|
108
114
|
posAppPort,
|
|
109
|
-
clientAppPort
|
|
115
|
+
clientAppPort,
|
|
116
|
+
backendClientPort
|
|
110
117
|
});
|
|
111
118
|
}
|
|
112
119
|
|
|
@@ -330,6 +337,37 @@ server {
|
|
|
330
337
|
proxy_read_timeout 60s;
|
|
331
338
|
}
|
|
332
339
|
}
|
|
340
|
+
` : ''}${backendClientHost ? `
|
|
341
|
+
# ANTE Backend Client API Configuration
|
|
342
|
+
server {
|
|
343
|
+
listen 80;
|
|
344
|
+
listen [::]:80;
|
|
345
|
+
server_name ${backendClientHost};
|
|
346
|
+
|
|
347
|
+
# Increase buffer sizes for large headers
|
|
348
|
+
client_header_buffer_size 16k;
|
|
349
|
+
large_client_header_buffers 4 16k;
|
|
350
|
+
|
|
351
|
+
# Increase body size for file uploads
|
|
352
|
+
client_max_body_size 100M;
|
|
353
|
+
|
|
354
|
+
location / {
|
|
355
|
+
proxy_pass http://localhost:${backendClientPort};
|
|
356
|
+
proxy_http_version 1.1;
|
|
357
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
358
|
+
proxy_set_header Connection 'upgrade';
|
|
359
|
+
proxy_set_header Host $host;
|
|
360
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
361
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
362
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
363
|
+
proxy_cache_bypass $http_upgrade;
|
|
364
|
+
|
|
365
|
+
# Timeout settings
|
|
366
|
+
proxy_connect_timeout 60s;
|
|
367
|
+
proxy_send_timeout 60s;
|
|
368
|
+
proxy_read_timeout 60s;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
333
371
|
` : ''}`;
|
|
334
372
|
}
|
|
335
373
|
|
|
@@ -343,6 +381,7 @@ server {
|
|
|
343
381
|
* @param {string} [config.facialAppHost] - Facial web app hostname (optional)
|
|
344
382
|
* @param {string} [config.posAppHost] - POS app hostname (optional)
|
|
345
383
|
* @param {string} [config.clientAppHost] - Client app hostname (optional)
|
|
384
|
+
* @param {string} [config.backendClientHost] - Backend client API hostname (optional)
|
|
346
385
|
* @param {number} config.frontendPort - Frontend port
|
|
347
386
|
* @param {number} config.apiPort - API port
|
|
348
387
|
* @param {number} [config.gateAppPort] - Gate app port (default: 8081)
|
|
@@ -350,6 +389,7 @@ server {
|
|
|
350
389
|
* @param {number} [config.facialWebPort] - Facial web app port (default: 8083)
|
|
351
390
|
* @param {number} [config.posAppPort] - POS app port (default: 8084)
|
|
352
391
|
* @param {number} [config.clientAppPort] - Client app port (default: 9005)
|
|
392
|
+
* @param {number} [config.backendClientPort] - Backend client API port (default: 4001)
|
|
353
393
|
* @returns {string} NGINX configuration with SSL
|
|
354
394
|
*/
|
|
355
395
|
function generateSslNginxConfig(config) {
|
|
@@ -361,13 +401,15 @@ function generateSslNginxConfig(config) {
|
|
|
361
401
|
facialAppHost,
|
|
362
402
|
posAppHost,
|
|
363
403
|
clientAppHost,
|
|
404
|
+
backendClientHost,
|
|
364
405
|
frontendPort,
|
|
365
406
|
apiPort,
|
|
366
407
|
gateAppPort = 8081,
|
|
367
408
|
guardianAppPort = 8082,
|
|
368
409
|
facialWebPort = 8083,
|
|
369
410
|
posAppPort = 8084,
|
|
370
|
-
clientAppPort = 9005
|
|
411
|
+
clientAppPort = 9005,
|
|
412
|
+
backendClientPort = 4001
|
|
371
413
|
} = config;
|
|
372
414
|
|
|
373
415
|
return `# ANTE Frontend Configuration (HTTPS)
|
|
@@ -782,6 +824,63 @@ server {
|
|
|
782
824
|
server_name ${clientAppHost};
|
|
783
825
|
return 301 https://$server_name$request_uri;
|
|
784
826
|
}
|
|
827
|
+
` : ''}${backendClientHost ? `
|
|
828
|
+
# ANTE Backend Client API Configuration (HTTPS)
|
|
829
|
+
server {
|
|
830
|
+
listen 443 ssl;
|
|
831
|
+
listen [::]:443 ssl;
|
|
832
|
+
http2 on;
|
|
833
|
+
server_name ${backendClientHost};
|
|
834
|
+
|
|
835
|
+
# SSL Certificate paths
|
|
836
|
+
ssl_certificate /etc/letsencrypt/live/${backendClientHost}/fullchain.pem;
|
|
837
|
+
ssl_certificate_key /etc/letsencrypt/live/${backendClientHost}/privkey.pem;
|
|
838
|
+
|
|
839
|
+
# SSL Configuration
|
|
840
|
+
ssl_protocols TLSv1.2 TLSv1.3;
|
|
841
|
+
ssl_ciphers HIGH:!aNULL:!MD5;
|
|
842
|
+
ssl_prefer_server_ciphers on;
|
|
843
|
+
ssl_session_cache shared:SSL:10m;
|
|
844
|
+
ssl_session_timeout 10m;
|
|
845
|
+
|
|
846
|
+
# Security headers
|
|
847
|
+
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
|
848
|
+
add_header X-Frame-Options SAMEORIGIN always;
|
|
849
|
+
add_header X-Content-Type-Options nosniff always;
|
|
850
|
+
add_header X-XSS-Protection "1; mode=block" always;
|
|
851
|
+
|
|
852
|
+
# Increase buffer sizes for large headers
|
|
853
|
+
client_header_buffer_size 16k;
|
|
854
|
+
large_client_header_buffers 4 16k;
|
|
855
|
+
|
|
856
|
+
# Increase body size for file uploads
|
|
857
|
+
client_max_body_size 100M;
|
|
858
|
+
|
|
859
|
+
location / {
|
|
860
|
+
proxy_pass http://localhost:${backendClientPort};
|
|
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
|
+
|
|
877
|
+
# HTTP to HTTPS redirect for ${backendClientHost}
|
|
878
|
+
server {
|
|
879
|
+
listen 80;
|
|
880
|
+
listen [::]:80;
|
|
881
|
+
server_name ${backendClientHost};
|
|
882
|
+
return 301 https://$server_name$request_uri;
|
|
883
|
+
}
|
|
785
884
|
` : ''}`;
|
|
786
885
|
}
|
|
787
886
|
|