Merge pull request #164 from WordOps/updating-configuration
Updating configuration
This commit is contained in:
30
CHANGELOG.md
30
CHANGELOG.md
@@ -8,15 +8,39 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
|
||||
### v3.9.x - [Unreleased]
|
||||
|
||||
### v3.9.9.1 - 2019-09-26
|
||||
|
||||
#### Added
|
||||
|
||||
- [SECURE] Allow new ssh port with UFW when running `wo secure --sshport`
|
||||
- [STACK] Additional Nginx directives to prevent access to log files or backup from web browser
|
||||
- [CORE] apt-mirror-updater to select the fastest debian/ubuntu mirror with automatic switching between mirrors if the current mirror is being updated
|
||||
- [SITE] add `--force` to force Let's Encrypt certificate issuance even if DNS check fail
|
||||
- [STACK] check if another mta is installed before installing sendmail
|
||||
- [SECURE] `--allowpassword` to allow password when using `--ssh` with `wo secure`
|
||||
|
||||
#### Changed
|
||||
|
||||
- [SECURE] Improved sshd_config template according to Mozilla Infosec guidelines
|
||||
- [STACK] Always add stack configuration into Git before making changes to make rollback easier
|
||||
- [STACK] Render php-fpm pools configuration from template
|
||||
- [STACK] Adminer updated to v4.7.3
|
||||
|
||||
#### Fixed
|
||||
|
||||
- [STACK] UFW setup after removing all stacks with `wo stack purge --all`
|
||||
- [CONFIG] Invalid CORS header
|
||||
- [STACK] PHP-FPM stack upgrade failure due to pool configuration
|
||||
|
||||
### v3.9.9 - 2019-09-24
|
||||
|
||||
#### Added
|
||||
|
||||
- [STACK] UFW now available as a stack with flag `--ufw`
|
||||
- [SECURE] `wo stack secure --ssh` to harden ssh security
|
||||
- [SECURE] `wo stack secure --sshport` to change ssh port
|
||||
- [SECURE] `wo secure --ssh` to harden ssh security
|
||||
- [SECURE] `wo secure --sshport` to change ssh port
|
||||
- [SITE] check domain DNS records before issuing a new certificate without DNS API
|
||||
- [STACK] Acme challenge with DNS Alias mode [acme.sh wiki](https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode)
|
||||
- [STACK] Acme challenge with DNS Alias mode `--dnsalias=aliasdomain.tld` [acme.sh wiki](https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode)
|
||||
|
||||
#### Changed
|
||||
|
||||
|
||||
3
setup.py
3
setup.py
@@ -25,7 +25,7 @@ if not os.path.exists('/var/lib/wo/'):
|
||||
os.makedirs('/var/lib/wo/')
|
||||
|
||||
setup(name='wo',
|
||||
version='3.9.9',
|
||||
version='3.9.9.1',
|
||||
description=long_description,
|
||||
long_description=long_description,
|
||||
classifiers=[],
|
||||
@@ -56,6 +56,7 @@ setup(name='wo',
|
||||
'SQLAlchemy',
|
||||
'requests',
|
||||
'distro',
|
||||
'apt-mirror-updater',
|
||||
],
|
||||
data_files=[('/etc/wo', ['config/wo.conf']),
|
||||
('/etc/wo/plugins.d', conf),
|
||||
|
||||
@@ -4,6 +4,7 @@ import os
|
||||
from cement.core import handler, hook
|
||||
from cement.core.controller import CementBaseController, expose
|
||||
|
||||
from wo.core.fileutils import WOFileUtils
|
||||
from wo.core.git import WOGit
|
||||
from wo.core.logging import Log
|
||||
from wo.core.random import RANDOM
|
||||
@@ -37,6 +38,9 @@ class WOSecureController(CementBaseController):
|
||||
help='set custom ssh port', action='store_true')),
|
||||
(['--ssh'], dict(
|
||||
help='harden ssh security', action='store_true')),
|
||||
(['--allowpassword'], dict(
|
||||
help='allow password authentification '
|
||||
'when hardening ssh security', action='store_true')),
|
||||
(['--force'],
|
||||
dict(help='force execution without being prompt',
|
||||
action='store_true')),
|
||||
@@ -156,7 +160,7 @@ class WOSecureController(CementBaseController):
|
||||
def secure_ssh(self):
|
||||
"""Harden ssh security"""
|
||||
pargs = self.app.pargs
|
||||
if not pargs.force:
|
||||
if not pargs.force and not pargs.allowpassword:
|
||||
start_secure = input('Are you sure you to want to'
|
||||
' harden SSH security ?'
|
||||
'\nSSH login with password will not '
|
||||
@@ -165,6 +169,8 @@ class WOSecureController(CementBaseController):
|
||||
'Harden SSH security [y/N]')
|
||||
if start_secure != "Y" and start_secure != "y":
|
||||
Log.error(self, "Not hardening SSH security")
|
||||
WOGit.add(self, ["/etc/ssh"],
|
||||
msg="Adding SSH into Git")
|
||||
Log.debug(self, "check if /etc/ssh/sshd_config exist")
|
||||
if os.path.isfile('/etc/ssh/sshd_config'):
|
||||
Log.debug(self, "looking for the current ssh port")
|
||||
@@ -178,7 +184,11 @@ class WOSecureController(CementBaseController):
|
||||
sudo_user = os.getenv('SUDO_USER')
|
||||
else:
|
||||
sudo_user = ''
|
||||
data = dict(sshport=current_ssh_port, allowpass='no',
|
||||
if pargs.allowpassword:
|
||||
wo_allowpassword = 'yes'
|
||||
else:
|
||||
wo_allowpassword = 'no'
|
||||
data = dict(sshport=current_ssh_port, allowpass=wo_allowpassword,
|
||||
user=sudo_user)
|
||||
WOTemplate.deploy(self, '/etc/ssh/sshd_config',
|
||||
'sshd.mustache', data)
|
||||
@@ -213,8 +223,23 @@ class WOSecureController(CementBaseController):
|
||||
WOShellExec.cmd_exec(self, "sed -i \"s/Port.*/Port "
|
||||
"{port}/\" /etc/ssh/sshd_config"
|
||||
.format(port=pargs.user_input))
|
||||
# allow new ssh port if ufw is enabled
|
||||
if os.path.isfile('/etc/ufw/ufw.conf'):
|
||||
# add rule for proftpd with UFW
|
||||
if WOFileUtils.grepcheck(
|
||||
self, '/etc/ufw/ufw.conf', 'ENABLED=yes'):
|
||||
try:
|
||||
WOShellExec.cmd_exec(
|
||||
self, 'ufw limit {0}'.format(pargs.user_input))
|
||||
WOShellExec.cmd_exec(
|
||||
self, 'ufw reload')
|
||||
except Exception as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "Unable to add UFW rule")
|
||||
# add ssh into git
|
||||
WOGit.add(self, ["/etc/ssh"],
|
||||
msg="Adding changed SSH port into Git")
|
||||
# restart ssh service
|
||||
if not WOService.restart_service(self, 'ssh'):
|
||||
Log.error(self, "service SSH restart failed.")
|
||||
Log.info(self, "Successfully changed SSH port to {port}"
|
||||
|
||||
@@ -368,6 +368,9 @@ class WOSiteCreateController(CementBaseController):
|
||||
action='store' or 'store_const',
|
||||
choices=('on', 'subdomain', 'wildcard'),
|
||||
const='on', nargs='?')),
|
||||
(['--force'],
|
||||
dict(help="force Let's Encrypt certificate issuance",
|
||||
action='store_true')),
|
||||
(['--dns'],
|
||||
dict(help="choose dns provider api for letsencrypt",
|
||||
action='store' or 'store_const',
|
||||
@@ -796,9 +799,11 @@ class WOSiteCreateController(CementBaseController):
|
||||
else:
|
||||
# check DNS records before issuing cert
|
||||
if not acmedata['dns'] is True:
|
||||
if not WOAcme.check_dns(self, acme_domains):
|
||||
Log.error(self,
|
||||
"Aborting SSL certificate issuance")
|
||||
if not pargs.force:
|
||||
if not WOAcme.check_dns(self, acme_domains):
|
||||
Log.error(self,
|
||||
"Aborting SSL "
|
||||
"certificate issuance")
|
||||
Log.debug(self, "Setup Cert with acme.sh for {0}"
|
||||
.format(wo_domain))
|
||||
if WOAcme.setupletsencrypt(
|
||||
@@ -806,9 +811,10 @@ class WOSiteCreateController(CementBaseController):
|
||||
WOAcme.deploycert(self, wo_domain)
|
||||
else:
|
||||
if not acmedata['dns'] is True:
|
||||
if not WOAcme.check_dns(self, acme_domains):
|
||||
Log.error(self,
|
||||
"Aborting SSL certificate issuance")
|
||||
if not pargs.force:
|
||||
if not WOAcme.check_dns(self, acme_domains):
|
||||
Log.error(self,
|
||||
"Aborting SSL certificate issuance")
|
||||
if WOAcme.setupletsencrypt(
|
||||
self, acme_domains, acmedata):
|
||||
WOAcme.deploycert(self, wo_domain)
|
||||
@@ -885,6 +891,9 @@ class WOSiteUpdateController(CementBaseController):
|
||||
choices=('on', 'off', 'renew', 'subdomain',
|
||||
'wildcard', 'clean', 'purge'),
|
||||
const='on', nargs='?')),
|
||||
(['--force'],
|
||||
dict(help="force LetsEncrypt certificate issuance/renewal",
|
||||
action='store_true')),
|
||||
(['--dns'],
|
||||
dict(help="choose dns provider api for letsencrypt",
|
||||
action='store' or 'store_const',
|
||||
@@ -901,9 +910,6 @@ class WOSiteUpdateController(CementBaseController):
|
||||
dict(help="update to proxy site", nargs='+')),
|
||||
(['--all'],
|
||||
dict(help="update all sites", action='store_true')),
|
||||
(['--force'],
|
||||
dict(help="force letsencrypt certificate renewal",
|
||||
action='store_true')),
|
||||
]
|
||||
|
||||
@expose(help="Update site type or cache")
|
||||
@@ -1446,10 +1452,13 @@ class WOSiteUpdateController(CementBaseController):
|
||||
else:
|
||||
# check DNS records before issuing cert
|
||||
if not acmedata['dns'] is True:
|
||||
if not WOAcme.check_dns(self, acme_domains):
|
||||
Log.error(
|
||||
self,
|
||||
"Aborting SSL certificate issuance")
|
||||
if not pargs.force:
|
||||
if not WOAcme.check_dns(self,
|
||||
acme_domains):
|
||||
Log.error(
|
||||
self,
|
||||
"Aborting SSL certificate "
|
||||
"issuance")
|
||||
Log.debug(self, "Setup Cert with acme.sh for {0}"
|
||||
.format(wo_domain))
|
||||
if WOAcme.setupletsencrypt(
|
||||
@@ -1460,10 +1469,11 @@ class WOSiteUpdateController(CementBaseController):
|
||||
else:
|
||||
# check DNS records before issuing cert
|
||||
if not acmedata['dns'] is True:
|
||||
if not WOAcme.check_dns(self, acme_domains):
|
||||
Log.error(
|
||||
self,
|
||||
"Aborting SSL certificate issuance")
|
||||
if not pargs.force:
|
||||
if not WOAcme.check_dns(self, acme_domains):
|
||||
Log.error(
|
||||
self,
|
||||
"Aborting SSL certificate issuance")
|
||||
if WOAcme.setupletsencrypt(
|
||||
self, acme_domains, acmedata):
|
||||
WOAcme.deploycert(self, wo_domain)
|
||||
|
||||
@@ -930,16 +930,9 @@ def updatewpuserpassword(self, wo_domain, wo_site_webroot):
|
||||
wo_wp_pass = ''
|
||||
WOFileUtils.chdir(self, '{0}/htdocs/'.format(wo_site_webroot))
|
||||
|
||||
# Check if wo_domain is wordpress install
|
||||
try:
|
||||
is_wp = WOShellExec.cmd_exec(self, "wp --allow-root core"
|
||||
" version")
|
||||
except CommandExecutionError as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
raise SiteError("is WordPress site? check command failed ")
|
||||
|
||||
# Exit if wo_domain is not wordpress install
|
||||
if not is_wp:
|
||||
if not WOShellExec.cmd_exec(self, "wp --allow-root core"
|
||||
" is-installed"):
|
||||
# Exit if wo_domain is not wordpress install
|
||||
Log.error(self, "{0} does not seem to be a WordPress site"
|
||||
.format(wo_domain))
|
||||
|
||||
@@ -1333,8 +1326,6 @@ def doCleanupAction(self, domain='', webroot='', dbname='', dbuser='',
|
||||
if os.path.isfile('/etc/nginx/sites-available/{0}'
|
||||
.format(domain)):
|
||||
removeNginxConf(self, domain)
|
||||
if os.path.isdir('/etc/letsencrypt/renewal/{0}_ecc'
|
||||
.format(domain)):
|
||||
removeAcmeConf(self, domain)
|
||||
|
||||
if webroot:
|
||||
|
||||
@@ -129,7 +129,6 @@ class WOStackController(CementBaseController):
|
||||
pargs.php73 = True
|
||||
pargs.redis = True
|
||||
pargs.proftpd = True
|
||||
pargs.security = True
|
||||
|
||||
if pargs.web:
|
||||
pargs.nginx = True
|
||||
@@ -152,7 +151,6 @@ class WOStackController(CementBaseController):
|
||||
if pargs.security:
|
||||
pargs.fail2ban = True
|
||||
pargs.clamav = True
|
||||
pargs.ufw = True
|
||||
|
||||
# Nginx
|
||||
if pargs.nginx:
|
||||
@@ -261,19 +259,24 @@ class WOStackController(CementBaseController):
|
||||
|
||||
# UFW
|
||||
if pargs.ufw:
|
||||
if not WOFileUtils.grep(
|
||||
self, '/etc/ufw/ufw.conf', 'ENABLED=yes'):
|
||||
Log.debug(self, "Setting apt_packages variable for UFW")
|
||||
apt_packages = apt_packages + ["ufw"]
|
||||
Log.debug(self, "Setting apt_packages variable for UFW")
|
||||
apt_packages = apt_packages + ["ufw"]
|
||||
|
||||
# sendmail
|
||||
if pargs.sendmail:
|
||||
Log.debug(self, "Setting apt_packages variable for Sendmail")
|
||||
if not WOAptGet.is_installed(self, 'sendmail'):
|
||||
if (not WOAptGet.is_installed(self, 'sendmail') and
|
||||
not WOAptGet.is_installed(self, 'postfix')):
|
||||
apt_packages = apt_packages + ["sendmail"]
|
||||
else:
|
||||
Log.debug(self, "Sendmail already installed")
|
||||
Log.info(self, "Sendmail already installed")
|
||||
if WOAptGet.is_installed(self, 'sendmail'):
|
||||
Log.debug(self, "Sendmail already installed")
|
||||
Log.info(self, "Sendmail already installed")
|
||||
else:
|
||||
Log.debug(
|
||||
self, "Another mta (Postfix) is already installed")
|
||||
Log.info(
|
||||
self, "Another mta (Postfix) is already installed")
|
||||
|
||||
# proftpd
|
||||
if pargs.proftpd:
|
||||
@@ -521,7 +524,6 @@ class WOStackController(CementBaseController):
|
||||
(not pargs.php73)):
|
||||
pargs.web = True
|
||||
pargs.admin = True
|
||||
pargs.security = True
|
||||
|
||||
if pargs.all:
|
||||
pargs.web = True
|
||||
|
||||
@@ -43,7 +43,7 @@ def pre_pref(self, apt_packages):
|
||||
WORepo.add_key(self, '0xcbcb082a1bb943db',
|
||||
keyserver='keys.gnupg.net')
|
||||
WORepo.add_key(self, '0xF1656F24C74CD1D8',
|
||||
keyserver='hkp://keys.gnupg.net')
|
||||
keyserver='keys.gnupg.net')
|
||||
if "mariadb-server" in apt_packages:
|
||||
# generate random 24 characters root password
|
||||
chars = ''.join(random.sample(string.ascii_letters, 24))
|
||||
@@ -153,11 +153,7 @@ def post_pref(self, apt_packages, packages, upgrade=False):
|
||||
ngxcnf = '/etc/nginx/conf.d'
|
||||
ngxcom = '/etc/nginx/common'
|
||||
ngxroot = '/var/www/'
|
||||
if upgrade:
|
||||
if os.path.isdir('/etc/nginx'):
|
||||
WOGit.add(self,
|
||||
["/etc/nginx"],
|
||||
msg="Adding Nginx into Git")
|
||||
WOGit.add(self, ["/etc/nginx"], msg="Adding Nginx into Git")
|
||||
data = dict(tls13=True)
|
||||
WOTemplate.deploy(self,
|
||||
'/etc/nginx/nginx.conf',
|
||||
@@ -490,6 +486,7 @@ def post_pref(self, apt_packages, packages, upgrade=False):
|
||||
WOService.restart_service(self, 'nginx')
|
||||
|
||||
if set(WOVariables.wo_php).issubset(set(apt_packages)):
|
||||
WOGit.add(self, ["/etc/php"], msg="Adding PHP into Git")
|
||||
Log.info(self, "Configuring php7.2-fpm")
|
||||
ngxroot = '/var/www/'
|
||||
# Create log directories
|
||||
@@ -527,72 +524,32 @@ def post_pref(self, apt_packages, packages, upgrade=False):
|
||||
"/etc/php/7.2/fpm/php.ini")
|
||||
config.write(configfile)
|
||||
|
||||
# Parse /etc/php/7.2/fpm/php-fpm.conf
|
||||
# Render php-fpm pool template for php7.3
|
||||
data = dict(pid="/run/php/php7.2-fpm.pid",
|
||||
error_log="/var/log/php/7.2/fpm.log",
|
||||
error_log="/var/log/php7.2-fpm.log",
|
||||
include="/etc/php/7.2/fpm/pool.d/*.conf")
|
||||
Log.debug(self, "writting php7.2 configuration into "
|
||||
"/etc/php/7.2/fpm/php-fpm.conf")
|
||||
wo_php_fpm = open('/etc/php/7.2/fpm/php-fpm.conf',
|
||||
encoding='utf-8', mode='w')
|
||||
self.app.render((data), 'php-fpm.mustache', out=wo_php_fpm)
|
||||
wo_php_fpm.close()
|
||||
WOTemplate.deploy(
|
||||
self, '/etc/php/7.2/fpm/php-fpm.conf',
|
||||
'php-fpm.mustache', data)
|
||||
|
||||
if not os.path.isfile('/etc/php/7.2/fpm/pool.d/www.conf.orig'):
|
||||
WOFileUtils.copyfile(self, '/etc/php/7.2/fpm/pool.d/www.conf',
|
||||
'/etc/php/7.2/fpm/pool.d/www.conf.orig')
|
||||
# Parse /etc/php/7.2/fpm/pool.d/www.conf
|
||||
config = configparser.ConfigParser()
|
||||
config.read_file(codecs.open('/etc/php/7.2/fpm/'
|
||||
'pool.d/www.conf.orig',
|
||||
"r", "utf8"))
|
||||
config['www']['ping.path'] = '/ping'
|
||||
config['www']['pm.status_path'] = '/status'
|
||||
config['www']['pm.max_requests'] = '1500'
|
||||
config['www']['pm.max_children'] = '50'
|
||||
config['www']['pm.start_servers'] = '10'
|
||||
config['www']['pm.min_spare_servers'] = '5'
|
||||
config['www']['pm.max_spare_servers'] = '15'
|
||||
config['www']['request_terminate_timeout'] = '300'
|
||||
config['www']['pm'] = 'ondemand'
|
||||
config['www']['chdir'] = '/'
|
||||
config['www']['prefix'] = '/var/run/php'
|
||||
config['www']['listen'] = 'php72-fpm.sock'
|
||||
config['www']['listen.mode'] = '0660'
|
||||
config['www']['listen.backlog'] = '32768'
|
||||
config['www']['catch_workers_output'] = 'yes'
|
||||
with codecs.open('/etc/php/7.2/fpm/pool.d/www.conf',
|
||||
encoding='utf-8', mode='w') as configfile:
|
||||
Log.debug(self, "Writing PHP 7.2 configuration into "
|
||||
"/etc/php/7.2/fpm/pool.d/www.conf")
|
||||
config.write(configfile)
|
||||
|
||||
with open("/etc/php/7.2/fpm/pool.d/www.conf",
|
||||
encoding='utf-8', mode='a') as myfile:
|
||||
myfile.write("\nphp_admin_value[open_basedir] "
|
||||
"= \"/var/www/:/usr/share/php/:"
|
||||
"/tmp/:/var/run/nginx-cache/:"
|
||||
"/dev/shm:/dev/urandom\"\n")
|
||||
|
||||
# Generate /etc/php/7.2/fpm/pool.d/www-two.conf
|
||||
WOFileUtils.copyfile(self, "/etc/php/7.2/fpm/pool.d/www.conf",
|
||||
"/etc/php/7.2/fpm/pool.d/www-two.conf")
|
||||
WOFileUtils.searchreplace(self, "/etc/php/7.2/fpm/pool.d/"
|
||||
"www-two.conf", "[www]", "[www-two]")
|
||||
config = configparser.ConfigParser()
|
||||
config.read('/etc/php/7.2/fpm/pool.d/www-two.conf')
|
||||
config['www-two']['listen'] = 'php72-two-fpm.sock'
|
||||
with open('/etc/php/7.2/fpm/pool.d/www-two.conf',
|
||||
encoding='utf-8', mode='w') as confifile:
|
||||
Log.debug(self, "writting PHP7.2 configuration into "
|
||||
"/etc/php/7.2/fpm/pool.d/www-two.conf")
|
||||
config.write(confifile)
|
||||
data = dict(pool='www-php72', listen='php72-fpm.sock',
|
||||
user='www-data',
|
||||
group='www-data', listenuser='root',
|
||||
listengroup='www-data', openbasedir=True)
|
||||
WOTemplate.deploy(self, '/etc/php/7.2/fpm/pool.d/www.conf',
|
||||
'php-pool.mustache', data)
|
||||
data = dict(pool='www-two-php72', listen='php72-two-fpm.sock',
|
||||
user='www-data',
|
||||
group='www-data', listenuser='root',
|
||||
listengroup='www-data', openbasedir=True)
|
||||
WOTemplate.deploy(self, '/etc/php/7.2/fpm/pool.d/www-two.conf',
|
||||
'php-pool.mustache', data)
|
||||
|
||||
# Generate /etc/php/7.2/fpm/pool.d/debug.conf
|
||||
WOFileUtils.copyfile(self, "/etc/php/7.2/fpm/pool.d/www.conf",
|
||||
"/etc/php/7.2/fpm/pool.d/debug.conf")
|
||||
WOFileUtils.searchreplace(self, "/etc/php/7.2/fpm/pool.d/"
|
||||
"debug.conf", "[www]", "[debug]")
|
||||
"debug.conf", "[www-php72]", "[debug]")
|
||||
config = configparser.ConfigParser()
|
||||
config.read('/etc/php/7.2/fpm/pool.d/debug.conf')
|
||||
config['debug']['listen'] = '127.0.0.1:9172'
|
||||
@@ -663,6 +620,7 @@ def post_pref(self, apt_packages, packages, upgrade=False):
|
||||
|
||||
# PHP7.3 configuration
|
||||
if set(WOVariables.wo_php73).issubset(set(apt_packages)):
|
||||
WOGit.add(self, ["/etc/php"], msg="Adding PHP into Git")
|
||||
Log.info(self, "Configuring php7.3-fpm")
|
||||
ngxroot = '/var/www/'
|
||||
# Create log directories
|
||||
@@ -700,72 +658,32 @@ def post_pref(self, apt_packages, packages, upgrade=False):
|
||||
"/etc/php/7.3/fpm/php.ini")
|
||||
config.write(configfile)
|
||||
|
||||
# Parse /etc/php/7.3/fpm/php-fpm.conf
|
||||
# Render php-fpm pool template for php7.3
|
||||
data = dict(pid="/run/php/php7.3-fpm.pid",
|
||||
error_log="/var/log/php7.3-fpm.log",
|
||||
include="/etc/php/7.3/fpm/pool.d/*.conf")
|
||||
Log.debug(self, "writting php 7.3 configuration into "
|
||||
"/etc/php/7.3/fpm/php-fpm.conf")
|
||||
wo_php_fpm = open('/etc/php/7.3/fpm/php-fpm.conf',
|
||||
encoding='utf-8', mode='w')
|
||||
self.app.render((data), 'php-fpm.mustache', out=wo_php_fpm)
|
||||
wo_php_fpm.close()
|
||||
WOTemplate.deploy(
|
||||
self, '/etc/php/7.3/fpm/php-fpm.conf',
|
||||
'php-fpm.mustache', data)
|
||||
|
||||
# Parse /etc/php/7.3/fpm/pool.d/www.conf
|
||||
if not os.path.isfile('/etc/php/7.3/fpm/pool.d/www.conf.orig'):
|
||||
WOFileUtils.copyfile(self, '/etc/php/7.3/fpm/pool.d/www.conf',
|
||||
'/etc/php/7.3/fpm/pool.d/www.conf.orig')
|
||||
config = configparser.ConfigParser()
|
||||
config.read_file(codecs.open('/etc/php/7.3/fpm/'
|
||||
'pool.d/www.conf.orig',
|
||||
"r", "utf8"))
|
||||
config['www']['ping.path'] = '/ping'
|
||||
config['www']['pm.status_path'] = '/status'
|
||||
config['www']['pm.max_requests'] = '1500'
|
||||
config['www']['pm.max_children'] = '50'
|
||||
config['www']['pm.start_servers'] = '10'
|
||||
config['www']['pm.min_spare_servers'] = '5'
|
||||
config['www']['pm.max_spare_servers'] = '15'
|
||||
config['www']['request_terminate_timeout'] = '300'
|
||||
config['www']['pm'] = 'ondemand'
|
||||
config['www']['chdir'] = '/'
|
||||
config['www']['prefix'] = '/var/run/php'
|
||||
config['www']['listen'] = 'php73-fpm.sock'
|
||||
config['www']['listen.mode'] = '0660'
|
||||
config['www']['listen.backlog'] = '32768'
|
||||
config['www']['catch_workers_output'] = 'yes'
|
||||
with codecs.open('/etc/php/7.3/fpm/pool.d/www.conf',
|
||||
encoding='utf-8', mode='w') as configfile:
|
||||
Log.debug(self, "writting PHP 7.3 configuration into "
|
||||
"/etc/php/7.3/fpm/pool.d/www.conf")
|
||||
config.write(configfile)
|
||||
|
||||
with open("/etc/php/7.3/fpm/pool.d/www.conf",
|
||||
encoding='utf-8', mode='a') as myfile:
|
||||
myfile.write("\nphp_admin_value[open_basedir] "
|
||||
"= \"/var/www/:/usr/share/php/:"
|
||||
"/tmp/:/var/run/nginx-cache/:"
|
||||
"/dev/shm:/dev/urandom\"\n")
|
||||
|
||||
# Generate /etc/php/7.3/fpm/pool.d/www-two.conf
|
||||
WOFileUtils.copyfile(self, "/etc/php/7.3/fpm/pool.d/www.conf",
|
||||
"/etc/php/7.3/fpm/pool.d/www-two.conf")
|
||||
WOFileUtils.searchreplace(self, "/etc/php/7.3/fpm/pool.d/"
|
||||
"www-two.conf", "[www]", "[www-two]")
|
||||
config = configparser.ConfigParser()
|
||||
config.read('/etc/php/7.3/fpm/pool.d/www-two.conf')
|
||||
config['www-two']['listen'] = 'php73-two-fpm.sock'
|
||||
with open('/etc/php/7.3/fpm/pool.d/www-two.conf',
|
||||
encoding='utf-8', mode='w') as confifile:
|
||||
Log.debug(self, "writting PHP7.3 configuration into "
|
||||
"/etc/php/7.3/fpm/pool.d/www-two.conf")
|
||||
config.write(confifile)
|
||||
data = dict(pool='www-php73', listen='php73-fpm.sock',
|
||||
user='www-data',
|
||||
group='www-data', listenuser='root',
|
||||
listengroup='www-data', openbasedir=True)
|
||||
WOTemplate.deploy(self, '/etc/php/7.3/fpm/pool.d/www.conf',
|
||||
'php-pool.mustache', data)
|
||||
data = dict(pool='www-two-php73', listen='php73-two-fpm.sock',
|
||||
user='www-data',
|
||||
group='www-data', listenuser='root',
|
||||
listengroup='www-data', openbasedir=True)
|
||||
WOTemplate.deploy(self, '/etc/php/7.3/fpm/pool.d/www-two.conf',
|
||||
'php-pool.mustache', data)
|
||||
|
||||
# Generate /etc/php/7.3/fpm/pool.d/debug.conf
|
||||
WOFileUtils.copyfile(self, "/etc/php/7.3/fpm/pool.d/www.conf",
|
||||
"/etc/php/7.3/fpm/pool.d/debug.conf")
|
||||
WOFileUtils.searchreplace(self, "/etc/php/7.3/fpm/pool.d/"
|
||||
"debug.conf", "[www]", "[debug]")
|
||||
"debug.conf", "[www-php73]", "[debug]")
|
||||
config = configparser.ConfigParser()
|
||||
config.read('/etc/php/7.3/fpm/pool.d/debug.conf')
|
||||
config['debug']['listen'] = '127.0.0.1:9173'
|
||||
@@ -836,6 +754,7 @@ def post_pref(self, apt_packages, packages, upgrade=False):
|
||||
|
||||
# create mysql config if it doesn't exist
|
||||
if "mariadb-server" in apt_packages:
|
||||
WOGit.add(self, ["/etc/mysql"], msg="Adding MySQL into Git")
|
||||
if not os.path.isfile("/etc/mysql/my.cnf"):
|
||||
config = ("[mysqld]\nwait_timeout = 30\n"
|
||||
"interactive_timeout=60\nperformance_schema = 0"
|
||||
@@ -889,6 +808,8 @@ def post_pref(self, apt_packages, packages, upgrade=False):
|
||||
|
||||
# create fail2ban configuration files
|
||||
if set(WOVariables.wo_fail2ban).issubset(set(apt_packages)):
|
||||
WOGit.add(self, ["/etc/fail2ban"],
|
||||
msg="Adding Fail2ban into Git")
|
||||
if not os.path.isfile("/etc/fail2ban/jail.d/custom.conf"):
|
||||
Log.info(self, "Configuring Fail2Ban")
|
||||
data = dict()
|
||||
@@ -914,6 +835,8 @@ def post_pref(self, apt_packages, packages, upgrade=False):
|
||||
|
||||
# Proftpd configuration
|
||||
if "proftpd-basic" in apt_packages:
|
||||
WOGit.add(self, ["/etc/proftpd"],
|
||||
msg="Adding ProFTPd into Git")
|
||||
if os.path.isfile("/etc/proftpd/proftpd.conf"):
|
||||
Log.info(self, "Configuring ProFTPd")
|
||||
Log.debug(self, "Setting up Proftpd configuration")
|
||||
@@ -936,32 +859,28 @@ def post_pref(self, apt_packages, packages, upgrade=False):
|
||||
WOFileUtils.chmod(self, "/etc/proftpd/ssl/proftpd.key", 0o700)
|
||||
WOFileUtils.chmod(self, "/etc/proftpd/ssl/proftpd.crt", 0o700)
|
||||
data = dict()
|
||||
Log.debug(self, 'Writting the proftpd configuration to '
|
||||
'file /etc/proftpd/tls.conf')
|
||||
wo_proftpdconf = open('/etc/proftpd/tls.conf',
|
||||
encoding='utf-8', mode='w')
|
||||
self.app.render((data), 'proftpd-tls.mustache',
|
||||
out=wo_proftpdconf)
|
||||
wo_proftpdconf.close()
|
||||
WOTemplate.deploy(self, '/etc/proftpd/tls.conf',
|
||||
'proftpd-tls.mustache', data)
|
||||
WOFileUtils.searchreplace(self, "/etc/proftpd/"
|
||||
"proftpd.conf",
|
||||
"#Include /etc/proftpd/tls.conf",
|
||||
"Include /etc/proftpd/tls.conf")
|
||||
WOService.restart_service(self, 'proftpd')
|
||||
|
||||
# add rule for proftpd with UFW
|
||||
if WOFileUtils.grepcheck(
|
||||
self, '/etc/ufw/ufw.conf', 'ENABLED=yes'):
|
||||
try:
|
||||
WOShellExec.cmd_exec(
|
||||
self, "ufw limit 21")
|
||||
WOShellExec.cmd_exec(
|
||||
self, "ufw allow 49000:50000/tcp")
|
||||
WOShellExec.cmd_exec(
|
||||
self, "ufw reload")
|
||||
except CommandExecutionError as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "Unable to add UFW rule")
|
||||
if os.path.isfile('/etc/ufw/ufw.conf'):
|
||||
# add rule for proftpd with UFW
|
||||
if WOFileUtils.grepcheck(
|
||||
self, '/etc/ufw/ufw.conf', 'ENABLED=yes'):
|
||||
try:
|
||||
WOShellExec.cmd_exec(
|
||||
self, "ufw limit 21")
|
||||
WOShellExec.cmd_exec(
|
||||
self, "ufw allow 49000:50000/tcp")
|
||||
WOShellExec.cmd_exec(
|
||||
self, "ufw reload")
|
||||
except Exception as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "Unable to add UFW rules")
|
||||
|
||||
if ((os.path.isfile("/etc/fail2ban/jail.d/custom.conf")) and
|
||||
(not WOFileUtils.grep(
|
||||
@@ -1021,6 +940,8 @@ def post_pref(self, apt_packages, packages, upgrade=False):
|
||||
# set maxmemory 10% for ram below 512MB and 20% for others
|
||||
# set maxmemory-policy allkeys-lru
|
||||
# enable systemd service
|
||||
WOGit.add(self, ["/etc/redis"],
|
||||
msg="Adding Redis into Git")
|
||||
Log.debug(self, "Enabling redis systemd service")
|
||||
WOShellExec.cmd_exec(self, "systemctl enable redis-server")
|
||||
if (os.path.isfile("/etc/redis/redis.conf") and
|
||||
@@ -1029,7 +950,7 @@ def post_pref(self, apt_packages, packages, upgrade=False):
|
||||
Log.wait(self, "Tuning Redis configuration")
|
||||
with open("/etc/redis/redis.conf",
|
||||
"a") as redis_file:
|
||||
redis_file.write("\n# WordOps v3.9.8\n")
|
||||
redis_file.write("\n# WordOps v3.9.9\n")
|
||||
wo_ram = psutil.virtual_memory().total / (1024 * 1024)
|
||||
if wo_ram < 1024:
|
||||
Log.debug(self, "Setting maxmemory variable to "
|
||||
@@ -1069,8 +990,10 @@ def post_pref(self, apt_packages, packages, upgrade=False):
|
||||
"tcp-backlog 32768")
|
||||
WOFileUtils.chown(self, '/etc/redis/redis.conf',
|
||||
'redis', 'redis', recursive=False)
|
||||
WOService.restart_service(self, 'redis-server')
|
||||
Log.valide(self, "Tuning Redis configuration")
|
||||
WOGit.add(self, ["/etc/redis"],
|
||||
msg="Adding Redis into Git")
|
||||
WOService.restart_service(self, 'redis-server')
|
||||
|
||||
# ClamAV configuration
|
||||
if set(WOVariables.wo_clamav).issubset(set(apt_packages)):
|
||||
@@ -1405,13 +1328,10 @@ def post_pref(self, apt_packages, packages, upgrade=False):
|
||||
Log.debug(self, "configration Anemometer")
|
||||
data = dict(host=WOVariables.wo_mysql_host, port='3306',
|
||||
user='anemometer', password=chars)
|
||||
wo_anemometer = open('{0}22222/htdocs/db/anemometer'
|
||||
'/conf/config.inc.php'
|
||||
.format(WOVariables.wo_webroot),
|
||||
encoding='utf-8', mode='w')
|
||||
self.app.render((data), 'anemometer.mustache',
|
||||
out=wo_anemometer)
|
||||
wo_anemometer.close()
|
||||
WOTemplate.deploy(self, '{0}22222/htdocs/db/anemometer'
|
||||
'/conf/config.inc.php'
|
||||
.format(WOVariables.wo_webroot),
|
||||
'anemometer.mustache', data)
|
||||
|
||||
# pt-query-advisor
|
||||
if any('/usr/bin/pt-query-advisor' == x[1]
|
||||
|
||||
@@ -212,7 +212,6 @@ class WOStackUpgradeController(CementBaseController):
|
||||
if ["php7.3-fpm"] in apt_packages:
|
||||
WOAptGet.remove(self, ['php7.3-fpm'],
|
||||
auto=False, purge=True)
|
||||
|
||||
# check if nginx upgrade is blocked
|
||||
if os.path.isfile(
|
||||
'/etc/apt/preferences.d/nginx-block'):
|
||||
|
||||
@@ -12,7 +12,7 @@ location @empty_gif {
|
||||
}
|
||||
# Cache static files
|
||||
location ~* \.(ogg|ogv|svg|svgz|eot|otf|woff|woff2|ttf|m4a|mp4|ttf|rss|atom|jpe?g|gif|cur|heic|png|tiff|ico|webm|mp3|aac|tgz|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|swf|webp|json|webmanifest)$ {
|
||||
more_set_headers 'Access-Control-Allow-Origin : "*"';
|
||||
more_set_headers 'Access-Control-Allow-Origin : *';
|
||||
more_set_headers "Cache-Control : public, no-transform";
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
@@ -20,7 +20,7 @@ location ~* \.(ogg|ogv|svg|svgz|eot|otf|woff|woff2|ttf|m4a|mp4|ttf|rss|atom|jpe?
|
||||
}
|
||||
# Cache css & js files
|
||||
location ~* \.(?:css(\.map)?|js(\.map)?)$ {
|
||||
more_set_headers 'Access-Control-Allow-Origin : "*"';
|
||||
more_set_headers 'Access-Control-Allow-Origin : *';
|
||||
more_set_headers "Cache-Control : public, no-transform";
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
|
||||
@@ -66,7 +66,7 @@ http {
|
||||
more_set_headers "X-Frame-Options : SAMEORIGIN";
|
||||
more_set_headers "X-Xss-Protection : 1; mode=block";
|
||||
more_set_headers "X-Content-Type-Options : nosniff";
|
||||
more_set_headers "Referrer-Policy : strict-origin-when-cross-origin";
|
||||
more_set_headers "Referrer-Policy : no-referrer, strict-origin-when-cross-origin";
|
||||
more_set_headers "X-Download-Options : noopen";
|
||||
|
||||
# oscp settings
|
||||
|
||||
23
wo/cli/templates/php-pool.mustache
Normal file
23
wo/cli/templates/php-pool.mustache
Normal file
@@ -0,0 +1,23 @@
|
||||
[{{pool}}]
|
||||
user = {{user}}
|
||||
group = {{group}}
|
||||
listen = {{listen}}
|
||||
listen.owner = {{listenuser}}
|
||||
listen.group = {{listengroup}}
|
||||
pm = ondemand
|
||||
pm.max_children = 50
|
||||
pm.start_servers = 10
|
||||
pm.min_spare_servers = 5
|
||||
pm.max_spare_servers = 15
|
||||
ping.path = /ping
|
||||
pm.status_path = /status
|
||||
pm.max_requests = 1500
|
||||
request_terminate_timeout = 300
|
||||
chdir = /
|
||||
prefix = /var/run/php
|
||||
listen.mode = 0660
|
||||
listen.backlog = 32768
|
||||
catch_workers_output = yes
|
||||
|
||||
|
||||
{{#openbasedir}}php_admin_value[open_basedir] = "/var/www/:/usr/share/php/:/tmp/:/var/run/nginx-cache/"{{/openbasedir}}
|
||||
@@ -33,8 +33,11 @@ X11Forwarding yes
|
||||
# Allow client to pass locale environment variables
|
||||
AcceptEnv LANG LC_*
|
||||
|
||||
# override default of no subsystems
|
||||
Subsystem sftp /usr/lib/openssh/sftp-server
|
||||
# LogLevel VERBOSE logs user's key fingerprint on login. Needed to have a clear audit track of which key was using to log in.
|
||||
LogLevel VERBOSE
|
||||
|
||||
# Log sftp level file access (read/write/etc.) that would not be easily logged otherwise.
|
||||
Subsystem sftp /usr/lib/ssh/sftp-server -f AUTHPRIV -l INFO
|
||||
|
||||
# Host keys the client accepts - order here is honored by OpenSSH
|
||||
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ssh-ed25519,ssh-rsa,ecdsa-sha2-nistp521-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp521,ecdsa-sha2-nistp384,ecdsa-sha2-nistp256
|
||||
@@ -42,4 +45,8 @@ HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,
|
||||
# use strong ciphers
|
||||
KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
|
||||
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
|
||||
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
|
||||
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
|
||||
|
||||
# Use kernel sandbox mechanisms where possible in unprivileged processes
|
||||
# Systrace on OpenBSD, Seccomp on Linux, seatbelt on MacOSX/Darwin, rlimit elsewhere.
|
||||
UsePrivilegeSeparation sandbox
|
||||
@@ -40,15 +40,15 @@ location @robots {
|
||||
location /wp-content/uploads {
|
||||
location ~ \.(png|jpe?g)$ {
|
||||
add_header Vary "Accept-Encoding";
|
||||
add_header "Access-Control-Allow-Origin" "*";
|
||||
more_set_headers 'Access-Control-Allow-Origin : *';
|
||||
add_header Cache-Control "public, no-transform";
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
expires max;
|
||||
try_files $uri$webp_suffix $uri =404;
|
||||
}
|
||||
location ~ \.php$ {
|
||||
#Prevent Direct Access Of PHP Files From Web Browsers
|
||||
location ~* \.(php|gz|log|zip|tar|rar)$ {
|
||||
#Prevent Direct Access Of PHP Files & BackupsFrom Web Browsers
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,7 @@ location /wp-content/uploads {
|
||||
location /wp-content/plugins/ewww-image-optimizer/images {
|
||||
location ~ \.(png|jpe?g)$ {
|
||||
add_header Vary "Accept-Encoding";
|
||||
add_header "Access-Control-Allow-Origin" "*";
|
||||
more_set_headers 'Access-Control-Allow-Origin : *';
|
||||
add_header Cache-Control "public, no-transform";
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
@@ -72,7 +72,7 @@ location /wp-content/plugins/ewww-image-optimizer/images {
|
||||
location /wp-content/cache {
|
||||
# Cache css & js files
|
||||
location ~* \.(?:css(\.map)?|js(\.map)?|.html)$ {
|
||||
add_header "Access-Control-Allow-Origin" "*";
|
||||
more_set_headers 'Access-Control-Allow-Origin : *';
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
expires 30d;
|
||||
|
||||
@@ -18,7 +18,7 @@ class WOAptGet():
|
||||
"""
|
||||
try:
|
||||
with open('/var/log/wo/wordops.log', 'a') as f:
|
||||
proc = subprocess.Popen('apt-get update',
|
||||
proc = subprocess.Popen('apt-mirror-updater -u',
|
||||
shell=True,
|
||||
stdin=None, stdout=f,
|
||||
stderr=subprocess.PIPE,
|
||||
|
||||
@@ -202,6 +202,37 @@ class WOFileUtils():
|
||||
Log.debug(self, "{0}".format(e.strerror))
|
||||
Log.error(self, "Unable to change owner : {0}".format(path))
|
||||
|
||||
def wpperm(self, path, harden=False):
|
||||
"""
|
||||
Fix WordPress site permissions
|
||||
path : WordPress site path
|
||||
harden : set 750/640 instead of 755/644
|
||||
"""
|
||||
userid = pwd.getpwnam('www-data')[2]
|
||||
groupid = pwd.getpwnam('www-data')[3]
|
||||
try:
|
||||
Log.debug(self, "Fixing WordPress permissions of {0}"
|
||||
.format(path))
|
||||
if harden:
|
||||
dperm = '0o750'
|
||||
fperm = '0o640'
|
||||
else:
|
||||
dperm = '0o755'
|
||||
fperm = '0o644'
|
||||
|
||||
for root, dirs, files in os.walk(path):
|
||||
for d in dirs:
|
||||
os.chown(os.path.join(root, d), userid,
|
||||
groupid)
|
||||
os.chmod(os.path.join(root, d), dperm)
|
||||
for f in files:
|
||||
os.chown(os.path.join(root, d), userid,
|
||||
groupid)
|
||||
os.chmod(os.path.join(root, f), fperm)
|
||||
except OSError as e:
|
||||
Log.debug(self, "{0}".format(e.strerror))
|
||||
Log.error(self, "Unable to change owner : {0}".format(path))
|
||||
|
||||
def mkdir(self, path):
|
||||
"""
|
||||
create directories.
|
||||
|
||||
@@ -74,7 +74,7 @@ class WOGit:
|
||||
try:
|
||||
Log.debug(self, "WOGit: git reset HEAD~ at {0}"
|
||||
.format(path))
|
||||
git.reset("--hard HEAD~")
|
||||
git.reset("HEAD~", "--hard")
|
||||
except ErrorReturnCode as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
Log.error(self, "Unable to git reset at {0} "
|
||||
|
||||
@@ -11,10 +11,10 @@ class WOVariables():
|
||||
"""Intialization of core variables"""
|
||||
|
||||
# WordOps version
|
||||
wo_version = "3.9.9"
|
||||
wo_version = "3.9.9.1"
|
||||
# WordOps packages versions
|
||||
wo_wp_cli = "2.3.0"
|
||||
wo_adminer = "4.7.2"
|
||||
wo_adminer = "4.7.3"
|
||||
wo_phpmyadmin = "4.9.1"
|
||||
wo_extplorer = "2.1.13"
|
||||
wo_dashboard = "1.2"
|
||||
|
||||
Reference in New Issue
Block a user