feat: convert WordOps from Nginx to OpenLiteSpeed + LSPHP + LSCache
Some checks failed
CI / test WordOps (ubuntu-22.04) (push) Has been cancelled
CI / test WordOps (ubuntu-24.04) (push) Has been cancelled

Complete conversion of the WordOps stack from Nginx + PHP-FPM to
OpenLiteSpeed + LSPHP + LSCache. This is a full rewrite across all 7
phases of the codebase:

- Foundation: OLS paths, variables, services, removed pynginxconfig dep
- Templates: 11 new OLS mustache templates, removed nginx-specific ones
- Stack: stack_pref, stack, stack_services, stack_upgrade, stack_migrate
- Site: site_functions, site, site_create, site_update
- Plugins: debug, info, log, clean rewritten for OLS
- SSL/ACME: acme.sh deploy uses lswsctrl, OLS vhssl blocks
- Other: secure, backup, clone, install script

Additional features:
- Debian 13 (trixie) support
- PHP 8.5 support
- WP Fort Knox mu-plugin integration (wo secure --lockdown/--unlock)
- --nginx CLI flag preserved for backward compatibility

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-08 18:55:16 +01:00
parent aa127070e1
commit fa5bf17eb8
42 changed files with 2328 additions and 2926 deletions

View File

@@ -128,33 +128,36 @@ class WOAcme:
self, "mkdir -p {0}/{1} && {2} --install-cert -d {1} --ecc "
"--cert-file {0}/{1}/cert.pem --key-file {0}/{1}/key.pem "
"--fullchain-file {0}/{1}/fullchain.pem "
"--ca-file {0}/{1}/ca.pem --reloadcmd \"nginx -t && "
"service nginx restart\" "
"--ca-file {0}/{1}/ca.pem --reloadcmd \"{3} restart\" "
.format(WOVar.wo_ssl_live,
wo_domain_name, WOAcme.wo_acme_exec)):
wo_domain_name, WOAcme.wo_acme_exec,
WOVar.wo_ols_ctrl)):
Log.valide(self, "Deploying SSL cert")
else:
Log.failed(self, "Deploying SSL cert")
Log.error(self, "Unable to deploy certificate")
if os.path.isdir('/var/www/{0}/conf/nginx'
.format(wo_domain_name)):
vhost_dir = '{0}/{1}'.format(
WOVar.wo_ols_vhost_dir, wo_domain_name)
if os.path.isdir(vhost_dir):
data = dict(ssl_live_path=WOVar.wo_ssl_live,
domain=wo_domain_name, quic=True)
WOTemplate.deploy(self,
'/var/www/{0}/conf/nginx/ssl.conf'
.format(wo_domain_name),
'ssl.mustache', data, overwrite=False)
'{0}/ssl.conf'.format(vhost_dir),
'ols-ssl.mustache', data, overwrite=False)
if not WOFileUtils.grep(self, '/var/www/22222/conf/nginx/ssl.conf',
'/etc/letsencrypt'):
backend_ssl = '{0}/22222/vhconf.conf'.format(
WOVar.wo_ols_vhost_dir)
if (os.path.isfile(backend_ssl) and
not WOFileUtils.grep(
self, backend_ssl, '/etc/letsencrypt')):
Log.info(self, "Securing WordOps backend with current cert")
data = dict(ssl_live_path=WOVar.wo_ssl_live,
domain=wo_domain_name, quic=False)
WOTemplate.deploy(self,
'/var/www/22222/conf/nginx/ssl.conf',
'ssl.mustache', data, overwrite=True)
'{0}/22222/ssl.conf'.format(
WOVar.wo_ols_vhost_dir),
'ols-ssl.mustache', data, overwrite=True)
WOGit.add(self, ["/etc/letsencrypt"],
msg="Adding letsencrypt folder")
@@ -223,16 +226,13 @@ class WOAcme:
return False
def removeconf(self, domain):
sslconf = ("/var/www/{0}/conf/nginx/ssl.conf"
.format(domain))
sslforce = ("/etc/nginx/conf.d/force-ssl-{0}.conf"
.format(domain))
sslconf = ("{0}/{1}/ssl.conf"
.format(WOVar.wo_ols_vhost_dir, domain))
acmedir = [
'{0}'.format(sslforce), '{0}'.format(sslconf),
'{0}'.format(sslconf),
'{0}/{1}_ecc'.format(WOVar.wo_ssl_archive, domain),
'{0}.disabled'.format(sslconf), '{0}.disabled'
.format(sslforce), '{0}/{1}'
.format(WOVar.wo_ssl_live, domain),
'{0}.disabled'.format(sslconf),
'{0}/{1}'.format(WOVar.wo_ssl_live, domain),
'/etc/letsencrypt/shared/{0}.conf'.format(domain)]
wo_domain = domain
# check acme.sh is installed
@@ -255,16 +255,15 @@ class WOAcme:
else:
if os.path.islink("{0}".format(sslconf)):
WOFileUtils.remove_symlink(self, "{0}".format(sslconf))
WOFileUtils.rm(self, '{0}'.format(sslforce))
if WOFileUtils.grepcheck(self, '/var/www/22222/conf/nginx/ssl.conf',
'{0}'.format(domain)):
backend_ssl = '{0}/22222/ssl.conf'.format(WOVar.wo_ols_vhost_dir)
if (os.path.isfile(backend_ssl) and
WOFileUtils.grepcheck(self, backend_ssl,
'{0}'.format(domain))):
Log.info(
self, "Setting back default certificate for WordOps backend")
with open("/var/www/22222/conf/nginx/"
"ssl.conf", "w") as ssl_conf_file:
ssl_conf_file.write("ssl_certificate "
"/var/www/22222/cert/22222.crt;\n"
"ssl_certificate_key "
"/var/www/22222/cert/22222.key;\n"
"ssl_stapling off;\n")
with open(backend_ssl, "w") as ssl_conf_file:
ssl_conf_file.write("vhssl {\n"
" keyFile /var/www/22222/cert/22222.key\n"
" certFile /var/www/22222/cert/22222.crt\n"
"}\n")

View File

@@ -94,7 +94,7 @@ class WOMysql():
try:
Log.info(self, "Backing up database at location: "
"/var/lib/wo-backup/mysql")
# Setup Nginx common directory
# Setup backup directory
if not os.path.exists('/var/lib/wo-backup/mysql'):
Log.debug(self, 'Creating directory'
'/var/lib/wo-backup/mysql')

View File

@@ -1,19 +1,2 @@
"""WordOps Nginx Manager"""
import subprocess
from wo.core.logging import Log
def check_config(self):
"""Check Nginx configuration and return boolean"""
Log.debug(self, "Testing Nginx configuration ")
# Check Nginx configuration before executing command
sub = subprocess.Popen('nginx -t', stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True)
output, error_output = sub.communicate()
if 'emerg' in str(error_output):
Log.debug(self, "Nginx configuration check failed")
return False
else:
Log.debug(self, "Nginx configuration check was successful")
return True
"""WordOps Nginx compatibility module - redirects to OLS"""
from wo.core.ols import check_config # noqa: F401

View File

@@ -1,49 +1,6 @@
"""WordOps Hash Bucket Calculator"""
import fileinput
import math
import os
import subprocess
from wo.core.fileutils import WOFileUtils
"""Deprecated: OLS does not require hash bucket configuration"""
def hashbucket(self):
# Check Nginx Hashbucket error
sub = subprocess.Popen('nginx -t', stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True)
output, error_output = sub.communicate()
if 'server_names_hash_bucket_size' not in str(error_output):
return True
count = 0
# Get the list of sites-availble
sites_list = os.listdir("/etc/nginx/sites-enabled/")
# Count the number of characters in site names
for site in sites_list:
count = sum([count, len(site)])
# Calculate Nginx hash bucket size
ngx_calc = math.trunc(sum([math.log(count, 2), 2]))
ngx_hash = math.trunc(math.pow(2, ngx_calc))
# Replace hashbucket in Nginx.conf file
if WOFileUtils.grepcheck(self, "/etc/nginx/nginx.conf",
"# server_names_hash_bucket_size 64;"):
ngxconf = open("/etc/nginx/conf.d/hashbucket.conf",
encoding='utf-8', mode='w')
ngxconf.write("\tserver_names_hash_bucket_size {0};".format(ngx_hash))
ngxconf.close()
elif WOFileUtils.grepcheck(self, "/etc/nginx/nginx/conf",
"server_names_hash_bucket_size"):
for line in fileinput.FileInput("/etc/nginx/nginx.conf", inplace=1):
if "server_names_hash_bucket_size" in line:
print("\tserver_names_hash_bucket_size {0};".format(ngx_hash))
else:
print(line, end='')
else:
ngxconf = open("/etc/nginx/conf.d/hashbucket.conf",
encoding='utf-8', mode='w')
ngxconf.write("\tserver_names_hash_bucket_size {0};".format(ngx_hash))
ngxconf.close()
"""No-op: OpenLiteSpeed does not need hash bucket configuration"""
return True

19
wo/core/ols.py Normal file
View File

@@ -0,0 +1,19 @@
"""WordOps OpenLiteSpeed Manager"""
import subprocess
from wo.core.logging import Log
def check_config(self):
"""Check OpenLiteSpeed configuration and return boolean"""
Log.debug(self, "Testing OpenLiteSpeed configuration ")
sub = subprocess.Popen('/usr/local/lsws/bin/openlitespeed -t',
stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True)
output, error_output = sub.communicate()
if 'ERROR' in str(error_output) or sub.returncode != 0:
Log.debug(self, "OpenLiteSpeed configuration check failed")
return False
else:
Log.debug(self, "OpenLiteSpeed configuration check was successful")
return True

View File

@@ -15,24 +15,25 @@ class WOService():
Similar to `service xyz start`
"""
try:
if service_name in ['nginx']:
Log.wait(self, "Testing Nginx configuration ")
# Check Nginx configuration before executing command
sub = subprocess.Popen('nginx -t', stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True)
if service_name in ['lsws']:
Log.wait(self, "Testing OpenLiteSpeed configuration ")
sub = subprocess.Popen(
'/usr/local/lsws/bin/openlitespeed -t',
stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True)
output = sub.communicate()
if 'emerg' not in str(output):
Log.valide(self, "Testing Nginx configuration ")
Log.wait(self, "Starting Nginx")
service_cmd = ('service {0} start'.format(service_name))
if sub.returncode == 0:
Log.valide(self, "Testing OpenLiteSpeed configuration ")
Log.wait(self, "Starting OpenLiteSpeed")
service_cmd = ('/usr/local/lsws/bin/lswsctrl start')
retcode = subprocess.getstatusoutput(service_cmd)
if retcode[0] == 0:
Log.valide(self, "Starting Nginx ")
Log.valide(self, "Starting OpenLiteSpeed ")
return True
else:
Log.failed(self, "Starting Nginx")
Log.failed(self, "Starting OpenLiteSpeed")
else:
Log.failed(self, "Testing Nginx configuration ")
Log.failed(self, "Testing OpenLiteSpeed configuration ")
return False
else:
service_cmd = ('service {0} start'.format(service_name))
@@ -59,9 +60,14 @@ class WOService():
Similar to `service xyz stop`
"""
try:
Log.info(self, "Stop : {0:10}" .format(service_name), end='')
retcode = subprocess.getstatusoutput('service {0} stop'
.format(service_name))
if service_name in ['lsws']:
Log.info(self, "Stop : {0:10}" .format(service_name), end='')
retcode = subprocess.getstatusoutput(
'/usr/local/lsws/bin/lswsctrl stop')
else:
Log.info(self, "Stop : {0:10}" .format(service_name), end='')
retcode = subprocess.getstatusoutput('service {0} stop'
.format(service_name))
if retcode[0] == 0:
Log.info(self, "[" + Log.ENDC + Log.OKGREEN + "OK" +
Log.ENDC + Log.OKBLUE + "]")
@@ -81,22 +87,23 @@ class WOService():
Similar to `service xyz restart`
"""
try:
if service_name in ['nginx']:
Log.wait(self, "Testing Nginx configuration ")
# Check Nginx configuration before executing command
sub = subprocess.Popen('nginx -t', stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True)
if service_name in ['lsws']:
Log.wait(self, "Testing OpenLiteSpeed configuration ")
sub = subprocess.Popen(
'/usr/local/lsws/bin/openlitespeed -t',
stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True)
output, error_output = sub.communicate()
if 'emerg' not in str(error_output):
Log.valide(self, "Testing Nginx configuration ")
Log.wait(self, "Restarting Nginx")
service_cmd = ('service {0} restart'.format(service_name))
if sub.returncode == 0:
Log.valide(self, "Testing OpenLiteSpeed configuration ")
Log.wait(self, "Restarting OpenLiteSpeed")
service_cmd = ('/usr/local/lsws/bin/lswsctrl restart')
retcode = subprocess.getstatusoutput(service_cmd)
if retcode[0] == 0:
Log.valide(self, "Restarting Nginx")
Log.valide(self, "Restarting OpenLiteSpeed")
return True
else:
Log.failed(self, "Testing Nginx configuration ")
Log.failed(self, "Testing OpenLiteSpeed configuration ")
return False
else:
service_cmd = ('service {0} restart'.format(service_name))
@@ -123,22 +130,23 @@ class WOService():
Similar to `service xyz reload`
"""
try:
if service_name in ['nginx']:
# Check Nginx configuration before executing command
Log.wait(self, "Testing Nginx configuration ")
sub = subprocess.Popen('nginx -t', stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True)
if service_name in ['lsws']:
Log.wait(self, "Testing OpenLiteSpeed configuration ")
sub = subprocess.Popen(
'/usr/local/lsws/bin/openlitespeed -t',
stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True)
output, error_output = sub.communicate()
if 'emerg' not in str(error_output):
Log.valide(self, "Testing Nginx configuration ")
Log.wait(self, "Reloading Nginx")
service_cmd = ('service {0} reload'.format(service_name))
if sub.returncode == 0:
Log.valide(self, "Testing OpenLiteSpeed configuration ")
Log.wait(self, "Reloading OpenLiteSpeed")
service_cmd = ('/usr/local/lsws/bin/lswsctrl restart')
retcode = subprocess.getstatusoutput(service_cmd)
if retcode[0] == 0:
Log.valide(self, "Reloading Nginx")
Log.valide(self, "Reloading OpenLiteSpeed")
return True
else:
Log.failed(self, "Testing Nginx configuration ")
Log.failed(self, "Testing OpenLiteSpeed configuration ")
return False
else:
service_cmd = ('service {0} reload'.format(service_name))
@@ -162,26 +170,27 @@ class WOService():
def get_service_status(self, service_name):
try:
is_exist = subprocess.getstatusoutput('command -v {0}'
.format(service_name))
if is_exist[0] == 0 or service_name in ['php7.2-fpm',
'php7.3-fpm',
'php7.4-fpm',
'php8.0-fpm',
'php8.1-fpm',
'php8.2-fpm',
'php8.3-fpm',
'php8.4-fpm',
]:
retcode = subprocess.getstatusoutput('service {0} status'
.format(service_name))
if service_name in ['lsws']:
retcode = subprocess.getstatusoutput(
'/usr/local/lsws/bin/lswsctrl status')
if retcode[0] == 0:
return True
else:
Log.debug(self, "{0}".format(retcode[1]))
return False
else:
return False
is_exist = subprocess.getstatusoutput('command -v {0}'
.format(service_name))
if is_exist[0] == 0:
retcode = subprocess.getstatusoutput('service {0} status'
.format(service_name))
if retcode[0] == 0:
return True
else:
Log.debug(self, "{0}".format(retcode[1]))
return False
else:
return False
except OSError as e:
Log.debug(self, "{0}{1}".format(e.errno, e.strerror))
Log.error(self, "Unable to get services status of {0}"

View File

@@ -55,7 +55,8 @@ class SSL:
# check if exist
if not os.path.isfile('/etc/letsencrypt/live/{0}/cert.pem'
.format(domain)):
if os.path.exists('/var/www/{0}/conf/nginx/ssl.conf'):
if os.path.exists('{0}/{1}/ssl.conf'
.format(WOVar.wo_ols_vhost_dir, domain)):
split_domain = domain.split('.')
check_domain = ('.').join(split_domain[1:])
else:
@@ -135,36 +136,46 @@ class SSL:
return False
def setuphsts(self, wo_domain_name, enable=True):
"""Enable or disable htsts for a site"""
"""Enable or disable HSTS for a site via OLS vhost config"""
vhconf = '{0}/{1}/vhconf.conf'.format(
WOVar.wo_ols_vhost_dir, wo_domain_name)
if enable is True:
if WOFileUtils.enabledisable(
self, f'/var/www/{wo_domain_name}/conf/nginx/hsts.conf'
):
if os.path.isfile(vhconf):
if not WOFileUtils.grepcheck(
self, vhconf, 'Strict-Transport-Security'):
Log.info(
self, "Enabling HSTS for {0}"
.format(wo_domain_name))
# Add HSTS header via OLS context configuration
hsts_block = ('\nmodule header {\n'
' note {\n'
' Strict-Transport-Security '
'"max-age=31536000; '
'includeSubDomains; preload"\n'
' }\n'
'}\n')
with open(vhconf, 'a', encoding='utf-8') as f:
f.write(hsts_block)
return 0
else:
Log.info(
self, "Adding /var/www/{0}/conf/nginx/hsts.conf"
.format(wo_domain_name))
hstsconf = open(f"/var/www/{wo_domain_name}/conf/nginx/hsts.conf",
encoding='utf-8', mode='w')
hstsconf.write("more_set_headers "
"\"Strict-Transport-Security: "
"max-age=31536000; "
"includeSubDomains; "
"preload\";")
hstsconf.close()
return 0
Log.info(self, "Vhost config not found for {0}"
.format(wo_domain_name))
return 1
else:
if WOFileUtils.enabledisable(
self, f'/var/www/{wo_domain_name}/conf/nginx/hsts.conf',
enable=False
):
Log.info(self, "HSTS disabled")
return 0
else:
Log.info(self, "HSTS is not enabled")
return 0
if os.path.isfile(vhconf):
if WOFileUtils.grepcheck(
self, vhconf, 'Strict-Transport-Security'):
Log.info(self, "HSTS disabled")
# Remove HSTS header block
WOFileUtils.searchreplace(
self, vhconf,
'Strict-Transport-Security',
'# HSTS disabled')
return 0
else:
Log.info(self, "HSTS is not enabled")
return 0
return 0
def selfsignedcert(self, proftpd=False, backend=False):
"""issue a self-signed certificate"""
@@ -227,43 +238,40 @@ class SSL:
WOFileUtils.rm(self, selfs_tmp)
def httpsredirect(self, wo_domain_name, acme_domains, redirect=True):
"""Create Nginx redirection from http to https"""
wo_acme_domains = ' '.join(acme_domains)
data = dict(domains=wo_acme_domains)
"""Enable/disable HTTPS redirect in OLS vhost config"""
vhconf = '{0}/{1}/vhconf.conf'.format(
WOVar.wo_ols_vhost_dir, wo_domain_name)
if redirect:
Log.wait(self, "Adding HTTPS redirection")
if WOFileUtils.enabledisable(
self, '/etc/nginx/conf.d/force-ssl-{0}.conf'
.format(wo_domain_name), enable=True):
if os.path.isfile(vhconf):
if not WOFileUtils.grepcheck(
self, vhconf, 'forceSecure'):
# Add forceSecure directive to OLS vhost
WOFileUtils.searchreplace(
self, vhconf,
'docRoot',
'forceSecure 1\n docRoot')
Log.valide(self, "Adding HTTPS redirection")
return 0
else:
try:
WOTemplate.deploy(self,
f'/etc/nginx/conf.d/force-ssl-{wo_domain_name}.conf',
'force-ssl.mustache',
data)
except IOError as e:
Log.debug(self, str(e))
Log.debug(
self, "Error occured while generating "
"/etc/nginx/conf.d/force-ssl-{0}.conf"
.format(wo_domain_name))
return 1
Log.valide(self, "Adding HTTPS redirection")
return 0
Log.debug(
self, "Vhost config not found for {0}"
.format(wo_domain_name))
return 1
else:
if WOFileUtils.enabledisable(
self, "/etc/nginx/conf.d/force-ssl-{0}.conf"
.format(wo_domain_name), enable=False):
Log.info(
self, "Disabled HTTPS Force Redirection for site "
"{0}".format(wo_domain_name))
else:
Log.info(
self, "HTTPS redirection already disabled for site"
"{0}".format(wo_domain_name)
)
if os.path.isfile(vhconf):
if WOFileUtils.grepcheck(
self, vhconf, 'forceSecure'):
WOFileUtils.searchreplace(
self, vhconf,
'forceSecure 1\n', '')
Log.info(
self, "Disabled HTTPS Force Redirection for site "
"{0}".format(wo_domain_name))
else:
Log.info(
self, "HTTPS redirection already disabled for site "
"{0}".format(wo_domain_name))
return 0
def archivedcertificatehandle(self, domain, acme_domains):
@@ -305,12 +313,11 @@ class SSL:
else:
Log.error(self, "Operation cancelled by user.")
if os.path.isfile("{0}/conf/nginx/ssl.conf"
.format(domain)):
vhost_ssl = "{0}/{1}/ssl.conf".format(
WOVar.wo_ols_vhost_dir, domain)
if os.path.isfile(vhost_ssl):
Log.info(self, "Existing ssl.conf . Backing it up ..")
WOFileUtils.mvfile(self, "/var/www/{0}/conf/nginx/ssl.conf"
.format(domain),
'/var/www/{0}/conf/nginx/ssl.conf.bak'
.format(domain))
WOFileUtils.mvfile(self, vhost_ssl,
'{0}.bak'.format(vhost_ssl))
return ssl

View File

@@ -10,41 +10,18 @@ class WOConf():
def __init__():
pass
def nginxcommon(self):
"""nginx common configuration deployment"""
def olscommon(self):
"""OpenLiteSpeed common configuration deployment - deploy extApp configs"""
wo_php_version = list(WOVar.wo_php_versions.keys())
ngxcom = '/etc/nginx/common'
if not os.path.exists(ngxcom):
os.mkdir(ngxcom)
ols_conf = WOVar.wo_ols_conf_dir
for wo_php in wo_php_version:
Log.debug(self, 'deploying templates for {0}'.format(wo_php))
data = dict(upstream="{0}".format(wo_php),
release=WOVar.wo_version)
short_ver = WOVar.wo_php_versions[wo_php].replace('.', '')
Log.debug(self, 'deploying OLS extApp config for {0}'.format(wo_php))
data = dict(
php_version=WOVar.wo_php_versions[wo_php],
short_version=short_ver,
release=WOVar.wo_version)
WOTemplate.deploy(self,
'{0}/{1}.conf'
.format(ngxcom, wo_php),
'php.mustache', data)
WOTemplate.deploy(
self, '{0}/redis-{1}.conf'.format(ngxcom, wo_php),
'redis.mustache', data)
WOTemplate.deploy(
self, '{0}/wpcommon-{1}.conf'.format(ngxcom, wo_php),
'wpcommon.mustache', data)
WOTemplate.deploy(
self, '{0}/wpfc-{1}.conf'.format(ngxcom, wo_php),
'wpfc.mustache', data)
WOTemplate.deploy(
self, '{0}/wpsc-{1}.conf'.format(ngxcom, wo_php),
'wpsc.mustache', data)
WOTemplate.deploy(
self, '{0}/wprocket-{1}.conf'.format(ngxcom, wo_php),
'wprocket.mustache', data)
WOTemplate.deploy(
self, '{0}/wpce-{1}.conf'.format(ngxcom, wo_php),
'wpce.mustache', data)
'{0}/lsphp{1}.conf'
.format(ols_conf, short_ver),
'ols-extapp.mustache', data)

View File

@@ -115,10 +115,17 @@ class WOVar():
wo_mysql_host = "localhost"
# WordOps stack installation variables
# Nginx repo and packages
if wo_distro == 'ubuntu':
wo_nginx_repo = "ppa:wordops/nginx-wo"
# OpenLiteSpeed path constants
wo_ols_conf_dir = '/usr/local/lsws/conf'
wo_ols_vhost_dir = '/usr/local/lsws/conf/vhosts'
wo_ols_bin = '/usr/local/lsws/bin/openlitespeed'
wo_ols_ctrl = '/usr/local/lsws/bin/lswsctrl'
# OpenLiteSpeed repo and packages
if wo_distro == 'ubuntu':
wo_ols_repo = ("deb [signed-by=/usr/share/keyrings/openlitespeed-keyring.gpg] "
"http://rpms.litespeedtech.com/debian/ "
"{0} main".format(wo_platform_codename))
else:
if wo_distro == 'debian':
if wo_platform_codename == 'buster':
@@ -127,6 +134,8 @@ class WOVar():
wo_deb_repo = "Debian_11"
elif wo_platform_codename == 'bookworm':
wo_deb_repo = "Debian_12"
elif wo_platform_codename == 'trixie':
wo_deb_repo = "Debian_13"
elif wo_distro == 'raspbian':
if wo_platform_codename == 'buster':
wo_deb_repo = "Raspbian_10"
@@ -134,14 +143,14 @@ class WOVar():
wo_deb_repo = "Raspbian_11"
elif wo_platform_codename == 'bookworm':
wo_deb_repo = "Raspbian_12"
# debian/raspbian nginx repository
wo_nginx_repo = ("deb [signed-by=/usr/share/keyrings/wordops-archive-keyring.gpg] "
"http://download.opensuse.org"
f"/repositories/home:/virtubox:/WordOps/{wo_deb_repo}/ /")
wo_nginx_key = (f"https://download.opensuse.org/repositories/home:virtubox:WordOps/{wo_deb_repo}/Release.key")
elif wo_platform_codename == 'trixie':
wo_deb_repo = "Raspbian_13"
wo_ols_repo = ("deb [signed-by=/usr/share/keyrings/openlitespeed-keyring.gpg] "
"http://rpms.litespeedtech.com/debian/ "
"{0} main".format(wo_platform_codename))
wo_nginx = ["nginx-custom", "nginx-wo"]
wo_nginx_key = 'FB898660'
wo_ols = ["openlitespeed"]
wo_ols_repo_key = "https://rpms.litespeedtech.com/debian/lst_debian_repo.gpg"
wo_php_versions = {
'php74': '7.4',
@@ -150,27 +159,34 @@ class WOVar():
'php82': '8.2',
'php83': '8.3',
'php84': '8.4',
'php85': '8.5',
}
def generate_php_modules(version_prefix, version_number):
wo_module = ["bcmath", "cli", "common", "curl", "fpm", "gd", "igbinary",
def generate_lsphp_modules(version_prefix, version_number):
"""Generate LSPHP module package list for a given PHP version.
LSPHP packages use lsphpXX- naming (no dot in version)."""
short_ver = version_number.replace('.', '')
wo_module = ["common", "curl", "gd", "igbinary",
"imagick", "imap", "intl", "mbstring", "memcached", "msgpack",
"mysql", "opcache", "readline", "redis", "soap", "xdebug",
"mysql", "opcache", "redis", "soap",
"xml", "zip"]
php_modules = ["php{0}-{1}".format(version_number, module) for module in wo_module]
# lsphp packages: lsphpXX, lsphpXX-common, lsphpXX-curl, etc.
php_modules = ["lsphp{0}".format(short_ver)]
php_modules.extend(["lsphp{0}-{1}".format(short_ver, module) for module in wo_module])
if version_prefix == 'php74':
php_modules.extend(["php{0}-geoip".format(version_number),
"php{0}-json".format(version_number)])
php_modules.extend(["lsphp{0}-json".format(short_ver)])
return php_modules
wo_php74 = generate_php_modules('php74', '7.4')
wo_php80 = generate_php_modules('php80', '8.0')
wo_php81 = generate_php_modules('php81', '8.1')
wo_php82 = generate_php_modules('php82', '8.2')
wo_php83 = generate_php_modules('php83', '8.3')
wo_php84 = generate_php_modules('php84', '8.4')
wo_php74 = generate_lsphp_modules('php74', '7.4')
wo_php80 = generate_lsphp_modules('php80', '8.0')
wo_php81 = generate_lsphp_modules('php81', '8.1')
wo_php82 = generate_lsphp_modules('php82', '8.2')
wo_php83 = generate_lsphp_modules('php83', '8.3')
wo_php84 = generate_lsphp_modules('php84', '8.4')
wo_php85 = generate_lsphp_modules('php85', '8.5')
wo_php_extra = ["graphviz"]
@@ -194,14 +210,14 @@ class WOVar():
f"{mariadb_ver}/{wo_distro} {wo_platform_codename} main")
mariadb_repo_key = "https://mariadb.org/mariadb_release_signing_key.pgp"
if wo_distro == 'ubuntu':
wo_php_repo = "ppa:ondrej/php"
# LSPHP comes from LiteSpeed repo (same as OLS)
wo_php_repo = wo_ols_repo
wo_goaccess_repo = ("ppa:alex-p/goaccess")
else:
wo_php_repo = (
"deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] "
f"https://packages.sury.org/php/ {wo_platform_codename} main")
wo_php_key = '95BD4743'
# LSPHP comes from LiteSpeed repo (same as OLS)
wo_php_repo = wo_ols_repo
wo_php_key = wo_ols_repo_key
wo_redis_key_url = "https://packages.redis.io/gpg"
wo_redis_repo = (
"deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] "