Letting Pi Upgrade My Mail Server

I installed Pi on my mail server and connected it to my local llama.cpp server running Qwen 3.6 27b. I knew upgrading by hand would be arduous as I was currently on Debian 11 and wanted to go to 13, and there are a ton of moving parts involved in a mail server. Plus you can't upgrade from 11 -> 13 directly as you have to move to 12 (Bookworm) first. This was a good opportunity to see how smart my local model really was. I had Pi write documentation along the way. WARNING - DON'T EVER DO THIS WITH A MODEL THAT YOU DO NOT HOST YOURSELF!!! Model created documentation below.

Server Upgrade: Debian 11 (Bullseye) → Debian 13 (Trixie)

Date: 2026-05-14
Server: mail.me.com
Hostname: mail.me.com
Domain: me.com
Mail Users: 5
iRedMail Edition: 1.8.0 (MariaDB edition)


Table of Contents

  1. Pre-Upgrade Inventory
  2. Upgrade Path
  3. Phase 1: Debian 11 → 12 (Bookworm)
  4. Phase 2: Debian 12 → 13 (Trixie)
  5. Post-Upgrade Verification
  6. Troubleshooting Notes

Pre-Upgrade Inventory

OS and Kernel

Item Value
OS Debian GNU/Linux 11 (bullseye)
Kernel 5.10.0-42-amd64
Architecture x86_64
Disk 125G (11G used, 108G available)
RAM 3.8Gi
Swap 974Mi

Installed Software Stack

Component Version Notes
iRedMail 1.8.0 MariaDB edition
Postfix 3.5.25 MTA
Dovecot 2.3.13 IMAP/POP3/LMTP/Sieve
MariaDB 10.5.29 Database backend
Nginx 1.18.0 Web server
PHP 7.4 (FPM) PHP-FPM on 127.0.0.1:9999
Python 3.9 For iRedAPD, mlmmjadmin
Amavis 2.11.1 Content filter
ClamAV 1.4.3 Antivirus
SpamAssassin 3.4.6 Spam filtering
Fail2ban 0.11.2 Intrusion prevention
Roundcube 1.5.2 (active), 1.6.1 available Webmail
iRedAdmin 2.8.1 Admin panel
iRedAPD 6.1 Policy daemon
mlmmjadmin 3.6.2 Mailing list manager
Netdata running Monitoring
Certbot 1.12.0 SSL certificates

Running Services

  • amavis, clamav-daemon, clamav-freshclam
  • dovecot (IMAP/POP3/LMTP/Sieve)
  • mariadb (MySQL 10.5)
  • nginx
  • php7.4-fpm
  • postfix
  • iredapd, iredadmin, mlmmjadmin
  • fail2ban, rsyslog, cron, ssh
  • netdata, qemu-guest-agent

Databases

  • amavisd, fail2ban, iredadmin, iredapd, roundcubemail, vmail

Key Configuration Paths

  • /etc/postfix/ - Postfix configuration
  • /etc/dovecot/ - Dovecot configuration
  • /etc/nginx/ - Nginx configuration
  • /etc/php/7.4/fpm/pool.d/www.conf - PHP-FPM pool config
  • /opt/www/roundcubemail → symlink to roundcubemail-1.5.2
  • /opt/www/iredadmin → symlink to iRedAdmin-2.8.1
  • /opt/iredapd → symlink to iRedAPD-6.1
  • /opt/mlmmjadmin → symlink to mlmmjadmin-3.6.2
  • /var/vmail/ - Mail storage

References


Upgrade Path

Debian 11 (Bullseye) → Debian 12 (Bookworm) → Debian 13 (Trixie)
PHP 7.4              → PHP 8.2                → PHP 8.4
MariaDB 10.5         → MariaDB 10.11          → MariaDB 11.x
Dovecot 2.3.13       → Dovecot 2.3.21         → Dovecot 2.4 (BREAKING!)
Nginx 1.18           → Nginx 1.22             → Nginx 1.26
Python 3.9           → Python 3.11            → Python 3.13
Postfix 3.5          → Postfix 3.7            → Postfix 3.9

⚠️ Critical: Dovecot 2.4 in Debian 13 is NOT backward-compatible with 2.3. Config files must be replaced.


Phase 1: Debian 11 → 12 (Bookworm)

Step 1.1: Pre-Upgrade Updates

  • [x] Run apt update && apt full-upgrade to get latest Bullseye packages
  • [x] Reboot to ensure clean state

Step 1.2: Backups

  • [x] Backup MariaDB databases
  • [x] Backup all configuration files
  • [x] Backup mail storage
  • [x] Backup /opt/www and /opt applications

Step 1.3: Sources List Change

  • [x] Replace bullseye with bookworm in /etc/apt/sources.list
  • [x] Remove bullseye-security references (merged into main in Bookworm)

Step 1.4: OS Upgrade

  • [x] apt update
  • [x] apt full-upgrade -y
  • [x] apt autoremove -y
  • [x] Reboot

Step 1.5: Post-Upgrade Fixes (per iRedMail docs)

  • [x] Re-upgrade Python apps: iRedAPD, mlmmjadmin, iRedAdmin (Python env changed 3.9→3.11)
  • [x] Verify all services running
  • [x] Test email send/receive

[x] PHP-FPM: Copy pool config from 7.4 → 8.2, restart php8.2-fpm

cp /etc/php/7.4/fpm/pool.d/www.conf /etc/php/8.2/fpm/pool.d/www.conf
service php8.2-fpm restart

Phase 2: Debian 12 → 13 (Trixie)

Step 2.1: Pre-Upgrade Updates

  • [x] Run apt update && apt full-upgrade to get latest Bookworm packages
  • [x] Reboot to ensure clean state

Step 2.2: Backups (again)

  • [x] Backup MariaDB databases
  • [x] Backup all configuration files
  • [x] Backup mail storage

Step 2.3: Sources List Change

  • [x] Replace bookworm with trixie in /etc/apt/sources.list

Step 2.4: OS Upgrade

  • [x] apt update
  • [x] apt full-upgrade -y
  • [x] apt autoremove -y
  • [x] Reboot

Step 2.5: Post-Upgrade Fixes (per iRedMail docs)

  • [x] Nginx: Remove http2 from listen directives, add http2 on;
  • [x] PHP-FPM: Copy pool config from 8.2 → 8.4, restart php8.4-fpm
  • [x] Dovecot 2.4: Replace config, update passwords, SSL certs, DH params
  • [x] Dovecot MariaDB trigger: Apply new SQL trigger for used_quota
  • [x] Re-upgrade Python apps: iRedAPD, mlmmjadmin, iRedAdmin (Python env changed 3.11→3.13)
  • [x] Verify all services running
  • [x] Test email send/receive

Post-Upgrade Verification

Services Check

systemctl status postfix dovecot mariadb nginx php*-fpm amavis clamav-daemon iredapd iredadmin mlmmjadmin fail2ban

Email Functionality Tests

  • [x] SMTP connection test (port 25)
  • [x] IMAP connection test (port 143/993)
  • [x] Webmail (Roundcube) login test
  • [x] iRedAdmin login test
  • [x] Send test email externally
  • [x] Receive test email externally
  • [x] Spam filtering test
  • [x] Antivirus scanning test

Troubleshooting Notes

Common Issues

  1. PHP-FPM not connecting to Nginx: Ensure pool config copied to new PHP version's directory
  2. Dovecot 2.4 config incompatibility: Must use new config format, old 2.3 configs won't work
  3. Python app failures: Re-install Python dependencies after each OS upgrade
  4. MariaDB upgrade failures: May need mysql_upgrade or manual migration
  5. Nginx http2 change: Debian 13 requires http2 on; directive instead of inline http2 in listen

Rollback Plan

If upgrade fails at any point:

  1. Restore MariaDB from backup
  2. Restore config files from backup
  3. Restore mail storage from backup
  4. Revert sources.list to previous release
  5. apt update && apt dist-downgrade (last resort)

Upgrade Log

2026-05-14

  • [x] System inventory completed
  • [x] Research completed - official iRedMail upgrade docs reviewed
  • [x] Documentation created

2026-05-14 (continued)

  • [x] Phase 1: Debian 11 → 12 completed successfully
    • PHP 7.4 → 8.2, MariaDB 10.5 → 10.11, Python 3.9 → 3.11
    • PHP-FPM config copied to 8.2, all services verified
  • [x] Phase 2: Debian 12 → 13 completed successfully
    • PHP 8.2 → 8.4, MariaDB 10.11 → 11.8, Python 3.11 → 3.13
    • Dovecot 2.3 → 2.4 (config rewritten for 2.4 compatibility)
    • Nginx http2 directive updated
    • PHP-FPM config copied to 8.4

Final State

Component Before After
OS Debian 11 Bullseye Debian 13 Trixie
PHP 7.4 8.4.21
MariaDB 10.5 11.8.6
Postfix 3.5.25 3.10.5
Dovecot 2.3.13 2.4.1
Nginx 1.18 1.26.3
Python 3.9 3.13.5
OpenSSL 1.1.1w 3.5.5

Post-Upgrade Fixes Applied

  1. Nginx http2: Removed http2 from listen directives, added http2 on;
  2. PHP-FPM: Copied pool config from 8.2 → 8.4, restarted php8.4-fpm
  3. Dovecot 2.4: Rewrote config for 2.4 compatibility:
    • mail_locationmail_driver + mail_home + mail_path
    • ssl_certssl_server_cert_file
    • ssl_keyssl_server_key_file
    • ssl_dhssl_server_dh_file
    • ssl_prefer_server_ciphersssl_server_prefer_ciphers = server
    • disable_plaintext_auth → removed (SSL required handles this)
    • addresslisten in inet_listener blocks
    • passdb {}passdb sql {} (needs driver name)
    • userdb {}userdb sql {} (needs driver name)
    • service_countprocess_min_avail
    • process_limit in service blocks → default_process_limit
  4. Python apps: iRedAPD, mlmmjadmin, iRedAdmin all running on Python 3.13

Known Warnings

  • Postfix warns about smtpd_tls_dh1024_param_file being deprecated (can be removed from main.cf)
  • Postfix warns about disable_dns_lookups being deprecated in master.cf

Backups

  • Phase 1 backup: /root/upgrade-backup-20260514/
  • Phase 2 backup: /root/upgrade-backup-phase2-20260514/
  • Old Dovecot config: /etc/dovecot.old.bak/
  • Old sources.list: /etc/apt/sources.list.bullseye.bak

Post-Upgrade Fixes

Dovecot 2.4 SQL Auth (Major Fix)

The Dovecot 2.4 upgrade broke SQL authentication. The config syntax changed significantly:

  1. Variable substitution: %u%{user} in SQL queries
  2. SQL queries: Must be set as global passdb_sql_query / userdb_sql_query instead of inside passdb sql {} blocks
  3. Database connection: Uses mysql 127.0.0.1 {} blocks at global scope
  4. Plugin removal: mailbox_alias plugin no longer exists in Dovecot 2.4
  5. Config file location: /etc/dovecot/conf.d/auth-sql.conf.ext (not dovecot-mysql.conf)

PHP 8.4 IMAP Extension

Debian 13 removed php-imap from its repos due to licensing issues. Installed from sury PHP repo:

curl -fsSL https://packages.sury.org/php/apt.gpg | gpg --dearmor -o /usr/share/keyrings/php.sury.org.gpg
echo "deb [signed-by=/usr/share/keyrings/php.sury.org.gpg] https://packages.sury.org/php/ trixie main" > /etc/apt/sources.list.d/php-sury.list
apt update && apt install php8.4-imap

Roundcube Version

  • Active symlink: /opt/www/roundcubemail -> /opt/www/roundcubemail-1.5.2 (upgraded in-place to 1.6.15)
  • Also have /opt/www/roundcubemail-1.6.1 available
  • Roundcube 1.5.x is incompatible with PHP 8.4

Final Status

  • [x] All services running
  • [x] SMTP/IMAP/POP3 working
  • [x] Roundcube webmail login working
  • [x] iRedAdmin web UI working
  • [x] Dovecot SQL auth working
  • [x] PHP 8.4 IMAP extension installed
  • [x] Kernel upgraded to 6.12.86
  • [x] Old kernel purged
  • [x] Documentation updated

Subscribe to on2fab

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe