vault backup: 2026-04-28 21:55:05

This commit is contained in:
Vadym Samoilenko 2026-04-28 21:55:05 +01:00
parent 1cd515b382
commit cdade805fd
12 changed files with 575 additions and 3 deletions

View file

@ -31,6 +31,18 @@ AI-assisted banner generation tool for Barclays marketing assets. Workflow: Brie
- **Port:** 8010 (backend API)
## Sessions
### 2026-04-28 Implement banner generation with AI copy,
**Asked:** Implement banner generation with AI copy, DAM images, and icon library support, plus checkbox selection system for variant filtering.
**Done:** Built backend conversation models with intent routing and checkbox-based variant selection system for Medium/Large banner previews.
### 2026-04-28 Implement checkbox selection system for users
**Asked:** Implement checkbox selection system for users to choose which banner variants to move forward with to the editor.
**Done:** Built backend conversation models and intent routing, plus frontend checkbox selection with validation for variant selection workflow.
### 2026-04-28 Implement checkbox selection system for users
**Asked:** Implement checkbox selection system for users to choose banner variants before moving to the editor.
**Done:** Built backend conversation models and intent routing, plus frontend checkbox UI for variant selection with validation.
### 2026-04-28 Implement checkbox selection system for users
**Asked:** Implement checkbox selection system for users to choose banner variants before moving to the editor.
**Done:** Added checkboxes to each variant, disabled "Open banner editor" button until valid selections are made, and filtered variants to show only selected ones in the editor.
@ -287,6 +299,9 @@ AI-assisted banner generation tool for Barclays marketing assets. Workflow: Brie
## Change Log
| Date | Requested | Changed | Files |
|------|-----------|---------|-------|
| 2026-04-28 | Banner variant system | Conversation models, intent router, variant selection checkboxes, migration, API endpoints | models/conversation.py, models/job.py, services/intent_router.py, api/conversations.py, alembic/versions/0005_add_conversations.py |
| 2026-04-28 | Banner variant selection | Checkboxes, single Medium/Large selection, editor button validation, filtered variants display | models/conversation.py, models/__init__.py, models/job.py, alembic/versions/0005_add_conversations.py, services/intent_router.py, api/conversations.py |
| 2026-04-28 | Banner variant selection | Checkbox UI, intent router, conversation models, validation logic | models/conversation.py, models/job.py, services/intent_router.py, api/conversations.py, alembic/versions/0005_add_conversations.py |
| 2026-04-28 | Banner variant selection | Add checkboxes to variants, disable editor button until valid selections, filter selected variants in editor | VariantsPage.tsx, BannerEditor.tsx |
| 2026-04-28 | Banner variant selection | Add checkboxes, selection validation, conditional button state | BannerVariants.tsx, BannerEditor.tsx |
| 2026-04-28 | Checkbox selection system | Variant checkboxes, selection validation, editor button gating | VariantsPage.tsx, BannerEditor.tsx |

View file

@ -293,3 +293,12 @@ tags: [daily]
- 21:42 | `aimpress`
- **Asked:** Developer asked for Proxmox address and port connectivity troubleshooting, received network unreachability error.
- **Done:** Diagnosed that RuTracker indexer integration is broken in current Prowlarr version and confirmed AmneziaVPN is incompatible with Gluetun setup.
- 21:51 | `Barclays-banner-builder`
- **Asked:** Implement checkbox selection system for users to choose banner variants before moving to the editor.
- **Done:** Built backend conversation models and intent routing, plus frontend checkbox UI for variant selection with validation.
- 21:53 | `Barclays-banner-builder`
- **Asked:** Implement checkbox selection system for users to choose which banner variants to move forward with to the editor.
- **Done:** Built backend conversation models and intent routing, plus frontend checkbox selection with validation for variant selection workflow.
- 21:54 | `Barclays-banner-builder`
- **Asked:** Implement banner generation with AI copy, DAM images, and icon library support, plus checkbox selection system for variant filtering.
- **Done:** Built backend conversation models with intent routing and checkbox-based variant selection system for Medium/Large banner previews.

View file

@ -23,8 +23,8 @@ This 3-hop pattern works for hundreds of articles without vector search.
| [[wiki/tech-patterns/_index\|tech-patterns/]] | Recurring tech stacks: FastAPI, React/Vite, Next.js, Azure AD, AI, Box, One2Edit, Redis/Celery, cost-tracker | 13 |
| [[wiki/architecture/_index\|architecture/]] | Cross-cutting architectural patterns: Docker Compose, multi-agent AI, GCP timeout, RAG, hotfolder, optical-dev deploy, cost-tracker, new-project checklist, troubleshooting playbooks, ADR log | 10 |
| [[wiki/client-knowledge/_index\|client-knowledge/]] | Per-client notes for Ford, H&M, L'Oréal, Barclays, Ferrero, 3M | 6 |
| [[wiki/concepts/_index\|concepts/]] | Atomic knowledge extracted from Claude Code sessions | 47 |
| [[wiki/connections/_index\|connections/]] | Cross-cutting insights linking 2+ concepts: FastAPI+Azure AD+Docker trinity, AI→cost-tracker, Apache+Vite basePath, GCP→REST polling, Box+hotfolder | 8 |
| [[wiki/concepts/_index\|concepts/]] | Atomic knowledge extracted from Claude Code sessions | 51 |
| [[wiki/connections/_index\|connections/]] | Cross-cutting insights linking 2+ concepts: FastAPI+Azure AD+Docker trinity, AI→cost-tracker, Apache+Vite basePath, GCP→REST polling, Box+hotfolder, Docker DNS+AdGuard | 9 |
| [[wiki/qa/_index\|qa/]] | Filed answers to queries (saved with `--file-back`) | 0 |
| [[wiki/homelab/_index\|homelab/]] | Self-hosted infra: Proxmox install, IOMMU/PCI passthrough, hypervisor setup, budget builds, HP Elitedesk G3, Homarr API + Apps + Boards + Certificates + Integrations + Settings + Tasks + AdGuard + Clock + Docker Stats + Docker Integration + Download Client + Firewall + Proxmox Integration + Radarr + Readarr + Sonarr + Bookmarks + Calendar + Icons + App Widget + Weather + GitHub + Nextcloud + qBittorrent + RSS Feed + Speedtest Tracker + System Health Monitoring + System Resources + Services Map + Media Stack | 38 |
| [[wiki/web-agency/_index\|web-agency/]] | AI-assisted website building & selling: Claude Code, Nanobanana 2, Kling, LaunchPath MCP | 9 |

View file

@ -52,6 +52,10 @@
| [[wiki/concepts/litellm-pricing-source]] | LiteLLM model_prices JSON as auto-updating LLM price source — why scraping provider sites is fragile | ai-cost-tracker | 2026-04-27 |
| [[wiki/concepts/authentik-homelab-tradeoffs]] | Authentik v2026.2.2 migration failure `0056`, ~500MB RAM overhead, NPM auth_request removal — when to keep vs remove | daily/2026-04-27.md | 2026-04-27 |
| [[wiki/concepts/icloud-git-sync-conflict]] | iCloud creates `main 2` files in `.git/refs/heads/` on sync conflict — causes `badRefName`; fix and prevention | daily/2026-04-27.md | 2026-04-27 |
| [[wiki/concepts/homarr-sqlite-integration-cleanup]] | Homarr upgrade removes widget kinds but leaves stale SQLite rows — crashes integrations page with TypeError | daily/2026-04-28.md | 2026-04-28 |
| [[wiki/concepts/docker-lxc-dns-configuration]] | Docker containers in LXC/Proxmox use router DNS by default — need explicit AdGuard DNS in compose for internal domains | daily/2026-04-28.md | 2026-04-28 |
| [[wiki/concepts/mac-address-randomization-dhcp]] | Apple MAC randomization creates multiple DHCP leases per device — exhausts pool, causes IP conflicts; disable per-network | daily/2026-04-28.md | 2026-04-28 |
| [[wiki/concepts/prowlarr-flaresolverr-limitation]] | Prowlarr bypasses FlareSolverr for some indexers (RuTracker); VPN alternatives: SOCKS5, WireGuard in LXC, router VPN | daily/2026-04-28.md | 2026-04-28 |
<!-- Articles added automatically by compile.py -->
<!-- Format: | [[concepts/slug]] | One-line summary | daily/YYYY-MM-DD.md | date | -->

View file

@ -4,8 +4,9 @@ aliases: [adguard-blocklists, adguard-dns-filter, adguard-hagezi, adguard-oisd,
tags: [adguard, dns, homelab, ad-blocking, selfhosted, blocklists]
sources:
- "daily/2026-04-23.md"
- "daily/2026-04-28.md"
created: 2026-04-23
updated: 2026-04-23
updated: 2026-04-28
---
# AdGuard Home — Blocklist Setup and Optimization
@ -19,6 +20,7 @@ A fresh AdGuard Home installation ships with a minimal default configuration: on
- **HaGeZi Multi Pro++** (~600k domains) is the best general-purpose upgrade — aggressive but low false-positive rate
- **HaGeZi TIF** (~1M+ domains) targets threat intelligence feeds (malware, phishing, C2) — complements ad blocking with security coverage
- DNS blocklists **cannot block YouTube ads** — see [[wiki/concepts/dns-youtube-ad-blocking]] for why and what works instead
- **Large blocklist sets (~38 MB) can OOM-kill AdGuard on startup** — AdGuard loads all filter lists into memory at once; running in a Docker container or LXC with insufficient RAM causes exit code 137 (SIGKILL); minimum 256 MB RAM for the 5-list stack, 512 MB recommended
## Details
@ -98,6 +100,23 @@ Each entry shows:
If a list shows 0 domains or "Error fetching", the URL may be stale or the AdGuard instance has no internet access.
### OOM Risk with Large Blocklist Sets
AdGuard Home loads all enabled blocklists into memory simultaneously during startup. The 5-list stack (~2.2M domains, ~38 MB of raw filter data) requires significant RAM headroom:
| RAM allocation | Risk |
|---------------|------|
| < 128 MB | Very high OOM kill at startup (exit code 137) |
| 128256 MB | Medium — may OOM under peak load |
| 256512 MB | Safe for 5-list stack |
| 512 MB+ | Comfortable, room for future lists |
**Exit code 137** means the process was killed by SIGKILL, typically by the Linux OOM killer. In Docker: `docker ps -a` shows `Exited (137)`. In systemd: `journalctl -u adguard` shows `Killed`.
Fix: increase the container's memory limit, or temporarily disable 12 of the largest lists (HaGeZi TIF is the biggest at ~1M domains) until RAM is increased.
For Proxmox LXC: `pct set <CTID> --memory 512` to raise to 512 MB. For Docker: add `mem_limit: 512m` to the service in `docker-compose.yml`.
## Related Concepts
- [[wiki/concepts/dns-youtube-ad-blocking]] — what AdGuard blocklists CAN'T do: block YouTube ads

View file

@ -0,0 +1,123 @@
---
title: "Docker in LXC/Proxmox — DNS Configuration for Internal Homelab Domains"
aliases: [docker-lxc-dns, docker-internal-dns, docker-adguard-dns, docker-compose-dns]
tags: [docker, lxc, proxmox, dns, adguard, homelab, networking]
sources:
- "daily/2026-04-28.md"
created: 2026-04-28
updated: 2026-04-28
---
# Docker in LXC/Proxmox — DNS Configuration for Internal Homelab Domains
Docker containers running inside a Proxmox LXC use the host LXC's DNS configuration, which by default points to the router (e.g., `192.168.1.1`). The router's upstream DNS knows nothing about internal homelab domains (e.g., `*.ai-impress.com`). This means services inside Docker containers cannot resolve other homelab services by their friendly domain names — even though the LXC host itself may resolve them correctly if AdGuard is configured differently at the OS level.
## Key Points
- **Docker containers inherit DNS from the LXC host** — the LXC's `/etc/resolv.conf` (usually pointing at the router's DNS) is passed into containers by default
- **Router DNS does not know internal domains** — AdGuard Home holds the split-horizon DNS records (e.g., `jellyfin.ai-impress.com → 192.168.1.x`); the router forwards to upstream public DNS which has no knowledge of these records
- **Fix:** Add an explicit `dns:` entry in `docker-compose.yml` pointing at AdGuard Home (`192.168.1.225`); this overrides the container's DNS regardless of the host's resolver config
- **Service ping checks (Homarr, Uptime Kuma) fail silently** when internal domain names are used as health check targets — they succeed via IP, fail via hostname, making the root cause non-obvious
- This is distinct from the host LXC's DNS — the LXC itself may resolve fine (if `/etc/resolv.conf` points to AdGuard), but Docker adds its own DNS indirection layer
## Details
### Why Docker Ignores the LXC's AdGuard Config
When Docker starts a container, it writes the container's `/etc/resolv.conf` based on:
1. The `dns:` setting in `docker-compose.yml` (explicit override — highest priority)
2. The Docker daemon's `--dns` flag in `/etc/docker/daemon.json`
3. The host's `/etc/resolv.conf` (fallback — this is what normally propagates)
In a Proxmox LXC, the LXC's `/etc/resolv.conf` typically points to the router (`nameserver 192.168.1.1`) because that's what the router's DHCP assigns. Even if you've manually edited the LXC's `/etc/resolv.conf` to use AdGuard, Docker may not pick it up unless the daemon is configured or the compose file specifies DNS explicitly.
### The Fix: Explicit DNS in docker-compose.yml
```yaml
# docker-compose.yml
services:
homarr:
image: ghcr.io/ajnart/homarr:latest
dns:
- 192.168.1.225 # AdGuard Home — knows internal domains
- 1.1.1.1 # Cloudflare — fallback for public DNS
ports:
- "7575:7575"
volumes:
- ./data:/data
```
The `dns:` array replaces the container's DNS entirely — the order matters (AdGuard first, public fallback second). After adding this and restarting the container, `ping jellyfin.ai-impress.com` works from inside the container.
### Global Fix: Docker Daemon DNS
To apply AdGuard DNS to all containers on an LXC without per-compose changes:
```json
// /etc/docker/daemon.json
{
"dns": ["192.168.1.225", "1.1.1.1"]
}
```
```bash
systemctl restart docker
```
This makes all Docker containers on that LXC use AdGuard as their DNS server by default. Per-compose `dns:` settings still override this.
### Diagnosing DNS Failures Inside Docker
```bash
# Enter the container
docker exec -it homarr sh
# Check what DNS server the container is using
cat /etc/resolv.conf
# Should show: nameserver 192.168.1.225
# If it shows: nameserver 192.168.1.1 → router DNS → no internal domains
# Test resolution directly
nslookup jellyfin.ai-impress.com 192.168.1.225
# Expected: Address: 192.168.1.x
# Test what the container currently resolves to
nslookup jellyfin.ai-impress.com
# If this fails but the above works → container DNS is wrong
```
### Service Health Check Failures
Many homelab dashboard services (Homarr, Homepage, Uptime Kuma) perform ping/HTTP health checks against configured service URLs. When internal domain names are used (e.g., `http://jellyfin.ai-impress.com`), the check fails if the container can't resolve the domain — but the failure looks like a connectivity problem, not a DNS problem.
Indicators that DNS is the issue:
- Health check fails using the domain name, succeeds using the IP directly
- `nslookup <domain>` fails from inside the container
- `cat /etc/resolv.conf` in the container shows the router IP, not AdGuard
### Static IP for LXC Services
When a service (like Immich in CT105) is using DHCP and gets a different IP after a router change or LXC restart, all DNS rewrites and health checks that reference the old IP break. The solution: assign a static IP in the Proxmox LXC config.
In Proxmox web UI → CT → Network → Edit the network interface:
- Set IP to static (e.g., `192.168.1.71/24`)
- Set gateway to `192.168.1.1`
Or via CLI on the Proxmox host:
```bash
pct set 105 --net0 name=eth0,bridge=vmbr0,ip=192.168.1.71/24,gw=192.168.1.1
```
Static IPs for services used in DNS rewrites and health checks should be considered mandatory — DHCP assignments change silently.
## Related Concepts
- [[wiki/concepts/adguard-dns-rewrites-homelab]] — AdGuard Home wildcard DNS rewrites that Docker containers need to reach
- [[wiki/connections/docker-dns-adguard-split-horizon]] — the cross-cutting connection between Docker networking and AdGuard split-horizon DNS
- [[wiki/concepts/homarr-sqlite-integration-cleanup]] — Homarr context where this DNS issue was discovered
- [[wiki/concepts/lxc-arp-cache-api-failures]] — another LXC networking issue that produces similar "service unreachable" symptoms
- [[wiki/homelab/_index]] — homelab infrastructure context
## Sources
- [[daily/2026-04-28.md]] — Homarr Docker container (CT107 LXC) could not ping `jellyfin.ai-impress.com` — container DNS pointed at router, not AdGuard; fixed by adding `dns: [192.168.1.225, 1.1.1.1]` to `docker-compose.yml`; CT105 (Immich) also given static IP `192.168.1.71` to prevent DHCP-related IP changes

View file

@ -0,0 +1,96 @@
---
title: "Homarr — SQLite Integration Cleanup After Major Upgrades"
aliases: [homarr-sqlite, homarr-upgrade-crash, homarr-integration-kind, homarr-typeerror]
tags: [homarr, homelab, sqlite, dashboard, selfhosted, upgrade]
sources:
- "daily/2026-04-28.md"
created: 2026-04-28
updated: 2026-04-28
---
# Homarr — SQLite Integration Cleanup After Major Upgrades
When Homarr removes a widget integration kind in a major update, existing entries with that kind remain in the SQLite database. On next load, the dashboard UI tries to read the `name` property of the unknown integration type, finds `undefined`, and crashes with `TypeError: Cannot read properties of undefined (reading 'name')`. The `/manage/integrations` page becomes inaccessible until the stale row is removed directly from SQLite.
## Key Points
- **Root cause:** Homarr stores integrations in an `integration` SQLite table with a `kind` column; when a kind is removed from the codebase, the row persists — the app crashes when it tries to look up the removed kind's metadata
- **Symptom:** `TypeError: Cannot read properties of undefined (reading 'name')` in the browser console; `/manage/integrations` page crashes on load
- **Fix:** Delete the stale row from SQLite directly — `DELETE FROM integration WHERE kind = 'dockerContainers';`
- **Known removed kind (April 2026 update):** `dockerContainers` — was removed when Homarr redesigned its Docker integration; entries with this kind crash the integrations page
- **Safe operation:** deleting the stale integration row only removes Homarr's internal reference to the integration widget; the Docker service itself is unaffected
## Details
### Why This Happens
Homarr's integrations system maps each integration widget to a `kind` string (e.g., `dockerContainers`, `proxmox`, `jellyfin`). When Homarr updates its integration registry (renaming or removing a kind), existing SQLite rows with the old kind become orphaned. The dashboard's integration page iterates over all rows and looks up each kind in the registry — a missing kind returns `undefined`, and the subsequent `.name` access throws.
The crash happens at page load, not lazily — meaning every visit to `/manage/integrations` fails, making it impossible to remove the bad integration through the UI.
### Finding and Removing Stale Integrations
Homarr stores its database in the container at `/data/db.sqlite` (exact path may vary by install method):
```bash
# Enter the Homarr container or LXC
# For Docker:
docker exec -it homarr sh
# For LXC-based install, SSH into the container directly
# Open the database
sqlite3 /data/db.sqlite
# List all integration kinds to find the unknown one
SELECT id, name, kind FROM integration;
# Remove the stale row (example: dockerContainers kind)
DELETE FROM integration WHERE kind = 'dockerContainers';
# Verify
SELECT COUNT(*) FROM integration WHERE kind = 'dockerContainers';
# Should return 0
.quit
```
After removing the row, restart Homarr and the integrations page will load normally.
### Diagnosing Which Kind Is Breaking
If the error message alone isn't clear, check the browser DevTools console for the full stack trace — it typically includes the `kind` value being processed when the crash occurs. Alternatively, query the database before deleting:
```sql
-- See what kinds exist vs what's in the app's registry
SELECT DISTINCT kind FROM integration ORDER BY kind;
```
Cross-reference the listed kinds against the current Homarr version's supported integration types. Any kind not present in the current release is a candidate for removal.
### Post-Upgrade Checklist for Homarr
After any major Homarr version bump:
1. Check release notes for removed or renamed integration kinds
2. Open `/manage/integrations` — if it crashes, open DevTools console for the error
3. Query `SELECT DISTINCT kind FROM integration;` to find all stored kinds
4. Remove rows for any kind that no longer exists in the current version
5. Restart Homarr
This is a one-time fix per removed kind — Homarr does not provide automatic migration for removed integration types.
### Docker DNS Issue (Same Session)
When the `dockerContainers` integration was working, Homarr also had a related issue: ping checks for internal services (e.g., Jellyfin) failed because Homarr's Docker container was using the router (`192.168.1.1`) as DNS instead of AdGuard Home (`192.168.1.225`). Internal domains like `jellyfin.ai-impress.com` only resolve via AdGuard. The fix: add explicit DNS to the Homarr `docker-compose.yml`. See [[wiki/concepts/docker-lxc-dns-configuration]].
## Related Concepts
- [[wiki/concepts/docker-lxc-dns-configuration]] — Docker containers in LXC/Proxmox need explicit internal DNS for homelab domains to resolve
- [[wiki/concepts/homarr-proxmox-integration]] — Homarr Proxmox integration cert trust and general Homarr setup
- [[wiki/concepts/proxmox-container-502-misdiagnosis]] — similar pattern of diagnosing before taking destructive action
- [[wiki/homelab/_index]] — homelab dashboard and infrastructure context
## Sources
- [[daily/2026-04-28.md]] — Homarr `/manage/integrations` crashed with `TypeError: Cannot read properties of undefined (reading 'name')`; root cause was stale `dockerContainers` kind in SQLite from April 2026 Homarr update; fixed by `DELETE FROM integration WHERE kind = 'dockerContainers'`

View file

@ -0,0 +1,106 @@
---
title: "MAC Address Randomization — DHCP Pool Exhaustion and IP Conflicts"
aliases: [mac-randomization, dhcp-conflicts, apple-mac-randomization, private-wifi-address]
tags: [dhcp, networking, homelab, apple, ios, macos, router, wifi]
sources:
- "daily/2026-04-28.md"
created: 2026-04-28
updated: 2026-04-28
---
# MAC Address Randomization — DHCP Pool Exhaustion and IP Conflicts
iOS 14+ and macOS 12+ (Monterey+) enable **Private Wi-Fi Address** by default on all Wi-Fi networks. This feature assigns a different randomly-generated MAC address per Wi-Fi network per day/week. On a home network with a small DHCP pool, each randomized MAC creates a new DHCP lease — the same physical device appears as multiple "clients" with different MAC addresses, exhausting the lease pool and causing IP conflicts.
## Key Points
- **Apple devices generate a new random MAC per network by default**`7E:FE:CE:2E:68:84` appearing on 4 different IPs is the classic symptom of MAC randomization, not a rogue device
- **DHCP lease pool exhaustion:** if the pool is small (e.g., `192.168.1.100150`, 50 addresses) and 23 Apple devices rotate MACs daily, the pool fills up — new devices get "no available address"
- **IP conflicts** arise when a new lease is issued for an IP that a previously-DHCP-assigned device still considers its own (lease time vs rotation period mismatch)
- **Fix:** disable "Private Wi-Fi Address" per network in Settings → Wi-Fi → ⓘ → Private Wi-Fi Address → Off; the device then uses its permanent hardware MAC for that network
- **DHCP reservation by MAC** is incompatible with randomization — you cannot reliably reserve IPs for Apple devices unless randomization is disabled for that network
## Details
### How MAC Randomization Works on Apple Devices
Starting with iOS 14 (2020) and macOS Monterey (2021), Apple enabled per-network randomized MACs by default:
- **iOS/iPadOS:** Settings → Wi-Fi → tap ⓘ next to network → Private Wi-Fi Address
- **macOS:** System Preferences/Settings → Network → Wi-Fi → Details → Private Wi-Fi Address
- Default: **On** — the device uses a "stable" randomized MAC for each network (same MAC per network until the setting is changed or the network is forgotten)
- In newer iOS versions, the MAC may rotate periodically even for the same network (rotating vs stable random)
The randomized MAC starts with a locally-administered bit set in the second nibble: `x2:`, `x6:`, `xA:`, or `xE:` where `x` is any hex digit. The `7E:` prefix in `7E:FE:CE:2E:68:84` is a locally-administered address — confirming this is a randomized MAC.
### DHCP Impact
A home router's DHCP server allocates addresses based on MAC address — each unique MAC gets its own lease. When an Apple device rotates its MAC:
1. Previous lease (old MAC) remains active until it expires (e.g., 24h lease time)
2. Device connects with new MAC → gets a new lease (new IP)
3. Old lease is not released (device doesn't know to release it with the old MAC)
4. After enough rotations, the pool has `N_devices × N_rotations` active leases
With a 4-hour lease time and daily rotation: one iPhone creates 6 leases per day. With a 24-hour lease time and daily rotation: 2 leases per device per day (yesterday's + today's). Larger lease times reduce pool exhaustion but slow recovery.
### Diagnosing the Problem
In the router's DHCP client list, look for:
- Multiple entries with similar hostnames (`iPhone`, `iPhone-2`, `iPhone-3`)
- Entries with locally-administered MACs (second nibble is `2`, `6`, `A`, or `E`)
- One physical device showing up as 24 different "clients" simultaneously
```bash
# On the router (if SSH/CLI is available)
# Or in the web UI → DHCP clients list
# Look for multiple entries with the same hostname
```
The specific symptom from 2026-04-28: MAC `7E:FE:CE:2E:68:84` appeared on 4 different IP addresses in the DHCP lease table — one device with 4 different MACs from different rotation periods.
### Fix: Disable Private Wi-Fi Address Per Network
**iPhone/iPad (iOS/iPadOS):**
1. Settings → Wi-Fi
2. Tap ⓘ next to your home network name
3. Scroll to **Private Wi-Fi Address**
4. Toggle **Off**
5. Reconnect to the network — device will use its permanent hardware MAC
**Mac (macOS Ventura/Sonoma/Sequoia):**
1. System Settings → Network → Wi-Fi
2. Click **Details...** next to your home network
3. **Private Wi-Fi Address** → set to **Off**
4. Click OK
**Apple TV / HomePod:**
Settings → Network → Wi-Fi → select network → Private Wi-Fi Address → Off
After disabling on all devices, the router's DHCP lease table will consolidate to one lease per physical device. Old randomized-MAC leases will expire after the lease time.
### DHCP Configuration Best Practices for Homelab
| Setting | Recommendation | Why |
|---------|---------------|-----|
| Pool range | `192.168.1.100199` (100 addresses) | Avoids overlap with static IPs (`199` reserved for servers) |
| Lease time | `24h` minimum | Too short = more frequent MAC rotation leases |
| Static reservations | By hardware MAC (after disabling randomization) | Reliable only with fixed MACs |
| Server IPs | `149` static (Proxmox, VMs, Docker) | Stable, never in DHCP pool |
Specifically: reserve `192.168.1.48` for Proxmox, `192.168.1.71` for Immich, `192.168.1.225` for AdGuard — these should have static IPs or DHCP reservations, never dynamic addresses.
### When Randomization Is Desirable
MAC randomization provides real privacy benefits on **public networks** (cafes, airports, hotels) — it prevents tracking across visits. For home networks where you control the router and want reliable DHCP reservations, disabling it is the correct trade-off. Most routers' "guest network" feature is the right privacy solution for home guests.
## Related Concepts
- [[wiki/concepts/adguard-dns-rewrites-homelab]] — DHCP conflicts can break AdGuard DNS reservations if device IPs change
- [[wiki/concepts/docker-lxc-dns-configuration]] — static IP assignment for LXC services to avoid DHCP-related address changes
- [[wiki/concepts/proxmox-lxc-autostart]] — related: LXC containers should have static IPs for reliable DNS rewrites
- [[wiki/homelab/_index]] — homelab network infrastructure context
## Sources
- [[daily/2026-04-28.md]] — MAC `7E:FE:CE:2E:68:84` appeared on 4 IPs in DHCP client list; identified as Apple MAC randomization; resolution: disable Private Wi-Fi Address on each Apple device for the home network; DHCP pool recommendation: `192.168.1.100199`, lease 24h+

View file

@ -0,0 +1,113 @@
---
title: "Prowlarr + FlareSolverr — Direct Request Bug and VPN Alternatives"
aliases: [prowlarr-flaresolverr, flaresolverr-bypass, prowlarr-cloudflare, prowlarr-rutracker]
tags: [prowlarr, flaresolverr, media-stack, homelab, torrent, indexer, vpn]
sources:
- "daily/2026-04-28.md"
created: 2026-04-28
updated: 2026-04-28
---
# Prowlarr + FlareSolverr — Direct Request Bug and VPN Alternatives
Prowlarr supports FlareSolverr integration for bypassing Cloudflare anti-bot protection on torrent indexers. However, for some indexers (notably RuTracker), Prowlarr makes direct HTTP requests rather than routing them through FlareSolverr — even when the FlareSolverr tag is correctly assigned. This is a known plugin-level bug, not a configuration error. The indexer shows as "online" in Prowlarr but search results always fail.
## Key Points
- **FlareSolverr tag assignment does not guarantee FlareSolverr is used** — some Prowlarr indexer plugins make direct requests regardless of the tag; this is a bug in those specific plugins
- **Diagnosis:** `curl rutracker.org` from the server returns 200 (network works); Prowlarr search returns errors → Prowlarr's plugin is making a direct request that gets blocked by Cloudflare, not routing through FlareSolverr
- **RuTracker specifically** was confirmed broken in Prowlarr with FlareSolverr as of April 2026 — the plugin bypasses FlareSolverr entirely
- **Pragmatic fix:** use alternative indexers (TPB, RuTor, SubsPlease, Nyaa) that don't require FlareSolverr — don't invest time debugging a known broken plugin
- **AmneziaVPN Free** only provides AmneziaWG (a proprietary WireGuard variant) — Gluetun does not support it; incompatible for qBittorrent VPN container
## Details
### How FlareSolverr Is Supposed to Work
FlareSolverr is a proxy service that uses a headless Chromium browser to solve Cloudflare challenges and return the actual page content. Prowlarr assigns indexers to a FlareSolverr "tag" in Settings → Indexers → FlareSolverr; when Prowlarr fetches that indexer, it's supposed to send the request to FlareSolverr's HTTP API instead of making a direct request.
The integration works correctly for many indexers. For others, particularly those with custom Prowlarr plugin implementations, the plugin bypasses the FlareSolverr proxy and makes direct requests.
### Confirming It's a Plugin Bug, Not a Config Error
```bash
# Step 1: Confirm network connectivity — is rutracker.org reachable from the server?
curl -I https://rutracker.org
# HTTP/1.1 200 OK → network is fine; Prowlarr is not routing through FlareSolverr
# Step 2: Check FlareSolverr itself is working
curl -X POST http://localhost:8191/v1 \
-H "Content-Type: application/json" \
-d '{"cmd": "request.get", "url": "https://rutracker.org", "maxTimeout": 60000}'
# {"status":"ok", ...} → FlareSolverr works; Prowlarr is not using it
# Step 3: In Prowlarr → Indexers → test the indexer
# If it fails even with FlareSolverr running and correctly tagged → plugin bug
```
If the server can reach the indexer directly (step 1) and FlareSolverr works (step 2), but Prowlarr still fails when testing the indexer, the plugin is making direct requests that get blocked.
### Which Indexers Work Without FlareSolverr
These indexers work reliably in Prowlarr without FlareSolverr and cover most use cases:
| Indexer | Content | Notes |
|---------|---------|-------|
| The Pirate Bay (TPB) | General | Most popular; works via Prowlarr public indexer |
| RuTor | General (Russian) | RuTracker alternative, no Cloudflare |
| SubsPlease | Anime (simulcast) | Reliable; no Cloudflare issues |
| Nyaa | Anime, manga, J-content | Most reliable anime indexer |
| 1337x | General | Works reliably |
| RARBG mirrors | General | Original RARBG gone; mirrors vary |
For most media setups, these 45 indexers provide sufficient coverage without FlareSolverr complexity.
### VPN for qBittorrent — Alternatives to Gluetun
When a VPN provider doesn't support Gluetun's protocols (OpenVPN, WireGuard standard), or when Gluetun configuration is complex, three alternatives exist:
**Option 1: SOCKS5 Proxy in qBittorrent**
The simplest option — qBittorrent has native SOCKS5 proxy support that routes torrent traffic (but not the WebUI) through a proxy:
```
qBittorrent → Options → Connection → Proxy Server
Type: SOCKS5
Host: <proxy_ip>
Port: <proxy_port>
```
Many VPN providers offer SOCKS5 endpoints as part of their service.
**Option 2: WireGuard Directly in LXC**
If the VPN provider offers WireGuard configuration files, install WireGuard directly in the qBittorrent LXC container (CT111):
```bash
apt install wireguard
# Write wg0.conf with provider's config
wg-quick up wg0
# All container traffic routes through VPN
```
This is cleaner than Gluetun for providers that offer standard WireGuard configs.
**Option 3: Router-Level VPN (TP-Link AX72)**
The TP-Link Archer AX72 router supports OpenVPN client mode. Configuring VPN at the router level routes all homelab traffic through the VPN — no per-container setup needed. Downside: all traffic goes through VPN, including services that shouldn't.
**AmneziaVPN Free Limitation:**
AmneziaVPN Free only provides AmneziaWG — a proprietary variant of WireGuard that obfuscates packets to bypass VPN blocks. Gluetun only supports standard WireGuard and OpenVPN. AmneziaVPN cannot be used with Gluetun; use a provider that offers standard WireGuard (Mullvad, ProtonVPN, etc.) if Gluetun is required.
### Media Stack Context
The homelab media stack (CT111, Proxmox LXC) includes:
- **Prowlarr** — indexer management
- **Radarr/Sonarr** — movie/TV automation
- **qBittorrent** — download client
- **FlareSolverr** — Cloudflare bypass proxy (optional, limited effectiveness)
The pragmatic approach: configure 45 reliable indexers that don't require FlareSolverr, skip RuTracker, and add a VPN to qBittorrent only if required by the ISP or content provider.
## Related Concepts
- [[wiki/homelab/_index]] — media stack articles (Radarr, Sonarr, Prowlarr, qBittorrent setup)
- [[wiki/concepts/adguard-dns-rewrites-homelab]] — homelab internal DNS for media services
- [[wiki/concepts/proxmox-lxc-autostart]] — CT111 (media stack LXC) should have autostart enabled
## Sources
- [[daily/2026-04-28.md]] — Prowlarr indexer testing: RuTracker failed with FlareSolverr tag; `curl rutracker.org` from server returned 200 (network fine); confirmed Prowlarr makes direct request bypassing FlareSolverr; decision to keep RuTracker broken and use TPB/RuTor/SubsPlease/Nyaa; AmneziaVPN Free incompatible with Gluetun (AmneziaWG only); VPN alternatives documented

View file

@ -13,6 +13,7 @@
| [[wiki/connections/optical-dev-apache-vite-basepath]] | Apache subpath ↔ Vite basePath — two configs that must match; what breaks when they don't | 2026-04-27 | 2026-04-27 |
| [[wiki/connections/gcp-no-websockets]] | GCP LB 30s timeout ↔ REST polling ↔ job table pattern — infrastructure constraint forces code architecture | 2026-04-27 | 2026-04-27 |
| [[wiki/connections/box-api-hotfolder-pattern]] | Box API ↔ hotfolder daemon — always paired; archive pattern prevents double-processing | 2026-04-27 | 2026-04-27 |
| [[wiki/connections/docker-dns-adguard-split-horizon]] | Docker DNS ↔ AdGuard split-horizon — Docker containers inherit router DNS, not AdGuard; explicit dns: config required | daily/2026-04-28.md | 2026-04-28 |
<!-- Articles added automatically by compile.py -->
<!-- Format: | [[connections/slug]] | ConceptA ↔ ConceptB | daily/YYYY-MM-DD.md | date | -->

View file

@ -0,0 +1,81 @@
---
title: "Connection: Docker DNS + AdGuard Split-Horizon — The Missing Link"
description: "Docker containers inside LXC always need explicit AdGuard DNS to resolve homelab internal domains — without it, split-horizon DNS is invisible to services"
connects:
- "concepts/docker-lxc-dns-configuration"
- "concepts/adguard-dns-rewrites-homelab"
sources:
- "daily/2026-04-28.md"
created: 2026-04-28
updated: 2026-04-28
---
# Connection: Docker DNS + AdGuard Split-Horizon — The Missing Link
## The Connection
AdGuard Home provides split-horizon DNS for internal homelab services (`*.ai-impress.com → internal IP`). Docker containers running in LXC/Proxmox use router DNS by default — not AdGuard. This means Docker services (Homarr, Uptime Kuma, monitoring agents) cannot resolve internal domains even though the LXC host itself can. AdGuard's DNS rewrites are invisible to Docker unless explicitly configured.
## Key Insight
**Two correct things break when combined.** AdGuard DNS rewrites work correctly at the OS level. Docker DNS inheritance works correctly by design. But "inherit from LXC host" means "inherit router DNS" (what DHCP assigned), not "inherit whatever the human added to `/etc/resolv.conf`." The result: every Docker service that health-checks a homelab service by domain name silently fails.
The symptom is deceptive: the Homarr UI shows the service as "offline" when it's actually online — Homarr's health ping resolves `jellyfin.ai-impress.com` to nothing, not to the wrong IP. The service is fine; the container's DNS is wrong.
## Where This Pattern Bites
| Service | Use of internal DNS | Failure symptom |
|---------|---------------------|-----------------|
| Homarr | Ping checks for dashboard tiles | Tiles show red/offline |
| Homepage | Widget API calls | Widget API errors |
| Uptime Kuma | Monitor HTTP checks | False-negative alerts |
| Beszel agent | Connecting to hub by hostname | Agent can't register |
| Any monitoring container | Checking sibling services by domain | False alerts across board |
## The Fix (Always)
In every `docker-compose.yml` for Docker services that reference homelab domains:
```yaml
services:
your-service:
dns:
- 192.168.1.225 # AdGuard Home — resolves *.ai-impress.com
- 1.1.1.1 # Cloudflare — fallback for public DNS
```
Or globally for all containers on an LXC:
```json
// /etc/docker/daemon.json on the LXC
{
"dns": ["192.168.1.225", "1.1.1.1"]
}
```
## Why This Isn't Obvious
AdGuard is configured in the router's DHCP settings (or the Tailscale admin panel) as the primary DNS for all LAN devices. LAN devices — including the LXC host — do use AdGuard. But Docker adds its own DNS resolution layer, bypassing the LXC's `/etc/resolv.conf` for containers and using whatever Docker daemon DNS is configured (default: inherit from host, which means the router).
The key confusion: "the LXC uses AdGuard" ≠ "containers in the LXC use AdGuard." These are two different DNS stacks.
## Connection to AdGuard DNS Rewrites
AdGuard's wildcard rewrite `*.ai-impress.com → NPM IP` is the foundation of the homelab's internal domain system. Everything that wants to reach a homelab service by friendly domain depends on this rewrite. For Docker services, the chain is:
```
Docker service queries *.ai-impress.com
↓ resolves via AdGuard (192.168.1.225)
↓ AdGuard returns NPM IP (192.168.1.205)
↓ NPM routes to the actual service container
Docker service connects to the right container
```
If any link in this chain is missing — Docker not using AdGuard — the entire chain fails silently at DNS resolution.
## Related
- [[wiki/concepts/docker-lxc-dns-configuration]] — implementation details, daemon.json config, diagnosing DNS inside containers
- [[wiki/concepts/adguard-dns-rewrites-homelab]] — the wildcard DNS rewrite that this connection depends on
- [[wiki/concepts/homarr-sqlite-integration-cleanup]] — the session where this was discovered (Homarr ping checks failing)
- [[wiki/concepts/lxc-arp-cache-api-failures]] — a different LXC networking failure that causes similar "service unreachable" symptoms

View file

@ -104,3 +104,8 @@
- Source: daily/2026-04-27.md
- Articles created: [[wiki/concepts/authentik-homelab-tradeoffs]], [[wiki/concepts/icloud-git-sync-conflict]]
- Articles updated: [[wiki/concepts/_index]] (concepts 45→47), [[wiki/_master-index]] (concepts 45→47)
## [2026-04-28T22:00:00+01:00] compile | 2026-04-28.md
- Source: daily/2026-04-28.md
- Articles created: [[wiki/concepts/homarr-sqlite-integration-cleanup]], [[wiki/concepts/docker-lxc-dns-configuration]], [[wiki/concepts/mac-address-randomization-dhcp]], [[wiki/concepts/prowlarr-flaresolverr-limitation]], [[wiki/connections/docker-dns-adguard-split-horizon]]
- Articles updated: [[wiki/concepts/adguard-blocklist-setup]] (added OOM risk section: exit code 137, RAM recommendations, fix); [[wiki/concepts/_index]] (concepts 47→51); [[wiki/connections/_index]] (connections 8→9); [[wiki/_master-index]] (concepts 47→51, connections 8→9)