Files
docs-alpha.jayfield.org/CLAUDE.md
T
jens 1518dc74c7 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.
2026-07-26 22:52:28 +02:00

5.4 KiB

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-01alpha 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.mds, not duplicated here — check there rather than assuming.