feat: one-click deployment for omi backend (#3919)#6598
feat: one-click deployment for omi backend (#3919)#6598huanshi231-cmd wants to merge 9 commits intoBasedHardware:mainfrom
Conversation
- Add docker-compose.yaml with Redis, Typesense, PostgreSQL - Add interactive install.sh script - Add deployment documentation - Health checks for all services - QUICK START mode (no API keys) - FULL SETUP mode (all features) Resolves BasedHardware#3919 ($300 bounty)
Greptile SummaryThis PR adds a one-click deployment script (
Confidence Score: 2/5Not safe to merge — the deployment will fail to build and the resulting container cannot connect to Redis, Typesense, or its primary datastore (Firestore). Five distinct P1 defects: wrong Docker build context (build errors out), wrong Redis env var names (Redis silently unused), wrong Typesense port env var (search broken), incorrect datastore (PostgreSQL instead of Firestore), and a broken relative path in install.sh. Each issue independently prevents the feature from working as described. backend/docker-compose.yaml and backend/scripts/install.sh both require significant corrections before the deployment can work. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[User runs ./install.sh] --> B{Choose mode}
B -->|1 - Quick Start| C[export QUICK_START=true\n⚠️ never consumed]
B -->|2 - Full Setup| D[Prompt: configure .env]
C --> E[docker-compose up -d\n⚠️ wrong path if run from scripts/]
D --> E
E --> F[Build backend image\n❌ context=. breaks COPY backend/]
E --> G[Start postgres:15\n⚠️ not used by backend]
E --> H[Start redis:7\n⚠️ REDIS_URL not read by backend]
E --> I[Start typesense:0.25.1\n⚠️ TYPESENSE_PORT ≠ TYPESENSE_HOST_PORT]
F -->|build fails| Z[❌ Deployment fails]
G --> J[backend container]
H --> J
I --> J
J -->|GOOGLE_APPLICATION_CREDENTIALS missing| K[❌ Firestore unreachable]
Reviews (1): Last reviewed commit: "feat: one-click deployment for omi backe..." | Re-trigger Greptile |
| build: | ||
| context: . | ||
| dockerfile: Dockerfile |
There was a problem hiding this comment.
Wrong build context — Docker build will fail
The existing backend/Dockerfile was written to be built from the repository root: it uses COPY backend/requirements.txt and COPY backend/ ., which require the context to include a backend/ subdirectory. Setting context: . when docker-compose.yaml lives inside backend/ makes the context backend/, so Docker will look for backend/backend/requirements.txt — which doesn't exist and causes the build to fail immediately.
Fix: set the context to the repo root.
| build: | |
| context: . | |
| dockerfile: Dockerfile | |
| build: | |
| context: .. | |
| dockerfile: backend/Dockerfile |
| - DATABASE_URL=${DATABASE_URL:-postgresql://postgres:postgres@postgres:5432/omi} | ||
| - REDIS_URL=${REDIS_URL:-redis://redis:6379} |
There was a problem hiding this comment.
Env vars don't match what the backend reads
Two mismatches here that will silently break the services:
-
DATABASE_URL— the backend uses Firestore as its primary database, not PostgreSQL. There is noDATABASE_URLread anywhere in the backend code; the PostgreSQL service (and this env var) have no effect and only add confusion. -
REDIS_URL—backend/database/redis_db.pyreadsos.getenv('REDIS_DB_HOST')(plusREDIS_DB_PORTandREDIS_DB_PASSWORD) as separate env vars, not a connection URL. PassingREDIS_URLmeans Redis will not be connected and the backend silently falls back to no-cache / no-rate-limiting mode.
Replace with the variables the backend actually consumes:
| - DATABASE_URL=${DATABASE_URL:-postgresql://postgres:postgres@postgres:5432/omi} | |
| - REDIS_URL=${REDIS_URL:-redis://redis:6379} | |
| - REDIS_DB_HOST=redis | |
| - REDIS_DB_PORT=6379 | |
| - REDIS_DB_PASSWORD= |
| - DATABASE_URL=${DATABASE_URL:-postgresql://postgres:postgres@postgres:5432/omi} | ||
| - REDIS_URL=${REDIS_URL:-redis://redis:6379} | ||
| - TYPESENSE_HOST=${TYPESENSE_HOST:-typesense} | ||
| - TYPESENSE_PORT=${TYPESENSE_PORT:-8108} |
There was a problem hiding this comment.
Typesense port env var name mismatch
backend/utils/conversations/search.py reads os.getenv('TYPESENSE_HOST_PORT'), but this compose file exposes the variable as TYPESENSE_PORT. The search client will receive None for the port and the Typesense connection will fail.
| - TYPESENSE_PORT=${TYPESENSE_PORT:-8108} | |
| - TYPESENSE_HOST_PORT=${TYPESENSE_HOST_PORT:-8108} |
| postgres: | ||
| image: postgres:15-alpine | ||
| environment: | ||
| POSTGRES_USER: postgres | ||
| POSTGRES_PASSWORD: postgres | ||
| POSTGRES_DB: omi | ||
| ports: | ||
| - "5432:5432" | ||
| volumes: | ||
| - postgres_data:/var/lib/postgresql/data | ||
| healthcheck: | ||
| test: ["CMD-SHELL", "pg_isready -U postgres"] | ||
| interval: 5s | ||
| timeout: 5s | ||
| retries: 5 |
There was a problem hiding this comment.
PostgreSQL service is unused — the backend runs on Firestore
The backend's primary datastore is Firestore (Google Cloud), not PostgreSQL. The backend/CLAUDE.md and backend/.env.template confirm there is no DATABASE_URL or any Postgres driver in the stack. Shipping a PostgreSQL container that nothing connects to misleads contributors and wastes resources.
The actual credentials the backend needs to start are GOOGLE_APPLICATION_CREDENTIALS (Firestore / GCS) and OPENAI_API_KEY (required for LLM calls). Neither is present in the compose file, so even the "QUICK START" mode won't produce a working backend.
| export QUICK_START=true | ||
| docker-compose -f docker-compose.yaml up -d |
There was a problem hiding this comment.
QUICK_START is exported but never consumed
export QUICK_START=true has no effect: docker-compose.yaml does not reference QUICK_START in any env block or condition, and both branches of the if/elif run the exact same docker-compose … up -d command. The two modes are functionally identical.
Either wire QUICK_START into the compose file (e.g., to skip optional services or set reduced resource limits), or remove the export and distinguish the modes in a meaningful way (e.g., mode 1 skips a .env validity check, mode 2 validates required API keys before starting).
| docker-compose -f docker-compose.yaml up -d | ||
| elif [ "$choice" = "2" ]; then | ||
| echo "" | ||
| echo "Starting FULL SETUP mode..." | ||
| echo "Please ensure you have configured your API keys in .env file" | ||
| read -p "Press Enter to continue..." | ||
| docker-compose -f docker-compose.yaml up -d |
There was a problem hiding this comment.
Relative path to
docker-compose.yaml will fail when running from backend/scripts/
The README instructs users to run ./install.sh from backend/scripts/, but docker-compose -f docker-compose.yaml looks for docker-compose.yaml in the current working directory, which would be backend/scripts/ — not backend/. The file won't be found and the script errors out immediately.
Use the script's own directory to build an absolute path:
| docker-compose -f docker-compose.yaml up -d | |
| elif [ "$choice" = "2" ]; then | |
| echo "" | |
| echo "Starting FULL SETUP mode..." | |
| echo "Please ensure you have configured your API keys in .env file" | |
| read -p "Press Enter to continue..." | |
| docker-compose -f docker-compose.yaml up -d | |
| SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" | |
| docker-compose -f "$SCRIPT_DIR/../docker-compose.yaml" up -d |
(Apply the same fix to the elif branch on line 24.)
| echo "" | ||
| echo "Starting QUICK START mode..." | ||
| export QUICK_START=true | ||
| docker-compose -f docker-compose.yaml up -d |
There was a problem hiding this comment.
docker-compose CLI is deprecated
docker-compose (v1, standalone Python binary) has been deprecated since Docker Desktop 4.x; the current command is docker compose (v2, built-in plugin). Users on newer Docker installs may not have docker-compose at all and will get a "command not found" error.
| docker-compose -f docker-compose.yaml up -d | |
| docker compose -f docker-compose.yaml up -d |
| echo "===================================" | ||
| sleep 10 |
There was a problem hiding this comment.
Fixed
sleep 10 instead of polling actual health
The compose file already configures health checks with condition: service_healthy on depends_on, so by the time up -d returns the services are likely not yet healthy. A hard sleep 10 either undershoots (services still starting) or wastes time. Consider polling with docker compose wait or checking health directly:
| echo "===================================" | |
| sleep 10 | |
| echo "Waiting for services to be ready..." | |
| docker compose -f "$SCRIPT_DIR/../docker-compose.yaml" wait backend || true |
…file, fix health check
One-Click Deployment Solution
Resolves #3919 ($300 bounty)
What was wrong with previous PRs (and how this fixes each one)
Based on the Greptile analysis of #6093 and feedback on #4732:
build.context: ./backend— wrong, Dockerfile usesCOPY backend/relative to repo rootcontext: ..,dockerfile: backend/Dockerfileenv_filedirectiveenv_file: .env.dockerREDIS_URL(not read by backend)REDIS_DB_HOST=redis,REDIS_DB_PORT=6379,REDIS_DB_PASSWORD=volumes: - ./:/appdefeats the Docker build/health/v1/health(matchesbackend/routers/other.py).env.dockercovers all variables frombackend/.env.templatedocker compose(v2) first, falls back todocker-compose(v1)Files Changed
backend/docker-compose.yamlbackend/.env.dockerbackend/scripts/install.shbackend/scripts/README.mdArchitecture
Usage
/claim #3919