-
Notifications
You must be signed in to change notification settings - Fork 1
Deployment Guide
This guide covers deploying LinkUp to production environments.
- Prerequisites
- Environment Preparation
- Deployment Options
- Production Configuration
- Security Hardening
- Monitoring and Maintenance
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
sudo apt update && sudo apt upgrade -y# 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 -ycd /var/www
sudo git clone https://github.com/martian56/videoo-call.git linkup
sudo chown -R $USER:$USER /var/www/linkup
cd linkupsudo -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;
\qcd 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 headcd ../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/distsudo nano /etc/nginx/sites-available/linkupPaste 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 nginxsudo certbot --nginx -d yourdomain.comFollow the prompts. Certbot will automatically update your Nginx config for HTTPS.
sudo nano /etc/systemd/system/linkup.servicePaste 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.targetStart the service:
sudo systemctl daemon-reload
sudo systemctl enable linkup
sudo systemctl start linkup
sudo systemctl status linkupVisit https://yourdomain.com in your browser. You should see LinkUp running!
# 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# 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
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
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;"]# 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 downBackend:
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 mainFrontend:
cd frontend
heroku create linkup-frontend
heroku buildpacks:add heroku/nodejs
git push heroku main- Connect your GitHub repository
- Configure build settings:
- Backend: Python, port 8000
-
Frontend: Node.js, build command
npm run build
- Add PostgreSQL database
- Set environment variables
- Deploy
- Launch EC2 instance (Ubuntu 22.04)
- Create RDS PostgreSQL instance
- Configure security groups (ports 80, 443, 22)
- Follow Traditional Server Deployment steps
- Use RDS connection string in backend
.env
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()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',
};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=10Frontend (.env):
VITE_API_URL=https://yourdomain.com
VITE_WS_URL=wss://yourdomain.com# 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 statussudo nano /etc/postgresql/15/main/pg_hba.confEnsure 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
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;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;
}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.comUpdate 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'
}
],
};Backend logs:
# Systemd service logs
sudo journalctl -u linkup -f
# Or if using log file
tail -f /var/log/linkup/app.logNginx logs:
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.logAutomated 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 -deletesudo chmod +x /etc/cron.daily/linkup-backupCertbot auto-renews, but verify:
sudo certbot renew --dry-runInstall monitoring stack:
# Prometheus + Grafana for metrics
# Or use cloud monitoring: DataDog, New Relic, etc.Health check endpoint:
curl https://yourdomain.com/healthMonitor with cron:
*/5 * * * * curl -f https://yourdomain.com/health || mail -s "LinkUp Down" admin@yourdomain.comZero-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 buildsudo 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# 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";
}# Check logs
sudo journalctl -u linkup -n 50
# Test manually
cd /var/www/linkup/backend
source venv/bin/activate
python main.py# Test connection
psql -U linkup_user -d linkup -h localhost
# Check PostgreSQL status
sudo systemctl status postgresql# Renew manually
sudo certbot renew --force-renewal
# Check certificate
sudo certbot certificatesNeed help? Check Troubleshooting or open an issue.