- Shell 46.3%
- Jinja 38.4%
- Python 12.9%
- Dockerfile 2.2%
- Go 0.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
ntfy was Tier-1/public (origin vhost + public CNAME) so push could reach a
device without WG. With always-on WireGuard on every device the bus rides the
tunnel, so public exposure bought nothing and only widened the attack surface.
Demote to Tier-2/WG-only, per the documented decision rule:
- origin_caddy: drop the ntfy.${domain} public vhost (origin stops serving it).
- bind_primary: add ntfy to bind_primary_private_names, so the dns-reconcile
task nsupdate-deletes the public record and keeps it deleted (self-healing).
- Internal path unchanged: apps-proxy proxy_vhosts_core + Unbound split-horizon
still serve ntfy.${domain} -> ntfy:8090 over WG/LAN.
- Docs (completion gate): CLAUDE.md exposure model + public-domains set + the
apps-proxy Tier-2 rows; runbook 18 subscribe note.
fmd stays Tier-1/public by design — a stolen phone with its WG peer cert
revoked must still reach the device API to phone home.
Converged caddy+bind and verified: public DNS record gone (both edge
secondaries + primary), public HTTPS path fails (no origin vhost), internal/WG
path still 200.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
(cherry picked from commit 755012508dd43f0d06b20ec5361422db3e81e7d9)
|
||
| .forgejo/workflows | ||
| ansible | ||
| docs | ||
| provision | ||
| runbooks | ||
| scripts | ||
| tests | ||
| .gitignore | ||
| CLAUDE.md | ||
| mkdocs.yml | ||
| README.md | ||
| requirements-docs.txt | ||
${domain} home lab
Infrastructure-as-code and runbooks for the ${domain} home lab — a segmented home network/firewall (OPNsense) plus a small AlmaLinux 9 server fleet, built to be reproducible from a clean install. Trust-based network segmentation, an edge/origin split that serves public sites from remote multi-vendor VPSes while TLS terminates at home, WireGuard-only management, a road-warrior VPN, and central identity (FreeIPA) backing NFS home directories.
Start here
CLAUDE.md— the design doc and single source of truth: threat model, trust zones, IP allocation, ProtonVPN egress, edge/origin, identity/NFS, DNS, and the why behind every locked decision. Read it first.runbooks/00-index.md— the ordered, step-by-step build/validate guides (provision → OPNsense → identity/storage → SSO → edge → extras).docs/— the public, reproducible-for-others guides (mkdocs → myos.io): Installation / Administration / User.
Layout
| Path | What |
|---|---|
provision/ |
qm clone + cloud-init shell scripts that define and create the VMs (Proxmox CLI only). vms.conf is the VM manifest. |
ansible/ |
Configuration (built-in modules only, pinned ansible-core). Roles, playbooks, inventory, vault. |
runbooks/ |
Ordered build/validate runbooks (OPNsense as GUI click-throughs; servers as command runbooks). |
docs/ |
mkdocs site sources (the three audience guides). |
scripts/ |
Operator helpers — secret access, SSH-CA / host-cert lifecycle, fleet phasing. See scripts/README.md. |
tests/ |
Firewall conformance harness. |
How it's built & run
Provision the VMs with provision/lab-provision.sh (clones the AlmaLinux 9 template),
then configure with Ansible (ansible/playbooks/site.yml). Appliances (OPNsense, FreeIPA
server, Home Assistant, Nextcloud) are stood up by runbook / manual install; everything
else is destroy-and-rebuild from code. Ansible runs from a dedicated control-node VM
(ctrl, MGMT) that holds the fleet SSH transport key and lab.kdbx, with its vault
password sealed to the VM's TPM. YubiKey-gated SSH-CA signing happens on a laptop and is
committed to git for ctrl to deploy.
Secrets
Never commit plaintext keys or passwords. Automation secrets live in the Ansible vault
(ansible/group_vars/all/vault.yml); the human break-glass store is KeePass
(lab.kdbx). WireGuard and host keys are generated on build, not stored in the repo.
What "adversary" means here
The threat model defends against the mundane, pervasive misuse of data — not (or not only) rogue states or fancy international espionage. The thing being prevented is the slow death by a thousand cuts: ISPs, VPS vendors, data brokers, and ad-tech monetizing your traffic, building behavioral/advertising profiles, and tricking or nudging users. Treating the ISP and the VPS vendors as "adversaries" just means they are positioned to harvest, sell, or profile your traffic — so the design denies them that by default. It's privacy / anti-profiling hygiene, not spy-vs-spy.