A self-hosted backend that powers tedawf.com with real-time content sync from Obsidian and a RAG-powered AI chatbot.
- Auto-sync from Obsidian: Blog posts and personal notes update instantly via Obsidian LiveSync
- AI Chatbot: Answers questions about my portfolio content using RAG
- Content API: Serves blog posts and images directly from CouchDB
- Vector Search: Semantic search with Postgres + pgvector
- Self-hosted: Runs on my proxmox homelab
graph TB
A[Obsidian] -->|LiveSync| B[CouchDB]
B -->|_changes| C[FastAPI]
C -->|Embeddings| D[Postgres+pgvector]
E[Users] -->|Chat| F[Portfolio Site]
F -->|/prompt| C
C -->|RAG| D
C -->|Stream response| F
F -->|Answer| E
- Write in Obsidian - I create blog posts and notes in my Obsidian vault
- Auto-sync to CouchDB - LiveSync plugin pushes changes instantly
- FastAPI processes changes - Listens for
_changesand ingests new content - Embeddings generated - OpenAI text embeddings for semantic search
- Store in Postgres - Free vector database with pgvector extension
- Chatbot queries - When you ask a question, it finds similar content and ranks them
- Chatbot responds - Uses retrieved context to answer specifically about my work
- Blog Posts (
blog/in Obsidian) - Personal KB (
kb/in Obsidian) - Portfolio Content (via
/updateAPI)
- Python 3.11+
- CouchDB 3.x
- Postgres 13+ with pgvector
- Obsidian + LiveSync plugin
Copy .env.example to .env key vars are:
COUCHDB_HOST=localhost
COUCHDB_DATABASE=obsidian_db
POSTGRES_HOST=localhost
POSTGRES_DATABASE=tacos_db
TACOS_API_KEY=your_custom_key
OPENAI_API_KEY=your_openai_keyhttps://docs.couchdb.org/en/stable/install/unix.html
CREATE EXTENSION IF NOT EXISTS vector;
alembic upgrade head- Install LiveSync plugin from the Obsidian community plugins marketplace
- Connect to CouchDB
- It will sync everything in your vault to CouchDB
# using venv
pip install -r requirements.txt
uvicorn app.main:app --reloadFor a self-hosting setup, I use:
- Nginx + certbot for reverse proxy and https
- Cloudflare for domain
- Proxmox + LXC (ubuntu)
GET /posts- List blog postsGET /posts/{slug}- Get post contentGET /images/{image}- Get images (like a permalink)POST /prompt- Chat with AI (streaming)GET /query- Semantic search (for debug)POST /reingest- Refresh all blog and kb contentPOST /update- Gets portfolio content
Check out the blog post for the full dev journey and lessons learned.
🔥 See it live in action: tedawf.com
📚 Check out the docs: OpenAPI Docs
Feel free to fork or open an issue/PR!