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

# Deployment

> Deploy EchOS via Docker, systemd on a VPS, or locally.

# Deployment

<Tip>
  **Troubleshooting?** See [Troubleshooting](/troubleshooting) for common issues and solutions.
  **Interface Usage?** See [Interfaces](/interfaces) for accessing Telegram, Web API, and CLI.
</Tip>

## Quick Start

See [Installation](/distribution) for all install methods (Homebrew, one-liner, Docker, manual).

The interactive wizard (`pnpm wizard`) handles all configuration — API keys, interfaces, storage paths, and scheduler. It writes a `chmod 0600` `.env` file and creates the required data directories.

## Prerequisites

* Node.js 20+, pnpm 9+
* Docker and Docker Compose (for Docker deployments)
* `.env` file — generated by `pnpm wizard` or manually from `.env.example`

## Docker Compose

```bash theme={null}
# Build and start
cd docker
docker compose up -d --build

# View logs
docker compose logs -f echos

# Stop
docker compose down
```

Services:

* **redis**: Redis 7 for BullMQ job queue (required)
* **echos**: The EchOS application (healthcheck: liveness heartbeat file, independent of `ENABLE_WEB` — see [Troubleshooting](/troubleshooting#docker-compose-ps-shows-echos-as-unhealthy-even-though-its-working))

Data is persisted via volume mounts to `./data/`.

### With nginx + Let's Encrypt (HTTPS)

```bash theme={null}
# 1. Generate nginx config from template
sed "s/DOMAIN_NAME/example.com/g" docker/nginx.conf.template > docker/nginx.conf

# 2. Start all services including nginx
cd docker && docker compose --profile nginx up -d

# 3. Obtain SSL certificate
docker compose --profile nginx run --rm certbot certonly \
  --webroot -w /var/www/certbot -d example.com

# 4. Uncomment the HTTPS server block in docker/nginx.conf
# (see the commented block at the bottom of the file)

# 5. Reload nginx
docker compose --profile nginx exec nginx nginx -s reload
```

Certbot auto-renews every 12 hours.

## Manual Deployment

```bash theme={null}
# Install dependencies
pnpm install

# Build all packages
pnpm build

# Start (requires Redis running)
pnpm start
```

### Troubleshooting

#### Module Not Found Errors

If you see `Cannot find package '@echos/shared'` or `'@echos/plugin-youtube'` or similar:

```bash theme={null}
# Rebuild all workspace packages
pnpm build

# Or if that fails, clean and rebuild
pnpm clean
pnpm install
pnpm build
```

#### LanceDB Native Module Errors

If you see `Cannot find module '@lancedb/lancedb-darwin-x64'` or similar:

1. **Intel Macs**: The project uses LanceDB 0.22.3 (configured in `packages/core/package.json`)
2. **ARM Macs/Linux**: LanceDB should install the correct native binding automatically
3. **Force reinstall**: `pnpm install --force`

#### Telegram Bot Conflicts

Error: `Conflict: terminated by other getUpdates request`

This means another instance of your bot is already running. Only one instance can poll Telegram.

**Solution:**

```bash theme={null}
# Stop all echos processes
pkill -f "tsx.*index.ts"

# Or find the specific process
ps aux | grep "tsx"
kill <PID>

# Verify nothing is running (should only show "grep echos")
ps aux | grep echos

# Then restart
pnpm start
```

**For production**: Use webhooks instead of polling to avoid conflicts.

## VPS Deployment (Ubuntu/Debian)

### One-liner install

```bash theme={null}
curl -sSL https://raw.githubusercontent.com/albinotonnina/echos/main/install.sh | bash
```

Installs prerequisites, clones repo, and launches the setup wizard.

### systemd service (production)

```ini theme={null}
# /etc/systemd/system/echos.service
[Unit]
Description=EchOS knowledge management
After=network.target

[Service]
Type=simple
User=echos
WorkingDirectory=/home/echos/echos
ExecStart=/usr/local/bin/pnpm start
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
```

```bash theme={null}
sudo systemctl daemon-reload
sudo systemctl enable --now echos
sudo journalctl -u echos -f   # follow logs
```

## SSH / VPS CLI Access

The daemon runs via systemd or Docker as normal. When you SSH in, run queries directly against the live data without interrupting the daemon:

```bash theme={null}
ssh user@your-server
cd ~/echos

# One-shot query
pnpm echos "what are my reminders for this week?"

# Interactive session
pnpm echos
```

SQLite WAL mode allows concurrent reads (and occasional writes) alongside the running daemon. This is safe for single-user personal use.

***

## Oracle Cloud Deployment

```bash theme={null}
# Deploy to remote server
./scripts/deploy.sh user@your-server-ip
```

The deploy script:

1. Syncs project files via rsync
2. Installs dependencies on remote
3. Builds the project
4. Restarts via docker-compose

### Important: Dev vs Production

**Before starting locally**, ensure your production deployment is stopped:

```bash theme={null}
# SSH to production
ssh user@your-server

# Stop the bot
docker compose down
# Or
pkill -f "echos"

# Exit SSH
exit

# Now safe to start locally
pnpm start
```

Only one instance can poll Telegram at a time. See [Troubleshooting](/troubleshooting#telegram-bot-conflicts) for details.

## Backup

```bash theme={null}
# Create backup
./scripts/backup.sh ./backups

# Restore (copy files back)
tar -xzf backups/echos_backup_TIMESTAMP.tar.gz
```

## Environment Variables

See `.env.example` for the full list. Required:

* `TELEGRAM_BOT_TOKEN` - Get from @BotFather on Telegram
* `ALLOWED_USER_IDS` - Comma-separated Telegram user IDs (get from @userinfobot)
* **At least one LLM key:**
  * `ANTHROPIC_API_KEY` - Anthropic pay-as-you-go key from [https://console.anthropic.com/](https://console.anthropic.com/)
  * `LLM_API_KEY` - API key for any other provider (Groq, Mistral, xAI, etc.)
* `DEFAULT_MODEL` - Model spec: bare ID (`claude-haiku-4-5-20251001`), `provider/model` (`groq/llama-3.3-70b-versatile`), or any ID when using `LLM_BASE_URL`

Optional:

* `LLM_BASE_URL` - Custom OpenAI-compatible endpoint (e.g. DeepInfra); requires `LLM_API_KEY`
* `OPENAI_API_KEY` - Required for embeddings and Whisper transcription
* `WHISPER_LANGUAGE` - ISO-639-1 code (e.g. `en`, `fr`, `de`) to pin Whisper transcription language. If unset, Whisper auto-detects. See [Troubleshooting](/troubleshooting#whisper-transcribes-audio-in-the-wrong-language).
* `CACHE_RETENTION` - Prompt cache TTL for Anthropic models: `long` (1h, default), `short` (5min), `none` (off). Always `none` for custom endpoints.
* `DISABLE_UPDATE_CHECK` - Set to `true` to disable the daily update check. Useful for air-gapped environments with no internet access.
* `TELEGRAM_REACTIONS` - Set to `false` to disable emoji reactions (👀, 🤗) on incoming Telegram messages. Default: `true`.

Redis (required):

* `REDIS_URL` - Redis connection URL (default: `redis://localhost:6379`)

See [Scheduler](/scheduler) for details.

## Process Management

### Development

```bash theme={null}
# Start daemon (foreground)
pnpm start

# Stop (Ctrl+C or from another terminal)
pkill -f "tsx.*index.ts"

# CLI — no daemon needed, works alongside or independently
pnpm echos "query"           # one-shot
pnpm echos                   # interactive REPL
echo "msg" | pnpm echos      # pipe mode
```

### Production

For production deployments, use a process manager:

```bash theme={null}
# With PM2
pm2 start "pnpm start" --name echos
pm2 stop echos
pm2 restart echos
pm2 logs echos

# Or use Docker Compose (recommended)
docker compose up -d
docker compose logs -f echos
docker compose stop
```
