# TIDE Forum State and Database Recovery This restores the Discourse state and database from the BorgBase backup configured by the TIDE NixOS module. It replaces the current 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 the TIDE NixOS module - 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, 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 TIDE module has 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 restored, open: ```text https://discourse.torahimderecheretz.com ```