Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions backend/.env.docker
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# ================================================================
# omi Backend - Local Docker Development Environment
# ================================================================
# Instructions:
# 1. Fill in [REQUIRED] values below
# 2. Run: bash scripts/install.sh
# ================================================================

# ---- Firebase / Google Cloud --------------------------------
# [REQUIRED] Paste your Firebase service account JSON as a single line:
# Get it: Firebase Console -> Project Settings -> Service Accounts -> Generate new private key
SERVICE_ACCOUNT_JSON=
GOOGLE_APPLICATION_CREDENTIALS=google-credentials.json
FIREBASE_API_KEY=
FIREBASE_AUTH_DOMAIN=
FIREBASE_PROJECT_ID=

# ---- Redis [pre-configured for local Docker] ----------------
REDIS_DB_HOST=redis
REDIS_DB_PORT=6379
REDIS_DB_PASSWORD=

# ---- Typesense [pre-configured for local Docker] ------------
TYPESENSE_HOST=typesense
TYPESENSE_HOST_PORT=8108
TYPESENSE_API_KEY=local_typesense_key

# ---- GCP Storage --------------------------------------------
# [REQUIRED] for audio processing and file storage
BUCKET_SPEECH_PROFILES=
BUCKET_BACKUPS=
BUCKET_PLUGINS_LOGOS=

# ---- Pinecone [REQUIRED for vector memory search] -----------
PINECONE_API_KEY=
PINECONE_INDEX_NAME=

# ---- Deepgram [REQUIRED for audio transcription] ------------
DEEPGRAM_API_KEY=

# ---- OpenAI [REQUIRED for AI features] ---------------------
OPENAI_API_KEY=

# ---- Security -----------------------------------------------
# [REQUIRED] Generate with: openssl rand -hex 32
ADMIN_KEY=
ENCRYPTION_SECRET=omi_ZwB2ZNqB2HHpMK6wStk7sTpavJiPTFg7gXUHnc4tFABPU6pZ2c2DKgehtfgi4RZv

# ---- Base URL -----------------------------------------------
BASE_API_URL=http://localhost:8080
API_BASE_URL=http://localhost:8080

# ---- Pusher (required for real-time conversation updates) ---
# Without this, conversations stay in_progress permanently
HOSTED_PUSHER_API_URL=

# ---- HuggingFace --------------------------------------------
HUGGINGFACE_TOKEN=

# ---- Optional Services --------------------------------------
GITHUB_TOKEN=
WORKFLOW_API_KEY=
HUME_API_KEY=
HUME_CALLBACK_URL=
STRIPE_API_KEY=
STRIPE_WEBHOOK_SECRET=
STRIPE_CONNECT_WEBHOOK_SECRET=
RAPID_API_HOST=
RAPID_API_KEY=
PERPLEXITY_API_KEY=

# ---- Google OAuth -------------------------------------------
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=

# ---- Apple OAuth --------------------------------------------
APPLE_CLIENT_ID=
APPLE_TEAM_ID=
APPLE_KEY_ID=
APPLE_PRIVATE_KEY=

# ---- Third-party OAuth Integrations -------------------------
TWITTER_CLIENT_ID=
TWITTER_CLIENT_SECRET=
NOTION_CLIENT_ID=
NOTION_CLIENT_SECRET=
WHOOP_CLIENT_ID=
WHOOP_CLIENT_SECRET=

# ---- Twilio (Phone Calls) -----------------------------------
TWILIO_ACCOUNT_SID=
TWILIO_AUTH_TOKEN=
TWILIO_API_KEY_SID=
TWILIO_API_KEY_SECRET=
TWILIO_TWIML_APP_SID=

# ---- LangSmith (optional - LLM observability) ---------------
LANGSMITH_TRACING=false
LANGSMITH_API_KEY=
LANGSMITH_PROJECT=omi-backend-chat
LANGSMITH_ENDPOINT=https://api.smith.langchain.com
OMI_LANGSMITH_AGENTIC_PROMPT_NAME=omi-agentic-system
OMI_LANGSMITH_PROMPT_CACHE_TTL_SECONDS=300
55 changes: 55 additions & 0 deletions backend/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
version: '3.8'

services:
backend:
build:
context: ..
dockerfile: backend/Dockerfile
ports:
- "8080:8080"
env_file:
- .env.docker
depends_on:
redis:
condition: service_healthy
typesense:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/v1/health"]
interval: 10s
timeout: 5s
retries: 10
start_period: 60s
restart: on-failure

redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
command: redis-server --appendonly yes
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 5s
retries: 5

typesense:
image: typesense/typesense:0.25.1
ports:
- "8108:8108"
environment:
- TYPESENSE_API_KEY=local_typesense_key
- TYPESENSE_DATA_DIR=/data
volumes:
- typesense_data:/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8108/health"]
interval: 5s
timeout: 5s
retries: 5

volumes:
redis_data:
typesense_data:
102 changes: 102 additions & 0 deletions backend/scripts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Omi Backend — One-Click Deployment

Self-host the omi backend with a single command using Docker Compose.

## Prerequisites

- [Docker](https://docs.docker.com/get-docker/) 20.10+
- Docker Compose v2 (plugin) or v1 (standalone)
- API credentials listed below

## Required API Keys

| Service | Purpose | Sign up |
|---------|---------|---------|
| Firebase / GCP | Auth, Firestore DB, Storage | [console.firebase.google.com](https://console.firebase.google.com) |
| OpenAI | AI chat and processing | [platform.openai.com](https://platform.openai.com) |
| Deepgram | Audio transcription | [console.deepgram.com](https://console.deepgram.com) |
| Pinecone | Vector memory search | [app.pinecone.io](https://app.pinecone.io) |

**Redis** and **Typesense** run locally inside Docker — no external accounts needed.

## Quick Start

```bash
# 1. Clone the repository
git clone https://github.com/BasedHardware/omi.git
cd omi/backend

# 2. Configure your API keys
cp .env.docker .env.docker
# Edit .env.docker — fill in SERVICE_ACCOUNT_JSON, OPENAI_API_KEY,
# DEEPGRAM_API_KEY, PINECONE_API_KEY, and GCP bucket names

# 3. Deploy
bash scripts/install.sh
```

## Manual Start

```bash
cd omi/backend
docker compose -f docker-compose.yaml up -d --build

# Verify
curl http://localhost:8080/v1/health
# Expected: {"status":"ok"}
```

## Services

| Service | Port | Notes |
|---------|------|-------|
| Backend API | 8080 | FastAPI application |
| Redis | 6379 | Persistent session cache |
| Typesense | 8108 | Full-text search index |

## Architecture

```
docker compose up (run from omi/backend/)
├── backend:8080 ← FastAPI
│ ├── build context = repo root (../), dockerfile = backend/Dockerfile
│ ├── env loaded from .env.docker
│ ├── REDIS_DB_HOST=redis, REDIS_DB_PORT=6379
│ └── TYPESENSE_HOST=typesense, TYPESENSE_HOST_PORT=8108
├── redis:6379 ← Persistent (appendonly yes)
└── typesense:8108 ← Search (local_typesense_key)
```

## Common Commands

```bash
# View backend logs
docker compose -f docker-compose.yaml logs -f backend

# Stop all services
docker compose -f docker-compose.yaml down

# Full reset (removes volumes)
docker compose -f docker-compose.yaml down -v

# Rebuild after code changes
docker compose -f docker-compose.yaml up -d --build
```

## Troubleshooting

**Health check:** The correct endpoint is `/v1/health` (not `/health`):
```bash
curl http://localhost:8080/v1/health
# → {"status":"ok"}
```

**Build fails:** Run `docker compose` from inside `omi/backend/` — the build context
is set to `..` (repo root) which is required by `backend/Dockerfile`.

**Backend exits on startup:** Check logs with `docker compose -f docker-compose.yaml logs backend`.
Usually a missing env var. Confirm `SERVICE_ACCOUNT_JSON` and `OPENAI_API_KEY` are set in `.env.docker`.

**Redis not connecting:** Ensure `.env.docker` has `REDIS_DB_HOST=redis` and `REDIS_DB_PORT=6379`
(not `REDIS_URL` — that variable is not read by the omi backend).
93 changes: 93 additions & 0 deletions backend/scripts/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/bin/bash
set -e

RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
info() { echo -e "${GREEN}[INFO]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }

echo "=================================="
echo " Omi Backend One-Click Deployment"
echo "=================================="

# Detect docker compose (v2 plugin first, fall back to v1 standalone)
if docker compose version &>/dev/null 2>&1; then
DOCKER_COMPOSE="docker compose"
elif docker-compose version &>/dev/null 2>&1; then
DOCKER_COMPOSE="docker-compose"
else
error "Docker Compose not found. Install Docker Desktop: https://docs.docker.com/get-docker/"
fi
info "Docker Compose: $DOCKER_COMPOSE"

# Check Docker is running
docker info &>/dev/null 2>&1 || error "Docker daemon not running. Please start Docker."

# Navigate to backend directory (script lives in backend/scripts/)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BACKEND_DIR="$(dirname "$SCRIPT_DIR")"
cd "$BACKEND_DIR"
info "Working directory: $BACKEND_DIR"

# Create .env.docker if missing
if [ ! -f ".env.docker" ]; then
error ".env.docker not found in $BACKEND_DIR. See scripts/README.md for setup instructions."
fi

# Generate ADMIN_KEY if not set
if grep -q "^ADMIN_KEY=$" .env.docker 2>/dev/null; then
if command -v openssl &>/dev/null; then
GENERATED_KEY=$(openssl rand -hex 32)
sed -i.bak "s/^ADMIN_KEY=$/ADMIN_KEY=$GENERATED_KEY/" .env.docker && rm -f .env.docker.bak
info "Generated secure ADMIN_KEY"
fi
fi

# Validate critical env vars
set -a; source .env.docker; set +a

missing=()
[ -z "${OPENAI_API_KEY:-}" ] && missing+=("OPENAI_API_KEY")
[ -z "${DEEPGRAM_API_KEY:-}" ] && missing+=("DEEPGRAM_API_KEY")
[ -z "${PINECONE_API_KEY:-}" ] && missing+=("PINECONE_API_KEY")
[ -z "${SERVICE_ACCOUNT_JSON:-}" ] && missing+=("SERVICE_ACCOUNT_JSON")

if [ ${#missing[@]} -gt 0 ]; then
warn "The following required keys are not set in .env.docker:"
for key in "${missing[@]}"; do warn " - $key"; done
echo ""
read -p "Continue anyway? Some features will not work. [y/N]: " confirm
[[ "$confirm" =~ ^[Yy]$ ]] || exit 1
fi

# Build and start services
info "Building and starting services (this may take a few minutes on first run)..."
$DOCKER_COMPOSE -f docker-compose.yaml up -d --build

# Wait for backend health
info "Waiting for backend to be ready..."
max_attempts=40
attempt=0
until curl -sf http://localhost:8080/v1/health &>/dev/null; do
attempt=$((attempt + 1))
if [ $attempt -ge $max_attempts ]; then
warn "Health check timed out after $((max_attempts * 3))s. Showing logs:"
$DOCKER_COMPOSE -f docker-compose.yaml logs backend --tail=30
exit 1
fi
printf "."
sleep 3
done
echo ""

info "========================================="
info " Omi backend is running!"
info "========================================="
info " API: http://localhost:8080"
info " Health: http://localhost:8080/v1/health"
info " Typesense: http://localhost:8108"
info " Redis: localhost:6379"
info ""
info " Logs: $DOCKER_COMPOSE -f docker-compose.yaml logs -f"
info " Stop: $DOCKER_COMPOSE -f docker-compose.yaml down"
info "========================================="