Refactor Letsencrypt stack

This commit is contained in:
VirtuBox
2019-07-15 10:43:40 +02:00
parent 65332103e1
commit 53b85719f1
4 changed files with 88 additions and 210 deletions

View File

@@ -6,9 +6,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
## Releases
### v3.9.x - [Unreleased]
### v3.9.6 - [Unreleased]
---
#### Added
- New Nginx package on Ubuntu with Cloudflare HTTP/2 HPACK and Dynamic TLS records
- phpMyAdmin upgrade with `wo stack upgrade --phpmyadmin`
- Wildcard SSL Certificates support with DNS validation
#### Fixed
- Nginx was not reloaded after enabling HSTS
### v3.9.5.4 - 2019-07-13

View File

@@ -42,11 +42,12 @@
- **Easy to install** : One step automated installer with migration from EasyEngine v3 support
- **Fast deployment** : Fast and automated WordPress, Nginx, PHP, MySQL & Redis installation
- **Up-to-date** : Nginx 1.16.0 with TLS v1.3 & Brotli support, PHP 7.2 & 7.3, MariaDB 10.3 & Redis 5.0
- **Custom Nginx build** : Nginx 1.16.0 - TLS v1.3 Cloudflare HTTP/2 HPACK & Brotli support
- **Up-to-date** : PHP 7.2 & 7.3, MariaDB 10.3 & Redis 5.0
- **Secured** : Hardened WordPress security with strict Nginx location directives
- **Powerful** : Optimized Nginx configurations with multiple cache backends support
- **SSL** : Let's Encrypt SSL certificates handled by acme.sh
- **Modern** : Secured SSL/TLS encryption with strong ciphers_suite, modern TLS protocols and HSTS support
- **SSL** : Domain, Subdomain & Wildcard Let's Encrypt SSL certificates handled by acme.sh
- **Modern** : Strong ciphers_suite, modern TLS protocols and HSTS support (Grade A+ on ssllabs)
- **Monitoring** : Live Nginx vhost traffic with ngx_vts_module and server monitoring with Netdata
## Requirements
@@ -167,12 +168,11 @@ Apps & Tools shipped with WordOps :
- [Composer](https://github.com/composer/composer)
- [Adminer](https://www.adminer.org/)
- [phpRedisAdmin](https://github.com/erikdubbelboer/phpRedisAdmin)
- [PHPMemcachedAdmin](https://github.com/elijaa/phpmemcachedadmin)
- [opcacheGUI](https://github.com/amnuts/opcache-gui)
- [eXtplorer](https://github.com/soerennb/extplorer)
- [MySQLTuner](https://github.com/major/MySQLTuner-perl/)
- [Webgrind](https://github.com/jokkedk/webgrind)
- [MySQLTuner](https://github.com/major/MySQLTuner-perl)
## License

View File

@@ -1264,19 +1264,30 @@ class WOSiteUpdateController(CementBaseController):
" http://{0}".format(wo_domain))
return 0
if self.app.pargs.dns:
wo_acme_dns = pargs.dns
if pargs.letsencrypt:
if data['letsencrypt'] is True:
if not os.path.isfile("{0}/conf/nginx/ssl.conf.disabled"
.format(wo_site_webroot)):
if self.app.pargs.letsencrypt == "on":
setupLetsEncrypt(self, wo_domain)
if self.app.pargs.dns:
setupLetsEncrypt(self, wo_domain, False,
False, True, wo_acme_dns)
else:
setupLetsEncrypt(self, wo_domain)
httpsRedirect(self, wo_domain)
elif self.app.pargs.letsencrypt == "subdomain":
setupLetsEncryptSubdomain(self, wo_domain)
if self.app.pargs.dns:
setupLetsEncrypt(self, wo_domain, True, False,
True, wo_acme_dns)
else:
setupLetsEncrypt(self, wo_domain, True)
httpsRedirect(self, wo_domain)
elif self.app.pargs.letsencrypt == "wildcard":
wo_acme_dns = pargs.dns
setupLetsEncryptWildcard(self, wo_domain, wo_acme_dns)
setupLetsEncrypt(self, wo_domain, false, True,
True, wo_acme_dns)
httpsRedirect(self, wo_domain, True, True)
else:
WOFileUtils.mvfile(self, "{0}/conf/nginx/ssl.conf.disabled"

View File

@@ -339,7 +339,8 @@ def setupwordpress(self, data):
.format(WOVariables.wo_wpcli_path) +
"config create " +
"--dbname=\'{0}\' --dbprefix=\'{1}\' --dbhost=\'{2}\' "
.format(data['wo_db_name'], wo_wp_prefix, data['wo_db_host']) +
.format(data['wo_db_name'],
wo_wp_prefix, data['wo_db_host']) +
"--dbuser=\'{0}\' --dbpass=\'{1}\' "
"--extra-php<<PHP \n {2} {3} {4} \nPHP\""
.format(data['wo_db_user'], data['wo_db_pass'],
@@ -1267,38 +1268,66 @@ def doCleanupAction(self, domain='', webroot='', dbname='', dbuser='',
# setup letsencrypt for domain + www.domain
def setupLetsEncrypt(self, wo_domain_name):
def setupLetsEncrypt(self, wo_domain_name, subdomain=false, wildcard=false,
wo_dns=false, wo_acme_dns='dns_cf'):
if os.path.isfile("/etc/letsencrypt/renewal/{0}_ecc/{0}.conf"
.format(wo_domain_name)):
if os.path.isfile("/etc/letsencrypt/"
"renewal/{0}_ecc/"
"fullchain.cer".format(wo_domain_name)):
Log.debug(self, "Let's Encrypt certificate "
"found for the domain: {0}"
.format(wo_domain_name))
ssl = archivedCertificateHandle(self, wo_domain_name)
else:
Log.info(self, "Issuing SSL cert with acme.sh")
ssl = WOShellExec.cmd_exec(self, "/etc/letsencrypt/acme.sh "
"--config-home "
"'/etc/letsencrypt/config' "
"--issue "
"-d {0} -d www.{0} -w /var/www/html "
"-k ec-384 -f"
.format(wo_domain_name))
if os.path.isfile("/etc/letsencrypt/"
"renewal/{0}_ecc/"
"fullchain.cer".format(wo_domain_name)):
Log.debug(self, "Let's Encrypt certificate "
"found for the domain: {0}"
.format(wo_domain_name))
ssl = archivedCertificateHandle(self, wo_domain_name)
else:
Log.info(self, "Issuing SSL cert with acme.sh")
ssl = WOShellExec.cmd_exec(self, "/etc/letsencrypt/acme.sh "
"--config-home "
"'/etc/letsencrypt/config' "
"--issue "
"-d {0} -d www.{0} -w /var/www/html "
"-k ec-384 -f"
.format(wo_domain_name))
if subdomain:
if wo_dns:
ssl = WOShellExec.cmd_exec(self, "/etc/letsencrypt/acme.sh "
"--config-home "
"'/etc/letsencrypt/config' "
"--issue "
"-d {0} --dns {1} "
"-k ec-384 -f"
.format(wo_domain_name,
wo_acme_dns))
else:
ssl = WOShellExec.cmd_exec(self, "/etc/letsencrypt/acme.sh "
"--config-home "
"'/etc/letsencrypt/config' "
"--issue "
"-d {0} -w /var/www/html "
"-k ec-384 -f"
.format(wo_domain_name))
elif wildcard:
if wo_dns:
ssl = WOShellExec.cmd_exec(self, "/etc/letsencrypt/acme.sh "
"--config-home "
"'/etc/letsencrypt/config' "
"--issue "
"-d {0} -d *.{0} --dns {1} "
"-k ec-384 -f"
.format(wo_domain_name,
wo_acme_dns))
else:
if wo_dns:
ssl = WOShellExec.cmd_exec(self, "/etc/letsencrypt/acme.sh "
"--config-home "
"'/etc/letsencrypt/config' "
"--issue "
"-d {0} -d www.{0} --dns {1} "
"-k ec-384 -f"
.format(wo_domain_name,
wo_acme_dns))
else:
ssl = WOShellExec.cmd_exec(self, "/etc/letsencrypt/acme.sh "
"--config-home "
"'/etc/letsencrypt/config' "
"--issue "
"-d {0} -d www.{0} "
"-w /var/www/html "
"-k ec-384 -f"
.format(wo_domain_name))
if ssl:
try:
Log.info(self, "Deploying SSL cert with acme.sh")
Log.debug(self, "Cert deployment for domain: {0}"
@@ -1349,176 +1378,6 @@ def setupLetsEncrypt(self, wo_domain_name):
"you are running Let\'s Encrypt Client "
"\n to allow it to verify the site automatically.")
# setup letsencrypt for a subdomain
def setupLetsEncryptSubdomain(self, wo_domain_name):
if os.path.isfile("/etc/letsencrypt/renewal/{0}_ecc/{0}.conf"
.format(wo_domain_name)):
if os.path.isfile("/etc/letsencrypt/"
"renewal/{0}_ecc/"
"fullchain.cer".format(wo_domain_name)):
Log.debug(self, "Let's Encrypt certificate "
"found for the domain: {0}"
.format(wo_domain_name))
ssl = archivedCertificateHandle(self, wo_domain_name)
else:
Log.info(self, "Issuing SSL cert with acme.sh")
ssl = WOShellExec.cmd_exec(self, "/etc/letsencrypt/acme.sh "
"--config-home "
"'/etc/letsencrypt/config' "
"--issue "
"-d {0} -w /var/www/html "
"-k ec-384 -f"
.format(wo_domain_name))
else:
Log.info(self, "Issuing SSL cert with acme.sh")
ssl = WOShellExec.cmd_exec(self, "/etc/letsencrypt/acme.sh "
"--config-home "
"'/etc/letsencrypt/config' "
"--issue "
"-d {0} -w /var/www/html "
"-k ec-384 -f"
.format(wo_domain_name))
if ssl:
try:
Log.info(self, "Deploying SSL cert with acme.sh")
Log.debug(self, "Deploying cert for domain: {0}"
.format(wo_domain_name))
sslsetup = WOShellExec.cmd_exec(self, "mkdir -p {0}/{1} && "
"/etc/letsencrypt/acme.sh "
"--config-home "
"'/etc/letsencrypt/config' "
"--install-cert -d {1} --ecc "
"--cert-file {0}/{1}/cert.pem "
"--key-file {0}/{1}/key.pem "
"--fullchain-file "
"{0}/{1}/fullchain.pem "
"--ca-file {0}/{1}/ca.pem "
"--reloadcmd "
"\"nginx -t && service nginx restart\" "
.format(WOVariables.wo_ssl_live,
wo_domain_name))
Log.info(
self, "Adding /var/www/{0}/conf/nginx/ssl.conf"
.format(wo_domain_name))
sslconf = open("/var/www/{0}/conf/nginx/ssl.conf"
.format(wo_domain_name),
encoding='utf-8', mode='w')
sslconf.write("listen 443 ssl http2;\n"
"listen [::]:443 ssl http2;\n"
"ssl_certificate {0}/{1}/fullchain.pem;\n"
"ssl_certificate_key {0}/{1}/key.pem;\n"
"ssl_trusted_certificate {0}/{1}/ca.pem;\n"
"ssl_stapling_verify on;\n"
.format(WOVariables.wo_ssl_live, wo_domain_name))
sslconf.close()
updateSiteInfo(self, wo_domain_name, ssl=True)
WOGit.add(self, ["/etc/letsencrypt"],
msg="Adding letsencrypt folder")
except IOError as e:
Log.debug(self, str(e))
Log.debug(self, "Error occured while generating "
"ssl.conf")
else:
Log.error(self, "Unable to create ssl.conf", False)
Log.error(self, "Please make sure that your site is pointed to \n"
"same server on which "
"you are running Let\'s Encrypt Client "
"\n to allow it to verify the site automatically.")
# setup letsencrypt for domain + www.domain
def setupLetsEncryptWildcard(self, wo_domain_name, wo_acme_dns='dns_cf'):
if os.path.isfile("/etc/letsencrypt/renewal/{0}_ecc/{0}.conf"
.format(wo_domain_name)):
if os.path.isfile("/etc/letsencrypt/"
"renewal/{0}_ecc/"
"fullchain.cer".format(wo_domain_name)):
Log.debug(self, "Let's Encrypt certificate "
"found for the domain: {0}"
.format(wo_domain_name))
ssl = archivedCertificateHandle(self, wo_domain_name)
else:
Log.info(self, "Issuing SSL cert with acme.sh")
ssl = WOShellExec.cmd_exec(self, "/etc/letsencrypt/acme.sh "
"--config-home "
"'/etc/letsencrypt/config' "
"--issue "
"-d {0} -d *.{0} --dns {1} "
"-k ec-384 -f"
.format(wo_domain_name, wo_acme_dns))
else:
Log.info(self, "Issuing SSL cert with acme.sh")
ssl = WOShellExec.cmd_exec(self, "/etc/letsencrypt/acme.sh "
"--config-home "
"'/etc/letsencrypt/config' "
"--issue "
"-d {0} -d *.{0} --dns {1} "
"-k ec-384 -f"
.format(wo_domain_name, wo_acme_dns))
if ssl:
try:
Log.info(self, "Deploying SSL cert with acme.sh")
Log.debug(self, "Cert deployment for domain: {0}"
.format(wo_domain_name))
sslsetup = WOShellExec.cmd_exec(self, "mkdir -p {0}/{1} && "
"/etc/letsencrypt/acme.sh "
"--config-home "
"'/etc/letsencrypt/config' "
"--install-cert -d {1} --ecc "
"--cert-file {0}/{1}/cert.pem "
"--key-file {0}/{1}/key.pem "
"--fullchain-file "
"{0}/{1}/fullchain.pem "
"--ca-file {0}/{1}/ca.pem "
"--reloadcmd "
"\"nginx -t && "
"service nginx restart\" "
.format(WOVariables.wo_ssl_live,
wo_domain_name))
Log.info(
self, "Adding /var/www/{0}/conf/nginx/ssl.conf"
.format(wo_domain_name))
sslconf = open("/var/www/{0}/conf/nginx/ssl.conf"
.format(wo_domain_name),
encoding='utf-8', mode='w')
sslconf.write("listen 443 ssl http2;\n"
"listen [::]:443 ssl http2;\n"
"ssl_certificate {0}/{1}/fullchain.pem;\n"
"ssl_certificate_key {0}/{1}/key.pem;\n"
"ssl_trusted_certificate {0}/{1}/ca.pem;\n"
"ssl_stapling_verify on;\n"
.format(WOVariables.wo_ssl_live, wo_domain_name))
sslconf.close()
updateSiteInfo(self, wo_domain_name, ssl=True)
WOGit.add(self, ["/etc/letsencrypt"],
msg="Adding letsencrypt folder")
except IOError as e:
Log.debug(self, str(e))
Log.debug(self, "Error occured while generating "
"ssl.conf")
else:
Log.error(self, "Unable to install certificate", False)
Log.error(self, "Please make sure that your site is pointed to \n"
"same server on which "
"you are running Let\'s Encrypt Client "
"\n to allow it to verify the site automatically.")
# letsencrypt cert renewal