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:
- Obtain a certificate from Let’s Encrypt.
- Automatically modify your nginx config to redirect HTTP to HTTPS.
- 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/Directory | Contents |
|---|---|
chvor.db | SQLite database with conversations, messages, and memory |
skills/ | Your custom skill YAML files |
config.json | MCP 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:
| Component | RAM | CPU | Notes |
|---|---|---|---|
| Chvor server | ~100 MB | Minimal | Node.js process |
| Each MCP server | ~50-100 MB | Varies | npx servers add overhead on first run |
| SQLite database | Scales with data | Minimal | Fine 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.