Skip to content

CesarPetrescu/Lifenode

Repository files navigation

LifeNode

LifeNode is a local-first, self-hosted knowledge workspace.

It runs as a single web app with:

  • Rust backend (axum + sqlx + SQLite)
  • React frontend (Vite + MUI)
  • llama.cpp services for chat + embeddings
  • Per-user local storage under ./user-files

What You Get

  • Authenticated multi-user app with optional admin bootstrap.
  • Wiki tab: Kiwix download center + embedded viewer, plus indexed-article tools for semantic search and Ask retrieval.
  • Maps tab: OpenStreetMap download center + embedded OSM visualizer.
  • Download job system for maps/wiki payloads (queue, progress, cancel, delete logs, delete files).
  • Ask tab with:
    • chat sidebar and persistent thread history
    • thread create/rename/delete
    • streaming assistant responses over SSE (/api/ask/stream)
    • optional model "thinking" mode
    • live Qwen 0.8B / 2B model switching with unload + reload
  • Notes tab with folder tree, file management, markdown editing, and live preview.
  • Drive tab with folder/file operations and rich file preview.
  • Drive viewer supports Markdown, text, PDF, image, audio, and video formats.
  • Calendar tab for personal events.
  • Health indicator for backend + model status.

Architecture

Browser (React + MUI)
        |
        v
Rust API (Axum)  ---> SQLite (user/files + metadata)
        |
        +---> llama-qwen manager (loads Qwen 0.8B / 2B / 4B into llama.cpp)
        +---> llama-embed (embeddings, OpenAI-compatible endpoint)
        +---> Kiwix service (serves downloaded .zim files)

Quick Start (Docker)

  1. Clone and enter the repo.
  2. Create env file and required directories.
  3. Place GGUF model files.
  4. Build and start all services.
cp .env.example .env
mkdir -p user-files models

# put your models in ./models
# - Qwen3.5-0.8B-UD-Q3_K_XL.gguf
# - Qwen3.5-2B-UD-Q4_K_XL.gguf
# - Qwen3.5-4B-UD-Q3_K_XL.gguf
# - embeddinggemma-300M-Q8_0.gguf

docker compose up --build -d
docker compose ps

On small hosts, start with the shipped defaults. They bias for stability:

  • Qwen 0.8B stays at 4096 context.
  • Qwen 2B drops to 2048 context.
  • Qwen 4B drops to 1024 context.
  • mmap stays enabled and mlock stays off by default.
  • The Qwen manager refuses model switches that exceed the current memory budget.

Open:

  • App: http://<your-private-ip>:8000
  • Kiwix direct (optional): http://<your-private-ip>:8081

Find your Wi-Fi private IP (Linux):

ip -4 addr show wlan0 | awk '/inet / {print $2}' | cut -d/ -f1

If your Wi-Fi interface is not wlan0, replace it (for example wlp2s0).

Service Layout

compose.yml runs 4 services:

  • lifenode: backend API + bundled frontend
  • llama-qwen: chat model manager for Qwen 0.8B / 2B / 4B
  • llama-embed: embeddings
  • kiwix: serves local .zim files on port 8081

Storage Layout

  • Database: ./user-files/lifenode.db
  • Per-user maps/wiki files: ./user-files/<username>/maps/...
  • Per-user drive files: ./user-files/<username>/files/...
  • Other per-user assets are stored under ./user-files/<username>/...

Local Development

Backend:

cd backend
cargo run

Frontend:

cd frontend
npm install
npm run dev -- --host

Optional frontend API override:

export VITE_API_BASE=http://127.0.0.1:8000/api

Key Environment Variables

General:

  • LIFENODE_HOST (default 0.0.0.0)
  • LIFENODE_PORT (default 8000)
  • LIFENODE_CORS_ORIGINS (default *)
  • LIFENODE_MAX_UPLOAD_MB (default 100)

Storage:

  • LIFENODE_DB_PATH (default /data/user-files/lifenode.db)
  • LIFENODE_USER_FILES_DIR (default /data/user-files)
  • LIFENODE_FRONTEND_DIST (default /app/frontend/dist)

Admin bootstrap (optional):

  • LIFENODE_ADMIN_USERNAME
  • LIFENODE_ADMIN_PASSWORD

Kiwix:

  • LIFENODE_KIWIX_EMBED_URL (default http://localhost:8081)
  • LIFENODE_KIWIX_PORT (default 8081)

llama.cpp endpoints:

  • LIFENODE_LLAMACPP_EMBED_URL
  • LIFENODE_LLAMACPP_EMBED_MODEL
  • LIFENODE_LLAMACPP_CHAT_URL
  • LIFENODE_LLAMACPP_CHAT_MODEL
  • LIFENODE_LLAMACPP_MANAGER_URL
  • LIFENODE_LLAMACPP_API_KEY
  • LIFENODE_LLAMACPP_CHAT_MAX_TOKENS
  • LIFENODE_LLAMACPP_CHAT_TIMEOUT_SECS
  • LIFENODE_LLAMACPP_CHAT_THINKING_DEFAULT

llama.cpp container runtime:

  • LLAMACPP_QWEN_DEFAULT_MODEL_ID
  • LLAMACPP_QWEN_0_8B_MODEL_PATH
  • LLAMACPP_QWEN_2B_MODEL_PATH
  • LLAMACPP_QWEN_4B_MODEL_PATH
  • LLAMACPP_EMBED_MODEL_PATH
  • LLAMACPP_QWEN_0_8B_CTX
  • LLAMACPP_QWEN_2B_CTX
  • LLAMACPP_QWEN_4B_CTX
  • LLAMACPP_EMBED_CTX
  • LLAMACPP_NGL
  • LLAMACPP_NO_MMAP
  • LLAMACPP_MLOCK
  • LLAMACPP_EMBED_NO_MMAP
  • LLAMACPP_EMBED_MLOCK
  • LLAMACPP_MEMORY_GUARD_ENABLED
  • LLAMACPP_MEMORY_GUARD_HEADROOM_MIB (default 1536)
  • LLAMACPP_CONTEXT_OVERHEAD_PER_TOKEN_KIB
  • LLAMACPP_RUNTIME_OVERHEAD_MIB

API Overview

Main route groups:

  • Auth: /api/auth/*
  • Ask + chat threads: /api/ask/*
  • Maps/wiki download center: /api/maps/*
  • Wiki indexing/search endpoints: /api/wiki/*, /api/search
  • Notes: /api/notes/*
  • Drive: /api/drive/*
  • Calendar: /api/calendar/*
  • Health: /api/health

For a concrete route map, see backend/src/main.rs.

Build and Verify

Backend:

cd backend
cargo check

Frontend:

cd frontend
npm run build

Stack:

docker compose up --build -d
docker compose ps

Troubleshooting

  • Download preset returns 404:
    • Use Custom Download URL in the UI for a known-good .zim or .osm.pbf.
    • The backend also attempts to auto-discover latest Kiwix English filenames.
  • Kiwix panel is blank:
    • Confirm at least one .zim file exists in your configured user-files mount.
    • Confirm kiwix container is running and LIFENODE_KIWIX_EMBED_URL is reachable.
  • Chat answers are fallback-style:
    • Check GET /api/health; if llama services are unavailable, backend falls back to deterministic embeddings and retrieval-only behavior.
  • Model switch takes a while:
    • The Ask composer now shows runtime status. Sending is disabled until the selected model finishes loading.
  • 2B or 4B is disabled in Ask:
    • The manager now blocks unsafe loads when current RAM, context size, and runtime flags make a switch risky.
    • On a 4 GiB host, keep LLAMACPP_NO_MMAP=0 and LLAMACPP_MLOCK=0, and expect 4B to stay blocked unless you move to a larger machine.

About

Lifenode is a Raspberry Pi–hosted WebUI that turns a Pi into an offline knowledge + personal utility hub.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages