diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..6bc7ddf --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,13 @@ + +This issue tracker is only for issues related to WordOps. +Please use for support questions. + +If you feel the issue is a WordOps specific issue, please attach the output of the following commands. + +System Information + +- [ ] lsb_release -a +- [ ] wo info +- [ ] nginx -V +- [ ] wo -v +- [ ] wp --allow-root info diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 3f0d1d2..0000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve WordOps -title: "[BUG]" -labels: bug -assignees: '' - ---- - -Please attach the output of the following commands with your report - -System Information -- [ ] lsb_release -a -- [ ] wo info -- [ ] wo -v -- [ ] wp --allow-root info diff --git a/.travis.yml b/.travis.yml index ef0b600..0adbc99 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,16 +23,14 @@ script: - sudo apt-get install -y --force-yes git python3-setuptools python3-dev python3-apt ccze - sudo bash install $TRAVIS_BRANCH - sudo wo --help + + - sudo wo site create wp-php73.net --wp --php73 || sudo tail -n50 /var/log/wo/wordops.log + - sudo wo stack install || sudo tail -n50 /var/log/wo/wordops.log - - sudo wo stack install --web || sudo tail -n50 /var/log/wo/wordops.log - sudo wo stack install --admin || sudo tail -n50 /var/log/wo/wordops.log - sudo wo site create html.net --html && sudo wo site create php.com --php && sudo wo site create mysql.com --mysql || sudo tail -n50 /var/log/wo/wordops.log - - - sudo wo site create mysql-php73.com --mysql --php73 || sudo tail -n50 /var/log/wo/wordops.log - - sudo wo site create wp1.com --wp || sudo tail -n50 /var/log/wo/wordops.log - - sudo wo site create wp-php73.com --wp --php73 || sudo tail -n50 /var/log/wo/wordops.log - sudo wo site create wpsc1.net --wpsc && sudo wo site create wpfc1.com --wpfc || sudo tail -n50 /var/log/wo/wordops.log @@ -60,6 +58,6 @@ script: - sudo ls /var/www/ - sudo wp --allow-root --info - - sudo bash -c 'nginx -T 2>&1 > /var/log/wo/nginx.log' + - sudo bash -c 'nginx -T 2>&1 > /var/log/wo/nginx.log 2>&1' || sudo tail -n50 /var/log/wo/wordops.log - sudo bash -c 'tar -I pigz -cf wordops.tar.gz /var/log/wo' - - sudo curl --progress-bar --upload-file "wordops.tar.gz" https://transfer.vtbox.net/$(basename wordops.tar.gz) && echo "" + - sudo curl --progress-bar --upload-file "wordops.tar.gz" https://transfer.sh/$(basename wordops.tar.gz) && echo "" diff --git a/CHANGELOG.md b/CHANGELOG.md index a333a97..710f261 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,9 +10,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### v3.9.5 - [Unreleased] -### Changed +#### Added +- IPv6 support with HTTPS +- Brotli support in Nginx + +#### Changed + +- letsencrypt stack refactored with acme.sh - "--letsencrypt=subdomain" option +- hardened nginx ssl_ecdh_curve #### Fixed diff --git a/README.md b/README.md index d57f89a..39cbdf9 100644 --- a/README.md +++ b/README.md @@ -28,10 +28,10 @@ - Easy Migration from EasyEngine v3 (migration script development in progress) - Automated WordPress, Nginx, PHP, MySQL & Redis installation -- Up-to-date server stack with Nginx 1.14.2, PHP 7.2 & 7.3, MariaDB 10.3 & Redis 5.0 +- Nginx 1.14.2 with Brotli support, PHP 7.2 & 7.3, MariaDB 10.3 & Redis 5.0 - Hardened WordPress security with strict Nginx location directives - Optimized Nginx configurations with multiple cache backends support -- Let's Encrypt SSL certificates +- Let's Encrypt SSL certificates handled by Acme.sh - Secured SSL/TLS encryption with strong ciphers_suite and modern TLS protocols ## Requirements @@ -41,7 +41,7 @@ - Ubuntu 16.04 LTS (Xenial) - Ubuntu 18.04 LTS (Bionic) - Debian 8 (Jessie) -- Debian 9 (Stretch) -> **Not fully supported yet** +- Debian 9 (Stretch) ### Ports requirements @@ -113,6 +113,13 @@ wo site create example.com --mysql # create example.com with php & mysql supp wo site create example.com --proxy=127.0.0.1:3000 # create example.com with nginx as reverse-proxy ``` +### Sites secured with Let's Encrypt + +```bash +wo site create example.com --wp --letsencrypt # install wordpress & secure site with letsencrypt +wo site create sub.example.com --wp --letsencrypt=subdomain # install wordpress and secure subdomain with letsencrypt +``` + ## Cheatsheet | | single site | multisite w/ subdir | multisite w/ subdom | @@ -128,9 +135,19 @@ wo site create example.com --proxy=127.0.0.1:3000 # create example.com with ngi wo update ``` +## Support + +If you feel there is a bug directly related to WordOps, feel free to open an issue. +For any other questions/suggestions about WordOps or if you need support, please use the [WordOps Community Forum](https://community.wordops.io/). + +# Contributing + +If you'd like to contribute, please fork the repository and make changes as you'd like. Pull requests are warmly welcome. + ## Credits -- [EasyEngine](https://github.com/easyengine/easyengine) +- Main source : [EasyEngine](https://github.com/easyengine/easyengine) +- Acme client : [Acme.sh](https://github.com/Neilpang/acme.sh) ## License diff --git a/install b/install index c69611e..4abdd21 100644 --- a/install +++ b/install @@ -136,6 +136,7 @@ wo_install_dep() if [ "$wo_linux_distro" == "Ubuntu" ]; then DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confmiss" -o Dpkg::Options::="--force-confold" -y install build-essential curl gzip python3 python3-apt python3-setuptools python3-dev sqlite3 git tar software-properties-common pigz gnupg2 fail2ban cron ccze > /dev/null 2>&1 else + wget -qO /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confmiss" -o Dpkg::Options::="--force-confold" -y install build-essential curl gzip dirmngr sudo python3 python3-apt python3-setuptools python3-dev ca-certificates sqlite3 git tar software-properties-common pigz apt-transport-https gnupg2 fail2ban cron ccze > /dev/null 2>&1 fi @@ -392,10 +393,10 @@ wo_upgrade_nginx() wget -qO /tmp/nginx-wo.key "https://download.opensuse.org/repositories/home:virtubox:WordOps/xUbuntu_${wo_distro_id}/Release.key" else if [ "$wo_distro_version" == "jessie" ]; then - echo "deb http://download.opensuse.org/repositories/home:/virtubox:/WordOps/Debian_8.0/ /" > /etc/apt/sources.list.d/wo-repo.list + echo "deb http://download.opensuse.org/repositories/home:/virtubox:/WordOps/Debian_8.0/ /" >> /etc/apt/sources.list.d/wo-repo.list wget -qO /tmp/nginx-wo.key https://download.opensuse.org/repositories/home:virtubox:WordOps/Debian_8.0/Release.key else - echo "deb http://download.opensuse.org/repositories/home:/virtubox:/WordOps/Debian_9.0/ /" > /etc/apt/sources.list.d/wo-repo.list + echo "deb http://download.opensuse.org/repositories/home:/virtubox:/WordOps/Debian_9.0/ /" >> /etc/apt/sources.list.d/wo-repo.list wget -qO /tmp/nginx-wo.key https://download.opensuse.org/repositories/home:virtubox:WordOps/Debian_9.0/Release.key fi fi @@ -413,7 +414,13 @@ wo_upgrade_nginx() apt-mark unhold nginx-ee nginx-common nginx-custom apt-get -y -qq autoremove nginx-ee nginx-common nginx-custom # install new nginx package - DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confmiss" -o Dpkg::Options::="--force-confnew" -y install nginx-custom nginx-wo + if [ -x /usr/local/bin/wo ]; then + rm -f /etc/nginx/conf.d/{upstream.conf,redis.conf,fastcgi.conf} + rm -f /etc/nginx/*.default + /usr/local/bin/wo stack install + else + DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confmiss" -o Dpkg::Options::="--force-confnew" -y install nginx-custom nginx-wo + fi # set back apt preference [ -f "$HOME/nginx-block" ] && { mv "$HOME/nginx-block" /etc/apt/preferences.d/nginx-block @@ -487,55 +494,19 @@ wo_update_latest() # Ref: http://wptavern.com/xss-vulnerability-in-jetpack-and-the-twenty-fifteen-default-theme-affects-millions-of-wordpress-users dpkg --get-selections | grep -v deinstall | grep nginx &>> /dev/null if [ $? -eq 0 ]; then - cp /usr/lib/wo/templates/locations.mustache /etc/nginx/common/locations.conf &>> /dev/null + cp /usr/lib/wo/templates/locations.mustache /etc/nginx/common/locations-php72.conf &>> /dev/null fi # Fix Redis-server security issue # http://redis.io/topics/security if [ -f /etc/redis/redis.conf ]; then - grep -0 -v "#" /etc/redis/redis.confse | grep 'bind' &>> /dev/null + grep -0 -v "#" /etc/redis/redis.conf | grep 'bind' &>> /dev/null if [ $? -ne 0 ]; then sed -i '$ a bind 127.0.0.1' /etc/redis/redis.conf &>> /dev/null service redis-server restart &>> /dev/null fi fi - # Let's Encrypt .well-known folder setup - if [ ! -d /var/www/html/.well-known/acme-challenge ]; then - mkdir -p /var/www/html/.well-known/acme-challenge - chown -R www-data:www-data /var/www/html /var/www/html/.well-known - fi - - - # Fix for 3.3.2 renamed nginx.conf - nginx -V &>>/dev/null 2>&1 - if [[ $? -eq 0 ]]; then - nginx -t 2>&1 | grep 'open() "/etc/nginx/nginx.conf" failed' &>>/dev/null - if [[ $? -eq 0 ]]; then - if [ -f /etc/nginx/nginx.conf.old ]; then - if [ ! -f /etc/nginx/nginx.conf ]; then - cp /etc/nginx/nginx.conf.old /etc/nginx/nginx.conf - fi - fi - fi - # Fix for 3.3.2 renamed fastcgi_param - nginx -t 2>&1 | grep 'open() "/etc/nginx/fastcgi_params" failed' &>>/dev/null - if [[ $? -eq 0 ]]; then - if [ -f /etc/nginx/fastcgi_params.old ]; then - if [ ! -f /etc/nginx/fastcgi_params ]; then - cp /etc/nginx/fastcgi_params.old /etc/nginx/fastcgi_params - fi - fi - fi - fi - - # Fix for SSL cert --all - crontab -l | grep -q '\-\-min_expiry_limit' - if [[ $? -eq 0 ]]; then - crontab -l > /var/spool/cron/cron-backup.txt #backup cron before editing - crontab -l | sed '/--min_expiry_limit/d' | crontab - - /bin/bash -c "crontab -l 2> /dev/null | { cat; echo -e \"\n0 0 * * 0 wo site update --le=renew --all 2> /dev/null # Renew all letsencrypt SSL cert. Set by WordOps\"; } | crontab -" - fi } # Do git intialisation diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index b5f9ba9..5794b5d 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -311,22 +311,22 @@ class WOSiteCreateController(CementBaseController): (['--mysql'], dict(help="create mysql site", action='store_true')), (['--wp'], - dict(help="create wordpress single site", + dict(help="create WordPress single site", action='store_true')), (['--wpsubdir'], - dict(help="create wordpress multisite with subdirectory setup", + dict(help="create WordPress multisite with subdirectory setup", action='store_true')), (['--wpsubdomain'], - dict(help="create wordpress multisite with subdomain setup", + dict(help="create WordPress multisite with subdomain setup", action='store_true')), (['--wpfc'], - dict(help="create wordpress single/multi site with wpfc cache", + dict(help="create WordPress single/multi site with wpfc cache", action='store_true')), (['--wpsc'], - dict(help="create wordpress single/multi site with wpsc cache", + dict(help="create WordPress single/multi site with wpsc cache", action='store_true')), (['--wpredis'], - dict(help="create wordpress single/multi site with redis cache", + dict(help="create WordPress single/multi site with redis cache", action='store_true')), (['-le', '--letsencrypt'], dict(help="configure letsencrypt ssl for the site", @@ -334,16 +334,18 @@ class WOSiteCreateController(CementBaseController): choices=('on', 'subdomain', 'wildcard'), const='on', nargs='?')), (['--user'], - dict(help="provide user for wordpress site")), + dict(help="provide user for WordPress site")), (['--email'], - dict(help="provide email address for wordpress site")), + dict(help="provide email address for WordPress site")), (['--pass'], - dict(help="provide password for wordpress user", + dict(help="provide password for WordPress user", dest='wppass')), (['--proxy'], dict(help="create proxy for site", nargs='+')), + (['--vhostonly'], + dict(help="only create vhost and database without installing WordPress", nargs='+')), (['--experimental'], - dict(help="Enable Experimenal packages without prompt", + dict(help="Enable Experimental packages without prompt", action='store_true')), ] @@ -447,45 +449,22 @@ class WOSiteCreateController(CementBaseController): pass if data and self.app.pargs.php73: - if (self.app.pargs.experimental): - Log.info( - self, "Do you wish to install PHP 7.3 now for {0}?".format(wo_domain)) - - # Check prompt - check_prompt = input("Type \"y\" to continue [n]:") - if check_prompt != "Y" and check_prompt != "y": - Log.info(self, "Not using PHP 7.3 for site.") - data['php73'] = True - data['basic'] = True - php73 = 1 - self.app.pargs.php73 = True - else: - data['php73'] = True - php73 = 1 - else: - data['php73'] = True - php73 = 1 + data['php73'] = True + php73 = 1 elif data: data['php73'] = False php73 = 0 - if (not self.app.pargs.wpfc) and (not self.app.pargs.wpsc) and (not self.app.pargs.wpredis): + if ((not self.app.pargs.wpfc) and + (not self.app.pargs.wpsc) and + (not self.app.pargs.wpredis)): data['basic'] = True - if (cache == 'wpredis' and (self.app.pargs.experimental)): - Log.info(self, "Redis is experimental feature and it may not " - "work with all CSS/JS/Cache of your site.\nYou can " - "disable it by changing cache later.\nDo you wish" - " to enable Redis now for {0}?".format(wo_domain)) - - # Check prompt - check_prompt = input("Type \"y\" to continue [n]:") - if check_prompt != "Y" and check_prompt != "y": - Log.error(self, "Not using Redis for site") - cache = 'basic' - data['wpredis'] = False - data['basic'] = True - self.app.pargs.wpredis = False + if (cache == 'wpredis'): + cache = 'wpredis' + data['wpredis'] = True + data['basic'] = False + self.app.pargs.wpredis = True # Check rerequired packages are installed or not wo_auth = site_package_check(self, stype) @@ -1107,21 +1086,8 @@ class WOSiteUpdateController(CementBaseController): if pargs.letsencrypt == "on" or pargs.php73 == "on": if pargs.php73 == "on": - if pargs.experimental: - Log.info( - self, "Do you wish to enable PHP 7.3 now for {0}?".format(wo_domain)) - - check_prompt = input("Type \"y\" to continue [n]:") - if check_prompt != "Y" and check_prompt != "y": - Log.info(self, "Not using PHP 7.3 for site") - data['php73'] = False - php73 = False - else: - data['php73'] = True - php73 = True - else: - data['php73'] = True - php73 = True + data['php73'] = True + php73 = True if pargs.letsencrypt == "on": if oldsitetype in ['wpsubdomain']: @@ -1134,21 +1100,12 @@ class WOSiteUpdateController(CementBaseController): wildcard = True if pargs.wpredis and data['currcachetype'] != 'wpredis': - if pargs.experimental: - Log.info(self, "Redis is experimental feature and it may not" - " work with all plugins of your site.\nYou can " - "disable it by changing cache type later.\nDo you wish" - " to enable Redis now for {0}?".format(wo_domain)) + data['wpredis'] = True + data['basic'] = False + cache = 'wpredis' - # Check prompt - check_prompt = input("Type \"y\" to continue [n]: ") - if check_prompt != "Y" and check_prompt != "y": - Log.error(self, "Not using Redis for site") - data['wpredis'] = False - data['basic'] = True - cache = 'basic' - - if (php73 is old_php73) and (stype == oldsitetype and cache == oldcachetype): + if (php73 is old_php73) and (stype == oldsitetype and + cache == oldcachetype): return 1 if not data: @@ -1258,7 +1215,8 @@ class WOSiteUpdateController(CementBaseController): Log.error(self, "service nginx reload failed. " "check issues with `nginx -t` command") - Log.info(self, "Congratulations! Successfully Configured SSl for Site " + Log.info(self, "Congratulations! Successfully" + " Configured SSL for Site " " https://{0}".format(wo_domain)) if (SSL.getExpirationDays(self, wo_domain) > 0): @@ -1266,7 +1224,8 @@ class WOSiteUpdateController(CementBaseController): str(SSL.getExpirationDays(self, wo_domain)) + " days.") else: Log.warn( - self, "Your cert already EXPIRED ! .PLEASE renew soon . ") + self, "Your cert already EXPIRED !" + " PLEASE renew soon . ") elif data['letsencrypt'] is False: if os.path.isfile("{0}/conf/nginx/ssl.conf" diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 7b8f2f6..3f6def4 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -1211,104 +1211,37 @@ def setupLetsEncrypt(self, wo_domain_name): Log.warn(self, "Please wait while we fetch the new HTTPS certificate" " for your site.\nIt may take a few minutes" " depending on the network.") - 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" - .format(wo_domain_name)) - if ssl: - Log.info(self, "The HTTPS setup for your website is " - "successfully completed!") - Log.info(self, "Your certificate and chain have been saved in " - "{0}/{1}/fullchain.pem" - .format(WOVariables.wo_ssl_live, wo_domain_name)) - Log.info(self, "Configuring nginx HTTPS configuration") + sslissue = 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" + .format(wo_domain_name)) + if sslissue: + + Log.debug(self, "Cert deployment for domain: {0}" + .format(wo_domain_name)) + ssl = 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 " + "--reloadcmd " + "\"service nginx restart\" " + .format(WOVariables.wo_ssl_live, + wo_domain_name)) + if ssl: - if os.path.isfile("{0}/{1}_ecc/fullchain.cer" - .format(WOVariables.wo_ssl_archive, wo_domain_name)): - Log.debug(self, "Cert deployment for domain: {0}" - .format(wo_domain_name)) - ssl_deploy = 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 " - "--reloadcmd " - "\"service nginx restart\" " - .format(WOVariables.wo_ssl_live, - wo_domain_name)) try: 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 on;\n" - "ssl_certificate {0}/{1}/fullchain.pem;\n" - "ssl_certificate_key {0}/{1}/key.pem;\n" - .format(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 setup, Let\'s Encrypt", 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 a subdomain - - -def setupLetsEncryptSubdomain(self, wo_domain_name): - wo_wp_email = WOVariables.wo_email - - if os.path.isfile("{0}/{1}_ecc/{1}.conf" - .format(WOVariables.wo_ssl_archive, wo_domain_name)): - Log.debug(self, "Let's Encrypt certificate found for the domain: {0}" - .format(wo_domain_name)) - else: - Log.warn(self, "Please wait while we fetch the new HTTPS certificate " - "for your site.\nIt may take a " - "few minutes depending on the network.") - ssl = WOShellExec.cmd_exec(self, "/etc/letsencrypt/acme.sh " - "--config-home " - "'/etc/letsencrypt/config' " - "--issue " - "-d {0} -w /var/www/html " - "-k ec-384" - .format(wo_domain_name)) - if ssl: - Log.info(self, "The HTTPS setup for your website " - "is successfully completed!") - Log.info(self, "Your certificate and chain have been saved in " - "{0}/{1}/fullchain.pem" - .format(WOVariables.wo_ssl_live, wo_domain_name)) - Log.info(self, "Configuring nginx HTTPS configuration") - - try: - 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') @@ -1327,9 +1260,81 @@ def setupLetsEncryptSubdomain(self, wo_domain_name): except IOError as e: Log.debug(self, str(e)) Log.debug(self, "Error occured while generating " - "ssl.conf") + "ssl.conf") else: - Log.error(self, "Unable to setup, Let\'s Encrypt", False) + 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.") + +# setup letsencrypt for a subdomain + + +def setupLetsEncryptSubdomain(self, wo_domain_name): + wo_wp_email = WOVariables.wo_email + + if os.path.isfile("{0}/{1}_ecc/{1}.conf" + .format(WOVariables.wo_ssl_archive, 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.warn(self, "Please wait while we fetch the new HTTPS certificate" + " for your site.\nIt may take a few minutes" + " depending on the network.") + sslissue = WOShellExec.cmd_exec(self, "/etc/letsencrypt/acme.sh " + "--config-home " + "'/etc/letsencrypt/config' " + "--issue " + "-d {0} -w /var/www/html " + "-k ec-384" + .format(wo_domain_name)) + if sslissue: + + Log.debug(self, "Cert deployment for domain: {0}" + .format(wo_domain_name)) + ssl = 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 " + "--reloadcmd " + "\"service nginx restart\" " + .format(WOVariables.wo_ssl_live, + wo_domain_name)) + if ssl: + + try: + 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 on;\n" + "ssl_certificate {0}/{1}/fullchain.pem;\n" + "ssl_certificate_key {0}/{1}/key.pem;\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 " @@ -1341,7 +1346,10 @@ def setupLetsEncryptSubdomain(self, wo_domain_name): def renewLetsEncrypt(self, wo_domain_name): ssl = WOShellExec.cmd_exec( - self, "/etc/letsencrypt/acme.sh --config-home '/etc/letsencrypt/config' --renew -d {0} --ecc --force" + self, "/etc/letsencrypt/acme.sh " + "--config-home " + "'/etc/letsencrypt/config' " + "--renew -d {0} --ecc --force" .format(wo_domain_name)) mail_list = '' @@ -1422,11 +1430,11 @@ def httpsRedirect(self, wo_domain_name, redirect=True): " http://{0}".format(wo_domain_name)) -def archivedCertificateHandle(self, domain, wo_wp_email): +def archivedCertificateHandle(self, domain): Log.warn(self, "You already have an existing certificate " "for the domain requested.\n" "(ref: {0}/" - "{0}_ecc/{0}.conf)".format(WOVariables.wo_ssl_archive, domain) + + "{1}_ecc/{1}.conf)".format(WOVariables.wo_ssl_archive, domain) + "\nPlease select an option from below?" "\n\t1: Reinstall existing certificate" "\n\t2: Keep the existing certificate for now" @@ -1437,7 +1445,7 @@ def archivedCertificateHandle(self, domain, wo_wp_email): if not os.path.isfile("{0}/{1}/fullchain.pem" .format(WOVariables.wo_ssl_live, domain)): Log.error( - self, "{0}/{1}/cert.pem file is missing." + self, "{0}/{1}/fullchain.pem file is missing." .format(WOVariables.wo_ssl_live, domain)) if check_prompt == "1": @@ -1456,10 +1464,31 @@ def archivedCertificateHandle(self, domain, wo_wp_email): "--reloadcmd " "\"service nginx restart\" " .format(WOVariables.wo_ssl_live, domain)) + if ssl: + + if not os.path.isfile("/var/www/{0}/conf/nginx/ssl.conf" + .format(domain)): + Log.info( + self, "Adding /var/www/{0}/conf/nginx/ssl.conf" + .format(domain)) + + sslconf = open("/var/www/{0}/conf/nginx/ssl.conf" + .format(domain), + encoding='utf-8', mode='w') + sslconf.write("listen 443 ssl http2;\n" + "listen [::]:443 ssl http2;\n" + "ssl on;\n" + "ssl_certificate {0}/{1}/fullchain.pem;\n" + "ssl_certificate_key {0}/{1}/key.pem;\n" + .format(WOVariables.wo_ssl_live, domain)) + sslconf.close() + + ssl = True elif (check_prompt == "2"): Log.info(self, "Using Existing Certificate files") - if not os.path.isfile("{0}/{1}/fullchain.pem".format(WOVariables.wo_ssl_live, domain)): + if not os.path.isfile("{0}/{1}/fullchain.pem" + .format(WOVariables.wo_ssl_live, domain)): Log.error(self, "Certificate files not found. Skipping.\n" "Please check if following file exist" "\n\t/etc/letsencrypt/live/{0}/fullchain.pem\n\t" @@ -1470,7 +1499,11 @@ def archivedCertificateHandle(self, domain, wo_wp_email): Log.info(self, "Please wait while we renew the Let's Encrypt" "certificate for your site.\nIt may take a few " "minutes depending on your network.") - ssl = WOShellExec.cmd_exec(self, "/etc/letsencrypt/acme.sh --config-home '/etc/letsencrypt/config' --renew -d {0} --ecc --force" + ssl = WOShellExec.cmd_exec(self, "/etc/letsencrypt/acme.sh " + "--config-home " + "'/etc/letsencrypt/config' " + "--renew -d {0} --ecc " + "--force" .format(domain)) else: diff --git a/wo/cli/plugins/sitedb.py b/wo/cli/plugins/sitedb.py index e006157..4048b26 100644 --- a/wo/cli/plugins/sitedb.py +++ b/wo/cli/plugins/sitedb.py @@ -12,7 +12,7 @@ import glob def addNewSite(self, site, stype, cache, path, enabled=True, ssl=False, fs='ext4', db='mysql', db_name=None, db_user=None, db_password=None, - db_host='localhost', hhvm=0, php_version='5.5'): + db_host='localhost', hhvm=0, php_version='7.2'): """ Add New Site record information into the wo database. """ diff --git a/wo/cli/templates/virtualconf-php7.mustache b/wo/cli/templates/virtualconf-php7.mustache index 1e590de..1ca898d 100644 --- a/wo/cli/templates/virtualconf-php7.mustache +++ b/wo/cli/templates/virtualconf-php7.mustache @@ -6,7 +6,7 @@ server { # listen 80 default_server; {{/multisite}} - server_name {{^vma}}{{^rc}}{{site_name}}{{/rc}}{{/vma}} {{#vma}}vma.*{{/vma}} {{#rc}}webmail.*{{/rc}} {{^vma}}{{^rc}}{{#multisite}}*{{/multisite}}{{^multisite}}www{{/multisite}}.{{site_name}}{{/rc}}{{/vma}}; + server_name {{site_name}} {{#multisite}}*{{/multisite}}{{^multisite}}www{{/multisite}}.{{site_name}}; {{#multisite}} # Uncomment the following line for domain mapping @@ -28,7 +28,7 @@ server { {{/proxy}} {{^proxy}} - {{^vma}}{{^rc}}root {{webroot}}/htdocs;{{/rc}}{{/vma}} + root {{webroot}}/htdocs; {{^proxy}}index {{^static}}index.php{{/static}} index.html index.htm;{{/proxy}} @@ -42,6 +42,6 @@ server { {{#wpsubdir}}include common/wpsubdir.conf;{{/wpsubdir}}{{/static}} {{#wp}}include common/wpcommon-php73.conf;{{/wp}} {{^proxy}}include common/locations-php73.conf;{{/proxy}} - {{^vma}}{{^rc}}include {{webroot}}/conf/nginx/*.conf;{{/rc}}{{/vma}} + include {{webroot}}/conf/nginx/*.conf; {{/proxy}} } diff --git a/wo/cli/templates/virtualconf.mustache b/wo/cli/templates/virtualconf.mustache index b4c52bf..653a5aa 100644 --- a/wo/cli/templates/virtualconf.mustache +++ b/wo/cli/templates/virtualconf.mustache @@ -6,7 +6,7 @@ server { # listen 80 default_server; {{/multisite}} - server_name {{^vma}}{{^rc}}{{site_name}}{{/rc}}{{/vma}} {{#vma}}vma.*{{/vma}} {{#rc}}webmail.*{{/rc}} {{^vma}}{{^rc}}{{#multisite}}*{{/multisite}}{{^multisite}}www{{/multisite}}.{{site_name}}{{/rc}}{{/vma}}; + server_name {{site_name}} {{#multisite}}*{{/multisite}}{{^multisite}}www{{/multisite}}.{{site_name}}; {{#multisite}} # Uncomment the following line for domain mapping @@ -28,7 +28,7 @@ server { {{/proxy}} {{^proxy}} - {{^vma}}{{^rc}}root {{webroot}}/htdocs;{{/rc}}{{/vma}} + root {{webroot}}/htdocs; {{^proxy}}index {{^static}}index.php{{/static}} index.html index.htm;{{/proxy}} @@ -42,6 +42,6 @@ server { {{#wpsubdir}}include common/wpsubdir.conf;{{/wpsubdir}}{{/static}} {{#wp}}include common/wpcommon-php72.conf;{{/wp}} {{^proxy}}include common/locations-php72.conf;{{/proxy}} - {{^vma}}{{^rc}}include {{webroot}}/conf/nginx/*.conf;{{/rc}}{{/vma}} + include {{webroot}}/conf/nginx/*.conf; {{/proxy}} } diff --git a/wo/core/apt_repo.py b/wo/core/apt_repo.py index 478bbbe..4c89dae 100644 --- a/wo/core/apt_repo.py +++ b/wo/core/apt_repo.py @@ -79,12 +79,12 @@ class WORepo(): def add_key(self, keyids, keyserver=None): """ This function adds imports repository keys from keyserver. - default keyserver is hkp://keys.gnupg.net + default keyserver is hkp://keyserver.ubuntu.com user can provide other keyserver with keyserver="hkp://xyz" """ WOShellExec.cmd_exec(self, "gpg --keyserver {serv}" .format(serv=(keyserver or - "hkp://keys.gnupg.net")) + "hkp://keyserver.ubuntu.com")) + " --recv-keys {key}".format(key=keyids)) WOShellExec.cmd_exec(self, "gpg -a --export --armor {0}" .format(keyids)