diff --git a/install/install.py b/install/install.py index 1dd0e31b7..504e34512 100644 --- a/install/install.py +++ b/install/install.py @@ -631,17 +631,49 @@ class preFlightsChecks: # Clone directly to /usr/local/CyberCP with explicit path logging.InstallLog.writeToFile("Cloning repository to /usr/local/CyberCP...") - command = "git clone https://github.com/usmannasir/cyberpanel /usr/local/CyberCP" - result = preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR) - - if result != 1: - logging.InstallLog.writeToFile("[ERROR] Git clone to /usr/local/CyberCP failed!") - sys.exit(1) - - # Verify CyberCP directory was created at the explicit path - if not os.path.exists('/usr/local/CyberCP'): - logging.InstallLog.writeToFile("[ERROR] Git clone did not create '/usr/local/CyberCP' directory!") - sys.exit(1) + + # Ensure the parent directory exists + os.makedirs("/usr/local", exist_ok=True) + + # Try multiple clone methods for better reliability + clone_commands = [ + "git clone https://github.com/usmannasir/cyberpanel /usr/local/CyberCP", + "git clone --depth 1 https://github.com/usmannasir/cyberpanel /usr/local/CyberCP", + "git clone --single-branch --branch stable https://github.com/usmannasir/cyberpanel /usr/local/CyberCP" + ] + + clone_success = False + for cmd in clone_commands: + try: + result = preFlightsChecks.call(cmd, self.distro, cmd, cmd, 1, 1, os.EX_OSERR) + if result == 1 and os.path.exists('/usr/local/CyberCP'): + clone_success = True + break + except: + continue + + if not clone_success or not os.path.exists('/usr/local/CyberCP'): + logging.InstallLog.writeToFile("[ERROR] All Git clone attempts failed!") + preFlightsChecks.stdOut("[ERROR] All Git clone attempts failed!") + + # Try manual download as fallback + logging.InstallLog.writeToFile("Attempting manual download as fallback...") + command = "wget -O /tmp/cyberpanel.zip https://github.com/usmannasir/cyberpanel/archive/refs/heads/stable.zip" + preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR) + + command = "unzip /tmp/cyberpanel.zip -d /usr/local/" + preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR) + + command = "mv /usr/local/cyberpanel-stable /usr/local/CyberCP" + preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR) + + command = "rm -f /tmp/cyberpanel.zip" + preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR) + + if not os.path.exists('/usr/local/CyberCP'): + logging.InstallLog.writeToFile("[ERROR] Manual download also failed!") + preFlightsChecks.stdOut("[ERROR] Manual download also failed!") + sys.exit(1) logging.InstallLog.writeToFile("Successfully cloned repository to /usr/local/CyberCP") @@ -1250,23 +1282,66 @@ $cfg['Servers'][$i]['LogoutURL'] = 'phpmyadminsignin.php?logout'; # Remove conflicting dovecot packages first try: - if self.distro in [centos, cent8]: + if self.distro == centos: + # CentOS 7 (Legacy - EOL) - use yum preFlightsChecks.call('yum remove -y dovecot dovecot-*', self.distro, 'Remove conflicting dovecot packages', 'Remove conflicting dovecot packages', 1, 0, os.EX_OSERR) + elif self.distro in [cent8, openeuler]: + # CentOS 8, AlmaLinux 8/9/10, RockyLinux 8/9, RHEL 8/9, CloudLinux 8/9 - use dnf + preFlightsChecks.call('dnf remove -y dovecot dovecot-*', self.distro, + 'Remove conflicting dovecot packages', + 'Remove conflicting dovecot packages', 1, 0, os.EX_OSERR) + else: + # Ubuntu 24.04/22.04/20.04, Debian 13/12/11 - use apt + preFlightsChecks.call('apt-get remove -y dovecot dovecot-*', self.distro, + 'Remove conflicting dovecot packages', + 'Remove conflicting dovecot packages', 1, 0, os.EX_OSERR) except: pass # Continue if removal fails if self.distro == centos: + # CentOS 7 (Legacy - EOL) command = 'yum --enablerepo=gf-plus -y install dovecot23 dovecot23-mysql --allowerasing' elif self.distro == cent8: + # CentOS 8, AlmaLinux 8, RockyLinux 8, RHEL 8, CloudLinux 8 command = 'dnf install --enablerepo=gf-plus dovecot23 dovecot23-mysql -y --allowerasing' elif self.distro == openeuler: - command = 'dnf install dovecot -y' + # AlmaLinux 9/10, RockyLinux 9, RHEL 9, CloudLinux 9, and other modern RHEL-based systems + dovecot_commands = [ + 'dnf install dovecot dovecot-mysql -y --skip-broken --nobest', + 'dnf install dovecot23 dovecot23-mysql -y --skip-broken --nobest', + 'dnf install dovecot -y --skip-broken --nobest' + ] + + dovecot_installed = False + for cmd in dovecot_commands: + try: + preFlightsChecks.call(cmd, self.distro, cmd, cmd, 1, 1, os.EX_OSERR, True) + if os.path.exists('/etc/dovecot') or os.path.exists('/usr/sbin/dovecot'): + dovecot_installed = True + break + except: + continue + + if not dovecot_installed: + command = 'dnf install dovecot -y --skip-broken --nobest --allowerasing' + preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR, True) else: + # Ubuntu 24.04/22.04/20.04, Debian 13/12/11 command = 'DEBIAN_FRONTEND=noninteractive apt-get -y install dovecot-mysql dovecot-imapd dovecot-pop3d' preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR, True) + + # Ensure Dovecot service is properly configured + self.manage_service('dovecot', 'enable') + self.manage_service('dovecot', 'start') + + # Verify Dovecot installation + if os.path.exists('/usr/sbin/dovecot') or os.path.exists('/usr/bin/dovecot'): + logging.InstallLog.writeToFile("Dovecot installation successful") + else: + logging.InstallLog.writeToFile("[WARNING] Dovecot binary not found after installation") except BaseException as msg: logging.InstallLog.writeToFile('[ERROR] ' + str(msg) + " [install_postfix_dovecot]") @@ -1435,6 +1510,17 @@ $cfg['Servers'][$i]['LogoutURL'] = 'phpmyadminsignin.php?logout'; master = "/etc/postfix/master.cf" dovecot = "/etc/dovecot/dovecot.conf" dovecotmysql = "/etc/dovecot/dovecot-sql.conf.ext" + + # Ensure dovecot directory exists + os.makedirs("/etc/dovecot", exist_ok=True) + + # Also ensure dovecot conf.d directory exists + os.makedirs("/etc/dovecot/conf.d", exist_ok=True) + + # Check if Dovecot is installed before proceeding + if not os.path.exists('/usr/sbin/dovecot') and not os.path.exists('/usr/bin/dovecot'): + logging.InstallLog.writeToFile("[ERROR] Dovecot not installed, cannot configure") + return 0 if os.path.exists(mysql_virtual_domains): os.remove(mysql_virtual_domains) @@ -1488,8 +1574,113 @@ $cfg['Servers'][$i]['LogoutURL'] = 'phpmyadminsignin.php?logout'; "/etc/postfix/mysql-virtual_email2email.cf") shutil.copy("email-configs-one/main.cf", main) shutil.copy("email-configs-one/master.cf", master) - shutil.copy("email-configs-one/dovecot.conf", dovecot) - shutil.copy("email-configs-one/dovecot-sql.conf.ext", dovecotmysql) + # Copy Dovecot configuration files with fallback + try: + shutil.copy("email-configs-one/dovecot.conf", dovecot) + shutil.copy("email-configs-one/dovecot-sql.conf.ext", dovecotmysql) + except FileNotFoundError: + # Fallback: create basic dovecot.conf if template not found + logging.InstallLog.writeToFile("[WARNING] Dovecot config templates not found, creating basic configuration") + + # Create basic dovecot.conf + with open(dovecot, 'w') as f: + f.write('''protocols = imap pop3 +log_timestamp = "%Y-%m-%d %H:%M:%S " + +ssl_cert =