docsSelf-Hosting

Self-Hosting

If you want to run SmartChats yourself — on your laptop, a VPS, a Raspberry Pi, anywhere with a shell — this is the page.

For most people, Quick Start already covers it. This page is the deep version: env-var management, running on a VPS, bearer-token auth for non-localhost deploys, Docker as an alternative, and the architecture inside.

TL;DR

curl -fsSL https://smartchats.ai/install | bash
smartchats setup

That’s a self-hosted SmartChats running on your machine. Everything below is for cases where you need more control.

What you need

  • macOS or Linux with a shell. Windows via WSL2.
  • An OpenAI API key — required for chat, embeddings, TTS.
  • Optional: Anthropic, Google (Gemini), Serper API keys for additional model providers and web search.
  • ~500 MB free disk for binaries + initial database.

The installer bundles the Bun runtime, the SurrealDB binary, and the SmartChats app — no Node, no Docker, no system-level deps required.

The stack, briefly

smartchats start launches two processes:

                  ┌──────────────────────────────────────┐
                  │  smartchats-server  (port 3000)      │
                  │                                      │
                  │   • serves the SPA at /              │
                  │   • handles /local-api/* (LLM, TTS,  │
                  │     embeddings, data, keys, tools,   │
                  │     usage, insights, health)         │
                  └─────────────────┬────────────────────┘
                                    │  ws://127.0.0.1:8000/rpc

                  ┌──────────────────────────────────────┐
                  │  surreal  (port 8000, loopback only) │
                  │  rocksdb:~/.smartchats/data          │
                  └──────────────────────────────────────┘


                   browser at :3000

One port externally (3000). SurrealDB stays on loopback. No Docker, no Next.js runtime, no Express-Next.js port juggling — the Express server serves the static export of the Next.js app directly.

Where things live

PathPurpose
~/.smartchats/bin/Installed binaries (smartchats CLI, smartchats-server, surreal, bun)
~/.smartchats/data/SurrealDB persistent storage (rocksdb)
~/.smartchats/run/pids.jsonLive process IDs + ports + start times
~/.smartchats/logs/Per-process logs (surreal.log, server.log)
<repo>/.envAPI keys + config (or any path you point SMARTCHATS_ENV_FILE at)
~/.smartchats/config.jsonCLI preferences (last port, resolved source root, etc.)

smartchats home prints the resolved source root if you need to script against it.

Required environment

The stack will boot without any keys, but the agent cannot reply until at least one LLM provider key is configured. smartchats start surfaces a loud warning at boot if it can’t find any.

VariableRequired?Effect if missing
OPENAI_API_KEYStrongly recommendedChat, embeddings, TTS all unavailable
ANTHROPIC_API_KEYOptionalClaude models can’t be selected
GOOGLE_API_KEY (or GEMINI_API_KEY)OptionalGemini models can’t be selected
SERPER_API_KEYOptionalAgent’s web-search tool is a no-op
SMARTCHATS_API_KEYOptionalBearer auth on every /local-api/* request (recommended for non-localhost)

Any of the canonical names above; for each provider there’s also a SMARTCHATS_<PROVIDER>_API_KEY alias for users who want a smartchats-namespaced env.

Environment configuration

Provider keys are read from process.env first, then from a .env file at the install root. The CLI walks the candidates per provider in this order; first match wins:

ProviderCanonicalAlso accepted
OpenAIOPENAI_API_KEYSMARTCHATS_OPENAI_API_KEY
AnthropicANTHROPIC_API_KEYSMARTCHATS_ANTHROPIC_API_KEY
Google (Gemini)GOOGLE_API_KEYSMARTCHATS_GOOGLE_API_KEY, GEMINI_API_KEY
Serper (web search)SERPER_API_KEYSMARTCHATS_SERPER_API_KEY

Where the .env file lives

Install path.env location
curl | sh install~/.smartchats/.env
git clone + npm link<repo>/.env (or ~/.smartchats/.env if SMARTCHATS_HOME not in the repo)
Docker container/root/.smartchats/.env (mount the host file into here, see below)

Three ways to write keys, in order of friendliness:

smartchats env                   # interactive walkthrough (recommended)
smartchats env --list            # show what's configured (masked)
vi ~/.smartchats/.env            # direct edit if you prefer

smartchats setup also writes the file as part of first-run. After editing by any of these methods, run smartchats restart (or docker restart <container>) to pick up the changes.

Sharing one .env between bare-metal and Docker installs

Because the Docker container looks at /root/.smartchats/.env (its install root), and the bare-metal install looks at ~/.smartchats/.env on the host, mounting the host file into the container reuses the exact same config:

mkdir -p ~/.smartchats
cat > ~/.smartchats/.env <<EOF
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
GOOGLE_API_KEY=AIza...
EOF
chmod 600 ~/.smartchats/.env
 
docker run -d --name smartchats \
  -p 3000:3000 \
  -v ~/.smartchats/.env:/root/.smartchats/.env:ro \
  -v ~/.smartchats/data:/data \
  smartchats/smartchats-aio:latest

Edit ~/.smartchats/.env later, then:

docker restart smartchats   # picks up changes in ~1 sec

Adding keys after the container is already running

Three options, easiest first:

  • smartchats env on the host (recommended): interactive prompts, writes to ~/.smartchats/.env. If you mounted that file into the container, docker restart <container> picks it up. If you didn’t, you can also run it inside the container with docker exec -it <container> smartchats env and edit the in-container /root/.smartchats/.env directly (changes lost when the container is removed unless you commit/mount).
  • Edit the host file directly: vi ~/.smartchats/.env, then docker restart <container>. Same end state as the env command, just text-editor instead of prompts.
  • SPA settings → BYO Keys: open localhost:3000, navigate to settings, paste keys into the BYO Keys panel. Stored in SurrealDB; no restart needed. Works without any host file or env config — handy when the container is on a VPS and you don’t want to touch the filesystem.

Optional: bearer-token auth (for non-localhost deploys)

If you’re exposing SmartChats beyond localhost, set a bearer token:

echo 'SMARTCHATS_API_KEY=any-string-you-want' >> ~/.smartchats/.env
smartchats restart   # or docker restart smartchats

Every /local-api/* request now requires Authorization: Bearer <token>. The setup wizard offers to set this for you.

Running on a VPS

The CLI was designed for laptop use, but it works fine on a VPS too — same install, same commands. The extras for a production deploy are nginx in front for TLS and the bearer token.

Install on the VPS

ssh user@vps
curl -fsSL https://smartchats.ai/install | bash
smartchats setup --no-prompt  # ← interactive; or pre-write .env and use --no-prompt

Bind to loopback only

smartchats stop
smartchats start --port 3000   # default; we'll proxy through nginx

The server binds to 0.0.0.0:3000 by default. If you want to be safer, use nginx as the only public-facing process and either firewall :3000 off, or run the smartchats process behind a reverse-only configuration.

Front it with nginx + Let’s Encrypt

server {
  listen 443 ssl http2;
  server_name smartchats.your-domain.com;
 
  ssl_certificate     /etc/letsencrypt/live/.../fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/.../privkey.pem;
 
  location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }
}

Auto-start on boot (systemd)

# /etc/systemd/system/smartchats.service
[Unit]
Description=SmartChats local stack
After=network.target
 
[Service]
Type=forking
User=YOUR_USER
WorkingDirectory=/home/YOUR_USER
ExecStart=/home/YOUR_USER/.smartchats/bin/smartchats start
ExecStop=/home/YOUR_USER/.smartchats/bin/smartchats stop
Restart=on-failure
RestartSec=5
 
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now smartchats
sudo systemctl status smartchats

Periodic backup

# /etc/cron.daily/smartchats-backup
#!/bin/bash
mkdir -p ~/backups
smartchats data export ~/backups/$(date +%Y-%m-%d).json --target=local

Docker (alternative)

If you prefer containers, there’s an image. Same install code path inside — the Dockerfile just runs curl … install | bash against a fresh Debian, then ENTRYPOINTs smartchats start --foreground. Image is ~300 MB.

docker run -d --name smartchats \
  -p 3000:3000 \
  -v ~/.smartchats/.env:/root/.smartchats/.env:ro \
  -v ~/.smartchats/data:/data \
  smartchats/smartchats-aio:latest

The .env mount is the same file the bare-metal CLI reads (~/.smartchats/.env), so one config works for both install modes — see Sharing one .env between bare-metal and Docker installs above.

-e flags also work for one-off runs:

docker run --rm -p 3000:3000 \
  -e OPENAI_API_KEY=$OPENAI_API_KEY \
  -v ~/.smartchats/data:/data \
  smartchats/smartchats-aio:latest

It’s a fallback for environments where you need process isolation or are deploying via container orchestration — for laptop self-host, the native install is faster and uses less disk.

Backup + restore

# Snapshot (writes a single JSON file)
smartchats data export ~/snapshot.json --target=local
 
# Wipe and restore (the import upserts every row by id)
smartchats stop
rm -rf ~/.smartchats/data
smartchats start
smartchats data import ~/snapshot.json --target=local

The fresh stack will boot, the client.ts root-mode connect will define the namespace + database, schema migrations will apply, and the import will populate.

Troubleshooting

⚠️

Port 3000 already in use → another process is bound to it. Either kill it (lsof -i:3000 to find), or smartchats start --port 3030.

⚠️

smartchats start exits with “surreal binary not found” → installer didn’t add ~/.smartchats/bin to PATH. Either rerun smartchats setup, or export PATH="$HOME/.smartchats/bin:$PATH" in your shell rc.

⚠️

App loads but says “no models available” → no provider API keys reachable. Run smartchats doctor to see what it found; add to .env; smartchats restart.

Diagnosing a running stacksmartchats status for a health snapshot, smartchats logs -f to tail per-process output, smartchats logs --proc server -n 200 for just the server’s last 200 lines.

Iterating on the source?smartchats dev (hot reload, Next.js dev server, Express side-by-side) instead of smartchats start. See Contributing.

See also