RFC — Homelab Plans & Notes
Last updated: 2026-03-24
10. LXC resource management as IaC
Tracked in chizuru-v2 issue #15. Design notes (pct set approach, resource table) moved to the issue.
1. Can I do all this with Ollama?
Short answer: partially, not as a replacement for Claude Code.
Your Ollama instance runs llama3.2:3b and qwen2.5:14b. For the kind of work we do
(multi-file Ansible edits, Forgejo API calls, Proxmox MCP, long YAML playbooks), you need:
- Large context window (we regularly load 5-10 files simultaneously)
- Strong tool use (file read/edit/bash in a feedback loop)
- Precise instruction following on complex IaC changes
qwen2.5:14b can handle simpler tasks but struggles with multi-step infrastructure changes
across many files. llama3.2:3b is too small for this work.
What Ollama/Open WebUI IS good for: - Learning concepts ("explain Vault namespaces") - Quick questions about CLI tools, Docker, Linux - Drafting config templates to paste and refine yourself - Rubber duck debugging when you understand the problem space
To give a local model context about your homelab:
1. Create a homelab-context.md file with: network topology, service IPs, conventions
2. Upload it to Open WebUI as a document for RAG
3. Use a system prompt with the key facts (see section 2)
Better local models to try for code tasks:
- qwen2.5-coder:14b — code-optimized variant, much better than base qwen for YAML/Ansible
- deepseek-coder-v2:16b — strong code model if LXC 107 has RAM headroom
- Check pct config 107 for memory allocation first
The right split: Use Claude Code for infrastructure changes, use Open WebUI/Ollama for learning, ideation, and documentation drafting.
2. Best way to use Open WebUI
System prompt (set this as your default for the homelab model):
You are a homelab assistant for a Proxmox-based setup.
Network: 192.168.1.x subnet. Proxmox host: chizuru (192.168.1.125).
Key services: Forgejo (100/192.168.1.69), Runner (101/192.168.1.211),
Docker host (103/192.168.1.22), Vault (106/192.168.1.106),
Ollama (107/192.168.1.107), Observability (108/192.168.1.108).
Domain: *.eva-00.network. Auth: PocketID OIDC.
IaC: Ansible + Forgejo Actions. All changes go through git → push → workflow.
Workflows that work well:
- RAG: Upload runbook.md and key playbooks as documents → ask questions against them
- Model per task: Switch between models (3b for quick, 14b for complex)
- Conversation history: Use named conversations per topic so you can return to them
- Image analysis: llava model for reading screenshots of logs/dashboards
Models to pull:
ollama pull qwen2.5-coder:14b # better for YAML/Ansible
ollama pull nomic-embed-text # enables RAG embeddings in Open WebUI
ollama pull llava:13b # image analysis
RAG setup in Open WebUI: Settings → Documents → set embedding model to
nomic-embed-text, then upload docs and enable RAG in conversations with #doc-name.
3. How to use Claude tokens more efficiently
High-impact habits:
-
New conversation per task — don't drag a Minecraft debugging session into a Vaultwarden SSO session. Context from unrelated work wastes tokens on every message.
-
Reference, don't paste — say "look at the vaultwarden playbook" instead of pasting it. Claude Code reads files directly.
-
Be specific upfront — "change
SSO_ONLYtotruein services/vaultwarden/docker-compose.yml" costs far fewer tokens than "make Vaultwarden SSO-only" followed by clarification rounds. -
Use CLAUDE.md — already doing this. It front-loads context without per-message cost.
-
Memory system — already set up. Persistent facts (your stack, preferences, ongoing projects) don't need to be re-explained.
-
/compact— run this in long sessions before a major task to summarize the conversation so far and free up context window. -
Targeted questions — "what's the correct Grafana env var for OIDC auto-login?" costs far less than "explain all Grafana auth options and their tradeoffs."
4. MCP vs learning skills/docs
When MCP is worth it: - Stateful or authenticated connections Claude literally can't replicate: Proxmox API, Vault API, GitHub/Forgejo with token auth - Real-time data: cluster status, container metrics, live logs - Actions with side effects that need to be reliable: starting VMs, creating snapshots
When built-in skills/learning is better: - Standard CLI tools (git, docker, ansible) — Claude already knows these deeply - Reading documentation — Claude can fetch and parse docs on demand - APIs with simple curl-style auth — just tell Claude the endpoint and token format
Your current Proxmox MCP: high value — gives real-time cluster visibility and VM/container management that would otherwise require SSH to chizuru for every check.
MCPs worth adding for your stack: - Forgejo MCP (if one exists): trigger workflows, read PR/issue state programmatically - Vault MCP: read/write secrets without needing the token in every conversation - Filesystem MCP: more powerful than built-in Read/Write — can handle binary files, directory trees, symlinks
MCPs to skip: - Generic web search — Claude handles this with WebFetch - Database MCPs for SQLite — overkill for your scale - Anything that duplicates what Ansible already does well
5. Host Docker images and artifacts — using Forgejo registry
Decision: use Forgejo's built-in package/container registry. No separate registry needed.
Forgejo's package registry is enabled by default (no [packages] section needed in app.ini).
Confirmed working — GET /api/v1/packages/holo returns 200.
Harbor was evaluated and ruled out — it's overkill for a single-user homelab (5+ containers, multi-tenancy, RBAC). Forgejo covers all needed use cases at zero extra cost.
Push a container image:
docker login git.eva-00.network # username: holo, password: Forgejo token
docker tag myimage git.eva-00.network/holo/myimage:latest
docker push git.eva-00.network/holo/myimage:latest
Push a generic artifact/binary:
curl -X PUT "https://git.eva-00.network/api/packages/holo/generic/<package>/<version>/<file>" \
-H "Authorization: token <token>" -T <file>
In Forgejo Actions:
- name: Build and push image
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | docker login git.eva-00.network -u holo --password-stdin
docker build -t git.eva-00.network/holo/myimage:${{ github.sha }} .
docker push git.eva-00.network/holo/myimage:${{ github.sha }}
Packages UI: https://git.eva-00.network/holo/-/packages
6. Sync code-server for remote work
Goal: continue homelab work from code-server at code.eva-00.network seamlessly.
The setup:
- Your repos are at /Users/gabriel/git on your Mac
- code-server workspace is at /workspace volume on LXC 103
- Forgejo at git.eva-00.network is the source of truth
Recommended approach: git-based sync
-
In code-server: clone your repos from Forgejo
git clone https://git.eva-00.network/holo/homelab.git git clone https://git.eva-00.network/holo/homelab-docs.git -
Set up SSH key in code-server so you can push without password:
Then switch remotes to SSH:ssh-keygen -t ed25519 -C "code-server" # Add the public key to your Forgejo account → Settings → SSH Keysgit remote set-url origin [email protected]:holo/homelab.git -
Workflow: commit on Mac → push to Forgejo → pull in code-server (and vice versa)
To run Claude Code in code-server:
npm install -g @anthropic-ai/claude-code
# Set ANTHROPIC_API_KEY in code-server environment
.bashrc or via docker-compose env:
ANTHROPIC_API_KEY=<your-key>
~/.claude/ directory is inside the code-server container.
To share Claude memory between Mac and code-server:
- Mount a shared volume or sync ~/.claude/projects/ via Syncthing (optional, complex)
- Simpler: keep a homelab-context.md in the repo that both environments can reference
Action items:
1. Open code-server, clone repos from Forgejo
2. Generate SSH key, add to Forgejo
3. Install Claude Code: npm install -g @anthropic-ai/claude-code
4. Set ANTHROPIC_API_KEY in the environment
7. Halo Online (ElDewrito) server — ON HOLD
What it is: ElDewrito is a community mod for the cancelled Halo Online. v0.7.1 released May 2024 by a new team — actively developed and maintained. Community organises games via HaloBase and ElDewrito Main on Discord.
Current version: 0.7.1 (May 2024) — changelog available at eldewrito.org
Recommended approach: Docker on existing LXC 103 (no Windows VM needed)
Use domistyle/eldewrito — a Docker image that runs the ElDewrito dedicated server headlessly on Linux via Wine + xvfb internally. No Windows license required.
- Docker Hub:
domistyle/eldewrito(latest: v0.7.0-c1.1, April 2024, 11 releases) - GitHub: https://github.com/DomiStyle/docker-eldewrito
- Requires
SYS_PTRACEcapability (add to docker-compose or use privileged LXC) - Game files (~2GB zip) must be downloaded separately and mounted into the container
Ports: | Port | Protocol | Purpose | |---|---|---| | 11774 | UDP | Game traffic (required) | | 11775 | TCP | HTTP/info server (required) | | 11776 | TCP | RCON (optional) | | 11777 | TCP | VoIP (optional) |
External access: UPnP handles port forwarding automatically if router supports it. Alternatively add a playit.gg TCP+UDP tunnel (account already exists).
Prerequisites before starting: 1. Check free RAM on chizuru — server needs ~2-4 GB 2. Download ElDewrito game files (~2GB zip) from the community 3. Decide: add to LXC 103 or new dedicated LXC
Configuration: dewrito_prefs.cfg — server name, max players, map rotation, RCON password.
Linux client (for playing, not hosting): Steam Play + Proton 9.0-4. Official guide at eldewrito.org.
8. Forgejo action logs → Loki: revisit approach (PARTIALLY RESOLVED by Alloy migration)
Current state (2026-03-24): A Python cron script runs every 2 minutes on the Forgejo LXC, decompresses .log.zst files from /var/lib/forgejo/data/actions_log/, and pushes them to Loki. It works, but a cron script is fragile and hard to observe — it has no health metrics, can silently fall behind, and is yet another custom thing to maintain.
Why the obvious approach (Promtail) doesn't work: Forgejo stores completed action logs as zstd-compressed binary files, not plain text. Promtail can only tail plain text files.
Alternatives to evaluate:
-
Grafana Alloy (replaces Promtail) — Alloy's pipeline supports
decompressorstages and customloki.processtransforms. It may be able to decompress zstd on the fly as files are written. Much more observable than a cron script — Alloy has a built-in UI and exposes metrics. -
Vector — purpose-built log router with a richer transform pipeline than Promtail. Supports file watching, custom decoding (including via WASM transforms), and has first-class zstd support in its codec. Would replace the script entirely and run as a proper service.
-
Forgejo webhook → log endpoint — Forgejo fires webhooks on workflow events. A small receiver (n8n workflow, or a lightweight HTTP service) could call the Forgejo API to download the job log on completion and push it to Loki. No polling, no cron, event-driven. The log download API exists but requires knowing the job ID, which the webhook payload may or may not include.
-
Change how Forgejo stores logs — Forgejo's
[actions]config section has options for log retention and storage. It may be possible to configure it to write uncompressed logs or to a different backend (e.g., S3/Minio), from which a proper log shipper could read them.
Recommendation to revisit: Try Grafana Alloy first — it's already in the Grafana ecosystem, replaces Promtail (which we're already running on the runner LXC), and has native zstd support. If Alloy works, we can consolidate all Promtail instances (runner + future ones) onto Alloy.
To pick this back up: Replace the cron script + Promtail setup on both the Forgejo LXC and the runner LXC with a single Alloy instance, or one Alloy per LXC. Check whether Alloy's loki.source.file + loki.process can handle .log.zst files natively.
9. Docker container logs → Loki (RESOLVED by Alloy migration)
Current state (2026-03-24): Docker container logs on docker-host (LXC 103) are shipped to Loki via the existing observability-agents stack (Promtail + Docker socket). This works for services on LXC 103. However, when debugging failures via MCP/Claude, docker logs is not accessible — we have to SSH through Proxmox, which is slow and manual.
The goal: Be able to query any container's stdout/stderr in Grafana (or via Loki MCP) without needing SSH access.
Options to evaluate:
-
Grafana Alloy with Docker log collection — Alloy has a native
loki.source.dockercomponent that streams logs from all containers via the Docker socket automatically, with container name/image/labels as stream labels. This is the cleanest solution and would also replace Promtail (consolidating with plan #8 above). -
Docker logging driver → Loki — Docker supports a
lokilog driver natively. Settinglog-driver: lokiin/etc/docker/daemon.jsonon LXC 103 sends all container logs directly to Loki without any sidecar. Downside: if Loki is unreachable, logs are lost (no local buffer). Also requires restarting all containers. -
Promtail Docker service discovery — the existing Promtail config can be extended with a
docker_sd_configsscrape job that autodiscovers containers and tails their log files from/var/lib/docker/containers/. Already partially in place — check whether the currentpromtail-config.ymlon LXC 103 covers this.
Recommendation: Try Grafana Alloy first (aligns with plan #8). One Alloy instance per LXC replaces both Promtail and the Forgejo cron script, and Alloy's Docker component handles container log discovery automatically.
To pick this back up: Check services/observability-agents/promtail-config.yml — if it already has Docker discovery, the gap might just be label configuration. Otherwise, migrate to Alloy.
SSO Status (as of 2026-03-22)
| Service | SSO Status | Method |
|---|---|---|
| Glance | Gate only (no app auth) | oauth2-proxy ✓ |
| Gatus | Gate only (no app auth) | oauth2-proxy ✓ |
| code-server | Transparent (no password set) | oauth2-proxy ✓ |
| Open WebUI | Native OIDC ✓ | Direct OIDC (pkceEnabled: false) |
| Grafana | Native OIDC ✓ | Direct OIDC |
| Vaultwarden | Native SSO ✓ | #/sso → org identifier homelab |
| Forgejo | Native OIDC ✓ | forgejo admin auth add-oauth (openidConnect) |
| n8n | Gate only, needs own login | oauth2-proxy (no fix available) |
| The Lounge | Gate only, needs own login | oauth2-proxy (no fix available) |