No description
Find a file
counterweight df4f712a93
headscale: the ACL was {} in code and real on the box. Put it in git
`Create ACL policies file` wrote this, verbatim, to /etc/headscale/acl.json:

    content: |
      {}

An empty policy. The real rules - who may reach which host on which port -
were maintained by hand on spacey and existed nowhere else. So the repo and
the box disagreed about the single file that governs every machine's access
to every other machine, and the repo's version was "nothing is allowed".

It had already fired once. /etc/headscale/acl.json.937464.2026-09-12@14:03:08~
is Ansible's own backup of a 1596-byte policy it replaced with {} on 12 Sep;
the live file is dated 17 Sep, so somebody rebuilt it by hand afterwards
without the playbook ever being corrected. Every subsequent `site.yml` run was
one command away from flattening the whole tailnet's access rules again.

This commit changes nothing on spacey. The policy now lives in
templates/acl.json.j2, captured verbatim from the live file, and the task is a
`template:` instead of an inline `{}`. Rendering it produces sha256
1ed14e7247d957db5e9f8d4f4c53846dc646131ad900054c868483a9a84ed8fd, byte for byte
the file that was already there - verified before applying, and again after.

Three deliberate choices:

- A template file, not the inline `content:` used elsewhere in this playbook.
  The whole failure was three invisible characters passing review; a 2KB
  policy needs to show up as a diff.
- `validate: python3 -m json.tool %s`. headscale refuses to load a malformed
  policy, and a policy it will not load is the same outage as an empty one.
- `"counter-net@"` is now `"{{ headscale_namespace }}@"`, which is already a
  fact in group_vars/all/main.yml rather than a fourteenth hand-typed copy.

The header comment records why a node with no ACL rule is INVISIBLE rather than
merely unreachable - it never appears in `tailscale status`, MagicDNS does not
resolve it, and the symptom is a downstream "no such host" that looks like a
DNS problem. That cost an hour today.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 17:49:54 +02:00
ansible headscale: the ACL was {} in code and real on the box. Put it in git 2026-09-19 17:49:54 +02:00
archive/uptime_kuma uptime kuma: remove every live reference, repoint the probes to Gatus 2026-09-14 10:30:28 +02:00
tofu/nodito tofu: stop gitignoring the lock file and the VM inventory 2026-09-12 18:43:14 +02:00
.gitignore tofu: stop gitignoring the lock file and the VM inventory 2026-09-12 18:43:14 +02:00
01_infra_setup.md docs: mark Uptime Kuma as decommissioned 2026-09-11 22:43:56 +02:00
02_vps_core_services_setup.md docs: mark Uptime Kuma as decommissioned 2026-09-11 22:43:56 +02:00
03_vm_disk_enlargement.md little thingies 2026-03-22 21:25:08 +01:00
README.md docs: mark Uptime Kuma as decommissioned 2026-09-11 22:43:56 +02:00
requirements.txt uptime-kuma: annotate config and drop the unused collection 2026-09-11 22:43:56 +02:00

Personal infra

My repo documenting my personal infra, along with artifacts, scripts, etc.

How to use

Go through the different numbered markdowns in the repo root to do the different parts.

How to edit secrets

ansible-vault edit ansible/your_file_with_secrets.yml

Assumes that you've set ansible/.vault_pass with chmod 600.

Overview

Services

  • Reverse Proxy
    • Deployed on Vipy
    • Caddy
    • Plan install
    • File based config
    • Crossbackup to Desky via rsync
  • Uptime Kuma — decommissioned 2026-09-11, see archive/uptime_kuma/
    • Deployed on Vipy
    • Crossbackup to Desky via rsync
  • Vaultwarden
    • Deployed on Desky
    • Crossbackup to Vipy via rsync
  • Gitea
    • Deployed on Desky
    • Crossbackup to Vipy via rsync
  • Immich
    • Deployed on Desky
  • VPN
    • All set up on Vipy
  • Bitcoin Knots
    • Deployed on Desky
  • electrs
  • Synapse Server
  • Phoenix D + LNBits
  • Backups

Infra

  • Laptop (Lapy)
  • One beefy desktop (Desky)
  • One VPS (Vipy)