mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2025-10-30 18:06:35 +01:00
Update PHP version references and improve AlmaLinux 9 compatibility
- Changed PHP symlink from version 8.0 to 8.3 in various scripts to ensure compatibility with the latest PHP version. - Updated documentation links in the FAQ to point to the new community support page. - Added checks and fixes for MariaDB installation issues specific to AlmaLinux 9. - Enhanced the installation script to support additional PHP versions and improve overall installation reliability.
This commit is contained in:
@@ -39,9 +39,9 @@ CyberPanel supports a wide range of PHP versions across different operating syst
|
|||||||
|
|
||||||
### ☑️ **Currently Supported PHP Versions**
|
### ☑️ **Currently Supported PHP Versions**
|
||||||
|
|
||||||
- **PHP 8.5** - Latest stable version (EOL: Dec 2028)
|
- **PHP 8.5** - Latest stable version (EOL: Dec 2028) ⭐ **NEW!**
|
||||||
- **PHP 8.4** - Stable version (EOL: Dec 2027)
|
- **PHP 8.4** - Stable version (EOL: Dec 2027)
|
||||||
- **PHP 8.3** - Stable version (EOL: Dec 2027)
|
- **PHP 8.3** - **Default version** - Stable version (EOL: Dec 2027) 🎯
|
||||||
- **PHP 8.2** - Stable version (EOL: Dec 2026)
|
- **PHP 8.2** - Stable version (EOL: Dec 2026)
|
||||||
- **PHP 8.1** - Stable version (EOL: Dec 2025)
|
- **PHP 8.1** - Stable version (EOL: Dec 2025)
|
||||||
- **PHP 8.0** - Legacy support (EOL: Nov 2023)
|
- **PHP 8.0** - Legacy support (EOL: Nov 2023)
|
||||||
|
|||||||
@@ -2278,7 +2278,7 @@ echo "echo \$@ > /etc/cyberpanel/adminPass" >> /usr/bin/adminPass
|
|||||||
chmod 700 /usr/bin/adminPass
|
chmod 700 /usr/bin/adminPass
|
||||||
|
|
||||||
rm -f /usr/bin/php
|
rm -f /usr/bin/php
|
||||||
ln -s /usr/local/lsws/lsphp80/bin/php /usr/bin/php
|
ln -s /usr/local/lsws/lsphp83/bin/php /usr/bin/php
|
||||||
|
|
||||||
if [[ "$Server_OS" = "CentOS" ]] ; then
|
if [[ "$Server_OS" = "CentOS" ]] ; then
|
||||||
#all centos 7/8 post change goes here
|
#all centos 7/8 post change goes here
|
||||||
|
|||||||
14
faq.sh
14
faq.sh
@@ -28,7 +28,7 @@ ${BLUE}------------------------------------------------------------${NC}
|
|||||||
|
|
||||||
${PURPLE}3.${NC} How to access LiteSpeed webadmin console ?
|
${PURPLE}3.${NC} How to access LiteSpeed webadmin console ?
|
||||||
|
|
||||||
Please check this post: ${GREEN}https://forums.cyberpanel.net/discussion/87/tutorial-how-to-setup-and-login-to-openlitespeed-webadmin-console/p1${NC}
|
Please check this post: ${GREEN}https://community.cyberpanel.net/c/support/55${NC}
|
||||||
|
|
||||||
${BLUE}------------------------------------------------------------${NC}
|
${BLUE}------------------------------------------------------------${NC}
|
||||||
|
|
||||||
@@ -52,9 +52,9 @@ ${BLUE}------------------------------------------------------------${NC}
|
|||||||
|
|
||||||
${PURPLE}6.${NC} How to raise upload limit for cyberpanel's phpMyAdmin and File Manager?
|
${PURPLE}6.${NC} How to raise upload limit for cyberpanel's phpMyAdmin and File Manager?
|
||||||
|
|
||||||
edit file ${RED}/usr/local/lsws/lsphp73/etc/php.ini${NC} for CentOS or openEuler
|
edit file ${RED}/usr/local/lsws/lsphp83/etc/php.ini${NC} for CentOS or openEuler
|
||||||
|
|
||||||
${RED}/usr/local/lsws/lsphp73/etc/php/7.3/litespeed/php.ini${NC} for Ubbuntu
|
${RED}/usr/local/lsws/lsphp83/etc/php/8.3/litespeed/php.ini${NC} for Ubuntu
|
||||||
|
|
||||||
find 2 configurations:
|
find 2 configurations:
|
||||||
|
|
||||||
@@ -66,9 +66,9 @@ ${BLUE}------------------------------------------------------------${NC}
|
|||||||
|
|
||||||
${PURPLE}7.${NC} How to add more IPs to my website(s) ?
|
${PURPLE}7.${NC} How to add more IPs to my website(s) ?
|
||||||
|
|
||||||
For OpenLiteSpeed, please check this post: ${GREEN}https://forums.cyberpanel.net/discussion/126/tutorial-how-to-add-2nd-ip-for-websites/p1${NC}
|
For OpenLiteSpeed, please check this post: ${GREEN}https://community.cyberpanel.net/c/support/55${NC}
|
||||||
|
|
||||||
For LiteSpeed Enterprise, please check this post: ${GREEN}https://forums.cyberpanel.net/discussion/3745/tutorial-how-to-add-2nd-ip-for-litespeed-enterprise/p1${NC}
|
For LiteSpeed Enterprise, please check this post: ${GREEN}https://community.cyberpanel.net/c/support/55${NC}
|
||||||
|
|
||||||
${BLUE}------------------------------------------------------------${NC}
|
${BLUE}------------------------------------------------------------${NC}
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ ${BLUE}------------------------------------------------------------${NC}
|
|||||||
|
|
||||||
${PURPLE}9.${NC} How to enable Auto-Index for my site ?
|
${PURPLE}9.${NC} How to enable Auto-Index for my site ?
|
||||||
|
|
||||||
Please check this post ${GREEN}https://forums.cyberpanel.net/discussion/3850/tutorial-how-to-enable-auto-index-on-openlitespeed-and-litespeed-enterprise${NC}
|
Please check this post ${GREEN}https://community.cyberpanel.net/c/support/55${NC}
|
||||||
|
|
||||||
${BLUE}------------------------------------------------------------${NC}
|
${BLUE}------------------------------------------------------------${NC}
|
||||||
|
|
||||||
@@ -111,5 +111,5 @@ ${BLUE}------------------------------------------------------------${NC}
|
|||||||
|
|
||||||
${PURPLE}13.${NC} How to enable PHP error log ?
|
${PURPLE}13.${NC} How to enable PHP error log ?
|
||||||
|
|
||||||
Please check this post ${GREEN}https://forums.cyberpanel.net/discussion/3977/tutorial-how-to-enable-php-error-log/p1${NC}
|
Please check this post ${GREEN}https://community.cyberpanel.net/c/support/55${NC}
|
||||||
"
|
"
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
import os
|
|
||||||
import shutil
|
|
||||||
import pathlib
|
|
||||||
import stat
|
|
||||||
|
|
||||||
|
|
||||||
def mkdir_p(path, exist_ok=True):
|
|
||||||
"""
|
|
||||||
Creates the directory and paths leading up to it like unix mkdir -p .
|
|
||||||
Defaults to exist_ok so if it exists were not throwing fatal errors
|
|
||||||
https://docs.python.org/3.7/library/os.html#os.makedirs
|
|
||||||
"""
|
|
||||||
if not os.path.exists(path):
|
|
||||||
print('creating directory: ' + path)
|
|
||||||
os.makedirs(path, exist_ok)
|
|
||||||
|
|
||||||
|
|
||||||
def chmod_digit(file_path, perms):
|
|
||||||
"""
|
|
||||||
Helper function to chmod like you would in unix without having to preface 0o or converting to octal yourself.
|
|
||||||
Credits: https://stackoverflow.com/a/60052847/1621381
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
os.chmod(file_path, int(str(perms), base=8))
|
|
||||||
except:
|
|
||||||
print(f'Could not chmod : {file_path} to {perms}')
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def touch(filepath: str, exist_ok=True):
|
|
||||||
"""
|
|
||||||
Touches a file like unix `touch somefile` would.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
pathlib.Path(filepath).touch(exist_ok)
|
|
||||||
except FileExistsError:
|
|
||||||
print('Could touch : ' + filepath)
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def symlink(src, dst):
|
|
||||||
"""
|
|
||||||
Symlink a path to another if the src exists.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
if os.access(src, os.R_OK):
|
|
||||||
os.symlink(src, dst)
|
|
||||||
except:
|
|
||||||
print(f'Could not symlink Source: {src} > Destination: {dst}')
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def chown(path, user, group=-1):
|
|
||||||
"""
|
|
||||||
Chown file/path to user/group provided. Passing -1 to user or group will leave it unchanged.
|
|
||||||
Useful if just changing user or group vs both.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
shutil.chown(path, user, group)
|
|
||||||
except PermissionError:
|
|
||||||
print(f'Could not change permissions for: {path} to {user}:{group}')
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def recursive_chown(path, owner, group=-1):
|
|
||||||
"""
|
|
||||||
Recursively chown a path and contents to owner.
|
|
||||||
https://docs.python.org/3/library/shutil.html
|
|
||||||
"""
|
|
||||||
for dirpath, dirnames, filenames in os.walk(path):
|
|
||||||
try:
|
|
||||||
shutil.chown(dirpath, owner, group)
|
|
||||||
except PermissionError:
|
|
||||||
print('Could not change permissions for: ' + dirpath + ' to: ' + owner)
|
|
||||||
pass
|
|
||||||
for filename in filenames:
|
|
||||||
try:
|
|
||||||
shutil.chown(os.path.join(dirpath, filename), owner, group)
|
|
||||||
except PermissionError:
|
|
||||||
print('Could not change permissions for: ' + os.path.join(dirpath, filename) + ' to: ' + owner)
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def recursive_permissions(path, dir_mode=755, file_mode=644, topdir=True):
|
|
||||||
"""
|
|
||||||
Recursively chmod a path and contents to mode.
|
|
||||||
Defaults to chmod top level directory but can be optionally
|
|
||||||
toggled off when you want to chmod only contents of like a user's homedir vs homedir itself
|
|
||||||
https://docs.python.org/3.6/library/os.html#os.walk
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Here we are converting the integers to string and then to octal.
|
|
||||||
# so this function doesn't need to be called with 0o prefixed for the file and dir mode
|
|
||||||
dir_mode = int(str(dir_mode), base=8)
|
|
||||||
file_mode = int(str(file_mode), base=8)
|
|
||||||
|
|
||||||
if topdir:
|
|
||||||
# Set chmod on top level path
|
|
||||||
try:
|
|
||||||
os.chmod(path, dir_mode)
|
|
||||||
except:
|
|
||||||
print('Could not chmod :' + path + ' to ' + str(dir_mode))
|
|
||||||
for root, dirs, files in os.walk(path):
|
|
||||||
for d in dirs:
|
|
||||||
try:
|
|
||||||
os.chmod(os.path.join(root, d), dir_mode)
|
|
||||||
except:
|
|
||||||
print('Could not chmod :' + os.path.join(root, d) + ' to ' + str(dir_mode))
|
|
||||||
pass
|
|
||||||
for f in files:
|
|
||||||
try:
|
|
||||||
os.chmod(os.path.join(root, f), file_mode)
|
|
||||||
except:
|
|
||||||
print('Could not chmod :' + path + ' to ' + str(file_mode))
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
# Left intentionally here for reference.
|
|
||||||
# Set recursive chown for a path
|
|
||||||
# recursive_chown(my_path, 'root', 'root')
|
|
||||||
# for changing group recursively without affecting user
|
|
||||||
# recursive_chown('/usr/local/lscp/cyberpanel/rainloop/data', -1, 'lscpd')
|
|
||||||
|
|
||||||
# explicitly set permissions for directories/folders to 0755 and files to 0644
|
|
||||||
# recursive_permissions(my_path, 755, 644)
|
|
||||||
|
|
||||||
# Fix permissions and use default values
|
|
||||||
# recursive_permissions(my_path)
|
|
||||||
# =========================================================
|
|
||||||
# Below is a helper class for getting and working with permissions
|
|
||||||
# Original credits to : https://github.com/keysemble/perfm
|
|
||||||
|
|
||||||
def perm_octal_digit(rwx):
|
|
||||||
digit = 0
|
|
||||||
if rwx[0] == 'r':
|
|
||||||
digit += 4
|
|
||||||
if rwx[1] == 'w':
|
|
||||||
digit += 2
|
|
||||||
if rwx[2] == 'x':
|
|
||||||
digit += 1
|
|
||||||
return digit
|
|
||||||
|
|
||||||
|
|
||||||
class FilePerm:
|
|
||||||
def __init__(self, filepath):
|
|
||||||
filemode = stat.filemode(os.stat(filepath).st_mode)
|
|
||||||
permissions = [filemode[-9:][i:i + 3] for i in range(0, len(filemode[-9:]), 3)]
|
|
||||||
self.filepath = filepath
|
|
||||||
self.access_dict = dict(zip(['user', 'group', 'other'], [list(perm) for perm in permissions]))
|
|
||||||
|
|
||||||
def mode(self):
|
|
||||||
mode = 0
|
|
||||||
for shift, digit in enumerate(self.octal()[::-1]):
|
|
||||||
mode += digit << (shift * 3)
|
|
||||||
return mode
|
|
||||||
|
|
||||||
def digits(self):
|
|
||||||
"""Get the octal chmod equivalent value 755 in single string"""
|
|
||||||
return "".join(map(str, self.octal()))
|
|
||||||
|
|
||||||
def octal(self):
|
|
||||||
"""Get the octal value in a list [7, 5, 5]"""
|
|
||||||
return [perm_octal_digit(p) for p in self.access_dict.values()]
|
|
||||||
|
|
||||||
def access_bits(self, access):
|
|
||||||
if access in self.access_dict.keys():
|
|
||||||
r, w, x = self.access_dict[access]
|
|
||||||
return [r == 'r', w == 'w', x == 'x']
|
|
||||||
|
|
||||||
def update_bitwise(self, settings):
|
|
||||||
def perm_list(read=False, write=False, execute=False):
|
|
||||||
pl = ['-', '-', '-']
|
|
||||||
if read:
|
|
||||||
pl[0] = 'r'
|
|
||||||
if write:
|
|
||||||
pl[1] = 'w'
|
|
||||||
if execute:
|
|
||||||
pl[2] = 'x'
|
|
||||||
return pl
|
|
||||||
|
|
||||||
self.access_dict = dict(
|
|
||||||
[(access, perm_list(read=r, write=w, execute=x)) for access, [r, w, x] in settings.items()])
|
|
||||||
os.chmod(self.filepath, self.mode())
|
|
||||||
|
|
||||||
# project_directory = os.path.abspath(os.path.dirname(sys.argv[0]))
|
|
||||||
# home_directory = os.path.expanduser('~')
|
|
||||||
# print(f'Path: {home_directory} Mode: {FilePerm(home_directory).mode()} Octal: {FilePerm(home_directory).octal()} '
|
|
||||||
# f'Digits: {FilePerm(home_directory).digits()}')
|
|
||||||
# Example: Output
|
|
||||||
# Path: /home/cooluser Mode: 493 Octal: [7, 5, 5] Digits: 755
|
|
||||||
@@ -2969,7 +2969,7 @@ echo $oConfig->Save() ? 'Done' : 'Error';
|
|||||||
writeToFile.write(content)
|
writeToFile.write(content)
|
||||||
writeToFile.close()
|
writeToFile.close()
|
||||||
|
|
||||||
command = '/usr/local/lsws/lsphp72/bin/php /usr/local/CyberCP/public/snappymail.php'
|
command = '/usr/local/lsws/lsphp83/bin/php /usr/local/CyberCP/public/snappymail.php'
|
||||||
subprocess.call(shlex.split(command))
|
subprocess.call(shlex.split(command))
|
||||||
|
|
||||||
command = "chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/snappymail/data"
|
command = "chown -R lscpd:lscpd /usr/local/lscp/cyberpanel/snappymail/data"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -44,6 +44,62 @@ FetchCloudLinuxAlmaVersionVersion = install_utils.FetchCloudLinuxAlmaVersionVers
|
|||||||
class InstallCyberPanel:
|
class InstallCyberPanel:
|
||||||
mysql_Root_password = ""
|
mysql_Root_password = ""
|
||||||
mysqlPassword = ""
|
mysqlPassword = ""
|
||||||
|
|
||||||
|
def is_almalinux9(self):
|
||||||
|
"""Check if running on AlmaLinux 9"""
|
||||||
|
if os.path.exists('/etc/almalinux-release'):
|
||||||
|
try:
|
||||||
|
with open('/etc/almalinux-release', 'r') as f:
|
||||||
|
content = f.read()
|
||||||
|
return 'release 9' in content
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
return False
|
||||||
|
|
||||||
|
def fix_almalinux9_mariadb(self):
|
||||||
|
"""Fix AlmaLinux 9 MariaDB installation issues"""
|
||||||
|
if not self.is_almalinux9():
|
||||||
|
return
|
||||||
|
|
||||||
|
self.stdOut("Applying AlmaLinux 9 MariaDB fixes...", 1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Disable problematic MariaDB MaxScale repository
|
||||||
|
self.stdOut("Disabling problematic MariaDB MaxScale repository...", 1)
|
||||||
|
command = "dnf config-manager --disable mariadb-maxscale 2>/dev/null || true"
|
||||||
|
install_utils.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
|
||||||
|
|
||||||
|
# Remove problematic repository files
|
||||||
|
self.stdOut("Removing problematic repository files...", 1)
|
||||||
|
problematic_repos = [
|
||||||
|
'/etc/yum.repos.d/mariadb-maxscale.repo',
|
||||||
|
'/etc/yum.repos.d/mariadb-maxscale.repo.rpmnew'
|
||||||
|
]
|
||||||
|
for repo_file in problematic_repos:
|
||||||
|
if os.path.exists(repo_file):
|
||||||
|
os.remove(repo_file)
|
||||||
|
self.stdOut(f"Removed {repo_file}", 1)
|
||||||
|
|
||||||
|
# Clean DNF cache
|
||||||
|
self.stdOut("Cleaning DNF cache...", 1)
|
||||||
|
command = "dnf clean all"
|
||||||
|
install_utils.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
|
||||||
|
|
||||||
|
# Install MariaDB from official repository
|
||||||
|
self.stdOut("Setting up official MariaDB repository...", 1)
|
||||||
|
command = "curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | bash -s -- --mariadb-server-version='10.11'"
|
||||||
|
install_utils.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
|
||||||
|
|
||||||
|
# Install MariaDB packages
|
||||||
|
self.stdOut("Installing MariaDB packages...", 1)
|
||||||
|
mariadb_packages = "MariaDB-server MariaDB-client MariaDB-backup MariaDB-devel"
|
||||||
|
command = f"dnf install -y {mariadb_packages}"
|
||||||
|
install_utils.call(command, self.distro, command, command, 1, 0, os.EX_OSERR)
|
||||||
|
|
||||||
|
self.stdOut("AlmaLinux 9 MariaDB fixes completed", 1)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.stdOut(f"Error applying AlmaLinux 9 MariaDB fixes: {str(e)}", 0)
|
||||||
CloudLinux8 = 0
|
CloudLinux8 = 0
|
||||||
|
|
||||||
def install_package(self, package_name, options=""):
|
def install_package(self, package_name, options=""):
|
||||||
@@ -335,7 +391,7 @@ class InstallCyberPanel:
|
|||||||
return self.reStartLiteSpeed()
|
return self.reStartLiteSpeed()
|
||||||
|
|
||||||
def installAllPHPVersions(self):
|
def installAllPHPVersions(self):
|
||||||
php_versions = ['71', '72', '73', '74', '80', '81', '82', '83']
|
php_versions = ['71', '72', '73', '74', '80', '81', '82', '83', '84', '85']
|
||||||
|
|
||||||
if self.distro == ubuntu:
|
if self.distro == ubuntu:
|
||||||
# Install base PHP 7.x packages
|
# Install base PHP 7.x packages
|
||||||
@@ -563,6 +619,12 @@ gpgcheck=1
|
|||||||
|
|
||||||
if self.remotemysql == 'OFF':
|
if self.remotemysql == 'OFF':
|
||||||
############## Start mariadb ######################
|
############## Start mariadb ######################
|
||||||
|
|
||||||
|
# Check if AlmaLinux 9 and apply fixes
|
||||||
|
if self.is_almalinux9():
|
||||||
|
self.stdOut("AlmaLinux 9 detected - applying MariaDB fixes", 1)
|
||||||
|
self.fix_almalinux9_mariadb()
|
||||||
|
|
||||||
self.manage_service('mariadb', 'start')
|
self.manage_service('mariadb', 'start')
|
||||||
|
|
||||||
############## Enable mariadb at system startup ######################
|
############## Enable mariadb at system startup ######################
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,121 +0,0 @@
|
|||||||
{% extends "baseTemplate/index.html" %}
|
|
||||||
{% load i18n %}
|
|
||||||
{% block title %}{% trans "Mail Functions - CyberPanel" %}{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
{% load static %}
|
|
||||||
{% get_current_language as LANGUAGE_CODE %}
|
|
||||||
<!-- Current language: {{ LANGUAGE_CODE }} -->
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<div id="page-title">
|
|
||||||
<h2>{% trans "Mail Functions" %}</h2>
|
|
||||||
<p>{% trans "Manage email accounts on this page." %}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="panel col-md-12">
|
|
||||||
<div class="panel-body">
|
|
||||||
<h3 class="content-box-header">
|
|
||||||
{% trans "Available Functions" %}
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<div class="example-box-wrapper">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-3 btn-min-width">
|
|
||||||
<a href="{% url 'createEmailAccount' %}" title="{% trans 'Create Email' %}"
|
|
||||||
class="tile-box tile-box-shortcut btn-primary">
|
|
||||||
<div class="tile-header">
|
|
||||||
{% trans "Create Email" %}
|
|
||||||
</div>
|
|
||||||
<div class="tile-content-wrapper">
|
|
||||||
<i class="fa fa-plus-square"></i>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-3 btn-min-width">
|
|
||||||
<a href="{% url 'listEmails' %}" title="{% trans 'List Emails' %}"
|
|
||||||
class="tile-box tile-box-shortcut btn-primary">
|
|
||||||
<div class="tile-header">
|
|
||||||
{% trans "List Emails" %}
|
|
||||||
</div>
|
|
||||||
<div class="tile-content-wrapper">
|
|
||||||
<i class="fa fa-plus-square"></i>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="col-md-3 btn-min-width">
|
|
||||||
<a href="{% url 'deleteEmailAccount' %}" title="{% trans 'Delete Email' %}"
|
|
||||||
class="tile-box tile-box-shortcut btn-primary">
|
|
||||||
<div class="tile-header">
|
|
||||||
{% trans "Delete Email" %}
|
|
||||||
</div>
|
|
||||||
<div class="tile-content-wrapper">
|
|
||||||
<i class="fa fa-trash"></i>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-3 btn-min-width">
|
|
||||||
<a href="{% url 'emailForwarding' %}" title="{% trans 'Email Forwarding' %}"
|
|
||||||
class="tile-box tile-box-shortcut btn-primary">
|
|
||||||
<div class="tile-header">
|
|
||||||
{% trans "Email Forwarding" %}
|
|
||||||
</div>
|
|
||||||
<div class="tile-content-wrapper">
|
|
||||||
<i class="fa fa-plus-square"></i>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="col-md-3 btn-min-width">
|
|
||||||
<a href="{% url 'changeEmailAccountPassword' %}" title="{% trans 'Change Password' %}"
|
|
||||||
class="tile-box tile-box-shortcut btn-primary">
|
|
||||||
<div class="tile-header">
|
|
||||||
{% trans "Change Password" %}
|
|
||||||
</div>
|
|
||||||
<div class="tile-content-wrapper">
|
|
||||||
<i class="fa fa-key"></i>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-3 btn-min-width">
|
|
||||||
<a href="{% url 'dkimManager' %}" title="{% trans 'DKIM Manager' %}"
|
|
||||||
class="tile-box tile-box-shortcut btn-primary">
|
|
||||||
<div class="tile-header">
|
|
||||||
{% trans "DKIM Manager" %}
|
|
||||||
</div>
|
|
||||||
<div class="tile-content-wrapper">
|
|
||||||
<i class="fa fa-key"></i>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-3 btn-min-width">
|
|
||||||
<a href="/snappymail/index.php" title="{% trans 'Access Webmail' %}"
|
|
||||||
class="tile-box tile-box-shortcut btn-primary">
|
|
||||||
<div class="tile-header">
|
|
||||||
{% trans "Access Webmail" %}
|
|
||||||
</div>
|
|
||||||
<div class="tile-content-wrapper">
|
|
||||||
<i class="fa fa-key"></i>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1372,7 +1372,7 @@ echo $oConfig->Save() ? 'Done' : 'Error';
|
|||||||
command = 'chmod 640 /usr/local/lscp/cyberpanel/logs/access.log'
|
command = 'chmod 640 /usr/local/lscp/cyberpanel/logs/access.log'
|
||||||
ProcessUtilities.executioner(command, 'root', True)
|
ProcessUtilities.executioner(command, 'root', True)
|
||||||
|
|
||||||
command = '/usr/local/lsws/lsphp72/bin/php /usr/local/CyberCP/public/snappymail.php'
|
command = '/usr/local/lsws/lsphp83/bin/php /usr/local/CyberCP/public/snappymail.php'
|
||||||
ProcessUtilities.executioner(command, 'root', True)
|
ProcessUtilities.executioner(command, 'root', True)
|
||||||
|
|
||||||
command = 'chmod 600 /usr/local/CyberCP/public/snappymail.php'
|
command = 'chmod 600 /usr/local/CyberCP/public/snappymail.php'
|
||||||
|
|||||||
@@ -1,190 +0,0 @@
|
|||||||
import os
|
|
||||||
import shutil
|
|
||||||
import pathlib
|
|
||||||
import stat
|
|
||||||
|
|
||||||
|
|
||||||
def mkdir_p(path, exist_ok=True):
|
|
||||||
"""
|
|
||||||
Creates the directory and paths leading up to it like unix mkdir -p .
|
|
||||||
Defaults to exist_ok so if it exists were not throwing fatal errors
|
|
||||||
https://docs.python.org/3.7/library/os.html#os.makedirs
|
|
||||||
"""
|
|
||||||
if not os.path.exists(path):
|
|
||||||
print('creating directory: ' + path)
|
|
||||||
os.makedirs(path, exist_ok)
|
|
||||||
|
|
||||||
|
|
||||||
def chmod_digit(file_path, perms):
|
|
||||||
"""
|
|
||||||
Helper function to chmod like you would in unix without having to preface 0o or converting to octal yourself.
|
|
||||||
Credits: https://stackoverflow.com/a/60052847/1621381
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
os.chmod(file_path, int(str(perms), base=8))
|
|
||||||
except:
|
|
||||||
print(f'Could not chmod : {file_path} to {perms}')
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def touch(filepath: str, exist_ok=True):
|
|
||||||
"""
|
|
||||||
Touches a file like unix `touch somefile` would.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
pathlib.Path(filepath).touch(exist_ok)
|
|
||||||
except FileExistsError:
|
|
||||||
print('Could touch : ' + filepath)
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def symlink(src, dst):
|
|
||||||
"""
|
|
||||||
Symlink a path to another if the src exists.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
if os.access(src, os.R_OK):
|
|
||||||
os.symlink(src, dst)
|
|
||||||
except:
|
|
||||||
print(f'Could not symlink Source: {src} > Destination: {dst}')
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def chown(path, user, group=-1):
|
|
||||||
"""
|
|
||||||
Chown file/path to user/group provided. Passing -1 to user or group will leave it unchanged.
|
|
||||||
Useful if just changing user or group vs both.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
shutil.chown(path, user, group)
|
|
||||||
except PermissionError:
|
|
||||||
print(f'Could not change permissions for: {path} to {user}:{group}')
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def recursive_chown(path, owner, group=-1):
|
|
||||||
"""
|
|
||||||
Recursively chown a path and contents to owner.
|
|
||||||
https://docs.python.org/3/library/shutil.html
|
|
||||||
"""
|
|
||||||
for dirpath, dirnames, filenames in os.walk(path):
|
|
||||||
try:
|
|
||||||
shutil.chown(dirpath, owner, group)
|
|
||||||
except PermissionError:
|
|
||||||
print('Could not change permissions for: ' + dirpath + ' to: ' + owner)
|
|
||||||
pass
|
|
||||||
for filename in filenames:
|
|
||||||
try:
|
|
||||||
shutil.chown(os.path.join(dirpath, filename), owner, group)
|
|
||||||
except PermissionError:
|
|
||||||
print('Could not change permissions for: ' + os.path.join(dirpath, filename) + ' to: ' + owner)
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def recursive_permissions(path, dir_mode=755, file_mode=644, topdir=True):
|
|
||||||
"""
|
|
||||||
Recursively chmod a path and contents to mode.
|
|
||||||
Defaults to chmod top level directory but can be optionally
|
|
||||||
toggled off when you want to chmod only contents of like a user's homedir vs homedir itself
|
|
||||||
https://docs.python.org/3.6/library/os.html#os.walk
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Here we are converting the integers to string and then to octal.
|
|
||||||
# so this function doesn't need to be called with 0o prefixed for the file and dir mode
|
|
||||||
dir_mode = int(str(dir_mode), base=8)
|
|
||||||
file_mode = int(str(file_mode), base=8)
|
|
||||||
|
|
||||||
if topdir:
|
|
||||||
# Set chmod on top level path
|
|
||||||
try:
|
|
||||||
os.chmod(path, dir_mode)
|
|
||||||
except:
|
|
||||||
print('Could not chmod :' + path + ' to ' + str(dir_mode))
|
|
||||||
for root, dirs, files in os.walk(path):
|
|
||||||
for d in dirs:
|
|
||||||
try:
|
|
||||||
os.chmod(os.path.join(root, d), dir_mode)
|
|
||||||
except:
|
|
||||||
print('Could not chmod :' + os.path.join(root, d) + ' to ' + str(dir_mode))
|
|
||||||
pass
|
|
||||||
for f in files:
|
|
||||||
try:
|
|
||||||
os.chmod(os.path.join(root, f), file_mode)
|
|
||||||
except:
|
|
||||||
print('Could not chmod :' + path + ' to ' + str(file_mode))
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
# Left intentionally here for reference.
|
|
||||||
# Set recursive chown for a path
|
|
||||||
# recursive_chown(my_path, 'root', 'root')
|
|
||||||
# for changing group recursively without affecting user
|
|
||||||
# recursive_chown('/usr/local/lscp/cyberpanel/rainloop/data', -1, 'lscpd')
|
|
||||||
|
|
||||||
# explicitly set permissions for directories/folders to 0755 and files to 0644
|
|
||||||
# recursive_permissions(my_path, 755, 644)
|
|
||||||
|
|
||||||
# Fix permissions and use default values
|
|
||||||
# recursive_permissions(my_path)
|
|
||||||
# =========================================================
|
|
||||||
# Below is a helper class for getting and working with permissions
|
|
||||||
# Original credits to : https://github.com/keysemble/perfm
|
|
||||||
|
|
||||||
def perm_octal_digit(rwx):
|
|
||||||
digit = 0
|
|
||||||
if rwx[0] == 'r':
|
|
||||||
digit += 4
|
|
||||||
if rwx[1] == 'w':
|
|
||||||
digit += 2
|
|
||||||
if rwx[2] == 'x':
|
|
||||||
digit += 1
|
|
||||||
return digit
|
|
||||||
|
|
||||||
|
|
||||||
class FilePerm:
|
|
||||||
def __init__(self, filepath):
|
|
||||||
filemode = stat.filemode(os.stat(filepath).st_mode)
|
|
||||||
permissions = [filemode[-9:][i:i + 3] for i in range(0, len(filemode[-9:]), 3)]
|
|
||||||
self.filepath = filepath
|
|
||||||
self.access_dict = dict(zip(['user', 'group', 'other'], [list(perm) for perm in permissions]))
|
|
||||||
|
|
||||||
def mode(self):
|
|
||||||
mode = 0
|
|
||||||
for shift, digit in enumerate(self.octal()[::-1]):
|
|
||||||
mode += digit << (shift * 3)
|
|
||||||
return mode
|
|
||||||
|
|
||||||
def digits(self):
|
|
||||||
"""Get the octal chmod equivalent value 755 in single string"""
|
|
||||||
return "".join(map(str, self.octal()))
|
|
||||||
|
|
||||||
def octal(self):
|
|
||||||
"""Get the octal value in a list [7, 5, 5]"""
|
|
||||||
return [perm_octal_digit(p) for p in self.access_dict.values()]
|
|
||||||
|
|
||||||
def access_bits(self, access):
|
|
||||||
if access in self.access_dict.keys():
|
|
||||||
r, w, x = self.access_dict[access]
|
|
||||||
return [r == 'r', w == 'w', x == 'x']
|
|
||||||
|
|
||||||
def update_bitwise(self, settings):
|
|
||||||
def perm_list(read=False, write=False, execute=False):
|
|
||||||
pl = ['-', '-', '-']
|
|
||||||
if read:
|
|
||||||
pl[0] = 'r'
|
|
||||||
if write:
|
|
||||||
pl[1] = 'w'
|
|
||||||
if execute:
|
|
||||||
pl[2] = 'x'
|
|
||||||
return pl
|
|
||||||
|
|
||||||
self.access_dict = dict(
|
|
||||||
[(access, perm_list(read=r, write=w, execute=x)) for access, [r, w, x] in settings.items()])
|
|
||||||
os.chmod(self.filepath, self.mode())
|
|
||||||
|
|
||||||
# project_directory = os.path.abspath(os.path.dirname(sys.argv[0]))
|
|
||||||
# home_directory = os.path.expanduser('~')
|
|
||||||
# print(f'Path: {home_directory} Mode: {FilePerm(home_directory).mode()} Octal: {FilePerm(home_directory).octal()} '
|
|
||||||
# f'Digits: {FilePerm(home_directory).digits()}')
|
|
||||||
# Example: Output
|
|
||||||
# Path: /home/cooluser Mode: 493 Octal: [7, 5, 5] Digits: 755
|
|
||||||
@@ -861,7 +861,7 @@ $cfg['Servers'][$i]['LogoutURL'] = 'phpmyadminsignin.php?logout';
|
|||||||
command = f'wget -q -O /usr/local/CyberCP/snappymail_cyberpanel.php https://raw.githubusercontent.com/the-djmaze/snappymail/master/integrations/cyberpanel/install.php'
|
command = f'wget -q -O /usr/local/CyberCP/snappymail_cyberpanel.php https://raw.githubusercontent.com/the-djmaze/snappymail/master/integrations/cyberpanel/install.php'
|
||||||
Upgrade.executioner_silent(command, 'verify certificate', 0)
|
Upgrade.executioner_silent(command, 'verify certificate', 0)
|
||||||
|
|
||||||
command = f'/usr/local/lsws/lsphp80/bin/php /usr/local/CyberCP/snappymail_cyberpanel.php'
|
command = f'/usr/local/lsws/lsphp83/bin/php /usr/local/CyberCP/snappymail_cyberpanel.php'
|
||||||
Upgrade.executioner_silent(command, 'verify certificate', 0)
|
Upgrade.executioner_silent(command, 'verify certificate', 0)
|
||||||
|
|
||||||
# labsPath = '/usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/configs/application.ini'
|
# labsPath = '/usr/local/lscp/cyberpanel/rainloop/data/_data_/_default_/configs/application.ini'
|
||||||
@@ -3121,7 +3121,7 @@ echo $oConfig->Save() ? 'Done' : 'Error';
|
|||||||
command = 'chmod 640 /usr/local/lscp/cyberpanel/logs/access.log'
|
command = 'chmod 640 /usr/local/lscp/cyberpanel/logs/access.log'
|
||||||
Upgrade.executioner(command, 0)
|
Upgrade.executioner(command, 0)
|
||||||
|
|
||||||
command = '/usr/local/lsws/lsphp72/bin/php /usr/local/CyberCP/public/snappymail.php'
|
command = '/usr/local/lsws/lsphp83/bin/php /usr/local/CyberCP/public/snappymail.php'
|
||||||
Upgrade.executioner_silent(command, 'Configure SnappyMail')
|
Upgrade.executioner_silent(command, 'Configure SnappyMail')
|
||||||
|
|
||||||
command = 'chmod 600 /usr/local/CyberCP/public/snappymail.php'
|
command = 'chmod 600 /usr/local/CyberCP/public/snappymail.php'
|
||||||
@@ -3182,44 +3182,221 @@ echo $oConfig->Save() ? 'Done' : 'Error';
|
|||||||
command = '/root/.acme.sh/acme.sh --set-default-ca --server letsencrypt'
|
command = '/root/.acme.sh/acme.sh --set-default-ca --server letsencrypt'
|
||||||
Upgrade.executioner(command, command, 0)
|
Upgrade.executioner(command, command, 0)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def check_package_availability(package_name):
|
||||||
|
"""Check if a package is available in the repositories"""
|
||||||
|
try:
|
||||||
|
# Try to search for the package without installing
|
||||||
|
if os.path.exists('/etc/yum.repos.d/') or os.path.exists('/etc/dnf/dnf.conf'):
|
||||||
|
# RHEL-based systems
|
||||||
|
command = f"dnf search --quiet {package_name} 2>/dev/null | grep -q '^Last metadata expiration' || yum search --quiet {package_name} 2>/dev/null | head -1"
|
||||||
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
||||||
|
return result.returncode == 0
|
||||||
|
else:
|
||||||
|
# Ubuntu/Debian systems
|
||||||
|
command = f"apt-cache search {package_name} 2>/dev/null | head -1"
|
||||||
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
||||||
|
return result.returncode == 0 and result.stdout.strip() != ""
|
||||||
|
except Exception as e:
|
||||||
|
Upgrade.stdOut(f"Error checking package availability for {package_name}: {str(e)}", 0)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_almalinux9():
|
||||||
|
"""Check if running on AlmaLinux 9"""
|
||||||
|
if os.path.exists('/etc/almalinux-release'):
|
||||||
|
try:
|
||||||
|
with open('/etc/almalinux-release', 'r') as f:
|
||||||
|
content = f.read()
|
||||||
|
return 'release 9' in content
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def fix_almalinux9_mariadb():
|
||||||
|
"""Fix AlmaLinux 9 MariaDB installation issues"""
|
||||||
|
if not Upgrade.is_almalinux9():
|
||||||
|
return
|
||||||
|
|
||||||
|
Upgrade.stdOut("Applying AlmaLinux 9 MariaDB fixes...", 1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Disable problematic MariaDB MaxScale repository
|
||||||
|
Upgrade.stdOut("Disabling problematic MariaDB MaxScale repository...", 1)
|
||||||
|
command = "dnf config-manager --disable mariadb-maxscale 2>/dev/null || true"
|
||||||
|
subprocess.run(command, shell=True, capture_output=True)
|
||||||
|
|
||||||
|
# Remove problematic repository files
|
||||||
|
Upgrade.stdOut("Removing problematic repository files...", 1)
|
||||||
|
problematic_repos = [
|
||||||
|
'/etc/yum.repos.d/mariadb-maxscale.repo',
|
||||||
|
'/etc/yum.repos.d/mariadb-maxscale.repo.rpmnew'
|
||||||
|
]
|
||||||
|
for repo_file in problematic_repos:
|
||||||
|
if os.path.exists(repo_file):
|
||||||
|
os.remove(repo_file)
|
||||||
|
Upgrade.stdOut(f"Removed {repo_file}", 1)
|
||||||
|
|
||||||
|
# Clean DNF cache
|
||||||
|
Upgrade.stdOut("Cleaning DNF cache...", 1)
|
||||||
|
command = "dnf clean all"
|
||||||
|
subprocess.run(command, shell=True, capture_output=True)
|
||||||
|
|
||||||
|
# Install MariaDB from official repository
|
||||||
|
Upgrade.stdOut("Setting up official MariaDB repository...", 1)
|
||||||
|
command = "curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | bash -s -- --mariadb-server-version='10.11'"
|
||||||
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
||||||
|
if result.returncode != 0:
|
||||||
|
Upgrade.stdOut(f"Warning: MariaDB repo setup failed: {result.stderr}", 0)
|
||||||
|
|
||||||
|
# Install MariaDB packages
|
||||||
|
Upgrade.stdOut("Installing MariaDB packages...", 1)
|
||||||
|
mariadb_packages = "MariaDB-server MariaDB-client MariaDB-backup MariaDB-devel"
|
||||||
|
command = f"dnf install -y {mariadb_packages}"
|
||||||
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
||||||
|
if result.returncode != 0:
|
||||||
|
Upgrade.stdOut(f"Warning: MariaDB installation issues: {result.stderr}", 0)
|
||||||
|
|
||||||
|
# Start and enable MariaDB service
|
||||||
|
Upgrade.stdOut("Starting MariaDB service...", 1)
|
||||||
|
services = ['mariadb', 'mysql', 'mysqld']
|
||||||
|
for service in services:
|
||||||
|
try:
|
||||||
|
command = f"systemctl start {service}"
|
||||||
|
result = subprocess.run(command, shell=True, capture_output=True)
|
||||||
|
if result.returncode == 0:
|
||||||
|
command = f"systemctl enable {service}"
|
||||||
|
subprocess.run(command, shell=True, capture_output=True)
|
||||||
|
Upgrade.stdOut(f"MariaDB service started as {service}", 1)
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
Upgrade.stdOut("AlmaLinux 9 MariaDB fixes completed", 1)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
Upgrade.stdOut(f"Error applying AlmaLinux 9 MariaDB fixes: {str(e)}", 0)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_available_php_versions():
|
||||||
|
"""Get list of available PHP versions based on OS"""
|
||||||
|
# Check for AlmaLinux 9+ first
|
||||||
|
if os.path.exists('/etc/almalinux-release'):
|
||||||
|
try:
|
||||||
|
with open('/etc/almalinux-release', 'r') as f:
|
||||||
|
content = f.read()
|
||||||
|
if 'release 9' in content or 'release 10' in content:
|
||||||
|
Upgrade.stdOut("AlmaLinux 9+ detected - checking available PHP versions", 1)
|
||||||
|
# AlmaLinux 9+ doesn't have PHP 7.1, 7.2, 7.3
|
||||||
|
php_versions = ['74', '80', '81', '82', '83', '84', '85']
|
||||||
|
else:
|
||||||
|
php_versions = ['71', '72', '73', '74', '80', '81', '82', '83', '84', '85']
|
||||||
|
except:
|
||||||
|
php_versions = ['71', '72', '73', '74', '80', '81', '82', '83', '84', '85']
|
||||||
|
else:
|
||||||
|
# Check other OS versions
|
||||||
|
os_info = Upgrade.findOperatingSytem()
|
||||||
|
if os_info in [Ubuntu24, CENTOS8]:
|
||||||
|
php_versions = ['74', '80', '81', '82', '83', '84', '85']
|
||||||
|
else:
|
||||||
|
php_versions = ['71', '72', '73', '74', '80', '81', '82', '83', '84', '85']
|
||||||
|
|
||||||
|
# Check availability of each version
|
||||||
|
available_versions = []
|
||||||
|
for version in php_versions:
|
||||||
|
if Upgrade.check_package_availability(f'lsphp{version}'):
|
||||||
|
available_versions.append(version)
|
||||||
|
else:
|
||||||
|
Upgrade.stdOut(f"PHP {version} not available on this OS", 0)
|
||||||
|
|
||||||
|
return available_versions
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def fixLiteSpeedConfig():
|
||||||
|
"""Fix LiteSpeed configuration issues by creating missing files"""
|
||||||
|
try:
|
||||||
|
Upgrade.stdOut("Checking and fixing LiteSpeed configuration...", 1)
|
||||||
|
|
||||||
|
# Check if LiteSpeed is installed
|
||||||
|
if not os.path.exists('/usr/local/lsws'):
|
||||||
|
Upgrade.stdOut("LiteSpeed not found at /usr/local/lsws", 0)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Create missing configuration files
|
||||||
|
config_files = [
|
||||||
|
"/usr/local/lsws/conf/httpd_config.xml",
|
||||||
|
"/usr/local/lsws/conf/httpd.conf",
|
||||||
|
"/usr/local/lsws/conf/modsec.conf"
|
||||||
|
]
|
||||||
|
|
||||||
|
for config_file in config_files:
|
||||||
|
if not os.path.exists(config_file):
|
||||||
|
Upgrade.stdOut(f"Missing LiteSpeed config: {config_file}", 0)
|
||||||
|
|
||||||
|
# Create directory if it doesn't exist
|
||||||
|
os.makedirs(os.path.dirname(config_file), exist_ok=True)
|
||||||
|
|
||||||
|
# Create minimal config file
|
||||||
|
if config_file.endswith('httpd_config.xml'):
|
||||||
|
with open(config_file, 'w') as f:
|
||||||
|
f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
|
||||||
|
f.write('<httpServerConfig>\n')
|
||||||
|
f.write(' <!-- Minimal LiteSpeed configuration -->\n')
|
||||||
|
f.write(' <listener>\n')
|
||||||
|
f.write(' <name>Default</name>\n')
|
||||||
|
f.write(' <address>*:8088</address>\n')
|
||||||
|
f.write(' </listener>\n')
|
||||||
|
f.write('</httpServerConfig>\n')
|
||||||
|
elif config_file.endswith('httpd.conf'):
|
||||||
|
with open(config_file, 'w') as f:
|
||||||
|
f.write('# Minimal LiteSpeed HTTP configuration\n')
|
||||||
|
f.write('# This file will be updated by CyberPanel\n')
|
||||||
|
elif config_file.endswith('modsec.conf'):
|
||||||
|
with open(config_file, 'w') as f:
|
||||||
|
f.write('# ModSecurity configuration\n')
|
||||||
|
f.write('# This file will be updated by CyberPanel\n')
|
||||||
|
|
||||||
|
Upgrade.stdOut(f"Created minimal config: {config_file}", 1)
|
||||||
|
else:
|
||||||
|
Upgrade.stdOut(f"LiteSpeed config exists: {config_file}", 1)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
Upgrade.stdOut(f"Error fixing LiteSpeed config: {str(e)}", 0)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def installPHP73():
|
def installPHP73():
|
||||||
try:
|
try:
|
||||||
if Upgrade.installedOutput.find('lsphp73') == -1:
|
Upgrade.stdOut("Installing PHP versions based on OS compatibility...", 1)
|
||||||
command = 'yum install -y lsphp73 lsphp73-json lsphp73-xmlrpc lsphp73-xml lsphp73-tidy lsphp73-soap lsphp73-snmp ' \
|
|
||||||
'lsphp73-recode lsphp73-pspell lsphp73-process lsphp73-pgsql lsphp73-pear lsphp73-pdo lsphp73-opcache ' \
|
# Get available PHP versions
|
||||||
'lsphp73-odbc lsphp73-mysqlnd lsphp73-mcrypt lsphp73-mbstring lsphp73-ldap lsphp73-intl lsphp73-imap ' \
|
available_versions = Upgrade.get_available_php_versions()
|
||||||
'lsphp73-gmp lsphp73-gd lsphp73-enchant lsphp73-dba lsphp73-common lsphp73-bcmath'
|
|
||||||
Upgrade.executioner(command, 'Install PHP 73, 0')
|
if not available_versions:
|
||||||
|
Upgrade.stdOut("No PHP versions available for installation", 0)
|
||||||
if Upgrade.installedOutput.find('lsphp74') == -1:
|
return
|
||||||
command = 'yum install -y lsphp74 lsphp74-json lsphp74-xmlrpc lsphp74-xml lsphp74-tidy lsphp74-soap lsphp74-snmp ' \
|
|
||||||
'lsphp74-recode lsphp74-pspell lsphp74-process lsphp74-pgsql lsphp74-pear lsphp74-pdo lsphp74-opcache ' \
|
Upgrade.stdOut(f"Installing available PHP versions: {', '.join(available_versions)}", 1)
|
||||||
'lsphp74-odbc lsphp74-mysqlnd lsphp74-mcrypt lsphp74-mbstring lsphp74-ldap lsphp74-intl lsphp74-imap ' \
|
|
||||||
'lsphp74-gmp lsphp74-gd lsphp74-enchant lsphp74-dba lsphp74-common lsphp74-bcmath'
|
for version in available_versions:
|
||||||
|
try:
|
||||||
Upgrade.executioner(command, 'Install PHP 74, 0')
|
if version in ['71', '72', '73', '74']:
|
||||||
|
# PHP 7.x versions with specific extensions
|
||||||
if Upgrade.installedOutput.find('lsphp80') == -1:
|
if Upgrade.installedOutput.find(f'lsphp{version}') == -1:
|
||||||
command = 'yum install lsphp80* -y'
|
extensions = ['json', 'xmlrpc', 'xml', 'tidy', 'soap', 'snmp', 'recode', 'pspell', 'process', 'pgsql', 'pear', 'pdo', 'opcache', 'odbc', 'mysqlnd', 'mcrypt', 'mbstring', 'ldap', 'intl', 'imap', 'gmp', 'gd', 'enchant', 'dba', 'common', 'bcmath']
|
||||||
subprocess.call(command, shell=True)
|
package_list = f"lsphp{version} " + " ".join([f"lsphp{version}-{ext}" for ext in extensions])
|
||||||
|
command = f"yum install -y {package_list}"
|
||||||
if Upgrade.installedOutput.find('lsphp81') == -1:
|
Upgrade.executioner(command, f'Install PHP {version}', 0)
|
||||||
command = 'yum install lsphp81* -y'
|
else:
|
||||||
subprocess.call(command, shell=True)
|
# PHP 8.x versions
|
||||||
|
if Upgrade.installedOutput.find(f'lsphp{version}') == -1:
|
||||||
if Upgrade.installedOutput.find('lsphp82') == -1:
|
command = f"yum install lsphp{version}* -y"
|
||||||
command = 'yum install lsphp82* -y'
|
|
||||||
subprocess.call(command, shell=True)
|
|
||||||
|
|
||||||
command = 'yum install lsphp83* -y'
|
|
||||||
subprocess.call(command, shell=True)
|
|
||||||
|
|
||||||
command = 'yum install lsphp84* -y'
|
|
||||||
subprocess.call(command, shell=True)
|
|
||||||
|
|
||||||
command = 'yum install lsphp85* -y'
|
|
||||||
subprocess.call(command, shell=True)
|
subprocess.call(command, shell=True)
|
||||||
|
Upgrade.stdOut(f"Installed PHP {version}", 1)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
Upgrade.stdOut(f"Error installing PHP {version}: {str(e)}", 0)
|
||||||
|
continue
|
||||||
|
|
||||||
except:
|
except:
|
||||||
command = 'DEBIAN_FRONTEND=noninteractive apt-get -y install ' \
|
command = 'DEBIAN_FRONTEND=noninteractive apt-get -y install ' \
|
||||||
@@ -3997,9 +4174,20 @@ pm.max_spare_servers = 3
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def setupPHPSymlink():
|
def setupPHPSymlink():
|
||||||
try:
|
try:
|
||||||
# Check if PHP 8.3 exists
|
# Try to find available PHP version (prioritize modern stable versions)
|
||||||
if not os.path.exists('/usr/local/lsws/lsphp83/bin/php'):
|
# Priority: 8.3 (recommended), 8.2, 8.4, 8.5, 8.1, 8.0, then older versions
|
||||||
Upgrade.stdOut("PHP 8.3 not found, installing it first...")
|
php_versions = ['83', '82', '84', '85', '81', '80', '74', '73', '72', '71']
|
||||||
|
selected_php = None
|
||||||
|
|
||||||
|
for version in php_versions:
|
||||||
|
if os.path.exists(f'/usr/local/lsws/lsphp{version}/bin/php'):
|
||||||
|
selected_php = version
|
||||||
|
Upgrade.stdOut(f"Found PHP {version}, using as default", 1)
|
||||||
|
break
|
||||||
|
|
||||||
|
if not selected_php:
|
||||||
|
# Try to install PHP 8.3 as fallback (modern stable version)
|
||||||
|
Upgrade.stdOut("No PHP found, installing PHP 8.3 as fallback...")
|
||||||
|
|
||||||
# Install PHP 8.3 based on OS
|
# Install PHP 8.3 based on OS
|
||||||
if os.path.exists(Upgrade.CentOSPath) or os.path.exists(Upgrade.openEulerPath):
|
if os.path.exists(Upgrade.CentOSPath) or os.path.exists(Upgrade.openEulerPath):
|
||||||
@@ -4013,16 +4201,17 @@ pm.max_spare_servers = 3
|
|||||||
if not os.path.exists('/usr/local/lsws/lsphp83/bin/php'):
|
if not os.path.exists('/usr/local/lsws/lsphp83/bin/php'):
|
||||||
Upgrade.stdOut('[ERROR] Failed to install PHP 8.3')
|
Upgrade.stdOut('[ERROR] Failed to install PHP 8.3')
|
||||||
return 0
|
return 0
|
||||||
|
selected_php = '83'
|
||||||
|
|
||||||
# Remove existing PHP symlink if it exists
|
# Remove existing PHP symlink if it exists
|
||||||
if os.path.exists('/usr/bin/php'):
|
if os.path.exists('/usr/bin/php'):
|
||||||
os.remove('/usr/bin/php')
|
os.remove('/usr/bin/php')
|
||||||
|
|
||||||
# Create symlink to PHP 8.3
|
# Create symlink to selected PHP version
|
||||||
command = 'ln -s /usr/local/lsws/lsphp83/bin/php /usr/bin/php'
|
command = f'ln -s /usr/local/lsws/lsphp{selected_php}/bin/php /usr/bin/php'
|
||||||
Upgrade.executioner(command, 'Setup PHP Symlink to 8.3', 0)
|
Upgrade.executioner(command, f'Setup PHP Symlink to {selected_php}', 0)
|
||||||
|
|
||||||
Upgrade.stdOut("PHP symlink updated to PHP 8.3 successfully.")
|
Upgrade.stdOut(f"PHP symlink updated to PHP {selected_php} successfully.")
|
||||||
|
|
||||||
except BaseException as msg:
|
except BaseException as msg:
|
||||||
Upgrade.stdOut('[ERROR] ' + str(msg) + " [setupPHPSymlink]")
|
Upgrade.stdOut('[ERROR] ' + str(msg) + " [setupPHPSymlink]")
|
||||||
@@ -4150,6 +4339,9 @@ pm.max_spare_servers = 3
|
|||||||
Upgrade.manageServiceMigrations()
|
Upgrade.manageServiceMigrations()
|
||||||
Upgrade.enableServices()
|
Upgrade.enableServices()
|
||||||
|
|
||||||
|
# Apply AlmaLinux 9 fixes before other installations
|
||||||
|
Upgrade.fix_almalinux9_mariadb()
|
||||||
|
|
||||||
Upgrade.installPHP73()
|
Upgrade.installPHP73()
|
||||||
Upgrade.setupCLI()
|
Upgrade.setupCLI()
|
||||||
Upgrade.someDirectories()
|
Upgrade.someDirectories()
|
||||||
@@ -4158,6 +4350,9 @@ pm.max_spare_servers = 3
|
|||||||
|
|
||||||
## Fix Apache configuration issues after upgrade
|
## Fix Apache configuration issues after upgrade
|
||||||
Upgrade.fixApacheConfiguration()
|
Upgrade.fixApacheConfiguration()
|
||||||
|
|
||||||
|
# Fix LiteSpeed configuration files if missing
|
||||||
|
Upgrade.fixLiteSpeedConfig()
|
||||||
|
|
||||||
### General migrations are not needed any more
|
### General migrations are not needed any more
|
||||||
|
|
||||||
@@ -4191,8 +4386,32 @@ pm.max_spare_servers = 3
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
command = 'cp /usr/local/lsws/lsphp80/bin/lsphp %s' % (phpPath)
|
# Try to find available PHP binary in order of preference (modern stable first)
|
||||||
|
php_versions = ['83', '82', '84', '85', '81', '80', '74', '73', '72', '71']
|
||||||
|
php_binary_found = False
|
||||||
|
|
||||||
|
for version in php_versions:
|
||||||
|
php_binary = f'/usr/local/lsws/lsphp{version}/bin/lsphp'
|
||||||
|
if os.path.exists(php_binary):
|
||||||
|
command = f'cp {php_binary} {phpPath}'
|
||||||
Upgrade.executioner(command, 0)
|
Upgrade.executioner(command, 0)
|
||||||
|
Upgrade.stdOut(f"Using PHP {version} for LSCPD", 1)
|
||||||
|
php_binary_found = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not php_binary_found:
|
||||||
|
Upgrade.stdOut("Warning: No PHP binary found for LSCPD", 0)
|
||||||
|
# Try to create a symlink to any available PHP
|
||||||
|
try:
|
||||||
|
command = 'find /usr/local/lsws -name "lsphp" -type f 2>/dev/null | head -1'
|
||||||
|
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
||||||
|
if result.stdout.strip():
|
||||||
|
php_binary = result.stdout.strip()
|
||||||
|
command = f'cp {php_binary} {phpPath}'
|
||||||
|
Upgrade.executioner(command, 0)
|
||||||
|
Upgrade.stdOut(f"Using found PHP binary: {php_binary}", 1)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
if Upgrade.SoftUpgrade == 0:
|
if Upgrade.SoftUpgrade == 0:
|
||||||
try:
|
try:
|
||||||
@@ -4200,6 +4419,42 @@ pm.max_spare_servers = 3
|
|||||||
Upgrade.executioner(command, 'Start LSCPD', 0)
|
Upgrade.executioner(command, 'Start LSCPD', 0)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Try to start other services if they exist
|
||||||
|
# Enhanced service startup with AlmaLinux 9 support
|
||||||
|
services_to_start = ['fastapi_ssh_server', 'cyberpanel']
|
||||||
|
|
||||||
|
# Special handling for AlmaLinux 9 MariaDB service
|
||||||
|
if Upgrade.is_almalinux9():
|
||||||
|
Upgrade.stdOut("AlmaLinux 9 detected - applying enhanced service management", 1)
|
||||||
|
mariadb_services = ['mariadb', 'mysql', 'mysqld']
|
||||||
|
for service in mariadb_services:
|
||||||
|
try:
|
||||||
|
check_command = f"systemctl list-unit-files | grep -q {service}"
|
||||||
|
result = subprocess.run(check_command, shell=True, capture_output=True)
|
||||||
|
if result.returncode == 0:
|
||||||
|
command = f"systemctl restart {service}"
|
||||||
|
Upgrade.executioner(command, f'Restart {service} for AlmaLinux 9', 0)
|
||||||
|
command = f"systemctl enable {service}"
|
||||||
|
Upgrade.executioner(command, f'Enable {service} for AlmaLinux 9', 0)
|
||||||
|
Upgrade.stdOut(f"MariaDB service managed as {service} on AlmaLinux 9", 1)
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
Upgrade.stdOut(f"Could not manage MariaDB service {service}: {str(e)}", 0)
|
||||||
|
continue
|
||||||
|
|
||||||
|
for service in services_to_start:
|
||||||
|
try:
|
||||||
|
# Check if service exists
|
||||||
|
check_command = f"systemctl list-unit-files | grep -q {service}"
|
||||||
|
result = subprocess.run(check_command, shell=True, capture_output=True)
|
||||||
|
if result.returncode == 0:
|
||||||
|
command = f"systemctl start {service}"
|
||||||
|
Upgrade.executioner(command, f'Start {service}', 0)
|
||||||
|
else:
|
||||||
|
Upgrade.stdOut(f"Service {service} not found, skipping", 0)
|
||||||
|
except Exception as e:
|
||||||
|
Upgrade.stdOut(f"Could not start {service}: {str(e)}", 0)
|
||||||
|
|
||||||
# Remove CSF if installed and restore firewalld (CSF is being discontinued on August 31, 2025)
|
# Remove CSF if installed and restore firewalld (CSF is being discontinued on August 31, 2025)
|
||||||
if os.path.exists('/etc/csf'):
|
if os.path.exists('/etc/csf'):
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user