diff --git a/README.md b/README.md
index 1b8cbe4..8b059ec 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
-
+
-
+
An essential toolset that eases WordPress site and server administration
diff --git a/install b/install
index 05113d3..732770b 100644
--- 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-03
+# Version 3.9.5 - 2019-04-05
# -------------------------------------------------------------------------
readonly wo_version_old="2.2.3"
-readonly wo_version_new="3.9.4.3"
+readonly wo_version_new="3.9.4.4"
# CONTENTS
# ---
# 1. VARIABLES AND DECLARATIONS
@@ -81,7 +81,11 @@ fi
###
# 1 - Define variables for later use
###
-wo_branch="$1"
+if [ -n "$1" ]; then
+ wo_branch="$1"
+else
+ wo_branch="master"
+fi
readonly wo_log_dir=/var/log/wo/
readonly wo_backup_dir=/var/lib/wo-backup/
readonly wo_install_log=/var/log/wo/install.log
@@ -381,10 +385,6 @@ wo_install() {
rm -rf /tmp/easyengine
rm -rf /tmp/wordops
- [ -z "$wo_branch" ] && {
- wo_branch=master
- }
-
git clone -b "$wo_branch" https://github.com/WordOps/WordOps.git /tmp/wordops --quiet
cd /tmp/wordops || exit 1
diff --git a/logo.png b/logo.png
new file mode 100644
index 0000000..2fe842e
Binary files /dev/null and b/logo.png differ
diff --git a/wo/cli/plugins/site.py b/wo/cli/plugins/site.py
index 439bd1a..1c85972 100644
--- a/wo/cli/plugins/site.py
+++ b/wo/cli/plugins/site.py
@@ -753,6 +753,11 @@ class WOSiteUpdateController(CementBaseController):
action='store' or 'store_const',
choices=('on', 'off', 'renew', 'subdomain', 'wildcard'),
const='on', nargs='?')),
+ (['--hsts'],
+ dict(help="configure hsts on site secured with letsencrypt",
+ action='store' or 'store_const',
+ choices=('on', 'off'),
+ const='on', nargs='?')),
(['--proxy'],
dict(help="update to proxy site", nargs='+')),
(['--experimental'],
@@ -1073,6 +1078,16 @@ class WOSiteUpdateController(CementBaseController):
elif pargs.letsencrypt == 'off':
data['letsencrypt'] = False
letsencrypt = False
+ data['hsts'] = False
+ hsts = False
+
+ if pargs.hsts:
+ if pargs.hsts == 'on':
+ data['hsts'] = True
+ hsts = True
+ elif pargs.hsts == 'off':
+ data['hsts'] = False
+ hsts = False
if letsencrypt is check_ssl:
if letsencrypt is False:
@@ -1170,12 +1185,23 @@ class WOSiteUpdateController(CementBaseController):
.format(wo_site_webroot))
httpsRedirect(self, wo_domain)
+ if data['hsts'] is True:
+ if not os.path.isfile(("{0}/conf/nginx/hsts.conf.disabled")
+ .format(wo_site_webroot)):
+ setupHsts(self, wo_domain)
+ else:
+ WOFileUtils.mvfile(self, "{0}/conf/nginx/"
+ "hsts.conf.disabled"
+ .format(wo_site_webroot),
+ '{0}/conf/nginx/hsts.conf'
+ .format(wo_site_webroot))
if not WOService.reload_service(self, 'nginx'):
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):
@@ -1194,6 +1220,12 @@ class WOSiteUpdateController(CementBaseController):
'{0}/conf/nginx/ssl.conf.disabled'
.format(wo_site_webroot))
httpsRedirect(self, wo_domain, False)
+ if os.path.isfile("{0}/conf/nginx/hsts.conf"
+ .format(wo_site_webroot)):
+ WOFileUtils.mvfile(self, "{0}/conf/nginx/hsts.conf"
+ .format(wo_site_webroot),
+ '{0}/conf/nginx/hsts.conf.disabled'
+ .format(wo_site_webroot))
if not WOService.reload_service(self, 'nginx'):
Log.error(self, "service nginx reload failed. "
"check issues with `nginx -t` command")
@@ -1217,6 +1249,16 @@ class WOSiteUpdateController(CementBaseController):
.format(wo_site_webroot))
httpsRedirect(self, wo_domain)
+ if data['hsts'] is True:
+ if not os.path.isfile(("{0}/conf/nginx/hsts.conf.disabled")
+ .format(wo_site_webroot)):
+ setupHsts(self, wo_domain)
+ else:
+ WOFileUtils.mvfile(self, "{0}/conf/nginx/"
+ "hsts.conf.disabled"
+ .format(wo_site_webroot),
+ '{0}/conf/nginx/hsts.conf'
+ .format(wo_site_webroot))
if not WOService.reload_service(self, 'nginx'):
Log.error(self, "service nginx reload failed. "
@@ -1243,6 +1285,14 @@ class WOSiteUpdateController(CementBaseController):
'{0}/conf/nginx/ssl.conf.disabled'
.format(wo_site_webroot))
httpsRedirect(self, wo_domain, False)
+ if os.path.isfile(("{0}/conf/nginx/hsts.conf")
+ .format(wo_site_webroot)):
+ WOFileUtils.mvfile(self, "{0}/conf/nginx/"
+ "hsts.conf"
+ .format(wo_site_webroot),
+ '{0}/conf/nginx/hsts.conf.disabled'
+ .format(wo_site_webroot))
+
if not WOService.reload_service(self, 'nginx'):
Log.error(self, "service nginx reload failed. "
"check issues with `nginx -t` command")
@@ -1269,7 +1319,8 @@ class WOSiteUpdateController(CementBaseController):
"check issues with `nginx -t` command")
updateSiteInfo(self, wo_domain, stype=stype, cache=cache,
- ssl=True if check_site.is_ssl else False, php_version=check_php_version)
+ ssl=True if check_site.is_ssl else False,
+ php_version=check_php_version)
Log.info(self, "Successfully updated site"
" http://{0}".format(wo_domain))
@@ -1327,44 +1378,94 @@ class WOSiteUpdateController(CementBaseController):
Log.debug(self, str(e))
Log.info(self, Log.FAIL + "Update site failed. "
"Check the log for details:"
- " `tail /var/log/wo/wordops.log` and please try again")
+ " `tail /var/log/wo/wordops.log` "
+ "and please try again")
return 1
if ((oldcachetype in ['wpsc', 'basic', 'wpredis'] and
(data['wpfc'])) or (oldsitetype == 'wp' and data['multisite'] and data['wpfc'])):
try:
- plugin_data = '{"log_level":"INFO","log_filesize":5,"enable_purge":1,"enable_map":0,"enable_log":0,"enable_stamp":0,"purge_homepage_on_new":1,"purge_homepage_on_edit":1,"purge_homepage_on_del":1,"purge_archive_on_new":1,"purge_archive_on_edit":0,"purge_archive_on_del":0,"purge_archive_on_new_comment":0,"purge_archive_on_deleted_comment":0,"purge_page_on_mod":1,"purge_page_on_new_comment":1,"purge_page_on_deleted_comment":1,"cache_method":"enable_fastcgi","purge_method":"get_request","redis_hostname":"127.0.0.1","redis_port":"6379","redis_prefix":"nginx-cache:"}'
+ plugin_data = '{"log_level":"INFO","log_filesize":5,'
+ '"enable_purge":1,"enable_map":0,"enable_log":0,'
+ '"enable_stamp":0,"purge_homepage_on_new":1,'
+ '"purge_homepage_on_edit":1,"purge_homepage_on_del":1,'
+ '"purge_archive_on_new":1,"purge_archive_on_edit":0,'
+ '"purge_archive_on_del":0,"purge_archive_on_new_comment":0,'
+ '"purge_archive_on_deleted_comment":0,"purge_page_on_mod":1,'
+ '"purge_page_on_new_comment":1,'
+ '"purge_page_on_deleted_comment":1,'
+ '"cache_method":"enable_fastcgi",'
+ '"purge_method":"get_request",'
+ '"redis_hostname":"127.0.0.1","redis_port":"6379",'
+ '"redis_prefix":"nginx-cache:"}'
setupwp_plugin(
- self, 'nginx-helper', 'rt_wp_nginx_helper_options', plugin_data, data)
+ self, 'nginx-helper',
+ 'rt_wp_nginx_helper_options', plugin_data, data)
except SiteError as e:
Log.debug(self, str(e))
- Log.info(self, Log.FAIL + "Update nginx-helper settings failed. "
+ Log.info(self, Log.FAIL + "Update nginx-helper "
+ "settings failed. "
"Check the log for details:"
- " `tail /var/log/wo/wordops.log` and please try again")
+ " `tail /var/log/wo/wordops.log` "
+ "and please try again")
return 1
elif ((oldcachetype in ['wpsc', 'basic', 'wpfc'] and
- (data['wpredis'])) or (oldsitetype == 'wp' and data['multisite'] and data['wpredis'])):
+ (data['wpredis'])) or (oldsitetype == 'wp' and
+ data['multisite'] and data['wpredis'])):
try:
- plugin_data = '{"log_level":"INFO","log_filesize":5,"enable_purge":1,"enable_map":0,"enable_log":0,"enable_stamp":0,"purge_homepage_on_new":1,"purge_homepage_on_edit":1,"purge_homepage_on_del":1,"purge_archive_on_new":1,"purge_archive_on_edit":0,"purge_archive_on_del":0,"purge_archive_on_new_comment":0,"purge_archive_on_deleted_comment":0,"purge_page_on_mod":1,"purge_page_on_new_comment":1,"purge_page_on_deleted_comment":1,"cache_method":"enable_redis","purge_method":"get_request","redis_hostname":"127.0.0.1","redis_port":"6379","redis_prefix":"nginx-cache:"}'
+ plugin_data = '{"log_level":"INFO","log_filesize":5,'
+ '"enable_purge":1,"enable_map":0,"enable_log":0,'
+ '"enable_stamp":0,"purge_homepage_on_new":1,'
+ '"purge_homepage_on_edit":1,"purge_homepage_on_del":1,'
+ '"purge_archive_on_new":1,"purge_archive_on_edit":0,'
+ '"purge_archive_on_del":0,'
+ '"purge_archive_on_new_comment":0,'
+ '"purge_archive_on_deleted_comment":0,'
+ '"purge_page_on_mod":1,'
+ '"purge_page_on_new_comment":1,'
+ '"purge_page_on_deleted_comment":1,'
+ '"cache_method":"enable_redis",'
+ '"purge_method":"get_request",'
+ '"redis_hostname":"127.0.0.1","redis_port":"6379",'
+ '"redis_prefix":"nginx-cache:"}'
setupwp_plugin(
- self, 'nginx-helper', 'rt_wp_nginx_helper_options', plugin_data, data)
+ self, 'nginx-helper',
+ 'rt_wp_nginx_helper_options', plugin_data, data)
except SiteError as e:
Log.debug(self, str(e))
- Log.info(self, Log.FAIL + "Update nginx-helper settings failed. "
+ Log.info(self, Log.FAIL + "Update nginx-helper "
+ "settings failed. "
"Check the log for details:"
- " `tail /var/log/wo/wordops.log` and please try again")
+ " `tail /var/log/wo/wordops.log` "
+ "and please try again")
return 1
else:
try:
- plugin_data = '{"log_level":"INFO","log_filesize":5,"enable_purge":0,"enable_map":0,"enable_log":0,"enable_stamp":0,"purge_homepage_on_new":1,"purge_homepage_on_edit":1,"purge_homepage_on_del":1,"purge_archive_on_new":1,"purge_archive_on_edit":0,"purge_archive_on_del":0,"purge_archive_on_new_comment":0,"purge_archive_on_deleted_comment":0,"purge_page_on_mod":1,"purge_page_on_new_comment":1,"purge_page_on_deleted_comment":1,"cache_method":"enable_redis","purge_method":"get_request","redis_hostname":"127.0.0.1","redis_port":"6379","redis_prefix":"nginx-cache:"}'
+ plugin_data = '{"log_level":"INFO","log_filesize":5,'
+ '"enable_purge":0,"enable_map":0,"enable_log":0,'
+ '"enable_stamp":0,"purge_homepage_on_new":1,'
+ '"purge_homepage_on_edit":1,"purge_homepage_on_del":1,'
+ '"purge_archive_on_new":1,"purge_archive_on_edit":0,'
+ '"purge_archive_on_del":0,'
+ '"purge_archive_on_new_comment":0,'
+ '"purge_archive_on_deleted_comment":0,'
+ '"purge_page_on_mod":1,"purge_page_on_new_comment":1,'
+ '"purge_page_on_deleted_comment":1,'
+ '"cache_method":"enable_redis",'
+ '"purge_method":"get_request",'
+ '"redis_hostname":"127.0.0.1",'
+ '"redis_port":"6379","redis_prefix":"nginx-cache:"}'
setupwp_plugin(
- self, 'nginx-helper', 'rt_wp_nginx_helper_options', plugin_data, data)
+ self, 'nginx-helper',
+ 'rt_wp_nginx_helper_options', plugin_data, data)
except SiteError as e:
Log.debug(self, str(e))
- Log.info(self, Log.FAIL + "Update nginx-helper settings failed. "
+ Log.info(self, Log.FAIL + "Update nginx-helper "
+ "settings failed. "
"Check the log for details:"
- " `tail /var/log/wo/wordops.log` and please try again")
+ " `tail /var/log/wo/wordops.log` "
+ "and please try again")
return 1
if oldcachetype == 'wpsc' and not data['wpsc']:
@@ -1374,7 +1475,8 @@ class WOSiteUpdateController(CementBaseController):
Log.debug(self, str(e))
Log.info(self, Log.FAIL + "Update site failed."
"Check the log for details:"
- " `tail /var/log/wo/wordops.log` and please try again")
+ " `tail /var/log/wo/wordops.log` "
+ "and please try again")
return 1
if oldcachetype == 'wpredis' and not data['wpredis']:
@@ -1384,7 +1486,8 @@ class WOSiteUpdateController(CementBaseController):
Log.debug(self, str(e))
Log.info(self, Log.FAIL + "Update site failed."
"Check the log for details:"
- " `tail /var/log/wo/wordops.log` and please try again")
+ " `tail /var/log/wo/wordops.log` "
+ "and please try again")
return 1
if oldcachetype != 'wpsc' and data['wpsc']:
@@ -1401,10 +1504,12 @@ class WOSiteUpdateController(CementBaseController):
try:
if installwp_plugin(self, 'redis-cache', data):
# search for wp-config.php
- if WOFileUtils.isexist(self, "{0}/wp-config.php".format(wo_site_webroot)):
+ if WOFileUtils.isexist(self, "{0}/wp-config.php"
+ .format(wo_site_webroot)):
config_path = '{0}/wp-config.php'.format(
wo_site_webroot)
- elif WOFileUtils.isexist(self, "{0}/htdocs/wp-config.php".format(wo_site_webroot)):
+ elif WOFileUtils.isexist(self, "{0}/htdocs/wp-config.php"
+ .format(wo_site_webroot)):
config_path = '{0}/htdocs/wp-config.php'.format(
wo_site_webroot)
else:
diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py
index fb779aa..8b49670 100644
--- a/wo/cli/plugins/site_functions.py
+++ b/wo/cli/plugins/site_functions.py
@@ -96,8 +96,8 @@ def setupdomain(self, data):
Log.info(self, "[" + Log.ENDC + "Done" + Log.OKBLUE + "]")
except CalledProcessError as e:
Log.debug(self, "{0}".format(str(e)))
- Log.info(self, "[" + Log.ENDC + Log.FAIL + "Fail"
- + Log.OKBLUE + "]")
+ Log.info(self, "[" + Log.ENDC + Log.FAIL + "Fail" +
+ Log.OKBLUE + "]")
raise SiteError("created nginx configuration failed for site."
" check with `nginx -t`")
@@ -312,8 +312,8 @@ def setupwordpress(self, data):
"--dbuser=\'{2}\' --dbhost=\'{3}\' "
.format(data['wo_db_name'], wo_wp_prefix,
data['wo_db_user'], data['wo_db_host']
- )
- + "--dbpass=\'{0}\' "
+ ) +
+ "--dbpass=\'{0}\' "
"--extra-php<.* "POST .*/wp-login.php([/\?#\\].*)? HTTP/.*" 200
+ignoreregex =
diff --git a/wo/cli/templates/fail2ban.mustache b/wo/cli/templates/fail2ban.mustache
new file mode 100644
index 0000000..10937f6
--- /dev/null
+++ b/wo/cli/templates/fail2ban.mustache
@@ -0,0 +1,24 @@
+[recidive]
+enabled = true
+
+[nginx-http-auth]
+enabled = true
+
+[nginx-botsearch]
+enabled = true
+
+[wo-wordpress]
+enabled = true
+filter = wo-wordpress
+action = iptables-multiport[name="wo-wordpress", port="http,https"]
+logpath = /var/log/nginx/*access.log
+maxretry = 5
+
+[nginx-forbidden]
+enabled = true
+filter = nginx-forbidden
+port = http,https
+logpath = /var/log/nginx/*error*.log
+findtime = 60
+bantime = 6000
+maxretry = 3
\ No newline at end of file
diff --git a/wo/core/variables.py b/wo/core/variables.py
index ab2eb2b..2aa6237 100644
--- a/wo/core/variables.py
+++ b/wo/core/variables.py
@@ -152,6 +152,8 @@ class WOVariables():
wo_mysql = ["mariadb-server", "percona-toolkit"]
+ wo_fail2ban = "fail2ban"
+
# Redis repo details
if wo_platform_distro == 'ubuntu':
wo_redis_repo = ("ppa:chris-lea/redis-server")