# Restores a Siftlode Postgres dump created by backup.ps1 into the running db container. # Usage: .\scripts\restore.ps1 backups\siftlode-YYYYMMDD-HHMMSS.dump # # Restoring the database does NOT restore the secrets that decrypt it. If this dump is from an # instance with a different TOKEN_ENCRYPTION_KEY than the current .env, the encrypted sysconfig # values and refresh tokens will not be readable. See docs/self-hosting.md § Backups. param([Parameter(Mandatory = $true)][string]$DumpFile) $ErrorActionPreference = "Stop" # See backup.ps1: the dump travels with `docker compose cp`, never through the PowerShell pipeline, # which corrupts binary on 5.1 and cannot express `-Encoding Byte` at all on 7. $remote = "/tmp/siftlode-restore.dump" if (-not $env:COMPOSE_FILE -and -not (Test-Path "docker-compose.yml") -and (Test-Path "docker-compose.selfhost.yml")) { $env:COMPOSE_FILE = "docker-compose.selfhost.yml" } $user = if ($env:POSTGRES_USER) { $env:POSTGRES_USER } else { "siftlode" } $dbname = if ($env:POSTGRES_DB) { $env:POSTGRES_DB } else { "siftlode" } if (-not (Test-Path $DumpFile)) { throw "Dump file not found: $DumpFile" } docker compose cp $DumpFile "db:$remote" if ($LASTEXITCODE -ne 0) { throw "RESTORE FAILED — could not copy the dump into the container (exit $LASTEXITCODE)." } docker compose exec -T db pg_restore -U $user -d $dbname --clean --if-exists $remote $restoreCode = $LASTEXITCODE docker compose exec -T db rm -f $remote 2>$null # pg_restore exits non-zero for ignorable warnings too (--clean --if-exists on a fresh database # reports every missing object it tried to drop), so a non-zero code is reported as "check this", # not swallowed and not dressed up as success. if ($restoreCode -ne 0) { throw "pg_restore reported errors while restoring $DumpFile (exit $restoreCode) — read the output above before treating this instance as restored." } Write-Output "Restored $DumpFile"