vault backup: 2026-05-10 22:32:42

This commit is contained in:
Vadym Samoilenko 2026-05-10 22:32:42 +01:00
parent 66518c5c28
commit e92e504dc2
5 changed files with 123 additions and 2 deletions

View file

@ -4,7 +4,7 @@
"syncFolder": "Hoarder",
"attachmentsFolder": "Hoarder/attachments",
"syncIntervalMinutes": 60,
"lastSyncTimestamp": 1778445148850,
"lastSyncTimestamp": 1778448753673,
"updateExistingFiles": false,
"excludeArchived": true,
"onlyFavorites": false,

View file

@ -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 |
<!-- Articles added automatically by compile.py -->
<!-- Format: | [[concepts/slug]] | One-line summary | daily/YYYY-MM-DD.md | date | -->

View file

@ -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

View file

@ -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

View file

@ -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]]