Skip to content

Deployment Guide

Martian edited this page Nov 9, 2025 · 1 revision

Deployment Guide

This guide covers deploying LinkUp to production environments.

Table of Contents


Prerequisites

Before deploying, ensure you have:

  • ✅ Production server (VPS, cloud instance, or dedicated server)
  • ✅ Domain name with DNS access
  • ✅ SSL certificate (Let's Encrypt recommended)
  • ✅ PostgreSQL database (can be same server or managed service)
  • ✅ Basic Linux/server administration knowledge

Minimum Server Requirements:

  • CPU: 2+ cores
  • RAM: 4GB minimum, 8GB recommended
  • Storage: 20GB minimum
  • OS: Ubuntu 22.04 LTS or similar Linux distribution

Environment Preparation

1. Update System

sudo apt update && sudo apt upgrade -y

2. Install Dependencies

# Python 3.11
sudo apt install python3.11 python3.11-venv python3-pip -y

# Node.js 18+
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install nodejs -y

# PostgreSQL
sudo apt install postgresql postgresql-contrib -y

# Nginx (reverse proxy)
sudo apt install nginx -y

# Certbot (SSL certificates)
sudo apt install certbot python3-certbot-nginx -y

# Git
sudo apt install git -y

Deployment Options

Option 1: Traditional Server Deployment

Step 1: Clone Repository

cd /var/www
sudo git clone https://github.com/martian56/videoo-call.git linkup
sudo chown -R $USER:$USER /var/www/linkup
cd linkup

Step 2: Set Up PostgreSQL Database

sudo -u postgres psql

# In PostgreSQL prompt:
CREATE DATABASE linkup;
CREATE USER linkup_user WITH PASSWORD 'your_secure_password_here';
GRANT ALL PRIVILEGES ON DATABASE linkup TO linkup_user;
\q

Step 3: Configure Backend

cd backend

# Create virtual environment
python3.11 -m venv venv
source venv/bin/activate

# Install dependencies
pip install --upgrade pip
pip install -r requirements.txt

# Create production .env file
cat > .env << EOF
DATABASE_URL=postgresql://linkup_user:your_secure_password_here@localhost:5432/linkup
SECRET_KEY=$(python -c "import secrets; print(secrets.token_urlsafe(32))")
CORS_ORIGINS=https://yourdomain.com
APP_NAME=LinkUp
DEBUG=False
EOF

# Run migrations
alembic upgrade head

Step 4: Build Frontend

cd ../frontend

# Install dependencies
npm install

# Create production .env
cat > .env << EOF
VITE_API_URL=https://yourdomain.com
VITE_WS_URL=wss://yourdomain.com
EOF

# Build for production
npm run build

# Build output is in frontend/dist

Step 5: Configure Nginx

sudo nano /etc/nginx/sites-available/linkup

Paste this configuration:

# Frontend
server {
    listen 80;
    server_name yourdomain.com;

    root /var/www/linkup/frontend/dist;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    # Backend API
    location /api {
        proxy_pass http://localhost:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        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;
    }

    # WebSocket
    location /ws {
        proxy_pass http://localhost:8000;
        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_read_timeout 86400;
    }

    # Health check
    location /health {
        proxy_pass http://localhost:8000;
        proxy_set_header Host $host;
    }
}

Enable the site:

sudo ln -s /etc/nginx/sites-available/linkup /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

Step 6: Set Up SSL with Let's Encrypt

sudo certbot --nginx -d yourdomain.com

Follow the prompts. Certbot will automatically update your Nginx config for HTTPS.

Step 7: Create Systemd Service for Backend

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

Paste this configuration:

[Unit]
Description=LinkUp Video Call Backend
After=network.target postgresql.service

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/linkup/backend
Environment="PATH=/var/www/linkup/backend/venv/bin"
ExecStart=/var/www/linkup/backend/venv/bin/python main.py
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Start the service:

sudo systemctl daemon-reload
sudo systemctl enable linkup
sudo systemctl start linkup
sudo systemctl status linkup

Step 8: Verify Deployment

Visit https://yourdomain.com in your browser. You should see LinkUp running!


Option 2: Docker Deployment

Prerequisites

# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Install Docker Compose
sudo apt install docker-compose -y

Create Docker Compose File

# docker-compose.yml
version: '3.8'

services:
  db:
    image: postgres:15
    environment:
      POSTGRES_DB: linkup
      POSTGRES_USER: linkup_user
      POSTGRES_PASSWORD: your_secure_password_here
    volumes:
      - postgres_data:/var/lib/postgresql/data
    restart: unless-stopped

  backend:
    build: ./backend
    environment:
      DATABASE_URL: postgresql://linkup_user:your_secure_password_here@db:5432/linkup
      SECRET_KEY: ${SECRET_KEY}
      CORS_ORIGINS: https://yourdomain.com
      DEBUG: "False"
    depends_on:
      - db
    ports:
      - "8000:8000"
    restart: unless-stopped
    command: >
      sh -c "alembic upgrade head && python main.py"

  frontend:
    build:
      context: ./frontend
      args:
        VITE_API_URL: https://yourdomain.com
        VITE_WS_URL: wss://yourdomain.com
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      - backend
    restart: unless-stopped

volumes:
  postgres_data:

Backend Dockerfile

# backend/Dockerfile
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["python", "main.py"]

Frontend Dockerfile

# frontend/Dockerfile
FROM node:18-alpine AS builder

WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .

ARG VITE_API_URL
ARG VITE_WS_URL
ENV VITE_API_URL=$VITE_API_URL
ENV VITE_WS_URL=$VITE_WS_URL

RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Deploy with Docker Compose

# Generate secret key
export SECRET_KEY=$(python -c "import secrets; print(secrets.token_urlsafe(32))")

# Start services
docker-compose up -d

# View logs
docker-compose logs -f

# Stop services
docker-compose down

Option 3: Cloud Platform Deployment

Heroku

Backend:

cd backend
heroku create linkup-backend
heroku addons:create heroku-postgresql:mini
heroku config:set SECRET_KEY=$(python -c "import secrets; print(secrets.token_urlsafe(32))")
git push heroku main

Frontend:

cd frontend
heroku create linkup-frontend
heroku buildpacks:add heroku/nodejs
git push heroku main

DigitalOcean App Platform

  1. Connect your GitHub repository
  2. Configure build settings:
    • Backend: Python, port 8000
    • Frontend: Node.js, build command npm run build
  3. Add PostgreSQL database
  4. Set environment variables
  5. Deploy

AWS (EC2 + RDS)

  1. Launch EC2 instance (Ubuntu 22.04)
  2. Create RDS PostgreSQL instance
  3. Configure security groups (ports 80, 443, 22)
  4. Follow Traditional Server Deployment steps
  5. Use RDS connection string in backend .env

Production Configuration

Backend Configuration

config.py:

import os
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    app_name: str = "LinkUp"
    debug: bool = False
    database_url: str
    secret_key: str
    cors_origins: list[str] = ["https://yourdomain.com"]
    max_connections_per_meeting: int = 10
    max_meetings: int = 100
    log_level: str = "INFO"
    
    class Config:
        env_file = ".env"

settings = Settings()

Frontend Configuration

Update config.ts:

export const config = {
  apiUrl: import.meta.env.VITE_API_URL || 'https://api.yourdomain.com',
  wsUrl: import.meta.env.VITE_WS_URL || 'wss://api.yourdomain.com',
  isDevelopment: import.meta.env.DEV,
  maxParticipants: 10,
  version: '2.0.0',
};

Environment Variables Checklist

Backend (.env):

DATABASE_URL=postgresql://user:pass@host:5432/linkup
SECRET_KEY=generate_secure_random_key_here
CORS_ORIGINS=https://yourdomain.com,https://www.yourdomain.com
APP_NAME=LinkUp
DEBUG=False
LOG_LEVEL=INFO
MAX_CONNECTIONS_PER_MEETING=10

Frontend (.env):

VITE_API_URL=https://yourdomain.com
VITE_WS_URL=wss://yourdomain.com

Security Hardening

1. Firewall Configuration

# Allow SSH, HTTP, HTTPS
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Enable firewall
sudo ufw enable
sudo ufw status

2. PostgreSQL Security

sudo nano /etc/postgresql/15/main/pg_hba.conf

Ensure local connections only:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   all             all                                     peer
host    all             all             127.0.0.1/32            md5
host    all             all             ::1/128                 md5

3. Nginx Security Headers

Add to Nginx config:

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 Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' https: wss: data: blob: 'unsafe-inline' 'unsafe-eval'" always;

4. Rate Limiting

Nginx rate limiting:

limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=meeting:10m rate=2r/m;

location /api/meetings {
    limit_req zone=meeting burst=5;
    proxy_pass http://localhost:8000;
}

location /api {
    limit_req zone=api burst=20;
    proxy_pass http://localhost:8000;
}

5. TURN Server (Optional)

For better connectivity behind firewalls:

# Install coturn
sudo apt install coturn -y

# Edit /etc/turnserver.conf
listening-port=3478
fingerprint
lt-cred-mech
user=linkup:your_turn_password
realm=yourdomain.com

Update frontend RTC config:

const RTC_CONFIG = {
  iceServers: [
    { urls: 'stun:stun.l.google.com:19302' },
    {
      urls: 'turn:yourdomain.com:3478',
      username: 'linkup',
      credential: 'your_turn_password'
    }
  ],
};

Monitoring and Maintenance

1. Application Logs

Backend logs:

# Systemd service logs
sudo journalctl -u linkup -f

# Or if using log file
tail -f /var/log/linkup/app.log

Nginx logs:

tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log

2. Database Backups

Automated daily backup:

sudo nano /etc/cron.daily/linkup-backup
#!/bin/bash
BACKUP_DIR="/var/backups/linkup"
DATE=$(date +%Y%m%d_%H%M%S)

mkdir -p $BACKUP_DIR

pg_dump -U linkup_user linkup | gzip > $BACKUP_DIR/linkup_$DATE.sql.gz

# Keep only last 30 days
find $BACKUP_DIR -name "linkup_*.sql.gz" -mtime +30 -delete
sudo chmod +x /etc/cron.daily/linkup-backup

3. SSL Certificate Renewal

Certbot auto-renews, but verify:

sudo certbot renew --dry-run

4. Monitoring Tools

Install monitoring stack:

# Prometheus + Grafana for metrics
# Or use cloud monitoring: DataDog, New Relic, etc.

Health check endpoint:

curl https://yourdomain.com/health

Monitor with cron:

*/5 * * * * curl -f https://yourdomain.com/health || mail -s "LinkUp Down" admin@yourdomain.com

5. Update Strategy

Zero-downtime updates:

# Pull latest code
cd /var/www/linkup
git pull origin main

# Update backend
cd backend
source venv/bin/activate
pip install -r requirements.txt
alembic upgrade head

# Restart service
sudo systemctl restart linkup

# Update frontend
cd ../frontend
npm install
npm run build

Performance Tuning

PostgreSQL Optimization

sudo nano /etc/postgresql/15/main/postgresql.conf
# Adjust based on your server RAM
shared_buffers = 1GB
effective_cache_size = 3GB
maintenance_work_mem = 256MB
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 100
random_page_cost = 1.1
effective_io_concurrency = 200
work_mem = 10MB
min_wal_size = 1GB
max_wal_size = 4GB

Nginx Optimization

# Worker processes
worker_processes auto;

# Gzip compression
gzip on;
gzip_vary on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript;

# Caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

Troubleshooting

Backend won't start

# Check logs
sudo journalctl -u linkup -n 50

# Test manually
cd /var/www/linkup/backend
source venv/bin/activate
python main.py

Database connection issues

# Test connection
psql -U linkup_user -d linkup -h localhost

# Check PostgreSQL status
sudo systemctl status postgresql

SSL certificate issues

# Renew manually
sudo certbot renew --force-renewal

# Check certificate
sudo certbot certificates

Need help? Check Troubleshooting or open an issue.

Clone this wiki locally