Mailcow guide series: Part 7 of 7. Start with Part 1.
Series index: Part 1 contains the full table of contents.
This is Part 7 of the Mailcow self-hosted email series. An email server is not recovered merely because its web page opens. You need a recent copy of mailbox data, its database, configuration, DNS records, and credentials. Make a backup before you need one.
Put backups somewhere else
Mailcow’s built-in backup helper collects its data components. Store the result on a mounted external disk or protected remote backup target, not only on the Mailcow VM. A backup on the same disk disappears with the disk. Restrict access to backups: they contain private email and sensitive configuration.
Assuming /mnt/mailcow-backups is a mounted, protected backup destination:
sudo mkdir -p /mnt/mailcow-backups
sudo chmod 700 /mnt/mailcow-backups
cd /opt/mailcow-dockerized
MAILCOW_BACKUP_LOCATION=/mnt/mailcow-backups ./helper-scripts/backup_and_restore.sh backup all --delete-days 30
Set a schedule only after one manual backup succeeds. Open the root user’s crontab with sudo crontab -e, then add this entry for 04:05 daily:
5 4 * * * cd /opt/mailcow-dockerized && MAILCOW_BACKUP_LOCATION=/mnt/mailcow-backups /opt/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup all --delete-days 30
The example keeps 30 days of backups according to Mailcow’s helper. Confirm the destination mount is present before relying on a scheduled backup. Also protect a copy of mailcow.conf, your DNS zone export, firewall rules, host name/IP notes, and a password-manager recovery plan. Keep configuration backups encrypted and permissions restricted; do not put them in Git or a public cloud bucket.
Mailcow’s backup guide lists components and options. Do a restore drill on a separate test machine before you depend on a backup for production.
Routine checks and recovery commands
SSH to the server and run these from the Mailcow directory:
cd /opt/mailcow-dockerized
docker compose ps
docker compose logs --tail=100 postfix-mailcow
docker compose logs --tail=100 dovecot-mailcow
docker compose logs --tail=100 nginx-mailcow acme-mailcow
ps shows whether containers are running. The logs show recent errors for mail delivery, mailbox access, web access, and certificates. A running container does not prove that DNS, TLS, mailbox login, or relay delivery works.
For a planned restart after changing Mailcow’s supported configuration:
cd /opt/mailcow-dockerized
docker compose up -d
For routine upgrades, make and verify a backup first, then use Mailcow’s update script:
cd /opt/mailcow-dockerized
./update.sh --check
./update.sh
Read the update prompt and release notes before confirming. Do not run docker compose down -v: the -v option removes persistent volumes and can erase mail data. Mailcow documents updates and rollback considerations.
Restore onto a replacement VM
If the old server is lost, first create a replacement Ubuntu VM and network rules. Give it a stable public IP and install the same Mailcow architecture/version as appropriate. Copy the protected mailcow.conf into the new /opt/mailcow-dockerized directory, check that the host name and volume settings match the original, then start the clean Mailcow stack. Do not restore into a random running production server.
Mount the backup destination, then start the interactive restore from the new Mailcow installation:
cd /opt/mailcow-dockerized
MAILCOW_BACKUP_LOCATION=/mnt/mailcow-backups ./helper-scripts/backup_and_restore.sh restore
Choose the correct dated backup and the components to restore. The full all backup includes the Mailcow components; restoration can take time. Mailcow requires the replacement installation to be initialized and running before restore. Read its restore guide carefully, particularly if changing CPU architecture or migrating an older installation.
After restoring, confirm the services, domain, mailbox data, and TLS certificates. If the replacement has a different IP, update the Route 53 A record, verify the MX target still resolves, and request a matching PTR from the IP provider. Do not change the MX until the replacement can receive mail on port 25 and send a test through the configured relay.
If the administrator password is lost
On the Mailcow host, check the password-reset instructions for your installed Mailcow version. If that version includes the helper script, run it from the installation directory:
cd /opt/mailcow-dockerized
./helper-scripts/mailcow-reset-admin.sh
Follow the prompt, save the generated password in a password manager, sign in, and immediately set a new administrator password and two-factor authentication. Use Mailcow’s current password reset instructions for the version you have installed.
Final recovery checklist
- Can you log in to the cloud console and the server over SSH?
- Do you know the domain registrar, Route 53 hosted zone, IP address, and PTR request process?
- Is there a recent backup on storage independent of the Mailcow VM?
- Can you access the encrypted config copy and the password manager?
- Have you restored the backup on a test server at least once?
If any answer is no, write down and fix that gap now. A tested restore plan is what turns a crashed server into an inconvenience instead of lost mail.
Official references: Mailcow backup, restore, updates, admin password reset.