From 7e86659a55bdb606fb200470d0977755c502163e Mon Sep 17 00:00:00 2001 From: usmannasir Date: Thu, 5 Mar 2026 05:54:09 +0500 Subject: [PATCH] Fix missing mail TLS certs: copy self-signed certs to /etc/pki/dovecot/ at install and upgrade 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. --- install/install.py | 10 +++++++++ plogical/upgrade.py | 54 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/install/install.py b/install/install.py index b447d5742..729d1296f 100644 --- a/install/install.py +++ b/install/install.py @@ -1396,6 +1396,16 @@ $cfg['Servers'][$i]['LogoutURL'] = 'phpmyadminsignin.php?logout'; command = "mkdir -p /etc/pki/dovecot/certs/" preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR) + # Copy self-signed certs to where Postfix main.cf expects them + command = "cp /etc/dovecot/cert.pem /etc/pki/dovecot/certs/dovecot.pem" + preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR) + + command = "cp /etc/dovecot/key.pem /etc/pki/dovecot/private/dovecot.pem" + preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR) + + command = "chmod 600 /etc/pki/dovecot/private/dovecot.pem" + preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR) + command = "mkdir -p /etc/opendkim/keys/" preFlightsChecks.call(command, self.distro, command, command, 1, 0, os.EX_OSERR) diff --git a/plogical/upgrade.py b/plogical/upgrade.py index 678a7e15a..afd587891 100644 --- a/plogical/upgrade.py +++ b/plogical/upgrade.py @@ -2890,6 +2890,59 @@ passdb { except BaseException as msg: Upgrade.stdOut("setupWebmail error: " + str(msg), 0) + @staticmethod + def fixMailTLS(): + """Ensure Postfix/Dovecot TLS cert files exist at expected paths. + + On Ubuntu, the install creates dirs at /etc/pki/dovecot/ but never + copies the self-signed certs there. This breaks STARTTLS and prevents + external mail servers (Gmail, etc.) from delivering inbound mail. + """ + try: + cert_path = '/etc/pki/dovecot/certs/dovecot.pem' + key_path = '/etc/pki/dovecot/private/dovecot.pem' + + # Skip if certs already exist + if os.path.exists(cert_path) and os.path.exists(key_path): + return + + # Skip if no mail server + if not os.path.exists('/etc/dovecot/dovecot.conf'): + return + + Upgrade.stdOut("Fixing mail TLS certificates...", 0) + + os.makedirs('/etc/pki/dovecot/certs', exist_ok=True) + os.makedirs('/etc/pki/dovecot/private', exist_ok=True) + + # Prefer existing Dovecot self-signed certs + if os.path.exists('/etc/dovecot/cert.pem') and os.path.exists('/etc/dovecot/key.pem'): + import shutil + shutil.copy2('/etc/dovecot/cert.pem', cert_path) + shutil.copy2('/etc/dovecot/key.pem', key_path) + else: + # Generate a new self-signed cert + hostname = ProcessUtilities.outputExecutioner( + 'hostname').strip() or 'localhost' + subprocess.call([ + 'openssl', 'req', '-x509', '-nodes', '-days', '3650', + '-newkey', 'rsa:2048', + '-subj', '/CN=%s' % hostname, + '-keyout', key_path, + '-out', cert_path + ]) + + os.chmod(cert_path, 0o644) + os.chmod(key_path, 0o600) + + # Restart Postfix to pick up the certs + subprocess.call(['systemctl', 'restart', 'postfix']) + + Upgrade.stdOut("Mail TLS certificates fixed.", 0) + + except BaseException as msg: + Upgrade.stdOut("fixMailTLS error: " + str(msg), 0) + @staticmethod def manageServiceMigrations(): try: @@ -4814,6 +4867,7 @@ pm.max_spare_servers = 3 Upgrade.s3BackupMigrations() Upgrade.containerMigrations() Upgrade.manageServiceMigrations() + Upgrade.fixMailTLS() Upgrade.setupWebmail() Upgrade.enableServices()