> ## Documentation Index
> Fetch the complete documentation index at: https://docs.opennous.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Docker Compose

> Deploy Nous on your own server with Docker Compose

The recommended way to self-host Nous. Tested on Ubuntu 24.04 with 2GB RAM and 2 vCPUs.

<Note>
  You will need a [Supabase](https://supabase.com) project before starting. The free tier is enough to get going.
</Note>

## What you get

Docker Compose brings up 5 containers:

* **api** — Express API server, identity resolution, signal ingestion
* **worker** — Background jobs: AI synthesis, two-way 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:

```bash theme={null}
git clone https://github.com/NousC/opennous.git
cd nous
```

## Step 2: Configure environment

```bash theme={null}
cp nous.env.example nous.env
```

Open `nous.env` and fill in:

```bash theme={null}
# ── 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=
```

**Optional — integrations.** These are instance-level: set the ones you want, then restart. Your agent will tell you which are missing during onboarding (it can't set env vars for you).

```bash theme={null}
# LinkedIn — Unipile (a paid third-party account)
UNIPILE_API_KEY=
UNIPILE_DSN=api1.unipile.com:13xxx

# Email sending — Resend
RESEND_API_KEY=

# Gmail connect — a Google Cloud OAuth client
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=

# Enrichment (Prospeo / Apollo) is bring-your-own-key — your agent connects it
# per workspace, no env var needed.
```

## Step 3: Run the database schema

<Warning>
  Required before first boot. Skip this and the app will start but nothing will work.
</Warning>

Open your Supabase project → **SQL Editor** → paste and run the full contents of [`supabase/schema.sql`](https://github.com/NousC/opennous/blob/main/supabase/schema.sql).

This one file is the complete schema — every table, view, function, trigger, RLS policy, and index, plus the `pgcrypto` and `vector` extensions it depends on. A fresh install needs only this file; do **not** also run the files in `supabase/migrations/` (those are the incremental history and are only used when updating an existing install — see Updating below).

## Step 4: Point your DNS

Create two A records pointing to your server IP:

| Record               | Points to      |
| -------------------- | -------------- |
| `app.yourdomain.com` | Your server IP |
| `api.yourdomain.com` | Your server IP |

Caddy handles SSL automatically once DNS resolves.

## Step 5: Start

```bash theme={null}
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**. The first account becomes the **owner**. You'll land on the **Connect** screen — Nous is operated by your agent, so this screen stays up until your agent has onboarded the workspace.

## Step 8: Connect your agent

Nous is set up *by your agent*, not by clicking through the app. Point your agent at this instance.

**Claude Code**

```
/plugin marketplace add NousC/opennous
/plugin install nous@nous-plugins
```

**Codex** — add to `~/.codex/config.toml`:

```toml theme={null}
[mcp_servers.nous]
command = "npx"
args = ["-y", "@opennous/mcp"]
```

**Cursor / any MCP host** — add to `mcp.json`:

```json theme={null}
{ "mcpServers": { "nous": { "command": "npx", "args": ["-y", "@opennous/mcp"] } } }
```

Then **sign in** — this mints a key and saves it (with your API URL) to `~/.nous/config.json`, which the MCP reads automatically:

```bash theme={null}
npx @opennous/cli login --url https://api.yourdomain.com
```

<Note>
  The `--url` is what points your agent at **your own instance** instead of Nous Cloud — it's the one self-host-specific bit. Prefer to paste a key instead of signing in? Create one at **Settings → API Keys** and set it directly in the MCP config:

  ```json theme={null}
  { "mcpServers": { "nous": { "command": "npx", "args": ["-y", "@opennous/mcp"],
    "env": { "NOUS_API_KEY": "sk_live_...", "NOUS_API_URL": "https://api.yourdomain.com" } } } }
  ```
</Note>

## Step 9: Onboard — let your agent set it up

Tell your agent:

> Set me up — onboard my workspace and build my playbook.

Your agent reads `get_workspace_status` and walks you through setup **in order**: profile → connect channels (Gmail / LinkedIn / a meeting note-taker) → enrichment → webhooks → import your CRM contacts (CSV) → build the ICP scoring model. The Connect screen unlocks the moment the workspace is onboarded, and drops you on the live Ops log.

Because it's self-hosted, your agent knows that **LinkedIn (Unipile), email (Resend), and Gmail (Google OAuth) are configured in `nous.env`** (Step 2) — it'll tell you which env vars to set and to restart. **Enrichment** (Prospeo / Apollo) is bring-your-own-key, and your agent connects it directly.

<Note>
  Self-hosters don't have **Lead Lists**, **CRM Sync**, **Triggers**, or **Reports** — those are Nous Cloud only. Everything else (the context graph, the MCP server + all agent tools, the ICP scoring model, enrichment, integrations) is fully open.
</Note>

***

## Updating

The images are built locally from source, so pull the latest code and rebuild:

```bash theme={null}
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.

<Warning>
  Some updates ship new database migrations under [`supabase/migrations/`](https://github.com/NousC/opennous/tree/main/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.
</Warning>

## Logs

```bash theme={null}
docker compose logs -f api       # API server
docker compose logs -f worker    # Background worker
docker compose logs -f frontend  # Nginx / frontend
```

## Stopping

```bash theme={null}
docker compose down              # stop containers, keep data
docker compose down -v           # stop and wipe volumes (destructive)
```
