Skip to main content

Deployment

Troubleshooting? See Troubleshooting for common issues and solutions. Interface Usage? See Interfaces for accessing Telegram, Web API, and CLI.

Quick Start

See Installation 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

# 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: GET /health)
Data is persisted via volume mounts to ./data/.

With nginx + Let’s Encrypt (HTTPS)

# 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

# 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:
# 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:
# 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

curl -sSL https://raw.githubusercontent.com/albinotonnina/echos/main/install.sh | bash
Installs prerequisites, clones repo, and launches the setup wizard.

systemd service (production)

# /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
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:
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

# 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:
# 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 for details.

Backup

# 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/
    • 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.
  • 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 for details.

Process Management

Development

# 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:
# 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