Skip to main content
The recommended way to self-host Nous. Tested on Ubuntu 24.04 with 2GB RAM and 2 vCPUs.
You will need a Supabase project before starting. The free tier is enough to get going.

What you get

Docker Compose brings up 5 containers:
  • api — Express API server, identity resolution, signal ingestion
  • worker — Background jobs: AI synthesis, live sync, ICP scoring
  • frontend — Nginx serving the React SPA
  • redis — Session state and job queue
  • caddy — Automatic SSL and subdomain routing

Step 1: Get the files

Clone the repo or download just the production files:
git clone https://github.com/NousC/nous.git
cd nous

Step 2: Configure environment

cp nous.env.example nous.env
Open nous.env and fill in:
# ── Domains ────────────────────────────────────────────────────────────────────
APP_DOMAIN=app.yourdomain.com
API_DOMAIN=api.yourdomain.com

# ── Supabase — Settings → API ──────────────────────────────────────────────────
SUPABASE_URL=https://yourproject.supabase.co
SUPABASE_SERVICE_ROLE_KEY=eyJ...
VITE_SUPABASE_URL=https://yourproject.supabase.co
VITE_SUPABASE_ANON_KEY=eyJ...

# ── Anthropic ──────────────────────────────────────────────────────────────────
ANTHROPIC_API_KEY=sk-ant-...

# ── Generate these — run: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
ENCRYPTION_KEY=

Step 3: Run the database schema

Required before first boot. Skip this and the app will start but nothing will work.
Open your Supabase project → SQL Editor → paste and run the full contents of supabase/schema.sql. This creates all tables, RLS policies, indexes, and enables vector and uuid-ossp.

Step 4: Point your DNS

Create two A records pointing to your server IP:
RecordPoints to
app.yourdomain.comYour server IP
api.yourdomain.comYour server IP
Caddy handles SSL automatically once DNS resolves.

Step 5: Start

docker compose up -d
First run builds all images — takes 2–3 minutes. After that:
  • Frontend → https://app.yourdomain.com
  • API → https://api.yourdomain.com

Step 6: Enable email auth in Supabase

Open your Supabase project → Authentication → Providers → Email and turn it on. Without this, no one can sign up. If you want Google sign-in, enable the Google provider in the same panel and set your OAuth client ID and secret.

Step 7: Create your first user

Open https://app.yourdomain.com and click Sign up. Enter your email and password, confirm the OTP, and run through the onboarding flow. Your workspace is created at the end of onboarding.

Step 8: Create an API key

In the app, go to Settings → API Keys → Create Key. Use that key for the MCP server or any REST call. The MCP config looks like this.
{
  "mcpServers": {
    "nous": {
      "command": "npx",
      "args": ["-y", "@opennous/mcp"],
      "env": {
        "NOUS_API_KEY": "sk_live_...",
        "NOUS_API_URL": "https://api.yourdomain.com"
      }
    }
  }
}
Self-hosters must set NOUS_API_URL to their own API domain. Otherwise the MCP server talks to Nous Cloud.

Step 9: Connect your first integration

Open Settings → Integrations and connect at least one signal source to start populating your customer graph.

Updating

The images are built locally from source, so pull the latest code and rebuild:
git pull
docker compose up -d --build
git pull fetches the new code, --build recompiles the images from it, and -d restarts only the containers that changed (Redis and Caddy are left untouched). The frontend is rebuilt too — Vite bakes the UI into a static bundle at build time, so a plain restart won’t pick up frontend changes.
Some updates ship new database migrations under supabase/migrations/. These are not applied automatically. After pulling, check that folder for files newer than your last update and run any new ones in your Supabase SQL Editor before (or right after) rebuilding. Skipping a migration will make the new code error against an outdated schema.

Logs

docker compose logs -f api       # API server
docker compose logs -f worker    # Background worker
docker compose logs -f frontend  # Nginx / frontend

Stopping

docker compose down              # stop containers, keep data
docker compose down -v           # stop and wipe volumes (destructive)