Production Deployment Guide
Complete server configuration documentation for deploying Frappe HR in production environments with enterprise-grade security and performance optimization.
Table of Contents
Server Requirements
Minimum Specifications
- CPU 2 cores
- RAM 4GB
- Storage 50GB SSD
- OS Ubuntu 22.04 LTS
Recommended Specifications
- CPU 4 cores
- RAM 8GB
- Storage 100GB SSD
- Network Public IP
Cloud Provider Options
This setup is compatible with any VPS provider. Recommended services include:
Server Setup and Connection
SSH Key Authentication (Recommended)
# Connect using SSH key ssh root@YOUR_SERVER_IP -i /path/to/your/private/key
Password Authentication
# Connect using password ssh root@YOUR_SERVER_IP # Enter password when prompted
Initial Security Setup
# Update root password passwd # Create sudo user adduser admin usermod -aG sudo admin # Switch to new user su - admin
System Preparation
Update System Packages
# Update package lists and upgrade system sudo apt-get update && sudo apt-get upgrade -y # Install essential utilities sudo apt-get install -y ca-certificates curl git wget \ software-properties-common apt-transport-https \ lsb-release gnupg
What this does: Updates your system to the latest security patches and installs basic tools needed for the installation process.
Docker Installation
Add Docker Repository
# Create directory for Docker GPG key
sudo install -m 0755 -d /etc/apt/keyrings
# Download and add Docker's official GPG key
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add Docker repository to sources
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Update package lists with Docker repository
sudo apt-get update
What this does: Adds Docker's official repository to your system so you can install the latest stable version.
Install Docker Engine
# Install Docker Engine and Compose plugin sudo apt-get install -y docker-ce docker-ce-cli containerd.io \ docker-buildx-plugin docker-compose-plugin # Add current user to docker group sudo usermod -aG docker $USER # Apply group changes newgrp docker
Verify Installation
# Check Docker version docker --version # Check Docker Compose version docker compose version # Test Docker installation docker run --rm hello-world
Expected output: You should see version numbers and a "Hello from Docker!" message.
Frappe HR Installation
Clone Repository
# Clone the official Frappe HR repository git clone https://github.com/frappe/hrms # Navigate to Docker directory cd hrms/docker
Deploy Frappe HR
# Start all services in background docker compose up -d # Monitor the installation process (optional) docker compose logs -f
What this does: Downloads and starts MariaDB, Redis, and Frappe application. Creates initial site and database. This process takes 5-15 minutes depending on your server speed.
Verify Installation
# Check running containers docker ps # Test local access curl http://localhost:8000
Default login credentials:
Username: Administrator
Password: admin
Domain and DNS Configuration
Direct DNS Setup (Simple)
If you're managing DNS directly without a proxy:
# A Record Configuration Type: A Name: @ (or your subdomain) Value: YOUR_SERVER_IP TTL: 300 # CNAME Record (for subdomains) Type: CNAME Name: hr (or your chosen subdomain) Value: yourdomain.com TTL: 300
Cloudflare Proxy Setup (Recommended)
For additional security and performance:
# Cloudflare A Record Type: A Name: @ (or subdomain like 'hr') Value: YOUR_SERVER_IP Proxy status: Proxied (orange cloud) # SSL/TLS Setting SSL/TLS → Overview → Full (Strict) # Origin Certificate SSL/TLS → Origin Server → Create Certificate
Nginx Reverse Proxy Setup
Install Nginx
# Install Nginx web server sudo apt install nginx -y # Start and enable Nginx sudo systemctl start nginx sudo systemctl enable nginx
Create Nginx Configuration
# Create configuration file sudo nano /etc/nginx/sites-available/your-domain.com
Configuration content for Direct DNS:
server {
listen 80;
server_name your-domain.com www.your-domain.com;
# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
# Logging
access_log /var/log/nginx/your-domain.access.log;
error_log /var/log/nginx/your-domain.error.log;
# Proxy to Frappe HR
location / {
proxy_pass http://127.0.0.1:8000;
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;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Buffering
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 8k;
}
# Static files optimization
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
expires 1y;
add_header Cache-Control "public, immutable";
}
}
Enable Configuration
# Create symbolic link to enable site sudo ln -s /etc/nginx/sites-available/your-domain.com /etc/nginx/sites-enabled/ # Remove default configuration sudo rm /etc/nginx/sites-enabled/default # Test configuration sudo nginx -t # Restart Nginx sudo systemctl restart nginx
SSL Certificate Configuration
Install Certbot
# Install Snapd sudo apt install snapd -y # Install Certbot via Snap sudo snap install core; sudo snap refresh core sudo snap install --classic certbot # Create symbolic link sudo ln -s /snap/bin/certbot /usr/bin/certbot
Obtain SSL Certificate
# Obtain certificate and automatically configure Nginx sudo certbot --nginx -d your-domain.com -d www.your-domain.com # Follow the prompts: # 1. Enter email address # 2. Agree to Terms of Service # 3. Choose whether to share email with EFF # 4. Select redirect option (recommended: 2 - Redirect HTTP to HTTPS)
Verify SSL Configuration
# Test certificate renewal sudo certbot renew --dry-run # Check certificate status sudo certbot certificates
Firewall Configuration
Install and Configure UFW
# Install UFW (Ubuntu Firewall) sudo apt install ufw -y # Set default policies sudo ufw default deny incoming sudo ufw default allow outgoing # Allow SSH (CRITICAL - do this first!) sudo ufw allow 22/tcp # Allow HTTP and HTTPS sudo ufw allow 80/tcp sudo ufw allow 443/tcp # Enable firewall sudo ufw enable # Check status sudo ufw status verbose
Critical: Always allow SSH before enabling the firewall to avoid being locked out of your server.
Block Direct Access to Docker Ports
# Block direct access to application ports sudo iptables -I DOCKER-USER -i eth0 -p tcp --dport 8000 -s ! 127.0.0.1 -j DROP sudo iptables -I DOCKER-USER -i eth0 -p tcp --dport 3306 -s ! 127.0.0.1 -j DROP sudo iptables -I DOCKER-USER -i eth0 -p tcp --dport 6379 -s ! 127.0.0.1 -j DROP # Install iptables-persistent to save rules sudo apt install iptables-persistent -y # Save current rules sudo netfilter-persistent save
Security Hardening
Configure SSH Security
# Edit SSH configuration sudo nano /etc/ssh/sshd_config # Find and modify these lines: # PermitRootLogin no # PasswordAuthentication no # Only if using SSH keys # PubkeyAuthentication yes # Restart SSH service sudo systemctl restart sshd
Set Up Automatic Security Updates
# Install unattended-upgrades sudo apt install unattended-upgrades -y # Configure automatic updates sudo dpkg-reconfigure -plow unattended-upgrades
Set Up Fail2Ban (Optional)
# Install Fail2Ban sudo apt install fail2ban -y # Create local configuration sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local # Edit configuration sudo nano /etc/fail2ban/jail.local # Find [sshd] section and ensure: # enabled = true # port = 22 # maxretry = 3 # bantime = 3600 # Restart Fail2Ban sudo systemctl restart fail2ban sudo systemctl enable fail2ban
User Management
Create Additional Users
# Access Frappe container docker exec -it docker-frappe-1 bash # Create new user bench --site hrms.localhost add-user user@yourdomain.com \ --first-name First --last-name Last \ --password SecurePassword123 # Available roles: # - System Manager (full admin) # - HR Manager (HR operations) # - HR User (basic HR functions) # - Employee (self-service) # Assign role bench --site hrms.localhost set-user-role user@yourdomain.com "HR Manager" # Exit container exit
Create Demo User
# Access Frappe container docker exec -it docker-frappe-1 bash # Create demo user bench --site hrms.localhost add-user demo@yourdomain.com \ --first-name Demo --last-name User \ --password DemoPassword123 --send-welcome-email 0 # Assign roles bench --site hrms.localhost set-user-role demo@yourdomain.com "HR Manager" bench --site hrms.localhost set-user-role demo@yourdomain.com "Employee" # Exit container exit
Monitoring and Maintenance
Set Up Automatic Certificate Renewal
# Add cron job for certificate renewal sudo crontab -e # Add this line: 0 2 * * 1 /usr/bin/certbot renew --quiet && /bin/systemctl reload nginx
Monitor System Resources
# Install monitoring tools sudo apt install htop iotop nethogs -y # Check system resources htop # Monitor disk usage df -h # Check Docker container status docker ps docker stats # View application logs docker logs docker-frappe-1
Automated Backup Script
# Create backup script sudo nano /usr/local/bin/backup-frappe.sh # Add content: #!/bin/bash BACKUP_DIR="/backup/frappe" DATE=$(date +%Y%m%d_%H%M%S) # Create backup directory mkdir -p $BACKUP_DIR # Backup database docker exec docker-mariadb-1 mysqldump -u root -padmin --all-databases > $BACKUP_DIR/database_$DATE.sql # Backup sites directory docker cp docker-frappe-1:/home/frappe/frappe-bench/sites $BACKUP_DIR/sites_$DATE # Compress backups tar -czf $BACKUP_DIR/frappe_backup_$DATE.tar.gz $BACKUP_DIR/database_$DATE.sql $BACKUP_DIR/sites_$DATE # Remove uncompressed backups rm -rf $BACKUP_DIR/database_$DATE.sql $BACKUP_DIR/sites_$DATE # Keep only last 7 days of backups find $BACKUP_DIR -name "frappe_backup_*.tar.gz" -mtime +7 -delete echo "Backup completed: frappe_backup_$DATE.tar.gz"
# Make script executable sudo chmod +x /usr/local/bin/backup-frappe.sh # Add to cron for daily backups sudo crontab -e # Add line: 0 3 * * * /usr/local/bin/backup-frappe.sh
Useful Maintenance Commands
# Restart all services sudo systemctl restart nginx docker restart docker-frappe-1 docker-mariadb-1 docker-redis-1 # Update system packages sudo apt update && sudo apt upgrade -y # Update Docker containers cd ~/hrms/docker docker compose pull docker compose up -d # Check disk space df -h du -sh /var/lib/docker/ # Clean up Docker docker system prune -f
Final Security Checklist
Before going live, ensure you have completed:
- Changed default passwords
- Configured firewall (UFW)
- Set up SSL certificate
- Configured real IP detection (if using Cloudflare)
- Set up automatic security updates
- Configured log rotation
- Set up automated backups
- Tested certificate renewal
- Disabled unnecessary services
- Set up monitoring
- Documented your configuration
Production Ready: This deployment is now production-ready with enterprise-grade security, SSL encryption, firewall protection, and monitoring capabilities. Regular maintenance and updates are essential for continued security and performance.