Add CLAUDE.md
Orients future Claude Code sessions: this is an ops/docs repo for two live remote hosts, not an application codebase - documents the file map, the scripts/ deploy-and-diff workflow, and sanity-check.sh as the closest thing to a test suite.
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## What this repository is
|
||||
|
||||
This is **not an application codebase** — there's nothing to build, lint,
|
||||
or test. It's the operations/documentation repo for administering two
|
||||
real, live hosts remotely over SSH:
|
||||
|
||||
- **`alpha.jayfield.org`** (`89.58.8.149`) — public VPS, Ubuntu 24.04 LTS,
|
||||
reached via `ssh -p 10022 jens@alpha.jayfield.org`. Runs authoritative
|
||||
DNS (BIND9), a full mail stack (Postfix/Dovecot/rspamd/MariaDB), Apache
|
||||
reverse-proxying into a Docker layer (Portainer, Nextcloud, Gitea, a
|
||||
plain nginx container), and fail2ban.
|
||||
- **`vlda-01`** — home intranet server (Unraid 7.3.2), reached via
|
||||
`ssh root@vlda-01` from the same LAN. Not part of `alpha`'s public
|
||||
`jayfield.org` zone — lives under the private, unresolvable
|
||||
`home.jayfield.org` namespace. Currently the pull side of the Gitea
|
||||
backup from `alpha`.
|
||||
|
||||
**All actual changes happen live on those hosts over SSH, not in this
|
||||
repo.** This repo records what's true afterward and keeps reference
|
||||
copies of deployed scripts/configs. There is no local checkout of any
|
||||
live service config to edit — the working pattern for every task is:
|
||||
SSH in → make the change on the real host → verify it live (curl a vhost,
|
||||
run `sanity-check.sh`, check a real log line) → record it here.
|
||||
|
||||
## Document map (read the right one, not all of them)
|
||||
|
||||
| File | Purpose | Rule |
|
||||
|---|---|---|
|
||||
| `README.md` | **Live state** — what's actually running on `alpha` right now | Source of truth when it disagrees with `SETUP.md` |
|
||||
| `SETUP.md` | Fresh-install build runbook (currently: from-scratch on 24.04) | How to reproduce the host from nothing, not what's live |
|
||||
| `TODO.md` | Full chronological audit log of every bug/fix/hardening pass | **Append-only. Never consolidate or summarize existing entries unprompted** — this has been corrected before; keep the full narrative detail even when it's long |
|
||||
| `SYNC-PLAN.md` | Point-in-time plan for the `vlda-01` → `alpha` intranet migration | Move a service's write-up into `README.md` once it's actually built and live; only update the plan for what's still pending |
|
||||
| `MAIL-ACCOUNTS.md` | Day-to-day recipe for adding/disabling mail accounts | References `SETUP.md` §3 for the underlying schema |
|
||||
| `DIFF.md` | One-time (2026-07-19) diff-vs-clean-install investigation | Explicitly a snapshot, not a live inventory — don't treat its findings as current without re-checking |
|
||||
| `scripts/` | Reference copies of everything deployed on `alpha` and its clients | **Not auto-deployed** — see below |
|
||||
|
||||
## The `scripts/` deployment workflow
|
||||
|
||||
`scripts/` is split by host (`scripts/alpha/`, `scripts/clients/<host>/`)
|
||||
because each host has a genuinely different OS with different
|
||||
persistence/deployment conventions — each subdirectory's own `README.md`
|
||||
states the exact OS/version and the live deployment path for every file.
|
||||
**Editing a file under `scripts/` changes nothing on the real host.**
|
||||
After editing, the actual workflow is:
|
||||
|
||||
1. Deploy the change to the live host (`scp`/`cat > file` over SSH to the
|
||||
path listed in that host's `README.md`).
|
||||
2. `diff` the deployed copy against the repo copy — they must match
|
||||
byte-for-byte before moving on.
|
||||
3. Test the actual behavior live (run the script, hit the endpoint,
|
||||
reboot if it's boot-triggered) — not just "it deployed without error."
|
||||
4. Only then update `README.md`/`TODO.md` to describe the change.
|
||||
|
||||
`vlda-01` (Unraid) needs particular care here: `/` and `/usr` are
|
||||
RAM-backed and don't survive a reboot, and `/boot` (the persistent USB
|
||||
stick) is VFAT with no Unix execute bit — scripts there are deployed via
|
||||
the **User Scripts** plugin and invoked with `bash <path>`, never `exec`.
|
||||
See `scripts/clients/vlda-01/README.md` before touching anything there.
|
||||
|
||||
## Verifying a change is the closest thing to a test suite
|
||||
|
||||
There's no CI here — "does it work" is checked directly against the live
|
||||
host:
|
||||
|
||||
- `sudo /usr/local/sbin/sanity-check.sh` on `alpha` — checks the whole
|
||||
stack (packages, DNS/DNSSEC, mail, MariaDB, fail2ban, every public
|
||||
vhost by expected HTTP status, all Docker containers, plus a version
|
||||
dump of every involved service) and prints PASS/WARN/FAIL. Runs
|
||||
automatically once per boot via `sanity-check.service`; run it manually
|
||||
after any config change that doesn't itself trigger a reboot.
|
||||
- `sudo /usr/local/sbin/attacker-check.py` — weekly fail2ban log analysis
|
||||
(also runs on its own via cron); safe to run manually any time.
|
||||
- For anything touching the mail stack, DNS, or a vhost: a real end-to-end
|
||||
check beats trusting the config on paper (e.g. an actual `dig` against
|
||||
the authoritative server, a real test email round-trip via
|
||||
`/var/log/mail.log`, a real `curl` against the public hostname) — this
|
||||
repo's history (`TODO.md`) has repeated cases of a config that "looked"
|
||||
correct but silently didn't work.
|
||||
|
||||
## A few standing facts worth knowing before editing docs
|
||||
|
||||
- `jayfield.org` (public, this host's zone) and `home.jayfield.org`
|
||||
(private home-LAN namespace, `vlda-01` and friends) are deliberately
|
||||
separate — see `README.md`'s "Domain namespace" section.
|
||||
- Gitea (`git.jayfield.org`) is the canonical git host for this repo
|
||||
itself (migrated from `vlda-01`, which keeps a cold, stopped backup
|
||||
copy). There is no GitHub remote.
|
||||
- SSH access details (ports, users) belong in `README.md`/host
|
||||
`README.md`s, not duplicated here — check there rather than assuming.
|
||||
Reference in New Issue
Block a user