Add SSL, certbot & go live setup steps
parent
7584d018f6
commit
2809d5fa7a
|
@ -81,10 +81,9 @@ $highlight: #f2c94c;
|
||||||
.panel {
|
.panel {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
padding: 1.5rem 0 2rem;
|
padding: 1.5rem 0 2rem;
|
||||||
|
|
||||||
&.presets {
|
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|
||||||
|
&.presets {
|
||||||
.header-group,
|
.header-group,
|
||||||
.buttons-group {
|
.buttons-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -115,21 +114,20 @@ $highlight: #f2c94c;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.setup {
|
&.setup {
|
||||||
ol {
|
|
||||||
color: $dark-blue;
|
|
||||||
margin: 0 1rem;
|
|
||||||
text-align: left;
|
|
||||||
|
|
||||||
li {
|
|
||||||
margin: 0 0 1.5rem;
|
|
||||||
|
|
||||||
p {
|
p {
|
||||||
|
color: $dark-blue;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ol {
|
||||||
|
margin: 0 1rem;
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin: 0 0 1.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
<div v-if="!sslProfileEnabled" class="field is-horizontal is-aligned-top">
|
||||||
|
<div class="field-label">
|
||||||
|
<label class="label">SSL profile</label>
|
||||||
|
</div>
|
||||||
|
<div class="field-body">
|
||||||
|
<div class="field">
|
||||||
|
<div class="control">
|
||||||
|
<label class="text">
|
||||||
|
HTTPS must be enabled on at least one site to configure global HTTPS settings.
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template v-else>
|
||||||
<div class="field is-horizontal is-aligned-top">
|
<div class="field is-horizontal is-aligned-top">
|
||||||
<div class="field-label">
|
<div class="field-label">
|
||||||
<label class="label">SSL profile</label>
|
<label class="label">SSL profile</label>
|
||||||
|
@ -72,6 +88,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -139,19 +156,52 @@
|
||||||
},
|
},
|
||||||
deep: true,
|
deep: true,
|
||||||
},
|
},
|
||||||
// Enable LE webroot if any site uses LE
|
|
||||||
'$parent.$parent.$data.domains': {
|
'$parent.$parent.$data.domains': {
|
||||||
handler(data) {
|
handler(data) {
|
||||||
|
let httpsEnabled = false, leEnabled = false;
|
||||||
|
|
||||||
for (const domain of data) {
|
for (const domain of data) {
|
||||||
|
// Enable HTTPS server settings if any site uses HTTPS
|
||||||
|
if (domain && domain.https && domain.https.https && domain.https.https.computed) {
|
||||||
|
this.$props.data.sslProfile.enabled = true;
|
||||||
|
this.$props.data.sslProfile.computed = this.$props.data.sslProfile.value;
|
||||||
|
this.$props.data.ocspCloudflare.enabled = true;
|
||||||
|
this.$props.data.ocspCloudflare.computed = this.$props.data.ocspCloudflare.value;
|
||||||
|
this.$props.data.ocspGoogle.enabled = true;
|
||||||
|
this.$props.data.ocspGoogle.computed = this.$props.data.ocspGoogle.value;
|
||||||
|
this.$props.data.ocspOpenDns.enabled = true;
|
||||||
|
this.$props.data.ocspOpenDns.computed = this.$props.data.ocspOpenDns.value;
|
||||||
|
this.$props.data.letsEncryptRoot.enabled = true;
|
||||||
|
this.$props.data.letsEncryptRoot.computed = this.$props.data.letsEncryptRoot.value;
|
||||||
|
httpsEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable LE webroot if any site uses LE
|
||||||
if (domain && domain.https && domain.https.certType
|
if (domain && domain.https && domain.https.certType
|
||||||
&& domain.https.certType.computed === 'letsEncrypt') {
|
&& domain.https.certType.computed === 'letsEncrypt') {
|
||||||
this.$props.data.letsEncryptRoot.enabled = true;
|
this.$props.data.letsEncryptRoot.enabled = true;
|
||||||
this.$props.data.letsEncryptRoot.computed = this.$props.data.letsEncryptRoot.value;
|
this.$props.data.letsEncryptRoot.computed = this.$props.data.letsEncryptRoot.value;
|
||||||
return;
|
leEnabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!httpsEnabled) {
|
||||||
|
this.$props.data.sslProfile.enabled = false;
|
||||||
|
this.$props.data.sslProfile.computed = '';
|
||||||
|
this.$props.data.ocspCloudflare.enabled = false;
|
||||||
|
this.$props.data.ocspCloudflare.computed = false;
|
||||||
|
this.$props.data.ocspGoogle.enabled = false;
|
||||||
|
this.$props.data.ocspGoogle.computed = false;
|
||||||
|
this.$props.data.ocspOpenDns.enabled = false;
|
||||||
|
this.$props.data.ocspOpenDns.computed = false;
|
||||||
this.$props.data.letsEncryptRoot.enabled = false;
|
this.$props.data.letsEncryptRoot.enabled = false;
|
||||||
this.$props.data.letsEncryptRoot.computed = '';
|
this.$props.data.letsEncryptRoot.computed = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!leEnabled) {
|
||||||
|
this.$props.data.letsEncryptRoot.enabled = false;
|
||||||
|
this.$props.data.letsEncryptRoot.computed = '';
|
||||||
|
}
|
||||||
},
|
},
|
||||||
deep: true,
|
deep: true,
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<ol v-if="letsEncryptActive">
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Comment out SSL related directives in the configuration:
|
||||||
|
<br />
|
||||||
|
<code class="slim">sed -i -r 's/(listen .*443)/\1;#/g;
|
||||||
|
s/(ssl_(certificate|certificate_key|trusted_certificate) )/#;#\1/g' {{ sitesAvailable }}</code>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Reload your NGINX server:
|
||||||
|
<br />
|
||||||
|
<code class="slim">sudo nginx -t && sudo systemctl reload nginx</code>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Obtain SSL certificates from Let's Encrypt using Certbot:
|
||||||
|
<template v-for="cmd in certbotCmds">
|
||||||
|
<br />
|
||||||
|
<code class="slim">{{ cmd }}</code>
|
||||||
|
</template>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Uncomment SSL related directives in the configuration:
|
||||||
|
<br />
|
||||||
|
<code class="slim">sed -i -r 's/#?;#//g' {{ sitesAvailable }}</code>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Reload your NGINX server:
|
||||||
|
<br />
|
||||||
|
<code class="slim">sudo nginx -t && sudo systemctl reload nginx</code>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<p>
|
||||||
|
Configure Certbot to reload NGINX when it successfully renews certificates:
|
||||||
|
<br />
|
||||||
|
<code class="slim">echo -e '#!/bin/bash\nnginx -t && systemctl reload nginx' | sudo tee /etc/letsencrypt/renewal-hooks/post/nginx-reload.sh</code>
|
||||||
|
<br />
|
||||||
|
<code class="slim">sudo chmod a+x /etc/letsencrypt/renewal-hooks/post/nginx-reload.sh</code>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<div v-else class="field is-horizontal">
|
||||||
|
<div class="field-body">
|
||||||
|
<div class="field">
|
||||||
|
<div class="control">
|
||||||
|
<label class="text">
|
||||||
|
Certbot does not need to be set up for your NGINX configuration.
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import i18n from '../../i18n';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SetupCertbot',
|
||||||
|
display: 'Certbot',
|
||||||
|
key: 'certbot',
|
||||||
|
props: {
|
||||||
|
data: Object,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
i18n,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
nginxDir() {
|
||||||
|
return this.$props.data.global.nginx.nginxConfigDirectory.computed.replace(/\/+$/, '');
|
||||||
|
},
|
||||||
|
letsEncryptDir() {
|
||||||
|
return this.$props.data.global.https.letsEncryptRoot.computed.replace(/\/+$/, '');
|
||||||
|
},
|
||||||
|
letsEncryptActive() {
|
||||||
|
for (const domain of this.$props.data.domains) {
|
||||||
|
if (domain && domain.https.certType.computed === 'letsEncrypt') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
sitesAvailable() {
|
||||||
|
const enabledAvailable = this.$props.data.global.tools.symlinkVhost.computed ? 'available' : 'enabled';
|
||||||
|
return this.$props.data.domains
|
||||||
|
.filter(domain => domain.https.certType.computed === 'letsEncrypt')
|
||||||
|
.map(domain => `${this.nginxDir}/sites-${enabledAvailable}/${domain.server.domain.computed}.conf`)
|
||||||
|
.join(' ');
|
||||||
|
},
|
||||||
|
certbotCmds() {
|
||||||
|
return this.$props.data.domains
|
||||||
|
.filter(domain => domain.https.certType.computed === 'letsEncrypt')
|
||||||
|
.map(domain => (
|
||||||
|
[
|
||||||
|
'certbot certonly --webroot',
|
||||||
|
`-d ${domain.server.domain.computed}`,
|
||||||
|
domain.server.wwwSubdomain.computed ? `-d www.${domain.server.domain.computed}` : null,
|
||||||
|
domain.server.cdnSubdomain.computed ? `-d cdn.${domain.server.domain.computed}` : null,
|
||||||
|
`--email ${domain.https.letsEncryptEmail.computed}`,
|
||||||
|
`-w ${this.letsEncryptDir}`,
|
||||||
|
'-n --agree-tos --force-renewal',
|
||||||
|
].filter(x => x !== null).join(' ')
|
||||||
|
));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,30 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
<b>Let's go live!</b> 🎉
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Reload NGINX to load in your new configuration:
|
||||||
|
<br />
|
||||||
|
<code class="slim">sudo nginx -t && sudo systemctl reload nginx</code>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import i18n from '../../i18n';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SetupGoLive',
|
||||||
|
display: 'Go live!',
|
||||||
|
key: 'goLive',
|
||||||
|
props: {
|
||||||
|
data: Object,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
i18n,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -1 +1,4 @@
|
||||||
export { default as Download } from './download';
|
export { default as Download } from './download';
|
||||||
|
export { default as SSL } from './ssl';
|
||||||
|
export { default as Certbot } from './certbot';
|
||||||
|
export { default as GoLive } from './go_live';
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<ol v-if="diffieHellmanValue || letsEncryptActive">
|
||||||
|
<li v-if="diffieHellmanValue">
|
||||||
|
<p>
|
||||||
|
Generate <b>Diffie-Hellman keys</b> by running this command on your server:
|
||||||
|
<br />
|
||||||
|
<code class="slim">openssl dhparam -out {{ nginxDir }}/dhparam.pem {{ diffieHellmanValue }}</code>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li v-if="letsEncryptActive">
|
||||||
|
<p>
|
||||||
|
Create a common <b>ACME-challenge</b> directory (for <b>Let's Encrypt</b>):
|
||||||
|
<br />
|
||||||
|
<code class="slim">mkdir -p {{ letsEncryptDir }}</code>
|
||||||
|
<br />
|
||||||
|
<code class="slim">chown {{ nginxUser }} {{ letsEncryptDir }}</code>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<div v-else class="field is-horizontal">
|
||||||
|
<div class="field-body">
|
||||||
|
<div class="field">
|
||||||
|
<div class="control">
|
||||||
|
<label class="text">
|
||||||
|
No additional steps are needed to set up SSL for your NGINX configuration.
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import i18n from '../../i18n';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SetupSSL',
|
||||||
|
display: 'SSL init',
|
||||||
|
key: 'ssl',
|
||||||
|
props: {
|
||||||
|
data: Object,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
i18n,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
nginxDir() {
|
||||||
|
return this.$props.data.global.nginx.nginxConfigDirectory.computed.replace(/\/+$/, '');
|
||||||
|
},
|
||||||
|
letsEncryptDir() {
|
||||||
|
return this.$props.data.global.https.letsEncryptRoot.computed.replace(/\/+$/, '');
|
||||||
|
},
|
||||||
|
nginxUser() {
|
||||||
|
return this.$props.data.global.nginx.user.computed;
|
||||||
|
},
|
||||||
|
diffieHellmanValue() {
|
||||||
|
switch (this.$props.data.global.https.sslProfile.computed) {
|
||||||
|
case 'intermediate':
|
||||||
|
return 2048;
|
||||||
|
case 'old':
|
||||||
|
return 1024;
|
||||||
|
case 'modern':
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
letsEncryptActive() {
|
||||||
|
for (const domain of this.$props.data.domains) {
|
||||||
|
if (domain && domain.https.certType.computed === 'letsEncrypt') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
Loading…
Reference in New Issue