Merge branch 'master' into hotfix/drupal.conf

pull/111/head
Alexandre Dias 2020-06-03 01:32:31 +01:00 committed by GitHub
commit 5db1fd7162
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 509 additions and 176 deletions

View File

@ -11,4 +11,4 @@ trim_trailing_whitespace = true
[*.yml]
indent_style = space
indent_size = 2
indent_size = 2

View File

@ -111,9 +111,24 @@ export default (domains, global) => {
|| global.https.ocspGoogle.computed
|| global.https.ocspOpenDns.computed) {
const ips = [];
if (global.https.ocspCloudflare.computed) ips.push('1.1.1.1', '1.0.0.1');
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');
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']);

View File

@ -202,7 +202,7 @@ export default (domain, domains, global) => {
serverConfig.push(['# handle .php', '']);
const loc = `location ~ ${domain.routing.legacyPhpRouting.computed ? '[^/]\\.php(/|$)' : '\\.php$'}`;
if (global.tools.modularizedStructure.computed) {
if (global.tools.modularizedStructure.computed || domain.php.wordPressRules.computed) {
// Modularized
serverConfig.push([loc, { include: 'nginxconfig.io/php_fastcgi.conf' }]);
} else {

View File

@ -32,6 +32,9 @@ export default global => {
deny: 'all',
};
config['# WordPress: SEO plugin'] = '';
config['location ~* ^/wp-content/plugins/wordpress-seo(?:-premium)?/css/main-sitemap\\.xsl$'] = {};
config['# WordPress: deny wp-content/plugins (except earlier rules)'] = '';
config['location ~ ^/wp-content/plugins'] = {
deny: 'all',

View File

@ -77,6 +77,10 @@ export default (domains, global) => {
if (domains.some(d => d.php.magentoRules.computed))
files.push(['nginxconfig.io/magento.conf', toConf(magentoConf())]);
} else {
// PHP
if (domains.some(d => d.php.wordPressRules.computed))
files.push(['nginxconfig.io/php_fastcgi.conf', toConf(phpConf(domains, global))]);
}
return files;

View File

@ -107,7 +107,9 @@ export default entriesOrObject => {
// Single linebreak between comment and block
.replace(/^([^\S\r\n]*#.*)(?:\n[^\S\r\n]*)+\n([^\S\r\n]*.*{)/gm, '$1\n$2')
// Double linebreak after double comment
.replace(/^([^\S\r\n]*#.*\n[^\S\r\n]*#.*\n)([^\S\r\n]*[^#\s])/gm, '$1\n$2');
.replace(/^([^\S\r\n]*#.*\n[^\S\r\n]*#.*\n)([^\S\r\n]*[^#\s])/gm, '$1\n$2')
// No newline for empty blocks
.replace(/^([^\S\r\n]*.*{)\n[^\S\r\n]*(})/gm, '$1$2');
// Cleanup extra linebreaks between multiple close blocks
// Use a loop as this has overlapping matches

View File

@ -0,0 +1,33 @@
/*
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.
*/
export default {
back: 'Back',
next: 'Next',
enable: 'enable',
php: 'PHP',
ssl: 'SSL',
nginx: 'NGINX',
http: 'HTTP',
https: 'HTTPS',
letsEncrypt: 'Let\'s Encrypt',
python: 'Python',
wordPress: 'WordPress',
drupal: 'Drupal',
magento: 'Magento',
django: 'Django',
logging: 'Logging',
};

View File

@ -14,8 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import common from './common';
import templates from './templates';
// TODO: centralised shared strings
export default { templates };
export default { common, templates };

View File

@ -14,8 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import common from '../common';
export default {
title: 'NGINXConfig',
description: 'The easiest way to configure a performant, secure, and stable NGINX server.',
oss: 'This tool is {link|open-source on GitHub|https://github.com/do-community/nginxconfig-vue} under the {link|Apache-2.0|https://github.com/do-community/nginxconfig-vue/blob/master/LICENSE} license! We welcome feedback and contributions.',
title: `${common.nginx}Config`,
description: `The easiest way to configure a performant, secure, and stable ${common.nginx} server.`,
singleColumnMode: 'Single column mode',
splitColumnMode: 'Split column mode',
perWebsiteConfig: 'Per-website config',
addSite: 'Add site',
globalConfig: 'Global config',
setup: 'Setup',
configFiles: 'Config files',
oss: 'This tool is {link|open-source on GitHub|https://github.com/digitalocean/nginxconfig.io} under the {link|Apache-2.0|https://github.com/digitalocean/nginxconfig.io/blob/master/LICENSE} license! We welcome feedback and contributions.',
};

View File

@ -14,16 +14,16 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import common from '../../common';
export default {
https: 'HTTPS',
enableEncryptedSslConnection: 'enable encrypted SSL connections',
http2: 'HTTP/2',
enableHttp2Connections: 'enable HTTP/2 connections',
forceHttps: 'Force HTTPS',
enableEncryptedSslConnection: `${common.enable} encrypted ${common.ssl} connections`,
http2: `${common.http}/2`,
enableHttp2Connections: `${common.enable} ${common.http}/2 connections`,
forceHttps: `Force ${common.https}`,
hsts: 'HSTS',
enableStrictTransportSecurity: 'enable Strict Transport Security',
enableStrictTransportSecurity: `${common.enable} Strict Transport Security`,
certificationType: 'Certification type',
letsEncrypt: 'Let\'s Encrypt',
customCertificate: 'Custom certificate',
letsEncryptEmail: 'Let\'s Encrypt email',
letsEncryptEmail: `${common.letsEncrypt} email`,
};

View File

@ -14,8 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import common from '../../common';
export default {
byDomain: 'by domain',
enableForThisDomain: 'enable for this domain',
logging: 'Logging',
enableForThisDomain: `${common.enable} for this domain`,
};

View File

@ -14,16 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import common from '../../common';
export default {
php: 'PHP',
phpIsDisabled: 'PHP is disabled.',
phpCannotBeEnabledWithReverseProxy: 'PHP cannot be enabled whilst the reverse proxy is enabled.',
phpCannotBeEnabledWithPython: 'PHP cannot be enabled whilst Python is enabled.',
enablePhp: 'enable PHP',
wordPressRules: 'WordPress rules',
enableWordPressRules: 'enable WordPress-specific rules',
drupalRules: 'Drupal rules',
enableDrupalRules: 'enable Drupal-specific rules',
magentoRules: 'Magento rules',
enableMagentoRules: 'enable Magento-specific rules',
phpIsDisabled: `${common.php} is disabled.`,
phpCannotBeEnabledWithReverseProxy: `${common.php} cannot be enabled whilst the reverse proxy is enabled.`,
phpCannotBeEnabledWithPython: `${common.php} cannot be enabled whilst ${common.python} is enabled.`,
enablePhp: `${common.enable} ${common.php}`,
wordPressRules: `${common.wordPress} rules`,
enableWordPressRules: `${common.enable} ${common.wordPress}-specific rules`,
drupalRules: `${common.drupal} rules`,
enableDrupalRules: `${common.enable} ${common.drupal}-specific rules`,
magentoRules: `${common.magento} rules`,
enableMagentoRules: `${common.enable} ${common.magento}-specific rules`,
};

View File

@ -18,11 +18,6 @@ export default {
presets: 'Presets',
itLooksLikeYouCustomisedTheConfig: 'It looks like you\'ve customised the configuration for this domain. Choosing a new preset may reset or change some of the settings that you\'ve customised.',
frontend: 'Frontend',
php: 'PHP',
django: 'Django',
nodeJs: 'Node.js',
singlePageApplication: 'Single-page application',
wordPress: 'WordPress',
drupal: 'Drupal',
magento: 'Magento',
};

View File

@ -14,12 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import common from '../../common';
export default {
python: 'Python',
pythonIsDisabled: 'Python is disabled.',
pythonCannotBeEnabledWithReverseProxy: 'Python cannot be enabled whilst the reverse proxy is enabled.',
pythonCannotBeEnabledWithPhp: 'Python cannot be enabled whilst PHP is enabled.',
enablePython: 'enable Python',
djangoRules: 'Django rules',
enableDjangoRules: 'enable Django-specific rules',
pythonIsDisabled: `${common.python} is disabled.`,
pythonCannotBeEnabledWithReverseProxy: `${common.python} cannot be enabled whilst the reverse proxy is enabled.`,
pythonCannotBeEnabledWithPhp: `${common.python} cannot be enabled whilst ${common.php} is enabled.`,
enablePython: `${common.enable} ${common.python}`,
djangoRules: `${common.django} rules`,
enableDjangoRules: `${common.enable} ${common.django}-specific rules`,
};

View File

@ -14,11 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import common from '../../common';
export default {
reverseProxy: 'Reverse proxy',
reverseProxyIsDisabled: 'Reverse proxy is disabled.',
reverseProxyCannotBeEnabledWithPhp: 'Reverse proxy cannot be enabled whilst PHP is enabled.',
reverseProxyCannotBeEnabledWithPython: 'Reverse proxy cannot be enabled whilst Python is enabled.',
enableReverseProxy: 'enable reverse proxy',
reverseProxyCannotBeEnabledWithPhp: `Reverse proxy cannot be enabled whilst ${common.php} is enabled.`,
reverseProxyCannotBeEnabledWithPython: `Reverse proxy cannot be enabled whilst ${common.python} is enabled.`,
enableReverseProxy: `${common.enable} reverse proxy`,
path: 'Path',
};

View File

@ -14,12 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import common from '../../common';
export default {
enable: 'enable',
fallbackRouting: 'Fallback routing',
fallbackRoutingPhpPath: 'Fallback routing PHP path',
legacyPhpRouting: 'Legacy PHP routing',
enableLegacyRouting: 'enable legacy routing',
fallbackRoutingPhpPath: `Fallback routing ${common.php} path`,
legacyPhpRouting: `Legacy ${common.php} routing`,
enableLegacyRouting: `${common.enable} legacy routing`,
path: 'Path',
routing: 'Routing',
};

View File

@ -14,16 +14,24 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import common from '../../common';
const mozilla = 'Mozilla';
const ipv4 = 'IPv4';
const ipv6 = 'IPv6';
export default {
sslProfile: 'SSL Profile',
httpsMustBeEnabledOnOneSite: 'HTTPS must be enabled on at least one site to configure global HTTPS settings.',
sslProfile: `${common.ssl} Profile`,
httpsMustBeEnabledOnOneSite: `${common.https} must be enabled on at least one site to configure global ${common.https} settings.`,
ocspDnsResolvers: 'OCSP DNS Resolvers',
cloudflareResolver: 'Cloudflare Resolver',
googlePublicDns: 'Google Public DNS',
openDns: 'OpenDNS',
letsEncryptWebroot: 'Let\'s Encrypt webroot',
mozillaModern: 'Mozilla Modern',
mozillaIntermediate: 'Mozilla Intermediate',
mozillaOld: 'Mozilla Old',
https: 'HTTPS',
letsEncryptWebroot: `${common.letsEncrypt} webroot`,
mozillaModern: `${mozilla} Modern`,
mozillaIntermediate: `${mozilla} Intermediate`,
mozillaOld: `${mozilla} Old`,
ipv4Only: `${ipv4} only`,
ipv6Only: `${ipv6} only`,
ipv4AndIpv6: `${ipv4} & ${ipv6}`,
};

View File

@ -14,7 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import common from '../../common';
export default {
enableFileNotFoundErrorLogging: 'enable file not found error logging in',
logging: 'Logging',
enableFileNotFoundErrorLogging: `${common.enable} file not found error logging in`,
};

View File

@ -14,8 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import common from '../../common';
export default {
nginxConfigDirectory: 'NGINX config directory',
nginxConfigDirectory: `${common.nginx} config directory`,
mb: 'MB',
nginx: 'NGINX',
};

View File

@ -14,11 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import common from '../../common';
export default {
gzipCompression: 'Gzip compression',
enableGzipCompression: 'enable gzip compression',
enableGzipCompression: `${common.enable} gzip compression`,
brotliCompression: 'Brotli compression',
enableBrotliCompression: 'enable brotli compression',
enableBrotliCompression: `${common.enable} brotli compression`,
expirationForAssets: 'Expiration for assets',
expirationForMedia: 'Expiration for media',
expirationForSvgs: 'Expiration for SVGs',

View File

@ -14,10 +14,12 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import common from '../../common';
export default {
phpServer: 'PHP server',
phpMustBeEnabledOnOneSite: 'PHP must be enabled on at least one site to configure global PHP settings.',
phpBackupServer: 'PHP backup server',
phpServer: `${common.php} server`,
phpMustBeEnabledOnOneSite: `${common.php} must be enabled on at least one site to configure global ${common.php} settings.`,
phpBackupServer: `${common.php} backup server`,
tcp: 'TCP',
hhvmSocket: 'HHVM socket',
php5Socket: '5.x socket',
@ -26,5 +28,4 @@ export default {
php72Socket: '7.2 socket',
php73Socket: '7.3 socket',
disabled: 'Disabled',
php: 'PHP',
};

View File

@ -14,8 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import common from '../../common';
export default {
pythonServer: 'Python server',
pythonMustBeEnabledOnOneSite: 'Python must be enabled on at least one site to configure global Python settings.',
python: 'Python',
pythonServer: `${common.python} server`,
pythonMustBeEnabledOnOneSite: `${common.python} must be enabled on at least one site to configure global ${common.python} settings.`,
};

View File

@ -14,7 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import common from '../../common';
export default {
enable: 'enable',
whenUsingWordPressUnsafeEvalIsOftenRequiredToAllowFunctionality: `When using ${common.wordPress}, <code class="slim">'unsafe-eval'</code> is often required in the Content Security Policy to allow the admin panel to function correctly.`,
security: 'Security',
};

View File

@ -14,11 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import common from '../../common';
export default {
modularizedStructure: 'Modularized structure',
enableModularizedConfigFiles: 'enable modularized config files',
enableModularizedConfigFiles: `${common.enable} modularized config files`,
symlinkVhost: 'Symlink vhost',
enableSymLinksFrom: 'enable symlinks from',
enableSymLinksFrom: `${common.enable} symlinks from`,
to: 'to',
shareConfiguration: 'Share configuration',
resetConfiguration: 'Reset configuration',

View File

@ -15,7 +15,9 @@ limitations under the License.
*/
import app from './app';
import setup from './setup';
import domainSections from './domain_sections';
import globalSections from './global_sections';
import setupSections from './setup_sections';
export default { app, domainSections, globalSections };
export default { app, setup, domainSections, globalSections, setupSections };

View File

@ -0,0 +1,20 @@
/*
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.
*/
export default {
downloadConfig: 'Download Config',
copyBase64: 'Copy Base64',
};

View File

@ -0,0 +1,29 @@
/*
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 common from '../../common';
const certbot = 'Certbot';
export default {
commentOutSslDirectivesInConfiguration: `Comment out ${common.ssl} related directives in the configuration:`,
reloadYourNginxServer: `Reload your ${common.nginx} server:`,
obtainSslCertificatesFromLetsEncrypt: `Obtain ${common.ssl} certificates from ${common.letsEncrypt} using ${certbot}:`,
uncommentSslDirectivesInConfiguration: `Uncomment ${common.ssl} related directives in the configuration:`,
configureCertbotToReloadNginxOnCertificateRenewal: `Configure ${certbot} to reload ${common.nginx} when it successfully renews certificates:`,
certbotDoesNotNeedToBeSetupForYourConfiguration: `${certbot} does not need to be set up for your ${common.nginx} configuration.`,
certbot,
};

View File

@ -0,0 +1,30 @@
/*
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 common from '../../common';
export default {
downloadTheGeneratedConfig: '<b>Download</b> the generated config:',
andUploadItToYourServers: 'and <b>upload</b> it to your server\'s',
directory: 'directory.',
or: 'or, ',
copyBase64StringOfCompressedConfig: 'Copy a base64 string of the compressed config',
pasteItInYourServersCommandLineAndExecute: ', paste it in your server\'s command line and execute it.',
navigateToYourNginxConfigurationDirectoryOnYourServer: `Navigate to your ${common.nginx} <b>configuration directory</b> on your server:`,
createABackupOfYourCurrentNginxConfiguration: `Create a <b>backup</b> of your current ${common.nginx} configuration:`,
extractTheNewCompressedConfigurationArchiveUsingTar: '<b>Extract</b> the new compressed configuration archive using tar:',
download: 'Download',
};

View File

@ -0,0 +1,23 @@
/*
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 common from '../../common';
export default {
letsGoLive: 'Let\'s go live!',
reloadNginxToLoadInYourNewConfiguration: `Reload ${common.nginx} to load in your new configuration:`,
goLive: 'Go live!',
};

View File

@ -0,0 +1,22 @@
/*
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 certbot from './certbot';
import download from './download';
import goLive from './go_live';
import ssl from './ssl';
export default { certbot, download, goLive, ssl };

View File

@ -0,0 +1,24 @@
/*
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 common from '../../common';
export default {
generateDiffieHellmanKeysByRunningThisCommandOnYourServer: 'Generate <b>Diffie-Hellman keys</b> by running this command on your server:',
createACommonAcmeChallengeDirectoryForLetsEncrypt: `Create a common <b>ACME-challenge</b> directory (for <b>${common.letsEncrypt}</b>):`,
noAdditionalStepsAreNeededToSetUpSslForNginx: `No additional steps are needed to set up ${common.ssl} for your ${common.nginx} configuration.`,
sslInit: `${common.ssl} init`,
};

View File

@ -39,6 +39,10 @@ limitations under the License.
&.is-aligned-top {
align-items: flex-start;
}
+ .control {
margin-top: .5rem;
}
}
&.is-grouped {

View File

@ -24,10 +24,10 @@ limitations under the License.
</template>
<template v-slot:buttons>
<a v-if="splitColumn" class="button is-primary is-outline" @click="splitColumn = false">
Single column mode
{{ i18n.templates.app.singleColumnMode }}
</a>
<a v-else class="button is-primary" @click="splitColumn = true">
Split column mode
{{ i18n.templates.app.splitColumnMode }}
</a>
</template>
</Header>
@ -35,7 +35,7 @@ limitations under the License.
<div class="main container" :style="{ display: ready ? undefined : 'none' }">
<div class="columns is-multiline">
<div :class="`column ${splitColumn ? 'is-half' : 'is-full'} is-full-mobile is-full-tablet`">
<h2>Per-website config</h2>
<h2>{{ i18n.templates.app.perWebsiteConfig }}</h2>
<div class="tabs">
<ul>
@ -48,7 +48,7 @@ limitations under the License.
</a>
</li>
<li>
<a @click="add"><i class="fas fa-plus"></i> Add site</a>
<a @click="add"><i class="fas fa-plus"></i> {{ i18n.templates.app.addSite }}</a>
</li>
</ul>
</div>
@ -60,15 +60,15 @@ limitations under the License.
></Domain>
</template>
<h2>Global config</h2>
<h2>{{ i18n.templates.app.globalConfig }}</h2>
<Global :data="global"></Global>
<h2>Setup</h2>
<h2>{{ i18n.templates.app.setup }}</h2>
<Setup :data="{ domains: domains.filter(d => d !== null), global, confFiles }"></Setup>
</div>
<div :class="`column ${splitColumn ? 'is-half' : 'is-full'} is-full-mobile is-full-tablet`">
<h2>Config files</h2>
<h2>{{ i18n.templates.app.configFiles }}</h2>
<div ref="files" class="columns is-multiline">
<NginxPrism v-for="conf in confFilesOutput"
:key="`${conf[0]}-${hash(conf[1])}`"

View File

@ -39,10 +39,10 @@ limitations under the License.
<div class="navigation-buttons">
<a v-if="previousTab !== false" class="button is-mini" @click="active = previousTab">
<i class="fas fa-long-arrow-alt-left"></i> <span>Back</span>
<i class="fas fa-long-arrow-alt-left"></i> <span>{{ i18n.common.back }}</span>
</a>
<a v-if="nextTab !== false" class="button is-primary is-mini" @click="active = nextTab">
<span>Next</span> <i class="fas fa-long-arrow-alt-right"></i>
<span>{{ i18n.common.next }}</span> <i class="fas fa-long-arrow-alt-right"></i>
</a>
</div>
</div>
@ -50,6 +50,7 @@ limitations under the License.
</template>
<script>
import i18n from '../i18n';
import isChanged from '../util/is_changed';
import Presets from './domain_sections/presets';
import * as Sections from './domain_sections';
@ -75,6 +76,7 @@ limitations under the License.
},
data() {
return {
i18n,
active: tabs[0].key,
tabs,
};

View File

@ -18,7 +18,7 @@ limitations under the License.
<div>
<div class="field is-horizontal">
<div class="field-label">
<label class="label">{{ i18n.templates.domainSections.https.https }}</label>
<label class="label">{{ i18n.common.https }}</label>
</div>
<div class="field-body">
<div class="field">
@ -216,7 +216,7 @@ limitations under the License.
certType: {
default: 'letsEncrypt',
options: {
letsEncrypt: i18n.templates.domainSections.https.letsEncrypt,
letsEncrypt: i18n.common.letsEncrypt,
custom: i18n.templates.domainSections.https.customCertificate,
},
enabled: true,
@ -236,16 +236,16 @@ limitations under the License.
};
export default {
name: 'DomainHTTPS', // Component name
display: i18n.templates.domainSections.https.https, // Display name for tab
key: 'https', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'DomainHTTPS', // Component name
display: i18n.common.https, // Display name for tab
key: 'https', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
PrettyRadio,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
data () {
return {
@ -253,7 +253,7 @@ limitations under the License.
};
},
computed: {
...computedFromDefaults(defaults, 'https'), // Getters & setters for the delegated data
...computedFromDefaults(defaults, 'https'), // Getters & setters for the delegated data
nginxDir() {
return this.$parent.$parent.$data.global.nginx.nginxConfigDirectory.computed.replace(/\/+$/, '');
},

View File

@ -72,15 +72,15 @@ limitations under the License.
};
export default {
name: 'DomainLogging', // Component name
display: i18n.templates.domainSections.logging.logging, // Display name for tab
key: 'logging', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'DomainLogging', // Component name
display: i18n.common.logging, // Display name for tab
key: 'logging', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
data () {
return {

View File

@ -18,7 +18,7 @@ limitations under the License.
<div>
<div v-if="!phpEnabled" class="field is-horizontal is-aligned-top">
<div class="field-label">
<label class="label">{{ i18n.templates.domainSections.php.php }}</label>
<label class="label">{{ i18n.common.php }}</label>
</div>
<div class="field-body">
<div class="field">
@ -39,7 +39,7 @@ limitations under the License.
<div v-else class="field is-horizontal">
<div class="field-label">
<label class="label">PHP</label>
<label class="label">{{ i18n.common.php }}</label>
</div>
<div class="field-body">
<div class="field">
@ -138,7 +138,7 @@ limitations under the License.
export default {
name: 'DomainPHP', // Component name
display: i18n.templates.domainSections.php.php, // Display name for tab
display: i18n.common.php, // Display name for tab
key: 'php', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
@ -152,7 +152,7 @@ limitations under the License.
i18n,
};
},
computed: computedFromDefaults(defaults, 'php'), // Getters & setters for the delegated data
computed: computedFromDefaults(defaults, 'php'), // Getters & setters for the delegated data
watch: {
// If the Reverse proxy or Python is enabled, PHP will be forced off
'$parent.$props.data': {

View File

@ -67,7 +67,7 @@ limitations under the License.
},
php: {
default: true,
display: i18n.templates.domainSections.presets.php,
display: i18n.common.php,
enabled: true,
computedCheck (data) {
return data.php.php.computed
@ -81,7 +81,7 @@ limitations under the License.
},
django: {
default: false,
display: i18n.templates.domainSections.presets.django,
display: i18n.common.django,
enabled: true,
computedCheck (data) {
return data.python.python.computed
@ -110,7 +110,7 @@ limitations under the License.
},
wordPress: {
default: false,
display: i18n.templates.domainSections.presets.wordPress,
display: i18n.common.wordPress,
enabled: true,
computedCheck (data) {
return data.routing.index.computed === 'index.php'
@ -123,7 +123,7 @@ limitations under the License.
},
drupal: {
default: false,
display: i18n.templates.domainSections.presets.drupal,
display: i18n.common.drupal,
enabled: true,
computedCheck (data) {
return data.routing.index.computed === 'index.php'
@ -136,7 +136,7 @@ limitations under the License.
},
magento: {
default: false,
display: i18n.templates.domainSections.presets.magento,
display: i18n.common.magento,
enabled: true,
computedCheck (data) {
return data.routing.index.computed === 'index.php'

View File

@ -18,7 +18,7 @@ limitations under the License.
<div>
<div v-if="!pythonEnabled" class="field is-horizontal is-aligned-top">
<div class="field-label">
<label class="label">{{ i18n.templates.domainSections.python.python }}</label>
<label class="label">{{ i18n.common.python }}</label>
</div>
<div class="field-body">
<div class="field">
@ -39,7 +39,7 @@ limitations under the License.
<div v-else class="field is-horizontal">
<div class="field-label">
<label class="label">{{ i18n.templates.domainSections.python.python }}</label>
<label class="label">{{ i18n.common.python }}</label>
</div>
<div class="field-body">
<div class="field">
@ -93,15 +93,15 @@ limitations under the License.
};
export default {
name: 'DomainPython', // Component name
display: i18n.templates.domainSections.python.python, // Display name for tab
key: 'python', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'DomainPython', // Component name
display: i18n.common.python, // Display name for tab
key: 'python', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
data () {
return {

View File

@ -26,7 +26,7 @@ limitations under the License.
<div class="checkbox">
<PrettyCheck v-model="root" class="p-default p-curve p-fill p-icon">
<i slot="extra" class="icon fas fa-check"></i>
{{ i18n.templates.domainSections.routing.enable }}
{{ i18n.common.enable }}
</PrettyCheck>
</div>
</div>

View File

@ -34,16 +34,17 @@ limitations under the License.
<div class="navigation-buttons">
<a v-if="previousTab !== false" class="button is-mini" @click="active = previousTab">
<i class="fas fa-long-arrow-alt-left"></i> <span>Back</span>
<i class="fas fa-long-arrow-alt-left"></i> <span>{{ i18n.common.back }}</span>
</a>
<a v-if="nextTab !== false" class="button is-primary is-mini" @click="active = nextTab">
<span>Next</span> <i class="fas fa-long-arrow-alt-right"></i>
<span>{{ i18n.common.next }}</span> <i class="fas fa-long-arrow-alt-right"></i>
</a>
</div>
</div>
</template>
<script>
import i18n from '../i18n';
import isChanged from '../util/is_changed';
import * as Sections from './global_sections';
@ -61,6 +62,7 @@ limitations under the License.
},
data() {
return {
i18n,
active: tabs[0].key,
tabs,
};

View File

@ -68,6 +68,19 @@ limitations under the License.
</PrettyCheck>
</div>
</div>
<div v-if="$props.data.ocspCloudflare.computed" class="control field is-horizontal is-expanded">
<div v-for="(name, value) in $props.data.ocspCloudflareType.options"
:class="`control${ocspCloudflareTypeChanged && value === ocspCloudflareType ? ' is-changed' : ''}`"
>
<div class="radio">
<PrettyRadio v-model="ocspCloudflareType" :value="value" class="p-default p-round p-fill p-icon">
<i slot="extra" class="icon fas fa-check"></i>
{{ name }}
</PrettyRadio>
</div>
</div>
</div>
<div :class="`control${ocspGoogleChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="ocspGoogle" class="p-default p-curve p-fill p-icon">
@ -76,6 +89,19 @@ limitations under the License.
</PrettyCheck>
</div>
</div>
<div v-if="$props.data.ocspGoogle.computed" class="control field is-horizontal is-expanded">
<div v-for="(name, value) in $props.data.ocspGoogleType.options"
:class="`control${ocspGoogleTypeChanged && value === ocspGoogleType ? ' is-changed' : ''}`"
>
<div class="radio">
<PrettyRadio v-model="ocspGoogleType" :value="value" class="p-default p-round p-fill p-icon">
<i slot="extra" class="icon fas fa-check"></i>
{{ name }}
</PrettyRadio>
</div>
</div>
</div>
<div :class="`control${ocspOpenDnsChanged ? ' is-changed' : ''}`">
<div class="checkbox">
<PrettyCheck v-model="ocspOpenDns" class="p-default p-curve p-fill p-icon">
@ -84,6 +110,18 @@ limitations under the License.
</PrettyCheck>
</div>
</div>
<div v-if="$props.data.ocspOpenDns.computed" class="control field is-horizontal is-expanded">
<div v-for="(name, value) in $props.data.ocspOpenDnsType.options"
:class="`control${ocspOpenDnsTypeChanged && value === ocspOpenDnsType ? ' is-changed' : ''}`"
>
<div class="radio">
<PrettyRadio v-model="ocspOpenDnsType" :value="value" class="p-default p-round p-fill p-icon">
<i slot="extra" class="icon fas fa-check"></i>
{{ name }}
</PrettyRadio>
</div>
</div>
</div>
</div>
</div>
</div>
@ -111,10 +149,27 @@ limitations under the License.
<script>
import PrettyCheck from 'pretty-checkbox-vue/check';
import PrettyRadio from 'pretty-checkbox-vue/radio';
import clone from 'clone';
import i18n from '../../i18n';
import delegatedFromDefaults from '../../util/delegated_from_defaults';
import computedFromDefaults from '../../util/computed_from_defaults';
const ipType = {
default: 'ipv4',
options: {
ipv4: i18n.templates.globalSections.https.ipv4Only,
ipv6: i18n.templates.globalSections.https.ipv6Only,
both: i18n.templates.globalSections.https.ipv4AndIpv6,
},
enabled: true,
};
const validOptionCheck = data => {
if (data.enabled)
if (!Object.keys(data.options).includes(data.computed))
data.computed = data.default;
};
const defaults = {
sslProfile: {
default: 'intermediate',
@ -129,14 +184,17 @@ limitations under the License.
default: true,
enabled: true,
},
ocspCloudflareType: clone(ipType),
ocspGoogle: {
default: true,
enabled: true,
},
ocspGoogleType: clone(ipType),
ocspOpenDns: {
default: true,
enabled: true,
},
ocspOpenDnsType: clone(ipType),
letsEncryptRoot: {
default: '/var/www/_letsencrypt/',
enabled: true,
@ -144,32 +202,40 @@ limitations under the License.
};
export default {
name: 'GlobalHTTPS', // Component name
display: i18n.templates.globalSections.https.https, // Display name for tab
key: 'https', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'GlobalHTTPS', // Component name
display: i18n.common.https, // Display name for tab
key: 'https', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
PrettyCheck,
PrettyRadio,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
data () {
return {
i18n,
};
},
computed: computedFromDefaults(defaults, 'https'), // Getters & setters for the delegated data
computed: computedFromDefaults(defaults, 'https'), // Getters & setters for the delegated data
watch: {
// Check SSL profile is valid
'$props.data.sslProfile': {
handler(data) {
// This might cause recursion, but seems not to
if (data.enabled)
if (!Object.keys(data.options).includes(data.computed))
data.computed = data.default;
},
handler: validOptionCheck,
deep: true,
},
// Check IP type is valid
'$props.data.ocspCloudflareType': {
handler: validOptionCheck,
deep: true,
},
'$props.data.ocspGoogleType': {
handler: validOptionCheck,
deep: true,
},
'$props.data.ocspOpenDnsType': {
handler: validOptionCheck,
deep: true,
},
'$parent.$parent.$data.domains': {

View File

@ -93,7 +93,7 @@ limitations under the License.
export default {
name: 'GlobalLogging', // Component name
display: i18n.templates.globalSections.logging.logging, // Display name for tab
display: i18n.common.logging, // Display name for tab
key: 'logging', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {

View File

@ -144,7 +144,7 @@ limitations under the License.
export default {
name: 'GlobalNGINX', // Component name
display: i18n.templates.globalSections.nginx.nginx, // Display name for tab
display: i18n.common.nginx, // Display name for tab
key: 'nginx', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {

View File

@ -100,15 +100,15 @@ limitations under the License.
};
export default {
name: 'GlobalPHP', // Component name
display: i18n.templates.globalSections.php.php, // Display name for tab
key: 'php', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'GlobalPHP', // Component name
display: i18n.common.php, // Display name for tab
key: 'php', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
components: {
VueSelect,
},
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
data () {
return {
@ -116,7 +116,7 @@ limitations under the License.
};
},
computed: {
...computedFromDefaults(defaults, 'php'), // Getters & setters for the delegated data
...computedFromDefaults(defaults, 'php'), // Getters & setters for the delegated data
phpServerOptions() {
return Object.entries(this.$props.data.phpServer.options)
.map(([key, value]) => ({ label: value, value: key }));

View File

@ -63,19 +63,19 @@ limitations under the License.
};
export default {
name: 'GlobalPython', // Component name
display: i18n.templates.globalSections.python.python, // Display name for tab
key: 'python', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
name: 'GlobalPython', // Component name
display: i18n.common.python, // Display name for tab
key: 'python', // Key for data in parent
delegated: delegatedFromDefaults(defaults), // Data the parent will present here
props: {
data: Object, // Data delegated back to us from parent
data: Object, // Data delegated back to us from parent
},
data () {
return {
i18n,
};
},
computed: computedFromDefaults(defaults, 'python'), // Getters & setters for the delegated data
computed: computedFromDefaults(defaults, 'python'), // Getters & setters for the delegated data
watch: {
// Enable Python server settings if any site uses Python
'$parent.$parent.$data.domains': {

View File

@ -32,7 +32,7 @@ limitations under the License.
</div>
</div>
<div class="field is-horizontal">
<div :class="`field is-horizontal${hasWordPress && !hasUnsafeEval ? ' is-aligned-top' : ''}`">
<div class="field-label">
<label class="label">Content-Security-Policy</label>
</div>
@ -45,6 +45,14 @@ limitations under the License.
:placeholder="$props.data.contentSecurityPolicy.default"
/>
</div>
<template v-if="hasWordPress && !hasUnsafeEval">
<br />
<div class="message is-warning">
<div class="message-body"
v-html="i18n.templates.globalSections.security.whenUsingWordPressUnsafeEvalIsOftenRequiredToAllowFunctionality"
></div>
</div>
</template>
</div>
</div>
</div>
@ -59,7 +67,7 @@ limitations under the License.
<div class="checkbox">
<PrettyCheck v-model="serverTokens" class="p-default p-curve p-fill p-icon">
<i slot="extra" class="icon fas fa-check"></i>
{{ i18n.templates.globalSections.security.enable }}
{{ i18n.common.enable }}
</PrettyCheck>
</div>
</div>
@ -77,7 +85,7 @@ limitations under the License.
<div class="checkbox">
<PrettyCheck v-model="limitReq" class="p-default p-curve p-fill p-icon">
<i slot="extra" class="icon fas fa-check"></i>
{{ i18n.templates.globalSections.security.enable }}
{{ i18n.common.enable }}
</PrettyCheck>
</div>
</div>
@ -140,7 +148,15 @@ limitations under the License.
i18n,
};
},
computed: computedFromDefaults(defaults, 'security'), // Getters & setters for the delegated data
computed: {
...computedFromDefaults(defaults, 'security'), // Getters & setters for the delegated data
hasWordPress() {
return this.$parent.$parent.$data.domains.some(d => d.php.wordPressRules.computed);
},
hasUnsafeEval() {
return this.$props.data.contentSecurityPolicy.computed.includes('\'unsafe-eval\'');
},
},
watch: {
// Check referrer policy selection is valid
'$props.data.referrerPolicy': {

View File

@ -35,17 +35,17 @@ limitations under the License.
<div class="navigation-buttons">
<a v-if="previousTab !== false" class="button is-mini" @click="active = previousTab">
<i class="fas fa-long-arrow-alt-left"></i> <span>Back</span>
<i class="fas fa-long-arrow-alt-left"></i> <span>{{ i18n.common.back }}</span>
</a>
<a v-if="nextTab !== false" class="button is-primary is-mini" @click="active = nextTab">
<span>Next</span> <i class="fas fa-long-arrow-alt-right"></i>
<span>{{ i18n.common.next }}</span> <i class="fas fa-long-arrow-alt-right"></i>
</a>
</div>
</div>
<div class="buttons is-centered">
<a class="button is-success" @click="downloadTar">Download Config</a>
<a class="button is-primary" @click="copyTar">Copy Base64</a>
<a class="button is-success" @click="downloadTar">{{ i18n.templates.setup.downloadConfig }}</a>
<a class="button is-primary" @click="copyTar">{{ i18n.templates.setup.copyBase64 }}</a>
</div>
</div>
</template>
@ -55,6 +55,7 @@ limitations under the License.
import getStream from 'get-stream';
import { gzip } from 'node-gzip';
import copy from 'copy-to-clipboard';
import i18n from '../i18n';
import * as Sections from './setup_sections';
const tabs = Object.values(Sections);
@ -66,6 +67,7 @@ limitations under the License.
},
data() {
return {
i18n,
active: tabs[0].key,
tabs,
};

View File

@ -19,7 +19,7 @@ limitations under the License.
<ol v-if="letsEncryptActive">
<li>
<p>
Comment out SSL related directives in the configuration:
{{ i18n.templates.setupSections.certbot.commentOutSslDirectivesInConfiguration }}
<br />
</p>
<BashPrism :key="sitesAvailable"
@ -29,7 +29,7 @@ limitations under the License.
<li>
<p>
Reload your NGINX server:
{{ i18n.templates.setupSections.certbot.reloadYourNginxServer }}
<br />
</p>
<BashPrism cmd="sudo nginx -t && sudo systemctl reload nginx"></BashPrism>
@ -37,7 +37,7 @@ limitations under the License.
<li>
<p>
Obtain SSL certificates from Let's Encrypt using Certbot:
{{ i18n.templates.setupSections.certbot.obtainSslCertificatesFromLetsEncrypt }}
<br />
</p>
<BashPrism :key="certbotCmds" :cmd="certbotCmds"></BashPrism>
@ -45,7 +45,7 @@ limitations under the License.
<li>
<p>
Uncomment SSL related directives in the configuration:
{{ i18n.templates.setupSections.certbot.uncommentSslDirectivesInConfiguration }}
<br />
</p>
<BashPrism :key="sitesAvailable" :cmd="`sed -i -r 's/#?;#//g' ${sitesAvailable}`"></BashPrism>
@ -53,7 +53,7 @@ limitations under the License.
<li>
<p>
Reload your NGINX server:
{{ i18n.templates.setupSections.certbot.reloadYourNginxServer }}
<br />
</p>
<BashPrism cmd="sudo nginx -t && sudo systemctl reload nginx"></BashPrism>
@ -61,7 +61,7 @@ limitations under the License.
<li>
<p>
Configure Certbot to reload NGINX when it successfully renews certificates:
{{ i18n.templates.setupSections.certbot.configureCertbotToReloadNginxOnCertificateRenewal }}
<br />
</p>
<BashPrism cmd="echo -e '#!/bin/bash\nnginx -t && systemctl reload nginx' | sudo tee /etc/letsencrypt/renewal-hooks/post/nginx-reload.sh"></BashPrism>
@ -74,7 +74,7 @@ limitations under the License.
<div class="field">
<div class="control">
<label class="text">
Certbot does not need to be set up for your NGINX configuration.
{{ i18n.templates.setupSections.certbot.certbotDoesNotNeedToBeSetupForYourConfiguration }}
</label>
</div>
</div>
@ -92,7 +92,7 @@ limitations under the License.
components: {
BashPrism,
},
display: 'Certbot',
display: i18n.templates.setupSections.certbot.certbot,
key: 'certbot',
props: {
data: Object,

View File

@ -19,19 +19,26 @@ limitations under the License.
<ol>
<li>
<p>
<b>Download</b> the generated config: <b><a @click="$parent.downloadTar">{{ $parent.tarName }}</a></b>
<span v-html="i18n.templates.setupSections.download.downloadTheGeneratedConfig"></span>
<b>&nbsp;<a @click="$parent.downloadTar">{{ $parent.tarName }}</a></b>
<br />
and <b>upload</b> it to your server's <code class="slim">{{ $parent.nginxDir }}</code> directory.
<span v-html="i18n.templates.setupSections.download.andUploadItToYourServers"></span>
<code class="slim">{{ $parent.nginxDir }}</code>
{{ i18n.templates.setupSections.download.directory }}
</p>
<p>
or, <b><a @click="$parent.copyTar">Copy a base64 string of the compressed config</a></b>, paste it in
your server's command line and execute it.
{{ i18n.templates.setupSections.download.or }}
<b>
<a @click="$parent.copyTar">
{{ i18n.templates.setupSections.download.copyBase64StringOfCompressedConfig }}</a>
</b>
<span v-html="i18n.templates.setupSections.download.pasteItInYourServersCommandLineAndExecute"></span>
</p>
</li>
<li>
<p>
Navigate to your NGINX <b>configuration directory</b> on your server:
<span v-html="i18n.templates.setupSections.download.navigateToYourNginxConfigurationDirectoryOnYourServer"></span>
<br />
<BashPrism :key="$parent.nginxDir" :cmd="`cd ${$parent.nginxDir}`"></BashPrism>
</p>
@ -39,7 +46,7 @@ limitations under the License.
<li>
<p>
Create a <b>backup</b> of your current NGINX configuration:
<span v-html="i18n.templates.setupSections.download.createABackupOfYourCurrentNginxConfiguration"></span>
<br />
<BashPrism cmd="tar -czvf nginx_$(date +'%F_%H-%M-%S').tar.gz nginx.conf sites-available/ sites-enabled/ nginxconfig.io/"></BashPrism>
</p>
@ -47,7 +54,7 @@ limitations under the License.
<li>
<p>
<b>Extract</b> the new compressed configuration archive using tar:
<span v-html="i18n.templates.setupSections.download.extractTheNewCompressedConfigurationArchiveUsingTar"></span>
<br />
<BashPrism :key="$parent.tarName" :cmd="`tar -xzvf ${$parent.tarName}`"></BashPrism>
</p>
@ -62,7 +69,7 @@ limitations under the License.
export default {
name: 'SetupDownload',
display: 'Download',
display: i18n.templates.setupSections.download.download,
key: 'download',
components: {
BashPrism,

View File

@ -17,10 +17,10 @@ limitations under the License.
<template>
<div>
<p>
<b>Let's go live!</b> 🎉
<b>{{ i18n.templates.setupSections.goLive.letsGoLive }}</b> 🎉
</p>
<p>
Reload NGINX to load in your new configuration:
{{ i18n.templates.setupSections.goLive.reloadNginxToLoadInYourNewConfiguration }}
<br />
<BashPrism cmd="sudo nginx -t && sudo systemctl reload nginx"></BashPrism>
</p>
@ -33,7 +33,7 @@ limitations under the License.
export default {
name: 'SetupGoLive',
display: 'Go live!',
display: i18n.templates.setupSections.goLive.goLive,
key: 'goLive',
components: {
BashPrism,

View File

@ -19,7 +19,7 @@ limitations under the License.
<ol v-if="diffieHellmanValue || letsEncryptActive">
<li v-if="diffieHellmanValue">
<p>
Generate <b>Diffie-Hellman keys</b> by running this command on your server:
<span v-html="i18n.templates.setupSections.ssl.generateDiffieHellmanKeysByRunningThisCommandOnYourServer"></span>
<br />
<BashPrism :key="`${nginxDir}-${diffieHellmanValue}`"
:cmd="`openssl dhparam -out ${nginxDir}/dhparam.pem ${diffieHellmanValue}`"
@ -29,10 +29,9 @@ limitations under the License.
<li v-if="letsEncryptActive">
<p>
Create a common <b>ACME-challenge</b> directory (for <b>Let's Encrypt</b>):
<span v-html="i18n.templates.setupSections.ssl.createACommonAcmeChallengeDirectoryForLetsEncrypt"></span>
<br />
<BashPrism :key="letsEncryptDir" :cmd="`mkdir -p ${letsEncryptDir}`"></BashPrism>
<br />
<BashPrism :key="`${nginxUser}-${letsEncryptDir}`"
:cmd="`chown ${nginxUser} ${letsEncryptDir}`"
></BashPrism>
@ -45,7 +44,7 @@ limitations under the License.
<div class="field">
<div class="control">
<label class="text">
No additional steps are needed to set up SSL for your NGINX configuration.
{{ i18n.templates.setupSections.ssl.noAdditionalStepsAreNeededToSetUpSslForNginx }}
</label>
</div>
</div>
@ -60,7 +59,7 @@ limitations under the License.
export default {
name: 'SetupSSL',
display: 'SSL init',
display: i18n.templates.setupSections.ssl.sslInit,
key: 'ssl',
components: {
BashPrism,

View File

@ -144,6 +144,7 @@ export default data => {
// Handle converting old domain settings to new ones
for (const key in values[i]) {
if (!Object.prototype.hasOwnProperty.call(values[i], key)) continue;
if (isObject(values[i][key])) continue;
// Map old settings to their new ones
if (key in domainMap) {

View File

@ -22,7 +22,7 @@ module.exports = {
publicPath: './',
outputDir: 'dist',
filenameHashing: false,
productionSourceMap: false,
//productionSourceMap: false,
configureWebpack: {
plugins: [
process.argv.includes('--analyze') && new BundleAnalyzerPlugin(),