Updating configuration (#197)

#### Added

- [ACME] Display warning about sudo usage when issuing certificate with DNS API validation (require `sudo -E`)

#### Changed

- [ACME] Resolve domain IP over HTTPS with Cloudflare DNS Resolver
- [CORE] Cement Framework updated to v2.10.2
- [SITE] database name = 0 to 16 characters from the site name + 4 randomly generated character
- [SITE] database user = 0 to 12 characters from the site name + 4 randomy generated character
- [STACK] Improve sysctl tweak deployment

#### Fixed

- [SITE] https redirection missing on subdomains sites
- Issues with digitalocean mariadb repository
- Cement Framework output handler issues
- [CLEAN] check if Nginx is installed before purging fastcgi or opcache
This commit is contained in:
VirtuBox
2019-11-11 19:06:11 +01:00
committed by GitHub
parent 8698332013
commit b771b2578e
59 changed files with 838 additions and 961 deletions

View File

@@ -37,9 +37,8 @@ class WOCleanController(CementBaseController):
@expose(hide=True)
def default(self):
pargs = self.app.pargs
if (not (pargs.all or pargs.fastcgi
or pargs.opcache or
pargs.redis)):
if ((not pargs.all) and (not pargs.fastcgi) and
(not pargs.opcache) and (not pargs.redis)):
self.clean_fastcgi()
if pargs.all:
self.clean_fastcgi()
@@ -63,7 +62,8 @@ class WOCleanController(CementBaseController):
@expose(hide=True)
def clean_fastcgi(self):
if(os.path.isdir("/var/run/nginx-cache")):
if(os.path.isdir("/var/run/nginx-cache") and
os.path.exists('/usr/sbin/nginx')):
Log.info(self, "Cleaning NGINX FastCGI cache")
WOShellExec.cmd_exec(self, "rm -rf /var/run/nginx-cache/*")
WOService.restart_service(self, 'nginx')
@@ -72,21 +72,24 @@ class WOCleanController(CementBaseController):
@expose(hide=True)
def clean_opcache(self):
try:
Log.info(self, "Cleaning opcache")
opgui = requests.get(
"https://127.0.0.1:22222/cache/opcache/opgui.php?reset=1")
if opgui.status_code != '200':
Log.warn(self, 'Cleaning opcache failed')
except Exception as e:
Log.debug(self, "{0}".format(e))
Log.debug(self, "Unable hit url, "
" https://127.0.0.1:22222/cache/opcache/"
"opgui.php?reset=1,"
" please check you have admin tools installed")
Log.debug(self, "please check you have admin tools installed,"
" or install them with `wo stack install --admin`")
Log.error(self, "Unable to clean opcache", False)
if (os.path.exists('/usr/sbin/nginx') and
os.path.exists(
'/var/www/22222/htdocs/cache/opcache/opgui.php')):
try:
Log.info(self, "Cleaning opcache")
opgui = requests.get(
"https://127.0.0.1:22222/cache/opcache/opgui.php?reset=1")
if opgui.status_code != '200':
Log.warn(self, 'Cleaning opcache failed')
except Exception as e:
Log.debug(self, "{0}".format(e))
Log.debug(self, "Unable hit url, "
" https://127.0.0.1:22222/cache/opcache/"
"opgui.php?reset=1,"
" please check you have admin tools installed")
Log.debug(self, "please check you have admin tools installed,"
" or install them with `wo stack install --admin`")
Log.error(self, "Unable to clean opcache", False)
def load(app):

View File

@@ -733,8 +733,11 @@ class WOSiteCreateController(CementBaseController):
Log.debug(self, "Going to issue Let's Encrypt certificate")
acmedata = dict(acme_domains, dns=False, acme_dns='dns_cf',
dnsalias=False, acme_alias='', keylength='')
acmedata['keylength'] = self.app.config.get('letsencrypt',
'keylength')
if self.app.config.has_section('letsencrypt'):
acmedata['keylength'] = self.app.config.get(
'letsencrypt', 'keylength')
else:
acmedata['keylength'] = 'ec-384'
if pargs.dns:
Log.debug(self, "DNS validation enabled")
acmedata['dns'] = True
@@ -813,11 +816,11 @@ class WOSiteCreateController(CementBaseController):
if WOAcme.setupletsencrypt(
self, acme_domains, acmedata):
WOAcme.deploycert(self, wo_domain)
httpsRedirect(self, wo_domain, True, acme_wildcard)
if pargs.hsts:
SSL.setuphsts(self, wo_domain)
httpsRedirect(self, wo_domain, True, acme_wildcard)
SSL.siteurlhttps(self, wo_domain)
if not WOService.reload_service(self, 'nginx'):
Log.error(self, "service nginx reload failed. "
@@ -1594,7 +1597,7 @@ 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,
ssl=(bool(check_site.is_ssl)),
php_version=check_php_version)
Log.info(self, "Successfully updated site"
@@ -1973,7 +1976,10 @@ class WOSiteDeleteController(CementBaseController):
if wo_site_type in ['mysql', 'wp', 'wpsubdir', 'wpsubdomain']:
wo_db_name = check_site.db_name
wo_db_user = check_site.db_user
wo_mysql_grant_host = self.app.config.get('mysql', 'grant-host')
if self.app.config.has_section('mysql'):
wo_mysql_grant_host = self.app.config.get('mysql', 'grant-host')
else:
wo_mysql_grant_host = 'localhost'
if wo_db_name == 'deleted':
mark_db_deleted = True
if pargs.all:

View File

@@ -149,9 +149,15 @@ def setupdatabase(self, data):
string.ascii_lowercase +
string.digits, 24)))
wo_replace_dot = wo_domain_name.replace('.', '')
prompt_dbname = self.app.config.get('mysql', 'db-name')
prompt_dbuser = self.app.config.get('mysql', 'db-user')
wo_mysql_grant_host = self.app.config.get('mysql', 'grant-host')
if self.app.config.has_section('mysql'):
prompt_dbname = self.app.config.get('mysql', 'db-name')
prompt_dbuser = self.app.config.get('mysql', 'db-user')
wo_mysql_grant_host = self.app.config.get('mysql', 'grant-host')
else:
prompt_dbname = False
prompt_dbuser = False
wo_mysql_grant_host = 'localhost'
wo_db_name = ''
wo_db_username = ''
wo_db_password = ''
@@ -165,7 +171,7 @@ def setupdatabase(self, data):
if not wo_db_name:
wo_db_name = wo_replace_dot
wo_db_name = (wo_db_name[0:8] + generate_random())
wo_db_name = (wo_db_name[0:16] + generate_random())
if prompt_dbuser == 'True' or prompt_dbuser == 'true':
try:
@@ -179,7 +185,7 @@ def setupdatabase(self, data):
if not wo_db_username:
wo_db_username = wo_replace_dot
wo_db_username = (wo_db_name[0:8] + generate_random())
wo_db_username = (wo_db_name[0:12] + generate_random())
if not wo_db_password:
wo_db_password = wo_random_pass
@@ -189,8 +195,8 @@ def setupdatabase(self, data):
try:
if WOMysql.check_db_exists(self, wo_db_name):
Log.debug(self, "Database already exists, Updating DB_NAME .. ")
wo_db_name = (wo_db_name[0:8] + generate_random())
wo_db_username = (wo_db_name[0:8] + generate_random())
wo_db_name = (wo_db_name[0:16] + generate_random())
wo_db_username = (wo_db_name[0:12] + generate_random())
except MySQLConnectionError:
raise SiteError("MySQL Connectivity problem occured")
@@ -237,10 +243,16 @@ def setupdatabase(self, data):
def setupwordpress(self, data, vhostonly=False):
wo_domain_name = data['site_name']
wo_site_webroot = data['webroot']
prompt_wpprefix = self.app.config.get('wordpress', 'prefix')
wo_wp_user = self.app.config.get('wordpress', 'user')
wo_wp_pass = self.app.config.get('wordpress', 'password')
wo_wp_email = self.app.config.get('wordpress', 'email')
if self.app.config.has_section('wordpress'):
prompt_wpprefix = self.app.config.get('wordpress', 'prefix')
wo_wp_user = self.app.config.get('wordpress', 'user')
wo_wp_pass = self.app.config.get('wordpress', 'password')
wo_wp_email = self.app.config.get('wordpress', 'email')
else:
prompt_wpprefix = False
wo_wp_user = ''
wo_wp_pass = ''
wo_wp_email = ''
# Random characters
wo_random_pass = (''.join(random.sample(string.ascii_uppercase +
string.ascii_lowercase +
@@ -380,10 +392,7 @@ def setupwordpress(self, data, vhostonly=False):
for wp_conf in wp_conf_variables:
wp_var = wp_conf[0]
wp_val = wp_conf[1]
if wp_val == 'true' or wp_val == 'false':
var_raw = True
else:
var_raw = False
var_raw = (bool(wp_val == 'true' or wp_val == 'false'))
try:
WOShellExec.cmd_exec(
self, "/bin/bash -c \"{0} --allow-root "
@@ -1195,7 +1204,7 @@ def generate_random_pass():
def generate_random():
wo_random10 = (''.join(random.sample(string.ascii_uppercase +
string.ascii_lowercase +
string.digits, 8)))
string.digits, 4)))
return wo_random10

View File

@@ -124,7 +124,7 @@ class WOStackController(CementBaseController):
(not pargs.cheat) and (not pargs.nanorc) and
(not pargs.ufw) and (not pargs.ngxblocker) and
(not pargs.phpredisadmin) and (not pargs.sendmail) and
(not pargs.php73)):
(not pargs.php73) and (not pargs.all)):
pargs.web = True
pargs.admin = True
pargs.fail2ban = True
@@ -563,7 +563,7 @@ class WOStackController(CementBaseController):
(not pargs.cheat) and (not pargs.nanorc) and
(not pargs.ufw) and (not pargs.ngxblocker) and
(not pargs.phpredisadmin) and (not pargs.sendmail) and
(not pargs.php73)):
(not pargs.php73) and (not pargs.all)):
self.app.args.print_help()
if pargs.all:
@@ -849,7 +849,7 @@ class WOStackController(CementBaseController):
(not pargs.cheat) and (not pargs.nanorc) and
(not pargs.ufw) and (not pargs.ngxblocker) and
(not pargs.phpredisadmin) and (not pargs.sendmail) and
(not pargs.php73)):
(not pargs.php73) and (not pargs.all)):
self.app.args.print_help()
if pargs.all:

View File

@@ -29,9 +29,9 @@ def pre_pref(self, apt_packages):
# add mariadb repository excepted on raspbian and ubuntu 19.04
if (not WOVar.wo_distro == 'raspbian'):
Log.info(self, "Adding repository for MySQL, please wait...")
mysql_pref = ("Package: *\nPin: origin "
"sfo1.mirrors.digitalocean.com"
"\nPin-Priority: 1000\n")
mysql_pref = (
"Package: *\nPin: origin mariadb.mirrors.ovh.net"
"\nPin-Priority: 1000\n")
with open('/etc/apt/preferences.d/'
'MariaDB.pref', 'w') as mysql_pref_file:
mysql_pref_file.write(mysql_pref)
@@ -215,25 +215,24 @@ def post_pref(self, apt_packages, packages, upgrade=False):
self, '{0}/upstream.conf'.format(ngxcnf),
'upstream.mustache', data, overwrite=True)
data = dict(phpconf=True if
WOAptGet.is_installed(self, 'php7.2-fpm')
else False)
WOTemplate.deploy(self,
'{0}/stub_status.conf'.format(ngxcnf),
'stub_status.mustache', data)
data = dict(phpconf=(
bool(WOAptGet.is_installed(self, 'php7.2-fpm'))))
WOTemplate.deploy(
self, '{0}/stub_status.conf'.format(ngxcnf),
'stub_status.mustache', data)
data = dict()
WOTemplate.deploy(self,
'{0}/webp.conf'.format(ngxcnf),
'webp.mustache', data, overwrite=False)
WOTemplate.deploy(
self, '{0}/webp.conf'.format(ngxcnf),
'webp.mustache', data, overwrite=False)
WOTemplate.deploy(self,
'{0}/cloudflare.conf'.format(ngxcnf),
'cloudflare.mustache', data)
WOTemplate.deploy(
self, '{0}/cloudflare.conf'.format(ngxcnf),
'cloudflare.mustache', data)
WOTemplate.deploy(self,
'{0}/map-wp-fastcgi-cache.conf'.format(
ngxcnf),
'map-wp.mustache', data)
WOTemplate.deploy(
self,
'{0}/map-wp-fastcgi-cache.conf'.format(ngxcnf),
'map-wp.mustache', data)
except CommandExecutionError as e:
Log.debug(self, "{0}".format(e))
@@ -1401,13 +1400,14 @@ def post_pref(self, apt_packages, packages, upgrade=False):
Log.debug(self, "{0}".format(e))
Log.error(self, "failed to configure Anemometer",
exit=False)
if self.app.config.has_section('mysql'):
wo_grant_host = self.app.config.get('mysql', 'grant-host')
else:
wo_grant_host = 'localhost'
WOMysql.execute(self, 'grant select on'
' *.* to \'anemometer\''
'@\'{0}\' IDENTIFIED'
' BY \'{1}\''.format(self.app.config.get
('mysql',
'grant-host'),
' BY \'{1}\''.format(wo_grant_host,
chars))
Log.debug(self, "grant all on slow-query-log.*"
" to anemometer@root_user"
@@ -1447,25 +1447,35 @@ def post_pref(self, apt_packages, packages, upgrade=False):
def pre_stack(self):
"""Inital server configuration and tweak"""
# wo sysctl tweaks
# check system type
wo_arch = os.uname()[4]
if os.path.isfile('/proc/1/environ'):
# detect lxc containers
wo_lxc = WOFileUtils.grepcheck(
self, '/proc/1/environ', 'container=lxc')
# detect wsl
wo_wsl = WOFileUtils.grepcheck(
self, '/proc/1/environ', 'wsl')
else:
wo_wsl = True
wo_lxc = True
# remove old sysctl tweak
if os.path.isfile('/etc/sysctl.d/60-ubuntu-nginx-web-server.conf'):
WOFileUtils.rm(self, '/etc/sysctl.d/60-ubuntu-nginx-web-server.conf')
WOFileUtils.rm(
self, '/etc/sysctl.d/60-ubuntu-nginx-web-server.conf')
# check if version.txt exist
if os.path.exists('/var/lib/wo/version.txt'):
with open('/var/lib/wo/version.txt',
mode='r', encoding='utf-8') as wo_ver:
# check version written in version.txt
wo_check = bool(wo_ver.read().strip() ==
'{0}'.format(WOVar.wo_version))
else:
wo_check = False
if wo_check is False:
# wo sysctl tweaks
# check system type
wo_arch = bool(os.uname()[4] == 'x86_x64')
if os.path.isfile('/proc/1/environ'):
# detect lxc containers
wo_lxc = WOFileUtils.grepcheck(
self, '/proc/1/environ', 'container=lxc')
# detect wsl
wo_wsl = WOFileUtils.grepcheck(
self, '/proc/1/environ', 'wsl')
else:
wo_wsl = True
wo_lxc = True
if wo_arch == 'x86_64':
if (wo_lxc is not True) and (wo_wsl is not True):
if (wo_lxc is not True) and (wo_wsl is not True) and (wo_arch is True):
data = dict()
WOTemplate.deploy(
self, '/etc/sysctl.d/60-wo-tweaks.conf',
@@ -1474,58 +1484,74 @@ def pre_stack(self):
if (WOVar.wo_platform_codename == 'bionic' or
WOVar.wo_platform_codename == 'disco' or
WOVar.wo_platform_codename == 'buster'):
if WOShellExec.cmd_exec(self, 'modprobe tcp_bbr'):
with open("/etc/modules-load.d/bbr.conf",
encoding='utf-8', mode='w') as bbr_file:
try:
WOShellExec.cmd_exec(
self, 'modprobe tcp_bbr')
with open(
"/etc/modules-load.d/bbr.conf",
encoding='utf-8', mode='w') as bbr_file:
bbr_file.write('tcp_bbr')
with open("/etc/sysctl.d/60-wo-tweaks.conf",
encoding='utf-8', mode='a') as sysctl_file:
with open(
"/etc/sysctl.d/60-wo-tweaks.conf",
encoding='utf-8', mode='a') as sysctl_file:
sysctl_file.write(
'\nnet.ipv4.tcp_congestion_control = bbr'
'\nnet.ipv4.tcp_notsent_lowat = 16384')
except OSError as e:
Log.debug(self, str(e))
Log.warn(self, "failed to tweak sysctl")
else:
if WOShellExec.cmd_exec(self, 'modprobe tcp_htcp'):
with open("/etc/modules-load.d/htcp.conf",
encoding='utf-8', mode='w') as bbr_file:
try:
WOShellExec.cmd_exec(
self, 'modprobe tcp_htcp')
with open(
"/etc/modules-load.d/htcp.conf",
encoding='utf-8', mode='w') as bbr_file:
bbr_file.write('tcp_htcp')
with open("/etc/sysctl.d/60-wo-tweaks.conf",
encoding='utf-8', mode='a') as sysctl_file:
with open(
"/etc/sysctl.d/60-wo-tweaks.conf",
encoding='utf-8', mode='a') as sysctl_file:
sysctl_file.write(
'\nnet.ipv4.tcp_congestion_control = htcp')
except OSError as e:
Log.debug(self, str(e))
Log.warn(self, "failed to tweak sysctl")
# apply sysctl tweaks
WOShellExec.cmd_exec(
self, 'sysctl -eq -p /etc/sysctl.d/60-wo-tweaks.conf')
# sysctl tweak service
data = dict()
if not os.path.isfile('/opt/wo-kernel.sh'):
WOTemplate.deploy(self, '/opt/wo-kernel.sh',
'wo-kernel-script.mustache', data)
if not os.path.isfile('/lib/systemd/system/wo-kernel.service'):
WOTemplate.deploy(
self, '/lib/systemd/system/wo-kernel.service',
'wo-kernel-service.mustache', data)
WOShellExec.cmd_exec(self, 'systemctl enable wo-kernel.service')
WOService.start_service(self, 'wo-kernel')
# open_files_limit tweak
if not WOFileUtils.grepcheck(self, '/etc/security/limits.conf', '500000'):
with open("/etc/security/limits.conf",
encoding='utf-8', mode='w') as limit_file:
limit_file.write(
'* hard nofile 500000\n'
'* soft nofile 500000\n'
'root hard nofile 500000\n'
'root soft nofile 500000\n')
# custom motd-news
data = dict()
# check if update-motd.d directory exist
if os.path.isdir('/etc/update-motd.d/'):
if not os.path.isfile('/etc/update-motd.d/98-wo-update'):
# sysctl tweak service
data = dict()
if not os.path.isfile('/opt/wo-kernel.sh'):
WOTemplate.deploy(self, '/opt/wo-kernel.sh',
'wo-kernel-script.mustache', data)
if not os.path.isfile('/lib/systemd/system/wo-kernel.service'):
WOTemplate.deploy(
self, '/lib/systemd/system/wo-kernel.service',
'wo-kernel-service.mustache', data)
WOShellExec.cmd_exec(self, 'systemctl enable wo-kernel.service')
WOService.start_service(self, 'wo-kernel')
# open_files_limit tweak
if not WOFileUtils.grepcheck(self,
'/etc/security/limits.conf', '500000'):
with open("/etc/security/limits.conf",
encoding='utf-8', mode='a') as limit_file:
limit_file.write(
'* hard nofile 500000\n'
'* soft nofile 500000\n'
'root hard nofile 500000\n'
'root soft nofile 500000\n')
# custom motd-news
data = dict()
# check if update-motd.d directory exist
if os.path.isdir('/etc/update-motd.d/'):
# render custom motd template
WOTemplate.deploy(
self, '/etc/update-motd.d/98-wo-update',
'wo-update.mustache', data)
WOFileUtils.chmod(
self, "/etc/update-motd.d/98-wo-update", 0o755)
# restart motd-news service if available
if os.path.isfile('/lib/systemd/system/motd-news.service'):
WOService.restart_service(self, 'motd-news')
with open('/var/lib/wo/version.txt',
mode='w', encoding='utf-8') as wo_ver:
wo_ver.write('{0}'.format(WOVar.wo_version))

View File

@@ -65,9 +65,10 @@ class WOUpdateController(CementBaseController):
wo_current = ("v{0}".format(WOVar.wo_version))
wo_latest = WODownload.latest_release(self, "WordOps/WordOps")
if wo_current == wo_latest:
Log.error(
Log.info(
self, "WordOps {0} is already installed"
.format(wo_latest))
self.app.close(0)
if not os.path.isdir('/var/lib/wo/tmp'):
os.makedirs('/var/lib/wo/tmp')