Add backup and restore scripts
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
#requires -Version 5.1
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$Archive,
|
||||
[switch]$Force
|
||||
)
|
||||
|
||||
$root = Split-Path $PSScriptRoot -Parent
|
||||
if (-not (Test-Path -LiteralPath $Archive -PathType Leaf)) { throw "Backup archive not found: $Archive" }
|
||||
if ((Test-Path (Join-Path $root '.env')) -and -not $Force) {
|
||||
throw 'Refusing to overwrite an existing deployment without -Force.'
|
||||
}
|
||||
|
||||
$staging = Join-Path ([IO.Path]::GetTempPath()) "eternitymail-restore-$([guid]::NewGuid())"
|
||||
New-Item -ItemType Directory -Force -Path $staging | Out-Null
|
||||
try {
|
||||
docker run --rm -v "${Archive}:/backup/archive.tar.gz:ro" -v "${staging}:/restore" alpine:3.21 tar -C /restore -xzf /backup/archive.tar.gz
|
||||
if ($LASTEXITCODE) { throw 'Could not extract backup archive.' }
|
||||
docker run --rm -v "${staging}:/restore:ro" alpine:3.21 sh -c 'cd /restore && sha256sum -c SHA256SUMS'
|
||||
if ($LASTEXITCODE) { throw 'Backup checksum verification failed.' }
|
||||
|
||||
if ($Force) {
|
||||
Push-Location $root
|
||||
docker compose down
|
||||
docker volume rm eternitymail-stalwart-etc eternitymail-stalwart-data eternitymail-stalwart-certs 2>$null
|
||||
docker run --rm -v /opt/eternitymail:/data alpine:3.21 sh -c 'rm -rf /data/roundcube-db /data/roundcube-config'
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
Copy-Item "$staging\.env" (Join-Path $root '.env') -Force
|
||||
$project = (Get-Content (Join-Path $root '.env') | Where-Object { $_ -match '^PROJECT_NAME=' } | Select-Object -First 1) -replace '^PROJECT_NAME=', ''
|
||||
if (-not $project) { $project = 'eternitymail' }
|
||||
foreach ($volume in 'stalwart-etc', 'stalwart-data', 'stalwart-certs') {
|
||||
docker volume create "${project}-${volume}" | Out-Null
|
||||
docker run --rm -v "${project}-${volume}:/destination" -v "${staging}:/restore:ro" alpine:3.21 tar -C /destination -xzf "/restore/volumes/$volume.tar.gz"
|
||||
if ($LASTEXITCODE) { throw "Could not restore volume $volume" }
|
||||
}
|
||||
foreach ($directory in 'roundcube-db', 'roundcube-config') {
|
||||
docker run --rm -v /opt/eternitymail:/data -v "${staging}:/restore:ro" alpine:3.21 sh -c "mkdir -p /data/$directory && tar -C /data/$directory -xzf /restore/bind-mounts/$directory.tar.gz"
|
||||
if ($LASTEXITCODE) { throw "Could not restore $directory" }
|
||||
}
|
||||
Push-Location $root
|
||||
docker compose up -d
|
||||
Pop-Location
|
||||
Write-Output 'Restore complete. Verify with: docker compose ps'
|
||||
} finally {
|
||||
Pop-Location -ErrorAction SilentlyContinue
|
||||
Remove-Item -Recurse -Force $staging -ErrorAction SilentlyContinue
|
||||
}
|
||||
Reference in New Issue
Block a user