Homelab setup

Running in your homelab in about a minute.

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

Requirements

Two things on your network, both common in a homelab.

Docker + Docker Compose

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.

An Ollama server

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.

pull the models
# chat: score / summarize / categorize
ollama pull qwen2.5:latest

# embeddings: clustering / taste / semantic search
ollama pull nomic-embed-text

Step 2

Quick start

Clone the repo, point it at your Ollama server, and bring it up.

terminal
# 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
docker-compose.yaml
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:

Then open 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

Keep it on a trusted network

Cruxwire's trust model is simple: the network is trusted, nothing more.

Cruxwire has no authentication

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.

Trusted feeds only

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.

No rate limiting or CSRF

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.

Data is unencrypted

Runtime data, read history, Read Later, learned source preferences, is stored unencrypted on the Docker volume. Back it up, and protect it, accordingly.

Tuning

A few knobs worth knowing

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 / settingDefaultPurpose
OLLAMA_HOSThttp://localhost:11434Ollama base URL for chat and embeddings.
Chat / embedding modelqwen2.5:latest / nomic-embed-textWhich Ollama models to use. Managed in Settings → Models.
Merge similarity0.74Cosine threshold to collapse same-topic articles into one card.
Lookback36 hHow far back fresh items are first discovered.
Retention floor / ceiling25 / 60Keep at least / at most this many unread stories.
Schedule0622, every 2 hWhen pipeline runs fire (active-hours window + interval).
History retention3 daysHow long read History is kept before it ages out. Read Later is never aged.
PORT8090Container 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.

Data & persistence

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.

Develop without Docker

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.

Grab the source and go

The repository has the full SPEC, the tuning guide, and sample feeds and categories to start from.