Skip to content

Add PostgreSQL and MS-SQL database backup guides - #235

Merged
HiranAdikari merged 3 commits into
wso2:terraformfrom
Akini98:feature/233-db-backup-guides
Jul 23, 2026
Merged

Add PostgreSQL and MS-SQL database backup guides#235
HiranAdikari merged 3 commits into
wso2:terraformfrom
Akini98:feature/233-db-backup-guides

Conversation

@Akini98

@Akini98 Akini98 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Purpose

Resolves #233. The tenancy/vm examples now cover VM-file backups with restic (#232), but not database backups. A database needs its engine's native tooling (logical/native backups are portable and restore into a same-or-newer engine; a raw data-directory copy is not). This adds the database companions to the restic and cluster backup guides.

Goals

Provide self-service database backup + restore guides beside the tenancy/vm module, matching the style of k8s-cluster/examples/BACKUPS.md and vm/examples/BACKUPS.md.

Approach

Add two guides under modules/tenancy/vm/examples/:

  • POSTGRES-BACKUPS.mdpg_dumpall --roles-only + per-database pg_dump -Fc, streamed straight to the tenant's own S3 bucket under timestamped prefixes; in-guest systemd timer (running as postgres, peer auth — no DB password stored) installed via the vm module's base64-embedded user_data; restore into a fresh VM, a single database, and cross-DC DR.
  • MSSQL-BACKUPS.md — native BACKUP DATABASE ... TO DISK + aws s3 cp (the reliable path vs BACKUP TO URL), with server logins exported separately (SID + password hash) and contained-database auth enabled on restore; same install/verify/restore shape.

Both follow the established structure: least-privilege bucket + IAM (with the multipart actions), cloud-init base64 install + timer, verify, restore (fresh VM / single database / cross-DC), a scheduling & retention reference, and a production-hardening checklist. They cross-link the restic and cluster guides.

Release note

Docs: add self-service PostgreSQL and MS-SQL database backup + restore guides for the tenancy/vm module.

Summary by CodeRabbit

  • Documentation
    • Added new end-to-end backup and restore guides for Microsoft SQL Server and PostgreSQL Harvester VMs to S3.
    • Includes in-guest automated scheduling via systemd (timer/service) with Terraform cloud-init, plus first-run and verification steps.
    • Covers full restores, single-database recovery at a chosen timestamp, and cross–datacenter DR guidance (including warm-standby considerations).
    • Adds S3 security, least-privilege IAM setup, retention/lifecycle scheduling references, and operational gotchas (e.g., SQL Server TDE prerequisites, role/login restore order, credential handling).

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 05216f55-6dec-4d8c-bb0b-1ddaa53cc430

📥 Commits

Reviewing files that changed from the base of the PR and between 3e6dc0a and f9fd95a.

📒 Files selected for processing (2)
  • modules/tenancy/vm/examples/MSSQL-BACKUPS.md
  • modules/tenancy/vm/examples/POSTGRES-BACKUPS.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • modules/tenancy/vm/examples/POSTGRES-BACKUPS.md
  • modules/tenancy/vm/examples/MSSQL-BACKUPS.md

📝 Walkthrough

Walkthrough

Added complete PostgreSQL and Microsoft SQL Server backup guides for Harvester VMs, covering S3/IAM setup, Terraform cloud-init provisioning, scheduled backups, verification, database restoration, cross-datacenter recovery, retention, and production hardening.

Changes

Database backup guides

Layer / File(s) Summary
MSSQL backup provisioning and execution
modules/tenancy/vm/examples/MSSQL-BACKUPS.md
Documents prerequisites, S3 and IAM configuration, Terraform variables, cloud-init setup, native database backups, login exports, and systemd scheduling.
MSSQL verification, restore, and operations
modules/tenancy/vm/examples/MSSQL-BACKUPS.md
Documents verification, full and single-database restoration, cross-DC recovery, retention, operational gotchas, hardening, and related guides.
PostgreSQL backup provisioning and execution
modules/tenancy/vm/examples/POSTGRES-BACKUPS.md
Documents S3 and IAM configuration, Terraform variables, cloud-init setup, logical dumps, and scheduled execution.
PostgreSQL verification, restore, and operations
modules/tenancy/vm/examples/POSTGRES-BACKUPS.md
Documents verification, roles-first restoration, single-database and DR recovery, retention, gotchas, hardening, and related guides.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

  • Issue 233 — Directly addressed by adding the requested PostgreSQL and MSSQL VM backup guides.
  • Issue 231 — Related documentation change covering S3-backed VM backup guides under the same tenancy VM examples area.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: adding PostgreSQL and MS-SQL backup guides.
Description check ✅ Passed The description is mostly complete and covers purpose, goals, and approach, but it omits explicit Testing and Checklist sections from the template.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 18

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@modules/tenancy/vm/examples/MSSQL-BACKUPS.md`:
- Around line 99-108: Remove the s3:DeleteObject action from the DbBackupObjects
runtime backup policy in the MSSQL backup example, leaving the remaining S3
permissions and resource scope unchanged.
- Around line 153-160: Update the db_backup_env template in MSSQL-BACKUPS.md to
avoid interpolating raw credentials into a sourced shell file; safely encode or
shell-escape every secret value, including db_s3_access_key, db_s3_secret_key,
and mssql_sa_password, so quotes, substitutions, backticks, and newlines cannot
alter execution. Preserve the existing configuration values while ensuring the
generated backup.env remains safe when sourced.
- Around line 171-192: Update the backup workflow around the timestamped DEST
prefix so uploads first target a temporary prefix. After all database backups
and the login artifact succeed, upload a manifest and create a final completion
marker; ensure failures cannot publish that marker. Update the restore logic to
consider only prefixes containing the completion marker, including the
corresponding flow around the additional referenced section.
- Around line 185-191: Scope the backup/restore guidance around the $SQLCMD
export and logins.sql to password-authenticated SQL login creation only. Qualify
or remove claims that users map automatically or application connectivity
remains unchanged, and state that server roles, permissions, default databases,
disabled state, and existing-login reconciliation are not preserved.
- Around line 176-183: Update the backup and restore loops in the MSSQL backup
example to preserve database names as opaque values: iterate query results
line-by-line without whitespace splitting, escape SQL identifiers using
QUOTENAME instead of interpolating names inside brackets, and use a stable
filename/manifest mapping consistently for both backup and restore.
- Around line 176-180: Update every sqlcmd invocation in the MSSQL backup
example to remove the -P password argument and provide the sa password through
the SQLCMDPASSWORD environment variable instead, including both the
database-listing and backup calls while preserving their existing commands and
options.
- Around line 173-175: Update the backup-directory setup around BK and mkdir so
/var/opt/mssql/backup is owned by mssql:mssql and has permissions allowing SQL
Server writes; preserve the existing mkdir -p behavior while applying ownership
and an appropriate mode either during creation or immediately afterward.
- Around line 328-364: The restore procedure in the documented recovery flow
must address TDE prerequisites. Update the relevant §5.1/§5.3 restore
instructions to back up the TDE certificate and private key from master and
restore them on the fresh VM before the RESTORE DATABASE loop, or explicitly
state that the guide supports non-TDE databases only.
- Around line 353-359: The restore snippets in this document must support
fresh-VM paths and existing databases: before each RESTORE DATABASE, query
RESTORE FILELISTONLY to obtain logical data and log names, set destination paths
on the VM, and include corresponding WITH MOVE clauses. Also switch existing
databases to SINGLE_USER WITH ROLLBACK IMMEDIATE before restoring, and apply
these changes to both restore snippets while retaining overwrite behavior.
- Around line 247-256: Update the db-backup.service unit content to explicitly
require and start mssql-server.service, not just order after it, and add a
suitable TimeoutStartSec for large backups. Keep the existing backup command and
network ordering unchanged.
- Around line 179-182: Update the backup command in the MSSQL backup procedure
to include WITH CHECKSUM, then validate the uploaded .bak using RESTORE
VERIFYONLY or an equivalent test-restore before the rm -f cleanup. Keep deletion
conditional on both the local backup being readable and the upload succeeding.
- Around line 118-121: Update the backup guide to separate login export from the
database backup flow: either document its server-admin credential requirements
and store that credential outside the backup environment/state path, or remove
login export and configure a least-privilege backup-only principal. Keep the
backup timer and backup credentials scoped only to the required database backup
permissions.

In `@modules/tenancy/vm/examples/POSTGRES-BACKUPS.md`:
- Around line 100-107: Remove s3:DeleteObject from the Action list in the backup
credentials example, while preserving the permissions required by the backup and
restore workflows. Do not add deletion permission elsewhere; administrative
deletion should remain separately controlled.
- Around line 163-168: Add a completion marker or manifest to the backup flow
around the pg_dumpall and per-database pg_dump commands, creating it only after
every dump and upload succeeds. Update the restore logic around the referenced
restore procedure to select only timestamp prefixes containing that marker,
excluding incomplete newest prefixes.
- Around line 166-167: Update the backup and corresponding restore logic in the
documented PostgreSQL workflow to avoid shell word-splitting and
whitespace-unsafe S3 listing parsing for database names. Use a delimiter-safe
manifest or structured encoding when enumerating names, preserve each exact
database name through dump and restore, and ensure generated S3 keys remain
reliably matchable.
- Around line 287-298: Update the verification commands following the systemd
checks to first identify the latest timestamp prefix, then run aws s3 ls against
that specific prefix so it displays roles.sql and each database dump. Keep the
existing root-only environment loading and region options intact, and ensure the
subsequent on-demand backup instruction remains unchanged.
- Around line 166-168: Update the backup loop query in the PostgreSQL backup
guide to include the postgres database so every database is uploaded, or revise
the documented contract to explicitly state that postgres is excluded; keep the
dump and S3 upload behavior unchanged.
- Around line 321-328: Update the restore block’s shell commands to enable
fail-fast behavior with set -euo pipefail and add --exit-on-error to the
pg_restore invocation. Keep the existing per-database loop and restore options
unchanged so any failed pipeline or database restore stops the run immediately.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b5ba38f4-51c0-4028-aea3-80de1df75c62

📥 Commits

Reviewing files that changed from the base of the PR and between 04353ac and 28f70c9.

📒 Files selected for processing (2)
  • modules/tenancy/vm/examples/MSSQL-BACKUPS.md
  • modules/tenancy/vm/examples/POSTGRES-BACKUPS.md

Comment thread modules/tenancy/vm/examples/MSSQL-BACKUPS.md
Comment thread modules/tenancy/vm/examples/MSSQL-BACKUPS.md Outdated
Comment thread modules/tenancy/vm/examples/MSSQL-BACKUPS.md
Comment thread modules/tenancy/vm/examples/MSSQL-BACKUPS.md
Comment thread modules/tenancy/vm/examples/MSSQL-BACKUPS.md
Comment thread modules/tenancy/vm/examples/POSTGRES-BACKUPS.md
Comment on lines +166 to +167
for db in $(psql -Atc "SELECT datname FROM pg_database WHERE datistemplate=false AND datname<>'postgres';"); do
pg_dump -Fc -d "$db" | aws s3 cp - "$DEST/$db.dump" --region "$DB_S3_REGION"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Avoid shell word-splitting and S3-key parsing for database names.

for db in $(...) breaks valid names containing whitespace, and aws s3 ls | awk | grep cannot reliably round-trip names containing whitespace or path separators. Such databases may be backed up under unusable keys or skipped during restore. Use a manifest with safely encoded database names, or a delimiter-safe structured listing.

Also applies to: 325-328

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/tenancy/vm/examples/POSTGRES-BACKUPS.md` around lines 166 - 167,
Update the backup and corresponding restore logic in the documented PostgreSQL
workflow to avoid shell word-splitting and whitespace-unsafe S3 listing parsing
for database names. Use a delimiter-safe manifest or structured encoding when
enumerating names, preserve each exact database name through dump and restore,
and ensure generated S3 keys remain reliably matchable.

Comment thread modules/tenancy/vm/examples/POSTGRES-BACKUPS.md Outdated
Comment thread modules/tenancy/vm/examples/POSTGRES-BACKUPS.md Outdated
Comment thread modules/tenancy/vm/examples/POSTGRES-BACKUPS.md Outdated
Security/robustness fixes across both guides:
- drop s3:DeleteObject from the runtime IAM policy (backup/restore never
  delete objects; retention is the S3 lifecycle rule)
- deliver secrets via the systemd unit's EnvironmentFile instead of a
  shell `source` (no evaluation of secret values); load env with a
  non-eval reader in the manual snippets
- write a COMPLETE marker last and restore only the latest marked prefix
  so a partial run is never restored
- fail fast on restore (set -euo pipefail; pg_restore --exit-on-error)
- add TimeoutStartSec=0 and Wants= the DB service to the backup unit

MS-SQL specifics:
- pass the sa password via SQLCMDPASSWORD, not -P (keeps it out of ps)
- create the backup dir owned by mssql (install -d -o mssql -g mssql)
- BACKUP ... WITH CHECKSUM + RESTORE VERIFYONLY before upload
- scope the login-export claim to SQL-auth logins; note TDE, WITH MOVE /
  SINGLE_USER on restore, and a dedicated backup principal for production

PostgreSQL specifics:
- exclude only the postgres maintenance DB and narrow the wording; -AtXc
@Akini98

Akini98 commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

Fixed

  • s3:DeleteObject removed from both IAM policies (backup/restore never delete objects; retention is the lifecycle rule).
  • Secrets no longer sourced as root — the backup unit now uses EnvironmentFile=, the env file is plain KEY=value, and the manual verify/restore snippets load it with a non-eval while IFS= read loop.
  • sa password now passed via SQLCMDPASSWORD (dropped -P, so it's out of ps).
  • Backup dir created with install -d -o mssql -g mssql.
  • Integrity: BACKUP ... WITH CHECKSUM + RESTORE VERIFYONLY before the local rm.
  • Partial-run safety: a COMPLETE marker is written last; verify and both restore paths select the latest prefix that has it.
  • Fail-fast restore: set -euo pipefail + pg_restore --exit-on-error.
  • systemd: TimeoutStartSec=0 + Wants=<db>.service on the backup unit.
  • Postgres postgres DB: narrowed the "every database" wording to "user databases" and switched to psql -AtXc.
  • Login claim scoped to SQL-authenticated logins (noted that server roles/permissions/Windows logins aren't included).

Documented rather than re-architected (these are example guides)

  • Dedicated backup principal vs sa (#login-export-admin): added a Production Hardening bullet — the example uses sa for brevity, with guidance to split a least-privilege backup login from the admin-level login export.
  • Database names with whitespace/] : added an explicit "assumes standard identifiers" note; full QUOTENAME + manifest machinery would obscure the example.
  • TDE: added a gotcha to back up/restore the TDE certificate + key first, or scope to non-TDE.
  • WITH MOVE / SINGLE_USER: added a restore callout for differing file paths and busy databases.

Add a short "Configure what to back up and when" subsection to both guides:
which databases (edit the SELECT/WHERE), how often (the timer OnCalendar),
and retention (the S3 lifecycle Expiration). Makes the existing knobs
explicit instead of only implied by the scripts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@HiranAdikari
HiranAdikari merged commit f46a1e9 into wso2:terraform Jul 23, 2026
2 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants