Skip to content

Heretek-AI/libre-stack

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Libre Stack

Self-hosted private AI assistant: LibreChat + Firecrawl + SearXNG + Camofox, fed by a custom Lemonade LLM endpoint.

  • Spec: docs/superpowers/specs/2026-06-27-libre-stack-design.md
  • Plan: docs/superpowers/plans/2026-06-27-libre-stack.md

Architecture

Twelve containers, all in one compose.yaml, all on a single bridge network libre-stack. Four host ports are exposed (3080, 3090, 3002, 8080); everything else is internal-only and reached via Zoraxy subdomain routing.

# Service Role Image Host port
1 librechat Chat UI / API librechat/librechat:latest 3080
2 admin-panel User / role admin UI registry.librechat.ai/clickhouse/librechat-admin-panel:latest 3090
3 mongo LibreChat DB mongo:8.0.20
4 meilisearch RAG index getmeili/meilisearch:v1.35.1
5 firecrawl-api REST scrape/crawl (harness) ghcr.io/firecrawl/firecrawl:latest 3002
6 firecrawl-playwright Headless browser ghcr.io/firecrawl/playwright-service:latest
7 firecrawl-redis BullMQ queue redis:7-alpine
8 firecrawl-postgres Firecrawl metadata ghcr.io/firecrawl/nuq-postgres:latest
9 firecrawl-rabbitmq Firecrawl queue broker rabbitmq:3-management
10 searxng Metasearch (JSON-only) searxng/searxng:latest 8080
11 mcp-firecrawl MCP server for Firecrawl ghcr.io/firecrawl/firecrawl-mcp-server:latest
12 camofox-browser Stealth browser + MCP server ghcr.io/redf0x1/camofox-browser:latest

Data flow:

User → Zoraxy (TLS) → librechat:3080
                         │
                         ├─→ mongo:27017          (users, messages, memory)
                         ├─→ meilisearch:7700     (RAG index)
                         ├─→ tesseract:5000       (OCR)
                         ├─→ searxng:8080         (web_search plugin → JSON)
                         ├─→ mcp-firecrawl:3000   (scrape/crawl tools)
                         ├─→ mcp-camofox:8000     (browser tools)
                         │       └─→ camofox-browser:8080
                         └─→ 192.168.31.246:13305 (Lemonade LLM, via host LAN)

User → Zoraxy → firecrawl-api:3002 (only via mcp-firecrawl from librechat;
                  also direct from Zoraxy as escape hatch for debugging)

LibreChat is the only service that talks to Lemonade (the LLM). Firecrawl and Camofox are tools called by LibreChat's agents, not by users directly.

MCP tool surface: LibreChat's default agent inherits all globally registered MCP servers plus the built-in web_search tool.

  • web_search → hits SearXNG JSON endpoint.
  • firecrawl_scrape, firecrawl_crawl, firecrawl_map, firecrawl_extract → mcp-firecrawl.
  • camofox_navigate, camofox_click, camofox_fill, camofox_screenshot, camofox_extract_text → mcp-camofox.

Quick start

# 1. Clone and enter the repo
cd /home/john/Projects/libre-stack

# 2. Bootstrap (copies .env.example → .env, generates secrets, verifies
#    Lemonade is reachable, pulls and brings up the stack, waits for health)
./bin/bootstrap.sh

# 3. Confirm the stack is healthy
./bin/smoke.sh

# 4. Wire Zoraxy (see "Zoraxy config" below) and visit
#    https://chat.example.com

bin/bootstrap.sh is idempotent: re-running it after a partial bring-up is safe. It prints the admin URL and generated credentials on success.


Zoraxy config

Four subdomains, each pointing to a host port exposed by compose.yaml. Configure these in your Zoraxy admin UI (/admin):

Subdomain Backend Notes
chat.example.com http://<host>:3080 Primary public entry — LibreChat UI + API.
admin.example.com http://<host>:3090 LibreChat admin panel (user/role management).
search.example.com http://<host>:8080 SearXNG escape hatch for direct debugging.
scrape.example.com http://<host>:3002 Firecrawl API escape hatch for direct debugging.

Production traffic should flow only through chat.example.com and admin.example.com. The SearXNG and Firecrawl host ports exist mainly so an operator can poke at them directly when something is wedged behind the agent loop. They are not part of the public UX.

Set ADMIN_PANEL_SESSION_COOKIE_SECURE=true in .env once admin.example.com is served over HTTPS so the panel's session cookie locks down. Leave it false for plain-HTTP local testing.

Zoraxy terminates TLS, handles ACME, and forwards per-subdomain. Make sure the host running Libre Stack is reachable on ports 3080, 3090, 3002, and 8080 from where Zoraxy runs (typically the same box or the same LAN).


Lemonade LLM endpoint

Lemonade is not a container in this stack — it runs on your LAN as a standalone OpenAI-compatible service (a custom OpenAI-compatible API on http://192.168.31.246:13305/v1 by default).

  • LibreChat's librechat.yaml is wired to that URL via the OPENAI_API_BASE / custom endpoint config.
  • The host running Libre Stack must be able to reach 192.168.31.246:13305. bin/bootstrap.sh verifies this on every run.
  • Lemonade's API is OpenAI-compatible, so any future swap (local Ollama, a vLLM server, a remote provider) is a single baseURL change in librechat.yaml.

To swap to local Ollama later: add an ollama container to compose.yaml and change the endpoints.custom[0].baseURL to http://ollama:11434/v1.


Repository layout

libre-stack/
├── README.md                 # this file
├── compose.yaml              # all 13 services + volumes + networks
├── librechat.yaml            # LibreChat app config (model list, MCP servers)
├── .env.example              # template for .env (no secrets committed)
├── .gitignore
├── bin/
│   ├── bootstrap.sh          # first-run / idempotent bring-up
│   ├── backup.sh             # snapshot stateful volumes + databases
│   ├── update.sh             # pull images and recreate stack
│   └── smoke.sh              # post-up health + integration checks
└── docs/superpowers/
    ├── specs/2026-06-27-libre-stack-design.md
    └── plans/2026-06-27-libre-stack.md

Named volumes

Volume Owner Purpose
mongo-data mongo LibreChat DB
meili-data meilisearch RAG index
firecrawl-postgres-data firecrawl-postgres Firecrawl metadata
firecrawl-redis-data firecrawl-redis BullMQ queues (transient)
firecrawl-playwright-data firecrawl-playwright browser cache
camofox-data camofox-browser browser profile, cookies
librechat-uploads librechat user-uploaded files (RAG source)

No volume for SearXNG — its only stateful bits are the in-process limiter and the redis-backed secret key, neither needs persistence in our config.


Operations

Update

./bin/update.sh
  • docker compose pull
  • docker compose up -d
  • Healthcheck grace period: 2 minutes for LibreChat and Firecrawl. On failure the script prints an error and leaves the stack as-is. Manual rollback to an earlier tag is left to the operator (LibreChat is pinned; Firecrawl and SearXNG use :latest).

Backup

BACKUP_DIR=/var/backups/libre-stack ./bin/backup.sh

Output to ${BACKUP_DIR}/YYYY-MM-DD/, retain 14 days. Intended for host cron, not run inside the stack.

Volume Contents Method
mongo-data users, messages, memory mongodump
meili-data RAG index Meili snapshot API
firecrawl-postgres-data Firecrawl metadata pg_dump
camofox-data browser profile tar
librechat-uploads user files tar
firecrawl-redis-data BullMQ queues skip — reconstructible
firecrawl-playwright-data browser cache skip

Example cron entry (daily at 03:17):

17 3 * * *  BACKUP_DIR=/var/backups/libre-stack /home/john/Projects/libre-stack/bin/backup.sh >> /var/log/libre-stack-backup.log 2>&1

Smoke test

./bin/smoke.sh                 # health + integration checks
RUN_E2E=1 ./bin/smoke.sh       # also runs a full LibreChat → Lemonade prompt round-trip

Checks (exits non-zero on first failure):

  • curl /api/health on librechat, firecrawl-api, searxng.
  • SearXNG GET /search?q=test&format=json returns a results array.
  • Firecrawl POST /v1/scrape against https://example.com returns markdown.
  • mcp-camofox GET /tools returns a tool list.
  • End-to-end (gated by RUN_E2E=1): LibreChat → Lemonade prompt round-trip with a known answer.

Monitoring

Not in scope for v1. docker stats + Zoraxy logs are sufficient. Prometheus and Grafana are added when a real need surfaces.


Troubleshooting

bin/bootstrap.sh fails on the Lemonade check. The host can't reach 192.168.31.246:13305. Verify network reachability (curl http://192.168.31.246:13305/v1/models) and that the Lemonade service is up. LibreChat cannot start without this — it's a hard dependency.

LibreChat healthcheck never goes green after update.sh. Check docker compose logs librechat. Most common cause: Meili or Mongo isn't ready yet (LibreChat waits on those internally). Give it the full 2-minute grace, then docker compose ps to see which container is unhealthy. Roll back by pinning LibreChat to the previous tag in compose.yaml and re-running ./bin/update.sh.

SearXNG returns empty results. Check docker compose logs searxng. SearXNG's JSON endpoint needs at least one enabled engine in searxng-settings.yml. If you've swapped the settings volume, restart the container.

Firecrawl POST /v1/scrape times out. firecrawl-api waits on firecrawl-worker, which waits on firecrawl-playwright. Verify the whole chain is healthy (docker compose ps). If only the worker is wedged, restart it in place: docker compose restart firecrawl-worker.

bin/smoke.sh reports MCP /tools is empty on mcp-camofox. The Camofox MCP image may not yet have a published release — progress.md notes this is deferred to the end-to-end run. Verify the image exists: docker pull ghcr.io/redf0x1/camofox-mcp:latest.

Backup snapshot directory is missing or partial. Check BACKUP_DIR is writable by the cron user and that the named volumes exist (docker volume ls | grep libre-stack).


Security notes

  • .env is never committed. .env.example is the template; bin/bootstrap.sh generates secrets with openssl rand -hex N on first run. Rotate them by editing .env and restarting the affected container.
  • All Lemonade traffic stays on the LAN (192.168.31.246); nothing crosses the public internet for inference.
  • SearXNG and Firecrawl host ports (8080, 3002) are published on the host's external interface by default (0.0.0.0). If you don't need direct LAN access to the escape hatches, tighten the bind in compose.yaml to 127.0.0.1:8080:8080 and 127.0.0.1:3002:3002 — Zoraxy on the same host can still reach them via loopback. Do not expose them on a public IP — they are escape hatches with no auth on the direct path.
  • LibreChat admin credentials are printed by bin/bootstrap.sh on first run and stored nowhere else. Change the admin password immediately after the first login via the LibreChat UI.
  • Backup archives under ${BACKUP_DIR} may contain chat history, uploaded files, and browser cookies (Camofox profile). Treat that directory as sensitive: encrypt at rest, restrict filesystem permissions, and never sync it to a public bucket.
  • Zoraxy is responsible for TLS, rate limiting, and bot protection on the public subdomains. This stack assumes Zoraxy is hardened separately.

Status: v1 design approved 2026-06-27. See docs/superpowers/specs/ for the full design and docs/superpowers/plans/ for the implementation plan.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages