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
- Pre-Upgrade Inventory
- Upgrade Path
- Phase 1: Debian 11 → 12 (Bookworm)
- Phase 2: Debian 12 → 13 (Trixie)
- Post-Upgrade Verification
- 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
- iRedMail: Fixes after upgrading Debian 11 → 12
- iRedMail: Fixes after upgrading Debian 12 → 13
- Debian 13 Release Notes
- Debian Upgrade Guide
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-upgradeto 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
bullseyewithbookwormin/etc/apt/sources.list - [x] Remove
bullseye-securityreferences (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-upgradeto 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
bookwormwithtrixiein/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
http2from listen directives, addhttp2 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
- PHP-FPM not connecting to Nginx: Ensure pool config copied to new PHP version's directory
- Dovecot 2.4 config incompatibility: Must use new config format, old 2.3 configs won't work
- Python app failures: Re-install Python dependencies after each OS upgrade
- MariaDB upgrade failures: May need
mysql_upgradeor manual migration - Nginx http2 change: Debian 13 requires
http2 on;directive instead of inlinehttp2in listen
Rollback Plan
If upgrade fails at any point:
- Restore MariaDB from backup
- Restore config files from backup
- Restore mail storage from backup
- Revert sources.list to previous release
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
- Nginx http2: Removed
http2fromlistendirectives, addedhttp2 on; - PHP-FPM: Copied pool config from 8.2 → 8.4, restarted php8.4-fpm
- Dovecot 2.4: Rewrote config for 2.4 compatibility:
mail_location→mail_driver+mail_home+mail_pathssl_cert→ssl_server_cert_filessl_key→ssl_server_key_filessl_dh→ssl_server_dh_filessl_prefer_server_ciphers→ssl_server_prefer_ciphers = serverdisable_plaintext_auth→ removed (SSL required handles this)address→listenin inet_listener blockspassdb {}→passdb sql {}(needs driver name)userdb {}→userdb sql {}(needs driver name)service_count→process_min_availprocess_limitin service blocks →default_process_limit
- Python apps: iRedAPD, mlmmjadmin, iRedAdmin all running on Python 3.13
Known Warnings
- Postfix warns about
smtpd_tls_dh1024_param_filebeing deprecated (can be removed from main.cf) - Postfix warns about
disable_dns_lookupsbeing 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:
- Variable substitution:
%u→%{user}in SQL queries - SQL queries: Must be set as global
passdb_sql_query/userdb_sql_queryinstead of insidepassdb sql {}blocks - Database connection: Uses
mysql 127.0.0.1 {}blocks at global scope - Plugin removal:
mailbox_aliasplugin no longer exists in Dovecot 2.4 - Config file location:
/etc/dovecot/conf.d/auth-sql.conf.ext(notdovecot-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.1available - 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