Homelab setup
Cruxwire is a single container that talks to your Ollama server and keeps its state on a local volume. If you can run docker compose up, you can run Cruxwire.
Step 1
Two things on your network, both common in a homelab.
Any host that runs containers: a NAS, a mini-PC, a VM, or a Raspberry Pi class box. The app has no build step and no Python dependencies, it's pure standard library inside the image.
A reachable Ollama endpoint over HTTP, with a chat model and an embedding model pulled. It can run on the same host or anywhere on your network, you point Cruxwire at it with OLLAMA_HOST.
# chat: score / summarize / categorize
ollama pull qwen2.5:latest
# embeddings: clustering / taste / semantic search
ollama pull nomic-embed-text
Step 2
Clone the repo, point it at your Ollama server, and bring it up.
# 1: get the source
git clone https://github.com/philoking/cruxwire
cd cruxwire
# 2: set your Ollama host
cp .env.example .env
# edit OLLAMA_HOST in .env
# 3: build and run
docker compose up -d --build
services:
cruxwire:
build: .
container_name: cruxwire
restart: unless-stopped
ports:
- "${PORT:-8090}:8090"
environment:
OLLAMA_HOST: ${OLLAMA_HOST:-http://localhost:11434}
PORT: 8090
volumes:
- cruxwire-data:/data
volumes:
cruxwire-data:
http://<host>:8090/On first run Cruxwire seeds its feed list from a sample and the pipeline generates the first digest, give it about a minute. Manage feeds in the UI's Feeds screen, or trigger a refresh with curl -X POST http://<host>:8090/refresh.
Step 3 · important
Cruxwire's trust model is simple: the network is trusted, nothing more.
Every endpoint, including the ones that change settings, feeds, and categories or trigger pipeline runs, is reachable by anyone who can reach the port. Do not expose port 8090 directly to the internet. If you want remote access, put it behind a reverse proxy that adds auth: Caddy/nginx with basic auth, Authelia, Tailscale, Cloudflare Access, and similar.
The pipeline fetches every feed you add and, for TL;DRs, the linked article pages. Treat your feed list as trusted input, and don't give the container network access to internal services it has no reason to reach.
The mutating endpoints have no rate limiting or CSRF protection. The trust model is "the network is trusted", keep it on a homelab LAN, a tailnet, or localhost.
Runtime data, read history, Read Later, learned source preferences, is stored unencrypted on the Docker volume. Back it up, and protect it, accordingly.
Tuning
Infrastructure wiring lives in docker-compose.yaml / .env; everything else is editable live in the Settings UI and applies on the next run without a restart.
| Variable / setting | Default | Purpose |
|---|---|---|
| OLLAMA_HOST | http://localhost:11434 | Ollama base URL for chat and embeddings. |
| Chat / embedding model | qwen2.5:latest / nomic-embed-text | Which Ollama models to use. Managed in Settings → Models. |
| Merge similarity | 0.74 | Cosine threshold to collapse same-topic articles into one card. |
| Lookback | 36 h | How far back fresh items are first discovered. |
| Retention floor / ceiling | 25 / 60 | Keep at least / at most this many unread stories. |
| Schedule | 06–22, every 2 h | When pipeline runs fire (active-hours window + interval). |
| History retention | 3 days | How long read History is kept before it ages out. Read Later is never aged. |
| PORT | 8090 | Container HTTP port. |
The repo's TUNING.md documents every adjustable knob, how they interact, and recipes for common situations ("it goes dry on weekends", "I'm seeing duplicate cards", "surface more of what I read"). Categories, their labels, colors, and the interest descriptions the scorer ranks against, are data you edit in categories.json or the Settings UI.
Mutable data lives on the cruxwire-data volume (/data): state.json, feeds.json, digest.json, settings.json, runs.json, categories.json, and article embeddings. Rebuilds preserve it; back up the volume to keep your feed list, read history, and learned preferences.
No dependencies means you can run the server directly against local files with a handful of env vars pointed at your Ollama host. To iterate on the layout without a live feed setup, point the feeds file at a nonexistent path and drop in a real digest.json.
The repository has the full SPEC, the tuning guide, and sample feeds and categories to start from.