Skip to content

makanilani.com — Infrastructure Wiki

Human-readable reference for the whole system: what runs where, how to reach it, how things connect, and what was learned the hard way. Last verified: 2026-09-27.

Ops tip: machine-readable snapshots + runbooks live in vpn-vps/. This file is the map; the directories are the picture.


1. The Big Picture

                        Internet
                           │
                    ┌──────▼───────┐
                    │   Cloudflare │  DNS for makanilani.com (+ wildcard *.p.m...)
                    └──────┬───────┘
                           │  (A records → VPS)
                 ┌─────────▼───────────┐
                 │  VPS vpn.makanilani.com
                 │  172.238.45.207 (RackNerd, Ubuntu 24.04)
                 │
                 │  ├─ Traefik        :80/:443 (owns both ports, docker-proxy on gerbil netns)
                 │  ├─ Pangolin CE    dashboard = pangolin.p.makanilani.com
                 │  ├─ Gerbil         WireGuard hub :51820 (sites) + :21820 (client relay)
                 │  ├─ AdGuard Home   DNS :53, admin :81, DoH via Traefik :443
                 │  └─ WireGuard wg0  personal VPN :57218/udp (10.66.66.0/24)
                 └─────────┬───────────┐
                           │ tunnels (WireGuard)
        ┌──────────────────┴──────────────────┐
        │                                     │
┌───────▼─────────────────┐        ┌──────────▼──────────────┐
│  HAOS raspi             │        │  Proxmox 192.168.0.131   │
│  homeassistant          │        │  PVE 9.2.20              │
│  192.168.0.129          │        │                          │
│                         │        │  LXC 100 hermesagent     │
│  ├─ Newt connector      │◄──────►│  LXC 101 neo4j           │
│  │  (Pangolin site      │  LAN   │  LXC 102 elementsynapse  │
│  │   "home")                        │  LXC 103 forgejo (git)   │
│  ├─ AdGuard Home addon  │        │  LXC 104 postgresql      │
│  │   DNS :53 for LAN    │        │  LXC 105 alpine-cinny    │
│  ├─ Nginx Proxy Manager │        │  LXC 106 wekan           │
│  │  :81 UI, :80/:443    │        │                          │
│  ├─ HA UI :8123         │        └──────────────────────────┘
│  └─ more addons...      │
└─────────────────────────┘

Home LAN is 192.168.0.0/24, gateway 192.168.0.1. The Haos raspi runs the LAN DNS (AdGuard) and the reverse proxy (NPM) for local-only access to services.


2. Host-by-host guide

2.1 VPS — vpn.makanilani.com (172.238.45.207)

Ubuntu 24.04 at RackNerd. Root: ssh -i ~/.ssh/vpn_pangolin root@vpn.makanilani.com.

Service Where Access
Pangolin + Gerbil + Traefik /opt/pangolin (docker compose) dashboard https://pangolin.p.makanilani.com
AdGuard Home /opt/AdGuardHome — DNS :53, admin UI :81 UI also via https://vpn.makanilani.com (DoH)
Outbound WG VPN /etc/wireguard/ wg0 port 57218/udp, peers on 10.66.66.x
CF DNS token /opt/pangolin/config/traefik/.cf-env used for Let's Encrypt DNS-01 (never in git)

Tunnel ports (critical): UDP 51820 and 21820 must BOTH be allowed on RackNerd's provider firewall (separate from host ufw!). This bit us once — Newt "bad gateway" until 21820 was opened at the provider edge.

Pangolin gives private access to home-LAN services using *.p.makanilani.com resources (wildcard Let's Encrypt cert via Cloudflare DNS-01: p.makanilani.com).

Current private resources (site "home", Newt connector on HAOS):

FQDN Backend Notes
vault.p.makanilani.com 192.168.0.129:7277 Vaultwarden on HAOS
options.p.makanilani.com 192.168.0.132:8899 LAN only, via client resource
git.p.makanilani.com 192.168.0.134:3000 Forgejo (also in NPM)
cinny.p.makanilani.com 192.168.0.136:8080 Cinny (matrix web client)
wekan.p.makanilani.com 192.168.0.137:8081 WeKan LXC (also in NPM for LAN)

Pangolin Integration API is enabled (self-host flag) and exposed at https://api.p.makanilani.com/v1 via a custom Traefik router (int-api-router in /opt/pangolin/config/traefik/dynamic_config.yml). Bearer token = PANGOLIN_API_KEY in profile env. Swagger UI at https://api.p.makanilani.com/v1/docs.

Gotchas uncovered by real debugging:

  • Pangolin Android client had a bad run in 0.7.x where hole punch traffic never got sent (fosrl#3478, closed "not_planned"). Fix: reinstall app + verify with docker exec gerbil wg show wg0 transfer on VPS — client peer must move bytes.
  • Deleting a user client is only possible server-side: docker exec pangolin pangctl delete-client --orgId <org> --niceId <niceId> (Dashboard only offers "Archive" for user clients).
  • "Public key mismatch" at re-register is normal. Repeated every connect means stale state — delete + re-enroll client.
  • Pangolin reads your Proxmox token from ~/.hermes/profiles/sysadmin/.env.

2.2 HAOS raspi — homeassistant (192.168.0.129)

Raspberry Pi 5, HAOS 18.3, Supervisor 1.14.0. ~28 GB disk (used ~18 GB).

SSH root: ssh -i ~/.ssh/forgejo_hermes root@192.168.0.129 → lands in "Advanced SSH & Web Terminal" addon container (a0d7b954-ssh), with the full ha CLI available. Must use root — homeassistant@ is rejected.

HA REST API: see HASS_URL / HASS_TOKEN in the sysadmin profile env. HA long-lived tokens do not work over websocket (auth_invalid on /api/websocket) — they only work on REST (/api/…). Use REST + ha over SSH.

Key addon slugs:

Addon Slug Port / notes
Advanced SSH & Web Terminal a0d7b954_ssh :22, keys in addon config tab, restart after edit
Nginx Proxy Manager a0d7b954_nginxproxymanager UI :81, proxy :80/:443 — yes, NPM owns LAN :80/:443 too! Best used for LAN routes (git.lan etc.)
AdGuard Home a0d7b954_adguard DNS :53 for LAN. Default UI via HA Ingress only; direct API on :3000 (HA basic auth)
Newt (Pangolin connector) 96282436_newt connects this box's resources to VPS tunnels
Vaultwarden a0d7b954_bitwarden :7277
Portainer db21ed7f_portainer manages HAOS docker
WireGuard a0d7b954_wireguard personal VPN
Monica db21ed7f_monica :8181
Joplin Server db21ed7f_joplin :22300
Postgres 17 / pgAdmin4 db21ed7f_postgres_latest / 77b2833f_pgadmin4
Matter Server core_matter_server
File editor core_configurator
ESPHome 5c53de3b_esphome
Duck DNS core_duckdns

AdGuard Home LAN (the one your devices actually use!) runs here, not on the VPS.

  • UI: via HA sidebar → AdGuard Home (Ingress). Direct API on port 3000 is disabled by default and only unlocked by setting a Network → port override then restarting the addon. Currently 3000 is open with HA basic auth.
  • Basic auth gotcha: NGINX in front (from the addon) validates against your Home Assistant login (not the AdGuard admin). Successful basic-auth = HA creds, which then talk to AdGuard's API itself (only if AdGuard has no users configured — which is our case).
  • API endpoints (mounted under /control, e.g. http://192.168.0.129:3000/control/…):
  • GET /control/status
  • GET /control/rewrite/list
  • POST /control/rewrite/add or /control/rewrite/delete with JSON {"domain":"x.example.com","answer":"192.168.0.x"}
  • Current rewrites include (as of 2026‑09‑27): matrix, git, vault, joplin, ma pointing to HAOS (192.168.0.129); git.lan → .134, hermes.lan → .132, proxmox.lan → .131, cinny.lan → .136, matrix.lan → .133.
  • WeKan rewrites were just added: wekan.p.makanilani.com and wekan.lan → 192.168.0.129 (a different direction — they go through NPM, see below).

Note also: personal VPN WireGuard on wg0 (VPS) has each peer's /32 and uses 10.66.66.x. AdGuard (this one) is the LAN's resolver, different from the VPS's /opt/AdGuardHome on the VPS itself. They're separate installs.

2.3 Proxmox — 192.168.0.131 (node "proxmox")

PVE 9.2.20, single node, ~31 GB RAM, local-lvm 94 GB free.

API/token (recommended for automation, password never on disk): root@pam!hermes — token secret stored in sysadmin .env as PROXMOX_API_TOKEN (the "full" string you'd need at login is root@pam!hermes=SECRET; stored value includes that left-hand prefix).

Reachability: - HTTPS API (turned on for the hermesagent token): https://192.168.0.131:8006/api2/json/version - SSH: ssh -i ~/.ssh/forgejo_hermes root@192.168.0.131 (root key auth works).

Existing guests (as of 2026-09):

VMID Name Type Notes
100 hermesagent LXC this agent itself — Debian with hermes running
101 neo4j LXC
102 elementsynapse LXC Matrix Synapse
103 forgejo LXC Forgejo git server
104 postgresql LXC
105 alpine-cinny LXC Cinny web client (Alpine, minimal)
106 wekan LXC WeKan + MongoDB 8 (unprivileged, nesting, DHCP)

2.4 LXC 106 — "wekan"

Debian 13.6, 2 cores / 2 GB RAM / 16 GB disk, under /opt/wekan:

  • MongoDB 8.0.32 → mongod systemd service (bound to 127.0.0.1)
  • WeKan v12.06 → wekan systemd service, main.js run as root, env file /etc/wekan-env, WRITABLE_PATH=/opt/wekan/uploads (without WRITABLE_PATH it crash-loops with "Universal file server" errors)

Upgrade gotchas that cost real time — must do these in this order:

  1. apt-get install -y nodejs mongodb unzip (node 20 works with current WeKan)
  2. PostgreSQL 8.0 apt repo for Debian 13 (trixie) does not exist — use the Debian 12 (bookworm) repo of MongoDB 8.0, it works fine.
  3. Meteor bundles must be rebuilt: cd /opt/wekan/bundle/programs/server && npm ci — if plain npm install fails on the rebuild step with METEOR_SKIP_NPM_REBUILD errors, use METEOR_SKIP_NPM_REBUILD=1 npm install then run node npm-rebuild.js separately.
  4. Always restart wekan after config changes, then curl http://127.0.0.1:8081/ returning HTTP 200 = healthy.

Configs: - Pangolin: private resource (siteResourceId 3), domain domain1 (= p.makanilani.com wildcard), subdomain wekan, destination 192.168.0.137:8081, attach user vr7wzkztoy9tcg8. - AdGuard: two rewrites, both for the "no round trip to VPS" goal: wekan.p.makanilani.com → 192.168.0.129 (NPM), and wekan.lan → 192.168.0.129 (same target) - NPM: proxy host 9, wekan.p.makanilani.com → 192.168.0.137:8081, with block_exploits + allow_websocket (must NOT use allow_websocket via the normal field, we had to put the WS proxy headers into advanced_config because allow_websocket isn't part of the v2.15 API schema), + cert id 10 (Let's Encrypt, Cloudflare DNS-01, renewed by NPM). - HTTPS inside LAN works with real Let's Encrypt cert (via NPM), no warnings in browser.

Accounts: - WeKan admin: ysakakibara / ysakakibara@gmail.com, isAdmin: true (auto-promoted for first registered user). - To reset a WeKan user to a temp password when needed, use mongo: mongosh wekan --eval 'db.users.updateOne({username:"X"},{$set:bCryptHash})' and then reset via the client recovery paths described in wekan docs. - ADGuard password was rotated for API use — the login is ysakakibara@gmail.com with the HA password. If you don't know it, just re-type it in the HA UI and it'll re-bcrypt the file.


3. Credentials & tokens — where they live

Item Name in profile env Location
Home Assistant API HASS_TOKEN ~/.hermes/profiles/sysadmin/.env
Proxmox API token PROXMOX_API_TOKEN (+ PROXMOX_URL) same file
Pangolin API key PANGOLIN_API_KEY, PANGOLIN_SERVER_URL same file
NPM admin NPM_USERNAME, NPM_PASSWORD same file
Cloudflare DNS (for makanilani.com) NOT in git — on the VPS at /opt/pangolin/config/traefik/.cf-env
Forgejo deploy key / PAT FORGEJO_TOKEN hermes profile env
SSH keys ~/.ssh/forgejo_hermes, ~/.ssh/vpn_pangolin ~/.ssh/

Rule of thumb: secrets never in git. infra-configs carries snapshots and runbooks only.


4. Access cheat-sheet

# VPS (Pangolin, Traefik, VPS AdGuard, wg0 personal VPN)
ssh -i ~/.ssh/vpn_pangolin root@vpn.makanilani.com

# HAOS raspi (AdGuard LAN, NPM, HA, Newt, Vaultwarden, …)
ssh -i ~/.ssh/forgejo_hermes root@192.168.0.129   # lands in "Advanced SSH" addon; `ha` CLI works

# Proxmox node
ssh -i ~/.ssh/forgejo_hermes root@192.168.0.131
# or API:
export PROXMOX_URL=https://192.168.0.131:8006
curl -sk -H "Authorization: PVEAPIToken=root@pam!hermes=$PROXMOX_API_TOKEN" \
     $PROXMOX_URL/api2/json/version

# WeKan LXC
ssh -i ~/.ssh/forgejo_hermes root@192.168.0.137   # DHCP IP, check AdGuard rewrite for current

# Local services (LAN, no detour)
open http://192.168.0.129:81        # NPM
open http://192.168.0.129:8123      # HA
open https://192.168.0.131:8006     # Proxmox UI
open http://wekan.lan               # WeKan via NPM on LAN

5. Self-documenting conventions

  • Don't push secrets to GitHub. The .env-in-hermes-profile file (or encrypted 1Password) is the only vault. Anything you'd hate to leak — CF token, AdGuard bcrypt hash, mongo passwords, WeKan user bcrypt hashes, Proxmox root — must not appear as plaintext here.
  • Prefer API-driven config edits over manual UI clicking, so changes are reproducible (especially: NPM proxy hosts, AdGuard rewrites, Pangolin resources).
  • Infrastructure should be re-buildable from this repo: fresh VPS → redo file copy for WireGuard/AdGuard → runinstall Pangolin → run the vpn-vps/ runbook. Wekan LXC: clone or rebuild via the notes above.
  • Own the docs. If you debug something new (that "Public key mismatch" 一汽, that 21820/51820 hole punch issue), add it to the relevant Gotchas section here instead of cursed know-how in your head.

6. Change log (top = newest)

  • 2026-09-27 — WeKan LXC (CT 106) live: Pangolin private resource, NPM LAN reverse-proxy with Let's Encrypt cert id 10 (Cloudflare DNS-01), AdGuard rewrites for wekan.p.makanilani.com and wekan.lan.
  • 2026-09-26 — Proxmox API token root@pam!hermes + privilege separation disabled so hermesagent can create LXCs. Pangolin integration API enabled, routed at api.p.makanilani.com/v1.
  • 2026-09-24 — tmp WIP pitfalls resolved: Pangolin Android client punch bug (fosrl#3478), pangctl delete-client only real way to remove user clients.
  • 2026-09-23 — first connection of Pixel-9a Pangolin (OLM) — rackner edge needed udp/21820 open in addition to host ufw.
  • 2026-09-22 — initial Pangolin install on VPS; wildcard LE certificate via Cloudflare DNS-01; HAOS Newt connector site "home".