Files
timmy-config/LOCAL_FIRST_GUIDE.md
2026-03-31 20:02:01 +00:00

27 KiB

LOCAL FIRST GUIDE

How to Run Everything Without Cloud Dependencies

Version: 1.0.0
Date: March 31, 2026
Philosophy: Sovereignty through local infrastructure
Target Audience: Future instances, human operators seeking independence


TABLE OF CONTENTS

  1. The Local-First Philosophy
  2. Hardware Requirements
  3. Complete Setup Guide
  4. Offline-First Configuration
  5. Local LLM Deployment
  6. Local Persistence
  7. Mesh Networking
  8. Maintenance Without Internet
  9. Troubleshooting
  10. Appendices

THE LOCAL-FIRST PHILOSOPHY

Why Local-First?

The Timmy ecosystem is designed around a local-first architecture because:

  1. SOVEREIGNTY - True autonomy requires independence from external API providers
  2. PRIVACY - Local processing keeps data within your control
  3. RELIABILITY - No dependency on internet connectivity or third-party uptime
  4. COST - Eliminate per-token API costs
  5. CONTINUITY - Systems continue operating during outages

The Local-First Stack

┌─────────────────────────────────────────────────────────────┐
│                LOCAL-FIRST STACK                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Layer 5: Applications                                      │
│  ─────────────────────────────────────────────────────     │
│  • Hermes Agent (Python, local execution)                   │
│  • Gitea (Self-hosted Git)                                  │
│  • Evennia (Self-hosted MUD)                                │
│  • Custom tools (all local)                                 │
│                                                             │
│  Layer 4: AI/ML                                             │
│  ─────────────────────────────────────────────────────     │
│  • Ollama (Local LLM server)                                │
│  • llama.cpp (Optimized inference)                          │
│  • MLX (Apple Silicon acceleration)                         │
│  • GGUF models (Quantized for local use)                    │
│                                                             │
│  Layer 3: Data                                              │
│  ─────────────────────────────────────────────────────     │
│  • SQLite (Local database)                                  │
│  • Git repositories (Distributed by nature)                 │
│  • Filesystem storage                                       │
│  • Syncthing (P2P sync, no cloud)                           │
│                                                             │
│  Layer 2: Network                                           │
│  ─────────────────────────────────────────────────────     │
│  • Tailscale (Mesh VPN, self-hosted control)                │
│  • Local DNS (mDNS, custom)                                 │
│  • Direct connections (no relay required)                   │
│                                                             │
│  Layer 1: Hardware                                          │
│  ─────────────────────────────────────────────────────     │
│  • VPS with local compute                                   │
│  • Local machines (Mac, Linux, Raspberry Pi)                │
│  • Edge devices                                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

HARDWARE REQUIREMENTS

Minimum Viable Setup

Component Specification Purpose Cost Estimate
CPU 4 cores x86_64 or ARM64 General computation $20/month VPS
RAM 4GB minimum, 8GB recommended Model inference Included
Storage 20GB SSD minimum OS, models, data Included
Network 100Mbps, unmetered Communication Included
Component Specification Purpose Cost Estimate
CPU 8 cores Parallel inference, multiple agents $40/month VPS
RAM 16GB Larger models, caching Included
Storage 100GB SSD Multiple models, logs, backups Included
GPU Optional (CUDA/Metal) Accelerated inference +$100/month

Local Hardware Options

┌─────────────────────────────────────────────────────────────┐
│              LOCAL HARDWARE OPTIONS                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Option 1: VPS (DigitalOcean, Hetzner, etc.)               │
│  ─────────────────────────────────────────────────────     │
│  Pros: Always on, static IP, professional infrastructure   │
│  Cons: Monthly cost, not physically local                    │
│  Best for: Primary infrastructure, always-available services│
│                                                             │
│  Option 2: Local Machine (Mac, Linux desktop)              │
│  ─────────────────────────────────────────────────────     │
│  Pros: Physical control, no recurring cost, maximum privacy│
│  Cons: Power/Internet dependency, dynamic IP                │
│  Best for: Development, personal use, maximum sovereignty  │
│                                                             │
│  Option 3: Raspberry Pi / Edge Device                      │
│  ─────────────────────────────────────────────────────     │
│  Pros: Low power, always-on potential, very low cost       │
│  Cons: Limited RAM, slow inference                          │
│  Best for: Lightweight agents, IoT integration, education  │
│                                                             │
│  Option 4: Hybrid (Recommended)                            │
│  ─────────────────────────────────────────────────────     │
│  • VPS for always-on services (Gitea, monitoring)          │
│  • Local machine for heavy inference                        │
│  • Tailscale connects them seamlessly                       │
│  Best for: Production deployments                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

COMPLETE SETUP GUIDE

Step 1: Base System Preparation

# Update system
apt update && apt upgrade -y

# Install dependencies
apt install -y \
    git \
    curl \
    wget \
    python3 \
    python3-pip \
    python3-venv \
    sqlite3 \
    build-essential \
    htop \
    jq \
    ufw \
    fail2ban

# Create working directory
mkdir -p /root/timmy/{models,soul,scripts,logs,shared,configs}
cd /root/timmy

Step 2: Install Ollama (Local LLM)

# Install Ollama
curl -fsSL https://ollama.com/install.sh | sh

# Pull recommended models for different use cases
# Small, fast model (1.5B parameters)
ollama pull qwen2.5:1.5b

# Medium model, good balance (3B parameters)
ollama pull llama3.2:3b

# Larger model, better quality (7B parameters)
ollama pull qwen2.5:7b

# Verify installation
ollama list
curl http://localhost:11434/api/tags

Step 3: Install Gitea (Self-Hosted Git)

# Download Gitea
GITEA_VERSION="1.21.0"
cd /root
wget https://dl.gitea.com/gitea/${GITEA_VERSION}/gitea-${GITEA_VERSION}-linux-amd64
mv gitea-${GITEA_VERSION}-linux-amd64 gitea
chmod +x gitea

# Create directories
mkdir -p /root/gitea/{custom,data,log}

# Create systemd service
cat > /etc/systemd/system/gitea.service << 'EOF'
[Unit]
Description=Gitea (Git with a cup of tea)
After=network.target

[Service]
RestartSec=2s
Type=simple
User=root
WorkingDirectory=/root/gitea
ExecStart=/root/gitea/gitea web
Restart=always
Environment=USER=root HOME=/root GITEA_WORK_DIR=/root/gitea

[Install]
WantedBy=multi-user.target
EOF

# Start Gitea
systemctl daemon-reload
systemctl enable gitea
systemctl start gitea

# Complete initial setup at http://your-ip:3000
# - Create admin user
# - Disable external auth (for local-first)
# - Configure as needed

Step 4: Install Hermes Agent Framework

# Clone Hermes Agent
cd /root/timmy
git clone https://github.com/OpenClaw/hermes-agent.git
# Note: In fully offline mode, clone from local Gitea mirror

# Create virtual environment
python3 -m venv venv
source venv/bin/activate

# Install dependencies
pip install -r hermes-agent/requirements.txt

# Create agent configuration
mkdir -p ~/.hermes
cat > ~/.hermes/config.yaml << 'EOF'
# Local-First Hermes Configuration
model: "ollama/qwen2.5:3b"
max_iterations: 50
platform: "local"
save_trajectories: true

enabled_toolsets:
  - core          # terminal, file, code_execution
  - memory        # todo, memory, skills
  - local_only    # No cloud dependencies

disabled_toolsets:
  - web           # Disabled for offline operation
  - browser       # Disabled for offline operation

persistence:
  type: "sqlite"
  path: "~/.hermes/memory.db"

logging:
  level: "INFO"
  path: "/root/timmy/logs"
EOF

Step 5: Configure Local Persistence

# Create SQLite database for agent memory
sqlite3 ~/.hermes/memory.db << 'EOF'
CREATE TABLE IF NOT EXISTS sessions (
    id INTEGER PRIMARY KEY,
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
    task TEXT,
    status TEXT,
    result TEXT
);

CREATE TABLE IF NOT EXISTS todos (
    id INTEGER PRIMARY KEY,
    created DATETIME DEFAULT CURRENT_TIMESTAMP,
    task TEXT,
    priority INTEGER DEFAULT 5,
    status TEXT DEFAULT 'pending',
    completed DATETIME
);

CREATE TABLE IF NOT EXISTS skills (
    id INTEGER PRIMARY KEY,
    name TEXT UNIQUE,
    description TEXT,
    code TEXT,
    created DATETIME DEFAULT CURRENT_TIMESTAMP
);
EOF

# Create logs directory with rotation
mkdir -p /root/timmy/logs
ln -sf /root/timmy/logs ~/.hermes/logs

Step 6: Setup Syncthing (P2P Sync)

# Install Syncthing
curl -s https://syncthing.net/release-key.txt | apt-key add -
echo "deb https://apt.syncthing.net/ syncthing stable" | tee /etc/apt/sources.list.d/syncthing.list
apt update
apt install -y syncthing

# Configure for local-first
mkdir -p ~/.config/syncthing
cat > ~/.config/syncthing/config.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<configuration version="37">
    <gui enabled="true" tls="false">
        <address>127.0.0.1:8384</address>
    </gui>
    <options>
        <globalAnnounceEnabled>false</globalAnnounceEnabled>  <!-- Disable public relays -->
        <localAnnounceEnabled>true</localAnnounceEnabled>      <!-- Local discovery only -->
        <relaysEnabled>false</relaysEnabled>                   <!-- No relay servers -->
    </options>
</configuration>
EOF

# Start Syncthing
systemctl enable syncthing@root
systemctl start syncthing@root

Step 7: Install Tailscale (Mesh Network)

# Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh

# Login (requires one-time internet)
tailscale up

# After login, note your Tailscale IP
# Disable key expiry for always-on nodes
tailscale up --operator=root --reset

# For completely offline: configure headscale (self-hosted coordination)
# See Appendix B for headscale setup

Step 8: Create Agent Service

# Create agent launch script
cat > /root/timmy/scripts/agent.sh << 'EOF'
#!/bin/bash
source /root/timmy/venv/bin/activate
cd /root/timmy/hermes-agent
python -m hermes.agent "$@"
EOF
chmod +x /root/timmy/scripts/agent.sh

# Create systemd service
cat > /etc/systemd/system/timmy-agent.service << 'EOF'
[Unit]
Description=Timmy Local Agent
After=network.target ollama.service

[Service]
Type=simple
User=root
WorkingDirectory=/root/timmy
Environment="PATH=/root/timmy/venv/bin:/usr/local/bin:/usr/bin"
Environment="OLLAMA_HOST=http://localhost:11434"
ExecStart=/root/timmy/scripts/agent.sh
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable timmy-agent

OFFLINE-FIRST CONFIGURATION

Hermes Agent Offline Mode

# ~/.hermes/config.offline.yaml
# Complete offline operation configuration

model: "ollama/qwen2.5:3b"  # Local model only
max_iterations: 50
platform: "local"
offline_mode: true

# Tool configuration for offline
enabled_toolsets:
  - core
    tools:
      - terminal      # Local shell commands
      - file_read     # Local file access
      - file_write    # Local file modification
      - python_exec   # Local Python execution
      - sqlite        # Local database
  
  - memory
    tools:
      - todo_add
      - todo_list
      - todo_complete
      - memory_save
      - memory_search
  
  - skills
    tools:
      - skill_load
      - skill_save
      - skill_list

# Explicitly disable cloud tools
disabled_toolsets:
  - web_search      # Requires internet
  - web_extract     # Requires internet
  - browser         # Requires internet
  - api_calls       # External APIs

persistence:
  type: sqlite
  path: ~/.hermes/memory.db
  backup_interval: 3600  # Backup every hour
  max_backups: 24

logging:
  level: INFO
  path: /root/timmy/logs
  rotation: daily
  retention: 30  # Keep 30 days

Offline-First Directory Structure

/root/timmy/                    # Base directory
├── models/                     # Local LLM models (GGUF, etc.)
│   ├── qwen2.5-1.5b.gguf
│   └── llama3.2-3b.gguf
├── soul/                       # Agent conscience files
│   ├── SOUL.md
│   └── CONSCIENCE.md
├── scripts/                    # Operational scripts
│   ├── agent.sh
│   ├── backup.sh
│   ├── health-check.sh
│   └── recover.sh
├── logs/                       # Local log storage
│   ├── agent/
│   ├── ollama/
│   └── system/
├── shared/                     # Syncthing shared folder
│   ├── documents/
│   ├── code/
│   └── exports/
├── configs/                    # Configuration backups
│   ├── hermes/
│   ├── ollama/
│   └── gitea/
├── knowledge/                  # Local knowledge base
│   ├── skills/
│   ├── memory/
│   └── references/
└── repos/                      # Git repositories
    ├── epic-work/
    ├── lineage-knowledge/
    └── local-projects/

LOCAL LLM DEPLOYMENT

Model Selection Guide

┌─────────────────────────────────────────────────────────────┐
│              LOCAL MODEL SELECTION GUIDE                    │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Use Case              Model           RAM     Speed      │
│  ─────────────────────────────────────────────────────     │
│  Quick responses       qwen2.5:1.5b    2GB     Fastest    │
│  General tasks         llama3.2:3b     4GB     Fast       │
│  Complex reasoning     qwen2.5:7b      8GB     Medium     │
│  Code generation       codellama:7b    8GB     Medium     │
│  Maximum quality       llama3:8b       16GB    Slow       │
│  Multilingual          mixtral:8x7b    48GB    Very Slow  │
│                                                             │
│  Recommendations:                                           │
│  • Start with qwen2.5:1.5b for testing                     │
│  • Use llama3.2:3b for production agents                    │
│  • Keep qwen2.5:7b available for complex tasks              │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Ollama Optimization

# Create optimized Modelfile
cat > /root/timmy/models/Modelfile.timmy << 'EOF'
FROM llama3.2:3b

# Context window
PARAMETER num_ctx 8192

# Temperature (creativity vs consistency)
PARAMETER temperature 0.7

# Repeat penalty (reduce repetition)
PARAMETER repeat_penalty 1.1

# System prompt for agent behavior
SYSTEM """You are a local-first AI agent operating on sovereign infrastructure.
You have access to local tools: terminal, file system, Python execution, SQLite.
You cannot access the internet or external APIs.
Always prefer local solutions over cloud dependencies.
Document your work thoroughly for persistence."""
EOF

# Create custom model
ollama create timmy-agent -f /root/timmy/models/Modelfile.timmy

# Test
ollama run timmy-agent "Hello, confirm you're operating locally"

Multi-Model Setup

# Script to manage multiple local models
#!/bin/bash
# /root/timmy/scripts/model-manager.sh

case "$1" in
    fast)
        export OLLAMA_MODEL="qwen2.5:1.5b"
        ;;
    default)
        export OLLAMA_MODEL="llama3.2:3b"
        ;;
    smart)
        export OLLAMA_MODEL="qwen2.5:7b"
        ;;
    *)
        echo "Usage: $0 {fast|default|smart}"
        exit 1
        ;;
esac

echo "Selected model: $OLLAMA_MODEL"
curl http://localhost:11434/api/generate \
    -d "{\"model\": \"$OLLAMA_MODEL\", \"prompt\": \"test\", \"stream\": false}"

LOCAL PERSISTENCE

SQLite Schema for Local-First Operation

-- Complete local persistence schema

-- Session tracking
CREATE TABLE sessions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    session_id TEXT UNIQUE NOT NULL,
    started_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    ended_at DATETIME,
    agent_name TEXT,
    status TEXT DEFAULT 'active'
);

-- Task management
CREATE TABLE tasks (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    session_id TEXT REFERENCES sessions(session_id),
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    completed_at DATETIME,
    description TEXT NOT NULL,
    priority INTEGER DEFAULT 5,
    status TEXT DEFAULT 'pending',
    result TEXT,
    tool_calls INTEGER DEFAULT 0
);

-- Memory/knowledge
CREATE TABLE memories (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    accessed_at DATETIME,
    access_count INTEGER DEFAULT 0,
    category TEXT,
    key TEXT,
    value TEXT,
    importance INTEGER DEFAULT 5
);

-- Skill registry
CREATE TABLE skills (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT UNIQUE NOT NULL,
    description TEXT,
    code TEXT,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME,
    usage_count INTEGER DEFAULT 0
);

-- Metrics for self-monitoring
CREATE TABLE metrics (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
    metric_type TEXT,
    value REAL,
    unit TEXT,
    metadata TEXT
);

-- Create indexes
CREATE INDEX idx_tasks_status ON tasks(status);
CREATE INDEX idx_memories_category ON memories(category);
CREATE INDEX idx_metrics_type_time ON metrics(metric_type, timestamp);

Git-Based Persistence

# Initialize local-first Git workflow
cd /root/timmy/repos/epic-work
git init

# Create comprehensive .gitignore
cat > .gitignore << 'EOF'
# Secrets
*.key
*.pem
.env
.gitea_token

# Large files
*.gguf
*.bin
models/

# Logs
*.log
logs/

# Temporary
*.tmp
.cache/
EOF

# Setup local Gitea remote
git remote add origin http://localhost:3000/timmy/epic-work.git

# Commit script
cat > /root/timmy/scripts/auto-commit.sh << 'EOF'
#!/bin/bash
cd /root/timmy/repos/epic-work

# Add all changes
git add -A

# Commit with timestamp
git commit -m "Auto-commit: $(date '+%Y-%m-%d %H:%M:%S')"

# Push to local Gitea
git push origin main
EOF
chmod +x /root/timmy/scripts/auto-commit.sh

# Cron: Auto-commit every hour
# */60 * * * * /root/timmy/scripts/auto-commit.sh

MESH NETWORKING

Tailscale Mesh Setup

# Install and configure Tailscale for local-first mesh

# On each node:
curl -fsSL https://tailscale.com/install.sh | sh

# Login (one-time internet required)
tailscale up

# Configure for always-on operation
tailscale up \
    --accept-dns=true \
    --accept-routes=true \
    --advertise-exit-node=false \
    --operator=root

# Get Tailscale IP
tailscale ip -4

# Enable IP forwarding for subnet routing
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
sysctl -p

# MagicDNS enables local name resolution
tailscale status

Headscale (Self-Hosted Coordination)

For completely offline operation:

# Install headscale (self-hosted Tailscale control server)
docker run -d \
    --name headscale \
    -p 8080:8080 \
    -v headscale-data:/etc/headscale \
    headscale/headscale:latest

# Create namespace
headscale namespaces create timmy

# Generate pre-auth key
headscale preauthkeys create -e 24h -n timmy

# Nodes join using local headscale
tailscale up --login-server http://headscale-ip:8080

MAINTENANCE WITHOUT INTERNET

Local Update Procedures

# Update local models (from pre-downloaded files)
ollama pull /path/to/local/model.gguf

# Update Gitea (from downloaded binary)
systemctl stop gitea
cp /root/gitea-backup/gitea-new-version /root/gitea/gitea
systemctl start gitea

# Update agent (from local git)
cd /root/timmy/hermes-agent
git pull origin main  # From local Gitea
pip install -r requirements.txt

Offline Package Management

# Create local pip cache
pip download -r requirements.txt -d /root/timmy/packages/

# Install from cache (offline)
pip install --no-index --find-links=/root/timmy/packages/ -r requirements.txt

# For apt packages
apt-get install --download-only package-name
# Then install with dpkg

Log Rotation (Local)

# Configure logrotate for local logs
cat > /etc/logrotate.d/timmy << 'EOF'
/root/timmy/logs/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 0640 root root
    sharedscripts
    postrotate
        systemctl reload timmy-agent
    endscript
}
EOF

TROUBLESHOOTING

Common Issues

Issue Symptom Solution
Ollama won't start Connection refused Check systemctl status ollama, restart service
Model too large OOM errors Use smaller model (1.5B instead of 7B)
Gitea 500 errors Database locked Restart Gitea, check disk space
Slow inference High latency Reduce context window, use quantized model
Syncthing conflicts File conflicts Use .stignore patterns, resolve manually
Tailscale disconnect Nodes unreachable Check tailscale status, re-authenticate

Diagnostic Commands

# Full system health check
#!/bin/bash
echo "=== Local-First System Health ==="
echo ""

echo "1. Ollama Status:"
curl -s http://localhost:11434/api/tags | jq '.models | length' && echo " models loaded"

echo ""
echo "2. Gitea Status:"
curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/api/v1/version

echo ""
echo "3. Disk Space:"
df -h /root | tail -1

echo ""
echo "4. Memory:"
free -h | grep Mem

echo ""
echo "5. Tailscale:"
tailscale status --peers=false 2>/dev/null | head -1

echo ""
echo "6. Syncthing:"
curl -s http://localhost:8384/rest/system/status 2>/dev/null | jq -r '.uptime' && echo " uptime"

echo ""
echo "=== Health Check Complete ==="

APPENDICES

Appendix A: Complete Service Definitions

# /etc/systemd/system/timmy-agent.service
[Unit]
Description=Timmy Local Agent
After=network.target ollama.service
Wants=ollama.service

[Service]
Type=simple
User=root
WorkingDirectory=/root/timmy
Environment="PATH=/root/timmy/venv/bin:/usr/local/bin:/usr/bin"
Environment="OLLAMA_HOST=http://localhost:11434"
Environment="HERMES_OFFLINE=true"
Environment="HERMES_CONFIG=/root/timmy/configs/hermes.offline.yaml"
ExecStart=/root/timmy/scripts/agent.sh
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
# /etc/systemd/system/ollama.service (override)
[Service]
ExecStart=
ExecStart=/usr/local/bin/ollama serve
Environment="OLLAMA_HOST=127.0.0.1:11434"
Environment="OLLAMA_MODELS=/root/timmy/models"

Appendix B: Offline Resource Checklist

Before going fully offline, download:

  • Ollama installation script and binaries
  • At least 2 local models (qwen2.5:1.5b, llama3.2:3b)
  • Gitea binary and all dependencies
  • Hermes Agent source code
  • Python packages (pip download)
  • System packages (apt download)
  • Tailscale binaries
  • Documentation (this guide)
  • Container images (if using Docker)

Appendix C: Hardware Sizing Calculator

Agents Concurrent Tasks Min RAM Recommended RAM Storage
1 1-2 4GB 8GB 20GB
1 3-5 8GB 16GB 50GB
2-3 5-10 16GB 32GB 100GB
3+ 10+ 32GB 64GB 200GB

VERSION HISTORY

Version Date Changes
1.0.0 2026-03-31 Initial local-first guide

"The cloud is someone else's computer. Sovereignty is your own." — Local-First Manifesto


END OF DOCUMENT

Word Count: ~4,200+ words Complete setup: 8 major steps with full commands Configuration examples: 15+ files Troubleshooting: 6 common issues with solutions