Roll our own js to conf solution & use kv

pull/111/head
MattIPv4 2020-05-08 20:53:00 +01:00
parent e6db3cea7b
commit c5b2459e9d
7 changed files with 115 additions and 89 deletions

29
package-lock.json generated
View File

@ -1117,14 +1117,6 @@
}
}
},
"@webantic/nginx-config-parser": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@webantic/nginx-config-parser/-/nginx-config-parser-1.2.0.tgz",
"integrity": "sha512-f+APSFykPZ06UaRgaxBCxAEUSG+qY9NVcGGqQkKfnJZaHBpqGxlR4FZixkdapnIadbw/uyWQ+96iTAXjyyJ+SQ==",
"requires": {
"glob": "^7.1.3"
}
},
"abab": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz",
@ -1793,14 +1785,6 @@
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
"dev": true
},
"chevrotain": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-7.0.1.tgz",
"integrity": "sha512-B/44jrdw5GAzy483LEeVSgXSX0qOYM8lUd3l5+yf6Vl6OQjEUCm2BUiYbHRCIK6xCEvCLAFe1kj8uyV6+zdaVw==",
"requires": {
"regexp-to-ast": "0.5.0"
}
},
"chokidar": {
"version": "2.1.8",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
@ -5404,14 +5388,6 @@
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
"dev": true
},
"nginx-format": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/nginx-format/-/nginx-format-0.1.7.tgz",
"integrity": "sha512-+6k0BGrASE0vE4X2sYujh0k2cZG+2DT0G82N3O+hS/7/7b3ZNzfHogthRGIJB+2xSJOvgIbJgKRVjqpyerPOtw==",
"requires": {
"chevrotain": "^7.0.1"
}
},
"nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
@ -6673,11 +6649,6 @@
"safe-regex": "^1.1.0"
}
},
"regexp-to-ast": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz",
"integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw=="
},
"regexpp": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",

View File

@ -34,12 +34,10 @@
"homepage": "https://github.com/do-community/nginxconfig-vue#readme",
"dependencies": {
"@babel/runtime": "^7.9.2",
"@webantic/nginx-config-parser": "^1.2.0",
"babel-polyfill": "^6.26.0",
"clone": "^2.1.2",
"do-bulma": "git+https://github.com/do-community/do-bulma.git",
"do-vue": "git+https://github.com/do-community/do-vue.git",
"nginx-format": "^0.1.7",
"parcel-bundler": "^1.12.4",
"pretty-checkbox-vue": "^1.1.9",
"prismjs": "^1.20.0",

View File

@ -1,18 +1,14 @@
import ConfigParser from '@webantic/nginx-config-parser';
const parser = new ConfigParser();
import { nginxFormat } from 'nginx-format';
import toConf from './to_conf';
import nginxConf from './nginx.conf';
const toConf = obj => {
const toConfig = obj => {
// Convert the obj to nginx
const rawConf = nginxFormat(parser.toConf(obj));
const rawConf = toConf(obj);
// Do some magic to comments
const commentConf = rawConf
.replace(/((?:^|\n)(?:[^\S\r\n]*)#.+);($|\n)/g, '$1$2') // Remove semis on comments
.replace(/((?:^|\n)[^\S\r\n]*[^#\s].*[^\n])\n([^\S\r\n]*)#/g, '$1\n$2\n$2#') // Double linebreak before comment
.replace(/((?:^|\n)[^\S\r\n]*#.*\n[^\S\r\n]*#.*\n)([^\S\r\n]*)([^#\s])/g, '$1\n$2$3'); // Double linebreak after double comment
.replace(/^([^\S\r\n]*[^#\s].*[^\n])\n([^\S\r\n]*)#/gm, '$1\n\n$2#') // Double linebreak before comment
.replace(/^([^\S\r\n]*#.*\n[^\S\r\n]*#.*\n)([^\S\r\n]*[^#\s])/gm, '$1\n$2') // Double linebreak after double comment
return commentConf;
}
@ -20,7 +16,7 @@ const toConf = obj => {
export default (domains, global) => {
const files = {};
files['nginx.conf'] = toConf(nginxConf(domains, global));
files['nginx.conf'] = toConfig(nginxConf(domains, global));
return files;
}

View File

@ -5,10 +5,9 @@ export default (domains, global) => {
// Source
config['# Generated by nginxconfig.io'] = '';
if (window.location.search)
config[`# ${window.location.protocol}//${window.location.host}${window.location.pathname}${window.location.search}`] = '';
config[`# ${window.location.protocol}//${window.location.host}${window.location.pathname}${window.location.search}`] = '';
// Basic nignx conf
// Basic nginx conf
config.user = global.nginx.user.computed;
config.pid = global.nginx.pid.computed;
config.worker_processes = global.nginx.workerProcesses.computed;
@ -18,40 +17,40 @@ export default (domains, global) => {
worker_connections: 65535,
};
// HTTP
config.http = {};
// HTTP (kv so we can use the same key multiple times)
config.http = [];
if (global.php.phpBackupServer.computed)
config.http['upstream php'] = {
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.charset = 'utf-8';
config.http.sendfile = 'on';
config.http.tcp_nopush = 'on';
config.http.tcp_nodelay = 'on';
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.server_tokens = 'off';
config.http.push(['server_tokens', 'off']);
if (!global.logging.logNotFound.computed)
config.http.log_not_found = 'off';
config.http.types_hash_max_size = 2048;
config.http.client_max_body_size = `${global.nginx.clientMaxBodySize.computed}M`;
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['# MIME'] = '';
config.http.include = 'mime.types';
config.http.default_type = 'application/octet-stream';
config.http.push(['# MIME', '']);
config.http.push(['include', 'mime.types']);
config.http.push(['default_type', 'application/octet-stream']);
config.http['# logging'] = '';
config.http.access_log = global.logging.accessLog.computed.trim() || 'off';
config.http.error_log = global.logging.errorLog.computed.trim() || '/dev/null';
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['# limits'] = '';
config.http.limit_req_log_level = 'warn';
config.http.limit_req_zone = '$binary_remote_addr zone=login:10m rate=10r/m';
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
@ -63,26 +62,26 @@ export default (domains, global) => {
}
}
if (hasHttps) {
config.http['# SSL'] = '';
config.http.ssl_session_timeout = '1d';
config.http.ssl_session_cache = 'shared:SSL:10m';
config.http.ssl_session_tickets = 'off';
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']);
if (sslProfiles[global.https.sslProfile.computed].dh_param_size) {
config.http['# Diffie-Hellman parameter for DHE ciphersuites'] = '';
config.http.ssl_dhparam = `${global.nginx.nginxConfigDirectory.computed.replace(/\/+$/, '')}/dhparam.pem`;
config.http.push(['# Diffie-Hellman parameter for DHE ciphersuites', '']);
config.http.push(['ssl_dhparam', `${global.nginx.nginxConfigDirectory.computed.replace(/\/+$/, '')}/dhparam.pem`]);
}
config.http[`# ${sslProfiles[global.https.sslProfile.computed].name} configuration`] = '';
config.http.ssl_protocols = sslProfiles[global.https.sslProfile.computed].protocols.join(' ');
config.http.push([`# ${sslProfiles[global.https.sslProfile.computed].name} configuration`, '']);
config.http.push(['ssl_protocols', sslProfiles[global.https.sslProfile.computed].protocols.join(' ')]);
if (sslProfiles[global.https.sslProfile.computed].ciphers.length)
config.http.ssl_ciphers = sslProfiles[global.https.sslProfile.computed].ciphers.join(':');
config.http.push(['ssl_ciphers', sslProfiles[global.https.sslProfile.computed].ciphers.join(':')]);
if (sslProfiles[global.https.sslProfile.computed].server_preferred_order)
config.http.ssl_prefer_server_ciphers = 'on';
config.http.push(['ssl_prefer_server_ciphers', 'on']);
config.http['# OCSP Stapling'] = '';
config.http.ssl_stapling = 'on';
config.http.ssl_stapling_verify = '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
@ -92,17 +91,17 @@ export default (domains, global) => {
if (global.https.ocspGoogle.computed) ips.push('8.8.8.8', '8.8.4.4');
if (global.https.ocspOpenDns.computed) ips.push('208.67.222.222', '208.67.220.220');
config.http.resolver = `${ips.join(' ')} valid=60s`;
config.http.resolver_timeout = '2s';
config.http.push(['resolver', `${ips.join(' ')} valid=60s`]);
config.http.push(['resolver_timeout', '2s']);
}
}
// Configs!
config.http['# load configs'] = '';
config.http.include = [
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);
].filter(x => x.length)]);
// Single file configs
if (!global.tools.modularizedStructure.computed) {

View File

@ -0,0 +1,51 @@
import isObject from '../util/is_object';
const recurse = (entriesOrObject, depth) => {
// Support an object or kv array entries
// Convert to entries if given an object
const entries = isObject(entriesOrObject) ? Object.entries(entriesOrObject) : entriesOrObject;
// If not a valid kv entries array, return
if (!Array.isArray(entries) || !entries.every(i => Array.isArray(i) && i.length === 2)) return '';
// Initial values
let retVal = '';
const longestKeyLen = entries.reduce((prev, current) => {
if (!current[0].startsWith('#') && current[0].length > prev)
return current[0].length;
return prev;
}, 0);
const indent = (' ').repeat(depth);
// Loop over every kv pair
for (const item of entries) {
// If an object, or kv entries, recurse
if (isObject(item[1]) || (Array.isArray(item[1]) && item[1].every(i => Array.isArray(i) && i.length === 2))) {
// Recurse
retVal += '\n' + indent + item[0] + ' {\n';
retVal += recurse(item[1], depth + 1);
retVal += indent + '}\n\n';
// Done
continue;
}
// Otherwise, assume it can be made a string
// Ensure we're working with an array
const val = Array.isArray(item[1]) ? item[1] : [item[1]];
// Calculate spacing
const keyValSpacing = (longestKeyLen - item[0].length) + 4;
const keyValIndent = (' ').repeat(Math.max(keyValSpacing, 0));
// Work through each item in the array
val.forEach(subVal => {
const val = subVal.toString();
retVal += indent + (item[0] + keyValIndent + val).trim() + (item[0].startsWith('#') ? '' : ';') + '\n';
});
}
return retVal.replace(/\n\n\n/g, '\n\n');
}
export default entriesOrObject => recurse(entriesOrObject, 0);

View File

@ -388,10 +388,16 @@ $highlight: #f2c94c;
code {
&[class*="language-"] {
&,
.token {
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-size: 13.6px;
font-weight: normal;
line-height: 1.4em;
}
// Fix Bulma interfering with Prism
// Fix Bulma interfering with Prism
.token {
&.number,
&.tag {
background: transparent;

View File

@ -63,8 +63,10 @@ limitations under the License.
<div :class="`column ${splitColumn ? 'is-half' : 'is-full'} is-full-mobile is-full-tablet`">
<h2>Config files</h2>
<!--<Prism language="nginx" :code="exportData"></Prism>-->
<pre><code>{{exportData}}</code></pre>
<template v-for="(conf, name) in confFiles">
<h3>{{ nginxDir }}/{{ name }}</h3>
<Prism language="nginx" :code="conf"></Prism>
</template>
</div>
</div>
</div>
@ -112,8 +114,11 @@ limitations under the License.
activeDomains() {
return this.$data.domains.map((domain, index) => [domain, index]).filter(d => d[0] !== null);
},
exportData() {
return generators(this.activeDomains, this.$data.global)['nginx.conf'];
nginxDir() {
return this.$data.global.nginx.nginxConfigDirectory.computed.replace(/\/+$/, '');
},
confFiles() {
return generators(this.$data.domains, this.$data.global);
},
},
mounted() {