Files

53 lines
2.0 KiB
PowerShell

param(
[Parameter(Mandatory = $true)][string]$Archive,
[string]$ComposeFile = "compose.yaml",
[string]$DataPath = "./data",
[switch]$Force
)
$ErrorActionPreference = "Stop"
$resolvedArchive = (Resolve-Path -LiteralPath $Archive).Path
$target = [System.IO.Path]::GetFullPath($DataPath)
$targetRoot = [System.IO.Path]::GetPathRoot($target).TrimEnd('\', '/')
if ($target.TrimEnd('\', '/') -eq $targetRoot) {
throw "Refusing to restore into a filesystem root."
}
$checksumFile = "$resolvedArchive.sha256"
if (Test-Path -LiteralPath $checksumFile) {
$expected = ((Get-Content -LiteralPath $checksumFile -TotalCount 1) -split '\s+')[0]
$actual = (Get-FileHash -Algorithm SHA256 -LiteralPath $resolvedArchive).Hash.ToLowerInvariant()
if ($actual -ne $expected.ToLowerInvariant()) {
throw "Backup checksum verification failed."
}
}
New-Item -ItemType Directory -Force -Path $target | Out-Null
if ((Get-ChildItem -Force -LiteralPath $target | Select-Object -First 1) -and -not $Force) {
throw "Target data directory is not empty. Re-run with -Force after verifying the archive."
}
docker compose -f $ComposeFile stop | Out-Host
if ($LASTEXITCODE -ne 0) {
throw "Unable to stop MemRelay services."
}
try {
if ($Force) {
Get-ChildItem -Force -LiteralPath $target | Remove-Item -Recurse -Force
}
$archiveDirectory = [System.IO.Path]::GetDirectoryName($resolvedArchive)
$archiveName = [System.IO.Path]::GetFileName($resolvedArchive)
& docker run --rm --user "1000:1000" `
--mount "type=bind,source=$archiveDirectory,target=/backup,readonly" `
--mount "type=bind,source=$target,target=/target" `
alpine:3.22 tar -xzf "/backup/$archiveName" -C /target
if ($LASTEXITCODE -ne 0) {
throw "Unable to extract the backup archive."
}
Write-Host "Restore completed: $target"
}
finally {
docker compose -f $ComposeFile up -d | Out-Host
if ($LASTEXITCODE -ne 0) {
Write-Error "Restore finished, but MemRelay services could not be started."
}
}