From 1cd515b3825483ec4e82a38e59abd602cb5f5eed Mon Sep 17 00:00:00 2001 From: Vadym Samoilenko Date: Tue, 28 Apr 2026 21:49:41 +0100 Subject: [PATCH] vault backup: 2026-04-28 21:49:41 --- wiki/_master-index.md | 2 +- wiki/concepts/_index.md | 2 + wiki/concepts/authentik-homelab-tradeoffs.md | 106 ++++++++++++++ wiki/concepts/icloud-git-sync-conflict.md | 141 +++++++++++++++++++ wiki/log.md | 5 + 5 files changed, 255 insertions(+), 1 deletion(-) create mode 100644 wiki/concepts/authentik-homelab-tradeoffs.md create mode 100644 wiki/concepts/icloud-git-sync-conflict.md diff --git a/wiki/_master-index.md b/wiki/_master-index.md index b054c7e..8b7e3b3 100644 --- a/wiki/_master-index.md +++ b/wiki/_master-index.md @@ -23,7 +23,7 @@ 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 | 45 | +| [[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/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 | diff --git a/wiki/concepts/_index.md b/wiki/concepts/_index.md index ac0fa51..868cbaa 100644 --- a/wiki/concepts/_index.md +++ b/wiki/concepts/_index.md @@ -50,6 +50,8 @@ | [[wiki/concepts/lazy-user-mirror]] | User mirror created on first AI event, not on user creation — minimal integration surface, source project stays owner | ai-cost-tracker | 2026-04-27 | | [[wiki/concepts/sync-with-outbox]] | Sync HTTP + SQLite outbox: record() never blocks the AI pipeline; background flusher retries up to 10x | ai-cost-tracker | 2026-04-27 | | [[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 | diff --git a/wiki/concepts/authentik-homelab-tradeoffs.md b/wiki/concepts/authentik-homelab-tradeoffs.md new file mode 100644 index 0000000..a070d3a --- /dev/null +++ b/wiki/concepts/authentik-homelab-tradeoffs.md @@ -0,0 +1,106 @@ +--- +title: "Authentik — Homelab Trade-offs and When to Remove It" +aliases: [authentik-homelab, authentik-sso, authentik-removal, authentik-npm-auth] +tags: [authentik, homelab, sso, npm, proxmox, lxc, selfhosted, security] +sources: + - "daily/2026-04-27.md" +created: 2026-04-27 +updated: 2026-04-27 +--- + +# Authentik — Homelab Trade-offs and When to Remove It + +Authentik is an open-source identity provider that adds SSO, OAuth2, and forward-proxy authentication to self-hosted services. In a homelab context it requires ~500 MB RAM and has a complex multi-container stack (server + worker + PostgreSQL + Redis). It is only worth running if SSO is genuinely configured for each service it protects — if services fall back to their native login pages, Authentik adds overhead without meaningful security benefit. + +## Key Points + +- **Authentik v2026.2.2 broke on migration `0056`** — the field `Role.filter(group_id=...)` was renamed; upgrading from an older version triggers this migration failure and prevents the stack from starting +- **RAM overhead: ~500 MB** per running instance — significant in a homelab with limited RAM (6–8 GB total) +- **Authentik is only justified if SSO is configured per service** — if protected services still show their own login form via NPM's `auth_request`, Authentik provides minimal protection +- **NPM `auth_request` removal** is the critical step when decommissioning — every proxy host that had Authentik auth must be individually updated; forget one and it blocks the service +- **Native service logins (Dozzle, AdGuard, Backrest, IT-Tools, Uptime Kuma) are sufficient** for homelab services accessible only via VPN or internal DNS + +## Details + +### The Migration Failure (v2026.2.2) + +Authentik 2026.2.2 introduced an ORM change that renamed a Role filter field. On first startup after upgrade, Django migrations run automatically — migration `0056` fails because the old field name no longer exists in the codebase, but the migration assumes it does. + +``` +authentik-server | django.db.utils.ProgrammingError: column "group_id" does not exist +authentik-server | Error occurred during database migration — aborting startup +``` + +The stack cannot start in this state. Options: +1. Downgrade Authentik to the last working version before `0056` +2. Restore from a database backup taken before the upgrade +3. Remove Authentik entirely if the SSO value doesn't justify the repair effort + +### Decision Criteria: Keep vs Remove + +| Condition | Keep Authentik | Remove Authentik | +|-----------|---------------|-----------------| +| SSO configured in each protected service | ✓ | — | +| Services support OIDC natively | ✓ | — | +| Multiple users with different access levels | ✓ | — | +| Services fall back to native login via `auth_request` | — | ✓ | +| Only 1–2 users (homelab owner) | — | ✓ | +| RAM is constrained (<8 GB total) | — | ✓ | +| Services accessible only via VPN/internal DNS | — | ✓ | + +For a single-user homelab where services are accessible only via Tailscale VPN or internal DNS, native service logins provide adequate security without the complexity of an identity provider. + +### NPM `auth_request` Removal + +When Authentik protects services via Nginx Proxy Manager's forward-proxy auth feature, each proxy host has an extra configuration block pointing to Authentik's outpost URL. Removing Authentik requires visiting each protected proxy host in NPM and disabling `auth_request`: + +**NPM Proxy Host → Advanced Tab → Custom Nginx Configuration** — remove the block similar to: +```nginx +auth_request /akprox/auth/nginx; +error_page 401 = @akprox-signin; +location @akprox-signin { + return 302 https://auth.internal.domain/akprox/sign_in?rd=$scheme://$http_host$request_uri; +} +``` + +This must be done for every protected proxy host — if missed, NPM attempts to reach Authentik's outpost (which no longer exists) and returns 401 for all requests to that service. Services affected in the 2026-04-27 removal: AdGuard, Backrest, Actual Budget, IT-Tools, Uptime Kuma — 5 services across 9 NPM proxy hosts with the configuration. + +### Dozzle Native Auth Fallback + +Dozzle (a Docker container log viewer) was previously behind Authentik forward-proxy auth without its own login. When Authentik is removed, Dozzle becomes unauthenticated. The fix: enable Dozzle's built-in user authentication. + +In Dozzle's Docker Compose environment: +```yaml +services: + dozzle: + environment: + DOZZLE_AUTH_PROVIDER: simple + volumes: + - ./users.yml:/data/users.yml +``` + +`users.yml` defines users and bcrypt-hashed passwords. This replaces the Authentik forward-proxy with Dozzle's own session management. + +### Authentik vs Simpler Alternatives + +For homelab SSO that is lighter than Authentik: + +| Solution | RAM | Complexity | OIDC | Forward Proxy | +|----------|-----|------------|------|---------------| +| Authentik | ~500 MB | High | ✓ | ✓ | +| Authelia | ~50 MB | Medium | ✓ | ✓ | +| Pocket ID | ~20 MB | Low | ✓ (limited) | ✗ | +| Native logins | 0 MB overhead | None | — | — | + +Authelia is the recommended replacement if centralized auth is still needed — significantly lighter RAM footprint, simpler stack (no separate worker process), and still supports forward-proxy authentication with NPM. + +## Related Concepts + +- [[wiki/concepts/homarr-proxmox-integration]] — Homarr and NPM configuration in the same homelab +- [[wiki/concepts/adguard-dns-rewrites-homelab]] — internal DNS for homelab services that Authentik was protecting +- [[wiki/concepts/proxmox-container-502-misdiagnosis]] — 502 errors from NPM are similar to what happens when auth_request misconfigured +- [[wiki/concepts/tailscale-dns-homelab]] — the VPN layer that provides access control without an identity provider + +## Sources + +- [[daily/2026-04-27.md]] — Authentik 2026.2.2 failed on migration `0056`; decided to remove rather than repair; `auth_request` removed from all 9 NPM proxy hosts; Dozzle switched to native simple auth; 5 services now use their own logins diff --git a/wiki/concepts/icloud-git-sync-conflict.md b/wiki/concepts/icloud-git-sync-conflict.md new file mode 100644 index 0000000..8377e9f --- /dev/null +++ b/wiki/concepts/icloud-git-sync-conflict.md @@ -0,0 +1,141 @@ +--- +title: "iCloud Sync — Git Repository Corruption via Conflict Files" +aliases: [icloud-git-conflict, icloud-obsidian-git, git-badrefname-icloud, icloud-git-sync] +tags: [icloud, git, obsidian, sync, homelab, dotfiles, conflict] +sources: + - "daily/2026-04-27.md" +created: 2026-04-27 +updated: 2026-04-27 +--- + +# iCloud Sync — Git Repository Corruption via Conflict Files + +iCloud Drive creates conflict copies of files by appending a space and number to the filename (e.g., `main 2`, `ORIG_HEAD 2`) when two devices have modified the same file simultaneously. If the `.git/` directory of a repository is stored inside an iCloud-synced folder, these conflict files appear inside `.git/refs/heads/` and git fails with `fatal: 'badRefName'` because git ref names cannot contain spaces. The repository becomes unusable until the conflict files are removed manually. + +## Key Points + +- **iCloud conflict file naming**: when a sync conflict occurs, iCloud creates `original_name 2` (space + number) in the same directory — this is not user-visible in Finder but exists on the filesystem +- **`.git/refs/heads/main 2`** is an invalid git ref name — git rejects any ref containing a space; `git status`, `git log`, and `git pull` all fail with `fatal: bad ref 'main 2'` +- **Root cause**: two devices with an Obsidian vault (or any git repo) open simultaneously editing the same files — when both commit and iCloud syncs, diverged histories create a conflict in `.git/refs/heads/` +- **Fix**: delete all `* 2` files from `.git/refs/heads/`, then merge the diverged histories with `git merge` +- **Prevention**: either exclude `.git/` from iCloud sync, keep Obsidian open on only one device at a time, or use Obsidian Sync instead of git + +## Details + +### How the Corruption Happens + +The sequence that leads to this state: + +1. Vault is open on Device A (Mac) and Device B (iPhone/iPad) simultaneously +2. Both devices make changes that result in different git commits (Device A via shell, Device B via Obsidian's git plugin) +3. iCloud syncs `.git/refs/heads/main` from both devices — they have different SHA hashes +4. iCloud detects a conflict and creates `.git/refs/heads/main 2` alongside the original `.git/refs/heads/main` +5. When either device runs any git command, git enumerates refs, encounters `main 2`, and fails: + ``` + fatal: 'refs/heads/main 2' is not a valid ref name + ``` + +Git's ref naming rules prohibit spaces (and several other characters) — this is enforced at the filesystem level in `git check-ref-format`. A space in a ref name is unconditionally rejected. + +### Diagnosing the Problem + +```bash +# Inside the git repo (.git is the vault's .git directory) +git status +# fatal: 'refs/heads/main 2' is not a valid ref name + +# Find all iCloud conflict files in .git +find .git/refs -name "* 2" -o -name "*ORIG*" +# .git/refs/heads/main 2 +# .git/refs/heads/ORIG_HEAD 2 (sometimes, if a merge was in progress) + +# Check if history has diverged +git log --oneline --graph --all +# Shows two branches diverging at a common ancestor +``` + +### The Fix + +```bash +# Step 1: Remove iCloud conflict files +rm ".git/refs/heads/main 2" +rm ".git/refs/heads/ORIG_HEAD 2" # if present + +# Step 2: Verify git is functional again +git status +# Will show: "Your branch and 'origin/main' have diverged" + +# Step 3: Merge the diverged histories +git merge origin/main +# Or if origin/main was the "other" device's version: +git pull --no-rebase + +# Step 4: Resolve any content conflicts (if files were edited on both devices) +# git will report conflicted files if any +# Edit them to resolve, then: +git add . +git commit -m "Merge diverged device histories" + +# Step 5: Push +git push +``` + +If `ORIG_HEAD` also has a conflict copy, git may be in an interrupted merge state. Check: +```bash +git status +# "You have unmerged paths" → resolve conflicts and commit +# Or abort: git merge --abort +``` + +### Prevention Options + +**Option 1: Exclude `.git/` from iCloud sync** + +Add a `.nosync` extension or use an iCloud exclusion mechanism: +```bash +# Rename .git directory to bypass iCloud (not recommended — breaks git) +# Better: move the entire repo outside iCloud Drive + +# For Obsidian vault: keep vault in iCloud but move .git outside +# (Not straightforward with standard git) +``` + +The cleanest solution for Obsidian: store the vault in iCloud (for Obsidian's own sync of notes) but use **Obsidian Sync** (Obsidian's paid service) instead of git for device sync. + +**Option 2: Use Obsidian Sync instead of git-based sync** + +Obsidian Sync handles device conflicts at the application level — it understands markdown notes and syncs them without creating filesystem-level conflicts. Downside: costs $10/month. Upside: no git conflict corruption possible. + +**Option 3: Single commit source** + +Designate one device as the git commit device (e.g., only the Mac commits). Other devices open the vault read-only or in Obsidian without the git plugin active. iCloud still syncs the files, but only one device creates git commits — no diverged histories. + +**Option 4: `.gitignore`-based partial solution** + +Cannot ignore `.git/` itself (git always tracks `.git/`), but can exclude files that iCloud conflict-copies more aggressively: +```bash +# This does NOT help — git itself needs .git/refs/heads/main +# and cannot ignore files in its own metadata directory +``` + +This option doesn't work — the `.git/` directory is not tracked by git and cannot be gitignored; iCloud syncs it regardless. + +### Obsidian + iCloud + Git Compatibility Matrix + +| Setup | Risk | Notes | +|-------|------|-------| +| Obsidian Sync only (no git) | Low | Paid; no conflict files in `.git/` | +| git in iCloud vault, single device | Low | No simultaneous edits | +| git in iCloud vault, 2+ devices | High | Conflict files in `.git/` on simultaneous edits | +| git repo outside iCloud | None | Vault not synced by iCloud | +| iCloud vault + Obsidian git plugin + 2 devices | Very high | Both git and iCloud create conflicts | + +## Related Concepts + +- [[wiki/concepts/memory-compiler-mac-migration]] — Obsidian vault and git repository migration context +- [[wiki/concepts/git-includeif-per-remote]] — git configuration for multiple identities across repos +- [[wiki/concepts/fish-fisher-conf-d-conflict]] — similar "file managed by tool X corrupted by external copy" pattern (Fisher vs manual conf.d copy) + +## Sources + +- [[daily/2026-04-27.md]] — Obsidian vault git repo on iCloud failed with `badRefName`; root cause was iCloud creating `main 2` and `ORIG_HEAD 2` in `.git/refs/heads/` after simultaneous edits on two devices; fix was deleting conflict files and merging diverged histories; lesson: don't keep vault open on two devices simultaneously with git sync diff --git a/wiki/log.md b/wiki/log.md index f574082..9f4199b 100644 --- a/wiki/log.md +++ b/wiki/log.md @@ -99,3 +99,8 @@ - Articles created: (none) - Articles updated: (none) - Note: No sessions in daily log; memory flush failed with FLUSH_ERROR (exit code 1) — no knowledge to extract + +## [2026-04-28T21:46:04+01:00] compile | 2026-04-27.md +- 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)