Your database holds all your mail, contacts, Screener decisions and secrets. A backup of it, plus your SESSION_SECRET and, if you encrypt backups, your backup key, is everything you need to rebuild imbox on a new machine. Attachments are fetched from your mail provider on demand, so a backup stays small.
A backup is not enough on its own
Keep SESSION_SECRET with your backups, in a different place from the server. A restored database with a different secret can't decrypt saved mailbox passwords, AI keys or two-factor secrets.
Backups hold all of your mail
A plain dump can be read by anyone who gets a copy. Encrypt backups so the server never holds a key that opens them. See Encrypt them.
What happens on its own
A server set up with the script makes a backup every night at 03:17 server time. Each is a compressed dump in /var/backups/imbox, named imbox-YYYYMMDDTHHMMSSZ.sql.gz, or .sql.gz.age once you encrypt them. They are readable only by root. Files older than 14 days are deleted. The log is /var/log/imbox-backup.log.
These live on the same machine, so they protect you from a mistake, not from losing the server. Copy them somewhere else too.
Encrypt them
A plain dump holds everything, so anyone who gets a copy can read your mail. imbox can encrypt each backup with age before it is written. It encrypts to a public key, so the server never holds anything that can open its own backups. Only the matching private key can, and you keep that somewhere else.
-
On your own computer, make a key pair. Install
agefirst (brew install age, orsudo apt-get install age).age-keygen -o imbox-backup.keyIt prints a line starting
Public key: age1.... The file holds the private key. -
Put the private key in a password manager and keep a copy off the server. Without it, encrypted backups can't be opened. Never put it on the server.
-
On the server, add the public key to
/etc/imbox/backup.env:BACKUP_AGE_RECIPIENT=age1...your-public-key -
Run a backup to check. It should say
backup ok (encrypted):sudo imbox-backup
From then on every nightly file ends in .sql.gz.age, and so does the copy sent to S3. If a backup can't be encrypted, for example because age is missing, it fails and says so in the log. It never falls back to a plain file. Without BACKUP_AGE_RECIPIENT a backup still works but the log line says NOT encrypted.
Servers made with the script before this was added need sudo apt-get install age, and the new imbox-backup from deploy/backup.sh.
Copy them off the server
The script installs the AWS command line tool for this. Create /etc/imbox/backup.env:
S3_BUCKET=your-bucket-nameEach night's file is then copied to s3://your-bucket-name/imbox/. The server needs permission to write to the bucket. The simplest way is an IAM role on the instance. If you use keys instead, put them in the same file as export lines:
export AWS_ACCESS_KEY_ID=your-key
export AWS_SECRET_ACCESS_KEY=your-secret
export AWS_DEFAULT_REGION=eu-west-1Run one backup by hand to check it works:
sudo imbox-backupIt prints backup ok: and the file name.
Make a backup now
Before a risky change, take one yourself.
Server:
sudo -u postgres pg_dump imbox | gzip > imbox-backup-$(date +%Y%m%d).sql.gzTo encrypt it as the nightly one is, add age with your public key:
sudo -u postgres pg_dump imbox | gzip | age -r age1...your-public-key > imbox-backup-$(date +%Y%m%d).sql.gz.ageDocker Compose:
docker compose exec -T db pg_dump -U inbox inbox | gzip > inbox-backup-$(date +%Y%m%d).sql.gzRestore
Restoring replaces the whole database with the backup. Anything that arrived after the backup is fetched again from your mail providers at the next sync.
A file ending in .age is encrypted. Decrypt it first with your private key, imbox-backup.key. Do this on a machine you trust, or copy the key to the server only for the restore and delete it after.
age -d -i imbox-backup.key imbox-YYYYMMDDTHHMMSSZ.sql.gz.age > imbox-restore.sql.gzThen restore the .sql.gz file.
Server:
sudo systemctl stop imbox
sudo -u postgres dropdb imbox && sudo -u postgres createdb -O imbox imbox
gunzip -c imbox-restore.sql.gz | sudo -u postgres psql inbox
sudo systemctl start imboxFor a plain nightly file, use /var/backups/imbox/imbox-YYYYMMDDTHHMMSSZ.sql.gz in place of imbox-restore.sql.gz.
Docker Compose:
docker compose stop imbox
docker compose exec -T db dropdb -U inbox inbox
docker compose exec -T db createdb -U inbox inbox
gunzip -c inbox-restore.sql.gz | docker compose exec -T db psql -U inbox inbox
docker compose start imboxThen check curl -s http://127.0.0.1:8787/healthz and sign in.
On a new server
- Do the install on the new machine.
- Before you start the app, put the old
SESSION_SECRETin/etc/imbox/imbox.env. AddBACKUP_AGE_RECIPIENTto/etc/imbox/backup.envagain, with the same public key. - Restore the dump as above.
- Point your domain at the new address.
Test it once
A backup you have never restored is a guess. Once, on a spare machine or a local Docker setup, restore a file, decrypting it with your private key if it is encrypted, and sign in. It takes ten minutes and tells you whether the backup works.