- Posted on
- • Artificial Intelligence
Building RAG Applications on Linux
- Author
-
-
- User
- linuxbash
- Posts by this author
- Posts by this author
-
Building RAG Applications on Linux: From Zero to Local Q&A
Ever wished your shell could answer questions about your codebase, your logs, or your company wiki—without sending data to the cloud? Retrieval-Augmented Generation (RAG) lets you ground an LLM with your own documents so answers are accurate, cite sources, and stay private. On Linux, it’s straightforward, scriptable, and fast.
This post shows you how to build a local RAG pipeline on Linux using open-source tools. You’ll index your docs, ask questions, and get sourced answers—entirely on your machine.
What problem does RAG solve?
LLMs hallucinate when they don’t know your domain. RAG retrieves relevant context from your docs and feeds it into the LLM, improving accuracy.
Keeps your data local. No copy-pasting screenshots into random chat windows.
Repeatable, automatable. Linux cron jobs, shell scripts, systemd—build it into your workflow.
At a high level:
Retrieval: Embed your documents and fetch the most relevant chunks for a question.
Generation: Pass those chunks to an LLM to produce a grounded answer with citations.
What we’ll build
A tiny RAG stack on Linux:
- Local LLM runtime: Ollama
- Embeddings + Vector store: sentence-transformers + FAISS
- Orchestration: LangChain
Two scripts:
- Index your docs into a vector database
- Ask questions and get answers with sources
You can adapt this to your codebase, knowledge base, logs, or even man pages.
1) Install prerequisites
We’ll install Python, Git, and a few basics. Use your distro’s package manager.
Debian/Ubuntu (apt):
sudo apt update sudo apt install -y python3 python3-venv python3-pip git curlFedora/RHEL/CentOS (dnf):
sudo dnf install -y python3 python3-pip python3-virtualenv git curlopenSUSE (zypper):
sudo zypper refresh sudo zypper install -y python3 python3-pip python3-virtualenv git curl
Note: We’ll create a Python venv, so either python3-venv or python3-virtualenv will work depending on your distro.
2) Install a local LLM with Ollama
Ollama runs LLMs locally and exposes a simple HTTP API.
Install Ollama (official script for Linux):
curl -fsSL https://ollama.com/install.sh | shStart the service (if not already running):
ollama servePull a model (Llama 3 8B is a solid default for CPU/GPU laptops):
ollama pull llama3:8b
Tip: You can also try mistral:7b, phi3:mini, or other models from the Ollama library. Keep an eye on RAM/VRAM requirements.
3) Create a Python environment and install libraries
We’ll use LangChain, FAISS, and sentence-transformers.
Create and activate a virtual environment:
python3 -m venv .venv . .venv/bin/activateInstall Python packages:
pip install --upgrade pip pip install "langchain>=0.2" "langchain-community>=0.2" "langchain-text-splitters>=0.2" \ "faiss-cpu" "sentence-transformers" "pypdf" "ollama"
4) Prepare some documents
Create a docs folder and add files you care about. Text, Markdown, code, and PDFs are fine.
Example: Export a few man pages into plain text:
mkdir -p docs for m in bash grep sed awk find; do man -P cat "$m" > "docs/$m.txt" doneOr add your project README and docs:
cp -r /path/to/your/project/docs/* ./docs/
5) Index and query: minimal RAG in two scripts
Below are two scripts:
rag_index.py: loads and chunks your documents, builds embeddings, and saves a FAISS index to disk.
rag_ask.py: retrieves the most relevant chunks and asks a local LLM (via Ollama) to answer with sources.
Save both scripts to your project directory.
rag_index.py:
#!/usr/bin/env python3
import sys
from pathlib import Path
from typing import List
from langchain_community.document_loaders import TextLoader, PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_community.embeddings import SentenceTransformerEmbeddings
def load_docs(root: Path) -> List:
docs = []
for path in root.rglob("*"):
if not path.is_file():
continue
suffix = path.suffix.lower()
try:
if suffix in [".txt", ".md", ".rst", ".log", ".cfg", ".ini", ".py", ".sh", ".yaml", ".yml"]:
docs.extend(TextLoader(str(path), encoding="utf-8").load())
elif suffix == ".pdf":
docs.extend(PyPDFLoader(str(path)).load())
except Exception as e:
print(f"Skip {path}: {e}")
return docs
def main():
if len(sys.argv) < 2:
print("Usage: rag_index.py /path/to/docs [index_dir]")
sys.exit(1)
docs_path = Path(sys.argv[1]).expanduser().resolve()
index_dir = Path(sys.argv[2]).resolve() if len(sys.argv) > 2 else Path("faiss_index")
print(f"Loading documents from: {docs_path}")
raw_docs = load_docs(docs_path)
if not raw_docs:
print("No documents found.")
sys.exit(1)
print(f"Loaded {len(raw_docs)} documents. Chunking...")
splitter = RecursiveCharacterTextSplitter(chunk_size=800, chunk_overlap=100)
chunks = splitter.split_documents(raw_docs)
print(f"Created {len(chunks)} chunks.")
print("Creating embeddings (all-MiniLM-L6-v2)...")
embeddings = SentenceTransformerEmbeddings(model_name="all-MiniLM-L6-v2")
print("Building FAISS index...")
vectordb = FAISS.from_documents(chunks, embeddings)
index_dir.mkdir(parents=True, exist_ok=True)
vectordb.save_local(str(index_dir))
print(f"Index saved to: {index_dir}")
if __name__ == "__main__":
main()
rag_ask.py:
#!/usr/bin/env python3
import sys
from langchain_community.vectorstores import FAISS
from langchain_community.embeddings import SentenceTransformerEmbeddings
from langchain_community.llms import Ollama
from langchain.chains import RetrievalQA
def main():
if len(sys.argv) < 2:
print("Usage: rag_ask.py \"your question\" [index_dir] [model]")
sys.exit(1)
question = sys.argv[1]
index_dir = sys.argv[2] if len(sys.argv) > 2 else "faiss_index"
model = sys.argv[3] if len(sys.argv) > 3 else "llama3:8b"
print(f"Loading index from: {index_dir}")
embeddings = SentenceTransformerEmbeddings(model_name="all-MiniLM-L6-v2")
vectordb = FAISS.load_local(index_dir, embeddings, allow_dangerous_deserialization=True)
retriever = vectordb.as_retriever(search_kwargs={"k": 4})
llm = Ollama(model=model)
qa = RetrievalQA.from_chain_type(
llm=llm,
retriever=retriever,
chain_type="stuff",
return_source_documents=True,
)
print(f"Asking: {question}\n")
result = qa({"query": question})
print("Answer:\n")
print(result["result"])
print("\nSources:")
for i, d in enumerate(result["source_documents"], 1):
print(f"{i}. {d.metadata.get('source', 'unknown')}")
print()
if __name__ == "__main__":
main()
Make them executable and run:
chmod +x rag_index.py rag_ask.py
# 1) Index your docs
./rag_index.py ./docs
# 2) Ask a question
./rag_ask.py "How do I search recursively for a string and show line numbers?"
Tip: If Ollama isn’t running, start it in another terminal:
ollama serve
And ensure you’ve pulled a model:
ollama pull llama3:8b
Real-world examples you can try today
Your codebase: Point the indexer at your repo’s docs and src to build a code-aware assistant.
System administration: Index /etc configs, runbook Markdown, and logs to quickly troubleshoot recurring issues.
Man pages + README: Combine local man pages with your project README for a power-user shell assistant.
Internal wiki exports: Export Confluence/Notion/MediaWiki pages to Markdown and index them.
Tips for good RAG results
Chunking matters: 600–1,000 characters with 10–20% overlap is a solid default. Tune for your data.
Keep embeddings small and fast: all-MiniLM-L6-v2 is lightweight and accurate for many cases.
Garbage in, garbage out: Clean your docs (remove boilerplate, banners, navigation).
Add citations to prompts: The RetrievalQA chain will include sources; keep them visible for trust and debugging.
Iterate: Evaluate a small test set of Q&A pairs and refine chunk sizes, k (number of retrieved chunks), and model choice.
Optional: Package install recap (all distros)
If you skipped the prerequisites earlier or are setting up another machine:
Debian/Ubuntu (apt):
sudo apt update sudo apt install -y python3 python3-venv python3-pip git curlFedora/RHEL/CentOS (dnf):
sudo dnf install -y python3 python3-pip python3-virtualenv git curlopenSUSE (zypper):
sudo zypper refresh sudo zypper install -y python3 python3-pip python3-virtualenv git curl
Then install Ollama:
curl -fsSL https://ollama.com/install.sh | sh
Conclusion and next steps
You’ve just built a local, private RAG app on Linux:
Documents in, vectors out
Relevant chunks retrieved
A local LLM generates grounded answers with sources
Next steps:
Add a TUI/CLI wrapper to stream answers in your terminal
Swap FAISS for a server-backed vector DB (e.g., Qdrant) for multi-user setups
Automate re-indexing with a cron job or systemd timer
Add domain-specific prompt templates and guardrails
If this improved your workflow, index your main project today and ask it three questions you search for weekly. Then iterate—Linux makes it easy to script, schedule, and scale your RAG.