Deployment & Self-Hosting

Deploy Chvor to a VPS with nginx, SSL, systemd, and a backup strategy for production use.

5 min read

Deployment & Self-Hosting

This guide walks through deploying Chvor on a VPS running Ubuntu. By the end, you will have Chvor running behind nginx with SSL, managed by systemd, and backed up automatically.


Prerequisites

  • A VPS with Ubuntu 22.04+ (1 GB RAM minimum, 2 GB recommended)
  • A domain name pointed at your VPS IP address (e.g., chvor.yourdomain.com)
  • SSH access to the server
  • At least one LLM API key

Step 1: Install System Dependencies

# Update packages
sudo apt update && sudo apt upgrade -y

# Install Node.js 20 via NodeSource
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

# Install pnpm
corepack enable
corepack prepare pnpm@latest --activate

# Install nginx and certbot
sudo apt install -y nginx certbot python3-certbot-nginx

# Verify versions
node --version    # Should be 20.x+
pnpm --version    # Should be 10.x+
nginx -v

Step 2: Clone and Build Chvor

# Create a dedicated user (optional but recommended)
sudo useradd -m -s /bin/bash chvor
sudo su - chvor

# Clone the repository
git clone https://github.com/luka-zivkovic/chvor.git ~/chvor
cd ~/chvor

# Install dependencies and build
pnpm install
pnpm build

Step 3: Configure Environment

Create the environment file:

cp .env.example .env
nano .env

Set your variables:

NODE_ENV=production

# LLM provider (at least one required)
ANTHROPIC_API_KEY=sk-ant-...

# Protect the web UI
CHVOR_TOKEN=a-strong-random-token

# Channel tokens (optional)
TELEGRAM_BOT_TOKEN=...
DISCORD_BOT_TOKEN=...
SLACK_BOT_TOKEN=...
SLACK_APP_TOKEN=...

Generate a secure random token:

openssl rand -hex 32

Step 4: Create a systemd Service

This ensures Chvor starts on boot and restarts automatically if it crashes.

sudo nano /etc/systemd/system/chvor.service

Paste the following:

[Unit]
Description=Chvor AI Platform
After=network.target

[Service]
Type=simple
User=chvor
WorkingDirectory=/home/chvor/chvor
ExecStart=/usr/bin/node /home/chvor/chvor/dist/server/index.js
Restart=always
RestartSec=5
EnvironmentFile=/home/chvor/chvor/.env

# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/home/chvor/.chvor

[Install]
WantedBy=multi-user.target

Enable and start the service:

sudo systemctl daemon-reload
sudo systemctl enable chvor
sudo systemctl start chvor

# Check that it is running
sudo systemctl status chvor

# View logs
sudo journalctl -u chvor -f

You should see Chvor start on port 3001:

Server running at http://localhost:3001

Step 5: Configure nginx Reverse Proxy

Create an nginx site configuration:

sudo nano /etc/nginx/sites-available/chvor
server {
    listen 80;
    server_name chvor.yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:3001;
        proxy_http_version 1.1;

        # WebSocket support (required for Brain Canvas)
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # Forward client info
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Increase timeouts for long LLM responses
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
    }

    # Increase max upload size for file attachments
    client_max_body_size 50M;
}

Enable the site:

sudo ln -s /etc/nginx/sites-available/chvor /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Verify it works by visiting http://chvor.yourdomain.com — you should see the Brain Canvas (or a login prompt if CHVOR_TOKEN is set).


Step 6: SSL with Let’s Encrypt

sudo certbot --nginx -d chvor.yourdomain.com

Certbot will:

  1. Obtain a certificate from Let’s Encrypt.
  2. Automatically modify your nginx config to redirect HTTP to HTTPS.
  3. Set up auto-renewal (runs via a systemd timer).

Verify auto-renewal works:

sudo certbot renew --dry-run

Your Chvor instance is now accessible at https://chvor.yourdomain.com.


Step 7: Firewall

If you are using ufw:

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

Port 3001 does not need to be open externally — nginx proxies all traffic.


Updating Chvor

When a new version is released:

# Stop the service
sudo systemctl stop chvor

# Pull and rebuild
cd /home/chvor/chvor
sudo -u chvor git pull
sudo -u chvor pnpm install
sudo -u chvor pnpm build

# Start the service
sudo systemctl start chvor

# Verify
sudo systemctl status chvor

For zero-downtime updates, you can run two instances on different ports and switch nginx between them, but for most self-hosted setups a brief restart is fine.


Backup Strategy

All Chvor data lives in ~/.chvor/ (or $CHVOR_DATA_DIR). This directory contains:

File/DirectoryContents
chvor.dbSQLite database with conversations, messages, and memory
skills/Your custom skill YAML files
config.jsonMCP tool configuration
uploads/Files uploaded by users
logs/Server logs

Automated daily backup

Create a backup script:

sudo nano /home/chvor/backup-chvor.sh
#!/bin/bash
BACKUP_DIR="/home/chvor/backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
SOURCE="/home/chvor/.chvor"

mkdir -p "$BACKUP_DIR"

# Create a compressed backup
tar -czf "$BACKUP_DIR/chvor-backup-$TIMESTAMP.tar.gz" -C "$(dirname $SOURCE)" "$(basename $SOURCE)"

# Delete backups older than 30 days
find "$BACKUP_DIR" -name "chvor-backup-*.tar.gz" -mtime +30 -delete

echo "Backup complete: chvor-backup-$TIMESTAMP.tar.gz"
chmod +x /home/chvor/backup-chvor.sh

Add a cron job to run it daily at 3 AM:

sudo crontab -u chvor -e

Add:

0 3 * * * /home/chvor/backup-chvor.sh >> /home/chvor/backups/backup.log 2>&1

Restoring from backup

# Stop Chvor
sudo systemctl stop chvor

# Restore
tar -xzf /home/chvor/backups/chvor-backup-20260325_030000.tar.gz -C /home/chvor/

# Start Chvor
sudo systemctl start chvor

Off-site backups

For critical deployments, sync backups to an external location:

# Using rsync to a remote server
rsync -az /home/chvor/backups/ user@backup-server:/backups/chvor/

# Using rclone to S3-compatible storage
rclone sync /home/chvor/backups/ s3:my-bucket/chvor-backups/

Resource Usage

Chvor itself is lightweight. Resource consumption depends primarily on MCP tool servers:

ComponentRAMCPUNotes
Chvor server~100 MBMinimalNode.js process
Each MCP server~50-100 MBVariesnpx servers add overhead on first run
SQLite databaseScales with dataMinimalFine up to millions of messages

A 1 GB VPS can run Chvor with 2-3 MCP tools comfortably. For heavier workloads (many concurrent users, many tools), 2-4 GB is recommended.


Next Steps

  • Docker — alternative deployment using Docker and Docker Compose.
  • Channel Setup — configure Telegram, Discord, and Slack (webhooks require HTTPS).
  • Environment Variables — full reference of all configuration options.