nginxconfig.io/src/nginxconfig/generators/conf/nginx.conf.js

156 lines
6.5 KiB
JavaScript

/*
Copyright 2020 DigitalOcean
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import qs from 'qs';
import sslProfiles from '../../util/ssl_profiles';
import exportData from '../../util/export_data';
import websiteConf from './website.conf';
export default (domains, global) => {
const config = {};
// Source
config['# Generated by nginxconfig.io'] = '';
const data = exportData(domains.map((domain, index) => [domain, index]).filter(d => d[0] !== null), global);
const query = qs.stringify(data, { allowDots: true });
config[`# ${window.location.protocol}//${window.location.host}${window.location.pathname}${query.length ? '?' : ''}${query}`] = '';
// Basic nginx conf
config.user = global.nginx.user.computed;
config.pid = global.nginx.pid.computed;
config.worker_processes = global.nginx.workerProcesses.computed;
config.worker_rlimit_nofile = 65535;
config.events = {
multi_accept: 'on',
worker_connections: 65535,
};
// HTTP (kv so we can use the same key multiple times)
config.http = [];
if (global.php.phpBackupServer.computed)
config.http.push(['upstream php', {
server: [
`${global.php.phpServer.computed[0] === '/' ? 'unix:' : ''}${global.php.phpServer.computed}`,
`${global.php.phpBackupServer.computed[0] === '/' ? 'unix:' : ''}${global.php.phpBackupServer.computed} backup`,
],
}]);
config.http.push(['charset', 'utf-8']);
config.http.push(['sendfile', 'on']);
config.http.push(['tcp_nopush', 'on']);
config.http.push(['tcp_nodelay', 'on']);
if (!global.security.serverTokens.computed)
config.http.push(['server_tokens', 'off']);
if (!global.logging.logNotFound.computed)
config.http.push(['log_not_found', 'off']);
config.http.push(['types_hash_max_size', 2048]);
config.http.push(['client_max_body_size', `${global.nginx.clientMaxBodySize.computed}M`]);
config.http.push(['# MIME', '']);
config.http.push(['include', 'mime.types']);
config.http.push(['default_type', 'application/octet-stream']);
config.http.push(['# Logging', '']);
config.http.push(['access_log', global.logging.accessLog.computed.trim() || 'off']);
config.http.push(['error_log', global.logging.errorLog.computed.trim() || '/dev/null']);
if (global.security.limitReq.computed) {
config.http.push(['# Limits', '']);
config.http.push(['limit_req_log_level', 'warn']);
config.http.push(['limit_req_zone', '$binary_remote_addr zone=login:10m rate=10r/m']);
}
// HTTPS
let hasHttps = false;
for (const domain of domains) {
if (domain && domain.https && domain.https.https && domain.https.https.computed) {
hasHttps = true;
break;
}
}
if (hasHttps) {
config.http.push(['# SSL', '']);
config.http.push(['ssl_session_timeout', '1d']);
config.http.push(['ssl_session_cache', 'shared:SSL:10m']);
config.http.push(['ssl_session_tickets', 'off']);
const sslProfile = sslProfiles[global.https.sslProfile.computed];
if (sslProfile) {
if (sslProfile.dh_param_size) {
config.http.push(['# Diffie-Hellman parameter for DHE ciphersuites', '']);
config.http.push(['ssl_dhparam', `${global.nginx.nginxConfigDirectory.computed.replace(/\/+$/, '')}/dhparam.pem`]);
}
config.http.push([`# ${sslProfile.name} configuration`, '']);
config.http.push(['ssl_protocols', sslProfile.protocols.join(' ')]);
if (sslProfile.ciphers.length)
config.http.push(['ssl_ciphers', sslProfile.ciphers.join(':')]);
if (sslProfile.server_preferred_order)
config.http.push(['ssl_prefer_server_ciphers', 'on']);
}
config.http.push(['# OCSP Stapling', '']);
config.http.push(['ssl_stapling', 'on']);
config.http.push(['ssl_stapling_verify', 'on']);
if (global.https.ocspCloudflare.computed
|| global.https.ocspGoogle.computed
|| global.https.ocspOpenDns.computed) {
const ips = [];
if (global.https.ocspCloudflare.computed) {
if (['ipv4', 'both'].includes(global.https.ocspCloudflareType.computed))
ips.push('1.1.1.1', '1.0.0.1');
if (['ipv6', 'both'].includes(global.https.ocspCloudflareType.computed))
ips.push('[2606:4700:4700::1111]', '[2606:4700:4700::1001]');
}
if (global.https.ocspGoogle.computed) {
if (['ipv4', 'both'].includes(global.https.ocspGoogleType.computed))
ips.push('8.8.8.8', '8.8.4.4');
if (['ipv6', 'both'].includes(global.https.ocspGoogleType.computed))
ips.push('[2001:4860:4860::8888]', '[2001:4860:4860::8844]');
}
if (global.https.ocspOpenDns.computed) {
if (['ipv4', 'both'].includes(global.https.ocspOpenDnsType.computed))
ips.push('208.67.222.222', '208.67.220.220');
if (['ipv6', 'both'].includes(global.https.ocspOpenDnsType.computed))
ips.push('[2620:119:35::35]', '[2620:119:53::53]');
}
config.http.push(['resolver', `${ips.join(' ')} valid=60s`]);
config.http.push(['resolver_timeout', '2s']);
}
}
// Configs!
config.http.push(['# Load configs', '']);
config.http.push(['include', [
`${global.nginx.nginxConfigDirectory.computed.replace(/\/+$/, '')}/conf.d/*.conf`,
global.tools.modularizedStructure.computed ? `${global.nginx.nginxConfigDirectory.computed.replace(/\/+$/, '')}/sites-enabled/*` : '',
].filter(x => x.length)]);
// Single file configs
if (!global.tools.modularizedStructure.computed) {
for (const domain of domains) {
config.http.push([`# ${domain.server.domain.computed}`, '']);
config.http.push(...websiteConf(domain, domains, global));
}
}
// Done!
return config;
};