Skip to content

Deploying a FrappeHR App

Introduction

FrappeHR is a modern, open-source Human Resource Management System built on the Frappe Framework. It provides comprehensive HR functionalities including employee management, leave tracking, attendance, payroll, recruitment, and performance reviews. Deploying FrappeHR on Klutch.sh provides you with a scalable, secure infrastructure for managing your organization’s human resources, with support for persistent storage, automated deployments from GitHub, and seamless integration with databases.

This guide walks through deploying FrappeHR on Klutch.sh using a Dockerfile, configuring persistent volumes for data storage, setting up environment variables, and implementing best practices for production deployments.


Prerequisites

Before deploying FrappeHR on Klutch.sh, ensure you have:

  • A Klutch.sh account (sign up here)
  • A GitHub repository for your FrappeHR deployment
  • Basic knowledge of Docker and HR management systems
  • Understanding of MariaDB or MySQL database operations
  • Familiarity with the Frappe Framework architecture

Understanding FrappeHR Architecture

FrappeHR is built on the Frappe Framework, which uses:

  • Python (3.10+) for the backend application logic
  • MariaDB/MySQL for database storage
  • Redis for caching and background job queuing
  • Node.js for building frontend assets
  • Nginx as a reverse proxy (handled by Klutch.sh)

The application consists of multiple components that work together to provide a complete HR management solution. When deploying on Klutch.sh, we’ll containerize these components and configure them appropriately.


Deployment Steps

    1. Prepare Your FrappeHR Repository

    Create or fork a GitHub repository for your FrappeHR deployment. Your repository should include:

    • A Dockerfile for building the FrappeHR application
    • Configuration files for environment-specific settings
    • Any custom apps or modifications you want to include

    Important considerations:

    • Store large assets (logs, uploads, backups) outside the Git repository using persistent volumes
    • Keep sensitive configuration separate from the codebase
    • Document any custom modifications or additional Frappe apps you’re including

    Refer to the Klutch.sh Quick Start Guide for detailed instructions on repository setup and GitHub integration.

    2. Create the Dockerfile

    Klutch.sh automatically detects a Dockerfile if present in the root directory of your repository. Create a Dockerfile in your repository root with the following configuration:

    FROM frappe/erpnext:v15
    # Set working directory
    WORKDIR /home/frappe/frappe-bench
    # Install FrappeHR
    RUN bench get-app --branch version-15 https://github.com/frappe/hrms.git
    # Install additional dependencies if needed
    RUN bench setup requirements
    # Build assets
    RUN bench build --app hrms
    # Create sites directory if it doesn't exist
    RUN mkdir -p /home/frappe/frappe-bench/sites
    # Expose the default Frappe port
    EXPOSE 8000
    # Set proper permissions
    RUN chown -R frappe:frappe /home/frappe/frappe-bench
    # Switch to frappe user
    USER frappe
    # Health check
    HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
    CMD curl -f http://localhost:8000/api/method/ping || exit 1
    # Start command
    CMD ["bench", "start"]

    Dockerfile Explanation:

    • We use the official frappe/erpnext base image which includes all necessary dependencies
    • The FrappeHR app (HRMS) is installed using bench get-app
    • Assets are built during the image creation for faster startup
    • The application runs as the frappe user for security
    • Health checks ensure the application is running correctly
    • Port 8000 is the default port for Frappe applications

    Alternative: Custom Build

    If you need more control, you can build from a base Python image:

    FROM python:3.10-slim
    # Install system dependencies
    RUN apt-get update && apt-get install -y \
    git \
    wget \
    curl \
    build-essential \
    python3-dev \
    libffi-dev \
    libssl-dev \
    libmysqlclient-dev \
    mariadb-client \
    redis-tools \
    nodejs \
    npm \
    && rm -rf /var/lib/apt/lists/*
    # Install bench
    RUN pip install frappe-bench
    # Create frappe user
    RUN useradd -m -s /bin/bash frappe
    # Switch to frappe user
    USER frappe
    WORKDIR /home/frappe
    # Initialize bench
    RUN bench init frappe-bench --frappe-branch version-15 --python python3.10
    # Change to bench directory
    WORKDIR /home/frappe/frappe-bench
    # Get FrappeHR
    RUN bench get-app --branch version-15 https://github.com/frappe/hrms.git
    # Expose port
    EXPOSE 8000
    CMD ["bench", "start"]

    3. Configure Database Connection

    FrappeHR requires a MariaDB or MySQL database. You can either:

    Option A: Use an external managed database (recommended for production)

    Set up a managed MariaDB/MySQL instance and configure connection via environment variables:

    Terminal window
    DB_HOST=your-database-host.example.com
    DB_PORT=3306
    DB_NAME=frappehr_production
    DB_USER=frappehr_user
    DB_PASSWORD=your-secure-password

    Option B: Deploy MariaDB on Klutch.sh

    1. Create a separate MariaDB app on Klutch.sh
    2. Select TCP traffic type in the Klutch.sh dashboard
    3. Connect to the database on port 8000 (external) with the internal port set to 3306
    4. Attach persistent volumes for database storage at /var/lib/mysql
    5. Note the connection details for use in your FrappeHR app

    4. Set Up Redis

    FrappeHR uses Redis for caching and background jobs. Deploy Redis on Klutch.sh:

    1. Create a new app for Redis
    2. Use the official Redis Docker image or create a simple Dockerfile:
    FROM redis:7-alpine
    # Custom Redis configuration if needed
    COPY redis.conf /usr/local/etc/redis/redis.conf
    EXPOSE 6379
    CMD ["redis-server", "/usr/local/etc/redis/redis.conf"]
    1. Select TCP traffic type
    2. Set the internal port to 6379
    3. Optionally attach a persistent volume to /data for Redis persistence

    5. Create a New Site

    After deploying the FrappeHR container, you need to create a new site. This is typically done as part of the startup process. Create a startup script start.sh:

    #!/bin/bash
    set -e
    # Wait for database to be ready
    echo "Waiting for database..."
    while ! mysqladmin ping -h"${DB_HOST}" -P"${DB_PORT}" --silent; do
    sleep 2
    done
    # Wait for Redis to be ready
    echo "Waiting for Redis..."
    while ! redis-cli -h "${REDIS_HOST}" -p "${REDIS_PORT}" ping; do
    sleep 2
    done
    # Change to bench directory
    cd /home/frappe/frappe-bench
    # Check if site exists, if not create it
    if [ ! -d "sites/${SITE_NAME}" ]; then
    echo "Creating new site: ${SITE_NAME}"
    bench new-site ${SITE_NAME} \
    --admin-password "${ADMIN_PASSWORD}" \
    --db-host "${DB_HOST}" \
    --db-port "${DB_PORT}" \
    --db-name "${DB_NAME}" \
    --db-password "${DB_PASSWORD}" \
    --no-mariadb-socket
    # Install FrappeHR app
    bench --site ${SITE_NAME} install-app hrms
    # Enable scheduler
    bench --site ${SITE_NAME} enable-scheduler
    fi
    # Set site as current site
    echo ${SITE_NAME} > sites/currentsite.txt
    # Start bench
    exec bench start

    Update your Dockerfile to include this script:

    # Add the startup script
    COPY start.sh /home/frappe/start.sh
    RUN chmod +x /home/frappe/start.sh
    CMD ["/home/frappe/start.sh"]

    6. Configure Persistent Storage

    FrappeHR requires persistent storage for several directories. In the Klutch.sh dashboard, attach persistent volumes with the following mount paths and recommended sizes:

    Mount PathPurposeRecommended Size
    /home/frappe/frappe-bench/sitesSite files, uploads, backups50GB - 200GB
    /home/frappe/frappe-bench/logsApplication logs10GB - 20GB

    Steps to attach volumes:

    1. Go to your FrappeHR app in the Klutch.sh dashboard
    2. Navigate to the “Volumes” section
    3. Click “Add Volume”
    4. Enter the mount path (e.g., /home/frappe/frappe-bench/sites)
    5. Specify the size in GB (e.g., 100)
    6. Click “Create” to attach the volume

    Note: You can only specify the mount path and size; volume names are managed automatically by Klutch.sh.

    7. Configure Environment Variables

    In the Klutch.sh dashboard, configure the following environment variables for your FrappeHR app. Mark sensitive values as secrets to prevent them from being logged.

    Required Environment Variables:

    Terminal window
    # Site Configuration
    SITE_NAME=example-app.klutch.sh
    ADMIN_PASSWORD=your-secure-admin-password
    # Database Configuration
    DB_HOST=your-mariadb-app.klutch.sh
    DB_PORT=8000
    DB_NAME=frappehr_db
    DB_USER=frappe_user
    DB_PASSWORD=your-database-password
    # Redis Configuration
    REDIS_HOST=your-redis-app.klutch.sh
    REDIS_PORT=8000
    REDIS_CACHE=redis://your-redis-app.klutch.sh:8000/1
    REDIS_QUEUE=redis://your-redis-app.klutch.sh:8000/2
    REDIS_SOCKETIO=redis://your-redis-app.klutch.sh:8000/3
    # Application Settings
    FRAPPE_SITE_NAME_HEADER=${SITE_NAME}
    DEVELOPER_MODE=0
    ALLOW_TESTS=0
    # Mail Configuration (optional but recommended)
    MAIL_SERVER=smtp.gmail.com
    MAIL_PORT=587
    MAIL_USE_TLS=1
    MAIL_LOGIN=your-email@example.com
    MAIL_PASSWORD=your-email-password

    Environment Variables for Nixpacks Customization:

    If you need to customize the build or start commands using Nixpacks, use these environment variables:

    Terminal window
    # Build-time environment variables
    NIXPACKS_BUILD_CMD=bench build --app hrms
    # Runtime environment variables
    NIXPACKS_START_CMD=/home/frappe/start.sh

    Security Best Practices:

    • Never commit sensitive credentials to your repository
    • Use Klutch.sh’s secret environment variables for passwords and API keys
    • Rotate credentials regularly
    • Use strong, unique passwords for database and admin accounts

    8. Configure Internal Port

    In the Klutch.sh dashboard:

    1. Select HTTP traffic type (FrappeHR is a web application)
    2. Set the internal port to 8000 (Frappe’s default port)
    3. Klutch.sh will automatically route external traffic to this port

    9. Deploy the Application

    Once everything is configured:

    1. Push your repository with the Dockerfile and configuration files to GitHub
    2. In the Klutch.sh dashboard at klutch.sh/app, create a new project if you haven’t already
    3. Create a new app within your project
    4. Connect your GitHub repository
    5. Klutch.sh will automatically detect the Dockerfile and begin building
    6. Configure the environment variables, volumes, and port settings as described above
    7. Click “Create” to deploy

    The deployment process will:

    • Pull your code from GitHub
    • Build the Docker image
    • Deploy the container with your configurations
    • Mount persistent volumes
    • Start the FrappeHR application

    10. Initial Setup and Configuration

    After your first deployment:

    1. Access your FrappeHR instance at https://example-app.klutch.sh
    2. Log in using the admin credentials you set in environment variables
    3. Complete the initial setup wizard:
      • Configure your company details
      • Set up employee directory
      • Configure leave types and policies
      • Set up department and designation hierarchies
      • Configure payroll settings
    4. Customize the system according to your organization’s requirements
    5. Create user accounts for your HR team

Getting Started with FrappeHR

Once deployed, here are some initial tasks to get started:

Create Your First Employee

  1. Navigate to HR > Employee from the sidebar
  2. Click New to create an employee record
  3. Fill in required fields:
    • Employee Name
    • Employee Number
    • Date of Birth
    • Date of Joining
    • Department
    • Designation
  4. Save the employee record

Configure Leave Types

  1. Go to HR > Leave Type
  2. Create common leave types:
    • Annual Leave
    • Sick Leave
    • Casual Leave
    • Maternity/Paternity Leave
  3. Configure leave allocation rules for each type

Set Up Attendance Tracking

  1. Navigate to HR > Attendance
  2. Configure attendance methods:
    • Manual entry
    • Biometric integration
    • Mobile check-in
  3. Set up shift management if needed

Example API Usage

FrappeHR provides a REST API for integration with other systems:

import requests
# API endpoint
base_url = "https://example-app.klutch.sh"
api_key = "your-api-key"
api_secret = "your-api-secret"
# Get list of employees
response = requests.get(
f"{base_url}/api/resource/Employee",
headers={
"Authorization": f"token {api_key}:{api_secret}"
}
)
employees = response.json()
print(f"Total employees: {len(employees['data'])}")
# Create a new leave application
leave_data = {
"employee": "EMP-001",
"leave_type": "Annual Leave",
"from_date": "2024-01-15",
"to_date": "2024-01-19",
"description": "Family vacation"
}
response = requests.post(
f"{base_url}/api/resource/Leave Application",
json=leave_data,
headers={
"Authorization": f"token {api_key}:{api_secret}"
}
)
print(f"Leave application created: {response.json()}")

Database Backups and Maintenance

Regular backups are crucial for data safety:

Automated Backups

Configure automated backups in FrappeHR:

  1. Go to Settings > System Settings
  2. Enable automatic backups
  3. Set backup frequency (daily recommended)
  4. Configure backup retention period

Manual Backup

Create a manual backup using the bench command:

Terminal window
# SSH into your container or run via exec
bench --site your-site-name backup
# Backup with files
bench --site your-site-name backup --with-files

Backups are stored in /home/frappe/frappe-bench/sites/your-site-name/private/backups/

Database Maintenance

Perform regular maintenance tasks:

Terminal window
# Optimize database tables
bench --site your-site-name mariadb -e "OPTIMIZE TABLE table_name"
# Clear cache
bench --site your-site-name clear-cache
# Rebuild search index
bench --site your-site-name build-search-index

Performance Optimization

Caching Configuration

Optimize Redis caching for better performance:

# In site_config.json (stored in persistent volume)
{
"redis_cache": "redis://your-redis-host:8000/1",
"redis_queue": "redis://your-redis-host:8000/2",
"redis_socketio": "redis://your-redis-host:8000/3",
"cache_ttl": 86400
}

Background Jobs

Configure background workers for better performance:

Terminal window
# In your start.sh script, you can configure workers
bench set-config -g worker_background_jobs 4
bench set-config -g worker_short_jobs 2
bench set-config -g worker_long_jobs 1

Database Indexing

Ensure proper database indexes for frequently queried fields:

-- Add indexes for common queries
CREATE INDEX idx_employee_status ON `tabEmployee` (status);
CREATE INDEX idx_attendance_date ON `tabAttendance` (attendance_date);
CREATE INDEX idx_leave_from_date ON `tabLeave Application` (from_date);

Monitoring and Logging

Application Logs

FrappeHR logs are stored in the persistent volume at /home/frappe/frappe-bench/logs/:

  • web.log - Web server logs
  • worker.log - Background job logs
  • schedule.log - Scheduled task logs
  • redis_queue.log - Queue logs

Access logs using:

Terminal window
# View recent web logs
tail -f /home/frappe/frappe-bench/logs/web.log
# Search for errors
grep ERROR /home/frappe/frappe-bench/logs/*.log

Monitoring Key Metrics

Monitor these important metrics:

  • Response Time: Average API response time
  • Database Connections: Active database connections
  • Redis Memory Usage: Cache memory utilization
  • Background Job Queue: Pending jobs count
  • Error Rate: Application error frequency

Use the Klutch.sh monitoring dashboard to track resource usage (CPU, memory, disk).

Health Checks

Implement health check endpoints:

# Custom health check endpoint
@frappe.whitelist(allow_guest=True)
def health_check():
# Check database connectivity
frappe.db.sql("SELECT 1")
# Check Redis connectivity
frappe.cache().get("health_check")
return {"status": "healthy"}

Scaling Considerations

Horizontal Scaling

For high-traffic deployments:

  1. Separate Web and Worker Processes:

    • Deploy multiple web server instances
    • Deploy dedicated worker instances for background jobs
    • Use a load balancer (provided by Klutch.sh)
  2. Database Read Replicas:

    • Set up MariaDB read replicas for read-heavy operations
    • Configure FrappeHR to use replicas for reporting queries
  3. Redis Clustering:

    • Use Redis Cluster for high availability
    • Separate cache, queue, and socket.io Redis instances

Vertical Scaling

Increase resources for your Klutch.sh app:

  • Upgrade CPU and memory allocation
  • Increase persistent volume size as data grows
  • Optimize database queries and indexes

Troubleshooting Common Issues

Site Not Accessible

Problem: Cannot access FrappeHR after deployment

Solutions:

  1. Check application logs for errors:

    Terminal window
    tail -f /home/frappe/frappe-bench/logs/web.log
  2. Verify environment variables are set correctly

  3. Ensure database connection is working:

    Terminal window
    bench --site your-site-name mariadb -e "SELECT 1"
  4. Check if the site exists:

    Terminal window
    bench --site your-site-name migrate

Database Connection Errors

Problem: Cannot connect to database

Solutions:

  1. Verify database host and port in environment variables
  2. Check if database service is running
  3. Verify database credentials
  4. Ensure network connectivity between containers

Performance Issues

Problem: Slow response times

Solutions:

  1. Enable Redis caching properly
  2. Optimize database queries and add indexes
  3. Increase worker processes
  4. Monitor and increase resource allocation
  5. Clear cache: bench --site your-site-name clear-cache

Background Jobs Not Running

Problem: Scheduled tasks not executing

Solutions:

  1. Verify scheduler is enabled:

    Terminal window
    bench --site your-site-name enable-scheduler
  2. Check worker logs:

    Terminal window
    tail -f /home/frappe/frappe-bench/logs/worker.log
  3. Ensure Redis queue is configured correctly

  4. Restart workers if needed


Security Best Practices

Application Security

  1. Regular Updates: Keep FrappeHR and dependencies updated

    Terminal window
    bench update --reset
  2. Strong Passwords: Enforce strong password policies

    • Minimum length of 12 characters
    • Mix of uppercase, lowercase, numbers, and symbols
    • Regular password rotation
  3. Two-Factor Authentication: Enable 2FA for all users

    • Go to User Settings > Two Factor Authentication
    • Require 2FA for administrator accounts
  4. Role-Based Access Control: Implement least privilege principle

    • Create custom roles based on job functions
    • Regularly audit user permissions
    • Remove inactive user accounts

Network Security

  1. HTTPS Only: Klutch.sh provides automatic HTTPS
  2. IP Whitelisting: Restrict access to admin panels
  3. API Security: Use API keys with limited permissions
  4. Rate Limiting: Prevent abuse of API endpoints

Data Security

  1. Encryption at Rest: Use encrypted persistent volumes
  2. Encryption in Transit: All connections use TLS
  3. Regular Backups: Automated daily backups
  4. Backup Testing: Regularly test backup restoration
  5. Data Retention: Implement data retention policies

Compliance Considerations

For organizations with compliance requirements:

  • GDPR: Configure data privacy settings
  • HIPAA: If handling health information, ensure proper security controls
  • SOC 2: Implement audit logging and access controls
  • Data Residency: Choose appropriate Klutch.sh regions

Advanced Configurations

Custom App Development

Extend FrappeHR with custom apps:

Terminal window
# Create a new custom app
bench new-app custom_hr_app
# Install the app on your site
bench --site your-site-name install-app custom_hr_app
# Example custom doctype
frappe.ui.form.on('Employee', {
refresh: function(frm) {
// Add custom button
frm.add_custom_button(__('Custom Action'), function() {
// Your custom logic
});
}
});

Integration with Third-Party Services

Integrate FrappeHR with external services:

Slack Integration:

import frappe
import requests
def send_slack_notification(message):
webhook_url = frappe.conf.get("slack_webhook_url")
requests.post(webhook_url, json={"text": message})
# Send notification on leave approval
@frappe.whitelist()
def on_leave_approved(doc, method):
message = f"Leave approved for {doc.employee_name}"
send_slack_notification(message)

Email Notifications:

# Configure in site_config.json
{
"mail_server": "smtp.gmail.com",
"mail_port": 587,
"use_tls": 1,
"mail_login": "your-email@example.com",
"mail_password": "your-password",
"auto_email_id": "hr@yourcompany.com"
}

Multi-Tenant Configuration

Run multiple companies on a single instance:

Terminal window
# Create additional sites
bench new-site company2.example.com \
--admin-password password \
--install-app hrms
# Configure site routing in Klutch.sh
# Use custom domains for each tenant

Migration and Upgrades

Migrating from Another System

Import data from existing HR systems:

  1. Export data from your current system in CSV format
  2. Use FrappeHR’s data import tool:
    • Go to Data Import Tool
    • Select doctype (Employee, Leave Application, etc.)
    • Upload CSV file
    • Map fields
    • Import data

Upgrading FrappeHR

Keep your installation up to date:

Terminal window
# Update to latest version
cd /home/frappe/frappe-bench
bench update --reset
# Migrate database
bench --site your-site-name migrate
# Rebuild assets
bench build --app hrms
# Restart services
bench restart

For major version upgrades:

  1. Review release notes and breaking changes
  2. Test upgrade in a staging environment
  3. Backup production data
  4. Perform upgrade during maintenance window
  5. Verify all functionality after upgrade

Production Best Practices

High Availability Setup

For mission-critical deployments:

  1. Multiple App Instances: Deploy 3+ FrappeHR instances
  2. Load Balancing: Distribute traffic across instances
  3. Database Replication: Set up master-slave replication
  4. Redis Sentinel: Use Redis Sentinel for automatic failover
  5. Monitoring: Implement comprehensive monitoring and alerting

Disaster Recovery Plan

Prepare for disaster scenarios:

  1. Regular Backups: Automated daily backups
  2. Off-site Storage: Store backups in separate region
  3. Recovery Testing: Quarterly disaster recovery drills
  4. Documentation: Maintain detailed recovery procedures
  5. RTO/RPO Targets: Define and meet recovery objectives

Performance Testing

Test system under load:

Terminal window
# Use Apache Bench for load testing
ab -n 1000 -c 10 https://example-app.klutch.sh/login
# Monitor during test
watch -n 1 'ps aux | grep bench'

Cost Optimization

Optimize infrastructure costs:

  1. Right-size Resources: Monitor and adjust CPU/memory
  2. Storage Management: Clean up old logs and backups
  3. Database Optimization: Remove unused indexes
  4. Caching: Maximize Redis cache hit rate
  5. CDN: Use CDN for static assets

Resources and Further Reading

Official Documentation

Klutch.sh Resources

Community Resources


Conclusion

Deploying FrappeHR on Klutch.sh provides a robust, scalable solution for managing your organization’s human resources. With automatic Dockerfile detection, persistent volumes for data storage, seamless GitHub integration, and flexible configuration options, you can focus on managing your workforce rather than infrastructure.

This guide has covered everything from initial setup to advanced configurations, security best practices, and production deployment strategies. Whether you’re running a small team or a large enterprise, FrappeHR on Klutch.sh can scale to meet your needs.

For additional assistance or advanced deployment scenarios, consult the official documentation or reach out to the Klutch.sh support team at klutch.sh/app.


Next Steps:

  • Set up your development environment
  • Deploy a test instance to familiarize yourself with the system
  • Configure your organization’s specific HR policies
  • Train your HR team on using FrappeHR
  • Plan your production deployment strategy
  • Implement monitoring and backup procedures