Skip to main content

Self-Hosting Guide

Deploy CuliUptime on your own infrastructure for complete control over your monitoring data and customization options.

🎯 Deployment Options

Choose between development and production deployment based on your needs:

AspectDevelopmentProduction
PurposeTesting, development, local useLive production systems
SSLOptional/manualAutomated Let's Encrypt
Docker Configdocker-compose.dev.ymldocker-compose.prd.yml
Resource LimitsBasicOptimized for 2vCPU/4GB
SecurityBasicHardened (firewall, headers)
MonitoringBasic health checksComprehensive monitoring

📚 Quick Navigation


🏠 Why Self-Host?

  • 🔒 Data Privacy - Keep all monitoring data on your infrastructure
  • 🎯 Custom Locations - Deploy monitoring agents anywhere
  • ⚙️ Full Customization - Modify source code to fit your needs
  • 🔗 Integration - Integrate with existing infrastructure and tools
  • 💰 Cost Control - Only pay for your infrastructure costs
  • 🛡️ Compliance - Meet specific regulatory requirements

📋 Prerequisites

System Requirements

Minimum (Development/Small Teams)

  • 2 GB RAM
  • 2 CPU cores
  • 10 GB disk space
  • Docker & Docker Compose
  • Open ports: 3000 (frontend), 8000 (API)

Recommended (Production)

  • 4 GB RAM
  • 4 CPU cores
  • 50 GB disk space (for monitoring data)
  • Reverse proxy (nginx/traefik)
  • SSL certificate
  • Backup solution

Software Requirements

  • Docker 20.10+
  • Docker Compose 2.0+
  • Git for cloning repository
  • OpenSSL for generating secrets

🚀 Development Setup

Perfect for local development, testing, and small-scale deployments.

1. Clone Repository

# Clone the latest stable release
git clone https://github.com/chiplonton/culiuptime.git
cd culiuptime

# Optional: Switch to latest release tag
git checkout $(git describe --tags --abbrev=0)

2. Environment Configuration

# Copy environment template
cp .env.example .env

# Generate secure secrets (REQUIRED!)
echo "SECRET_KEY=$(openssl rand -hex 32)" >> .env
echo "AGENT_SECRET_KEY=$(openssl rand -hex 32)" >> .env

3. Configure Environment Variables

Edit .env with your settings:

# Essential Configuration
ENVIRONMENT=production
DEBUG=false
SECRET_KEY=your_generated_jwt_secret_key_here
AGENT_SECRET_KEY=your_generated_agent_secret_key_here

# Database (PostgreSQL)
POSTGRES_SERVER=postgres
POSTGRES_USER=culiuptime
POSTGRES_PASSWORD=your_secure_database_password_here
POSTGRES_DB=culiuptime_prod
POSTGRES_PORT=5432

# Redis Configuration
REDIS_URL=redis://redis:6379/0
CELERY_BROKER_URL=redis://redis:6379/0
CELERY_RESULT_BACKEND=redis://redis:6379/0

# OAuth2 Authentication (Optional but recommended)
GOOGLE_CLIENT_ID=your_google_oauth_client_id
GOOGLE_CLIENT_SECRET=your_google_oauth_client_secret
GITHUB_CLIENT_ID=your_github_oauth_client_id
GITHUB_CLIENT_SECRET=your_github_oauth_client_secret

# Email Configuration (Required for alerts)
SMTP_HOST=your_smtp_server.com
SMTP_PORT=587
SMTP_USERNAME=[email protected]
SMTP_PASSWORD=your_email_password
SMTP_TLS=true
FROM_EMAIL=[email protected]

4. Start Services

# Start all services in development mode
docker-compose -f docker-compose.dev.yml up -d

# Initialize database
docker-compose -f docker-compose.dev.yml run --rm culiuptime alembic upgrade head

# Verify services are running
docker-compose -f docker-compose.dev.yml ps

5. Access Your Instance


🏭 Production Deployment

For production environments requiring SSL, optimized performance, and enterprise features.

📖 Complete Production Setup
This section provides comprehensive production deployment guidance including SSL automation, security hardening, and operational procedures.

Production Quick Start

# Clone repository
git clone https://github.com/chiplonton/culiuptime.git
cd culiuptime

# Configure for production
cp .env.example .env
# Edit .env with production settings (see environment configuration section above)

# Set your domain and email for SSL
export DOMAIN=your-domain.com
export EMAIL=[email protected]

# Initialize SSL and start production services
./scripts/init-letsencrypt.sh

# Wait for services to initialize
echo "Waiting for services to initialize..."
sleep 30

# CRITICAL: Initialize database schema with Alembic migrations
# This step creates all required database tables and indexes
docker compose -f docker-compose.prd.yml exec backend alembic upgrade head

# Verify database initialization
docker compose -f docker-compose.prd.yml exec backend python -c "
from app.core.database import get_engine
from sqlalchemy import text
engine = get_engine()
with engine.connect() as conn:
result = conn.execute(text('SELECT count(*) FROM information_schema.tables WHERE table_schema = \'public\''))
table_count = result.scalar()
print(f'Database initialized successfully! Tables created: {table_count}')
"

# Verify deployment
docker-compose -f docker-compose.prd.yml ps

Key Production Features

  • 🔒 Automatic SSL - Let's Encrypt certificates with auto-renewal
  • ⚡ Optimized Performance - Resource limits for 2vCPU/4GB systems
  • 🛡️ Security Hardening - Firewall, rate limiting, security headers
  • 📊 Monitoring - Health checks, metrics, log rotation
  • 💾 Backup Strategy - Automated database and system backups

Production Architecture

Internet (HTTPS) → nginx:443 → backend:8000
Internet (HTTP) → nginx:80 → redirect to HTTPS

Services:
- nginx: SSL termination, static files, API proxy
- backend: FastAPI application (2 workers)
- celery_worker: Background tasks (2 workers)
- postgres: Database (1GB memory limit)
- redis: Cache and message broker
- certbot: Automatic SSL management

Next Steps for Production

  1. Configure your domain and SSL certificates
  2. Set up production monitoring and backups
  3. Deploy monitoring agents globally
  4. Review security hardening and operational procedures (see sections below)

⚙️ Development Configuration

Reverse Proxy Setup (nginx)

Create /etc/nginx/sites-available/culiuptime:

server {
listen 80;
server_name uptime.yourdomain.com;
return 301 https://$server_name$request_uri;
}

server {
listen 443 ssl http2;
server_name uptime.yourdomain.com;

ssl_certificate /path/to/your/certificate.pem;
ssl_certificate_key /path/to/your/private.key;

# Frontend
location / {
proxy_pass http://localhost:3000;
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;
}

# API
location /api/ {
proxy_pass http://localhost:8000/api/;
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;
}

# API Documentation
location /docs {
proxy_pass http://localhost:8000/docs;
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;
}
}

Environment-Specific Configurations

Create environment-specific .env files:

# .env.production
ENVIRONMENT=production
DEBUG=false
# ... production settings

# .env.staging
ENVIRONMENT=staging
DEBUG=true
# ... staging settings

Database Configuration

External PostgreSQL

# Use external PostgreSQL server
POSTGRES_SERVER=your-postgres-server.com
POSTGRES_PORT=5432
POSTGRES_USER=culiuptime_user
POSTGRES_PASSWORD=secure_password
POSTGRES_DB=culiuptime

Database Tuning

For production workloads, tune your PostgreSQL:

-- postgresql.conf recommendations
shared_buffers = 256MB
effective_cache_size = 1GB
work_mem = 4MB
maintenance_work_mem = 64MB
max_connections = 100

🔐 Security Hardening

1. Secrets Management

# Use strong, unique secrets
SECRET_KEY=$(openssl rand -hex 32)
AGENT_SECRET_KEY=$(openssl rand -hex 32)
POSTGRES_PASSWORD=$(openssl rand -base64 32)

# Store in secure location
chmod 600 .env

2. Network Security

# Firewall rules (iptables example)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT # SSH
iptables -A INPUT -p tcp --dport 80 -j ACCEPT # HTTP
iptables -A INPUT -p tcp --dport 443 -j ACCEPT # HTTPS
iptables -A INPUT -p tcp --dport 3000 -j DROP # Block direct frontend access
iptables -A INPUT -p tcp --dport 8000 -j DROP # Block direct API access

3. SSL/TLS Configuration

Use Let's Encrypt for free SSL certificates:

# Install certbot
sudo apt install certbot python3-certbot-nginx

# Get certificate
sudo certbot --nginx -d uptime.yourdomain.com

# Auto-renewal
sudo crontab -e
# Add: 0 12 * * * /usr/bin/certbot renew --quiet

📊 Monitoring Your Installation

Health Checks

CuliUptime includes built-in health checks:

# Check application health
curl http://localhost:8000/health

# Check database connection
curl http://localhost:8000/health/db

# Check Redis connection
curl http://localhost:8000/health/redis

Log Management

# For development setup
docker-compose -f docker-compose.dev.yml logs culiuptime

# For production setup
docker-compose -f docker-compose.prd.yml logs culiuptime

# View all service logs (use appropriate compose file)
docker-compose -f docker-compose.[dev|prd].yml logs

# Follow logs in real-time (use appropriate compose file)
docker-compose -f docker-compose.[dev|prd].yml logs -f culiuptime

Metrics Collection

Integrate with monitoring systems:

  • Prometheus: Metrics endpoint at /metrics
  • Grafana: Import CuliUptime dashboard
  • ELK Stack: Structured JSON logging

🔄 Maintenance

Updates

# Backup database first (use appropriate compose file)
docker-compose -f docker-compose.[dev|prd].yml exec postgres pg_dump -U culiuptime culiuptime_prod > backup.sql

# Pull latest code
git pull origin main

# Update containers (use appropriate compose file)
docker-compose -f docker-compose.[dev|prd].yml pull
docker-compose -f docker-compose.[dev|prd].yml up -d

# Apply database migrations (use appropriate compose file)
docker-compose -f docker-compose.[dev|prd].yml run --rm culiuptime alembic upgrade head

Backup Strategy

Database Backups

#!/bin/bash
# backup-db.sh
DATE=$(date +%Y%m%d_%H%M%S)
# Use appropriate compose file: docker-compose.dev.yml for development or docker-compose.prd.yml for production
COMPOSE_FILE=${1:-docker-compose.dev.yml}
docker-compose -f $COMPOSE_FILE exec -T postgres pg_dump -U culiuptime culiuptime_prod | gzip > "backup_${DATE}.sql.gz"

# Keep last 7 days of backups
find . -name "backup_*.sql.gz" -mtime +7 -delete

Full System Backup

#!/bin/bash
# backup-full.sh
tar -czf culiuptime_backup_$(date +%Y%m%d).tar.gz \
.env \
docker-compose.dev.yml \
docker-compose.prd.yml \
custom_configs/ \
--exclude=node_modules \
--exclude=.git

🌍 Global Agent Deployment

For multi-location monitoring coverage, deploy CuliUptime agents on hosting providers or VPS/servers worldwide.

📖 Complete Agent Deployment Guide
Agent deployment requires hosting/VPS setup with SSL certificates. See the Agent Deployment Guide for comprehensive instructions on deploying monitoring agents globally.

Key Requirements for Agents

  • Web hosting or VPS/Server with PHP 7.4+ support
  • SSL certificate (Let's Encrypt or self-signed) for secure communication
  • Web-accessible deployment (not cron scheduling)
  • HTTPS endpoint for agent communication

Quick Agent Setup

# Download agent files
wget https://github.com/chiplonton/culiuptime/archive/main.zip
cd culiuptime-main/agents/

# Configure agent by editing web_agent.php directly
# Edit the AGENT_ID, AGENT_SECRET_KEY, and PLATFORM_API_KEY values at the top of the file

# Upload to your hosting/VPS web directory
# Deploy as web-accessible HTTPS endpoint

👉 Follow Complete Agent Deployment Guide

🆘 Troubleshooting

Common Issues

Services won't start

# Check port conflicts
sudo netstat -tulpn | grep :3000
sudo netstat -tulpn | grep :8000

# Check Docker logs (use appropriate compose file)
docker-compose -f docker-compose.[dev|prd].yml logs

Database connection errors

# Verify PostgreSQL is running (use appropriate compose file)
docker-compose -f docker-compose.[dev|prd].yml ps postgres

# Check database logs (use appropriate compose file)
docker-compose -f docker-compose.[dev|prd].yml logs postgres

# Test database connection (use appropriate compose file)
docker-compose -f docker-compose.[dev|prd].yml exec postgres psql -U culiuptime culiuptime_prod

Database migration issues (Production)

# If database migration fails, check logs
docker compose -f docker-compose.prd.yml logs backend
docker compose -f docker-compose.prd.yml logs postgres

# Ensure PostgreSQL is healthy before running migrations
docker compose -f docker-compose.prd.yml ps postgres

# If needed, restart backend service and retry migration
docker compose -f docker-compose.prd.yml restart backend
docker compose -f docker-compose.prd.yml exec backend alembic upgrade head

# Check database tables were created
docker compose -f docker-compose.prd.yml exec postgres psql -U culiuptime culiuptime_prod -c "\dt"

OAuth authentication failures

  • Verify OAuth credentials in .env
  • Check callback URLs in provider settings
  • Ensure domain matches OAuth configuration

Email alerts not working

# Test SMTP connection (use appropriate compose file)
docker-compose -f docker-compose.[dev|prd].yml run --rm culiuptime python -c "
import smtplib
from email.mime.text import MIMEText
# Add your SMTP test code here
"

Getting Help

🎯 Next Steps

  1. Configure monitoring for your services
  2. Set up email alerts for notifications
  3. Deploy additional agents globally
  4. Explore the API for integrations

Happy self-hosting! 🏠