3.3 KiB
Discourse State and Database Recovery
This restores Discourse from the BorgBase backup configured in discourse.nix.
It replaces the current Discourse state directory and PostgreSQL database with
the selected Borg archive.
The backup contains:
/var/lib/discourse/var/backup/discourse/discourse.dump
Requirements
- BorgBase repo URL:
ssh://oas17j8p@oas17j8p.repo.borgbase.com/./repo - Decrypted Borg SSH private key from the flash drive
- Borg repository passphrase from the flash drive
- A target server that has already been switched to this NixOS config
- A shell with
borg,openssh,postgresql, andrsync
On NixOS or another machine with Nix:
nix-shell -p borgbackup openssh postgresql rsync
Prepare Borg Access
Copy the Borg SSH key into a local recovery directory:
mkdir -p ~/borg-recovery/discourse
cp /path/to/flash/borg-private-key ~/borg-recovery/discourse/borg-private-key
chmod 600 ~/borg-recovery/discourse/borg-private-key
Set the Borg connection environment:
export BORG_REPO='ssh://oas17j8p@oas17j8p.repo.borgbase.com/./repo'
export BORG_RSH='ssh -i ~/borg-recovery/discourse/borg-private-key -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new'
Read the Borg passphrase without showing it on screen:
read -rsp 'Borg passphrase: ' BORG_PASSPHRASE
export BORG_PASSPHRASE
echo
Extract a Backup
List available archives:
borg list
Choose an archive name from the list, then extract only the Discourse state and
database dump into a temporary directory. Do not extract directly into /.
export ARCHIVE='ARCHIVE_NAME_FROM_BORG_LIST'
mkdir -p ~/borg-recovery/discourse/extract
cd ~/borg-recovery/discourse/extract
borg extract ::$ARCHIVE var/lib/discourse var/backup/discourse/discourse.dump
Restore on the Server
Run these commands from ~/borg-recovery/discourse/extract on the target
server. They assume the NixOS config has already created the discourse user,
postgresql.service, and discourse-postgresql.service.
Capture absolute tool paths so they still work through sudo:
RSYNC="$(command -v rsync)"
PSQL="$(command -v psql)"
DROPDB="$(command -v dropdb)"
PG_RESTORE="$(command -v pg_restore)"
Stop Discourse and make sure PostgreSQL is running:
sudo systemctl stop discourse.service
sudo systemctl start postgresql.service
Restore /var/lib/discourse:
sudo "$RSYNC" -a --delete ./var/lib/discourse/ /var/lib/discourse/
sudo chown -R discourse:discourse /var/lib/discourse
Replace the discourse PostgreSQL database:
sudo -u postgres "$PSQL" -d postgres -v ON_ERROR_STOP=1 \
-c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'discourse';"
sudo -u postgres "$DROPDB" --if-exists discourse
sudo systemctl restart discourse-postgresql.service
sudo -u postgres "$PG_RESTORE" \
--exit-on-error \
--no-owner \
--role=discourse \
--dbname=discourse \
./var/backup/discourse/discourse.dump
sudo systemctl restart discourse-postgresql.service
Start Discourse:
sudo systemctl start discourse.service
Verify
Check the service and recent logs:
sudo systemctl status discourse.service --no-pager
sudo journalctl -u discourse.service -b --no-pager -n 100
If networking and DNS are already restored, open:
https://discourse.torahimderecheretz.com