Self-Hosting Guide
Recommended: Coolify Deployment
For the easiest production deployment, we recommend using Coolify with pre-built Docker images from GHCR. See the Coolify Deployment Guide.
This page documents alternative self-hosting options for advanced users who prefer manual server management.
Complete guide for deploying CS2Inspect on your own infrastructure. This guide covers multiple deployment scenarios from simple Docker setups to production-ready cloud deployments.
📋 Table of Contents
- Prerequisites
- Quick Start (Docker)
- Production Deployment
- Database Setup
- Environment Configuration
- Reverse Proxy Setup (Nginx)
- SSL/TLS Configuration
- Monitoring & Maintenance
- Troubleshooting
Prerequisites
Required
Server: VPS or dedicated server with minimum:
- 2 CPU cores
- 4GB RAM (8GB recommended)
- 20GB storage (SSD recommended)
- Ubuntu 22.04 LTS / Debian 12 (recommended)
Domain: Registered domain name pointing to your server
Steam API Key: Get from Steam Developer Portal
Database: MariaDB 11
Optional but Recommended
- Steam Bot Account: Separate Steam account for inspect features (without 2FA)
- Email Service: For notifications and alerts
- Monitoring Tools: Uptime Kuma, Grafana, or similar
Quick Start (Docker)
The fastest way to get CS2Inspect running on your server.
1. Install Docker
# Update system
sudo apt update && sudo apt upgrade -y
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Add your user to docker group
sudo usermod -aG docker $USER
# Install Docker Compose
sudo apt install docker-compose-plugin -y
# Verify installation
docker --version
docker compose version2. Clone Repository
git clone https://github.com/sak0a/cs2inspect-web.git
cd cs2inspect-web3. Configure Environment
# Copy example environment file
cp .env.example .env
# Edit with your settings
nano .envMinimum required configuration:
# Server
PORT=3210
HOST=0.0.0.0
# JWT (generate with: openssl rand -hex 32)
JWT_TOKEN=your_secure_random_key_here
JWT_EXPIRY=7d
# Database
DATABASE_HOST=127.0.0.1
DATABASE_PORT=3306
DATABASE_USER=csinspect
DATABASE_PASSWORD=your_secure_password_here
DATABASE_NAME=csinspect
DATABASE_CONNECTION_LIMIT=10
# Steam API
STEAM_API_KEY=your_steam_api_key_here4. Start Services
# Start all services
docker compose up -d
# Check logs
docker compose logs -f
# Verify health
curl http://localhost:3210/api/health/ready5. Setup Database
# Run migrations
docker compose exec web bun run db:push
# Verify database
docker compose exec web bun run db:studioYour application should now be running at http://localhost:3210!
Production Deployment
VPS Deployment (Ubuntu/Debian)
Complete setup for production environment on a VPS.
Step 1: Initial Server Setup
# Update system
sudo apt update && sudo apt upgrade -y
# Install essential tools
sudo apt install -y git curl wget unzip software-properties-common \
build-essential ufw fail2ban
# Configure firewall
sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw enable
# Enable fail2ban for SSH protection
sudo systemctl enable fail2ban
sudo systemctl start fail2banStep 2: Install Node.js 20
# Add NodeSource repository
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
# Install Node.js
sudo apt install -y nodejs
# Verify installation
node --version # Should show v20.x.x
npm --versionStep 3: Install and Configure MariaDB
# Install MariaDB
sudo apt install -y mariadb-server mariadb-client
# Secure installation
sudo mysql_secure_installation
# Answer: Y, Set root password, Y, Y, Y, Y
# Create database and user
sudo mysql -u root -p << EOF
CREATE DATABASE csinspect CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'csinspect'@'localhost' IDENTIFIED BY 'your_secure_password';
GRANT ALL PRIVILEGES ON csinspect.* TO 'csinspect'@'localhost';
FLUSH PRIVILEGES;
EOF
# Verify database
sudo mysql -u csinspect -p csinspectStep 4: Deploy Application
# Create application user (security best practice)
sudo useradd -m -s /bin/bash cs2inspect
sudo usermod -aG sudo cs2inspect
# Switch to application user
sudo su - cs2inspect
# Clone repository
git clone https://github.com/sak0a/cs2inspect-web.git
cd cs2inspect-web
# Install dependencies
bun install --production
# Configure environment
cp .env.example .env
nano .env # Edit with your settings
# Build application
bun run build
# Test run
bun run previewStep 5: Setup Process Manager (PM2)
# Install PM2 globally
sudo npm install -g pm2
# Create PM2 ecosystem file
cat > ecosystem.config.js << EOF
module.exports = {
apps: [{
name: 'cs2inspect',
script: './.output/server/index.mjs',
instances: 'max',
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 3210,
HOST: '0.0.0.0'
},
error_file: './logs/err.log',
out_file: './logs/out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
merge_logs: true,
autorestart: true,
watch: false,
max_memory_restart: '1G'
}]
}
EOF
# Create logs directory
mkdir -p logs
# Start application with PM2
pm2 start ecosystem.config.js
# Setup PM2 to start on boot
pm2 startup systemd
# Follow the displayed command
# Save PM2 configuration
pm2 save
# Monitor application
pm2 monitStep 6: Configure Nginx Reverse Proxy
# Install Nginx
sudo apt install -y nginx
# Create Nginx configuration
sudo nano /etc/nginx/sites-available/cs2inspectNginx configuration:
# /etc/nginx/sites-available/cs2inspect
upstream cs2inspect_backend {
server 127.0.0.1:3210;
keepalive 64;
}
# HTTP server (redirects to HTTPS)
server {
listen 80;
listen [::]:80;
server_name yourdomain.com www.yourdomain.com;
# ACME challenge for Let's Encrypt
location /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 301 https://$server_name$request_uri;
}
}
# HTTPS server
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
# SSL certificates (we'll add these in next step)
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# SSL configuration (Mozilla Intermediate)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Logging
access_log /var/log/nginx/cs2inspect.access.log;
error_log /var/log/nginx/cs2inspect.error.log;
# Client body size limit
client_max_body_size 10M;
# Proxy to Nuxt application
location / {
proxy_pass http://cs2inspect_backend;
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-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 60s;
proxy_connect_timeout 60s;
}
# Health check endpoint
location /api/health/ {
proxy_pass http://cs2inspect_backend;
access_log off;
}
# Static assets caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
proxy_pass http://cs2inspect_backend;
expires 1y;
add_header Cache-Control "public, immutable";
}
}Enable site and restart Nginx:
# Enable site
sudo ln -s /etc/nginx/sites-available/cs2inspect /etc/nginx/sites-enabled/
# Remove default site
sudo rm /etc/nginx/sites-enabled/default
# Test configuration
sudo nginx -t
# Restart Nginx
sudo systemctl restart nginxStep 7: Setup SSL with Let's Encrypt
# Install Certbot
sudo apt install -y certbot python3-certbot-nginx
# Obtain SSL certificate
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
# Test automatic renewal
sudo certbot renew --dry-run
# Restart Nginx
sudo systemctl restart nginxStep 8: Setup Monitoring
# Install monitoring script
cat > /home/cs2inspect/monitor.sh << 'EOF'
#!/bin/bash
# Check if application is responding
HEALTH_CHECK=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3210/api/health/ready)
if [ "$HEALTH_CHECK" != "200" ]; then
echo "Health check failed! Restarting application..."
pm2 restart cs2inspect
# Send alert (optional - configure with your email)
# echo "CS2Inspect health check failed at $(date)" | mail -s "CS2Inspect Alert" your@email.com
fi
EOF
chmod +x /home/cs2inspect/monitor.sh
# Add to crontab (check every 5 minutes)
(crontab -l 2>/dev/null; echo "*/5 * * * * /home/cs2inspect/monitor.sh") | crontab -Bare Metal Deployment
For deployment without Docker on a dedicated server.
System Requirements
- Ubuntu 22.04 LTS or Debian 12
- Node.js 20.x
- MariaDB 11
- Nginx (reverse proxy)
- 8GB RAM minimum
- 40GB+ storage
Installation Steps
Follow the VPS deployment steps above. The process is identical for bare metal servers.
Additional considerations for bare metal:
- RAID Configuration: Setup RAID 1 or RAID 10 for database storage
- Backup Strategy: Implement automated backups to external storage
- Hardware Monitoring: Install monitoring tools like
lm-sensors
# Install hardware monitoring
sudo apt install -y lm-sensors smartmontools
# Detect sensors
sudo sensors-detect
# Check temperatures
sensors
# Check disk health
sudo smartctl -a /dev/sdaDocker Compose (Production)
Optimized Docker Compose setup for production.
Create Production Compose File
Create docker-compose.coolify.yml:
version: "3.9"
services:
database:
image: mariadb:11
container_name: cs2inspect-db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${DATABASE_ROOT_PASSWORD}
MYSQL_DATABASE: ${DATABASE_NAME}
MYSQL_USER: ${DATABASE_USER}
MYSQL_PASSWORD: ${DATABASE_PASSWORD}
volumes:
- db_data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
networks:
- app-network
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
- --max-connections=200
- --innodb-buffer-pool-size=1G
web:
container_name: cs2inspect-web
build:
context: .
dockerfile: Dockerfile
image: cs2inspect-web:latest
restart: unless-stopped
environment:
- NODE_ENV=production
- PORT=${PORT:-3210}
- HOST=${HOST:-0.0.0.0}
- JWT_TOKEN=${JWT_TOKEN}
- JWT_EXPIRY=${JWT_EXPIRY}
- DATABASE_HOST=database
- DATABASE_PORT=3306
- DATABASE_USER=${DATABASE_USER}
- DATABASE_PASSWORD=${DATABASE_PASSWORD}
- DATABASE_NAME=${DATABASE_NAME}
- DATABASE_CONNECTION_LIMIT=${DATABASE_CONNECTION_LIMIT}
- STEAM_API_KEY=${STEAM_API_KEY}
- STEAM_SERVICE_URL=${STEAM_SERVICE_URL}
- LOG_API_REQUESTS=${LOG_API_REQUESTS}
ports:
- "${PORT:-3210}:${PORT:-3210}"
depends_on:
database:
condition: service_healthy
networks:
- app-network
healthcheck:
test: ["CMD", "sh", "-c", "curl -fsS http://localhost:${PORT:-3210}/api/health/ready"]
interval: 30s
timeout: 5s
retries: 3
start_period: 60s
volumes:
- ./logs:/app/logs
steam-service:
container_name: cs2inspect-steam-service
build:
context: ./services/steam-service
dockerfile: Dockerfile
image: cs2inspect-steam-service:latest
restart: unless-stopped
environment:
- NODE_ENV=production
- PORT=${STEAM_SERVICE_PORT:-3211}
- HOST=${STEAM_SERVICE_HOST:-0.0.0.0}
- STEAM_USERNAME=${STEAM_USERNAME}
- STEAM_PASSWORD=${STEAM_PASSWORD}
- STEAM_API_KEY=${STEAM_API_KEY}
- API_KEYS=${STEAM_SERVICE_API_KEYS}
- CORS_ORIGINS=${STEAM_SERVICE_CORS_ORIGINS}
ports:
- "${STEAM_SERVICE_PORT:-3211}:${STEAM_SERVICE_PORT:-3211}"
networks:
- app-network
healthcheck:
test: ["CMD", "sh", "-c", "curl -fsS http://localhost:${PORT:-3211}/api/health/ready"]
interval: 30s
timeout: 5s
retries: 3
start_period: 60s
nginx:
image: nginx:alpine
container_name: cs2inspect-nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./certbot/conf:/etc/letsencrypt:ro
- ./certbot/www:/var/www/certbot:ro
depends_on:
- web
networks:
- app-network
certbot:
image: certbot/certbot:latest
container_name: cs2inspect-certbot
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
networks:
app-network:
driver: bridge
volumes:
db_data:
driver: localDeploy with Production Compose
# Build images
docker compose -f docker-compose.coolify.yml build
# Start services
docker compose -f docker-compose.coolify.yml up -d
# View logs
docker compose -f docker-compose.coolify.yml logs -f
# Check status
docker compose -f docker-compose.coolify.yml psDatabase Setup
Initial Database Configuration
-- Connect to MariaDB
mysql -u root -p
-- Create database with proper charset
CREATE DATABASE csinspect
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
-- Create user with secure password
CREATE USER 'csinspect'@'localhost'
IDENTIFIED BY 'your_secure_password_here';
-- Grant privileges
GRANT ALL PRIVILEGES ON csinspect.*
TO 'csinspect'@'localhost';
FLUSH PRIVILEGES;
-- Verify
SHOW DATABASES;
SELECT User, Host FROM mysql.user WHERE User = 'csinspect';Database Optimization
-- Add to /etc/mysql/mariadb.conf.d/50-server.cnf
[mysqld]
# Connection settings
max_connections = 200
max_allowed_packet = 64M
connect_timeout = 10
# Buffer sizes
innodb_buffer_pool_size = 2G
innodb_log_file_size = 512M
innodb_log_buffer_size = 16M
# Query cache
query_cache_size = 0
query_cache_type = 0
# Character set
character_set_server = utf8mb4
collation_server = utf8mb4_unicode_ci
# Logging
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow-query.log
long_query_time = 2Run Migrations
# Using bun
bun run db:push
# Or with docker
docker compose exec web bun run db:push
# Open database studio
bun run db:studioEnvironment Configuration
Complete .env Template
########## Server Configuration ##########
PORT=3210
HOST=0.0.0.0
NODE_ENV=production
########## JWT Configuration ##########
# Generate with: openssl rand -hex 32
JWT_TOKEN=your_64_character_secure_random_key_here
JWT_EXPIRY=7d
########## Database Configuration ##########
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATABASE_USER=csinspect
DATABASE_PASSWORD=your_secure_db_password_here
DATABASE_NAME=csinspect
DATABASE_CONNECTION_LIMIT=10
# For Docker deployments
DATABASE_ROOT_PASSWORD=your_root_password_here
########## Steam API Configuration ##########
STEAM_API_KEY=your_steam_api_key_from_steamcommunity
########## Steam Bot Account (Optional) ##########
# Use dedicated bot account without 2FA
STEAM_USERNAME=your_bot_username
STEAM_PASSWORD=your_bot_password
########## Steam Service Configuration ##########
STEAM_SERVICE_URL=http://localhost:3211
STEAM_SERVICE_API_KEY=your_service_api_key_here
STEAM_SERVICE_PORT=3211
STEAM_SERVICE_HOST=0.0.0.0
########## Rate Limiting ##########
STEAM_RATE_LIMIT_DELAY=1500
STEAM_MAX_QUEUE_SIZE=100
STEAM_REQUEST_TIMEOUT=10000
STEAM_QUEUE_TIMEOUT=30000
########## Logging ##########
LOG_API_REQUESTS=true
LOG_LEVEL=info
########## Assets CDN (Optional) ##########
ASSETS_URL=https://assets.yourdomain.com
ASSETS_STICKER_PATH=/stickers
ASSETS_CHARMS_PATH=/charms
ASSETS_WEAPONS_PATH=/weapons
########## Application URLs ##########
PUBLIC_URL=https://yourdomain.com
API_URL=https://api.yourdomain.comGenerate Secure Keys
# Generate JWT secret (32 bytes)
openssl rand -hex 32
# Generate API key (16 bytes)
openssl rand -hex 16
# Generate secure password (24 characters)
openssl rand -base64 24Validate Environment
Create a validation script scripts/validate-env.sh:
#!/bin/bash
# Color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo "🔍 Validating environment configuration..."
echo ""
# Check if .env exists
if [ ! -f .env ]; then
echo -e "${RED}❌ .env file not found!${NC}"
echo "Copy .env.example to .env and configure it."
exit 1
fi
# Load .env
source .env
# Required variables
REQUIRED_VARS=(
"PORT"
"HOST"
"JWT_TOKEN"
"DATABASE_HOST"
"DATABASE_USER"
"DATABASE_PASSWORD"
"DATABASE_NAME"
"STEAM_API_KEY"
)
errors=0
for var in "${REQUIRED_VARS[@]}"; do
if [ -z "${!var}" ]; then
echo -e "${RED}❌ $var is not set${NC}"
errors=$((errors + 1))
else
echo -e "${GREEN}✅ $var is set${NC}"
fi
done
# Check JWT token length
if [ ${#JWT_TOKEN} -lt 32 ]; then
echo -e "${YELLOW}⚠️ JWT_TOKEN should be at least 32 characters${NC}"
errors=$((errors + 1))
fi
# Check database connection
echo ""
echo "🔍 Testing database connection..."
if command -v mysql &> /dev/null; then
if mysql -h"$DATABASE_HOST" -u"$DATABASE_USER" -p"$DATABASE_PASSWORD" -e "USE $DATABASE_NAME" 2>/dev/null; then
echo -e "${GREEN}✅ Database connection successful${NC}"
else
echo -e "${RED}❌ Database connection failed${NC}"
errors=$((errors + 1))
fi
else
echo -e "${YELLOW}⚠️ MySQL client not installed, skipping database test${NC}"
fi
echo ""
if [ $errors -eq 0 ]; then
echo -e "${GREEN}✅ All checks passed!${NC}"
exit 0
else
echo -e "${RED}❌ Found $errors error(s)${NC}"
exit 1
fiMake it executable:
chmod +x scripts/validate-env.sh
./scripts/validate-env.shReverse Proxy Setup (Nginx)
Install Nginx
sudo apt update
sudo apt install -y nginxConfigure Nginx for CS2Inspect
See the complete Nginx configuration in the VPS Deployment section above.
Nginx Performance Tuning
Edit /etc/nginx/nginx.conf:
user www-data;
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
http {
# Basic Settings
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
# Gzip Settings
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml+rss
application/rss+xml font/truetype font/opentype
application/vnd.ms-fontobject image/svg+xml;
# Logging
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
# Include configs
include /etc/nginx/mime.types;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}SSL/TLS Configuration
Obtain SSL Certificate with Let's Encrypt
# Install Certbot
sudo apt install -y certbot python3-certbot-nginx
# Stop Nginx temporarily
sudo systemctl stop nginx
# Obtain certificate
sudo certbot certonly --standalone \
-d yourdomain.com \
-d www.yourdomain.com \
--email your@email.com \
--agree-tos \
--no-eff-email
# Start Nginx
sudo systemctl start nginx
# Setup automatic renewal
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer
# Test renewal
sudo certbot renew --dry-runSSL Best Practices
Add to your Nginx SSL configuration:
# Mozilla Modern SSL Configuration
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# DH Parameters
ssl_dhparam /etc/nginx/dhparam.pem;
# Session settings
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;Generate DH parameters:
sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048Monitoring & Maintenance
Setup Uptime Monitoring
Option 1: Uptime Kuma (Self-hosted)
# Install Uptime Kuma with Docker
docker run -d --restart=always \
-p 3001:3001 \
-v uptime-kuma:/app/data \
--name uptime-kuma \
louislam/uptime-kuma:1
# Access at http://your-server:3001Option 2: External Services
- UptimeRobot - Free tier available
- Pingdom
- StatusCake
Configure monitor for: https://yourdomain.com/api/health/ready
Application Logging
# PM2 logs
pm2 logs cs2inspect
# Nginx logs
sudo tail -f /var/log/nginx/cs2inspect.access.log
sudo tail -f /var/log/nginx/cs2inspect.error.log
# Application logs
tail -f ~/cs2inspect-web/logs/out.log
tail -f ~/cs2inspect-web/logs/err.log
# Docker logs
docker compose logs -f --tail=100 webDatabase Backups
Create backup script scripts/backup-db.sh:
#!/bin/bash
# Configuration
BACKUP_DIR="/home/cs2inspect/backups"
DB_NAME="csinspect"
DB_USER="csinspect"
DB_PASS="your_password"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=30
# Create backup directory
mkdir -p $BACKUP_DIR
# Backup database
mysqldump -u$DB_USER -p$DB_PASS $DB_NAME | gzip > $BACKUP_DIR/csinspect_$DATE.sql.gz
# Delete old backups
find $BACKUP_DIR -name "csinspect_*.sql.gz" -mtime +$RETENTION_DAYS -delete
echo "Backup completed: csinspect_$DATE.sql.gz"Schedule with cron:
# Edit crontab
crontab -e
# Add daily backup at 2 AM
0 2 * * * /home/cs2inspect/scripts/backup-db.sh >> /home/cs2inspect/logs/backup.log 2>&1System Updates
# Update system packages
sudo apt update && sudo apt upgrade -y
# Update Node.js dependencies
cd ~/cs2inspect-web
bun install
# Rebuild application
bun run build
# Restart with PM2
pm2 restart cs2inspect
# Or with Docker
docker compose pull
docker compose up -d --buildTroubleshooting
Application Won't Start
# Check PM2 status
pm2 list
pm2 logs cs2inspect --lines 100
# Check if port is in use
sudo lsof -i :3210
# Check environment variables
pm2 env 0
# Restart application
pm2 restart cs2inspect
# Or delete and restart
pm2 delete cs2inspect
pm2 start ecosystem.config.jsDatabase Connection Issues
# Test database connection
mysql -h localhost -u csinspect -p csinspect
# Check database status
sudo systemctl status mariadb
# Check database logs
sudo tail -f /var/log/mysql/error.log
# Restart database
sudo systemctl restart mariadbHigh Memory Usage
# Check memory usage
free -h
htop
# Check PM2 memory
pm2 monit
# Restart application to free memory
pm2 restart cs2inspectSSL Certificate Issues
# Check certificate expiry
sudo certbot certificates
# Renew certificate manually
sudo certbot renew --force-renewal
# Check Nginx configuration
sudo nginx -t
# Reload Nginx
sudo systemctl reload nginxPerformance Issues
# Check system resources
htop
iotop
netstat -tulpn
# Check application metrics
pm2 monit
# Analyze slow queries
sudo tail -f /var/log/mysql/slow-query.log
# Check Nginx access patterns
sudo tail -f /var/log/nginx/cs2inspect.access.log | grep -E "POST|GET"Health Check Failures
# Manual health check
curl http://localhost:3210/api/health/ready
curl http://localhost:3210/api/health/details
# Check application logs
pm2 logs cs2inspect --lines 50
# Check database health
mysql -u csinspect -p -e "SELECT 1"
# Restart services
pm2 restart cs2inspect
sudo systemctl restart mariadbSecurity Checklist
Before going to production, verify:
- [ ] UFW firewall enabled with only necessary ports open
- [ ] Fail2ban configured for SSH protection
- [ ] SSL/TLS certificates installed and auto-renewal working
- [ ] Strong passwords for database and application
- [ ] JWT secret is random and secure (32+ characters)
- [ ] Database user has minimal required privileges
- [ ] Nginx security headers configured
- [ ] Application running as non-root user
- [ ] Regular backups configured and tested
- [ ] Monitoring and alerting configured
- [ ] Server SSH key-only authentication enabled
- [ ] Application logs properly configured
- [ ] Rate limiting configured
- [ ] CORS properly configured
Performance Optimization
Enable HTTP/2 in Nginx
Already configured in the Nginx template above with http2 directive.
Enable Brotli Compression
# Install brotli module
sudo apt install -y libnginx-mod-http-brotli
# Add to nginx.conf http block
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;Database Query Optimization
-- Add indexes for frequently queried tables
ALTER TABLE loadouts ADD INDEX idx_user_id (user_id);
ALTER TABLE user_items ADD INDEX idx_user_loadout (user_id, loadout_id);
-- Analyze tables
ANALYZE TABLE loadouts, user_items, health_check_history;CDN Configuration (Optional)
For serving static assets:
- Setup CloudFlare (free tier)
- Point your domain to CloudFlare nameservers
- Enable caching for static assets
- Configure Page Rules for
/img/*,/assets/*
Next Steps
After deployment:
- Monitor: Setup monitoring dashboards
- Backup: Test backup restoration process
- Scale: Add load balancer if traffic increases
- Optimize: Tune database and application based on metrics
- Update: Keep system and dependencies updated
Related Documentation
- Development Setup - Local development environment
- Deployment Guide - Detailed deployment scenarios
- Health Checks - Health monitoring system
- API Reference - API documentation
Support
- Issues: GitHub Issues
- Documentation: Full Docs
- Community: Join discussions on GitHub
Last Updated: January 2026
Tested On: Ubuntu 22.04 LTS, Debian 12, Node.js 20.x