diff --git a/src/nginxconfig/generators/conf/nginx.conf.js b/src/nginxconfig/generators/conf/nginx.conf.js index 48acc00..3ff1b82 100644 --- a/src/nginxconfig/generators/conf/nginx.conf.js +++ b/src/nginxconfig/generators/conf/nginx.conf.js @@ -222,9 +222,10 @@ export default (domains, global) => { // Single file configs if (!global.tools.modularizedStructure.computed) { + const ipPortPairs = new Set(); for (const domain of domains) { config.http.push([`# ${domain.server.domain.computed}`, '']); - config.http.push(...websiteConf(domain, domains, global)); + config.http.push(...websiteConf(domain, domains, global, ipPortPairs)); } } diff --git a/src/nginxconfig/generators/conf/website.conf.js b/src/nginxconfig/generators/conf/website.conf.js index 95f0da2..1d67aef 100644 --- a/src/nginxconfig/generators/conf/website.conf.js +++ b/src/nginxconfig/generators/conf/website.conf.js @@ -56,56 +56,75 @@ const sslConfig = (domain, global) => { return config; }; -const httpsListen = domain => { +const httpsListen = (domain, global, ipPortPairs) => { const config = []; + // Check if reuseport needs to be set + const ipPortV4 = `${domain.server.listenIpv4.computed === '*' ? '' : `${domain.server.listenIpv4.computed}:`}443`; + const reusePortV4 = global.https.portReuse.computed && !ipPortPairs.has(ipPortV4); + if (reusePortV4) ipPortPairs.add(ipPortV4); + // HTTPS config.push(['listen', - `${domain.server.listenIpv4.computed === '*' ? '' : `${domain.server.listenIpv4.computed}:`}443 ssl${domain.https.http2.computed ? ' http2' : ''}`]); + `${ipPortV4} ssl${domain.https.http2.computed ? ' http2' : ''}${reusePortV4 ? ' reuseport' : ''}`]); // HTTP/3 if (domain.https.http3.computed) - config.push(['listen', - `${domain.server.listenIpv4.computed === '*' ? '' : `${domain.server.listenIpv4.computed}:`}443 http3${domain.https.portReuse.computed ? ' reuseport' : ''}`]); + config.push(['listen', `${ipPortV4} http3`]); // v6 - if (domain.server.listenIpv6.computed) - config.push(['listen', - `[${domain.server.listenIpv6.computed}]:443 ssl${domain.https.http2.computed ? ' http2' : ''}`]); + if (domain.server.listenIpv6.computed) { + // Check if reuseport needs to be set + const ipPortV6 = `[${domain.server.listenIpv6.computed}]:443`; + const reusePortV6 = global.https.portReuse.computed && !ipPortPairs.has(ipPortV6); + if (reusePortV6) ipPortPairs.add(ipPortV6); - // v6 HTTP/3 - if (domain.server.listenIpv6.computed && domain.https.http3.computed) + // HTTPS config.push(['listen', - `[${domain.server.listenIpv6.computed}]:443 http3${domain.https.portReuse.computed ? ' reuseport' : ''}`]); + `${ipPortV6} ssl${domain.https.http2.computed ? ' http2' : ''}${reusePortV6 ? ' reuseport' : ''}`]); + + // HTTP/3 + if (domain.https.http3.computed) + config.push(['listen', `${ipPortV6} http3`]); + } return config; }; -const httpListen = domain => { +const httpListen = (domain, global, ipPortPairs) => { const config = []; - // Not HTTPS - config.push(['listen', - `${domain.server.listenIpv4.computed === '*' ? '' : `${domain.server.listenIpv4.computed}:`}80`]); + // Check if reuseport needs to be set + const ipPortV4 = `${domain.server.listenIpv4.computed === '*' ? '' : `${domain.server.listenIpv4.computed}:`}80`; + const reusePortV4 = global.https.portReuse.computed && !ipPortPairs.has(ipPortV4); + if (reusePortV4) ipPortPairs.add(ipPortV4); + + // v4 + config.push(['listen', `${ipPortV4}${reusePortV4 ? ' reuseport' : ''}`]); // v6 - if (domain.server.listenIpv6.computed) - config.push(['listen', `[${domain.server.listenIpv6.computed}]:80`]); + if (domain.server.listenIpv6.computed) { + // Check if reuseport needs to be set + const ipPortV6 = `[${domain.server.listenIpv6.computed}]:80`; + const reusePortV6 = global.https.portReuse.computed && !ipPortPairs.has(ipPortV6); + if (reusePortV6) ipPortPairs.add(ipPortV6); + + config.push(['listen', `${ipPortV6}${reusePortV6 ? ' reuseport' : ''}`]); + } return config; }; -const listenConfig = domain => { - if (domain.https.https.computed) return httpsListen(domain); - return httpListen(domain); +const listenConfig = (domain, global, ipPortPairs) => { + if (domain.https.https.computed) return httpsListen(domain, global, ipPortPairs); + return httpListen(domain, global, ipPortPairs); }; - -const httpRedirectConfig = (domain, global, domainName, redirectDomain) => { +const httpRedirectConfig = (domain, global, ipPortPairs, domainName, redirectDomain) => { // Build the server config on its own before adding it to the parent config const config = []; - config.push(...httpListen(domain)); + config.push(...httpListen(domain, global, ipPortPairs)); config.push(['server_name', domainName]); if (domain.https.certType.computed === 'letsEncrypt') { @@ -130,7 +149,7 @@ const httpRedirectConfig = (domain, global, domainName, redirectDomain) => { return config; }; -export default (domain, domains, global) => { +export default (domain, domains, global, ipPortPairs) => { // Use kv so we can use the same key multiple times const config = []; @@ -138,10 +157,12 @@ export default (domain, domains, global) => { const serverConfig = []; // Not HTTPS or not force HTTPS - if (!domain.https.https.computed || !domain.https.forceHttps.computed) serverConfig.push(...httpListen(domain)); + if (!domain.https.https.computed || !domain.https.forceHttps.computed) + serverConfig.push(...httpListen(domain, global, ipPortPairs)); // HTTPS - if (domain.https.https.computed) serverConfig.push(...httpsListen(domain)); + if (domain.https.https.computed) + serverConfig.push(...httpsListen(domain, global, ipPortPairs)); serverConfig.push(['server_name', `${domain.server.wwwSubdomain.computed ? 'www.' : ''}${domain.server.domain.computed}`]); @@ -340,7 +361,7 @@ export default (domain, domains, global) => { // Build the server config on its own before adding it to the parent config const cdnConfig = []; - cdnConfig.push(...listenConfig(domain)); + cdnConfig.push(...listenConfig(domain, global, ipPortPairs)); cdnConfig.push(['server_name', `cdn.${domain.server.domain.computed}`]); cdnConfig.push(['root', `${domain.server.path.computed}${domain.server.documentRoot.computed}`]); @@ -383,7 +404,7 @@ export default (domain, domains, global) => { // Build the server config on its own before adding it to the parent config const redirectConfig = []; - redirectConfig.push(...listenConfig(domain)); + redirectConfig.push(...listenConfig(domain, global, ipPortPairs)); redirectConfig.push(['server_name', `${domain.server.wwwSubdomain.computed ? '' : '*'}.${domain.server.domain.computed}`]); @@ -403,17 +424,21 @@ export default (domain, domains, global) => { // Add the redirect config to the parent config now its built config.push(['# HTTP redirect', '']); if (domain.server.wwwSubdomain.computed && !domain.server.redirectSubdomains.computed) { - config.push(['server', httpRedirectConfig(domain, global, domain.server.domain.computed, + config.push(['server', httpRedirectConfig(domain, global, ipPortPairs, + domain.server.domain.computed, `www.${domain.server.domain.computed}`)]); + config.push(['server', httpRedirectConfig(domain, global, ipPortPairs, `www.${domain.server.domain.computed}`)]); - config.push(['server', httpRedirectConfig(domain, global, `www.${domain.server.domain.computed}`)]); } else if (!domain.server.wwwSubdomain.computed && !domain.server.redirectSubdomains.computed) { - config.push(['server', httpRedirectConfig(domain, global, domain.server.domain.computed)]); + config.push(['server', httpRedirectConfig(domain, global, ipPortPairs, + domain.server.domain.computed)]); } if (domain.server.cdnSubdomain.computed) { - config.push(['server', httpRedirectConfig(domain, global, `cdn.${domain.server.domain.computed}`)]); + config.push(['server', httpRedirectConfig(domain, global, ipPortPairs, + `cdn.${domain.server.domain.computed}`)]); } if (domain.server.redirectSubdomains.computed) { - config.push(['server', httpRedirectConfig(domain, global, `.${domain.server.domain.computed}`, + config.push(['server', httpRedirectConfig(domain, global, ipPortPairs, + `.${domain.server.domain.computed}`, `${domain.server.wwwSubdomain.computed ? 'www.' : '' }${domain.server.domain.computed}`)]); } } diff --git a/src/nginxconfig/generators/index.js b/src/nginxconfig/generators/index.js index 83e75f9..0479b29 100644 --- a/src/nginxconfig/generators/index.js +++ b/src/nginxconfig/generators/index.js @@ -57,8 +57,10 @@ export default (domains, global) => { // Modularised configs if (global.tools.modularizedStructure.computed) { // Domain config + const sitesDir = `sites-${global.tools.symlinkVhost.computed ? 'available' : 'enabled'}`; + const ipPortPairs = new Set(); for (const domain of domains) { - files[`sites-${global.tools.symlinkVhost.computed ? 'available' : 'enabled'}/${domain.server.domain.computed}.conf`] = toConf(websiteConf(domain, domains, global)); + files[`${sitesDir}/${domain.server.domain.computed}.conf`] = toConf(websiteConf(domain, domains, global, ipPortPairs)); } // Let's encrypt diff --git a/src/nginxconfig/i18n/en/templates/domain_sections/https.js b/src/nginxconfig/i18n/en/templates/domain_sections/https.js index 9aefe26..a6511b6 100644 --- a/src/nginxconfig/i18n/en/templates/domain_sections/https.js +++ b/src/nginxconfig/i18n/en/templates/domain_sections/https.js @@ -32,8 +32,6 @@ export default { enableHttp2Connections: `${common.enable} ${common.http}/2 connections`, http3: `${common.http}/3`, enableHttp3Connections: `${common.enable} ${common.http}/3 connections`, - portReuse: 'Reuseport', - enableReuseOfPort: `${common.enable} reuseport to generate a listening socket per worker`, forceHttps: `Force ${common.https}`, hsts: 'HSTS', enableStrictTransportSecurity: `${common.enable} Strict Transport Security, requiring HTTPS connections`, diff --git a/src/nginxconfig/i18n/en/templates/global_sections/https.js b/src/nginxconfig/i18n/en/templates/global_sections/https.js index ddef688..5815768 100644 --- a/src/nginxconfig/i18n/en/templates/global_sections/https.js +++ b/src/nginxconfig/i18n/en/templates/global_sections/https.js @@ -1,5 +1,5 @@ /* -Copyright 2020 DigitalOcean +Copyright 2021 DigitalOcean This code is licensed under the MIT License. You may obtain a copy of the License at @@ -33,6 +33,8 @@ const ipv6 = 'IPv6'; export default { sslProfile: `${common.ssl} Profile`, httpsMustBeEnabledOnOneSite: `${common.https} must be enabled on at least one site to configure global ${common.https} settings.`, + portReuse: 'Reuseport', + enableReuseOfPort: `${common.enable} reuseport to generate a listening socket per worker`, ocspDnsResolvers: 'OCSP DNS Resolvers', cloudflareResolver: 'Cloudflare Resolver', googlePublicDns: 'Google Public DNS', diff --git a/src/nginxconfig/i18n/fr/templates/domain_sections/https.js b/src/nginxconfig/i18n/fr/templates/domain_sections/https.js index 1db8572..9c6cb6e 100644 --- a/src/nginxconfig/i18n/fr/templates/domain_sections/https.js +++ b/src/nginxconfig/i18n/fr/templates/domain_sections/https.js @@ -32,8 +32,6 @@ export default { enableHttp2Connections: `${common.enable} les connexions ${common.http}/2`, http3: `${common.http}/3`, enableHttp3Connections: `${common.enable} les connexions ${common.http}/3`, - portReuse: 'Reuseport', // TODO: translate - enableReuseOfPort: `${common.enable} reuseport to generate a listening socket per worker`, // TODO: translate forceHttps: `Forcer ${common.https}`, hsts: 'HSTS', enableStrictTransportSecurity: `${common.enable} Strict Transport Security, exigeant HTTPS`, diff --git a/src/nginxconfig/i18n/fr/templates/global_sections/https.js b/src/nginxconfig/i18n/fr/templates/global_sections/https.js index 1a457a6..03841e7 100644 --- a/src/nginxconfig/i18n/fr/templates/global_sections/https.js +++ b/src/nginxconfig/i18n/fr/templates/global_sections/https.js @@ -33,6 +33,8 @@ const ipv6 = 'IPv6'; export default { sslProfile: `Profil ${common.ssl}`, httpsMustBeEnabledOnOneSite: `${common.https} doit être activé sur au moins un site pour configurer les paramètres ${common.https} globaux.`, + portReuse: 'Reuseport', // TODO: translate + enableReuseOfPort: `${common.enable} reuseport to generate a listening socket per worker`, // TODO: translate ocspDnsResolvers: 'Résolveur DNS OCSP', cloudflareResolver: 'Résolveur Cloudflare', googlePublicDns: 'Google Public DNS', diff --git a/src/nginxconfig/i18n/pl/templates/domain_sections/https.js b/src/nginxconfig/i18n/pl/templates/domain_sections/https.js index eede331..7e233b0 100644 --- a/src/nginxconfig/i18n/pl/templates/domain_sections/https.js +++ b/src/nginxconfig/i18n/pl/templates/domain_sections/https.js @@ -32,8 +32,6 @@ export default { enableHttp2Connections: `${common.enable} połączenia ${common.http}/2`, http3: `${common.http}/3`, enableHttp3Connections: `${common.enable} połączenia ${common.http}/3`, - portReuse: 'Reuseport', - enableReuseOfPort: `${common.enable} reuseport aby generować listening socket per worker`, forceHttps: `Wymuś ${common.https}`, hsts: 'HSTS', enableStrictTransportSecurity: `${common.enable} Strict Transport Security, wymaga połaczenia HTTPS`, diff --git a/src/nginxconfig/i18n/pl/templates/global_sections/https.js b/src/nginxconfig/i18n/pl/templates/global_sections/https.js index be41939..9c029c4 100644 --- a/src/nginxconfig/i18n/pl/templates/global_sections/https.js +++ b/src/nginxconfig/i18n/pl/templates/global_sections/https.js @@ -33,6 +33,8 @@ const ipv6 = 'IPv6'; export default { sslProfile: `Profil ${common.ssl}`, httpsMustBeEnabledOnOneSite: `${common.https} musi być włączony na conajmniej jednej stronie, aby móc zastosować globalną konfigurację ${common.https}.`, + portReuse: 'Reuseport', + enableReuseOfPort: `${common.enable} reuseport aby generować listening socket per worker`, ocspDnsResolvers: 'OCSP DNS Resolvers', cloudflareResolver: 'Cloudflare Resolver', googlePublicDns: 'Google Public DNS', diff --git a/src/nginxconfig/i18n/pt-br/templates/domain_sections/https.js b/src/nginxconfig/i18n/pt-br/templates/domain_sections/https.js index 6c52840..5d1ebef 100644 --- a/src/nginxconfig/i18n/pt-br/templates/domain_sections/https.js +++ b/src/nginxconfig/i18n/pt-br/templates/domain_sections/https.js @@ -32,8 +32,6 @@ export default { enableHttp2Connections: `${common.enable} conexões ${common.http}/2`, http3: `${common.http}/3`, enableHttp3Connections: `${common.enable} conexões ${common.http}/3`, - portReuse: 'Reuseport', // TODO: translate - enableReuseOfPort: `${common.enable} reuseport to generate a listening socket per worker`, // TODO: translate forceHttps: `Forçar ${common.https}`, hsts: 'HSTS', enableStrictTransportSecurity: `${common.enable} Strict Transport Security, requerendo conexões HTTPS`, diff --git a/src/nginxconfig/i18n/pt-br/templates/global_sections/https.js b/src/nginxconfig/i18n/pt-br/templates/global_sections/https.js index a385c59..e9a33e9 100644 --- a/src/nginxconfig/i18n/pt-br/templates/global_sections/https.js +++ b/src/nginxconfig/i18n/pt-br/templates/global_sections/https.js @@ -1,5 +1,5 @@ /* -Copyright 2020 DigitalOcean +Copyright 2021 DigitalOcean This code is licensed under the MIT License. You may obtain a copy of the License at @@ -33,6 +33,8 @@ const ipv6 = 'IPv6'; export default { sslProfile: `Perfil ${common.ssl}`, httpsMustBeEnabledOnOneSite: `O ${common.https} deve estar habilitado em pelo menos um site para definir as configurações globais de ${common.https}.`, + portReuse: 'Reuseport', // TODO: translate + enableReuseOfPort: `${common.enable} reuseport to generate a listening socket per worker`, // TODO: translate ocspDnsResolvers: 'Resolvedores de DNS OCSP', cloudflareResolver: 'Resolvedor Cloudflare', googlePublicDns: 'DNS público do Google', diff --git a/src/nginxconfig/i18n/ru/templates/domain_sections/https.js b/src/nginxconfig/i18n/ru/templates/domain_sections/https.js index 97e24a9..c326207 100644 --- a/src/nginxconfig/i18n/ru/templates/domain_sections/https.js +++ b/src/nginxconfig/i18n/ru/templates/domain_sections/https.js @@ -32,8 +32,6 @@ export default { enableHttp2Connections: `${common.enable} ${common.http}/2 соединения`, http3: `${common.http}/3`, enableHttp3Connections: `${common.enable} ${common.http}/3 соединения`, - portReuse: 'Reuseport', // TODO: translate - enableReuseOfPort: `${common.enable} reuseport to generate a listening socket per worker`, // TODO: translate forceHttps: `Использовать только ${common.https}`, hsts: 'HSTS', enableStrictTransportSecurity: `${common.enable} Strict Transport Security, требующая HTTPS соединения`, diff --git a/src/nginxconfig/i18n/ru/templates/global_sections/https.js b/src/nginxconfig/i18n/ru/templates/global_sections/https.js index 28f47de..5631926 100644 --- a/src/nginxconfig/i18n/ru/templates/global_sections/https.js +++ b/src/nginxconfig/i18n/ru/templates/global_sections/https.js @@ -33,6 +33,8 @@ const ipv6 = 'IPv6'; export default { sslProfile: `${common.ssl} Профиль`, httpsMustBeEnabledOnOneSite: `${common.https} должен быть включен хотя бы на одном сайте, чтобы сконфигурировать глобальные ${common.https} настройки.`, + portReuse: 'Reuseport', // TODO: translate + enableReuseOfPort: `${common.enable} reuseport to generate a listening socket per worker`, // TODO: translate ocspDnsResolvers: 'OCSP DNS Преобразователи', cloudflareResolver: 'Cloudflare Преобразователь', googlePublicDns: 'Публичные Google DNS', diff --git a/src/nginxconfig/i18n/zh-cn/templates/domain_sections/https.js b/src/nginxconfig/i18n/zh-cn/templates/domain_sections/https.js index 0c9987f..7f95990 100644 --- a/src/nginxconfig/i18n/zh-cn/templates/domain_sections/https.js +++ b/src/nginxconfig/i18n/zh-cn/templates/domain_sections/https.js @@ -32,8 +32,6 @@ export default { enableHttp2Connections: `${common.enable} ${common.http}/2 连接`, http3: `${common.http}/3`, enableHttp3Connections: `${common.enable} ${common.http}/3 连接`, - portReuse: '端口重用', - enableReuseOfPort: `${common.enable} 重用端口 为每个 NGINX Worker 单独生成一个监听套接字`, forceHttps: `强制 ${common.https}`, hsts: 'HSTS', enableStrictTransportSecurity: `${common.enable}HSTS(强制客户端、浏览器等使用 HTTPS 与服务器创建链接),需要HTTPS连接`, diff --git a/src/nginxconfig/i18n/zh-cn/templates/global_sections/https.js b/src/nginxconfig/i18n/zh-cn/templates/global_sections/https.js index 9e93323..c559236 100644 --- a/src/nginxconfig/i18n/zh-cn/templates/global_sections/https.js +++ b/src/nginxconfig/i18n/zh-cn/templates/global_sections/https.js @@ -1,5 +1,5 @@ /* -Copyright 2020 DigitalOcean +Copyright 2021 DigitalOcean This code is licensed under the MIT License. You may obtain a copy of the License at @@ -33,6 +33,8 @@ const ipv6 = 'IPv6'; export default { sslProfile: `${common.ssl}配置`, httpsMustBeEnabledOnOneSite: `必须在至少一个站点上启用${common.https}才能配置全局${common.https}设置。`, + portReuse: '端口重用', + enableReuseOfPort: `${common.enable} 重用端口 为每个 NGINX Worker 单独生成一个监听套接字`, ocspDnsResolvers: 'OCSP DNS解析器', cloudflareResolver: 'Cloudflare解析器', googlePublicDns: '谷歌公共DNS', diff --git a/src/nginxconfig/i18n/zh-tw/templates/domain_sections/https.js b/src/nginxconfig/i18n/zh-tw/templates/domain_sections/https.js index 8b47140..2733638 100644 --- a/src/nginxconfig/i18n/zh-tw/templates/domain_sections/https.js +++ b/src/nginxconfig/i18n/zh-tw/templates/domain_sections/https.js @@ -32,8 +32,6 @@ export default { enableHttp2Connections: `${common.enable} ${common.http}/2 連接`, http3: `${common.http}/3`, enableHttp3Connections: `${common.enable} ${common.http}/3 連接`, - portReuse: '端口複用', - enableReuseOfPort: `${common.enable} 端口複用來為每個worker生成監聽套接字`, forceHttps: `強制 ${common.https}`, hsts: 'HSTS', enableStrictTransportSecurity: `${common.enable}HSTS(強制用戶端、瀏覽器等使用HTTPS與服務器創建連結),需要HTTPS連接`, diff --git a/src/nginxconfig/i18n/zh-tw/templates/global_sections/https.js b/src/nginxconfig/i18n/zh-tw/templates/global_sections/https.js index 1d36a0b..0e7430d 100644 --- a/src/nginxconfig/i18n/zh-tw/templates/global_sections/https.js +++ b/src/nginxconfig/i18n/zh-tw/templates/global_sections/https.js @@ -1,5 +1,5 @@ /* -Copyright 2020 DigitalOcean +Copyright 2021 DigitalOcean This code is licensed under the MIT License. You may obtain a copy of the License at @@ -33,6 +33,8 @@ const ipv6 = 'IPv6'; export default { sslProfile: `${common.ssl}配寘`, httpsMustBeEnabledOnOneSite: `必須在至少一個網站上啟用${common.https}才能配寘全域${common.https}設定。`, + portReuse: '端口複用', + enableReuseOfPort: `${common.enable} 端口複用來為每個worker生成監聽套接字`, ocspDnsResolvers: 'OCSP DNS解析器', cloudflareResolver: 'Cloudflare解析器', googlePublicDns: '穀歌公共DNS', diff --git a/src/nginxconfig/templates/domain_sections/https.vue b/src/nginxconfig/templates/domain_sections/https.vue index 316ea77..1e13240 100644 --- a/src/nginxconfig/templates/domain_sections/https.vue +++ b/src/nginxconfig/templates/domain_sections/https.vue @@ -96,24 +96,6 @@ THE SOFTWARE. -