# 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`, and `rsync` On NixOS or another machine with Nix: ```sh nix-shell -p borgbackup openssh postgresql rsync ``` ## Prepare Borg Access Copy the Borg SSH key into a local recovery directory: ```sh 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: ```sh 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: ```sh read -rsp 'Borg passphrase: ' BORG_PASSPHRASE export BORG_PASSPHRASE echo ``` ## Extract a Backup List available archives: ```sh 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 `/`. ```sh 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`: ```sh 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: ```sh sudo systemctl stop discourse.service sudo systemctl start postgresql.service ``` Restore `/var/lib/discourse`: ```sh sudo "$RSYNC" -a --delete ./var/lib/discourse/ /var/lib/discourse/ sudo chown -R discourse:discourse /var/lib/discourse ``` Replace the `discourse` PostgreSQL database: ```sh 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: ```sh sudo systemctl start discourse.service ``` ## Verify Check the service and recent logs: ```sh 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: ```text https://discourse.torahimderecheretz.com ```