From 555269decfe135597de046413b963c3a6fdba35e Mon Sep 17 00:00:00 2001 From: Janio Sarmento Date: Sun, 23 Jan 2022 15:14:24 -0300 Subject: [PATCH 01/14] #348: PHP8 --- wo/cli/plugins/debug.py | 2 +- wo/cli/plugins/info.py | 199 ++++++++++++++++++- wo/cli/plugins/site_create.py | 24 ++- wo/cli/plugins/site_functions.py | 100 +++++++++- wo/cli/plugins/site_update.py | 74 +++++-- wo/cli/plugins/stack.py | 119 ++++++++++- wo/cli/plugins/stack_pref.py | 326 ++++++++++++++++++++++++++++++- wo/cli/plugins/stack_services.py | 94 ++++++++- wo/cli/plugins/stack_upgrade.py | 23 ++- wo/core/services.py | 4 +- wo/core/variables.py | 23 ++- 11 files changed, 943 insertions(+), 45 deletions(-) diff --git a/wo/cli/plugins/debug.py b/wo/cli/plugins/debug.py index 43fdb87..9a34f26 100644 --- a/wo/cli/plugins/debug.py +++ b/wo/cli/plugins/debug.py @@ -607,7 +607,7 @@ class WODebugController(CementBaseController): self.debug_fpm73() if self.app.pargs.mysql: # MySQL debug will not work for remote MySQL - if WOVar.wo_mysql_host is "localhost": + if WOVar.wo_mysql_host == "localhost": self.app.pargs.mysql = 'off' self.debug_mysql() else: diff --git a/wo/cli/plugins/info.py b/wo/cli/plugins/info.py index 3c690e9..a463f0d 100644 --- a/wo/cli/plugins/info.py +++ b/wo/cli/plugins/info.py @@ -35,6 +35,12 @@ class WOInfoController(CementBaseController): (['--php74'], dict(help='Get PHP 7.4 configuration information', action='store_true')), + (['--php80'], + dict(help='Get PHP 8.0 configuration information', + action='store_true')), + (['--php81'], + dict(help='Get PHP 8.1 configuration information', + action='store_true')), (['--nginx'], dict(help='Get Nginx configuration information', action='store_true')), @@ -328,6 +334,180 @@ class WOInfoController(CementBaseController): debug_xdebug_profiler_enable_trigger=debug_xdebug) self.app.render((data), 'info_php.mustache') + @expose(hide=True) + def info_php80(self): + """Display PHP information""" + version = os.popen("/usr/bin/php8.0 -v 2>/dev/null | " + "head -n1 | cut -d' ' -f2 |" + " cut -d'+' -f1 | tr -d '\n'").read + config = configparser.ConfigParser() + config.read('/etc/php/8.0/fpm/php.ini') + expose_php = config['PHP']['expose_php'] + memory_limit = config['PHP']['memory_limit'] + post_max_size = config['PHP']['post_max_size'] + upload_max_filesize = config['PHP']['upload_max_filesize'] + max_execution_time = config['PHP']['max_execution_time'] + + if os.path.exists('/etc/php/8.0/fpm/pool.d/www.conf'): + config.read('/etc/php/8.0/fpm/pool.d/www.conf') + else: + Log.error(self, 'php-fpm pool config not found') + if config.has_section('www'): + wconfig = config['www'] + elif config.has_section('www-php80'): + wconfig = config['www-php80'] + else: + Log.error(self, 'Unable to parse configuration') + www_listen = wconfig['listen'] + www_ping_path = wconfig['ping.path'] + www_pm_status_path = wconfig['pm.status_path'] + www_pm = wconfig['pm'] + www_pm_max_requests = wconfig['pm.max_requests'] + www_pm_max_children = wconfig['pm.max_children'] + www_pm_start_servers = wconfig['pm.start_servers'] + www_pm_min_spare_servers = wconfig['pm.min_spare_servers'] + www_pm_max_spare_servers = wconfig['pm.max_spare_servers'] + www_request_terminate_time = (wconfig + ['request_terminate_timeout']) + try: + www_xdebug = (wconfig + ['php_admin_flag[xdebug.profiler_enable' + '_trigger]']) + except Exception as e: + Log.debug(self, "{0}".format(e)) + www_xdebug = 'off' + + config.read('/etc/php/8.0/fpm/pool.d/debug.conf') + debug_listen = config['debug']['listen'] + debug_ping_path = config['debug']['ping.path'] + debug_pm_status_path = config['debug']['pm.status_path'] + debug_pm = config['debug']['pm'] + debug_pm_max_requests = config['debug']['pm.max_requests'] + debug_pm_max_children = config['debug']['pm.max_children'] + debug_pm_start_servers = config['debug']['pm.start_servers'] + debug_pm_min_spare_servers = config['debug']['pm.min_spare_servers'] + debug_pm_max_spare_servers = config['debug']['pm.max_spare_servers'] + debug_request_terminate = (config['debug'] + ['request_terminate_timeout']) + try: + debug_xdebug = (config['debug']['php_admin_flag[xdebug.profiler_' + 'enable_trigger]']) + except Exception as e: + Log.debug(self, "{0}".format(e)) + debug_xdebug = 'off' + + data = dict(version=version, expose_php=expose_php, + memory_limit=memory_limit, post_max_size=post_max_size, + upload_max_filesize=upload_max_filesize, + max_execution_time=max_execution_time, + www_listen=www_listen, www_ping_path=www_ping_path, + www_pm_status_path=www_pm_status_path, www_pm=www_pm, + www_pm_max_requests=www_pm_max_requests, + www_pm_max_children=www_pm_max_children, + www_pm_start_servers=www_pm_start_servers, + www_pm_min_spare_servers=www_pm_min_spare_servers, + www_pm_max_spare_servers=www_pm_max_spare_servers, + www_request_terminate_timeout=www_request_terminate_time, + www_xdebug_profiler_enable_trigger=www_xdebug, + debug_listen=debug_listen, debug_ping_path=debug_ping_path, + debug_pm_status_path=debug_pm_status_path, + debug_pm=debug_pm, + debug_pm_max_requests=debug_pm_max_requests, + debug_pm_max_children=debug_pm_max_children, + debug_pm_start_servers=debug_pm_start_servers, + debug_pm_min_spare_servers=debug_pm_min_spare_servers, + debug_pm_max_spare_servers=debug_pm_max_spare_servers, + debug_request_terminate_timeout=debug_request_terminate, + debug_xdebug_profiler_enable_trigger=debug_xdebug) + self.app.render((data), 'info_php.mustache') + + @expose(hide=True) + def info_php81(self): + """Display PHP information""" + version = os.popen("/usr/bin/php8.1 -v 2>/dev/null | " + "head -n1 | cut -d' ' -f2 |" + " cut -d'+' -f1 | tr -d '\n'").read + config = configparser.ConfigParser() + config.read('/etc/php/8.1/fpm/php.ini') + expose_php = config['PHP']['expose_php'] + memory_limit = config['PHP']['memory_limit'] + post_max_size = config['PHP']['post_max_size'] + upload_max_filesize = config['PHP']['upload_max_filesize'] + max_execution_time = config['PHP']['max_execution_time'] + + if os.path.exists('/etc/php/8.1/fpm/pool.d/www.conf'): + config.read('/etc/php/8.1/fpm/pool.d/www.conf') + else: + Log.error(self, 'php-fpm pool config not found') + if config.has_section('www'): + wconfig = config['www'] + elif config.has_section('www-php81'): + wconfig = config['www-php81'] + else: + Log.error(self, 'Unable to parse configuration') + www_listen = wconfig['listen'] + www_ping_path = wconfig['ping.path'] + www_pm_status_path = wconfig['pm.status_path'] + www_pm = wconfig['pm'] + www_pm_max_requests = wconfig['pm.max_requests'] + www_pm_max_children = wconfig['pm.max_children'] + www_pm_start_servers = wconfig['pm.start_servers'] + www_pm_min_spare_servers = wconfig['pm.min_spare_servers'] + www_pm_max_spare_servers = wconfig['pm.max_spare_servers'] + www_request_terminate_time = (wconfig + ['request_terminate_timeout']) + try: + www_xdebug = (wconfig + ['php_admin_flag[xdebug.profiler_enable' + '_trigger]']) + except Exception as e: + Log.debug(self, "{0}".format(e)) + www_xdebug = 'off' + + config.read('/etc/php/8.1/fpm/pool.d/debug.conf') + debug_listen = config['debug']['listen'] + debug_ping_path = config['debug']['ping.path'] + debug_pm_status_path = config['debug']['pm.status_path'] + debug_pm = config['debug']['pm'] + debug_pm_max_requests = config['debug']['pm.max_requests'] + debug_pm_max_children = config['debug']['pm.max_children'] + debug_pm_start_servers = config['debug']['pm.start_servers'] + debug_pm_min_spare_servers = config['debug']['pm.min_spare_servers'] + debug_pm_max_spare_servers = config['debug']['pm.max_spare_servers'] + debug_request_terminate = (config['debug'] + ['request_terminate_timeout']) + try: + debug_xdebug = (config['debug']['php_admin_flag[xdebug.profiler_' + 'enable_trigger]']) + except Exception as e: + Log.debug(self, "{0}".format(e)) + debug_xdebug = 'off' + + data = dict(version=version, expose_php=expose_php, + memory_limit=memory_limit, post_max_size=post_max_size, + upload_max_filesize=upload_max_filesize, + max_execution_time=max_execution_time, + www_listen=www_listen, www_ping_path=www_ping_path, + www_pm_status_path=www_pm_status_path, www_pm=www_pm, + www_pm_max_requests=www_pm_max_requests, + www_pm_max_children=www_pm_max_children, + www_pm_start_servers=www_pm_start_servers, + www_pm_min_spare_servers=www_pm_min_spare_servers, + www_pm_max_spare_servers=www_pm_max_spare_servers, + www_request_terminate_timeout=www_request_terminate_time, + www_xdebug_profiler_enable_trigger=www_xdebug, + debug_listen=debug_listen, debug_ping_path=debug_ping_path, + debug_pm_status_path=debug_pm_status_path, + debug_pm=debug_pm, + debug_pm_max_requests=debug_pm_max_requests, + debug_pm_max_children=debug_pm_max_children, + debug_pm_start_servers=debug_pm_start_servers, + debug_pm_min_spare_servers=debug_pm_min_spare_servers, + debug_pm_max_spare_servers=debug_pm_max_spare_servers, + debug_request_terminate_timeout=debug_request_terminate, + debug_xdebug_profiler_enable_trigger=debug_xdebug) + self.app.render((data), 'info_php.mustache') + @expose(hide=True) def info_mysql(self): """Display MySQL information""" @@ -368,7 +548,8 @@ class WOInfoController(CementBaseController): pargs = self.app.pargs if (not pargs.nginx and not pargs.php and not pargs.mysql and not pargs.php73 and - not pargs.php74): + not pargs.php74 and not pargs.php80 and + not pargs.php81): pargs.nginx = True pargs.php = True pargs.mysql = True @@ -376,6 +557,10 @@ class WOInfoController(CementBaseController): pargs.php73 = True if WOAptGet.is_installed(self, 'php7.4-fpm'): pargs.php74 = True + if WOAptGet.is_installed(self, 'php8.0-fpm'): + pargs.php80 = True + if WOAptGet.is_installed(self, 'php8.1-fpm'): + pargs.php81 = True if pargs.nginx: if ((not WOAptGet.is_installed(self, 'nginx-custom')) and @@ -402,6 +587,18 @@ class WOInfoController(CementBaseController): else: Log.info(self, "PHP 7.4 is not installed") + if pargs.php80: + if WOAptGet.is_installed(self, 'php8.0-fpm'): + self.info_php80() + else: + Log.info(self, "PHP 8.0 is not installed") + + if pargs.php81: + if WOAptGet.is_installed(self, 'php8.1-fpm'): + self.info_php81() + else: + Log.info(self, "PHP 8.1 is not installed") + if pargs.mysql: if WOShellExec.cmd_exec(self, "/usr/bin/mysqladmin ping"): self.info_mysql() diff --git a/wo/cli/plugins/site_create.py b/wo/cli/plugins/site_create.py index aa8d5b3..e43aae9 100644 --- a/wo/cli/plugins/site_create.py +++ b/wo/cli/plugins/site_create.py @@ -39,6 +39,10 @@ class WOSiteCreateController(CementBaseController): dict(help="create php 7.3 site", action='store_true')), (['--php74'], dict(help="create php 7.4 site", action='store_true')), + (['--php80'], + dict(help="create php 8.0 site", action='store_true')), + (['--php81'], + dict(help="create php 8.1 site", action='store_true')), (['--mysql'], dict(help="create mysql site", action='store_true')), (['--wp'], @@ -167,7 +171,7 @@ class WOSiteCreateController(CementBaseController): data['port'] = port data['basic'] = True - if pargs.php72 or pargs.php73 or pargs.php74: + if pargs.php72 or pargs.php73 or pargs.php74 or pargs.php80 or pargs.php81: data = dict( site_name=wo_domain, www_domain=wo_www_domain, static=False, basic=False, @@ -214,6 +218,8 @@ class WOSiteCreateController(CementBaseController): data['php73'] = False data['php74'] = False data['php72'] = False + data['php80'] = False + data['php81'] = False if data and pargs.php73: data['php73'] = True @@ -224,6 +230,12 @@ class WOSiteCreateController(CementBaseController): elif data and pargs.php72: data['php72'] = True data['wo_php'] = 'php72' + elif data and pargs.php80: + data['php80'] = True + data['wo_php'] = 'php80' + elif data and pargs.php81: + data['php81'] = True + data['wo_php'] = 'php81' else: if self.app.config.has_section('php'): config_php_ver = self.app.config.get( @@ -237,6 +249,12 @@ class WOSiteCreateController(CementBaseController): elif config_php_ver == '7.4': data['php74'] = True data['wo_php'] = 'php74' + elif config_php_ver == '8.0': + data['php80'] = True + data['wo_php'] = 'php80' + elif config_php_ver == '8.1': + data['php81'] = True + data['wo_php'] = 'php81' else: data['php73'] = True data['wo_php'] = 'php73' @@ -306,6 +324,10 @@ class WOSiteCreateController(CementBaseController): php_version = "7.2" elif data['php74']: php_version = "7.4" + elif data['php80']: + php_version = "8.0" + elif data['php81']: + php_version = "8.1" else: php_version = "7.3" diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index d824641..26a962d 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -780,7 +780,7 @@ def sitebackup(self, data): .format(data['site_name']), backup_path) if data['currsitetype'] in ['html', 'php', 'php72', 'php74', - 'php73', 'proxy', 'mysql']: + 'php73', 'php80', 'php81', 'proxy', 'mysql']: if not data['wp']: Log.info(self, "Backing up Webroot \t\t", end='') WOFileUtils.copyfiles(self, wo_site_webroot + @@ -840,7 +840,7 @@ def site_package_check(self, stype): stack.app = self.app pargs = self.app.pargs if stype in ['html', 'proxy', 'php', 'php72', 'mysql', 'wp', 'wpsubdir', - 'wpsubdomain', 'php73', 'php74']: + 'wpsubdomain', 'php73', 'php74', 'php80', 'php81']: Log.debug(self, "Setting apt_packages variable for Nginx") # Check if server has nginx-custom package @@ -877,14 +877,20 @@ def site_package_check(self, stype): '\t$request_filename;\n') if ((pargs.php and pargs.php73) or (pargs.php and pargs.php74) or - (pargs.php and pargs.php72) or + (pargs.php and pargs.php72) or (pargs.php and pargs.php80) or + (pargs.php and pargs.php81) or (pargs.php73 and pargs.php74) or (pargs.php72 and pargs.php73) or - (pargs.php72 and pargs.php74)): + (pargs.php72 and pargs.php74) or (pargs.php73 and pargs.php80) or + (pargs.php74 and pargs.php80) or (pargs.php80 and pargs.php81) or + (pargs.php72 and pargs.php80) or (pargs.php72 and pargs.php81) or + (pargs.php73 and pargs.php81) or (pargs.php74 and pargs.php81) or + (pargs.php80 and pargs.php81)): Log.error( self, "Error: two different PHP versions cannot be " "combined within the same WordOps site") if ((not pargs.php72) and (not pargs.php73) and (not pargs.php74) and + (not pargs.php80) and (not pargs.php81) and stype in ['php', 'mysql', 'wp', 'wpsubdir', 'wpsubdomain']): Log.debug(self, "Setting apt_packages variable for PHP") @@ -902,6 +908,12 @@ def site_package_check(self, stype): elif config_php_ver == '7.4': php_check = 'php7.4-fpm' php_to_setup = WOVar.wo_php74 + elif config_php_ver == '8.0': + php_check = 'php8.0-fpm' + php_to_setup = WOVar.wo_php80 + elif config_php_ver == '8.1': + php_check = 'php8.1-fpm' + php_to_setup = WOVar.wo_php81 else: php_check = 'php7.3-fpm' php_to_setup = WOVar.wo_php73 @@ -930,6 +942,18 @@ def site_package_check(self, stype): if not WOAptGet.is_installed(self, 'php7.4-fpm'): apt_packages = apt_packages + WOVar.wo_php74 + WOVar.wo_php_extra + if pargs.php80 and stype in ['php80', 'mysql', 'wp', + 'wpsubdir', 'wpsubdomain']: + Log.debug(self, "Setting apt_packages variable for PHP 8.0") + if not WOAptGet.is_installed(self, 'php8.0-fpm'): + apt_packages = apt_packages + WOVar.wo_php80 + WOVar.wo_php_extra + + if pargs.php81 and stype in ['php81', 'mysql', 'wp', + 'wpsubdir', 'wpsubdomain']: + Log.debug(self, "Setting apt_packages variable for PHP 8.1") + if not WOAptGet.is_installed(self, 'php8.1-fpm'): + apt_packages = apt_packages + WOVar.wo_php81 + WOVar.wo_php_extra + if stype in ['mysql', 'wp', 'wpsubdir', 'wpsubdomain']: Log.debug(self, "Setting apt_packages variable for MySQL") if not WOShellExec.cmd_exec(self, "/usr/bin/mysqladmin ping"): @@ -1111,7 +1135,7 @@ def detSitePar(opts): for key, val in opts.items(): if val and key in ['html', 'php', 'mysql', 'wp', 'wpsubdir', 'wpsubdomain', 'php72', - 'php73', 'php74']: + 'php73', 'php74', 'php80', 'php81']: typelist.append(key) elif val and key in ['wpfc', 'wpsc', 'wpredis', 'wprocket', 'wpce']: cachelist.append(key) @@ -1145,6 +1169,18 @@ def detSitePar(opts): cachetype = 'basic' else: cachetype = cachelist[0] + elif False not in [x in ('php80', 'mysql', 'html') for x in typelist]: + sitetype = 'mysql' + if not cachelist: + cachetype = 'basic' + else: + cachetype = cachelist[0] + elif False not in [x in ('php81', 'mysql', 'html') for x in typelist]: + sitetype = 'mysql' + if not cachelist: + cachetype = 'basic' + else: + cachetype = cachelist[0] elif False not in [x in ('php', 'mysql') for x in typelist]: sitetype = 'mysql' if not cachelist: @@ -1169,6 +1205,18 @@ def detSitePar(opts): cachetype = 'basic' else: cachetype = cachelist[0] + elif False not in [x in ('php80', 'mysql') for x in typelist]: + sitetype = 'mysql' + if not cachelist: + cachetype = 'basic' + else: + cachetype = cachelist[0] + elif False not in [x in ('php81', 'mysql') for x in typelist]: + sitetype = 'mysql' + if not cachelist: + cachetype = 'basic' + else: + cachetype = cachelist[0] elif False not in [x in ('html', 'mysql') for x in typelist]: sitetype = 'mysql' if not cachelist: @@ -1211,6 +1259,18 @@ def detSitePar(opts): cachetype = 'basic' else: cachetype = cachelist[0] + elif False not in [x in ('wp', 'php80') for x in typelist]: + sitetype = 'wp' + if not cachelist: + cachetype = 'basic' + else: + cachetype = cachelist[0] + elif False not in [x in ('wp', 'php81') for x in typelist]: + sitetype = 'wp' + if not cachelist: + cachetype = 'basic' + else: + cachetype = cachelist[0] elif False not in [x in ('wpsubdir', 'php72') for x in typelist]: sitetype = 'wpsubdir' if not cachelist: @@ -1229,6 +1289,18 @@ def detSitePar(opts): cachetype = 'basic' else: cachetype = cachelist[0] + elif False not in [x in ('wpsubdir', 'php80') for x in typelist]: + sitetype = 'wpsubdir' + if not cachelist: + cachetype = 'basic' + else: + cachetype = cachelist[0] + elif False not in [x in ('wpsubdir', 'php81') for x in typelist]: + sitetype = 'wpsubdir' + if not cachelist: + cachetype = 'basic' + else: + cachetype = cachelist[0] elif False not in [x in ('wpsubdomain', 'php72') for x in typelist]: sitetype = 'wpsubdomain' if not cachelist: @@ -1247,6 +1319,18 @@ def detSitePar(opts): cachetype = 'basic' else: cachetype = cachelist[0] + elif False not in [x in ('wpsubdomain', 'php80') for x in typelist]: + sitetype = 'wpsubdomain' + if not cachelist: + cachetype = 'basic' + else: + cachetype = cachelist[0] + elif False not in [x in ('wpsubdomain', 'php81') for x in typelist]: + sitetype = 'wpsubdomain' + if not cachelist: + cachetype = 'basic' + else: + cachetype = cachelist[0] else: raise RuntimeError("could not determine site and cache type") else: @@ -1262,6 +1346,12 @@ def detSitePar(opts): elif (not typelist or "php74" in typelist) and cachelist: sitetype = 'wp' cachetype = cachelist[0] + elif (not typelist or "php80" in typelist) and cachelist: + sitetype = 'wp' + cachetype = cachelist[0] + elif (not typelist or "php81" in typelist) and cachelist: + sitetype = 'wp' + cachetype = cachelist[0] elif typelist and (not cachelist): sitetype = typelist[0] cachetype = 'basic' diff --git a/wo/cli/plugins/site_update.py b/wo/cli/plugins/site_update.py index ecabd3d..6fdd626 100644 --- a/wo/cli/plugins/site_update.py +++ b/wo/cli/plugins/site_update.py @@ -47,6 +47,10 @@ class WOSiteUpdateController(CementBaseController): dict(help="update to php73 site", action='store_true')), (['--php74'], dict(help="update to php74 site", action='store_true')), + (['--php80'], + dict(help="update to php80 site", action='store_true')), + (['--php81'], + dict(help="update to php81 site", action='store_true')), (['--mysql'], dict(help="update to mysql site", action='store_true')), (['--wp'], @@ -111,6 +115,7 @@ class WOSiteUpdateController(CementBaseController): Log.error(self, "No site can be updated to html") if not (pargs.php or pargs.php72 or pargs.php73 or pargs.php74 or + pargs.php80 or pargs.php81 or pargs.mysql or pargs.wp or pargs.wpsubdir or pargs.wpsubdomain or pargs.wpfc or pargs.wpsc or pargs.wprocket or pargs.wpce or @@ -143,6 +148,8 @@ class WOSiteUpdateController(CementBaseController): php73 = False php74 = False php72 = False + php80 = False + php81 = False data = dict() try: @@ -191,11 +198,13 @@ class WOSiteUpdateController(CementBaseController): old_php72 = bool(check_php_version == "7.2") old_php73 = bool(check_php_version == "7.3") old_php74 = bool(check_php_version == "7.4") + old_php80 = bool(check_php_version == "8.0") + old_php81 = bool(check_php_version == "8.1") if ((pargs.password or pargs.hsts or pargs.ngxblocker or pargs.letsencrypt == 'renew') and not ( pargs.html or pargs.php or pargs.php72 or pargs.php73 or - pargs.php74 or + pargs.php74 or pargs.php80 or pargs.php81 or pargs.mysql or pargs.wp or pargs.wpfc or pargs.wpsc or pargs.wprocket or pargs.wpce or pargs.wpsubdir or pargs.wpsubdomain)): @@ -263,16 +272,18 @@ class WOSiteUpdateController(CementBaseController): if (((stype == 'php' and oldsitetype not in ['html', 'proxy', 'php', 'php72', - 'php73', 'php74']) or + 'php73', 'php74', 'php80', 'php81']) or (stype == 'mysql' and oldsitetype not in [ - 'html', 'php', 'php72', 'php73', 'php74', 'proxy']) or + 'html', 'php', 'php72', 'php73', 'php74','php80', 'php81', + 'proxy']) or (stype == 'wp' and oldsitetype not in [ - 'html', 'php', 'php72', 'php73', 'php74', 'mysql', - 'proxy', 'wp']) or + 'html', 'php', 'php72', 'php73', 'php74', 'php80', 'php81', + 'mysql', 'proxy', 'wp']) or (stype == 'wpsubdir' and oldsitetype in ['wpsubdomain']) or (stype == 'wpsubdomain' and oldsitetype in ['wpsubdir']) or (stype == oldsitetype and cache == oldcachetype)) and - not (pargs.php72 or pargs.php73 or pargs.php74)): + not (pargs.php72 or pargs.php73 or pargs.php74 or pargs.php80 or + pargs.php81)): Log.info(self, Log.FAIL + "can not update {0} {1} to {2} {3}". format(oldsitetype, oldcachetype, stype, cache)) return 1 @@ -291,7 +302,7 @@ class WOSiteUpdateController(CementBaseController): data = dict( site_name=wo_domain, www_domain=wo_www_domain, static=False, basic=True, wp=False, wpfc=False, - php72=False, php73=False, php74=False, + php72=False, php73=False, php74=False, php80=False, php81=False, wpsc=False, wpredis=False, wprocket=False, wpce=False, multisite=False, wpsubdir=False, webroot=wo_site_webroot, currsitetype=oldsitetype, currcachetype=oldcachetype) @@ -316,9 +327,9 @@ class WOSiteUpdateController(CementBaseController): data['wpsubdir'] = True if ((pargs.php72 or pargs.php73 or - pargs.php74) and (not data)): + pargs.php74 or pargs.php80 or pargs.php81) and (not data)): Log.debug( - self, "pargs php72, or php73, or php74 enabled") + self, "pargs php72, or php73, or php74, or php80, or php81 enabled") data = dict( site_name=wo_domain, www_domain=wo_www_domain, @@ -333,7 +344,8 @@ class WOSiteUpdateController(CementBaseController): data['multisite'] = False data['wpsubdir'] = False elif (oldsitetype == 'php' or oldsitetype == 'mysql' or - oldsitetype == 'php73'or oldsitetype == 'php74'): + oldsitetype == 'php73' or oldsitetype == 'php74' or + oldsitetype == 'php80' or oldsitetype == 'php81'): data['static'] = False data['wp'] = False data['multisite'] = False @@ -409,6 +421,14 @@ class WOSiteUpdateController(CementBaseController): Log.debug(self, "pargs.php74 detected") data['php74'] = True php74 = True + elif pargs.php80: + Log.debug(self, "pargs.php80 detected") + data['php80'] = True + php80 = True + elif pargs.php81: + Log.debug(self, "pargs.php81 detected") + data['php81'] = True + php81 = True if pargs.php72: if php72 is old_php72: @@ -428,8 +448,21 @@ class WOSiteUpdateController(CementBaseController): "site") pargs.php74 = False + if pargs.php80: + if php80 is old_php80: + Log.info(self, "PHP 8.0 is already enabled for given " + "site") + pargs.php80 = False + + if pargs.php81: + if php81 is old_php81: + Log.info(self, "PHP 8.1 is already enabled for given " + "site") + pargs.php81 = False + if (data and (not pargs.php73) and - (not pargs.php74) and (not pargs.php72)): + (not pargs.php74) and (not pargs.php72) and + (not pargs.php80) and (not pargs.php81)): data['php72'] = bool(old_php72 is True) Log.debug(self, "data php72 = {0}".format(data['php72'])) php72 = bool(old_php72 is True) @@ -439,6 +472,12 @@ class WOSiteUpdateController(CementBaseController): data['php74'] = bool(old_php74 is True) Log.debug(self, "data php74 = {0}".format(data['php74'])) php74 = bool(old_php74 is True) + data['php80'] = bool(old_php80 is True) + Log.debug(self, "data php80 = {0}".format(data['php80'])) + php80 = bool(old_php80 is True) + data['php80'] = bool(old_php80 is True) + Log.debug(self, "data php80 = {0}".format(data['php80'])) + php80 = bool(old_php80 is True) if pargs.letsencrypt: acme_domains = [] @@ -516,7 +555,9 @@ class WOSiteUpdateController(CementBaseController): cache = 'wpce' if ((php73 is old_php73) and (php72 is old_php72) and - (php74 is old_php74) and (stype == oldsitetype and + (php74 is old_php74) and (php80 is old_php80) and + (php81 is old_php81) and + (stype == oldsitetype and cache == oldcachetype)): Log.debug(self, "Nothing to update") return 1 @@ -530,6 +571,12 @@ class WOSiteUpdateController(CementBaseController): elif php72 is True: data['wo_php'] = 'php72' check_php_version = '7.2' + elif php80 is True: + data['wo_php'] = 'php80' + check_php_version = '8.0' + elif php81 is True: + data['wo_php'] = 'php81' + check_php_version = '8.1' else: data['wo_php'] = 'php73' check_php_version = '7.3' @@ -830,7 +877,8 @@ class WOSiteUpdateController(CementBaseController): # Setup WordPress if old sites are html/php/mysql sites if data['wp'] and oldsitetype in ['html', 'proxy', 'php', 'php72', - 'mysql', 'php73', 'php74']: + 'mysql', 'php73', 'php74', 'php80', + 'php81',]: try: wo_wp_creds = setupwordpress(self, data) except SiteError as e: diff --git a/wo/cli/plugins/stack.py b/wo/cli/plugins/stack.py index 0053128..6854bde 100644 --- a/wo/cli/plugins/stack.py +++ b/wo/cli/plugins/stack.py @@ -47,6 +47,10 @@ class WOStackController(CementBaseController): dict(help='Install PHP 7.3 stack', action='store_true')), (['--php74'], dict(help='Install PHP 7.4 stack', action='store_true')), + (['--php80'], + dict(help='Install PHP 8.0 stack', action='store_true')), + (['--php81'], + dict(help='Install PHP 8.1 stack', action='store_true')), (['--mysql'], dict(help='Install MySQL stack', action='store_true')), (['--mariadb'], @@ -117,6 +121,7 @@ class WOStackController(CementBaseController): # Default action for stack installation if not (pargs.web or pargs.admin or pargs.nginx or pargs.php or pargs.php72 or pargs.php73 or pargs.php74 or + pargs.php80 or pargs.php81 or pargs.mysql or pargs.wpcli or pargs.phpmyadmin or pargs.composer or pargs.netdata or pargs.composer or pargs.dashboard or pargs.fail2ban or pargs.security or @@ -142,6 +147,8 @@ class WOStackController(CementBaseController): pargs.admin = True pargs.php73 = True pargs.php74 = True + pargs.php80 = True + pargs.php81 = True pargs.redis = True pargs.proftpd = True @@ -155,6 +162,10 @@ class WOStackController(CementBaseController): pargs.php73 = True elif config_php_ver == '7.4': pargs.php74 = True + elif config_php_ver == '8.0': + pargs.php80 = True + elif config_php_ver == '8.1': + pargs.php80 = True else: pargs.php74 = True pargs.nginx = True @@ -226,6 +237,26 @@ class WOStackController(CementBaseController): Log.debug(self, "PHP 7.4 already installed") Log.info(self, "PHP 7.4 already installed") + # PHP 8.0 + if pargs.php80: + Log.debug(self, "Setting apt_packages variable for PHP 8.0") + if not WOAptGet.is_installed(self, 'php8.0-fpm'): + apt_packages = (apt_packages + WOVar.wo_php80 + + WOVar.wo_php_extra) + else: + Log.debug(self, "PHP 8.0 already installed") + Log.info(self, "PHP 8.0 already installed") + + # PHP 8.1 + if pargs.php81: + Log.debug(self, "Setting apt_packages variable for PHP 8.1") + if not WOAptGet.is_installed(self, 'php8.1-fpm'): + apt_packages = (apt_packages + WOVar.wo_php81 + + WOVar.wo_php_extra) + else: + Log.debug(self, "PHP 8.1 already installed") + Log.info(self, "PHP 8.1 already installed") + # MariaDB 10.3 if pargs.mysql: pargs.mysqltuner = True @@ -485,7 +516,9 @@ class WOStackController(CementBaseController): pargs.mysql = True if not (WOAptGet.is_installed(self, 'php7.2-fpm') or WOAptGet.is_installed(self, 'php7.3-fpm') or - WOAptGet.is_installed(self, 'php7.4-fpm')): + WOAptGet.is_installed(self, 'php7.4-fpm') or + WOAptGet.is_installed(self, 'php8.0-fpm') or + WOAptGet.is_installed(self, 'php8.1-fpm')): pargs.php74 = True Log.debug(self, "Setting packages variable for utils") packages = packages + [[ @@ -582,7 +615,8 @@ class WOStackController(CementBaseController): (not pargs.ufw) and (not pargs.ngxblocker) and (not pargs.phpredisadmin) and (not pargs.sendmail) and (not pargs.php73) and (not pargs.php74) and - (not pargs.php72) and (not pargs.all)): + (not pargs.php72) (not pargs.php80) and + (not pargs.php81) and (not pargs.all)): self.app.args.print_help() if pargs.php: @@ -636,7 +670,9 @@ class WOStackController(CementBaseController): if (WOAptGet.is_installed(self, 'php7.2-fpm')): apt_packages = apt_packages + WOVar.wo_php72 if not (WOAptGet.is_installed(self, 'php7.3-fpm') or - WOAptGet.is_installed(self, 'php7.4-fpm')): + WOAptGet.is_installed(self, 'php7.4-fpm') or + WOAptGet.is_installed(self, 'php8.0-fpm') or + WOAptGet.is_installed(self, 'php8.1-fpm')): apt_packages = apt_packages + WOVar.wo_php_extra else: Log.debug(self, "PHP 7.2 is not installed") @@ -648,7 +684,9 @@ class WOStackController(CementBaseController): if WOAptGet.is_installed(self, 'php7.3-fpm'): apt_packages = apt_packages + WOVar.wo_php73 if not (WOAptGet.is_installed(self, 'php7.2-fpm') or - WOAptGet.is_installed(self, 'php7.4-fpm')): + WOAptGet.is_installed(self, 'php7.4-fpm') or + WOAptGet.is_installed(self, 'php8.0-fpm') or + WOAptGet.is_installed(self, 'php8.1-fpm')): apt_packages = apt_packages + WOVar.wo_php_extra else: Log.debug(self, "PHP 7.3 is not installed") @@ -660,12 +698,42 @@ class WOStackController(CementBaseController): if WOAptGet.is_installed(self, 'php7.4-fpm'): apt_packages = apt_packages + WOVar.wo_php74 if not (WOAptGet.is_installed(self, 'php7.3-fpm') or - WOAptGet.is_installed(self, 'php7.2-fpm')): + WOAptGet.is_installed(self, 'php7.2-fpm') or + WOAptGet.is_installed(self, 'php8.0-fpm') or + WOAptGet.is_installed(self, 'php8.1-fpm')): apt_packages = apt_packages + WOVar.wo_php_extra else: Log.debug(self, "PHP 7.4 is not installed") Log.info(self, "PHP 7.4 is not installed") + # PHP 8.0 + if pargs.php80: + Log.debug(self, "Setting apt_packages variable for PHP 8.0") + if WOAptGet.is_installed(self, 'php8.0-fpm'): + apt_packages = apt_packages + WOVar.wo_php80 + if not (WOAptGet.is_installed(self, 'php7.3-fpm') or + WOAptGet.is_installed(self, 'php7.2-fpm') or + WOAptGet.is_installed(self, 'php7.4-fpm') or + WOAptGet.is_installed(self, 'php8.1-fpm')): + apt_packages = apt_packages + WOVar.wo_php_extra + else: + Log.debug(self, "PHP 8.0 is not installed") + Log.info(self, "PHP 8.0 is not installed") + + # PHP 8.1 + if pargs.php81: + Log.debug(self, "Setting apt_packages variable for PHP 8.1") + if WOAptGet.is_installed(self, 'php8.1-fpm'): + apt_packages = apt_packages + WOVar.wo_php81 + if not (WOAptGet.is_installed(self, 'php7.3-fpm') or + WOAptGet.is_installed(self, 'php7.2-fpm') or + WOAptGet.is_installed(self, 'php7.4-fpm') or + WOAptGet.is_installed(self, 'php8.0-fpm')): + apt_packages = apt_packages + WOVar.wo_php_extra + else: + Log.debug(self, "PHP 8.1 is not installed") + Log.info(self, "PHP 8.1 is not installed") + # REDIS if pargs.redis: if WOAptGet.is_installed(self, 'redis-server'): @@ -898,6 +966,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.php80) and (not pargs.php81) and (not pargs.php73) and (not pargs.php74) and (not pargs.php72) and (not pargs.all)): self.app.args.print_help() @@ -913,6 +982,8 @@ class WOStackController(CementBaseController): pargs.admin = True pargs.php73 = True pargs.php74 = True + pargs.php80 = True + pargs.php81 = True pargs.fail2ban = True pargs.proftpd = True pargs.utils = True @@ -966,8 +1037,10 @@ class WOStackController(CementBaseController): if WOAptGet.is_installed(self, 'php7.3-fpm'): apt_packages = apt_packages + WOVar.wo_php73 if not (WOAptGet.is_installed(self, 'php7.2-fpm') or - WOAptGet.is_installed(self, 'php7.4-fpm')): - apt_packages = apt_packages + WOVar.wo_php_extra + WOAptGet.is_installed(self, 'php7.4-fpm') or + WOAptGet.is_installed(self, 'php8.0-fpm') or + WOAptGet.is_installed(self, 'php8.1-fpm')): + apt_packages = apt_packages + WOVar.wo_php_extra else: Log.debug(self, "PHP 7.3 is not installed") Log.info(self, "PHP 7.3 is not installed") @@ -978,12 +1051,42 @@ class WOStackController(CementBaseController): if WOAptGet.is_installed(self, 'php7.4-fpm'): apt_packages = apt_packages + WOVar.wo_php74 if not (WOAptGet.is_installed(self, 'php7.3-fpm') or - WOAptGet.is_installed(self, 'php7.2-fpm')): + WOAptGet.is_installed(self, 'php7.2-fpm') or + WOAptGet.is_installed(self, 'php8.0-fpm') or + WOAptGet.is_installed(self, 'php8.1-fpm')): apt_packages = apt_packages + WOVar.wo_php_extra else: Log.debug(self, "PHP 7.4 is not installed") Log.info(self, "PHP 7.4 is not installed") + # PHP 8.0 + if pargs.php80: + Log.debug(self, "Setting apt_packages variable for PHP 8.0") + if WOAptGet.is_installed(self, 'php8.0-fpm'): + apt_packages = apt_packages + WOVar.wo_php80 + if not (WOAptGet.is_installed(self, 'php7.3-fpm') or + WOAptGet.is_installed(self, 'php7.2-fpm') or + WOAptGet.is_installed(self, 'php7.4-fpm') or + WOAptGet.is_installed(self, 'php8.1-fpm')): + apt_packages = apt_packages + WOVar.wo_php_extra + else: + Log.debug(self, "PHP 8.0 is not installed") + Log.info(self, "PHP 8.0 is not installed") + + # PHP 8.1 + if pargs.php81: + Log.debug(self, "Setting apt_packages variable for PHP 8.1") + if WOAptGet.is_installed(self, 'php8.1-fpm'): + apt_packages = apt_packages + WOVar.wo_php74 + if not (WOAptGet.is_installed(self, 'php7.3-fpm') or + WOAptGet.is_installed(self, 'php7.2-fpm') or + WOAptGet.is_installed(self, 'php8.0-fpm') or + WOAptGet.is_installed(self, 'php7.4-fpm')): + apt_packages = apt_packages + WOVar.wo_php_extra + else: + Log.debug(self, "PHP 8.1 is not installed") + Log.info(self, "PHP 8.1 is not installed") + # REDIS if pargs.redis: if WOAptGet.is_installed(self, 'redis-server'): diff --git a/wo/cli/plugins/stack_pref.py b/wo/cli/plugins/stack_pref.py index 7ad72ed..988172a 100644 --- a/wo/cli/plugins/stack_pref.py +++ b/wo/cli/plugins/stack_pref.py @@ -229,7 +229,7 @@ def post_pref(self, apt_packages, packages, upgrade=False): .format(ngxcom), 'wpsubdir.mustache', data) - wo_php_version = ["php72", "php73", "php74"] + wo_php_version = ["php72", "php73", "php74", "php80" "php81"] for wo_php in wo_php_version: data = dict(upstream="{0}".format(wo_php), release=WOVar.wo_version) @@ -922,6 +922,330 @@ def post_pref(self, apt_packages, packages, upgrade=False): 'upstream.mustache', data, True) WOConf.nginxcommon(self) + # php8.0 configuration + if set(WOVar.wo_php80).issubset(set(apt_packages)): + WOGit.add(self, ["/etc/php"], msg="Adding PHP into Git") + Log.info(self, "Configuring php8.0-fpm") + ngxroot = '/var/www/' + # Create log directories + if not os.path.exists('/var/log/php/8.0/'): + Log.debug(self, 'Creating directory /var/log/php/8.0/') + os.makedirs('/var/log/php/8.0/') + + if not os.path.isfile('/etc/php/8.0/fpm/php.ini.orig'): + WOFileUtils.copyfile(self, '/etc/php/8.0/fpm/php.ini', + '/etc/php/8.0/fpm/php.ini.orig') + + # Parse etc/php/8.0/fpm/php.ini + config = configparser.ConfigParser() + Log.debug(self, "configuring php file /etc/php/8.0/" + "fpm/php.ini") + config.read('/etc/php/8.0/fpm/php.ini.orig') + config['PHP']['expose_php'] = 'Off' + config['PHP']['post_max_size'] = '100M' + config['PHP']['upload_max_filesize'] = '100M' + config['PHP']['max_execution_time'] = '300' + config['PHP']['max_input_time'] = '300' + config['PHP']['max_input_vars'] = '20000' + config['Date']['date.timezone'] = WOVar.wo_timezone + config['opcache']['opcache.enable'] = '1' + config['opcache']['opcache.interned_strings_buffer'] = '8' + config['opcache']['opcache.max_accelerated_files'] = '10000' + config['opcache']['opcache.memory_consumption'] = '256' + config['opcache']['opcache.save_comments'] = '1' + config['opcache']['opcache.revalidate_freq'] = '5' + config['opcache']['opcache.consistency_checks'] = '0' + config['opcache']['opcache.validate_timestamps'] = '1' + config['opcache']['opcache.preload_user'] = 'www-data' + with open('/etc/php/8.0/fpm/php.ini', + encoding='utf-8', mode='w') as configfile: + Log.debug(self, "Writting php configuration into " + "/etc/php/8.0/fpm/php.ini") + config.write(configfile) + + # Render php-fpm pool template for php8.0 + data = dict(pid="/run/php/php8.0-fpm.pid", + error_log="/var/log/php8.0-fpm.log", + include="/etc/php/8.0/fpm/pool.d/*.conf") + WOTemplate.deploy( + self, '/etc/php/8.0/fpm/php-fpm.conf', + 'php-fpm.mustache', data) + + data = dict(pool='www-php80', listen='php80-fpm.sock', + user='www-data', + group='www-data', listenuser='root', + listengroup='www-data', openbasedir=True) + WOTemplate.deploy(self, '/etc/php/8.0/fpm/pool.d/www.conf', + 'php-pool.mustache', data) + data = dict(pool='www-two-php80', listen='php80-two-fpm.sock', + user='www-data', + group='www-data', listenuser='root', + listengroup='www-data', openbasedir=True) + WOTemplate.deploy(self, '/etc/php/8.0/fpm/pool.d/www-two.conf', + 'php-pool.mustache', data) + + # Generate /etc/php/8.0/fpm/pool.d/debug.conf + WOFileUtils.copyfile(self, "/etc/php/8.0/fpm/pool.d/www.conf", + "/etc/php/8.0/fpm/pool.d/debug.conf") + WOFileUtils.searchreplace(self, "/etc/php/8.0/fpm/pool.d/" + "debug.conf", "[www-php80]", "[debug]") + config = configparser.ConfigParser() + config.read('/etc/php/8.0/fpm/pool.d/debug.conf') + config['debug']['listen'] = '127.0.0.1:9180' + config['debug']['rlimit_core'] = 'unlimited' + config['debug']['slowlog'] = '/var/log/php/8.0/slow.log' + config['debug']['request_slowlog_timeout'] = '10s' + with open('/etc/php/8.0/fpm/pool.d/debug.conf', + encoding='utf-8', mode='w') as confifile: + Log.debug(self, "writting PHP 8.0 configuration into " + "/etc/php/8.0/fpm/pool.d/debug.conf") + config.write(confifile) + + with open("/etc/php/8.0/fpm/pool.d/debug.conf", + encoding='utf-8', mode='a') as myfile: + myfile.write( + "php_admin_value[xdebug.profiler_output_dir] " + "= /tmp/ \nphp_admin_value[xdebug.profiler_" + "output_name] = cachegrind.out.%p-%H-%R " + "\nphp_admin_flag[xdebug.profiler_enable" + "_trigger] = on \nphp_admin_flag[xdebug." + "profiler_enable] = off\n") + + # Disable xdebug + if not WOShellExec.cmd_exec( + self, "grep -q \';zend_extension\'" + " /etc/php/8.0/mods-available/xdebug.ini"): + WOFileUtils.searchreplace( + self, "/etc/php/8.0/mods-available/" + "xdebug.ini", + "zend_extension", ";zend_extension") + + # PHP and Debug pull configuration + if not os.path.exists('{0}22222/htdocs/fpm/status/' + .format(ngxroot)): + Log.debug(self, 'Creating directory ' + '{0}22222/htdocs/fpm/status/ ' + .format(ngxroot)) + os.makedirs('{0}22222/htdocs/fpm/status/' + .format(ngxroot)) + open('{0}22222/htdocs/fpm/status/debug80' + .format(ngxroot), + encoding='utf-8', mode='a').close() + open('{0}22222/htdocs/fpm/status/php80' + .format(ngxroot), + encoding='utf-8', mode='a').close() + + # Write info.php + if not os.path.exists('{0}22222/htdocs/php/' + .format(ngxroot)): + Log.debug(self, 'Creating directory ' + '{0}22222/htdocs/php/ ' + .format(ngxroot)) + os.makedirs('{0}22222/htdocs/php' + .format(ngxroot)) + + WOFileUtils.textwrite( + self, "{0}22222/htdocs/php/info.php" + .format(ngxroot), "") + + # write opcache clean for php80 + if not os.path.exists('{0}22222/htdocs/cache/opcache' + .format(ngxroot)): + os.makedirs('{0}22222/htdocs/cache/opcache' + .format(ngxroot)) + WOFileUtils.textwrite( + self, '{0}22222/htdocs/cache/opcache/php80.php' + .format(ngxroot), + '') + + WOFileUtils.chown(self, "{0}22222/htdocs" + .format(ngxroot), + 'www-data', + 'www-data', recursive=True) + + # enable imagick php extension + WOShellExec.cmd_exec(self, 'phpenmod -v ALL imagick') + + # check service restart or rollback configuration + if not WOService.restart_service(self, 'php8.0-fpm'): + WOGit.rollback(self, ["/etc/php"], msg="Rollback PHP") + else: + WOGit.add(self, ["/etc/php"], msg="Adding PHP into Git") + + if os.path.exists('/etc/nginx/conf.d/upstream.conf'): + if not WOFileUtils.grepcheck( + self, '/etc/nginx/conf.d/upstream.conf', 'php81'): + data = dict(php="9000", debug="9001", + php7="9070", debug7="9170", + php8="9080", debug8="9180", + release=WOVar.wo_version) + WOTemplate.deploy( + self, '/etc/nginx/conf.d/upstream.conf', + 'upstream.mustache', data, True) + WOConf.nginxcommon(self) + + # php8.1 configuration + if set(WOVar.wo_php81).issubset(set(apt_packages)): + WOGit.add(self, ["/etc/php"], msg="Adding PHP into Git") + Log.info(self, "Configuring php8.1-fpm") + ngxroot = '/var/www/' + # Create log directories + if not os.path.exists('/var/log/php/8.1/'): + Log.debug(self, 'Creating directory /var/log/php/8.1/') + os.makedirs('/var/log/php/8.1/') + + if not os.path.isfile('/etc/php/8.1/fpm/php.ini.orig'): + WOFileUtils.copyfile(self, '/etc/php/8.1/fpm/php.ini', + '/etc/php/8.1/fpm/php.ini.orig') + + # Parse etc/php/8.1/fpm/php.ini + config = configparser.ConfigParser() + Log.debug(self, "configuring php file /etc/php/8.1/" + "fpm/php.ini") + config.read('/etc/php/8.1/fpm/php.ini.orig') + config['PHP']['expose_php'] = 'Off' + config['PHP']['post_max_size'] = '100M' + config['PHP']['upload_max_filesize'] = '100M' + config['PHP']['max_execution_time'] = '300' + config['PHP']['max_input_time'] = '300' + config['PHP']['max_input_vars'] = '20000' + config['Date']['date.timezone'] = WOVar.wo_timezone + config['opcache']['opcache.enable'] = '1' + config['opcache']['opcache.interned_strings_buffer'] = '8' + config['opcache']['opcache.max_accelerated_files'] = '10000' + config['opcache']['opcache.memory_consumption'] = '256' + config['opcache']['opcache.save_comments'] = '1' + config['opcache']['opcache.revalidate_freq'] = '5' + config['opcache']['opcache.consistency_checks'] = '0' + config['opcache']['opcache.validate_timestamps'] = '1' + config['opcache']['opcache.preload_user'] = 'www-data' + with open('/etc/php/8.1/fpm/php.ini', + encoding='utf-8', mode='w') as configfile: + Log.debug(self, "Writting php configuration into " + "/etc/php/8.1/fpm/php.ini") + config.write(configfile) + + # Render php-fpm pool template for php8.1 + data = dict(pid="/run/php/php8.1-fpm.pid", + error_log="/var/log/php8.1-fpm.log", + include="/etc/php/8.1/fpm/pool.d/*.conf") + WOTemplate.deploy( + self, '/etc/php/8.1/fpm/php-fpm.conf', + 'php-fpm.mustache', data) + + data = dict(pool='www-php81', listen='php81-fpm.sock', + user='www-data', + group='www-data', listenuser='root', + listengroup='www-data', openbasedir=True) + WOTemplate.deploy(self, '/etc/php/8.1/fpm/pool.d/www.conf', + 'php-pool.mustache', data) + data = dict(pool='www-two-php81', listen='php81-two-fpm.sock', + user='www-data', + group='www-data', listenuser='root', + listengroup='www-data', openbasedir=True) + WOTemplate.deploy(self, '/etc/php/8.1/fpm/pool.d/www-two.conf', + 'php-pool.mustache', data) + + # Generate /etc/php/8.1/fpm/pool.d/debug.conf + WOFileUtils.copyfile(self, "/etc/php/8.1/fpm/pool.d/www.conf", + "/etc/php/8.1/fpm/pool.d/debug.conf") + WOFileUtils.searchreplace(self, "/etc/php/8.1/fpm/pool.d/" + "debug.conf", "[www-php81]", "[debug]") + config = configparser.ConfigParser() + config.read('/etc/php/8.1/fpm/pool.d/debug.conf') + config['debug']['listen'] = '127.0.0.1:9181' + config['debug']['rlimit_core'] = 'unlimited' + config['debug']['slowlog'] = '/var/log/php/8.1/slow.log' + config['debug']['request_slowlog_timeout'] = '10s' + with open('/etc/php/8.1/fpm/pool.d/debug.conf', + encoding='utf-8', mode='w') as confifile: + Log.debug(self, "writting PHP 8.1 configuration into " + "/etc/php/8.1/fpm/pool.d/debug.conf") + config.write(confifile) + + with open("/etc/php/8.1/fpm/pool.d/debug.conf", + encoding='utf-8', mode='a') as myfile: + myfile.write( + "php_admin_value[xdebug.profiler_output_dir] " + "= /tmp/ \nphp_admin_value[xdebug.profiler_" + "output_name] = cachegrind.out.%p-%H-%R " + "\nphp_admin_flag[xdebug.profiler_enable" + "_trigger] = on \nphp_admin_flag[xdebug." + "profiler_enable] = off\n") + + # Disable xdebug + if not WOShellExec.cmd_exec( + self, "grep -q \';zend_extension\'" + " /etc/php/8.1/mods-available/xdebug.ini"): + WOFileUtils.searchreplace( + self, "/etc/php/8.1/mods-available/" + "xdebug.ini", + "zend_extension", ";zend_extension") + + # PHP and Debug pull configuration + if not os.path.exists('{0}22222/htdocs/fpm/status/' + .format(ngxroot)): + Log.debug(self, 'Creating directory ' + '{0}22222/htdocs/fpm/status/ ' + .format(ngxroot)) + os.makedirs('{0}22222/htdocs/fpm/status/' + .format(ngxroot)) + open('{0}22222/htdocs/fpm/status/debug81' + .format(ngxroot), + encoding='utf-8', mode='a').close() + open('{0}22222/htdocs/fpm/status/php81' + .format(ngxroot), + encoding='utf-8', mode='a').close() + + # Write info.php + if not os.path.exists('{0}22222/htdocs/php/' + .format(ngxroot)): + Log.debug(self, 'Creating directory ' + '{0}22222/htdocs/php/ ' + .format(ngxroot)) + os.makedirs('{0}22222/htdocs/php' + .format(ngxroot)) + + WOFileUtils.textwrite( + self, "{0}22222/htdocs/php/info.php" + .format(ngxroot), "") + + # write opcache clean for php81 + if not os.path.exists('{0}22222/htdocs/cache/opcache' + .format(ngxroot)): + os.makedirs('{0}22222/htdocs/cache/opcache' + .format(ngxroot)) + WOFileUtils.textwrite( + self, '{0}22222/htdocs/cache/opcache/php81.php' + .format(ngxroot), + '') + + WOFileUtils.chown(self, "{0}22222/htdocs" + .format(ngxroot), + 'www-data', + 'www-data', recursive=True) + + # enable imagick php extension + WOShellExec.cmd_exec(self, 'phpenmod -v ALL imagick') + + # check service restart or rollback configuration + if not WOService.restart_service(self, 'php8.1-fpm'): + WOGit.rollback(self, ["/etc/php"], msg="Rollback PHP") + else: + WOGit.add(self, ["/etc/php"], msg="Adding PHP into Git") + + if os.path.exists('/etc/nginx/conf.d/upstream.conf'): + if not WOFileUtils.grepcheck( + self, '/etc/nginx/conf.d/upstream.conf', 'php81'): + data = dict(php="9000", debug="9001", + php7="9070", debug7="9170", + php8="9080", debug8="9180", + release=WOVar.wo_version) + WOTemplate.deploy( + self, '/etc/nginx/conf.d/upstream.conf', + 'upstream.mustache', data, True) + WOConf.nginxcommon(self) + # create mysql config if it doesn't exist if "mariadb-server" in apt_packages: WOGit.add(self, ["/etc/mysql"], msg="Adding MySQL into Git") diff --git a/wo/cli/plugins/stack_services.py b/wo/cli/plugins/stack_services.py index a775565..7999b03 100644 --- a/wo/cli/plugins/stack_services.py +++ b/wo/cli/plugins/stack_services.py @@ -24,6 +24,8 @@ class WOStackStatusController(CementBaseController): pargs.php72 or pargs.php73 or pargs.php74 or + pargs.php80 or + pargs.php81 or pargs.mysql or pargs.redis or pargs.fail2ban or @@ -56,6 +58,14 @@ class WOStackStatusController(CementBaseController): services = services + ['php7.4-fpm'] else: Log.info(self, "PHP7.4-FPM is not installed") + if os.path.exists('{0}'.format(wo_system) + 'php8.0-fpm.service'): + services = services + ['php8.0-fpm'] + else: + Log.info(self, "PHP8.0-FPM is not installed") + if os.path.exists('{0}'.format(wo_system) + 'php8.1-fpm.service'): + services = services + ['php8.1-fpm'] + else: + Log.info(self, "PHP8.1-FPM is not installed") if pargs.php72: if os.path.exists('{0}'.format(wo_system) + 'php7.2-fpm.service'): @@ -75,6 +85,18 @@ class WOStackStatusController(CementBaseController): else: Log.info(self, "PHP7.4-FPM is not installed") + if pargs.php80: + if os.path.exists('{0}'.format(wo_system) + 'php8.0-fpm.service'): + services = services + ['php8.0-fpm'] + else: + Log.info(self, "PHP8.0-FPM is not installed") + + if pargs.php81: + if os.path.exists('{0}'.format(wo_system) + 'php8.1-fpm.service'): + services = services + ['php8.1-fpm'] + else: + Log.info(self, "PHP8.1-FPM is not installed") + if pargs.mysql: if ((WOVar.wo_mysql_host == "localhost") or (WOVar.wo_mysql_host == "127.0.0.1")): @@ -125,7 +147,7 @@ class WOStackStatusController(CementBaseController): pargs = self.app.pargs if not (pargs.nginx or pargs.php or pargs.php72 or pargs.php73 or - pargs.php74 or + pargs.php74 or pargs.php80 or pargs.php81 or pargs.mysql or pargs.fail2ban or pargs.netdata or @@ -173,6 +195,18 @@ class WOStackStatusController(CementBaseController): else: Log.info(self, "PHP7.4-FPM is not installed") + if pargs.php80: + if os.path.exists('{0}'.format(wo_system) + 'php8.0-fpm.service'): + services = services + ['php8.0-fpm'] + else: + Log.info(self, "PHP8.0-FPM is not installed") + + if pargs.php81: + if os.path.exists('{0}'.format(wo_system) + 'php8.1-fpm.service'): + services = services + ['php8.1-fpm'] + else: + Log.info(self, "PHP8.1-FPM is not installed") + if pargs.mysql: if ((WOVar.wo_mysql_host == "localhost") or (WOVar.wo_mysql_host == "127.0.0.1")): @@ -223,7 +257,7 @@ class WOStackStatusController(CementBaseController): pargs = self.app.pargs if not (pargs.nginx or pargs.php or pargs.php72 or pargs.php73 or - pargs.php74 or + pargs.php74 or pargs.php80 or pargs.php81 or pargs.mysql or pargs.netdata or pargs.proftpd or @@ -251,6 +285,14 @@ class WOStackStatusController(CementBaseController): Log.info(self, "PHP7.3-FPM is not installed") if os.path.exists('{0}'.format(wo_system) + 'php7.4-fpm.service'): services = services + ['php7.4-fpm'] + else: + Log.info(self, "PHP8.0-FPM is not installed") + if os.path.exists('{0}'.format(wo_system) + 'php8.0-fpm.service'): + services = services + ['php8.0-fpm'] + else: + Log.info(self, "PHP8.1-FPM is not installed") + if os.path.exists('{0}'.format(wo_system) + 'php8.1-fpm.service'): + services = services + ['php8.1-fpm'] else: Log.info(self, "PHP7.4-FPM is not installed") @@ -272,6 +314,18 @@ class WOStackStatusController(CementBaseController): else: Log.info(self, "PHP7.4-FPM is not installed") + if pargs.php80: + if os.path.exists('{0}'.format(wo_system) + 'php8.0-fpm.service'): + services = services + ['php8.0-fpm'] + else: + Log.info(self, "PHP8.0-FPM is not installed") + + if pargs.php81: + if os.path.exists('{0}'.format(wo_system) + 'php8.1-fpm.service'): + services = services + ['php8.1-fpm'] + else: + Log.info(self, "PHP8.1-FPM is not installed") + if pargs.mysql: if ((WOVar.wo_mysql_host == "localhost") or (WOVar.wo_mysql_host == "127.0.0.1")): @@ -324,6 +378,8 @@ class WOStackStatusController(CementBaseController): pargs.php72 or pargs.php73 or pargs.php74 or + pargs.php80 or + pargs.php81 or pargs.mysql or pargs.netdata or pargs.proftpd or @@ -374,6 +430,18 @@ class WOStackStatusController(CementBaseController): else: Log.info(self, "PHP7.4-FPM is not installed") + if pargs.php80: + if os.path.exists('{0}'.format(wo_system) + 'php8.0-fpm.service'): + services = services + ['php8.0-fpm'] + else: + Log.info(self, "PHP8.0-FPM is not installed") + + if pargs.php81: + if os.path.exists('{0}'.format(wo_system) + 'php8.1-fpm.service'): + services = services + ['php8.1-fpm'] + else: + Log.info(self, "PHP8.1-FPM is not installed") + if pargs.mysql: if ((WOVar.wo_mysql_host == "localhost") or (WOVar.wo_mysql_host == "127.0.0.1")): @@ -435,7 +503,7 @@ class WOStackStatusController(CementBaseController): pargs = self.app.pargs if not (pargs.nginx or pargs.php or pargs.php72 or pargs.php73 or - pargs.php74 or + pargs.php74 or pargs.php80 or pargs.php81 or pargs.mysql or pargs.netdata or pargs.proftpd or @@ -465,6 +533,14 @@ class WOStackStatusController(CementBaseController): services = services + ['php7.4-fpm'] else: Log.info(self, "PHP7.4-FPM is not installed") + if os.path.exists('{0}'.format(wo_system) + 'php8.0-fpm.service'): + services = services + ['php8.0-fpm'] + else: + Log.info(self, "PHP8.0-FPM is not installed") + if os.path.exists('{0}'.format(wo_system) + 'php8.1-fpm.service'): + services = services + ['php8.1-fpm'] + else: + Log.info(self, "PHP8.1-FPM is not installed") if pargs.php72: if os.path.exists('{0}'.format(wo_system) + 'php7.2-fpm.service'): @@ -484,6 +560,18 @@ class WOStackStatusController(CementBaseController): else: Log.info(self, "PHP7.4-FPM is not installed") + if pargs.php80: + if os.path.exists('{0}'.format(wo_system) + 'php8.0-fpm.service'): + services = services + ['php8.0-fpm'] + else: + Log.info(self, "PHP8.0-FPM is not installed") + + if pargs.php81: + if os.path.exists('{0}'.format(wo_system) + 'php8.1-fpm.service'): + services = services + ['php8.1-fpm'] + else: + Log.info(self, "PHP8.1-FPM is not installed") + if pargs.mysql: if ((WOVar.wo_mysql_host == "localhost") or (WOVar.wo_mysql_host == "127.0.0.1")): diff --git a/wo/cli/plugins/stack_upgrade.py b/wo/cli/plugins/stack_upgrade.py index f0071c8..aaf259a 100644 --- a/wo/cli/plugins/stack_upgrade.py +++ b/wo/cli/plugins/stack_upgrade.py @@ -39,6 +39,10 @@ class WOStackUpgradeController(CementBaseController): dict(help='Upgrade PHP 7.3 stack', action='store_true')), (['--php74'], dict(help='Upgrade PHP 7.4 stack', action='store_true')), + (['--php80'], + dict(help='Upgrade PHP 8.0 stack', action='store_true')), + (['--php81'], + dict(help='Upgrade PHP 8.1 stack', action='store_true')), (['--mysql'], dict(help='Upgrade MySQL stack', action='store_true')), (['--mariadb'], @@ -81,7 +85,8 @@ class WOStackUpgradeController(CementBaseController): pargs = self.app.pargs wo_phpmyadmin = WODownload.pma_release(self) if not (pargs.web or pargs.nginx or pargs.php or - pargs.php72 or pargs.php73 or pargs.php74 or pargs.mysql or + pargs.php72 or pargs.php73 or pargs.php74 or + pargs.php80 or pargs.php81 or pargs.mysql or pargs.mariadb or pargs.ngxblocker or pargs.all or pargs.netdata or pargs.wpcli or pargs.composer or pargs.phpmyadmin or pargs.adminer or pargs.dashboard or @@ -108,6 +113,8 @@ class WOStackUpgradeController(CementBaseController): pargs.php72 = True pargs.php73 = True pargs.php74 = True + pargs.php80 = True + pargs.php81 = True pargs.mysql = True pargs.wpcli = True @@ -153,6 +160,18 @@ class WOStackUpgradeController(CementBaseController): apt_packages = apt_packages + WOVar.wo_php74 + \ WOVar.wo_php_extra + # php 8.0 + if pargs.php80: + if WOAptGet.is_installed(self, 'php8.0-fpm'): + apt_packages = apt_packages + WOVar.wo_php80 + \ + WOVar.wo_php_extra + + # php 8.1 + if pargs.php81: + if WOAptGet.is_installed(self, 'php8.1-fpm'): + apt_packages = apt_packages + WOVar.wo_php81 + \ + WOVar.wo_php_extra + # mysql if pargs.mysql: if WOShellExec.cmd_exec(self, 'mysqladmin ping'): @@ -284,6 +303,8 @@ class WOStackUpgradeController(CementBaseController): if not ("php7.2-fpm" in apt_packages or "php7.3-fpm" in apt_packages or "php7.4-fpm" in apt_packages or + "php8.0-fpm" in apt_packages or + "php8.1-fpm" in apt_packages or "redis-server" in apt_packages or "nginx-custom" in apt_packages or "mariadb-server" in apt_packages): diff --git a/wo/core/services.py b/wo/core/services.py index 84156aa..87811ba 100644 --- a/wo/core/services.py +++ b/wo/core/services.py @@ -166,7 +166,9 @@ class WOService(): .format(service_name)) if is_exist[0] == 0 or service_name in ['php7.2-fpm', 'php7.3-fpm', - 'php7.4-fpm']: + 'php7.4-fpm', + 'php8.0-fpm', + 'php8.1-fpm',]: retcode = subprocess.getstatusoutput('service {0} status' .format(service_name)) if retcode[0] == 0: diff --git a/wo/core/variables.py b/wo/core/variables.py index 8405400..80e4f48 100644 --- a/wo/core/variables.py +++ b/wo/core/variables.py @@ -14,9 +14,9 @@ class WOVar(): """Intialization of core variables""" # WordOps version - wo_version = "3.13.3" + wo_version = "3.13.3-fork" # WordOps packages versions - wo_wp_cli = "2.5.0" + wo_wp_cli = "2.4.0" wo_adminer = "4.7.5" wo_phpmyadmin = "5.0.2" wo_extplorer = "2.1.13" @@ -137,13 +137,10 @@ class WOVar(): wo_nginx = ["nginx-custom", "nginx-wo"] wo_nginx_key = '188C9FB063F0247A' - wo_module = ["fpm", "curl", "gd", "imap", - "readline", "common", - "cli", "mbstring", "intl", - "bcmath", "mysql", "opcache", - "zip", "xml", "soap", "memcached", - "imagick", "igbinary", "msgpack", - "redis", "xdebug"] + wo_module = ["bcmath", "cli", "common", "curl", "fpm", "gd", "igbinary", + "imagick", "imap", "intl", "mbstring", "memcached", "msgpack", + "mysql", "opcache", "readline", "redis", "soap", "xdebug", + "xml", "zip"] wo_php72 = [] for module in wo_module: wo_php72 = wo_php72 + ["php7.2-{0}".format(module)] @@ -152,9 +149,15 @@ class WOVar(): for module in wo_module: wo_php73 = wo_php73 + ["php7.3-{0}".format(module)] wo_php73 = wo_php73 + ["php7.3-recode"] - wo_php74 = [] + wo_php74 = ["geoip", "json"] for module in wo_module: wo_php74 = wo_php74 + ["php7.4-{0}".format(module)] + wo_php80 = [] + for module in wo_module: + wo_php80 = wo_php80 + ["php8.0-{0}".format(module)] + wo_php81 = [] + for module in wo_module: + wo_php81 = wo_php81 + ["php8.1-{0}".format(module)] wo_php_extra = ["graphviz"] From 089ff2c98ffe047813d330996ae3dc1bfbf3f943 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Mon, 24 Jan 2022 12:21:12 +0100 Subject: [PATCH 02/14] Auto stash before merge of "updating-configuration" and "origin/updating-configuration" --- wo/cli/plugins/site_backup.py | 380 ++++++++++++++++++++++ wo/cli/plugins/site_clone.py | 571 ++++++++++++++++++++++++++++++++++ 2 files changed, 951 insertions(+) create mode 100644 wo/cli/plugins/site_backup.py create mode 100644 wo/cli/plugins/site_clone.py diff --git a/wo/cli/plugins/site_backup.py b/wo/cli/plugins/site_backup.py new file mode 100644 index 0000000..1855d6e --- /dev/null +++ b/wo/cli/plugins/site_backup.py @@ -0,0 +1,380 @@ +import os + +from cement.core.controller import CementBaseController, expose +from wo.cli.plugins.site_functions import ( + detSitePar, check_domain_exists, site_package_check, + pre_run_checks, setupdomain, SiteError, + doCleanupAction, setupdatabase, setupwordpress, setwebrootpermissions, + display_cache_settings, copyWildcardCert) +from wo.cli.plugins.sitedb import (deleteSiteInfo, getAllsites, + getSiteInfo, updateSiteInfo) +from wo.core.acme import WOAcme +from wo.core.domainvalidate import WODomain +from wo.core.git import WOGit +from wo.core.logging import Log +from wo.core.nginxhashbucket import hashbucket +from wo.core.services import WOService +from wo.core.sslutils import SSL +from wo.core.variables import WOVar + + +class WOSiteBackupController(CementBaseController): + class Meta: + label = 'backup' + stacked_on = 'site' + stacked_type = 'nested' + description = ('this commands allow you to backup your sites') + arguments = [ + (['site_name'], + dict(help='domain name for the site to be cloned.', + nargs='?')), + (['--db'], + dict(help="backup only site database", action='store_true')), + (['--files'], + dict(help="backup only site files", action='store_true')), + (['--all'], + dict(help="backup all sites", action='store_true')), + ] + + @expose(hide=True) + def default(self): + pargs = self.app.pargs + # self.app.render((data), 'default.mustache') + # Check domain name validation + data = dict() + sites = getAllsites(self) + + if not pargs.site_name and not pargs.all: + try: + while not pargs.site_name: + # preprocessing before finalize site name + pargs.site_name = (input('Enter site name : ') + .strip()) + except IOError as e: + Log.debug(self, str(e)) + Log.error(self, "Unable to input site name, Please try again!") + + pargs.site_name = pargs.site_name.strip() + wo_domain = WODomain.validate(self, pargs.site_name) + wo_www_domain = "www.{0}".format(wo_domain) + (wo_domain_type, wo_root_domain) = WODomain.getlevel( + self, wo_domain) + if not wo_domain.strip(): + Log.error(self, "Invalid domain name, " + "Provide valid domain name") + + wo_site_webroot = WOVar.wo_webroot + wo_domain + + if not check_domain_exists(self, wo_domain): + Log.error(self, "site {0} already exists".format(wo_domain)) + elif os.path.isfile('/etc/nginx/sites-available/{0}' + .format(wo_domain)): + Log.error(self, "Nginx configuration /etc/nginx/sites-available/" + "{0} already exists".format(wo_domain)) + + + try: + try: + # setup NGINX configuration, and webroot + setupdomain(self, data) + + # Fix Nginx Hashbucket size error + hashbucket(self) + except SiteError as e: + # call cleanup actions on failure + Log.info(self, Log.FAIL + + "There was a serious error encountered...") + Log.info(self, Log.FAIL + "Cleaning up afterwards...") + doCleanupAction(self, domain=wo_domain, + webroot=data['webroot']) + Log.debug(self, str(e)) + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` " + "and please try again") + + if 'proxy' in data.keys() and data['proxy']: + addNewSite(self, wo_domain, stype, cache, wo_site_webroot) + # Service Nginx Reload + if not WOService.reload_service(self, 'nginx'): + Log.info(self, Log.FAIL + + "There was a serious error encountered...") + Log.info(self, Log.FAIL + "Cleaning up afterwards...") + doCleanupAction(self, domain=wo_domain) + deleteSiteInfo(self, wo_domain) + Log.error(self, "service nginx reload failed. " + "check issues with `nginx -t` command") + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` " + "and please try again") + if wo_auth and len(wo_auth): + for msg in wo_auth: + Log.info(self, Log.ENDC + msg, log=False) + Log.info(self, "Successfully created site" + " http://{0}".format(wo_domain)) + return + + if data['php72']: + php_version = "7.2" + elif data['php74']: + php_version = "7.4" + else: + php_version = "7.3" + + addNewSite(self, wo_domain, stype, cache, wo_site_webroot, + php_version=php_version) + + # Setup database for MySQL site + if 'wo_db_name' in data.keys() and not data['wp']: + try: + data = setupdatabase(self, data) + # Add database information for site into database + updateSiteInfo(self, wo_domain, db_name=data['wo_db_name'], + db_user=data['wo_db_user'], + db_password=data['wo_db_pass'], + db_host=data['wo_db_host']) + except SiteError as e: + # call cleanup actions on failure + Log.debug(self, str(e)) + Log.info(self, Log.FAIL + + "There was a serious error encountered...") + Log.info(self, Log.FAIL + "Cleaning up afterwards...") + doCleanupAction(self, domain=wo_domain, + webroot=data['webroot'], + dbname=data['wo_db_name'], + dbuser=data['wo_db_user'], + dbhost=data['wo_db_host']) + deleteSiteInfo(self, wo_domain) + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` " + "and please try again") + + try: + wodbconfig = open("{0}/wo-config.php" + .format(wo_site_webroot), + encoding='utf-8', mode='w') + wodbconfig.write("" + .format(data['wo_db_name'], + data['wo_db_user'], + data['wo_db_pass'], + data['wo_db_host'])) + wodbconfig.close() + stype = 'mysql' + except IOError as e: + Log.debug(self, str(e)) + Log.debug(self, "Error occured while generating " + "wo-config.php") + Log.info(self, Log.FAIL + + "There was a serious error encountered...") + Log.info(self, Log.FAIL + "Cleaning up afterwards...") + doCleanupAction(self, domain=wo_domain, + webroot=data['webroot'], + dbname=data['wo_db_name'], + dbuser=data['wo_db_user'], + dbhost=data['wo_db_host']) + deleteSiteInfo(self, wo_domain) + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` " + "and please try again") + + # Setup WordPress if Wordpress site + if data['wp']: + vhostonly = bool(pargs.vhostonly) + try: + wo_wp_creds = setupwordpress(self, data, vhostonly) + # Add database information for site into database + updateSiteInfo(self, wo_domain, + db_name=data['wo_db_name'], + db_user=data['wo_db_user'], + db_password=data['wo_db_pass'], + db_host=data['wo_db_host']) + except SiteError as e: + # call cleanup actions on failure + Log.debug(self, str(e)) + Log.info(self, Log.FAIL + + "There was a serious error encountered...") + Log.info(self, Log.FAIL + "Cleaning up afterwards...") + doCleanupAction(self, domain=wo_domain, + webroot=data['webroot'], + dbname=data['wo_db_name'], + dbuser=data['wo_db_user'], + dbhost=data['wo_mysql_grant_host']) + deleteSiteInfo(self, wo_domain) + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` " + "and please try again") + + # Service Nginx Reload call cleanup if failed to reload nginx + if not WOService.reload_service(self, 'nginx'): + Log.info(self, Log.FAIL + + "There was a serious error encountered...") + Log.info(self, Log.FAIL + "Cleaning up afterwards...") + doCleanupAction(self, domain=wo_domain, + webroot=data['webroot']) + if 'wo_db_name' in data.keys(): + doCleanupAction(self, domain=wo_domain, + dbname=data['wo_db_name'], + dbuser=data['wo_db_user'], + dbhost=data['wo_mysql_grant_host']) + deleteSiteInfo(self, wo_domain) + Log.info(self, Log.FAIL + "service nginx reload failed." + " check issues with `nginx -t` command.") + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` " + "and please try again") + + WOGit.add(self, ["/etc/nginx"], + msg="{0} created with {1} {2}" + .format(wo_www_domain, stype, cache)) + # Setup Permissions for webroot + try: + setwebrootpermissions(self, data['webroot']) + except SiteError as e: + Log.debug(self, str(e)) + Log.info(self, Log.FAIL + + "There was a serious error encountered...") + Log.info(self, Log.FAIL + "Cleaning up afterwards...") + doCleanupAction(self, domain=wo_domain, + webroot=data['webroot']) + if 'wo_db_name' in data.keys(): + print("Inside db cleanup") + doCleanupAction(self, domain=wo_domain, + dbname=data['wo_db_name'], + dbuser=data['wo_db_user'], + dbhost=data['wo_mysql_grant_host']) + deleteSiteInfo(self, wo_domain) + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` and " + "please try again") + + if wo_auth and len(wo_auth): + for msg in wo_auth: + Log.info(self, Log.ENDC + msg, log=False) + + if data['wp'] and (not pargs.vhostonly): + Log.info(self, Log.ENDC + "WordPress admin user :" + " {0}".format(wo_wp_creds['wp_user']), log=False) + Log.info(self, Log.ENDC + "WordPress admin password : {0}" + .format(wo_wp_creds['wp_pass']), log=False) + + display_cache_settings(self, data) + + Log.info(self, "Successfully created site" + " http://{0}".format(wo_domain)) + except SiteError: + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` and please try again") + + if pargs.letsencrypt: + acme_domains = [] + data['letsencrypt'] = True + letsencrypt = True + 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='') + 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 + if not pargs.dns == 'dns_cf': + Log.debug(self, "DNS API : {0}".format(pargs.dns)) + acmedata['acme_dns'] = pargs.dns + if pargs.dnsalias: + Log.debug(self, "DNS Alias enabled") + acmedata['dnsalias'] = True + acmedata['acme_alias'] = pargs.dnsalias + + # detect subdomain and set subdomain variable + if pargs.letsencrypt == "subdomain": + Log.warn( + self, 'Flag --letsencrypt=subdomain is ' + 'deprecated and not required anymore.') + acme_subdomain = True + acme_wildcard = False + elif pargs.letsencrypt == "wildcard": + acme_wildcard = True + acme_subdomain = False + acmedata['dns'] = True + else: + if ((wo_domain_type == 'subdomain')): + Log.debug(self, "Domain type = {0}" + .format(wo_domain_type)) + acme_subdomain = True + else: + acme_subdomain = False + acme_wildcard = False + + if acme_subdomain is True: + Log.info(self, "Certificate type : subdomain") + acme_domains = acme_domains + ['{0}'.format(wo_domain)] + elif acme_wildcard is True: + Log.info(self, "Certificate type : wildcard") + acme_domains = acme_domains + ['{0}'.format(wo_domain), + '*.{0}'.format(wo_domain)] + else: + Log.info(self, "Certificate type : domain") + acme_domains = acme_domains + ['{0}'.format(wo_domain), + 'www.{0}'.format(wo_domain)] + + if WOAcme.cert_check(self, wo_domain): + SSL.archivedcertificatehandle(self, wo_domain, acme_domains) + else: + if acme_subdomain is True: + # check if a wildcard cert for the root domain exist + Log.debug(self, "checkWildcardExist on *.{0}" + .format(wo_root_domain)) + if SSL.checkwildcardexist(self, wo_root_domain): + Log.info(self, "Using existing Wildcard SSL " + "certificate from {0} to secure {1}" + .format(wo_root_domain, wo_domain)) + Log.debug(self, "symlink wildcard " + "cert between {0} & {1}" + .format(wo_domain, wo_root_domain)) + # copy the cert from the root domain + copyWildcardCert(self, wo_domain, wo_root_domain) + else: + # check DNS records before issuing cert + if not acmedata['dns'] is True: + 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( + self, acme_domains, acmedata): + WOAcme.deploycert(self, wo_domain) + else: + if not acmedata['dns'] is True: + 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) + + if pargs.hsts: + SSL.setuphsts(self, wo_domain) + + SSL.httpsredirect(self, wo_domain, acme_domains, True) + SSL.siteurlhttps(self, wo_domain) + 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 on https://{0}".format(wo_domain)) + + # Add nginx conf folder into GIT + WOGit.add(self, ["{0}/conf/nginx".format(wo_site_webroot)], + msg="Adding letsencrypts config of site: {0}" + .format(wo_domain)) + updateSiteInfo(self, wo_domain, ssl=letsencrypt) diff --git a/wo/cli/plugins/site_clone.py b/wo/cli/plugins/site_clone.py new file mode 100644 index 0000000..8396331 --- /dev/null +++ b/wo/cli/plugins/site_clone.py @@ -0,0 +1,571 @@ +import os + +from cement.core.controller import CementBaseController, expose +from wo.cli.plugins.site_functions import ( + detSitePar, check_domain_exists, site_package_check, + pre_run_checks, setupdomain, SiteError, + doCleanupAction, setupdatabase, setupwordpress, setwebrootpermissions, + display_cache_settings, copyWildcardCert) +from wo.cli.plugins.sitedb import (addNewSite, deleteSiteInfo, + updateSiteInfo) +from wo.core.acme import WOAcme +from wo.core.domainvalidate import WODomain +from wo.core.git import WOGit +from wo.core.logging import Log +from wo.core.nginxhashbucket import hashbucket +from wo.core.services import WOService +from wo.core.sslutils import SSL +from wo.core.variables import WOVar + + +class WOSiteCloneController(CementBaseController): + class Meta: + label = 'clone' + stacked_on = 'site' + stacked_type = 'nested' + description = ('this commands allow you to clone a site') + arguments = [ + (['site_name'], + dict(help='domain name for the site to be cloned.', + nargs='?')), + (['newsite_name'], + dict(help='domain name for the site to be created.', + nargs='?')), + (['--html'], + dict(help="create html site", action='store_true')), + (['--php'], + dict(help="create php 7.2 site", action='store_true')), + (['--php72'], + dict(help="create php 7.2 site", action='store_true')), + (['--php73'], + dict(help="create php 7.3 site", action='store_true')), + (['--php74'], + dict(help="create php 7.4 site", action='store_true')), + (['--mysql'], + dict(help="create mysql site", action='store_true')), + (['--wp'], + dict(help="create WordPress single site", + action='store_true')), + (['--wpsubdir'], + dict(help="create WordPress multisite with subdirectory setup", + action='store_true')), + (['--wpsubdomain'], + dict(help="create WordPress multisite with subdomain setup", + action='store_true')), + (['--wpfc'], + dict(help="create WordPress single/multi site with " + "Nginx fastcgi_cache", + action='store_true')), + (['--wpsc'], + dict(help="create WordPress single/multi site with wpsc cache", + action='store_true')), + (['--wprocket'], + dict(help="create WordPress single/multi site with WP-Rocket", + action='store_true')), + (['--wpce'], + dict(help="create WordPress single/multi site with Cache-Enabler", + action='store_true')), + (['--wpredis'], + dict(help="create WordPress single/multi site " + "with redis cache", + action='store_true')), + (['-le', '--letsencrypt'], + dict(help="configure letsencrypt ssl for the site", + 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', + const='dns_cf', nargs='?')), + (['--dnsalias'], + dict(help="set domain used for acme dns alias validation", + action='store', nargs='?')), + (['--hsts'], + dict(help="enable HSTS for site secured with letsencrypt", + action='store_true')), + (['--ngxblocker'], + dict(help="enable HSTS for site secured with letsencrypt", + action='store_true')), + (['--user'], + dict(help="provide user for WordPress site")), + (['--email'], + dict(help="provide email address for WordPress site")), + (['--pass'], + 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", + action='store_true')), + ] + + @expose(hide=True) + def default(self): + pargs = self.app.pargs + # self.app.render((data), 'default.mustache') + # Check domain name validation + data = dict() + host, port = None, None + try: + stype, cache = detSitePar(vars(pargs)) + except RuntimeError as e: + Log.debug(self, str(e)) + Log.error(self, "Please provide valid options to creating site") + + if stype is None and pargs.proxy: + stype, cache = 'proxy', '' + proxyinfo = pargs.proxy[0].strip() + if not proxyinfo: + Log.error(self, "Please provide proxy server host information") + proxyinfo = proxyinfo.split(':') + host = proxyinfo[0].strip() + port = '80' if len(proxyinfo) < 2 else proxyinfo[1].strip() + elif stype is None and not pargs.proxy: + stype, cache = 'html', 'basic' + elif stype and pargs.proxy: + Log.error(self, "proxy should not be used with other site types") + + if not pargs.site_name: + try: + while not pargs.site_name: + # preprocessing before finalize site name + pargs.site_name = (input('Enter site name : ') + .strip()) + except IOError as e: + Log.debug(self, str(e)) + Log.error(self, "Unable to input site name, Please try again!") + + pargs.site_name = pargs.site_name.strip() + wo_domain = WODomain.validate(self, pargs.site_name) + wo_www_domain = "www.{0}".format(wo_domain) + (wo_domain_type, wo_root_domain) = WODomain.getlevel( + self, wo_domain) + if not wo_domain.strip(): + Log.error(self, "Invalid domain name, " + "Provide valid domain name") + + wo_site_webroot = WOVar.wo_webroot + wo_domain + + if check_domain_exists(self, wo_domain): + Log.error(self, "site {0} already exists".format(wo_domain)) + elif os.path.isfile('/etc/nginx/sites-available/{0}' + .format(wo_domain)): + Log.error(self, "Nginx configuration /etc/nginx/sites-available/" + "{0} already exists".format(wo_domain)) + + if stype == 'proxy': + data = dict( + site_name=wo_domain, www_domain=wo_www_domain, + static=True, basic=False, wp=False, + wpfc=False, wpsc=False, wprocket=False, wpce=False, + multisite=False, wpsubdir=False, webroot=wo_site_webroot) + data['proxy'] = True + data['host'] = host + data['port'] = port + data['basic'] = True + + if pargs.php72 or pargs.php73 or pargs.php74: + data = dict( + site_name=wo_domain, www_domain=wo_www_domain, + static=False, basic=False, + wp=False, wpfc=False, wpsc=False, wprocket=False, + wpce=False, multisite=False, + wpsubdir=False, webroot=wo_site_webroot) + data['basic'] = True + + if stype in ['html', 'php']: + data = dict( + site_name=wo_domain, www_domain=wo_www_domain, + static=True, basic=False, wp=False, + wpfc=False, wpsc=False, wprocket=False, wpce=False, + multisite=False, wpsubdir=False, webroot=wo_site_webroot) + + if stype == 'php': + data['static'] = False + data['basic'] = True + + elif stype in ['mysql', 'wp', 'wpsubdir', 'wpsubdomain']: + + data = dict( + site_name=wo_domain, www_domain=wo_www_domain, + static=False, basic=True, wp=False, wpfc=False, + wpsc=False, wpredis=False, wprocket=False, wpce=False, + multisite=False, wpsubdir=False, webroot=wo_site_webroot, + wo_db_name='', wo_db_user='', wo_db_pass='', + wo_db_host='') + + if stype in ['wp', 'wpsubdir', 'wpsubdomain']: + data['wp'] = True + data['basic'] = False + data[cache] = True + data['wp-user'] = pargs.user + data['wp-email'] = pargs.email + data['wp-pass'] = pargs.wppass + if stype in ['wpsubdir', 'wpsubdomain']: + data['multisite'] = True + if stype == 'wpsubdir': + data['wpsubdir'] = True + else: + pass + + data['php73'] = False + data['php74'] = False + data['php72'] = False + + if data and pargs.php73: + data['php73'] = True + data['wo_php'] = 'php73' + elif data and pargs.php74: + data['php74'] = True + data['wo_php'] = 'php74' + elif data and pargs.php72: + data['php72'] = True + data['wo_php'] = 'php72' + else: + if self.app.config.has_section('php'): + config_php_ver = self.app.config.get( + 'php', 'version') + if config_php_ver == '7.2': + data['php72'] = True + data['wo_php'] = 'php72' + elif config_php_ver == '7.3': + data['php73'] = True + data['wo_php'] = 'php73' + elif config_php_ver == '7.4': + data['php74'] = True + data['wo_php'] = 'php74' + else: + data['php73'] = True + data['wo_php'] = 'php73' + + if ((not pargs.wpfc) and (not pargs.wpsc) and + (not pargs.wprocket) and + (not pargs.wpce) and + (not pargs.wpredis)): + data['basic'] = True + + if (cache == 'wpredis'): + cache = 'wpredis' + data['wpredis'] = True + data['basic'] = False + pargs.wpredis = True + + # Check rerequired packages are installed or not + wo_auth = site_package_check(self, stype) + + try: + pre_run_checks(self) + except SiteError as e: + Log.debug(self, str(e)) + Log.error(self, "NGINX configuration check failed.") + + try: + try: + # setup NGINX configuration, and webroot + setupdomain(self, data) + + # Fix Nginx Hashbucket size error + hashbucket(self) + except SiteError as e: + # call cleanup actions on failure + Log.info(self, Log.FAIL + + "There was a serious error encountered...") + Log.info(self, Log.FAIL + "Cleaning up afterwards...") + doCleanupAction(self, domain=wo_domain, + webroot=data['webroot']) + Log.debug(self, str(e)) + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` " + "and please try again") + + if 'proxy' in data.keys() and data['proxy']: + addNewSite(self, wo_domain, stype, cache, wo_site_webroot) + # Service Nginx Reload + if not WOService.reload_service(self, 'nginx'): + Log.info(self, Log.FAIL + + "There was a serious error encountered...") + Log.info(self, Log.FAIL + "Cleaning up afterwards...") + doCleanupAction(self, domain=wo_domain) + deleteSiteInfo(self, wo_domain) + Log.error(self, "service nginx reload failed. " + "check issues with `nginx -t` command") + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` " + "and please try again") + if wo_auth and len(wo_auth): + for msg in wo_auth: + Log.info(self, Log.ENDC + msg, log=False) + Log.info(self, "Successfully created site" + " http://{0}".format(wo_domain)) + return + + if data['php72']: + php_version = "7.2" + elif data['php74']: + php_version = "7.4" + else: + php_version = "7.3" + + addNewSite(self, wo_domain, stype, cache, wo_site_webroot, + php_version=php_version) + + # Setup database for MySQL site + if 'wo_db_name' in data.keys() and not data['wp']: + try: + data = setupdatabase(self, data) + # Add database information for site into database + updateSiteInfo(self, wo_domain, db_name=data['wo_db_name'], + db_user=data['wo_db_user'], + db_password=data['wo_db_pass'], + db_host=data['wo_db_host']) + except SiteError as e: + # call cleanup actions on failure + Log.debug(self, str(e)) + Log.info(self, Log.FAIL + + "There was a serious error encountered...") + Log.info(self, Log.FAIL + "Cleaning up afterwards...") + doCleanupAction(self, domain=wo_domain, + webroot=data['webroot'], + dbname=data['wo_db_name'], + dbuser=data['wo_db_user'], + dbhost=data['wo_db_host']) + deleteSiteInfo(self, wo_domain) + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` " + "and please try again") + + try: + wodbconfig = open("{0}/wo-config.php" + .format(wo_site_webroot), + encoding='utf-8', mode='w') + wodbconfig.write("" + .format(data['wo_db_name'], + data['wo_db_user'], + data['wo_db_pass'], + data['wo_db_host'])) + wodbconfig.close() + stype = 'mysql' + except IOError as e: + Log.debug(self, str(e)) + Log.debug(self, "Error occured while generating " + "wo-config.php") + Log.info(self, Log.FAIL + + "There was a serious error encountered...") + Log.info(self, Log.FAIL + "Cleaning up afterwards...") + doCleanupAction(self, domain=wo_domain, + webroot=data['webroot'], + dbname=data['wo_db_name'], + dbuser=data['wo_db_user'], + dbhost=data['wo_db_host']) + deleteSiteInfo(self, wo_domain) + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` " + "and please try again") + + # Setup WordPress if Wordpress site + if data['wp']: + vhostonly = bool(pargs.vhostonly) + try: + wo_wp_creds = setupwordpress(self, data, vhostonly) + # Add database information for site into database + updateSiteInfo(self, wo_domain, + db_name=data['wo_db_name'], + db_user=data['wo_db_user'], + db_password=data['wo_db_pass'], + db_host=data['wo_db_host']) + except SiteError as e: + # call cleanup actions on failure + Log.debug(self, str(e)) + Log.info(self, Log.FAIL + + "There was a serious error encountered...") + Log.info(self, Log.FAIL + "Cleaning up afterwards...") + doCleanupAction(self, domain=wo_domain, + webroot=data['webroot'], + dbname=data['wo_db_name'], + dbuser=data['wo_db_user'], + dbhost=data['wo_mysql_grant_host']) + deleteSiteInfo(self, wo_domain) + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` " + "and please try again") + + # Service Nginx Reload call cleanup if failed to reload nginx + if not WOService.reload_service(self, 'nginx'): + Log.info(self, Log.FAIL + + "There was a serious error encountered...") + Log.info(self, Log.FAIL + "Cleaning up afterwards...") + doCleanupAction(self, domain=wo_domain, + webroot=data['webroot']) + if 'wo_db_name' in data.keys(): + doCleanupAction(self, domain=wo_domain, + dbname=data['wo_db_name'], + dbuser=data['wo_db_user'], + dbhost=data['wo_mysql_grant_host']) + deleteSiteInfo(self, wo_domain) + Log.info(self, Log.FAIL + "service nginx reload failed." + " check issues with `nginx -t` command.") + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` " + "and please try again") + + WOGit.add(self, ["/etc/nginx"], + msg="{0} created with {1} {2}" + .format(wo_www_domain, stype, cache)) + # Setup Permissions for webroot + try: + setwebrootpermissions(self, data['webroot']) + except SiteError as e: + Log.debug(self, str(e)) + Log.info(self, Log.FAIL + + "There was a serious error encountered...") + Log.info(self, Log.FAIL + "Cleaning up afterwards...") + doCleanupAction(self, domain=wo_domain, + webroot=data['webroot']) + if 'wo_db_name' in data.keys(): + print("Inside db cleanup") + doCleanupAction(self, domain=wo_domain, + dbname=data['wo_db_name'], + dbuser=data['wo_db_user'], + dbhost=data['wo_mysql_grant_host']) + deleteSiteInfo(self, wo_domain) + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` and " + "please try again") + + if wo_auth and len(wo_auth): + for msg in wo_auth: + Log.info(self, Log.ENDC + msg, log=False) + + if data['wp'] and (not pargs.vhostonly): + Log.info(self, Log.ENDC + "WordPress admin user :" + " {0}".format(wo_wp_creds['wp_user']), log=False) + Log.info(self, Log.ENDC + "WordPress admin password : {0}" + .format(wo_wp_creds['wp_pass']), log=False) + + display_cache_settings(self, data) + + Log.info(self, "Successfully created site" + " http://{0}".format(wo_domain)) + except SiteError: + Log.error(self, "Check the log for details: " + "`tail /var/log/wo/wordops.log` and please try again") + + if pargs.letsencrypt: + acme_domains = [] + data['letsencrypt'] = True + letsencrypt = True + 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='') + 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 + if not pargs.dns == 'dns_cf': + Log.debug(self, "DNS API : {0}".format(pargs.dns)) + acmedata['acme_dns'] = pargs.dns + if pargs.dnsalias: + Log.debug(self, "DNS Alias enabled") + acmedata['dnsalias'] = True + acmedata['acme_alias'] = pargs.dnsalias + + # detect subdomain and set subdomain variable + if pargs.letsencrypt == "subdomain": + Log.warn( + self, 'Flag --letsencrypt=subdomain is ' + 'deprecated and not required anymore.') + acme_subdomain = True + acme_wildcard = False + elif pargs.letsencrypt == "wildcard": + acme_wildcard = True + acme_subdomain = False + acmedata['dns'] = True + else: + if ((wo_domain_type == 'subdomain')): + Log.debug(self, "Domain type = {0}" + .format(wo_domain_type)) + acme_subdomain = True + else: + acme_subdomain = False + acme_wildcard = False + + if acme_subdomain is True: + Log.info(self, "Certificate type : subdomain") + acme_domains = acme_domains + ['{0}'.format(wo_domain)] + elif acme_wildcard is True: + Log.info(self, "Certificate type : wildcard") + acme_domains = acme_domains + ['{0}'.format(wo_domain), + '*.{0}'.format(wo_domain)] + else: + Log.info(self, "Certificate type : domain") + acme_domains = acme_domains + ['{0}'.format(wo_domain), + 'www.{0}'.format(wo_domain)] + + if WOAcme.cert_check(self, wo_domain): + SSL.archivedcertificatehandle(self, wo_domain, acme_domains) + else: + if acme_subdomain is True: + # check if a wildcard cert for the root domain exist + Log.debug(self, "checkWildcardExist on *.{0}" + .format(wo_root_domain)) + if SSL.checkwildcardexist(self, wo_root_domain): + Log.info(self, "Using existing Wildcard SSL " + "certificate from {0} to secure {1}" + .format(wo_root_domain, wo_domain)) + Log.debug(self, "symlink wildcard " + "cert between {0} & {1}" + .format(wo_domain, wo_root_domain)) + # copy the cert from the root domain + copyWildcardCert(self, wo_domain, wo_root_domain) + else: + # check DNS records before issuing cert + if not acmedata['dns'] is True: + 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( + self, acme_domains, acmedata): + WOAcme.deploycert(self, wo_domain) + else: + if not acmedata['dns'] is True: + 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) + + if pargs.hsts: + SSL.setuphsts(self, wo_domain) + + SSL.httpsredirect(self, wo_domain, acme_domains, True) + SSL.siteurlhttps(self, wo_domain) + 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 on https://{0}".format(wo_domain)) + + # Add nginx conf folder into GIT + WOGit.add(self, ["{0}/conf/nginx".format(wo_site_webroot)], + msg="Adding letsencrypts config of site: {0}" + .format(wo_domain)) + updateSiteInfo(self, wo_domain, ssl=letsencrypt) From db57d22279c7e73913e7f685c6d58b792e8a88ba Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Mon, 24 Jan 2022 16:38:28 +0100 Subject: [PATCH 03/14] Fix php7.4 modules --- wo/core/variables.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wo/core/variables.py b/wo/core/variables.py index 80e4f48..a7b0c81 100644 --- a/wo/core/variables.py +++ b/wo/core/variables.py @@ -149,9 +149,10 @@ class WOVar(): for module in wo_module: wo_php73 = wo_php73 + ["php7.3-{0}".format(module)] wo_php73 = wo_php73 + ["php7.3-recode"] - wo_php74 = ["geoip", "json"] + wo_php74 = [] for module in wo_module: wo_php74 = wo_php74 + ["php7.4-{0}".format(module)] + wo_php74 = wo_php74 + ["php7.4-geoip", "php7.4-json"] wo_php80 = [] for module in wo_module: wo_php80 = wo_php80 + ["php8.0-{0}".format(module)] From 4d18b7827419a143e25e3099a3d66dc61c559fbe Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Tue, 25 Jan 2022 15:49:11 +0100 Subject: [PATCH 04/14] Update wo version --- install | 2 +- setup.py | 2 +- wo/cli/templates/upstream.mustache | 40 ++++++++++++++++++++++++++++++ wo/core/variables.py | 4 +-- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/install b/install index 594d5be..08c1098 100755 --- a/install +++ b/install @@ -9,7 +9,7 @@ # ------------------------------------------------------------------------- # wget -qO wo wops.cc && sudo -E bash wo # ------------------------------------------------------------------------- -# Version 3.13.3 - 2021-09-15 +# Version 3.14.0 - 2022-01-24 # ------------------------------------------------------------------------- # CONTENTS diff --git a/setup.py b/setup.py index 340893f..1be8c0b 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ if os.geteuid() == 0: os.makedirs('/var/lib/wo/tmp/') setup(name='wordops', - version='3.13.3', + version='3.14.0', description='An essential toolset that eases server administration', long_description=LONG, long_description_content_type='text/markdown', diff --git a/wo/cli/templates/upstream.mustache b/wo/cli/templates/upstream.mustache index 1a75efb..9838068 100644 --- a/wo/cli/templates/upstream.mustache +++ b/wo/cli/templates/upstream.mustache @@ -85,6 +85,46 @@ upstream debug74 { server 127.0.0.1:9174; } +#------------------------------- +# PHP 8.0 +#------------------------------- + +# PHP 8.0 upstream with load-balancing on two unix sockets +upstream php80 { + least_conn; + + server unix:/var/run/php/php80-fpm.sock; + server unix:/var/run/php/php80-two-fpm.sock; + + keepalive 5; +} + +# PHP 8.0 debug +upstream debug80 { + # Debug Pool + server 127.0.0.1:9175; +} + +#------------------------------- +# PHP 8.1 +#------------------------------- + +# PHP 8.1 upstream with load-balancing on two unix sockets +upstream php81 { + least_conn; + + server unix:/var/run/php/php81-fpm.sock; + server unix:/var/run/php/php81-two-fpm.sock; + + keepalive 5; +} + +# PHP 8.1 debug +upstream debug81 { + # Debug Pool + server 127.0.0.1:9176; +} + #------------------------------- # Netdata #------------------------------- diff --git a/wo/core/variables.py b/wo/core/variables.py index a7b0c81..8025f90 100644 --- a/wo/core/variables.py +++ b/wo/core/variables.py @@ -14,9 +14,9 @@ class WOVar(): """Intialization of core variables""" # WordOps version - wo_version = "3.13.3-fork" + wo_version = "3.14.0" # WordOps packages versions - wo_wp_cli = "2.4.0" + wo_wp_cli = "2.5.0" wo_adminer = "4.7.5" wo_phpmyadmin = "5.0.2" wo_extplorer = "2.1.13" From bb4daf002a4e7f022f9795d79655670e76aa3d01 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Tue, 25 Jan 2022 15:54:08 +0100 Subject: [PATCH 05/14] Add php repository for php8.0 --- wo/cli/plugins/stack_pref.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wo/cli/plugins/stack_pref.py b/wo/cli/plugins/stack_pref.py index 988172a..ff2b143 100644 --- a/wo/cli/plugins/stack_pref.py +++ b/wo/cli/plugins/stack_pref.py @@ -81,7 +81,8 @@ def pre_pref(self, apt_packages): # add php repository if (('php7.3-fpm' in apt_packages) or - ('php7.2-fpm' in apt_packages) or ('php7.4-fpm' in apt_packages)): + ('php7.2-fpm' in apt_packages) or ('php7.4-fpm' in apt_packages) or + ('php8.0-fpm' in apt_packages) or ('php8.1-fpm' in apt_packages)): if (WOVar.wo_distro == 'ubuntu'): Log.debug(self, 'Adding ppa for PHP') Log.info(self, "Adding repository for PHP, please wait...") From c68d173f42324fe5e3a59a0ee5f47d05d2389bde Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Tue, 25 Jan 2022 16:16:46 +0100 Subject: [PATCH 06/14] Fix missing nginx configurations --- install | 16 ---------------- wo/cli/controllers/base.py | 2 +- wo/core/stackconf.py | 2 +- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/install b/install index 08c1098..b0d172f 100755 --- a/install +++ b/install @@ -779,22 +779,6 @@ wo_init() { } wo_php_fix() { - local php_versions="5.6 7.0 7.1 7.2 7.3 7.4" - - apt-get autoremove --assume-yes --purge php8.0-* php-igbinary php-memcached php-msgpack php-redis php-imagick php-xdebug php-memcache - for php_version in $php_versions; do - if [ -f "/usr/bin/php$php_version" ]; then - if [ -f "/usr/sbin/php-fpm$php_version" ]; then - local php_extensions="igbinary memcached msgpack redis imagick xdebug" - for php_ext in $php_extensions; do - apt-get -option=Dpkg::options::=--force-confmiss --option=Dpkg::options::=--force-confold --assume-yes install "php$php_version-$php_ext" - done - else - apt-get autoremove --assume-yes --purge "php$php_version-*" - fi - - fi - done if [ -f /lib/systemd/system/mariadb.service ]; then systemctl daemon-reload systemctl enable mariadb diff --git a/wo/cli/controllers/base.py b/wo/cli/controllers/base.py index 95be6a6..4078777 100644 --- a/wo/cli/controllers/base.py +++ b/wo/cli/controllers/base.py @@ -8,7 +8,7 @@ VERSION = WOVar.wo_version BANNER = """ WordOps v%s -Copyright (c) 2020 WordOps. +Copyright (c) 2022 WordOps. """ % VERSION diff --git a/wo/core/stackconf.py b/wo/core/stackconf.py index bd8b25c..992ef28 100644 --- a/wo/core/stackconf.py +++ b/wo/core/stackconf.py @@ -12,7 +12,7 @@ class WOConf(): def nginxcommon(self): """nginx common configuration deployment""" - wo_php_version = ["php72", "php73", "php74"] + wo_php_version = ["php72", "php73", "php74", "php80", "php81"] ngxcom = '/etc/nginx/common' if not os.path.exists(ngxcom): os.mkdir(ngxcom) From 9743a6074221fc6b45dc44183122a7da792ca9ff Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Tue, 25 Jan 2022 16:29:13 +0100 Subject: [PATCH 07/14] Set php8.0 as default --- README.md | 5 +++-- config/wo.conf | 2 +- wo/cli/plugins/site_functions.py | 14 +++++++------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 8a19e20..2c8a6bc 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ - **Easy to install** : One step automated installer with migration from EasyEngine v3 support - **Fast deployment** : Fast and automated WordPress, Nginx, PHP, MySQL & Redis installation - **Custom Nginx build** : Nginx 1.18.0 - TLS v1.3 Cloudflare HTTP/2 HPACK & Brotli support -- **Up-to-date** : PHP 7.2, 7.3 & 7.4, MariaDB 10.5 & Redis 6.0 +- **Up-to-date** : PHP 7.2, 7.3, 7.4, 8.0 & 8.1 - MariaDB 10.5 & Redis 6.0 - **Secured** : Hardened WordPress security with strict Nginx location directives - **Powerful** : Optimized Nginx configurations with multiple cache backends support - **SSL** : Domain, Subdomain & Wildcard Let's Encrypt SSL certificates with DNS API support @@ -64,7 +64,6 @@ #### Also compatible -- Ubuntu 16.04 LTS (Xenial) - Debian 9 (Stretch) - Debian 10 (Buster) - Raspbian 9 (Stretch) @@ -135,6 +134,8 @@ wo site create example.com --proxy=127.0.0.1:3000 # create example.com with ngi wo site update example.com --php72 # switch to PHP 7.2 wo site update example.com --php73 # switch to PHP 7.3 wo site update example.com --php74 # switch to PHP 7.4 +wo site update example.com --php80 # switch to PHP 8.0 +wo site update example.com --php81 # switch to PHP 8.1 ``` ### Sites secured with Let's Encrypt diff --git a/config/wo.conf b/config/wo.conf index 37376f7..ceb2827 100644 --- a/config/wo.conf +++ b/config/wo.conf @@ -79,7 +79,7 @@ keylength = "ec-384" [php] ### Default PHP version -version = 7.4 +version = 8.0 [mariadb] diff --git a/wo/cli/plugins/site_functions.py b/wo/cli/plugins/site_functions.py index 26a962d..f3c6b24 100644 --- a/wo/cli/plugins/site_functions.py +++ b/wo/cli/plugins/site_functions.py @@ -884,7 +884,7 @@ def site_package_check(self, stype): (pargs.php74 and pargs.php80) or (pargs.php80 and pargs.php81) or (pargs.php72 and pargs.php80) or (pargs.php72 and pargs.php81) or (pargs.php73 and pargs.php81) or (pargs.php74 and pargs.php81) or - (pargs.php80 and pargs.php81)): + (pargs.php80 and pargs.php81)): Log.error( self, "Error: two different PHP versions cannot be " "combined within the same WordOps site") @@ -894,8 +894,8 @@ def site_package_check(self, stype): stype in ['php', 'mysql', 'wp', 'wpsubdir', 'wpsubdomain']): Log.debug(self, "Setting apt_packages variable for PHP") - php_check = 'php7.3-fpm' - php_to_setup = WOVar.wo_php73 + php_check = 'php8.0-fpm' + php_to_setup = WOVar.wo_php80 if self.app.config.has_section('php'): config_php_ver = self.app.config.get( 'php', 'version') @@ -915,11 +915,11 @@ def site_package_check(self, stype): php_check = 'php8.1-fpm' php_to_setup = WOVar.wo_php81 else: - php_check = 'php7.3-fpm' - php_to_setup = WOVar.wo_php73 + php_check = 'php8.0-fpm' + php_to_setup = WOVar.wo_php80 else: - php_check = 'php7.3-fpm' - php_to_setup = WOVar.wo_php73 + php_check = 'php8.0-fpm' + php_to_setup = WOVar.wo_php80 if not (WOAptGet.is_installed(self, php_check)): apt_packages = apt_packages + php_to_setup + WOVar.wo_php_extra From c2f0542afaadf4ae2578fb9b8679fb69d2d237fa Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Tue, 25 Jan 2022 16:43:55 +0100 Subject: [PATCH 08/14] Fix php8.1 package install --- CHANGELOG.md | 6 +++++- wo/cli/plugins/site_update.py | 25 ++++++++++++++----------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7aca5e5..1754bee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## Releases -### v3.9.x - [Unreleased] +### v3.14.0 - [Unreleased] + +#### Added + +- PHP 8.0 and 8.1 support #### v3.13.2 - 2020-10-27 diff --git a/wo/cli/plugins/site_update.py b/wo/cli/plugins/site_update.py index 6fdd626..dfa3dfb 100644 --- a/wo/cli/plugins/site_update.py +++ b/wo/cli/plugins/site_update.py @@ -274,7 +274,7 @@ class WOSiteUpdateController(CementBaseController): oldsitetype not in ['html', 'proxy', 'php', 'php72', 'php73', 'php74', 'php80', 'php81']) or (stype == 'mysql' and oldsitetype not in [ - 'html', 'php', 'php72', 'php73', 'php74','php80', 'php81', + 'html', 'php', 'php72', 'php73', 'php74', 'php80', 'php81', 'proxy']) or (stype == 'wp' and oldsitetype not in [ 'html', 'php', 'php72', 'php73', 'php74', 'php80', 'php81', @@ -282,7 +282,8 @@ class WOSiteUpdateController(CementBaseController): (stype == 'wpsubdir' and oldsitetype in ['wpsubdomain']) or (stype == 'wpsubdomain' and oldsitetype in ['wpsubdir']) or (stype == oldsitetype and cache == oldcachetype)) and - not (pargs.php72 or pargs.php73 or pargs.php74 or pargs.php80 or + not (pargs.php72 or pargs.php73 or + pargs.php74 or pargs.php80 or pargs.php81)): Log.info(self, Log.FAIL + "can not update {0} {1} to {2} {3}". format(oldsitetype, oldcachetype, stype, cache)) @@ -302,7 +303,8 @@ class WOSiteUpdateController(CementBaseController): data = dict( site_name=wo_domain, www_domain=wo_www_domain, static=False, basic=True, wp=False, wpfc=False, - php72=False, php73=False, php74=False, php80=False, php81=False, + php72=False, php73=False, php74=False, + php80=False, php81=False, wpsc=False, wpredis=False, wprocket=False, wpce=False, multisite=False, wpsubdir=False, webroot=wo_site_webroot, currsitetype=oldsitetype, currcachetype=oldcachetype) @@ -329,7 +331,8 @@ class WOSiteUpdateController(CementBaseController): if ((pargs.php72 or pargs.php73 or pargs.php74 or pargs.php80 or pargs.php81) and (not data)): Log.debug( - self, "pargs php72, or php73, or php74, or php80, or php81 enabled") + self, "pargs php72, or php73, or php74, " + "or php80, or php81 enabled") data = dict( site_name=wo_domain, www_domain=wo_www_domain, @@ -475,9 +478,9 @@ class WOSiteUpdateController(CementBaseController): data['php80'] = bool(old_php80 is True) Log.debug(self, "data php80 = {0}".format(data['php80'])) php80 = bool(old_php80 is True) - data['php80'] = bool(old_php80 is True) - Log.debug(self, "data php80 = {0}".format(data['php80'])) - php80 = bool(old_php80 is True) + data['php81'] = bool(old_php81 is True) + Log.debug(self, "data php81 = {0}".format(data['php81'])) + php81 = bool(old_php81 is True) if pargs.letsencrypt: acme_domains = [] @@ -558,7 +561,7 @@ class WOSiteUpdateController(CementBaseController): (php74 is old_php74) and (php80 is old_php80) and (php81 is old_php81) and (stype == oldsitetype and - cache == oldcachetype)): + cache == oldcachetype)): Log.debug(self, "Nothing to update") return 1 @@ -578,8 +581,8 @@ class WOSiteUpdateController(CementBaseController): data['wo_php'] = 'php81' check_php_version = '8.1' else: - data['wo_php'] = 'php73' - check_php_version = '7.3' + data['wo_php'] = 'php80' + check_php_version = '8.0' if pargs.hsts: data['hsts'] = bool(pargs.hsts == "on") @@ -878,7 +881,7 @@ class WOSiteUpdateController(CementBaseController): # Setup WordPress if old sites are html/php/mysql sites if data['wp'] and oldsitetype in ['html', 'proxy', 'php', 'php72', 'mysql', 'php73', 'php74', 'php80', - 'php81',]: + 'php81', ]: try: wo_wp_creds = setupwordpress(self, data) except SiteError as e: From 83b84678ac0a13f3481380c032dabab4d0cc60ef Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Tue, 25 Jan 2022 17:15:15 +0100 Subject: [PATCH 09/14] Fix for php stack install --- wo/cli/plugins/stack.py | 12 ++++++------ wo/cli/plugins/stack_upgrade.py | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/wo/cli/plugins/stack.py b/wo/cli/plugins/stack.py index 6854bde..a792a38 100644 --- a/wo/cli/plugins/stack.py +++ b/wo/cli/plugins/stack.py @@ -137,7 +137,7 @@ class WOStackController(CementBaseController): pargs.fail2ban = True if pargs.php: - pargs.php72 = True + pargs.php80 = True if pargs.mariadb: pargs.mysql = True @@ -165,9 +165,9 @@ class WOStackController(CementBaseController): elif config_php_ver == '8.0': pargs.php80 = True elif config_php_ver == '8.1': - pargs.php80 = True + pargs.php81 = True else: - pargs.php74 = True + pargs.php80 = True pargs.nginx = True pargs.mysql = True pargs.wpcli = True @@ -519,7 +519,7 @@ class WOStackController(CementBaseController): WOAptGet.is_installed(self, 'php7.4-fpm') or WOAptGet.is_installed(self, 'php8.0-fpm') or WOAptGet.is_installed(self, 'php8.1-fpm')): - pargs.php74 = True + pargs.php80 = True Log.debug(self, "Setting packages variable for utils") packages = packages + [[ "https://raw.githubusercontent.com" @@ -615,7 +615,7 @@ class WOStackController(CementBaseController): (not pargs.ufw) and (not pargs.ngxblocker) and (not pargs.phpredisadmin) and (not pargs.sendmail) and (not pargs.php73) and (not pargs.php74) and - (not pargs.php72) (not pargs.php80) and + (not pargs.php72) and (not pargs.php80) and (not pargs.php81) and (not pargs.all)): self.app.args.print_help() @@ -1040,7 +1040,7 @@ class WOStackController(CementBaseController): WOAptGet.is_installed(self, 'php7.4-fpm') or WOAptGet.is_installed(self, 'php8.0-fpm') or WOAptGet.is_installed(self, 'php8.1-fpm')): - apt_packages = apt_packages + WOVar.wo_php_extra + apt_packages = apt_packages + WOVar.wo_php_extra else: Log.debug(self, "PHP 7.3 is not installed") Log.info(self, "PHP 7.3 is not installed") diff --git a/wo/cli/plugins/stack_upgrade.py b/wo/cli/plugins/stack_upgrade.py index aaf259a..ee0ff5e 100644 --- a/wo/cli/plugins/stack_upgrade.py +++ b/wo/cli/plugins/stack_upgrade.py @@ -39,9 +39,9 @@ class WOStackUpgradeController(CementBaseController): dict(help='Upgrade PHP 7.3 stack', action='store_true')), (['--php74'], dict(help='Upgrade PHP 7.4 stack', action='store_true')), - (['--php80'], + (['--php80'], dict(help='Upgrade PHP 8.0 stack', action='store_true')), - (['--php81'], + (['--php81'], dict(help='Upgrade PHP 8.1 stack', action='store_true')), (['--mysql'], dict(help='Upgrade MySQL stack', action='store_true')), @@ -87,8 +87,8 @@ class WOStackUpgradeController(CementBaseController): if not (pargs.web or pargs.nginx or pargs.php or pargs.php72 or pargs.php73 or pargs.php74 or pargs.php80 or pargs.php81 or pargs.mysql or - pargs.mariadb or pargs.ngxblocker or pargs.all - or pargs.netdata or pargs.wpcli or pargs.composer or + pargs.mariadb or pargs.ngxblocker or pargs.all or + pargs.netdata or pargs.wpcli or pargs.composer or pargs.phpmyadmin or pargs.adminer or pargs.dashboard or pargs.mysqltuner or pargs.redis or pargs.fail2ban or pargs.security): From 9523ce05aa472b50117ac3000fbcbe56271a213b Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Wed, 26 Jan 2022 13:05:34 +0100 Subject: [PATCH 10/14] Update wp-cli to v2.6.0 and adminer to v4.8.1 --- wo/cli/plugins/site_create.py | 3 ++- wo/core/variables.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/wo/cli/plugins/site_create.py b/wo/cli/plugins/site_create.py index e43aae9..21a3300 100644 --- a/wo/cli/plugins/site_create.py +++ b/wo/cli/plugins/site_create.py @@ -171,7 +171,8 @@ class WOSiteCreateController(CementBaseController): data['port'] = port data['basic'] = True - if pargs.php72 or pargs.php73 or pargs.php74 or pargs.php80 or pargs.php81: + if (pargs.php72 or pargs.php73 or pargs.php74 or + pargs.php80 or pargs.php81): data = dict( site_name=wo_domain, www_domain=wo_www_domain, static=False, basic=False, diff --git a/wo/core/variables.py b/wo/core/variables.py index 8025f90..d882367 100644 --- a/wo/core/variables.py +++ b/wo/core/variables.py @@ -16,8 +16,8 @@ class WOVar(): # WordOps version wo_version = "3.14.0" # WordOps packages versions - wo_wp_cli = "2.5.0" - wo_adminer = "4.7.5" + wo_wp_cli = "2.6.0" + wo_adminer = "4.8.1" wo_phpmyadmin = "5.0.2" wo_extplorer = "2.1.13" wo_dashboard = "1.2" From 9732383cb87fd7d6ee8019e24fd894d6fd3f9cb2 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Wed, 26 Jan 2022 13:14:13 +0100 Subject: [PATCH 11/14] Prepare for release v3.14.0 --- CHANGELOG.md | 18 ++++++++++++++++-- README.md | 12 ++++++------ install | 4 ++-- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1754bee..0c775eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,25 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## Releases -### v3.14.0 - [Unreleased] +### v3.15.0 - [Unreleased] + +### v3.14.0 - 2022-01-26 #### Added -- PHP 8.0 and 8.1 support +- PHP 8.0 and 8.1 support ([PR #413](https://github.com/WordOps/WordOps/pull/413)) +- Support arm64 architecture ([PR #392](https://github.com/WordOps/WordOps/pull/392)) + +#### Changed + +- Update WP-CLI to v2.6.0 with PHP 8.0/8.1 support +- Update adminer to v4.8.1 +- Update Redis repository ([PR #377](https://github.com/WordOps/WordOps/pull/377)) + +#### Fixed + +- WordOps install script issues +- acme.sh issues with zero-ssl CA #### v3.13.2 - 2020-10-27 diff --git a/README.md b/README.md index 2c8a6bc..39c0ed5 100644 --- a/README.md +++ b/README.md @@ -84,8 +84,8 @@ Detailed Getting Started guide with additional installation methods can be found ```bash wo site create example.com --wp # install wordpress with PHP 7.3 without any page caching -wo site create example.com --wp --php72 # install wordpress with PHP 7.2 without any page caching -wo site create example.com --wp --php74 # install wordpress with PHP 7.4 without any page caching +wo site create example.com --wp --php80 # install wordpress with PHP 8.0 without any page caching +wo site create example.com --wp --php81 # install wordpress with PHP 8.1 without any page caching wo site create example.com --wpfc # install wordpress + nginx fastcgi_cache wo site create example.com --wpredis # install wordpress + nginx redis_cache wo site create example.com --wprocket # install wordpress with WP-Rocket plugin @@ -119,12 +119,12 @@ wo site create example.com --wpsubdomain --wpce # install wpmu-subdomain + C ```bash wo site create example.com --html # create example.com for static/html sites -wo site create example.com --php # create example.com with php 7.3 support -wo site create example.com --php72 # create example.com with php 7.2 support +wo site create example.com --php # create example.com with php 8.0 support +wo site create example.com --php80 # create example.com with php 8.0 support wo site create example.com --php74 # create example.com with php 7.4 support wo site create example.com --mysql # create example.com with php 7.3 & mysql support -wo site create example.com --mysql --php72 # create example.com with php 7.2 & mysql support -wo site create example.com --mysql --php74 # create example.com with php 7.4 & mysql support +wo site create example.com --mysql --php81 # create example.com with php 8.1 & mysql support +wo site create example.com --mysql --php73 # create example.com with php 7.3 & mysql support wo site create example.com --proxy=127.0.0.1:3000 # create example.com with nginx as reverse-proxy ``` diff --git a/install b/install index b0d172f..c21505a 100755 --- a/install +++ b/install @@ -4,12 +4,12 @@ # ------------------------------------------------------------------------- # Website: https://wordops.net # GitHub: https://github.com/WordOps/WordOps -# Copyright (c) 2019-2021 - WordOps +# Copyright (c) 2019-2022 - WordOps # This script is licensed under M.I.T # ------------------------------------------------------------------------- # wget -qO wo wops.cc && sudo -E bash wo # ------------------------------------------------------------------------- -# Version 3.14.0 - 2022-01-24 +# Version 3.14.0 - 2022-01-26 # ------------------------------------------------------------------------- # CONTENTS From b575e08b9423b1d1fe5b5544a6c7a67c84cf2f51 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Wed, 26 Jan 2022 17:03:42 +0100 Subject: [PATCH 12/14] Update bash_completion --- config/bash_completion.d/wo_auto.rc | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/config/bash_completion.d/wo_auto.rc b/config/bash_completion.d/wo_auto.rc index bde5b19..4f71ed4 100644 --- a/config/bash_completion.d/wo_auto.rc +++ b/config/bash_completion.d/wo_auto.rc @@ -74,12 +74,12 @@ _wo_complete() # HANDLE EVERYTHING AFTER THE THIRD LEVEL NAMESPACE "install" | "purge" | "remove" ) COMPREPLY=( $(compgen \ - -W "--web --admin --security --nginx --php72 --php73 --php74 --mysql --wpcli --phpmyadmin --adminer --utils --redis --phpredisadmin --composer --netdata --fail2ban --ufw --dashboard --proftpd --clamav --sendmail --ngxblocker --mysqlclient --mysqltuner --extplorer --nanorc --cheat --all --force" \ + -W "--web --admin --security --nginx --php72 --php73 --php74 --php80 --php81 --mysql --wpcli --phpmyadmin --adminer --utils --redis --phpredisadmin --composer --netdata --fail2ban --ufw --dashboard --proftpd --clamav --sendmail --ngxblocker --mysqlclient --mysqltuner --extplorer --nanorc --cheat --all --force" \ -- $cur) ) ;; "upgrade" ) COMPREPLY=( $(compgen \ - -W "--web --admin --utils --nginx --php72 --php73 --php74 --mysql --all --netdata --composer --phpmyadmin --adminer --dashboard --mysqltuner --wpcli --force" \ + -W "--web --admin --utils --nginx --php72 --php73 --php74 --php80 --php81 --mysql --all --netdata --composer --phpmyadmin --adminer --dashboard --mysqltuner --wpcli --force" \ -- $cur) ) ;; "migrate") @@ -89,7 +89,7 @@ _wo_complete() ;; "start" | "stop" | "reload" | "restart" | "status") COMPREPLY=( $(compgen \ - -W "--nginx --php --php72 --php73 --php74 --mysql --redis --fail2ban --ufw --netdata -proftpd" \ + -W "--nginx --php --php72 --php73 --php74 --php80 --php81 --mysql --redis --fail2ban --ufw --netdata -proftpd" \ -- $cur) ) ;; "list") @@ -159,13 +159,13 @@ _wo_complete() "create") COMPREPLY=( $(compgen \ - -W "--user --pass --email --html --php --php72 --php73 --php74 --mysql --wp --wpsubdir --wpsubdomain --wpfc --wpsc --proxy= --wpredis --wprocket --wpce -le --letsencrypt --letsencrypt=wildcard -le=wildcard --dns --dns=dns_cf --dns=dns_dgon" \ + -W "--user --pass --email --html --php --php72 --php73 --php74 --php80 --php81 --mysql --wp --wpsubdir --wpsubdomain --wpfc --wpsc --proxy= --wpredis --wprocket --wpce -le --letsencrypt --letsencrypt=wildcard -le=wildcard --dns --dns=dns_cf --dns=dns_dgon" \ -- $cur) ) ;; "update") COMPREPLY=( $(compgen \ - -W "--password --php --php72 --php73 --php74 --mysql --wp --wpsubdir --wpsubdomain --wpfc --wpsc --wpredis --wprocket --wpce -le -le=off --letsencrypt --letsencrypt=off --letsencrypt=clean -le=wildcard -le=clean --dns --dns=dns_cf --dns=dns_dgon --ngxblocker --ngxblocker=off" \ + -W "--password --php --php72 --php73 --php74 --php80 --php81 --mysql --wp --wpsubdir --wpsubdomain --wpfc --wpsc --wpredis --wprocket --wpce -le -le=off --letsencrypt --letsencrypt=off --letsencrypt=clean -le=wildcard -le=clean --dns --dns=dns_cf --dns=dns_dgon --ngxblocker --ngxblocker=off" \ -- $cur) ) ;; "delete") @@ -211,9 +211,9 @@ _wo_complete() "--wp") if [ "${COMP_WORDS[1]}" != "debug" ]; then if [ "${COMP_WORDS[2]}" == "create" ]; then - retlist="--wp --wpsc --wpfc --user --email --pass --wpredis --wprocket --wpce --letsencrypt -le --letsencrypt=wildcard --dns --dns=dns_cf --dns=dns_dgon --php72 --php73 --php74" + retlist="--wp --wpsc --wpfc --user --email --pass --wpredis --wprocket --wpce --letsencrypt -le --letsencrypt=wildcard --dns --dns=dns_cf --dns=dns_dgon --php72 --php73 --php74 --php80 --php81" elif [ "${COMP_WORDS[2]}" == "update" ]; then - retlist="--wp --wpfc --wpsc --php72 --php73 --php74 --wpredis --wprocket --wpce -le --letsencrypt --letsencrypt=wildcard -le=wildcard --dns --dns=dns_cf --dns=dns_dgon" + retlist="--wp --wpfc --wpsc --php72 --php73 --php74 --php80 --php81 --wpredis --wprocket --wpce -le --letsencrypt --letsencrypt=wildcard -le=wildcard --dns --dns=dns_cf --dns=dns_dgon" else retlist="" fi @@ -230,9 +230,9 @@ _wo_complete() "--wpsubdir" | "--wpsubdomain") if [ "${COMP_WORDS[1]}" != "debug" ]; then if [ "${COMP_WORDS[2]}" == "create" ]; then - retlist="--wpsc --wpfc --user --email --pass --wpredis --wprocket --wpce -le -le=wildcard --letsencrypt --letsencrypt=wildcard --php72 --php73 --php74 --dns --dns=dns_cf --dns=dns_dgon" + retlist="--wpsc --wpfc --user --email --pass --wpredis --wprocket --wpce -le -le=wildcard --letsencrypt --letsencrypt=wildcard --php72 --php73 --php74 --php80 --php81 --dns --dns=dns_cf --dns=dns_dgon" elif [ "${COMP_WORDS[2]}" == "update" ]; then - retlist="--wpfc --wpsc --php72 --php73 --php74 --wpredis --wprocket --wpce -le -le=wildcard --letsencrypt --letsencrypt=wildcard --dns --dns=dns_cf --dns=dns_dgon" + retlist="--wpfc --wpsc --php72 --php73 --php74 --php80 --php81 --wpredis --wprocket --wpce -le -le=wildcard --letsencrypt --letsencrypt=wildcard --dns --dns=dns_cf --dns=dns_dgon" else retlist="" fi @@ -248,7 +248,7 @@ _wo_complete() "--wpredis" | "--wprocket" | "--wpce" | "--wpfc" | "--wpsc" | "--wpsubdir" | "--wpsubdomain" | "--user" | "--pass" | "--email" | "--wp") if [ "${COMP_WORDS[2]}" == "create" ]; then - retlist="--user --pass --email --wp --wpsubdir --wpsubdomain --wpfc --wpsc --wpredis --wprocket --wpce --php72 --php73 --php74 -le -le=wildcard --letsencrypt --letsencrypt=wildcard --dns --dns=dns_cf --dns=dns_dgon" + retlist="--user --pass --email --wp --wpsubdir --wpsubdomain --wpfc --wpsc --wpredis --wprocket --wpce --php72 --php73 --php74 --php80 --php81 -le -le=wildcard --letsencrypt --letsencrypt=wildcard --dns --dns=dns_cf --dns=dns_dgon" else retlist="" fi @@ -261,7 +261,7 @@ _wo_complete() "--wpredis" | "--wprocket" | "--wpce" | "--wpfc" | "--wpsc") if [ "${COMP_WORDS[2]}" == "update" ]; then - retlist="--password --php72 --php73 --php74 --mysql --wp --wpsubdir --wpsubdomain -le --letsencrypt --dns --dns=dns_cf --dns=dns_dgon" + retlist="--password --php72 --php73 --php74 --php80 --php81 --mysql --wp --wpsubdir --wpsubdomain -le --letsencrypt --dns --dns=dns_cf --dns=dns_dgon" else retlist="" fi @@ -272,11 +272,11 @@ _wo_complete() -- $cur) ) ;; - "--web" | "--admin" | "--nginx" | "--php" | "--php73" | "--php74" | "--mysql" | "--wpcli" | "--phpmyadmin" | "--adminer" | "--utils" | "--fail2ban" | "--ufw" | "--redis" | "--phpredisadmin" | "--netdata" | "--sendmail" | "--composer" | "--proftpd" | "--cheat" | "--nanorc" | "--clamav" | "--dashboard") + "--web" | "--admin" | "--nginx" | "--php" | "--php73" | "--php74" | "--php80" | "--php81" | "--mysql" | "--wpcli" | "--phpmyadmin" | "--adminer" | "--utils" | "--fail2ban" | "--ufw" | "--redis" | "--phpredisadmin" | "--netdata" | "--sendmail" | "--composer" | "--proftpd" | "--cheat" | "--nanorc" | "--clamav" | "--dashboard") if [[ "${COMP_WORDS[2]}" == "install" || "${COMP_WORDS[2]}" == "purge" || "${COMP_WORDS[2]}" == "remove" ]]; then - retlist="--web --admin --security --nginx --php --php73 --php74 --mysql --wpcli --phpmyadmin --adminer --utils --redis --fail2ban --ufw --phpredisadmin --netdata --force" + retlist="--web --admin --security --nginx --php --php73 --php74 --php80 --php81 --mysql --wpcli --phpmyadmin --adminer --utils --redis --fail2ban --ufw --phpredisadmin --netdata --force" elif [[ "${COMP_WORDS[2]}" == "start" || "${COMP_WORDS[2]}" == "reload" || "${COMP_WORDS[2]}" == "restart" || "${COMP_WORDS[2]}" == "stop" ]]; then - retlist="--nginx --php --php73 --php74 --mysql --redis --netdata --fail2ban --ufw" + retlist="--nginx --php --php73 --php74 --php80 --php81 --mysql --redis --netdata --fail2ban --ufw" elif [[ "${COMP_WORDS[1]}" == "debug" ]]; then retlist="--start --nginx --php --php73 --fpm --fpm7 --mysql -i --interactive -stop --import-slow-log --import-slow-log-interval= -" if [[ $prev == '--mysql' ]]; then @@ -363,7 +363,7 @@ _wo_complete() case "$mprev" in "--user" | "--email" | "--pass") if [ "${COMP_WORDS[2]}" == "create" ]; then - retlist="--user --pass --email --html --php --php73 --php74 --mysql --wp --wpsubdir --wpsubdomain --wpfc --wpsc --wpredis --wprocket --wpce -le -le=wildcard --letsencrypt --letsencrypt=wildcard --dns --dns=dns_cf --dns=dns_dgon" + retlist="--user --pass --email --html --php --php73 --php74 --php80 --php81 --mysql --wp --wpsubdir --wpsubdomain --wpfc --wpsc --wpredis --wprocket --wpce -le -le=wildcard --letsencrypt --letsencrypt=wildcard --dns --dns=dns_cf --dns=dns_dgon" fi ret="${retlist[@]/$prev}" COMPREPLY=( $(compgen \ From 7f50d675d233d2be9596d9728f97704824ba9e63 Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Wed, 26 Jan 2022 17:07:01 +0100 Subject: [PATCH 13/14] Fix stack status --- CHANGELOG.md | 1 + wo/cli/plugins/stack_services.py | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c775eb..e3dc02f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Update WP-CLI to v2.6.0 with PHP 8.0/8.1 support - Update adminer to v4.8.1 - Update Redis repository ([PR #377](https://github.com/WordOps/WordOps/pull/377)) +- Set PHP 8.0 as default PHP version. Can be changed in `/etc/wo/wo.conf` #### Fixed diff --git a/wo/cli/plugins/stack_services.py b/wo/cli/plugins/stack_services.py index 7999b03..7d83a3c 100644 --- a/wo/cli/plugins/stack_services.py +++ b/wo/cli/plugins/stack_services.py @@ -411,6 +411,14 @@ class WOStackStatusController(CementBaseController): services = services + ['php7.4-fpm'] else: Log.info(self, "PHP7.4-FPM is not installed") + if os.path.exists('{0}'.format(wo_system) + 'php8.0-fpm.service'): + services = services + ['php8.0-fpm'] + else: + Log.info(self, "PHP8.0-FPM is not installed") + if os.path.exists('{0}'.format(wo_system) + 'php8.1-fpm.service'): + services = services + ['php8.1-fpm'] + else: + Log.info(self, "PHP8.1-FPM is not installed") if pargs.php72: if os.path.exists('{0}'.format(wo_system) + 'php7.2-fpm.service'): From 88e358f36c6f6d3ec1b84bcf99410a16de5999de Mon Sep 17 00:00:00 2001 From: VirtuBox Date: Wed, 26 Jan 2022 17:40:17 +0100 Subject: [PATCH 14/14] Update tests with PHP 8.0 & 8.1 --- tests/travis.sh | 56 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/tests/travis.sh b/tests/travis.sh index 7ee3096..62a0afa 100644 --- a/tests/travis.sh +++ b/tests/travis.sh @@ -32,9 +32,9 @@ echo -e "${CGREEN}#############################################${CEND}" echo -e ' stack install ' echo -e "${CGREEN}#############################################${CEND}" if [ "$wo_distro" != "xenial" ]; then -stack_list='nginx php php73 php74 mysql redis fail2ban clamav proftpd netdata phpmyadmin composer dashboard extplorer adminer redis sendmail phpredisadmin mysqltuner utils ufw cheat nanorc' +stack_list='nginx php php73 php74 php80 php81 mysql redis fail2ban clamav proftpd netdata phpmyadmin composer dashboard extplorer adminer redis sendmail phpredisadmin mysqltuner utils ufw cheat nanorc' else -stack_list='nginx php php73 php74 mysql redis fail2ban clamav proftpd netdata phpmyadmin composer dashboard extplorer adminer redis phpredisadmin mysqltuner utils ufw cheat nanorc' +stack_list='nginx php php73 php74 php80 php81 mysql redis fail2ban clamav proftpd netdata phpmyadmin composer dashboard extplorer adminer redis phpredisadmin mysqltuner utils ufw cheat nanorc' fi for stack in $stack_list; do echo -ne " Installing $stack [..]\r" @@ -54,7 +54,7 @@ done echo -e "${CGREEN}#############################################${CEND}" echo -e ' Simple site create ' echo -e "${CGREEN}#############################################${CEND}" -site_types='html php php72 php73 php74 mysql wp wpfc wpsc wpredis wpce wprocket wpsubdomain wpsubdir ngxblocker' +site_types='html php php72 php73 php74 php80 php81 mysql wp wpfc wpsc wpredis wpce wprocket wpsubdomain wpsubdir ngxblocker' for site in $site_types; do echo -ne " Creating $site [..]\r" if { @@ -151,6 +151,52 @@ echo wo site info wp.net echo echo -e "${CGREEN}#############################################${CEND}" +echo -e ' wo site update --php80 ' +echo -e "${CGREEN}#############################################${CEND}" +other_site_types='mysql php72 php73 wp wpfc wpsc wpredis wpce wprocket wpsubdomain wpsubdir' +for site in $other_site_types; do + echo -ne " Updating site to $site php80 [..]\r" + if { + wo site update ${site}.net --php80 + } >>/var/log/wo/test.log; then + echo -ne " Updating site to $site php80 [${CGREEN}OK${CEND}]\\r" + echo -ne '\n' + else + echo -e " Updating site to $site php80 [${CRED}FAIL${CEND}]" + echo -ne '\n' + exit_script + + fi +done +echo +echo -e "${CGREEN}#############################################${CEND}" +echo +wo site info wp.net +echo +echo -e "${CGREEN}#############################################${CEND}" +echo -e ' wo site update --php81 ' +echo -e "${CGREEN}#############################################${CEND}" +other_site_types='mysql php72 php73 wp wpfc wpsc wpredis wpce wprocket wpsubdomain wpsubdir' +for site in $other_site_types; do + echo -ne " Updating site to $site php81 [..]\r" + if { + wo site update ${site}.net --php81 + } >>/var/log/wo/test.log; then + echo -ne " Updating site to $site php81 [${CGREEN}OK${CEND}]\\r" + echo -ne '\n' + else + echo -e " Updating site to $site php81 [${CRED}FAIL${CEND}]" + echo -ne '\n' + exit_script + + fi +done +echo +echo -e "${CGREEN}#############################################${CEND}" +echo +wo site info wp.net +echo +echo -e "${CGREEN}#############################################${CEND}" echo -e ' wo site update WP ' echo -e "${CGREEN}#############################################${CEND}" @@ -214,7 +260,7 @@ if [ -z "$1" ]; then echo -e "${CGREEN}#############################################${CEND}" echo -e ' wo stack upgrade ' echo -e "${CGREEN}#############################################${CEND}" - stack_upgrade='nginx php php72 php73 php74 mysql redis netdata dashboard phpmyadmin adminer fail2ban composer ngxblocker mysqltuner' + stack_upgrade='nginx php php72 php73 php74 php80 php81 mysql redis netdata dashboard phpmyadmin adminer fail2ban composer ngxblocker mysqltuner' for stack in $stack_upgrade; do echo -ne " Upgrading $stack [..]\r" if { @@ -361,7 +407,7 @@ wo info echo -e "${CGREEN}#############################################${CEND}" echo -e ' wo stack purge ' echo -e "${CGREEN}#############################################${CEND}" -stack_purge='nginx php php73 php74 mysql redis fail2ban clamav proftpd netdata phpmyadmin composer dashboard extplorer adminer redis ufw ngxblocker cheat nanorc' +stack_purge='nginx php php73 php74 php80 php81 mysql redis fail2ban clamav proftpd netdata phpmyadmin composer dashboard extplorer adminer redis ufw ngxblocker cheat nanorc' for stack in $stack_purge; do echo -ne " purging $stack [..]\r" if {