Backups in CHT
Which data to backup when hosting the CHT
Assuming you have a CHT server based off the Docker Hosting guide, the two main sets of files that need backing up are:
- CouchDB directory:
/home/ubuntu/cht/couchdb .envfile:/home/ubuntu/cht/upgrade-service/.env
If you changed these paths during install, please be sure to update the paths accordingly below.
Backups should be sure to follow the 3-2-1 rule:
There should be at least 3 copies of the data, stored on 2 different types of storage media, and one copy should be kept offsite, in a remote location. - Wikipedia
Manual backup
When a backup is needed in the short term, an ad hoc backup can suffice:
Create Directory
Create a backup directory called backup in the cht directory:
mkdir /home/ubuntu/cht/backupBackup .env and CouchDB
Copy the .env and CouchDB files to the newly created directory:
cp --archive /home/ubuntu/cht/upgrade-service/.env /home/ubuntu/cht/backup/
cp --archive /home/ubuntu/cht/couchdb /home/ubuntu/cht/backup/Verify .env
A critical part of a backup is verifying both that the backup was made to the destination, but also that a restore works. See below for restore, but to verify files were copied we can first check the .env files are identical with md5sum:
md5sum /home/ubuntu/cht/upgrade-service/.env /home/ubuntu/cht/backup/.envEnsure the resulting IDs match as seen here:
d0f3db77002732fafded733e4b4f85f0 /home/ubuntu/cht/upgrade-service/.env
d0f3db77002732fafded733e4b4f85f0 /home/ubuntu/cht/backup/.envVerify CouchDB
Check that the file count and directory sizes of couchdb directories matches as well by running these 4 lines:
echo "CouchDB Prod";du -h -d1 /home/ubuntu/cht/couchdb
echo "CouchDB Backup";du -h -d1 /home/ubuntu/cht/backup/couchdb
echo "CouchDB Prod";ls -R /home/ubuntu/cht/backup/couchdb |wc -l
echo "CouchDB Backup";ls -R /home/ubuntu/cht/couchdb |wc -lRunning the lines should show a similar output to below. Be sure that Prod and Backup sections exactly match:
CouchDB Prod
0 /home/ubuntu/cht/couchdb/.delete
4.7M /home/ubuntu/cht/couchdb/shards
1.2M /home/ubuntu/cht/couchdb/.shards
5.9M /home/ubuntu/cht/couchdb
CouchDB Backup
0 /home/ubuntu/cht/backup/couchdb/.delete
4.7M /home/ubuntu/cht/backup/couchdb/shards
1.2M /home/ubuntu/cht/backup/couchdb/.shards
5.9M /home/ubuntu/cht/backup/couchdb
CouchDB Prod
174
CouchDB Backup
174Automated backup
Manual backups are good a quick one off. For ongoing backups, automation that runs regularly is key for success. Humans often forget to run tasks like backup but computers will never forget. This guide uses borg software, but administrators should use the backup software they’re most familiar with.
This example assumes a server called backup.server exists with a borg user on it. Additionally, borg should be installed on both the CHT server and the backup server.
Backing up to a remote server means that if your production server gets entirely deleted, your backups are safe.
Verify SSH connection
From your CHT Server, make sure your SSH keys are shared such that you can transparently SSH to your remote server and that borg executable is installed and available to your user:
ssh borg@backup.server "borg --version;whoami;date;hostname"This should show similar output as below:
borg 1.2.8
borg
Mon Oct 20 09:31:11 PM UTC 2025
backup-serverCreate a new borg repository
On your CHT server, create a new repository cht on the backup.server server. Be sure to replace PASSWORD with your real password here and all subsequent calls:
BORG_PASSPHRASE='PASSWORD' borg init --encryption \
repokey-blake2 borg@backup.server:chtManually run borg
To ensure our repository is working correctly, manually call borg from your CHT server:
BORG_PASSPHRASE='PASSWORD' borg create borg@backup.server:cht::$(date "+%y-%m-%d_%H:%M:%S") /home/ubuntu/cht/couchdb /home/ubuntu/cht/upgrade-service/.envVerify backup
On your backup server, verify the manually run backup was successful:
BORG_PASSPHRASE='PASSWORD' borg list /home/borg/chtThis will show the backup you just ran:
25-10-20_15:21:04 Mon, 2025-10-20 22:21:05 [a7698bb7275e3e947234e3d25c3b2084c14b5fd4dd5313f6bc1fef38ecbbca41]By passing in the name of the backup 25-10-20_15:21:04 to the list call, we can see all the files in the backup:
BORG_PASSPHRASE='PASSWORD' borg list /home/borg/cht::25-10-20_15:21:04Here is a truncated version of the output
drwxr-xr-x 5984 5984 0 Mon, 2025-10-20 20:15:56 home/ubuntu/cht/couchdb
drwxr-xr-x 5984 5984 0 Mon, 2025-10-20 20:15:57 home/ubuntu/cht/couchdb/.delete
-rw-r--r-- 5984 5984 8389 Mon, 2025-10-20 20:15:50 home/ubuntu/cht/couchdb/_nodes.couch
-rw-r--r-- 5984 5984 49361 Mon, 2025-10-20 20:21:56 home/ubuntu/cht/couchdb/_dbs.couch
drwxr-xr-x 5984 5984 0 Mon, 2025-10-20 20:15:54 home/ubuntu/cht/couchdb/shards
drwxr-xr-x 5984 5984 0 Mon, 2025-10-20 20:21:56 home/ubuntu/cht/couchdb/shards/15555555-2aaaaaa9
...
-rw-r--r-- ubuntu ubuntu 932 Mon, 2025-10-20 20:15:37 home/ubuntu/cht/upgrade-service/.envCreate a cron job
Now it’s time to automate the backup so it runs without human intervention. Open a cron editor on your CHT production server:
crontab -eEnter in this at the bottom of the file:
# m h dom mon dow command
0 */4 * * * BORG_PASSPHRASE='PASSWORD' borg create borg@backup.server:cht::$(date "+%y-%m-%d_%H:%M:%S") /home/ubuntu/cht/couchdb /home/ubuntu/cht/upgrade-service/.envListing your crontab should show the above command:
crontab -lVerify cron job
Wait 24 hours. On the backup server, when you call borg list... you should see many entries. Be sure to inspect them to verify that everything is as it should be.
Optional 1: Prune backups
With the current set up, backups will grow forever in size eventually filling the disk of your backup server. To avoid this, you can set up a cronjob on the backup server to run once per day. This call will keep the past 10 days, keep 4 end of weeks and 1 monthly:
BORG_PASSPHRASE='PASSWORD' borg prune \
--list --keep-within=10d --keep-weekly=4 \
--keep-monthly=-1 /home/borg/chtSee the prune docs for more information
Optional 2: Only allow append
As configured above, an attacker who gained access to your production CHT server, could delete your productoin data and then use borg to remotely delete all your backups.
To prevent this, on your backup server, edit the /home/borg/.ssh/authorized_keys file to set a forced command. Prepend this before the SSH Key for your borg user. Note that ssh-ed25519 AAA... is the truncated SSH key, be sure to leave the entire SSH key in place:
command="borg serve --append-only --restrict-to-path /home/borg/cht/",no-pty,no-agent-forwarding,no-port-forwarding,no-X11-forwarding,no-user-rc ssh-ed25519 AAA...Restore
The restore process involves setting up the CHT, restoring the files from backup, moving the files into position and restarting the CHT.
Find correct backup
For users of borg, list your backups and find the one you want to use:
BORG_PASSPHRASE='PASSWORD' borg list /home/borg/chtThe left column is the backup name and right column is the date and hash of the backup. In this case, we’ll use 25-10-21_11:15:24
25-10-20_15:21:04 Mon, 2025-10-20 22:21:05 [a7698bb7275e3e947234e3d25c3b2084c14b5fd4dd5313f6bc1fef38ecbbca41]
25-10-21_15:21:56 Tue, 2025-10-21 15:21:56 [26f1f9af11c11027f828f6eab30061e01fb7e69e1cafb3e2eee71f3260546b53]
25-10-22_01:15:04 Wed, 2025-10-22 01:15:04 [b9e083d0175ea0253644359508c3df1066d49c0e3ad44d97009aac0ce9808b37]/home/ubuntu/cht/backup/ as the location of the backup.Restore to staging
For users of borg, restore with this command. Be sure to replace the name of your repository as needed:
mkdir /home/ubuntu/cht/restore
cd /home/ubuntu/cht/restore
BORG_PASSPHRASE='PASSWORD' borg extract \
--list \
borg@backup.server:cht::25-10-21_11:15:24
mv home/ubuntu/cht/couchdb .
mv home/ubuntu/cht/upgrade-service/.env
rm -r homeManually run backups will use the copy command to copy the files from the backup to the restore directories:
mkdir /home/ubuntu/cht/restore
cd /home/ubuntu/cht/restore
cp --archive /home/ubuntu/cht/backup/couchdb /home/ubuntu/cht/backup/.env .Once the files are restored, manually inspect them to ensure they’re correct and ready to be put into production
Stop CHT, Restore and start
Stop all the containers:
cd /home/ubuntu/cht/compose
docker compose -f cht-core.yml -f cht-couchdb.yml --env-file ../upgrade-service/.env -p cht stopCopy the staged files into place:
cd /home/ubuntu/cht/restore
cp --archive .env /home/ubuntu/cht/upgrade-service/.env
sudo cp --archive couchdb/* /home/ubuntu/cht/couchdb/.Start up the CHT:
cd /home/ubuntu/cht/upgrade-service
docker compose restartDid this documentation help you ?