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 transferon 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/statusGET /control/rewrite/listPOST /control/rewrite/addor/control/rewrite/deletewith 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.comandwekan.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 →
mongodsystemd service (bound to 127.0.0.1) - WeKan v12.06 →
wekansystemd service,main.jsrun 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:
apt-get install -y nodejs mongodb unzip(node 20 works with current WeKan)- 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.
- Meteor bundles must be rebuilt:
cd /opt/wekan/bundle/programs/server && npm ci— if plainnpm installfails on the rebuild step withMETEOR_SKIP_NPM_REBUILDerrors, useMETEOR_SKIP_NPM_REBUILD=1 npm installthen runnode npm-rebuild.jsseparately. - Always restart
wekanafter config changes, then curlhttp://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.comandwekan.lan. - 2026-09-26 — Proxmox API token
root@pam!hermes+ privilege separation disabled so hermesagent can create LXCs. Pangolin integration API enabled, routed atapi.p.makanilani.com/v1. - 2026-09-24 — tmp WIP pitfalls resolved: Pangolin Android client punch bug
(fosrl#3478),
pangctl delete-clientonly 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".