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

@@ -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