Production Deployment Guide¶
Complete guide for deploying the Laboratory Management System to a production server.
Table of Contents¶
- Prerequisites
- Quick Start
- Detailed Setup
- Deployment Process
- SSL Configuration
- Monitoring
- Backup and Restore
- Rollback
- Troubleshooting
- Security Checklist
Prerequisites¶
Server Requirements¶
Minimum: - OS: Ubuntu 20.04+ or CentOS 8+ - CPU: 2 cores - RAM: 4GB - Storage: 20GB free space
Recommended: - CPU: 4 cores - RAM: 8GB - Storage: 50GB+ free space
Required Software¶
- Docker 20.10+ with Docker Compose v2
- Git 2.25+
- curl (for health checks)
- gzip (for backups)
Network Requirements¶
- Domain name pointed to your server
- Ports 80 and 443 accessible from internet
- Port 22 for SSH access
- Stable internet connection
Quick Start¶
This section provides a streamlined deployment process for production.
1. Clone Repository¶
cd /opt
sudo mkdir laboratory-system
sudo chown $USER:$USER laboratory-system
cd laboratory-system
git clone <your-repo-url> .
2. Configure Environment¶
# Copy production environment template
cp .env.production.example .env
# Generate SECRET_KEY
python3 -c "import secrets; print(secrets.token_urlsafe(50))"
# Edit configuration
nano .env
Critical variables to set:
# Django Settings
SECRET_KEY=<generated-secret-key>
DEBUG=False
ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com
DOMAIN_NAME=yourdomain.com
# Database
POSTGRES_USER=lab_user
POSTGRES_PASSWORD=<strong-random-password>
POSTGRES_DB=laboratory_db
# Email (see Configuration Guide for SMTP details)
EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
EMAIL_HOST=smtp.yourdomain.com
EMAIL_PORT=587
EMAIL_HOST_USER=noreply@yourdomain.com
EMAIL_HOST_PASSWORD=<email-password>
EMAIL_USE_TLS=True
DEFAULT_FROM_EMAIL=noreply@yourdomain.com
# Security
SESSION_COOKIE_SECURE=True
CSRF_COOKIE_SECURE=True
SECURE_SSL_REDIRECT=True
# Redis & Celery
REDIS_URL=redis://redis:6379/0
CELERY_BROKER_URL=redis://redis:6379/0
See Environment Variables for complete reference.
3. Install Docker (if needed)¶
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
# Install Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# Verify installation
docker --version
docker-compose --version
# Re-login for group changes to take effect
exit
# SSH back in
4. Build and Start Services¶
# Build images
docker compose -f compose.yaml -f compose.production.yaml build
# Start database and redis
docker compose -f compose.yaml -f compose.production.yaml up -d postgres redis
# Wait for database to be ready
sleep 10
# Run migrations
make manage migrate
# Create superuser
make manage createsuperuser
# Collect static files
make manage collectstatic --no-input
# Start application services
docker compose -f compose.yaml -f compose.production.yaml up -d web worker beat
5. Initialize SSL Certificates¶
# Initialize Let's Encrypt SSL
./bin/init-letsencrypt.sh yourdomain.com admin@yourdomain.com
# For testing (uses Let's Encrypt staging):
# ./bin/init-letsencrypt.sh yourdomain.com admin@yourdomain.com 1
This will: - Request SSL certificates from Let's Encrypt - Configure Nginx with SSL - Set up automatic certificate renewal
See SSL Certificates for detailed SSL setup.
6. Verify Deployment¶
# Check all services are running
docker compose -f compose.yaml -f compose.production.yaml ps
# Test application health
curl https://yourdomain.com/up
# View logs
docker compose -f compose.yaml -f compose.production.yaml logs -f web
Expected output from health check:
Detailed Setup¶
Automated Setup (Recommended)¶
For fresh server setup, use the automated setup script:
# Download and run the setup script
curl -fsSL https://raw.githubusercontent.com/your-username/laboratory-system/main/bin/setup-server -o setup-server.sh
chmod +x setup-server.sh
# Run automated setup
./setup-server.sh --repo https://github.com/your-username/laboratory-system.git --domain yourdomain.com
Setup script features: - ✅ Updates system packages - ✅ Installs Docker and Docker Compose - ✅ Configures firewall (UFW) and fail2ban - ✅ Creates application directory - ✅ Clones repository - ✅ Sets up environment configuration - ✅ Configures systemd service - ✅ Sets up log rotation - ✅ Configures automated backups - ✅ Runs initial deployment
Manual Setup¶
If you prefer manual setup or the automated script isn't suitable, follow the Quick Start section above for step-by-step manual instructions.
Deployment Process¶
Pre-Deployment Checklist¶
Before deploying, run the pre-deployment check script:
This verifies: - ✅ Project directory structure - ✅ Git repository status - ✅ Environment configuration - ✅ System resources (disk space, memory) - ✅ Docker installation and status - ✅ Database connectivity - ✅ Redis connectivity - ✅ Pending migrations - ✅ Application health - ✅ Security settings
Deploy to Production¶
Use the deployment script for updates:
The deployment script performs these steps in order:
- 🔍 Validate — Check production mode (DEBUG=False, ALLOWED_HOSTS set) and exit if invalid.
- 🗄️ Start infrastructure — Bring up Postgres and Redis so backup and migrations can run (idempotent if already up).
- 💾 Backup — Create a database dump in
./backups(fails if DB is unreachable). - 📥 Pull — Fetch and pull latest from
origin/main(skips if already up to date). - 🏗️ Build — Build Docker images for web, worker, and beat. The Dockerfile runs
collectstaticduring image build (case-insensitive DEBUG check), so the image always contains a valid WhiteNoise manifest. - 🚀 Start app services — Start web, worker, and beat so migrations and collectstatic can run inside the web container. Nginx is NOT started yet, so no external traffic reaches the app while the manifest is being rebuilt.
- 🔄 Migrations — Run
migrate --checkthenmigrate --no-input(fails on migration errors). - 📦 Collect static — Run
collectstatic --no-input --clearto rebuild the WhiteNoise manifest from the image's static sources (repairs references likeimages/logo-unl-fcv.png). Output is persisted to the host via the volume mount at/public_collected(matchingSTATIC_ROOT). - 📚 Build documentation — Run
make docs-buildin the web container to write MkDocs output intopublic_collected/docs/(continues on failure with a warning). - 🌐 Start proxy — Start nginx so the app is reachable via HTTPS. By this point migrations, static files, and documentation are all ready.
- 🔁 Recreate app services — Run
docker compose up -d web worker beatso containers use the current production config (e.g. web has no published port 8000; all traffic must go through nginx). - ✅ Health check — Poll
http://localhost/upuntil success or timeout; exit with error if services do not become healthy.
Monitor Deployment¶
# Watch application logs in real-time
docker compose -f compose.yaml -f compose.production.yaml logs -f web
# Check all service statuses
docker compose -f compose.yaml -f compose.production.yaml ps
# Test application
curl https://yourdomain.com/up
# View recent errors
docker compose -f compose.yaml -f compose.production.yaml logs --tail=50 web | grep ERROR
SSL Configuration¶
Automatic SSL with Let's Encrypt¶
The system includes automated SSL certificate management:
Certificate Renewal¶
Certificates automatically renew via cron job. To manually renew:
# Manual renewal
docker compose -f compose.yaml -f compose.production.yaml run --rm certbot certbot renew
# Reload Nginx
docker compose -f compose.yaml -f compose.production.yaml exec nginx nginx -s reload
# Check certificate status
docker compose -f compose.yaml -f compose.production.yaml exec certbot certbot certificates
See SSL Certificates Guide for detailed SSL documentation.
Monitoring¶
View Logs¶
# All services
docker compose -f compose.yaml -f compose.production.yaml logs -f
# Specific service
docker compose -f compose.yaml -f compose.production.yaml logs -f web
docker compose -f compose.yaml -f compose.production.yaml logs -f nginx
docker compose -f compose.yaml -f compose.production.yaml logs -f worker
# Nginx access logs
docker compose -f compose.yaml -f compose.production.yaml exec nginx tail -f /var/log/nginx/laboratory-access.log
# Nginx error logs
docker compose -f compose.yaml -f compose.production.yaml exec nginx tail -f /var/log/nginx/laboratory-error.log
Check Service Status¶
# Service status
docker compose -f compose.yaml -f compose.production.yaml ps
# Resource usage
docker stats
# Application health
curl https://yourdomain.com/up
Automated Monitoring¶
Set up automated health checks:
# Check monitoring logs
tail -f /opt/laboratory-system/logs/monitor.log
# Run manual health check
/opt/laboratory-system/bin/monitor
See Operations Guide for detailed monitoring procedures.
Backup and Restore¶
Automated Backups¶
The system includes automated backup scripts:
# Backups are stored in: /opt/laboratory-system/backups/
ls -lh /opt/laboratory-system/backups/
# Backup retention: 7 daily, 4 weekly, 3 monthly
Manual Backup¶
# Create backup directory if needed
mkdir -p backups
# Backup database
make db:dump
# Creates: backups/adlab_dump_YYYYMMDD_HHMMSS.sql
# Or using Docker directly:
docker compose -f compose.yaml -f compose.production.yaml exec -T postgres \
pg_dump -U lab_user laboratory_db | gzip > backups/backup_$(date +%Y%m%d_%H%M%S).sql.gz
Restore from Backup¶
# Stop application services (keep database running)
docker compose -f compose.yaml -f compose.production.yaml stop web worker beat
# Restore database
gunzip -c backups/backup_YYYYMMDD_HHMMSS.sql.gz | \
docker compose -f compose.yaml -f compose.production.yaml exec -T postgres \
psql -U lab_user laboratory_db
# Start application services
docker compose -f compose.yaml -f compose.production.yaml up -d web worker beat
See Backup & Restore Guide for detailed backup procedures.
Rollback¶
If deployment issues occur, use the rollback process:
Quick Rollback¶
Advanced Rollback Options¶
# List available backups
./bin/rollback --list
# Restore specific backup
./bin/rollback --backup db_backup_20241201_143022.sql.gz
# Rollback to specific git commit
./bin/rollback --commit abc1234
# Force rollback (skip confirmations - use with caution)
./bin/rollback --force
Manual Rollback¶
# 1. Stop services
docker compose -f compose.yaml -f compose.production.yaml stop web worker beat
# 2. Revert code to previous commit
git reset --hard HEAD~1
# 3. Rebuild images
docker compose -f compose.yaml -f compose.production.yaml build
# 4. Restore database if needed
# (see Backup and Restore section)
# 5. Start services
docker compose -f compose.yaml -f compose.production.yaml up -d
Troubleshooting¶
SSL Certificate Issues¶
# Check certificate
docker compose -f compose.yaml -f compose.production.yaml exec certbot certbot certificates
# Renew certificate manually
docker compose -f compose.yaml -f compose.production.yaml run --rm certbot certbot renew
# Reload Nginx
docker compose -f compose.yaml -f compose.production.yaml exec nginx nginx -s reload
# Test SSL configuration
curl -vI https://yourdomain.com
Service Not Starting¶
# Check logs for specific service
docker compose -f compose.yaml -f compose.production.yaml logs web
# Check container status
docker compose -f compose.yaml -f compose.production.yaml ps
# Restart specific service
docker compose -f compose.yaml -f compose.production.yaml restart web
# Full restart (if needed)
docker compose -f compose.yaml -f compose.production.yaml down
docker compose -f compose.yaml -f compose.production.yaml up -d
Database Connection Issues¶
# Check database is running
docker compose -f compose.yaml -f compose.production.yaml ps postgres
# Test connection from within container
docker compose -f compose.yaml -f compose.production.yaml exec postgres psql -U lab_user laboratory_db
# Check Django can connect
make manage check --database default
# View database logs
docker compose -f compose.yaml -f compose.production.yaml logs postgres
Static Files Not Loading¶
# Collect static files again
make manage collectstatic --no-input
# Check Nginx configuration
docker compose -f compose.yaml -f compose.production.yaml exec nginx nginx -t
# Restart Nginx
docker compose -f compose.yaml -f compose.production.yaml restart nginx
See Troubleshooting Guide for more issues and solutions.
Security Checklist¶
Before going live, verify all security settings:
Environment Security¶
-
DEBUG=Falsein production - Strong
SECRET_KEYgenerated (50+ characters) - Strong
POSTGRES_PASSWORDset (20+ characters) -
ALLOWED_HOSTSconfigured correctly (no wildcards) -
DOMAIN_NAMEmatches your actual domain
SSL/TLS Security¶
- SSL certificates installed and valid
- Auto-renewal configured (certbot cron job)
-
SESSION_COOKIE_SECURE=True -
CSRF_COOKIE_SECURE=True -
SECURE_SSL_REDIRECT=True - HTTPS working without certificate warnings
Firewall Configuration¶
- Firewall enabled (UFW or similar)
- Only necessary ports open (80, 443, 22)
- SSH port secured or changed
- fail2ban configured for SSH protection
Backup & Recovery¶
- Automated backups configured
- Backup restoration tested successfully
- Backups stored securely (offsite if possible)
- Retention policy defined and implemented
Application Security¶
- Email SMTP configured (when ready)
- System updates applied regularly
- Docker images up to date
- Database access restricted
- Redis access restricted
- No sensitive data in logs
Access Control¶
- Strong passwords for all admin accounts
- SSH key-based authentication enabled
- Sudo access restricted
- Application user permissions configured correctly
See Security Audit Guide for comprehensive security review.
Post-Deployment Tasks¶
After successful deployment:
-
Configure Automated Backups
-
Set Up Monitoring (optional)
- Configure Grafana + Prometheus
- Set up log aggregation
-
Configure alerting
-
Configure Email
- Test email sending:
make manage sendtestemail admin@yourdomain.com - Configure SMTP properly
-
Set Up Systemd Service (auto-start on boot)
-
Test Disaster Recovery
- Perform test backup
- Perform test restore
-
Verify rollback procedure
-
Document Your Setup
- Note any custom configurations
- Document any deviations from this guide
- Update team documentation
Next Steps¶
- Configure Email - Set up SMTP for notifications
- Operations Guide - Daily operations and maintenance
- Troubleshooting - Common issues and solutions
- Backup Procedures - Detailed backup documentation
Additional Resources¶
- Nginx Setup Guide - Detailed Nginx configuration
- SSL Certificate Setup - SSL/TLS configuration
- Server Connection - SSH and remote access
- Production Checklist - Pre-launch verification