diff --git a/.obsidian/plugins/hoarder-sync/data.json b/.obsidian/plugins/hoarder-sync/data.json index 6fbcda9..dd89017 100644 --- a/.obsidian/plugins/hoarder-sync/data.json +++ b/.obsidian/plugins/hoarder-sync/data.json @@ -4,7 +4,7 @@ "syncFolder": "Hoarder", "attachmentsFolder": "Hoarder/attachments", "syncIntervalMinutes": 60, - "lastSyncTimestamp": 1778445148850, + "lastSyncTimestamp": 1778448753673, "updateExistingFiles": false, "excludeArchived": true, "onlyFavorites": false, diff --git a/wiki/concepts/_index.md b/wiki/concepts/_index.md index 95a7135..92e326f 100644 --- a/wiki/concepts/_index.md +++ b/wiki/concepts/_index.md @@ -215,5 +215,6 @@ | [[wiki/concepts/overflow-hidden-clips-absolute-children\|overflow:hidden Clips Absolute/Fixed Children Regardless of z-index]] | `overflow: hidden` on a parent element **clips all descendant content at its boundary** — including | daily/2026-05-10.md | 2026-05-10 | | [[wiki/concepts/figma-fig-binary-format\|Figma .fig File — Proprietary Binary Format; Assets Extractable, Layout Data Not]] | `.fig` = ZIP with proprietary binary `canvas.fig` (magic bytes `fig-kiwij`); image assets extractable via `unzip`, but layer/component/text data requires Figma REST API or Desktop | daily/2026-05-10.md | 2026-05-10 | | [[wiki/concepts/vite-base-url-slash-concatenation]] | `${BASE_URL}file.png` works in dev (BASE_URL="/") but breaks in prod — always use explicit slash or `new URL(file, BASE_URL).href` | daily/2026-05-10.md | 2026-05-10 | +| [[wiki/concepts/adguard-parallel-instances-diagnostic]] | Two AdGuard instances on different IPs — how to identify the real production one vs empty placeholder; fix is router-side DNS update | daily/2026-05-03.md | 2026-05-03 | diff --git a/wiki/concepts/adguard-parallel-instances-diagnostic.md b/wiki/concepts/adguard-parallel-instances-diagnostic.md new file mode 100644 index 0000000..6c9ce7c --- /dev/null +++ b/wiki/concepts/adguard-parallel-instances-diagnostic.md @@ -0,0 +1,62 @@ +--- +title: "AdGuard — Two Parallel Instances, Identifying the Real Production One" +aliases: [adguard-duplicate-instances, adguard-shadow-instance, adguard-homelab-diagnostic] +tags: [adguard, homelab, dns, proxmox, lxc, docker, diagnostic] +sources: + - "daily/2026-05-03.md" +created: 2026-05-03 +updated: 2026-05-03 +--- + +# AdGuard — Two Parallel Instances, Identifying the Real Production One + +In a Proxmox homelab with LXC containers, it is possible to end up with two AdGuard Home instances running simultaneously on different IPs — one empty/unconfigured (a forgotten placeholder CT) and one fully configured production instance. The router may point DNS to the wrong one, silently making all filtering ineffective. + +## Key Points + +- **Two AdGuard instances can coexist on different IPs** — router DNS points to only one; if it points to the wrong one, filtering is silently disabled +- **The empty instance shows no query log** — open both UIs, check the query log; the real one will have active queries +- **Check the blocklist count** — the production instance has imported blocklists; the placeholder shows 0 lists +- **The fix is router-side** — update the DNS server IP in router settings to point to the production AdGuard; then destroy the placeholder CT + +## Details + +### How This Happens + +During homelab setup, a new LXC container (CT101) was created as a placeholder for AdGuard. Later, a Docker-based AdGuard was deployed inside CT102 for better maintainability alongside the rest of the monitoring stack. CT101 was never configured or destroyed. Both were reachable: + +| Instance | IP | Type | State | +|----------|----|------|-------| +| CT101 | 192.168.1.62 | LXC native | Empty — no blocklists, no rewrites | +| CT102 Docker | 192.168.1.225 | Docker in CT102 | Production — full config, blocklists, DNS rewrites | + +The router was pointing to `192.168.1.62` (CT101), so all DNS queries bypassed filtering entirely. + +### How to Identify the Real Instance + +1. **Open both UIs** — `http://192.168.1.62` and `http://192.168.1.225` +2. **Check the Dashboard query log** — the production instance shows live queries within seconds; the placeholder shows zero +3. **Check Filters → DNS blocklists** — production has multiple lists enabled; placeholder shows none +4. **Check DNS rewrites** — production has all internal service rewrites; placeholder has none + +### Fix + +1. Update router DNS: `Advanced → DNS` (varies by router) → Primary DNS: `192.168.1.225` +2. Verify filtering is working: query a known blocked domain; should return `0.0.0.0` +3. Destroy placeholder CT: Proxmox UI → CT101 → Stop → Destroy + +### Prevention + +- Destroy placeholder CTs as soon as the real service is deployed elsewhere +- Document which IP each AdGuard instance (or any duplicate service) runs on in a homelab inventory +- Use distinct hostnames (`adguard.local` vs `adguard-old.local`) to make both UIs accessible without remembering IPs + +## Related Concepts + +- [[wiki/concepts/adguard-dns-rewrites-homelab]] — DNS rewrites and blocklist configuration for the production AdGuard instance +- [[wiki/concepts/adguard-blocklist-setup]] — blocklist selection and Custom filtering rules +- [[wiki/homelab/_index]] — homelab infrastructure overview; CT102 is the monitoring stack container + +## Sources + +- [[daily/2026-05-03.md]] — Security audit revealed CT101 (192.168.1.62) was an empty AdGuard placeholder; CT102 Docker (192.168.1.225) was the real production instance with all config; router DNS was pointing to the wrong one; CT101 scheduled for destruction diff --git a/wiki/concepts/glance-dashboard-config.md b/wiki/concepts/glance-dashboard-config.md index 139dcbe..0fd6c44 100644 --- a/wiki/concepts/glance-dashboard-config.md +++ b/wiki/concepts/glance-dashboard-config.md @@ -4,8 +4,9 @@ aliases: [glance-dashboard, glance-yaml-config, glance-homarr-replacement] tags: [glance, dashboard, homelab, monitoring, yaml, self-hosted] sources: - "daily/2026-04-29.md" + - "daily/2026-05-03.md" created: 2026-04-29 -updated: 2026-04-29 +updated: 2026-05-03 --- # Glance Dashboard — Config Patterns and Homelab Setup @@ -96,6 +97,55 @@ Glance can embed Grafana panels via iframe. For CPU power draw and thermal monit Power Cost dashboard was also proxied via NPM: `https://power.ai-impress.com → 192.168.1.225:8091` +### Hot-Reload — No Container Restart Needed + +Glance picks up changes to `glance.yml` automatically without restarting the container. This makes iterative dashboard development fast: edit the file, save, and refresh the browser. + +This is the default behavior for Glance as of v0.7.x — no polling interval config or signal is needed. The binary watches the config file with inotify. + +### Jellyfin Sessions Widget Fix + +The sessions widget uses Go templates to render `NowPlayingItem.Name`. If the session has no active item (user is paused or browsing), accessing `.NowPlayingItem.Name` panics the template. Fix: + +```yaml +- type: custom-api + url: http://192.168.1.111:8096/Sessions?apiKey={{ .Env.JELLYFIN_API_KEY }} + template: | + {{ range .Response }} + {{ if .Exists "NowPlayingItem" }} + {{ .NowPlayingItem.Name }} — {{ .UserName }} + {{ end }} + {{ end }} +``` + +The API key must be moved to `headers:` or `{{ .Env.VARIABLE }}` — embedding it directly in the URL path leaks it in Glance's request logs. + +### Prometheus Path Mismatch + +When a Prometheus query uses a mount path (e.g., for disk usage), the path must match the actual mount inside the container, not the host path. CT102 mounts the media drive at `/mnt/data`, not `/mnt/media` — using the wrong path returns 0 for the widget. + +```yaml +# Wrong — /mnt/media doesn't exist inside CT102 +expr: node_filesystem_free_bytes{mountpoint="/mnt/media"} + +# Correct +expr: node_filesystem_free_bytes{mountpoint="/mnt/data"} +``` + +Debug with: `docker exec -it prometheus curl -s 'http://localhost:9090/api/v1/label/mountpoint/values'` + +### RSS Feed URL Patterns + +Common RSS feed gotchas found in practice: + +| Source | Wrong | Correct | +|--------|-------|---------| +| Habr (hub) | `https://habr.com/ru/hub/llm/rss/` | `https://habr.com/ru/hubs/neural_networks/rss/` | +| Habr (hub) | `https://habr.com/ru/hub/llm_tools/rss/` | `https://habr.com/ru/hubs/llm_tools/rss/` | +| deeplearning.ai | any URL | No RSS feed — replaced with Simon Willison's blog (`https://simonwillison.net/atom/everything/`) | + +Habr uses `hubs/` (plural) for topic feeds. The singular `hub/` URL returns 404. Verify RSS URLs in a browser before embedding in Glance config. + ## Related Concepts - [[wiki/concepts/prometheus-joules-watts-gotcha]] — RAPL `rate(joules_total)` is already watts; multiplying by 1000 is a display bug @@ -105,3 +155,4 @@ Power Cost dashboard was also proxied via NPM: `https://power.ai-impress.com → ## Sources - [[daily/2026-04-29.md]] — Glance install session: `$include` page split failure, monitor timeout root cause (Cloudflare IPs), NPM password reset via SQLite bcrypt, RAPL metrics integration, location set to Henley-on-Thames UK +- [[daily/2026-05-03.md]] — Glance dashboard redesign: hot-reload confirmed (no restart needed), Jellyfin sessions widget fix (`.Exists "NowPlayingItem"` + token in headers), Prometheus `/mnt/media` vs `/mnt/data` path mismatch, Habr RSS URL format (`hubs/` plural, not `hub/` singular), deeplearning.ai has no RSS diff --git a/wiki/log.md b/wiki/log.md index 74562a9..1c4c6d2 100644 --- a/wiki/log.md +++ b/wiki/log.md @@ -1,6 +1,13 @@ # Build Log +## [2026-05-10T23:00:00+02:00] compile | daily/2026-05-03.md (addendum — Glance widgets + dual AdGuard) +- Source: daily/2026-05-03.md +- Articles created: [[wiki/concepts/adguard-parallel-instances-diagnostic]] +- Articles updated: [[wiki/concepts/glance-dashboard-config]] (added hot-reload, Jellyfin sessions widget fix, Prometheus path mismatch, Habr RSS URL format `hubs/` vs `hub/`) +- Index updates: [[wiki/concepts/_index]] (+1 new row, adguard-parallel-instances-diagnostic) +- Note: Two prior passes (2026-05-08T22:00 and 2026-05-08T23:30) had captured the main debugging patterns but noted dual AdGuard and Glance widget fixes as "handled as notes" without actually writing them. This pass captures them properly: (1) CT101 empty AdGuard placeholder vs CT102 Docker production instance — router DNS pointed to wrong one; (2) Glance hot-reload confirmed, Jellyfin sessions widget `.Exists "NowPlayingItem"` fix, Prometheus `/mnt/media` vs `/mnt/data` path mismatch, Habr `hubs/` plural URL format. + ## [2026-05-11T00:45:00+01:00] compile | daily/2026-05-10.md (addendum — Vite BASE_URL slash concatenation) - Source: daily/2026-05-10.md - Articles created: [[wiki/concepts/vite-base-url-slash-concatenation]]