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.
94 lines
5.4 KiB
Markdown
94 lines
5.4 KiB
Markdown
# 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.
|