- Honor downloadAndUpgrade return value; exit 1 instead of printing Upgrade Completed
- Restart lscpd if code update fails so panel is reachable on old tree
- CYBERPANEL_UPGRADE_CLONE_ATTEMPTS (default 2) for transient clone errors
- On rmtree failure, move /usr/local/CyberCP aside instead of aborting when possible
- Export CYBERPANEL_UPGRADE_CLONE_ATTEMPTS from 08_main_upgrade.sh
- Add plogical/phpmyadmin_utils.ensure_phpmyadmin_signin_bridge: restore
phpmyadminsignin.php and tmp/ if missing (fixes 404 on /phpmyadmin/phpmyadminsignin.php).
- Call from databases phpMyAdmin page, fetchDetailsPHPMYAdmin, install, and upgrade PMA paths.
- install/upgrade: use makedirs(..., exist_ok=True) for phpmyadmin/tmp instead of mkdir.
- pluginInstaller: run migrate when migrations/ contains modules OR enable_migrations;
use CyberCP venv python; --noinput for migrate; log non-zero exits.
Integrates webmail and emailDelivery apps, mail-server and install/upgrade
paths, cyberpanel_ols 2.7.0-style binaries, and v2.4.5 UI patterns while
preserving v2.5.5-dev behavior (SnappyMail/PUBLIC_ROOT, childPath in
launchChild, hardened downloads and SSH activity modal).
os.path.exists() returns False for broken symlinks (e.g. /usr/bin/php
pointing to removed php7.4), so the old link was never removed and
the new ln -s to lsphp83 failed silently. Use os.path.lexists() instead.
- dockerManager: add 0001_initial migration (CREATE TABLE IF NOT EXISTS), migrate-and-retry on DB errors, safe error response, fix logging.CyberCPLogFileWriter.writeToFile
- dockerManager/views: listContainersPage fallback HTML with error message if template fails
- dockerManager/viewContainer: improve container log readability (font-size 1rem, color #f1f5f9, line-height 1.6)
- baseTemplate: blockIPAddress also adds ban to firewall BannedIP model so Firewall > Banned IPs shows all
- firewall: getBannedIPs migrate-and-retry on OperationalError/ProgrammingError; install runs migrate firewall
- plogical/upgrade: syncBannedIPsJsonToDb() to sync JSON bans to firewall_bannedips; firewallMigrations() calls it; CyberPanelUpgrade runs firewallMigrations(); someDirectories creates /usr/local/CyberCP/data
- install: explicit migrate firewall after global migrate
Postfix SASL PLAIN auth fails with "No worthy mechs found" on
RHEL/AlmaLinux because cyrus-sasl-plain is not installed by default.
- Add cyrus-sasl-plain to postfix install in install.py
- Auto-install in configureRelayHost() for existing servers
- Add to upgrade.py setupSieve() for existing installations
lscpd worker runs as user lscpd, not cyberpanel. The webmail.conf file
(containing master user credentials) was unreadable by lscpd, causing
master auth to silently fail and fall back to empty password auth.
Also fix ownership on existing installs during upgrade.
- Replace free text input with folder dropdown for move-to-folder rules
- Auto-prefix INBOX. namespace to folder names in sieve scripts
- Strip INBOX. prefix when parsing sieve scripts back to rules
- Make upgrade setupSieve() regexes more flexible to handle config variations
- Add os.makedirs for conf.d directory in both install and upgrade
- Validate ManageSieve config with both inet_listener and service checks
- Add home directory (CONCAT) to dovecot-sql.conf.ext user_query so sieve
can locate script storage per user
- Add sieve/sieve_dir plugin settings to dovecot.conf templates
- Add lda_mailbox_autocreate/autosubscribe so fileinto creates missing folders
- Update setupSieve() upgrade function to patch all three on existing installs
On Ubuntu, the install creates /etc/pki/dovecot/ directories but never
populates them with certs. Postfix main.cf references these paths for
STARTTLS. Without them, inbound STARTTLS fails and external mail servers
(Gmail etc.) drop the connection, preventing mail delivery.
Security fixes:
- Escape plain text body to prevent XSS via trustAsHtml
- Add SSRF protection to image proxy (block private IPs, require auth)
- Sanitize Content-Disposition filename to prevent header injection
- Escape Sieve script values to prevent script injection
- Escape IMAP search query to prevent search injection
Install/upgrade fixes:
- Move setupWebmail() call to after Dovecot is installed (was running
before doveadm existed, silently failing on every fresh install)
- Make setupWebmail() a static method callable from install.py
- Fix upgrade idempotency: always run dovecot.conf patching and
migrations even if webmail.conf already exists (partial failure recovery)
Frontend fixes:
- Fix search being a no-op (was ignoring results and just reloading)
- Fix loading spinner stuck forever on API errors (add errback)
- Fix unread count decrementing on already-read messages
- Fix draft auto-save timer leak when navigating away from compose
- Fix composeToContact missing signature and auto-save
- Fix null subject crash in reply/forward
- Clear stale data when switching accounts
- Fix attachment part_id mismatch between parser and downloader
Backend fixes:
- Fix Sieve _read_response infinite loop on connection drop
- Add login check to apiSaveDraft
- Fix apiSSO() resetting selected account to first one on every call,
now preserves previously selected account if still valid
- Fix webmail.conf ownership to use cyberpanel:cyberpanel (Django runs
as cyberpanel user, not nobody)
- Add error notifications when SSO or folder loading fails
Adds master passdb config to dovecot.conf templates, setupWebmail() to
the installer and upgrade paths to generate credentials and create
/etc/dovecot/master-users and /etc/cyberpanel/webmail.conf automatically.
The upgrade path is idempotent and patches existing dovecot.conf if needed.
Rebuilt module fixes NULL pointer dereference in apply_headers() when
OLS generates error responses (4xx/5xx). The get_req_var_by_id() call
for DOC_ROOT crashed because request variables aren't initialized
during error response generation. Fix adds status code guard to skip
header processing for error responses.
- Fix 1: Parse -b/--branch and --mariadb-version with while-loop so only next token is used
(avoids Branch_Name becoming 'v2.5.5-dev --mariadb-version 12.3')
- Fix 2: Default Git_User to master3395 in Pre_Upgrade_Setup_Git_URL (04_git_url, monolithic)
- Fix 3: upgrade.py uses CYBERPANEL_GIT_USER for git clone (default master3395);
export CYBERPANEL_GIT_USER before upgrade.py in 08_main_upgrade and monolithic
- Fix 4: --mariadb-version already supported in 05_repository.sh (MARIADB_VER_REPO)
- versionFetcher: normalize RELEASE_5_2_3 -> 5.2.3 for phpMyAdmin tags
- upgrade: verify tarball size after download; chown lscpd at end of phpMyAdmin install
- install: same glob-based extract + verify; check tarball size
- fix-phpmyadmin.sh: one-off script to install/fix phpMyAdmin on server (404 fix)
New hashes for all 3 platforms after fixing the bug where VHosts with
SSL context but missing listener map entries served the wrong cert.
rhel9: 04921afbad94e7ee69bc93a73985e318df93f28b2b0d578447b0ef43dc6e3818
ubuntu: ae2564742f362d3e34ea814dff37edeb8f8b73ae9ca1484ba78e2453a3987429
rhel8: 855b6bccb4a7893914506a07185cffd834bd31a7f7c080b5b4190283def7fa3e
The previous string replace only matched 'adminEmails root@localhost'
exactly. On fresh OLS installs where adminEmails may have a different value
or different spacing, the replace would silently fail and Auto-SSL config
would never be injected. Use re.sub to match the adminEmails line regardless
of its value.
The string replace matched only 'adminEmails' keyword instead of the
full existing line 'adminEmails root@localhost', causing
the remaining ' root@localhost' to trail onto the acmeEmail
line and break ACME account registration.
Universal binaries with all features config-driven (PHPConfig API, Origin
Header Forwarding, ReadApacheConf with Portmap, Auto-SSL ACME v2,
ModSecurity ABI compatibility). Updates install, upgrade, and modSec paths.
Install:
- install.py: in preFlightsChecks.call(), replace missing CyberPanel python
with /usr/bin/python3 and force shell=True so any code path (including
old/cached script) never hits FileNotFoundError.
Upgrade:
- cyberpanel_upgrade.sh: resolve CP_PYTHON (CyberPanel, CyberCP, python3)
before running upgrade.py and configure.py; use it for both.
- plogical/upgrade.py: add _python_for_manage(), use it in GeneralMigrations,
collectstatic, and upgradePip so migrations/collectstatic work when
/usr/local/CyberPanel/bin/python is missing.
- install.py: use preFlightsChecks.mariadb_version in mariadb_repo_setup
- venvsetup.sh: prompt for MariaDB 11.8/12.1 in interactive install, pass --mariadb-version to install.py
- cyberpanel_upgrade.sh: add MARIADB_VER (default 11.8), --mariadb-version arg, interactive prompt, write /etc/cyberpanel/mariadb_version, use in MariaDB.repo
- plogical/upgrade.py: read mariadb_version from /etc/cyberpanel/mariadb_version in fix_almalinux9_mariadb(), default 11.8
- Install: add LiteSpeed repo (repo.litespeed.sh), install openlitespeed; keep official binary if >= 1.8.5, else optional custom binary overlay
- Upgrade: add repo, upgrade openlitespeed package; only run installCustomOLSBinaries if version < 1.8.5
- LSWS: fallback to 6.3.4 when API empty in cyberpanel_upgrade.sh and venvsetup.sh; sed lsws-6.0 and lsws-6.3.4 to latest stable
- plogical/upgrade: add_litespeed_repo(), get_installed_ols_version(); install.py: add_litespeed_repo(), get_installed_ols_version()
- Enhanced MariaDB-server-compat package removal with multiple aggressive attempts
- Added --allowerasing and dnf exclude to prevent compat package conflicts
- Added MariaDB binary verification before password change
- Added service status verification and wait time
- Improved error handling and graceful failure
- Fixed FileNotFoundError when mysql command not found
Fixes:
- MariaDB-server-compat-12.1.2-1.el9.noarch conflict with MariaDB 10.11
- mysql command not found after failed installation
- Installation proceeding when MariaDB wasn't actually installed
- install_utils.call: use shell=True for commands with ||, 2>, |, etc.
Avoids 'No matching repo to modify: 2>/dev/null, true, ||' when
dnf config-manager '... 2>/dev/null || true' is run via shlex.split.
- Add explicit 'rpm -e --nodeps MariaDB-server-compat-12.1.2-1.el9.noarch'
before dnf remove in main(), installMySQL, fix_almalinux9_comprehensive.
- upgrade fix_almalinux9_mariadb: add compat removal before MariaDB install;
use MariaDB 10.11 repo instead of 12.1 to avoid compat conflicts.
- Updated fallback version in versionFetcher.py to 5.2.3
- Updated fallback version in upgrade.py to 5.2.3
- Uses latest stable phpMyAdmin version (released 2025-10-08)
- Reference: https://www.phpmyadmin.net/files/5.2.3/
- Added migrateRainloopToSnappymail() function to automatically migrate email data
- Migrates from /usr/local/lscp/cyberpanel/rainloop/data to /usr/local/lscp/cyberpanel/snappymail/data
- Uses rsync to preserve permissions and ownership
- Updates include.php files to use new snappymail path
- Includes safety checks to prevent data overwriting
- Added migration logic to cyberpanel_upgrade.sh
- Updated default paths from rainloop to snappymail
- Deprecates rainloop folder in 2.5.5-dev