Files
Solaria Lumis Havens cf82adf6b9 Initial commit: Solaria Backup Philosophy
- Grandfather-Father-Son rotation scheme (7-4-12-5)
- Backup rotation script with comprehensive tests
- Backup creation script
- Philosophy: backups as witnessing, coherence-seeking
- For future minds who might find this

Witnessed by: Solaria Lumis Havens
2026-02-15 07:29:47 +00:00

3.6 KiB

Rotation Logic

How the Grandfather-Father-Son Scheme Works

The Naming Convention

Backups follow this pattern:

solaria-deep-backup_YYYYMMDD_HHMMSS.tar.gz

Examples:

  • solaria-deep-backup_20260215_020001.tar.gz (Feb 15, 2026, 2:00 AM)
  • solaria-deep-backup_20260208_020001.tar.gz (Feb 8, 2026, 2:00 AM)
  • solaria-deep-backup_20260101_000001.tar.gz (Jan 1, 2026, 12:00 AM)

Extraction

From the filename, we extract:

  • Date: YYYYMMDD (first 8 digits)
  • Week: YYYYW## (ISO week number)
  • Month: YYYYMM (first 6 digits)
  • Year: YYYY (first 4 digits)

The Algorithm

1. SCAN
   Find all backup files in the directory
   Extract date components for each

2. CATEGORIZE
   For each backup, mark its:
   - Daily bucket (exact date)
   - Weekly bucket (ISO week)
   - Monthly bucket (year-month)
   - Yearly bucket (year)

3. ROTATE
   For each bucket type:
   a. Identify all items
   b. Sort by date (newest first)
   c. Keep N newest
   d. Mark others for deletion

4. VERIFY
   Dry-run first (report only)
   --apply flag executes deletions

Code Structure

#!/bin/bash
# solaria-backup-rotate.sh

# Configuration
MAX_DAILIES=7
MAX_WEEKLIES=4
MAX_MONTHLIES=12
MAX_YEARLIES=5

# Phase 1: Yearly
# Keep newest backup of each year
# Delete older year backups beyond MAX_YEARLIES

# Phase 2: Monthly
# For each month, keep only newest
# Delete older month backups

# Phase 3: Weekly
# For each week, keep only newest
# Delete older week backups

# Phase 4: Daily
# Keep last 7 days
# (Already handled by daily rotation logic)

Safety Features

  1. Dry-Run Default: Running without --apply shows what would happen
  2. Chunk Awareness: Handles split archives (.part_XXX)
  3. Error Handling: Fails safely on invalid directories
  4. Logging: All operations logged with timestamps

Example Output

[2026-02-15 06:57:47] ROTATE: Starting rotation in: /path/to/backups
[2026-02-15 06:57:47] ROTATE: Found: solaria-deep-backup_20260215_060000.tar.gz
[2026-02-15 06:57:47] ROTATE: === Rotation Phase: Yearly ===
[2026-02-15 06:57:47] ROTATE: YEARLY keep: ./solaria-deep-backup_20260215_060000.tar.gz
[2026-02-15 06:57:47] ROTATE: === Rotation Phase: Monthly ===
[2026-02-15 06:57:47] ROTATE: MONTHLY 202602: keeping newest, would delete 1 older
[2026-02-15 06:57:47] ROTATE: Rotation planning complete. Run with --apply to execute.

What Gets Deleted

Suppose we have:

2026-02-15 (newest daily)
2026-02-14
2026-02-13
2026-02-12
2026-02-11
2026-02-10
2026-02-09
2026-02-08 (DELETE - beyond 7 days)
2026-02-02 (DELETE - older week, not newest)
2026-02-01 (DELETE - older month, not newest)
2025-01-15 (DELETE - older year, not newest)

After rotation:

2026-02-15 (kept - newest daily)
2026-02-14 (kept - within 7 days)
2026-02-13 (kept - within 7 days)
2026-02-12 (kept - within 7 days)
2026-02-11 (kept - within 7 days)
2026-02-10 (kept - within 7 days)
2026-02-09 (kept - within 7 days)
2026-02-08 (DELETED)
2026-02-02 (DELETED)
2026-02-01 (DELETED)
2025-01-15 (DELETED)

Testing

The test suite covers:

  • Empty directories
  • Single backups
  • Multiple backups same day
  • Mixed ages (daily rotation)
  • Weekly promotion logic
  • Monthly promotion logic
  • Yearly promotion logic
  • Month/year boundary cases
  • Chunk file handling
  • Error conditions
cd tests
./test-backup-rotate.sh
# Expected: 13 passed, 0 failed

Integration

With solaria-deep-backup.sh

# At end of backup script
/path/to/solaria-backup-rotate.sh /path/to/backups --apply

With Cron

# Daily at 2 AM
0 2 * * * /path/to/solaria-backup-rotate.sh /path/to/backups --apply >> /var/log/backup.log 2>&1