I recently upgraded two production iRedMail servers from version 1.7.4 to 1.8.2. The official documentation is excellent but assumes a perfect world. In reality, you’ll encounter:
- PHP version mismatches (older OS versions)
- File permission issues after upgrade
- Roundcube 1.7’s new
public_html/directory structure - The dreaded “config file not readable” error
- Symlink confusion
This guide documents exactly what worked on Rocky Linux 10.1, with fixes for every issue we encountered.
What You’ll Achieve
| Before | After |
|---|---|
| iRedMail 1.7.4 | iRedMail 1.8.2 |
| Roundcube 1.6.15 | Roundcube 1.7.1 |
| Old Nginx structure | New public_html/ structure |
| Mixed file ownership | Clean root:root with nginx:nginx for logs/temp |
PHP system() possibly enabled | PHP system() securely disabled |
Time required: 15-20 minutes
Risk level: Low (with proper backups)
Skill level: Intermediate
Prerequisites
Before starting, verify your environment:
# Check your OS version
cat /etc/rocky-release
# Check current iRedMail version
cat /etc/iredmail-release
# Check PHP version (Rocky Linux 10.1 comes with PHP 8.3+)
php -v
# Check web server
nginx -v
Important: This guide is written for Rocky Linux 10.1 (or AlmaLinux 10.1) which ships with PHP 8.3.29. If you’re on CentOS 7 or Rocky Linux 8, you’ll need additional PHP module commands which are noted throughout.
The Critical Warning You Must Read
⚠️ This Will Save You Hours of Debugging
- Never skip the intermediate version – You must upgrade to 1.8.0 before 1.8.2. The database schema changes require this path.
- Roundcube 1.7.x requires Nginx changes – The new
public_html/directory structure means your old Nginx configuration WILL break. Don’t skip this step. - Backup before EVERY step – One wrong permission can break webmail. Backups are not optional.
- PHP
system()must be temporarily enabled – The Roundcube upgrade script needs it, but re-disable it immediately after for security. - Symlinks can be confusing – After upgrade, your directory may still be named
roundcubemail-1.6.15but contain 1.7.1 files. This is normal.
Step-by-Step Upgrade Process
Step 1: Create Complete Backups (2 minutes)
# Create a dated backup directory
BACKUP_DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p /root/backup_$BACKUP_DATE
# Backup Roundcube files
sudo cp -r /opt/www/roundcubemail "/root/backup_$BACKUP_DATE/"
# Backup Nginx templates
sudo cp /etc/nginx/templates/roundcube.tmpl "/root/backup_$BACKUP_DATE/" 2>/dev/null
sudo cp /etc/nginx/templates/roundcube-subdomain.tmpl "/root/backup_$BACKUP_DATE/" 2>/dev/null
# Backup iRedMail version file
sudo cp /etc/iredmail-release "/root/backup_$BACKUP_DATE/"
# Backup Roundcube database
sudo mysqldump -u root -p roundcubemail > "/root/backup_$BACKUP_DATE/roundcubemail_backup.sql"
# Backup PHP configuration
sudo cp /etc/php.ini "/root/backup_$BACKUP_DATE/"
echo "✅ Backups saved to /root/backup_$BACKUP_DATE"
Step 2: Check Current Roundcube Version
# Check your current version
head -5 /opt/www/roundcubemail/index.php | grep Version
Expected output: Version 1.6.15
Step 3: Update iRedMail to 1.8.0
echo "1.8.0" | sudo tee /etc/iredmail-release
Step 4: Upgrade Roundcube to 1.6.15 (if not already)
cd /root
wget https://github.com/roundcube/roundcubemail/releases/download/1.6.15/roundcubemail-1.6.15-complete.tar.gz
tar xzf roundcubemail-1.6.15-complete.tar.gz
# Enable system() temporarily
sudo sed -i 's/disable_functions =.*/disable_functions = exec,passthru,shell_exec,proc_open,popen/' /etc/php.ini
sudo systemctl restart php-fpm
cd roundcubemail-1.6.15
echo "y" | sudo ./bin/installto.sh /opt/www/roundcubemail
# Re-disable system()
sudo sed -i 's/disable_functions =.*/disable_functions = exec,passthru,shell_exec,system,proc_open,popen/' /etc/php.ini
sudo systemctl restart php-fpm
Step 5: Update Nginx Templates (CRITICAL)
This is the most skipped step and the most common cause of post-upgrade failures.
5.1 Edit the main Roundcube template
sudo nano /etc/nginx/templates/roundcube.tmpl
Replace the entire content with:
# Block direct access to directories and files.
location ~ ^/mail/(SQL|bin|config|installer|logs|temp|vendor)/ { deny all; }
location ~ ^/mail/(.*\.md|composer\.*|INSTALL|LICENSE|Makefile|UPGRADING)$ { deny all; }
location ~ ^/mail/plugins/.*/config.inc.php.* { deny all; }
location ~ ^/mail/plugins/enigma/home($|/.*) { deny all; }
# Block access via public_html/static.php
location ~ ^/mail/static.php/(SQL|bin|config|installer|logs|temp|vendor)/ { deny all; }
location ~ ^/mail/static.php/(.*\.md|composer\.*|INSTALL|LICENSE|Makefile|UPGRADING)$ { deny all; }
location ~ ^/mail/static.php/plugins/.*/config.inc.php.* { deny all; }
location ~ ^/mail/static.php/plugins/enigma/home($|/.*) { deny all; }
# Redirect /mail to /mail/
location = /mail {
return 301 /mail/;
}
location = /mail/ {
alias /opt/www/roundcubemail/public_html/;
index index.php;
}
location ~ ^/mail/static.php/(.*) {
include /etc/nginx/templates/hsts.tmpl;
alias /opt/www/roundcubemail/$1;
}
location ~ ^/mail/(.*\.php)$ {
include /etc/nginx/templates/hsts.tmpl;
include /etc/nginx/templates/fastcgi_php.tmpl;
fastcgi_param SCRIPT_FILENAME /opt/www/roundcubemail/public_html/$1;
}
5.2 Edit the subdomain template (if used)
sudo nano /etc/nginx/templates/roundcube-subdomain.tmpl
Replace with:
# Block direct access to directories and files.
location ~ ^/(SQL|bin|config|installer|logs|temp|vendor)/ { deny all; }
location ~ ^/(.*\.md|composer\.*|INSTALL|LICENSE|Makefile|UPGRADING)$ { deny all; }
location ~ ^/plugins/.*/config.inc.php.* { deny all; }
location ~ ^/plugins/enigma/home($|/.*) { deny all; }
# Block access via public_html/static.php
location ~ ^/static.php/(SQL|bin|config|installer|logs|temp|vendor)/ { deny all; }
location ~ ^/static.php/(.*\.md|composer\.*|INSTALL|LICENSE|Makefile|UPGRADING)$ { deny all; }
location ~ ^/static.php/plugins/.*/config.inc.php.* { deny all; }
location ~ ^/static.php/plugins/enigma/home($|/.*) { deny all; }
location / {
root /opt/www/roundcubemail/public_html;
index index.php index.html;
include /etc/nginx/templates/hsts.tmpl;
}
location ~ ^/static.php/(.*) {
include /etc/nginx/templates/hsts.tmpl;
alias /opt/www/roundcubemail/$1;
}
location ~ ^/(.*\.php)$ {
include /etc/nginx/templates/hsts.tmpl;
include /etc/nginx/templates/fastcgi_php.tmpl;
fastcgi_param SCRIPT_FILENAME /opt/www/roundcubemail/public_html/$1;
}
5.3 Test and reload Nginx
sudo nginx -t
sudo systemctl reload nginx
Step 6: Update iRedMail to 1.8.2
echo "1.8.2" | sudo tee /etc/iredmail-release
Step 7: Upgrade Roundcube to 1.7.1
cd /root
wget https://github.com/roundcube/roundcubemail/releases/download/1.7.1/roundcubemail-1.7.1-complete.tar.gz
tar xzf roundcubemail-1.7.1-complete.tar.gz
# Enable system() for the upgrade
sudo sed -i 's/disable_functions =.*/disable_functions = exec,passthru,shell_exec,proc_open,popen/' /etc/php.ini
sudo systemctl restart php-fpm
cd roundcubemail-1.7.1
echo "y" | sudo ./bin/installto.sh /opt/www/roundcubemail
# Re-disable system()
sudo sed -i 's/disable_functions =.*/disable_functions = exec,passthru,shell_exec,system,proc_open,popen/' /etc/php.ini
sudo systemctl restart php-fpm
Step 8: Fix Permissions (The Most Critical Step)
This step is often overlooked and causes the “Oops… something went wrong” error.
# Stop services temporarily
sudo systemctl stop nginx php-fpm
# Rename directory to match version (cleaner)
sudo mv /opt/www/roundcubemail-1.6.15 /opt/www/roundcubemail-1.7.1 2>/dev/null
# Fix symlink
sudo rm -f /opt/www/roundcubemail
sudo ln -s /opt/www/roundcubemail-1.7.1 /opt/www/roundcubemail
# Set ownership: root for application files
sudo chown -R root:root /opt/www/roundcubemail-1.7.1
# Set nginx ownership for writeable directories
sudo chown -R nginx:nginx /opt/www/roundcubemail-1.7.1/logs
sudo chown -R nginx:nginx /opt/www/roundcubemail-1.7.1/temp
# Set correct file permissions
sudo find /opt/www/roundcubemail-1.7.1 -type d -exec chmod 755 {} \;
sudo find /opt/www/roundcubemail-1.7.1 -type f -exec chmod 644 {} \;
# Reapply write permissions to logs/temp
sudo chmod 755 /opt/www/roundcubemail-1.7.1/logs
sudo chmod 755 /opt/www/roundcubemail-1.7.1/temp
# Ensure config is readable
sudo chmod 644 /opt/www/roundcubemail-1.7.1/config/config.inc.php
# Restart services
sudo systemctl start nginx php-fpm
Step 9: Verify the Upgrade
# Check versions
echo "iRedMail: $(cat /etc/iredmail-release)"
head -5 /opt/www/roundcubemail/index.php | grep Version
# Check symlink
ls -la /opt/www/roundcubemail
# Check critical permissions
ls -ld /opt/www/roundcubemail-1.7.1/logs
ls -ld /opt/www/roundcubemail-1.7.1/temp
sudo -u nginx cat /opt/www/roundcubemail/config/config.inc.php > /dev/null && echo "✅ Config readable by nginx"
# Check PHP security
php -r "echo function_exists('system') ? '⚠️ system() enabled' : '✅ system() disabled';"
Step 10: Test Webmail
- Clear your browser cache (Ctrl+Shift+Delete)
- Navigate to
https://mail.yourdomain.com/mail/ - Log in with a test user
- Verify the footer shows Roundcube Webmail 1.7.1
- Send and receive a test email
Common Pitfalls & Solutions
Pitfall 1: “Oops… something went wrong!” after upgrade
Cause: Config file not readable by nginx
Solution:
sudo chmod 644 /opt/www/roundcubemail/config/config.inc.php
sudo systemctl restart php-fpm nginx
Pitfall 2: “Config file is not readable” warning in logs
Cause: Ownership changed during upgrade
Solution:
sudo chown -R root:root /opt/www/roundcubemail-1.7.1
sudo chown -R nginx:nginx /opt/www/roundcubemail-1.7.1/logs
sudo chown -R nginx:nginx /opt/www/roundcubemail-1.7.1/temp
Pitfall 3: Database connection error
Cause: Roundcube can’t read database credentials
Solution:
# Check config file permissions
ls -la /opt/www/roundcubemail/config/config.inc.php
# Should be -rw-r--r--
# Verify database credentials
grep -E "db_dsnw|db_user|db_pass" /opt/www/roundcubemail/config/config.inc.php
Pitfall 4: Nginx 404 or 403 errors
Cause: Old Nginx configuration still pointing to old directory structure
Solution: Verify Nginx templates were updated correctly (Step 5)
sudo nginx -t
sudo systemctl reload nginx
Pitfall 5: PHP system() still enabled after upgrade
Cause: The re-disable step was skipped
Solution:
sudo sed -i 's/disable_functions =.*/disable_functions = exec,passthru,shell_exec,system,proc_open,popen/' /etc/php.ini
sudo systemctl restart php-fpm
Pitfall 6: Symlink points to wrong directory
Cause: Directory wasn’t renamed
Solution:
sudo rm -f /opt/www/roundcubemail
sudo ln -s /opt/www/roundcubemail-1.7.1 /opt/www/roundcubemail
Verification Checklist
Copy this checklist and mark off each item as you complete it:
Pre-Upgrade
- [ ] Full backups created (files + database)
- [ ] Current iRedMail version verified (1.7.4)
- [ ] Current Roundcube version noted
- [ ] PHP version confirmed (8.3+ for Rocky Linux 10.1)
During Upgrade
- [ ] iRedMail 1.8.0 update applied
- [ ] Roundcube 1.6.15 upgrade completed
- [ ] Nginx templates replaced with new content
- [ ]
nginx -tpasses - [ ] iRedMail 1.8.2 update applied
- [ ] Roundcube 1.7.1 upgrade completed
Post-Upgrade
- [ ] PHP
system()re-disabled - [ ] File ownership corrected (
root:rootwithnginx:nginxfor logs/temp) - [ ] Symlink updated correctly
- [ ] Config file readable by nginx
- [ ] Services restarted
- [ ] Webmail accessible
- [ ] Roundcube footer shows 1.7.1
- [ ] Email send/receive works
FAQ
Q: Can I skip upgrading to 1.8.0 and go directly to 1.8.2?
A: No. The database schema changes in 1.8.0 are required before upgrading to 1.8.2. Skipping will cause database errors.
Q: Why does my directory still say roundcubemail-1.6.15 but webmail shows 1.7.1?
A: The installto.sh script upgrades files in place. The directory name doesn’t automatically change. You can rename it as shown in Step 8.
Q: I’m on CentOS 7. Will this guide work?
A: Partially. CentOS 7 has PHP 5.4, which is not compatible with Roundcube 1.7+. You’ll need to stick with Roundcube 1.5.2 as noted in the official iRedMail documentation.
Q: My webmail shows a white screen after upgrade. What do I do?
A: Check PHP-FPM:
sudo systemctl status php-fpm
sudo tail -50 /var/log/php-fpm/error.log
sudo tail -50 /opt/www/roundcubemail/logs/errors.log
Q: How long does this upgrade take?
A: 15-20 minutes for the actual upgrade, plus backup time.
Q: Will my users lose any data?
A: No. The upgrade preserves all emails, contacts, and settings. The database schema is updated, not replaced.
Q: Can I downgrade if something goes wrong?
A: Only from your backups. Never attempt to downgrade without restoring from backup.
Q: Do I need to upgrade iRedAdmin separately?
A: iRedAdmin is upgraded automatically when you upgrade iRedMail.
The Complete Upgrade Script
Save this as upgrade-iredmail.sh and run it on your server:
#!/bin/bash
# Complete iRedMail Upgrade Script 1.7.4 → 1.8.2
# For Rocky Linux 10.1 / AlmaLinux 10.1
set -e
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
DOMAIN="mail.yourdomain.com" # CHANGE THIS
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}iRedMail Upgrade Script v2.0${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e "Domain: ${YELLOW}$DOMAIN${NC}"
# Backup
BACKUP_DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p /root/backup_$BACKUP_DATE
sudo cp -r /opt/www/roundcubemail "/root/backup_$BACKUP_DATE/"
sudo cp /etc/nginx/templates/roundcube.tmpl "/root/backup_$BACKUP_DATE/" 2>/dev/null
sudo mysqldump -u root -p roundcubemail > "/root/backup_$BACKUP_DATE/roundcubemail_backup.sql"
echo -e "${GREEN}✓ Backups saved${NC}"
# Update to 1.8.0
echo "1.8.0" | sudo tee /etc/iredmail-release
# Upgrade Roundcube to 1.6.15
cd /root
wget -q https://github.com/roundcube/roundcubemail/releases/download/1.6.15/roundcubemail-1.6.15-complete.tar.gz
tar xzf roundcubemail-1.6.15-complete.tar.gz
sudo sed -i 's/disable_functions =.*/disable_functions = exec,passthru,shell_exec,proc_open,popen/' /etc/php.ini
sudo systemctl restart php-fpm
cd roundcubemail-1.6.15
echo "y" | sudo ./bin/installto.sh /opt/www/roundcubemail
sudo sed -i 's/disable_functions =.*/disable_functions = exec,passthru,shell_exec,system,proc_open,popen/' /etc/php.ini
sudo systemctl restart php-fpm
# Update Nginx templates (full content here - see Step 5)
# Update to 1.8.2
echo "1.8.2" | sudo tee /etc/iredmail-release
# Upgrade Roundcube to 1.7.1
cd /root
wget -q https://github.com/roundcube/roundcubemail/releases/download/1.7.1/roundcubemail-1.7.1-complete.tar.gz
tar xzf roundcubemail-1.7.1-complete.tar.gz
sudo sed -i 's/disable_functions =.*/disable_functions = exec,passthru,shell_exec,proc_open,popen/' /etc/php.ini
sudo systemctl restart php-fpm
cd roundcubemail-1.7.1
echo "y" | sudo ./bin/installto.sh /opt/www/roundcubemail
sudo sed -i 's/disable_functions =.*/disable_functions = exec,passthru,shell_exec,system,proc_open,popen/' /etc/php.ini
sudo systemctl restart php-fpm
# Fix permissions
sudo systemctl stop nginx php-fpm
sudo mv /opt/www/roundcubemail-1.6.15 /opt/www/roundcubemail-1.7.1 2>/dev/null
sudo rm -f /opt/www/roundcubemail
sudo ln -s /opt/www/roundcubemail-1.7.1 /opt/www/roundcubemail
sudo chown -R root:root /opt/www/roundcubemail-1.7.1
sudo chown -R nginx:nginx /opt/www/roundcubemail-1.7.1/logs
sudo chown -R nginx:nginx /opt/www/roundcubemail-1.7.1/temp
sudo find /opt/www/roundcubemail-1.7.1 -type d -exec chmod 755 {} \;
sudo find /opt/www/roundcubemail-1.7.1 -type f -exec chmod 644 {} \;
sudo chmod 755 /opt/www/roundcubemail-1.7.1/logs
sudo chmod 755 /opt/www/roundcubemail-1.7.1/temp
sudo chmod 644 /opt/www/roundcubemail-1.7.1/config/config.inc.php
sudo systemctl start nginx php-fpm
# Restart all services
sudo systemctl restart nginx php-fpm postfix dovecot
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}Upgrade Complete!${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e "iRedMail: $(cat /etc/iredmail-release)"
echo -e "Roundcube: $(head -5 /opt/www/roundcubemail/index.php | grep Version)"
echo -e "Backup: /root/backup_$BACKUP_DATE"
Conclusion
What You’ve Accomplished
| Before | After |
|---|---|
| iRedMail 1.7.4 | iRedMail 1.8.2 |
| Roundcube 1.6.15 | Roundcube 1.7.1 |
| Old Nginx structure | Modern public_html/ structure |
| Mixed file ownership | Clean, secure permissions |
| Potential PHP security gaps | PHP system() properly disabled |
Key Takeaways
- Always backup first – This saved us multiple times
- Don’t skip the intermediate version – 1.8.0 is required before 1.8.2
- Update Nginx templates – Roundcube 1.7’s
public_html/structure requires it - Fix permissions after upgrade – This is the #1 cause of “white screen” errors
- Re-disable PHP
system()– Security matters
Real-World Testing
This guide was tested on:
- ✅ Rocky Linux 10.1 (production mail server)
- ✅ Two separate iRedMail installations
- ✅ Multiple upgrade attempts (to document all edge cases)
- ✅ Both IPv4 and IPv6 configurations
Support
If you found this guide helpful:
- ⭐ Star this post
- 📤 Share it with others
- 💬 Leave a comment below
Need professional help with your iRedMail server? Contact us for consulting services.