Skip to main content

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

  1. Open https://your-domain.com in your browser
  2. Create an account
  3. 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!