32 lines
1.9 KiB
PowerShell
32 lines
1.9 KiB
PowerShell
#requires -Version 5.1
|
|
param([string]$Destination = (Join-Path (Split-Path $PSScriptRoot -Parent) "backups"))
|
|
|
|
$root = Split-Path $PSScriptRoot -Parent
|
|
$project = (Get-Content (Join-Path $root '.env') | Where-Object { $_ -match '^PROJECT_NAME=' } | Select-Object -First 1) -replace '^PROJECT_NAME=', ''
|
|
if (-not $project) { $project = 'eternitymail' }
|
|
$timestamp = (Get-Date).ToUniversalTime().ToString('yyyyMMddTHHmmssZ')
|
|
$staging = Join-Path ([IO.Path]::GetTempPath()) "$project-backup-$timestamp"
|
|
$archive = Join-Path $Destination "$project-$timestamp.tar.gz"
|
|
|
|
New-Item -ItemType Directory -Force -Path $staging, $Destination | Out-Null
|
|
try {
|
|
Push-Location $root
|
|
docker compose stop
|
|
New-Item -ItemType Directory -Force -Path "$staging\volumes", "$staging\bind-mounts" | Out-Null
|
|
Copy-Item '.env', 'docker-compose.yml' -Destination $staging
|
|
foreach ($volume in 'stalwart-etc', 'stalwart-data', 'stalwart-certs') {
|
|
docker run --rm -v "${project}-${volume}:/source:ro" -v "${staging}:/backup" alpine:3.21 tar -C /source -czf "/backup/volumes/$volume.tar.gz" .
|
|
if ($LASTEXITCODE) { throw "Failed to back up volume $volume" }
|
|
}
|
|
foreach ($directory in 'roundcube-db', 'roundcube-config') {
|
|
docker run --rm -v "/opt/eternitymail/${directory}:/source:ro" -v "${staging}:/backup" alpine:3.21 tar -C /source -czf "/backup/bind-mounts/$directory.tar.gz" .
|
|
if ($LASTEXITCODE) { throw "Failed to back up $directory" }
|
|
}
|
|
docker run --rm -v "${staging}:/backup" alpine:3.21 sh -c 'cd /backup && sha256sum .env docker-compose.yml volumes/*.tar.gz bind-mounts/*.tar.gz > SHA256SUMS && tar -czf /backup/archive.tar.gz .env docker-compose.yml volumes bind-mounts SHA256SUMS'
|
|
Move-Item "$staging\archive.tar.gz" $archive
|
|
Write-Output "Backup created: $archive"
|
|
} finally {
|
|
docker compose start 2>$null
|
|
Pop-Location -ErrorAction SilentlyContinue
|
|
Remove-Item -Recurse -Force $staging -ErrorAction SilentlyContinue
|
|
} |