Production Setup Guide
This guide will help you set up Chirp for production use with proper security, performance, and reliability configurations. For a simpler deployment, consider using Docker instead.
Prerequisites
Before starting this guide, ensure you have:
- A server with enough free storage
- Domain name
- SSL certificate (Let's Encrypt recommended)
- Basic knowledge of Linux server administration
Architecture Overview
A typical production Chirp setup includes:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Nginx/Proxy │────│ Chirp App │────│ PostgreSQL │
│ (Port 80/443) │ │ (Port 3001) │ │ (Port 5432) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │
┌─────────────────┐ ┌─────────────────┐
│ Redis │ │ Coturn │
│ (Port 6379) │ │ (Port 3478) │
└─────────────────┘ └─────────────────┘
Step 1: Server Preparation
System Update and Security
# Update system packages
sudo apt update && sudo apt upgrade -y
# Install essential packages
sudo apt install -y curl wget git ufw fail2ban \
build-essential python3 software-properties-common \
certbot python3-certbot-nginx
# Configure firewall
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 'Nginx Full'
sudo ufw allow 3478/udp # TURN signaling
sudo ufw allow 3478/tcp # TURN signaling (TCP)
sudo ufw allow 49152:49252/udp # TURN media relay
sudo ufw enable
Create Dedicated User
# Create chirp user
sudo useradd -m -s /bin/bash chirp
sudo usermod -aG sudo chirp
# Switch to chirp user
sudo su - chirp
Step 2: Install Dependencies
Node.js 20.x LTS
# 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 be v20.x
npm --version
PostgreSQL
# Install PostgreSQL
sudo apt install -y postgresql postgresql-contrib
# Start and enable PostgreSQL
sudo systemctl start postgresql
sudo systemctl enable postgresql
# Create database and user
sudo -u postgres psql << EOF
CREATE DATABASE chirp_prod;
CREATE USER chirp_user WITH PASSWORD 'your_strong_password_here';
GRANT ALL PRIVILEGES ON DATABASE chirp_prod TO chirp_user;
REVOKE ALL ON SCHEMA public FROM PUBLIC;
GRANT ALL ON SCHEMA public TO chirp_user;
\q
EOF
Redis
# Install Redis
sudo apt install -y redis-server
# Configure Redis security
sudo nano /etc/redis/redis.conf
Update these settings in redis.conf:
# Bind to localhost only
bind 127.0.0.1 ::1
# Optionally set a password
requirepass your_redis_password
# Restart Redis
sudo systemctl restart redis
sudo systemctl enable redis
Coturn (TURN Server for Voice)
# Install Coturn
sudo apt install -y coturn
# Enable Coturn service
echo 'TURNSERVER_ENABLED=1' | sudo tee /etc/default/coturn
# Configure Coturn
sudo nano /etc/turnserver.conf
Add to turnserver.conf:
listening-port=3478
fingerprint
lt-cred-mech
user=chirp:your_turn_password
realm=chirp
external-ip=YOUR_PUBLIC_IP
min-port=49152
max-port=49252
no-tls
no-dtls
log-file=/var/log/turnserver.log
verbose
sudo systemctl restart coturn
sudo systemctl enable coturn
Step 3: Install Chirp
Clone and Setup
# Clone repository
git clone https://git.eidenz.moe/Eidenz/chirp.git /home/chirp/app
cd /home/chirp/app
# Install dependencies
npm install --omit=dev
# Set ownership
sudo chown -R chirp:chirp /home/chirp/app
Configure Environment
# Create production environment file
cp server/.env.example server/.env
nano server/.env
Configure your production environment:
# Core
NODE_ENV=production
PORT=3001
CORS_ORIGIN=https://your-domain.com
BASE_URL=https://your-domain.com
MAX_SERVERS_PER_USER=15
MAX_BOTS_PER_USER=3
# Security (generate new ones!)
JWT_SECRET=your_super_secure_jwt_secret_minimum_64_characters
# Database
DB_HOST=localhost
DB_PORT=5432
DB_USER=chirp_user
DB_PASSWORD=your_strong_password_here
DB_NAME=chirp_prod
DB_SSL=false
# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=your_redis_password
REDIS_DB=0
REDIS_URL=redis://:your_redis_password@localhost:6379
# Email (required for registration)
EMAIL_HOST=smtp.gmail.com
EMAIL_PORT=587
EMAIL_USER=your-email@gmail.com
EMAIL_PASS=your_app_specific_password
EMAIL_FROM=your-email@gmail.com
EMAIL_FROM_NAME=Chirp
# TURN Server (for voice channels)
TURN_SERVER_URLS=turn:your-domain.com:3478,turn:your-domain.com:3478?transport=tcp
TURN_USERNAME=chirp
TURN_CREDENTIAL=your_turn_password
# VAPID Keys (auto-generated on first run, or set manually)
VAPID_SUBJECT=mailto:admin@your-domain.com
# Optional
TENOR_API_KEY=your_tenor_api_key
Generate Secure Keys
# Generate JWT secret
node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"
Step 4: Build and Migrate
Build Frontend Assets
cd /home/chirp/app
npm run build:web
Run Database Migrations
npm run migrate:prod
Step 5: Nginx Configuration
Install Nginx
sudo apt install -y nginx
sudo systemctl start nginx
sudo systemctl enable nginx
Configure Nginx
Create /etc/nginx/sites-available/chirp:
server {
listen 80;
server_name your-domain.com www.your-domain.com;
# Redirect to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name your-domain.com www.your-domain.com;
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
# SSL Settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-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 DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# File Upload Size
client_max_body_size 250M;
# Proxy to Chirp App
location / {
proxy_pass http://127.0.0.1:3001;
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;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# WebSocket support for Socket.IO
location /socket.io/ {
proxy_pass http://127.0.0.1:3001;
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;
}
}
Enable Site
# Enable site
sudo ln -s /etc/nginx/sites-available/chirp /etc/nginx/sites-enabled/
# Remove default site
sudo rm /etc/nginx/sites-enabled/default
# Test configuration
sudo nginx -t
# Reload Nginx
sudo systemctl reload nginx
Step 6: SSL Certificate with Let's Encrypt
# Obtain SSL certificate
sudo certbot --nginx -d your-domain.com -d www.your-domain.com
Step 7: System Service
Create /etc/systemd/system/chirp.service:
[Unit]
Description=Chirp Social Platform
After=network.target postgresql.service redis.service nginx.service
[Service]
Type=simple
User=chirp
Group=chirp
WorkingDirectory=/home/chirp/app
Environment=NODE_ENV=production
ExecStart=/usr/bin/node server/index.js
Restart=always
RestartSec=10
SyslogIdentifier=chirp
# Security
NoNewPrivileges=true
PrivateTmp=true
# Resource limits
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
# Reload systemd and enable service
sudo systemctl daemon-reload
sudo systemctl enable chirp
sudo systemctl start chirp
# Check status
sudo systemctl status chirp
Step 8: Monitoring and Logging
Log Rotation
Create /etc/logrotate.d/chirp:
/home/chirp/app/server/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 644 chirp chirp
}
Check Logs
# View Chirp service logs
sudo journalctl -u chirp -f
# View Nginx logs
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log
Step 9: Backup Setup
Database Backup Script
Create /home/chirp/backup.sh:
#!/bin/bash
BACKUP_DIR="/home/chirp/backups"
DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME="chirp_prod"
DB_USER="chirp_user"
# Create backup directory
mkdir -p $BACKUP_DIR
# Database backup
pg_dump -h localhost -U $DB_USER -d $DB_NAME | gzip > $BACKUP_DIR/db_backup_$DATE.sql.gz
# File backup
tar -czf $BACKUP_DIR/files_backup_$DATE.tar.gz /home/chirp/app/server/uploads
# Clean old backups (keep last 30 days)
find $BACKUP_DIR -name "*.gz" -mtime +30 -delete
echo "Backup completed: $DATE"
chmod +x /home/chirp/backup.sh
# Add daily backup at 3 AM
(crontab -l 2>/dev/null; echo "0 3 * * * /home/chirp/backup.sh") | crontab -
Final Verification
Health Checks
# Check service status
sudo systemctl status chirp
sudo systemctl status nginx
sudo systemctl status postgresql
sudo systemctl status redis
sudo systemctl status coturn
# Check logs
sudo journalctl -u chirp -f
Test Installation
- Open https://your-domain.com in your browser
- Create an account
- Test basic functionality:
- Create a server
- Create a channel
- Send a message
- Upload a file
- Join a voice channel
Production Checklist
- System requirements met
- Firewall configured (UFW)
- SSL certificate installed
- Nginx reverse proxy configured
- PostgreSQL secured with strong password
- Redis installed and configured
- Coturn TURN server installed for voice
- Environment variables configured
- Frontend assets built (
npm run build:web) - Database migrations applied
- System service configured
- Log rotation set up
- Backup script created and scheduled
- Email configuration verified
- VAPID keys generated (auto on first run)
Next Steps
Your Chirp instance is now running in production!