diff --git a/CHANGELOG.md b/CHANGELOG.md index 816b810..b49e736 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - additional argument for letsencrypt : --hsts - Theme for adminer - Credits for tools shipped with WordOps +- Cache exception for Easy Digital Download +- Additional cache exception for Woocommerce +- MySQL monitoring with Netdata +- WordOps-dashboard on 22222 +- Extplorer filemanager #### Changed @@ -41,6 +46,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Increase MySQL users password size to 16 characters - Nginx locations template is the same for php7.2 & 7.3 - backend SSL configuration now stored in /var/www/22222/conf/nginx/ssl.conf +- Install Netdata with static pre-built binaries instead of having to compile it from source #### Fixed @@ -59,6 +65,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - command "wo clean --memcached" - phpredisadmin setup - --hsts flag with basic html site +- hsts flag on site not secure with letsencrypt ### v3.9.4 - 2019-03-15 diff --git a/README.md b/README.md index 36cc13a..e2f5f86 100644 --- a/README.md +++ b/README.md @@ -153,12 +153,13 @@ There is no need to be a developer or a system administrator to contribute to Wo - Source : [EasyEngine](https://github.com/easyengine/easyengine) -Shipped with WordOps +Apps & Tools shipped with WordOps -- Acme client : [Acme.sh](https://github.com/Neilpang/acme.sh) -- WordPress deployment : [WP-CLI](https://github.com/wp-cli/wp-cli) -- Monitoring : [Netdata](https://github.com/netdata/netdata) +- [Acme.sh](https://github.com/Neilpang/acme.sh) +- [WP-CLI](https://github.com/wp-cli/wp-cli) +- [Netdata](https://github.com/netdata/netdata) - [phpMyAdmin](https://www.phpmyadmin.net/) +- [Composer](https://github.com/composer/composer) - [Adminer](https://www.adminer.org/) - [phpRedisAdmin](https://github.com/erikdubbelboer/phpRedisAdmin) - [PHPMemcachedAdmin](https://github.com/elijaa/phpmemcachedadmin) diff --git a/install b/install index 6cafc7f..1ea406b 100755 --- a/install +++ b/install @@ -7,10 +7,10 @@ # Copyright (c) 2019 - WordOps # This script is licensed under M.I.T # ------------------------------------------------------------------------- -# Version 3.9.5 - 2019-04-14 +# Version 3.9.5 - 2019-04-22 # ------------------------------------------------------------------------- readonly wo_version_old="2.2.3" -readonly wo_version_new="3.9.4.5" +readonly wo_version_new="3.9.4.6" # CONTENTS # --- # 1. VARIABLES AND DECLARATIONS @@ -93,8 +93,8 @@ echo "" # 1- Update the apt sewers with fresh info ### [ -z "$wo_travis" ] && { -wo_lib_echo "Updating apt-get repository info" -apt-get update -qq + wo_lib_echo "Updating apt-get repository info" + apt-get update -qq } ### diff --git a/wo/cli/plugins/secure.py b/wo/cli/plugins/secure.py index cb6305a..4312e84 100644 --- a/wo/cli/plugins/secure.py +++ b/wo/cli/plugins/secure.py @@ -50,7 +50,7 @@ class WOSecureController(CementBaseController): """This function secures authentication""" passwd = ''.join([random.choice (string.ascii_letters + string.digits) - for n in range(16)]) + for n in range(24)]) if not self.app.pargs.user_input: username = input("Provide HTTP authentication user " "name [{0}] :".format(WOVariables.wo_user)) @@ -93,16 +93,10 @@ class WOSecureController(CementBaseController): Log.info(self, "Please Enter valid port number :") port = input("WordOps admin port [22222]:") self.app.pargs.user_input = port - if WOVariables.wo_platform_distro == 'ubuntu': - WOShellExec.cmd_exec(self, "sed -i \"s/listen.*/listen " - "{port} default_server ssl http2;/\" " - "/etc/nginx/sites-available/22222" - .format(port=self.app.pargs.user_input)) - if WOVariables.wo_platform_distro == 'debian': - WOShellExec.cmd_exec(self, "sed -i \"s/listen.*/listen " - "{port} default_server ssl http2;/\" " - "/etc/nginx/sites-available/22222" - .format(port=self.app.pargs.user_input)) + WOShellExec.cmd_exec(self, "sed -i \"s/listen.*/listen " + "{port} default_server ssl http2;/\" " + "/etc/nginx/sites-available/22222" + .format(port=self.app.pargs.user_input)) WOGit.add(self, ["/etc/nginx"], msg="Adding changed secure port into Git") if not WOService.reload_service(self, 'nginx'): diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py index 17fa3eb..86ecb10 100644 --- a/wo/cli/plugins/site.py +++ b/wo/cli/plugins/site.py @@ -673,22 +673,14 @@ class WOSiteCreateController(CementBaseController): "`tail /var/log/wo/wordops.log` and please try again") if self.app.pargs.letsencrypt == "on": - if self.app.pargs.hsts: - data['letsencrypt'] = True - letsencrypt = True - data['hsts'] = True - hsts = True - else: - data['letsencrypt'] = True - letsencrypt = True - data['hsts'] = False - hsts = False + data['letsencrypt'] = True + letsencrypt = True if data['letsencrypt'] is True: setupLetsEncrypt(self, wo_domain) httpsRedirect(self, wo_domain) - if data['hsts'] is True: + if self.app.pargs.hsts: setupHsts(self, wo_domain) if not WOService.reload_service(self, 'nginx'): @@ -713,15 +705,11 @@ class WOSiteCreateController(CementBaseController): data['letsencrypt'] = True letsencrypt = True - if self.app.pargs.hsts == 'on': - data['hsts'] = True - hsts = True - if data['letsencrypt'] is True: setupLetsEncryptSubdomain(self, wo_domain) httpsRedirect(self, wo_domain) - if data['hsts'] is True: + if self.app.pargs.hsts: setupHsts(self, wo_domain) if not WOService.reload_service(self, 'nginx'): @@ -902,7 +890,8 @@ class WOSiteUpdateController(CementBaseController): if (pargs.hsts and not (pargs.html or pargs.php or pargs.php73 or pargs.mysql or pargs.wp or pargs.wpfc or pargs.wpsc or - pargs.wpsubdir or pargs.wpsubdomain)): + pargs.wpsubdir or pargs.wpsubdomain or + pargs.password)): try: setupHsts(self, wo_domain) except SiteError as e: @@ -918,8 +907,8 @@ class WOSiteUpdateController(CementBaseController): 'proxy', 'wp', 'php73']) or (stype == 'wpsubdir' and oldsitetype in ['wpsubdomain']) or (stype == 'wpsubdomain' and oldsitetype in ['wpsubdir']) or - (stype == oldsitetype and cache == oldcachetype) and - not pargs.php73 or pargs.hsts): + (stype == oldsitetype and cache == oldcachetype) and not + (pargs.php73 or pargs.hsts or pargs.letsencrypt)): Log.info(self, Log.FAIL + "can not update {0} {1} to {2} {3}". format(oldsitetype, oldcachetype, stype, cache)) return 1 diff --git a/wo/cli/plugins/stack.py b/wo/cli/plugins/stack.py index 92a3331..003ab42 100644 --- a/wo/cli/plugins/stack.py +++ b/wo/cli/plugins/stack.py @@ -68,6 +68,8 @@ class WOStackController(CementBaseController): (['--netdata'], dict(help='Install Netdata monitoring suite', action='store_true')), + (['--dashboard'], + dict(help='Install WordOps dashboard', action='store_true')), (['--adminer'], dict(help='Install Adminer stack', action='store_true')), (['--utils'], @@ -519,7 +521,8 @@ class WOStackController(CementBaseController): else: self.msg = (self.msg + ["HTTP Auth User " "Name: WordOps"] + - ["HTTP Auth Password : {0}".format(passwd)]) + ["HTTP Auth Password : {0}" + .format(passwd)]) else: WOService.restart_service(self, 'nginx') @@ -1014,7 +1017,8 @@ class WOStackController(CementBaseController): if len(packages): if any('/usr/local/bin/wp' == x[1] for x in packages): - Log.debug(self, "Setting Privileges to /usr/local/bin/wp file ") + Log.debug(self, "Setting Privileges" + " to /usr/local/bin/wp file ") WOFileUtils.chmod(self, "/usr/local/bin/wp", 0o775) if any('/tmp/pma.tar.gz' == x[1] @@ -1029,8 +1033,7 @@ class WOStackController(CementBaseController): .format(WOVariables.wo_webroot)) os.makedirs('{0}22222/htdocs/db' .format(WOVariables.wo_webroot)) - if not os.path.exists('{0}22222/htdocs/db/' - 'pma/phpmyadmin-STABLE' + if not os.path.exists('{0}22222/htdocs/db/pma/' .format(WOVariables.wo_webroot)): shutil.move('/tmp/phpmyadmin-STABLE/', '{0}22222/htdocs/db/pma/' @@ -1069,13 +1072,12 @@ class WOStackController(CementBaseController): "[\'Servers\'][$i][\'host\'] = \'{0}\';" .format(WOVariables.wo_mysql_host)) Log.debug(self, 'Setting Privileges of webroot permission to ' - '{0}22222/htdocs/db/pma file ' - .format(WOVariables.wo_webroot)) - WOFileUtils.chown(self, '{0}22222' - .format(WOVariables.wo_webroot), + '{0}22222/htdocs/db/pma file '.format(WOVariables.wo_webroot)) + WOFileUtils.chown(self, '{0}22222'.format(WOVariables.wo_webroot), WOVariables.wo_php_user, WOVariables.wo_php_user, recursive=True) + # composer install and phpmyadmin update if any('/tmp/composer-install' == x[1] for x in packages): @@ -1092,16 +1094,79 @@ class WOStackController(CementBaseController): # netdata install if any('/tmp/kickstart.sh' == x[1] for x in packages): - if not os.path.exists('/etc/netdata'): + if ((not os.path.exists('/opt/netdata')) and + (not os.path.exists('/etc/netdata'))): Log.info(self, "Installing Netdata, please wait...") WOShellExec.cmd_exec(self, "bash /tmp/kickstart.sh " - "--dont-wait --no-updates") - WOFileUtils.searchreplace(self, "/usr/lib/netdata/conf.d/" - "health_alarm_notify.conf", - 'SEND_EMAIL="YES"', - 'SEND_EMAIL="NO"') - WOService.restart_service(self, 'netdata') + "--dont-wait") + # disable mail notifications + WOFileUtils.searchreplace(self, "/opt/netdata/usr/" + "lib/netdata/conf.d/" + "health_alarm_notify.conf", + 'SEND_EMAIL="YES"', + 'SEND_EMAIL="NO"') + # check if mysql credentials are available + if os.path.isfile('/etc/mysql/conf.d/my.cnf'): + try: + WOMysql.execute(self, + "create user " + "'netdata'@'localhost';", + log=False) + WOMysql.execute(self, + "grant usage on *.* to " + "'netdata'@'localhost';", + log=False) + WOMysql.execute(self, + "flush privileges;", + log=False) + except StatementExcecutionError as e: + Log.info( + self, "fail to setup mysql user for netdata") + WOService.restart_service(self, 'netdata') + # WordOps Dashboard + if any('/tmp/wo-dashboard.tar.gz' == x[1] + for x in packages): + if not os.path.isfile('{0}22222/htdocs/index.php' + .format(WOVariables.wo_webroot)): + Log.debug(self, "Extracting wo-dashboard.tar.gz " + "to location {0}22222/htdocs/" + .format(WOVariables.wo_webroot)) + WOExtract.extract(self, '/tmp/wo-dashboard.tar.gz', + '{0}22222/htdocs' + .format(WOVariables.wo_webroot)) + Log.debug(self, "Setting Privileges to " + "{0}22222/htdocs" + .format(WOVariables.wo_webroot)) + WOFileUtils.chown(self, '{0}22222' + .format(WOVariables.wo_webroot), + WOVariables.wo_php_user, + WOVariables.wo_php_user, + recursive=True) + + # Extplorer FileManager + if any('/tmp/extplorer.tar.gz' == x[1] + for x in packages): + if not os.path.exists('{0}22222/htdocs/files' + .format(WOVariables.wo_webroot)): + os.makedirs('{0}22222/htdocs/files' + .format(WOVariables.wo_webroot)) + Log.debug(self, "Extracting explorer.tar.gz " + "to location {0}22222/htdocs/" + .format(WOVariables.wo_webroot)) + WOExtract.extract(self, '/tmp/extplorer.tar.gz', + '{0}22222/htdocs/files' + .format(WOVariables.wo_webroot)) + Log.debug(self, "Setting Privileges to " + "{0}22222/htdocs/files" + .format(WOVariables.wo_webroot)) + WOFileUtils.chown(self, '{0}22222' + .format(WOVariables.wo_webroot), + WOVariables.wo_php_user, + WOVariables.wo_php_user, + recursive=True) + + # phpmemcachedadmin if any('/tmp/memcached.tar.gz' == x[1] for x in packages): Log.debug(self, "Extracting memcached.tar.gz to location" @@ -1188,7 +1253,8 @@ class WOStackController(CementBaseController): ' *.* to \'anemometer\'' '@\'{0}\' IDENTIFIED' ' BY \'{1}\''.format(self.app.config.get - ('mysql', 'grant-host'), + ('mysql', + 'grant-host'), chars)) Log.debug(self, "grant all on slow-query-log.*" " to anemometer@root_user" @@ -1216,7 +1282,7 @@ class WOStackController(CementBaseController): if any('/usr/bin/pt-query-advisor' == x[1] for x in packages): WOFileUtils.chmod(self, "/usr/bin/pt-query-advisor", 0o775) - + # ph if any('/tmp/pra.tar.gz' == x[1] for x in packages): if not os.path.exists('{0}22222/htdocs/cache/redis' @@ -1254,6 +1320,7 @@ class WOStackController(CementBaseController): (not self.app.pargs.phpmyadmin) and (not self.app.pargs.composer) and (not self.app.pargs.netdata) and + (not self.app.pargs.dashboard) and (not self.app.pargs.adminer) and (not self.app.pargs.utils) and (not self.app.pargs.redis) and (not self.app.pargs.phpredisadmin) and @@ -1280,7 +1347,9 @@ class WOStackController(CementBaseController): self.app.pargs.composer = True self.app.pargs.utils = True self.app.pargs.netdata = True + self.app.pargs.dashboard = True + # Redis if self.app.pargs.redis: if not WOAptGet.is_installed(self, 'redis-server'): apt_packages = apt_packages + WOVariables.wo_redis @@ -1288,6 +1357,7 @@ class WOStackController(CementBaseController): else: Log.info(self, "Redis already installed") + # Nginx if self.app.pargs.nginx: Log.debug(self, "Setting apt_packages variable for Nginx") @@ -1411,10 +1481,24 @@ class WOStackController(CementBaseController): Log.debug(self, "Setting packages variable for Netdata") if not os.path.exists('/opt/netdata'): packages = packages + [['https://my-netdata.io/' - 'kickstart.sh', + 'kickstart-static64.sh', '/tmp/kickstart.sh', 'Netdata']] + # WordOps Dashboard + if self.app.pargs.dashboard: + Log.debug(self, "Setting packages variable for WO-Dashboard") + packages = packages + \ + [["https://github.com/WordOps/" + "wordops-dashboard/releases/" + "download/v1.0/wo-dashboard.tar.gz", + "/tmp/wo-dashboard.tar.gz", + "WordOps Dashboard"], + ["https://github.com/soerennb/" + "extplorer/archive/v2.1.11.tar.gz", + "/tmp/extplorer.tar.gz", + "Extplorer"]] + # UTILS if self.app.pargs.utils: Log.debug(self, "Setting packages variable for utils") @@ -1706,7 +1790,8 @@ class WOStackController(CementBaseController): Log.debug(self, "Purge apt_packages variable of Nginx") apt_packages = apt_packages + WOVariables.wo_nginx else: - Log.error(self, "Cannot Purge! Nginx Stable version not found.") + Log.error(self, "Cannot Purge! " + "Nginx Stable version not found.") # PHP if self.app.pargs.php: diff --git a/wo/cli/templates/kerneltweaks-script.mustache b/wo/cli/templates/kerneltweaks-script.mustache new file mode 100644 index 0000000..4071530 --- /dev/null +++ b/wo/cli/templates/kerneltweaks-script.mustache @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Kernel tweak script launched by kerneltweak systemd service +# script path after installation /opt/kerneltweaks.sh + +echo 1 >/sys/kernel/mm/ksm/run +echo 1000 >/sys/kernel/mm/ksm/sleep_millisecs +echo never > /sys/kernel/mm/transparent_hugepage/enabled diff --git a/wo/cli/templates/kerneltweaks-service.mustache b/wo/cli/templates/kerneltweaks-service.mustache new file mode 100644 index 0000000..60f8de9 --- /dev/null +++ b/wo/cli/templates/kerneltweaks-service.mustache @@ -0,0 +1,13 @@ +[Unit] +Description=Linux kernel tweaks + +# append here other services you want netdata to wait for them to start +After=network.target + +[Service] +Type=simple +User=root +ExecStart=/opt/kerneltweaks.sh + +[Install] +WantedBy=multi-user.target diff --git a/wo/cli/templates/map-wp.mustache b/wo/cli/templates/map-wp.mustache index a289cee..5cdb3d9 100644 --- a/wo/cli/templates/map-wp.mustache +++ b/wo/cli/templates/map-wp.mustache @@ -19,6 +19,7 @@ map $http_cookie $cookie_no_cache { "~*woocommerce_cart_hash" 1; "~*wptouch_switch_toogle" 1; "~*comment_author_email_" 1; + "~*edd" 1; } # do not cache the following uri @@ -33,6 +34,16 @@ map $request_uri $uri_no_cache { "~*/wp-comments-popup.php" 1; "~*/wp-links-opml.php" 1; "~*/xmlrpc.php" 1; + "~*/checkout" 1; + "~*/edd_action" 1; + "~*/add_to_cart/" 1; + "~*/cart/" 1; + "~*/my-account/" 1; + "~*/checkout/" 1; + "~*/addons/" 1; + "~*/wc-api/*" 1; + "~*/logout/" 1; + "~*/lost-password/" 1; } # do not cache requests with query strings @@ -49,6 +60,6 @@ map $http_request_no_cache$cookie_no_cache$uri_no_cache$query_no_cache $skip_cac # map $skip_cache with $cache_uri for --wpsc stack map $skip_cache $cache_uri { - default 'null cache'; 0 $request_uri; + default 'null cache'; }