MyOS — reproducible home-lab platform (generic master; the public reference tree). Clone + add your instance overlay.
  • Shell 46.3%
  • Jinja 38.4%
  • Python 12.9%
  • Dockerfile 2.2%
  • Go 0.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
MyOS maintainer d7f9d1fe14 ntfy: demote to Tier-2 (WG-only) — remove from public edge + public DNS
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)
2026-07-02 10:04:46 -05:00
.forgejo/workflows MyOS — reproducible home-lab platform (initial generic release) 2026-07-02 05:45:30 -05:00
ansible ntfy: demote to Tier-2 (WG-only) — remove from public edge + public DNS 2026-07-02 10:04:46 -05:00
docs MyOS — reproducible home-lab platform (initial generic release) 2026-07-02 05:45:30 -05:00
provision A5/pre-public: genericize personal machine names in docs/comments (prose scrub) 2026-07-02 07:59:06 -05:00
runbooks ntfy: demote to Tier-2 (WG-only) — remove from public edge + public DNS 2026-07-02 10:04:46 -05:00
scripts A5/pre-public: placeholder the last instance pubkeys (fleet_transport root@pve, allowed_signers) 2026-07-02 08:05:31 -05:00
tests A5/pre-public: genericize personal machine names in docs/comments (prose scrub) 2026-07-02 07:59:06 -05:00
.gitignore A5/pre-public: genericize personal machine names in docs/comments (prose scrub) 2026-07-02 07:59:06 -05:00
CLAUDE.md ntfy: demote to Tier-2 (WG-only) — remove from public edge + public DNS 2026-07-02 10:04:46 -05:00
mkdocs.yml MyOS — reproducible home-lab platform (initial generic release) 2026-07-02 05:45:30 -05:00
README.md MyOS — reproducible home-lab platform (initial generic release) 2026-07-02 05:45:30 -05:00
requirements-docs.txt MyOS — reproducible home-lab platform (initial generic release) 2026-07-02 05:45:30 -05:00

${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.