Ignore files, remove old and add CLAUDE.md
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## What this is
|
||||
|
||||
Backup + disaster-recovery tooling for a Linux server: Borg (encrypted, offsite-synced via rclone) backing up `/home/srv/files/content`, including MariaDB running in Docker. Plain bash, no build system, no CI. `RUNBOOK.md` is the operational doc (setup, deploy, cron, day-2 ops, recovery). `old/` holds the legacy scripts this replaced — reference only, not maintained.
|
||||
|
||||
- `borg-backup.sh` — daily backup orchestrator (cron). Never stops MariaDB: `dump_db.sh`'s `--single-transaction` dump is consistent on its own, and the raw data directory is excluded from the archive via a `.nobackup` marker file.
|
||||
- `dump_db.sh` — per-database `mysqldump`/`mariadb-dump` with atomic staging/swap. Deployed to `/home/srv/files/content/mariadb/dump_db.sh` (borg-backup.sh invokes it at that exact path).
|
||||
- `restore.sh` — recovery CLI: `full` (disaster recovery), `db <name>`, `file <path>`, `--list-archives`, all supporting `--dry-run`.
|
||||
|
||||
## Global conventions (don't re-derive these)
|
||||
|
||||
- `TARGET=/home/srv/files/content`, `REPO=/home/srv/files/backups/borg-2025`, `DB_CONTAINER=mariadb`
|
||||
- `BORG_PASSPHRASE_FILE=/root/.borg-passphrase` (chmod 600, read via `BORG_PASSCOMMAND`)
|
||||
- Backup DB user `backup` (password file `/root/.mariadb-backup.pw`, limited SELECT/LOCK grants) is separate from restore's `root` creds (`MYSQL_ROOT_PASSWORD` env or `/root/.mariadb-root.pw`) — restore needs CREATE/DROP privileges the backup user doesn't have.
|
||||
- Dumps live at `mariadb/dump/*.sql` plus `00-users-and-grants.sql`, inside `$TARGET`.
|
||||
- `restore.sh` and `borg-backup.sh` share one lockfile (`/var/lock/borg-backup.lock` via `flock -n 9`) so a restore and the nightly backup can never run concurrently.
|
||||
- Destructive-op safety: `full` refuses a non-empty `$TARGET` without `--force`; `db` requires typed dbname confirmation unless `--yes`; every mode supports `--dry-run`.
|
||||
- `resolve_archive()` in `restore.sh` deliberately does *not* filter archives by hostname (unlike backup's prune/list, which does) — disaster recovery may run from a different host than made the backup.
|
||||
- Logs: `/var/log/borg/{backup,restore}-*.log` (override with `BORG_BACKUP_LOGFILE` / `RESTORE_LOGDIR` for local testing).
|
||||
|
||||
## Testing
|
||||
|
||||
```
|
||||
RESTORE_LOGDIR=/tmp/restore-test-logs bash tests/test_restore.sh
|
||||
```
|
||||
|
||||
Plain bash, no framework (`assert_eq`/`assert_contains` + a `$FAILURES` counter in `tests/test_restore.sh`). `tests/lib/setup_mocks.sh` builds fake `borg`/`docker`/`mysql`/`mariadb`/`flock` executables into a temp dir.
|
||||
|
||||
Mock isolation requires all three of:
|
||||
- `PATH="$mockdir:$PATH"`
|
||||
- `BASH_ENV="$(mock_bash_env "$mockdir")"` — both scripts prepend a hardened `PATH` with system dirs (`/usr/local/bin` etc.) *ahead* of `$PATH`, so a real binary there would win over a PATH-only mock. `BASH_ENV` shell functions take priority regardless of PATH order.
|
||||
- Env overrides for `LOCKFILE` / `BORG_PASSPHRASE_FILE` / `ROOT_PASSWORD_FILE` pointed at throwaway paths, so `acquire_lock()`/`preflight()` never touch real `/var/lock` or `/root`.
|
||||
|
||||
`flock(1)` (util-linux) doesn't exist on macOS — that's why it's mocked too, not just for isolation.
|
||||
|
||||
## Conventions
|
||||
|
||||
- Conventional commits (`feat:`, `fix:`, `docs:`, `chore:`). Direct commits to `master`, no PR workflow.
|
||||
- New restore/backup logic should mirror the existing style in `borg-backup.sh`/`restore.sh`: `log()`/`step()`/`die()`/`run_cmd()` helpers, `set -euo pipefail`, config constants up top.
|
||||
Reference in New Issue
Block a user