Deploying an EspoCRM App
Introduction
EspoCRM is a powerful, open-source Customer Relationship Management (CRM) platform designed to help businesses manage customer interactions, sales pipelines, marketing campaigns, and support services. Built with PHP and MySQL, EspoCRM offers a modern, intuitive interface with extensive customization capabilities to fit diverse business needs.
EspoCRM is designed to be:
- Flexible and Customizable: Adapt the CRM to your business processes with custom entities, fields, and workflows
- User-Friendly: Modern, responsive interface that works seamlessly across desktop and mobile devices
- Feature-Rich: Comprehensive CRM features including lead management, opportunity tracking, contact management, and more
- Extensible: Support for extensions and integrations to expand functionality
- Secure: Built-in security features with role-based access control and data encryption
- Open Source: Self-hosted solution giving you complete control over your data and infrastructure
Key features include:
- Sales Management: Lead tracking, opportunity management, sales forecasting, and pipeline visualization
- Contact Management: Comprehensive contact and account management with relationship tracking
- Marketing Automation: Email campaigns, marketing lists, and campaign tracking
- Customer Support: Case management, knowledge base, and support ticket system
- Calendar & Activities: Integrated calendar, tasks, calls, and meetings management
- Email Integration: Built-in email client with IMAP/SMTP support
- Reporting & Analytics: Customizable reports and dashboards with visual analytics
- Team Collaboration: Shared calendars, streams, and collaborative tools
- Workflow Automation: Business process management with automated workflows
- Mobile Access: Responsive design optimized for mobile devices
This comprehensive guide walks you through deploying EspoCRM on Klutch.sh using Docker, including detailed installation steps, database configuration, persistent storage setup, environment variables, and production-ready best practices.
Prerequisites
Before you begin deploying EspoCRM to Klutch.sh, ensure you have the following:
- A Klutch.sh account
- A GitHub account with a repository for your EspoCRM project
- Docker installed locally for testing (optional but recommended)
- Basic understanding of Docker, PHP applications, and CRM concepts
- A MySQL or MariaDB database (can be provisioned separately on Klutch.sh)
Installation and Setup
Step 1: Create Your Project Directory
First, create a new directory for your EspoCRM deployment project:
mkdir espocrm-klutchcd espocrm-klutchgit initStep 2: Create the Dockerfile
Create a Dockerfile in your project root directory. This will define your EspoCRM container configuration:
# Use the official EspoCRM imageFROM espocrm/espocrm:latest
# Set the working directoryWORKDIR /var/www/html
# Set default environment variables# These can be overridden in the Klutch.sh dashboardENV ESPOCRM_DATABASE_DRIVER=pdo_mysqlENV ESPOCRM_DATABASE_HOST=dbENV ESPOCRM_DATABASE_NAME=espocrmENV ESPOCRM_DATABASE_USER=espocrmENV ESPOCRM_DATABASE_PASSWORD=CHANGE_ME_SECURE_DB_PASSWORDENV ESPOCRM_ADMIN_USERNAME=adminENV ESPOCRM_ADMIN_PASSWORD=CHANGE_ME_SECURE_ADMIN_PASSWORDENV ESPOCRM_SITE_URL=http://localhost
# EspoCRM listens on port 80 by defaultEXPOSE 80
# The entrypoint and command are defined in the base imageImportant Security Notes:
- CRITICAL: Replace
CHANGE_ME_SECURE_DB_PASSWORDwith a strong, unique database password before deploying - CRITICAL: Replace
CHANGE_ME_SECURE_ADMIN_PASSWORDwith a strong, unique admin password before deploying - The
ESPOCRM_SITE_URLshould be set to your actual Klutch.sh app URL (e.g.,https://example-app.klutch.sh) - Change the admin username from the default ‘admin’ for better security
- Never commit real passwords to your repository - use environment variables in Klutch.sh instead
- The official EspoCRM Docker image includes Apache and PHP pre-configured
Step 3: Create a .dockerignore File
Create a .dockerignore file to exclude unnecessary files from your Docker build:
.git.github.gitignoreREADME.md.env*.lognode_modulesdataStep 4: Create a README
Create a README.md file to document your deployment:
# EspoCRM Deployment
This repository contains the configuration for deploying EspoCRM on Klutch.sh.
## Setup
1. Configure environment variables in Klutch.sh dashboard2. Set up MySQL database connection3. Deploy the application4. Complete the initial setup wizard
## Environment Variables
- `ESPOCRM_DATABASE_HOST`: MySQL database host- `ESPOCRM_DATABASE_NAME`: Database name- `ESPOCRM_DATABASE_USER`: Database user- `ESPOCRM_DATABASE_PASSWORD`: Database password- `ESPOCRM_ADMIN_USERNAME`: Initial admin username- `ESPOCRM_ADMIN_PASSWORD`: Initial admin password- `ESPOCRM_SITE_URL`: Your EspoCRM site URLStep 5: Test Locally (Optional)
Before deploying to Klutch.sh, you can test your EspoCRM setup locally using Docker:
# Build the Docker imagedocker build -t my-espocrm .
# Create a network for EspoCRM and MySQLdocker network create espocrm-network
# Run MySQL containerdocker run -d \ --name espocrm-mysql \ --network espocrm-network \ -e MYSQL_ROOT_PASSWORD=root \ -e MYSQL_DATABASE=espocrm \ -e MYSQL_USER=espocrm \ -e MYSQL_PASSWORD=espocrm_password \ mysql:8.0
# Wait for MySQL to be ready (about 30 seconds)sleep 30
# Run the EspoCRM containerdocker run -d \ --name espocrm-app \ --network espocrm-network \ -p 8080:80 \ -e ESPOCRM_DATABASE_HOST=espocrm-mysql \ -e ESPOCRM_DATABASE_NAME=espocrm \ -e ESPOCRM_DATABASE_USER=espocrm \ -e ESPOCRM_DATABASE_PASSWORD=espocrm_password \ -e ESPOCRM_ADMIN_USERNAME=admin \ -e ESPOCRM_ADMIN_PASSWORD=admin \ -e ESPOCRM_SITE_URL=http://localhost:8080 \ my-espocrm
# Check if EspoCRM is running# Wait a minute for the container to initialize, then visit http://localhost:8080
# View logsdocker logs espocrm-app
# Stop and remove the test containers when donedocker stop espocrm-app espocrm-mysqldocker rm espocrm-app espocrm-mysqldocker network rm espocrm-networkStep 6: Push to GitHub
Commit your Dockerfile and configuration to your GitHub repository:
git add Dockerfile .dockerignore README.mdgit commit -m "Add EspoCRM Dockerfile configuration"git remote add origin https://github.com/yourusername/espocrm-klutch.gitgit push -u origin mainSetting Up the Database
EspoCRM requires a MySQL or MariaDB database to store all CRM data, including contacts, accounts, opportunities, and system configurations.
Database Setup Options
Option 1: Deploy MySQL on Klutch.sh
You can deploy a MySQL database on Klutch.sh. Follow the MySQL deployment guide to set up a MySQL instance.
Option 2: Use an External Database Service
You can use external database services such as:
Database Requirements
- MySQL Version: 5.7 or higher (MySQL 8.0 recommended)
- MariaDB Version: 10.2 or higher
- Database Collation: utf8mb4_unicode_ci
- Required Privileges: CREATE, DROP, SELECT, INSERT, UPDATE, DELETE, ALTER, INDEX
Create Database and User
If you’re managing your own MySQL instance, create a database and user for EspoCRM:
CREATE DATABASE espocrm CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;CREATE USER 'espocrm'@'your-klutch-app-ip' IDENTIFIED BY 'CHANGE_ME_SECURE_PASSWORD';GRANT ALL PRIVILEGES ON espocrm.* TO 'espocrm'@'your-klutch-app-ip';FLUSH PRIVILEGES;Security Notes:
- Replace
CHANGE_ME_SECURE_PASSWORDwith a strong, unique password - Replace
'your-klutch-app-ip'with the specific IP address or hostname of your Klutch.sh app for better security - If using
'%'as the host (allows connections from any host), ensure your database is behind a firewall and only accessible to trusted networks
Deploying to Klutch.sh
Now that your EspoCRM project is ready and pushed to GitHub, follow these steps to deploy it on Klutch.sh with persistent storage.
Deployment Steps
-
Log in to Klutch.sh
Navigate to klutch.sh/app and sign in to your account.
-
Create a New Project
Go to Create Project and give your project a meaningful name (e.g., “EspoCRM Production”).
-
Create a New App
Navigate to Create App and configure the following settings:
-
Select Your Repository
- Choose GitHub as your Git source
- Select the repository containing your Dockerfile
- Choose the branch you want to deploy (usually
mainormaster)
-
Configure Traffic Type
- Traffic Type: Select HTTP (EspoCRM serves HTTP/HTTPS traffic)
- Internal Port: Set to
80(the port that EspoCRM listens on inside the container)
-
Set Environment Variables
Add the following essential environment variables for your EspoCRM configuration:
Required Database Environment Variables:
ESPOCRM_DATABASE_DRIVER: Set topdo_mysqlESPOCRM_DATABASE_HOST: Your MySQL database hostname (e.g.,mysql-service.klutch.shor external database host)ESPOCRM_DATABASE_PORT: Database port (default:3306)ESPOCRM_DATABASE_NAME: Database name (e.g.,espocrm)ESPOCRM_DATABASE_USER: Database usernameESPOCRM_DATABASE_PASSWORD: Database password (mark as secret)
Required Site Configuration:
ESPOCRM_SITE_URL: Your Klutch.sh app URL (e.g.,https://example-app.klutch.sh)ESPOCRM_ADMIN_USERNAME: Initial admin username (change after first login)ESPOCRM_ADMIN_PASSWORD: Initial admin password (change after first login, mark as secret)
Optional but Recommended:
ESPOCRM_LANGUAGE: Default language (e.g.,en_US)ESPOCRM_TIMEZONE: Server timezone (e.g.,America/New_York)ESPOCRM_DATE_FORMAT: Date format (e.g.,MM/DD/YYYY)ESPOCRM_TIME_FORMAT: Time format (e.g.,hh:mm A)ESPOCRM_CURRENCY: Default currency (e.g.,USD)
Email Configuration (SMTP):
ESPOCRM_EMAIL_TRANSPORT: Set tosmtpESPOCRM_EMAIL_FROM_NAME: Sender name for emailsESPOCRM_EMAIL_FROM_ADDRESS: Sender email addressESPOCRM_SMTP_HOST: SMTP server hostnameESPOCRM_SMTP_PORT: SMTP port (typically 587 for TLS or 465 for SSL)ESPOCRM_SMTP_SECURITY: Set totlsorsslESPOCRM_SMTP_USERNAME: SMTP usernameESPOCRM_SMTP_PASSWORD: SMTP password (mark as secret)
Security Note: Never commit sensitive credentials like database passwords or SMTP passwords to your repository. Always set them as environment variables in Klutch.sh and mark them as secrets.
-
Attach Persistent Volumes
EspoCRM requires persistent storage for custom modules, uploaded files, and configuration. Configure the following volumes:
Volume 1 - Data Storage:
- Mount Path:
/var/www/html/data - Size: Choose based on expected file uploads and attachments (e.g., 10GB, 20GB, 50GB)
Volume 2 - Custom Modules and Extensions:
- Mount Path:
/var/www/html/custom - Size: 5GB (for custom modules and extensions)
Volume 3 - Configuration Files:
- Mount Path:
/var/www/html/config - Size: 1GB (for configuration files)
Important: Persistent volumes are critical for EspoCRM. Without them, you’ll lose all custom configurations, uploaded files, and customizations when the container restarts.
- Mount Path:
-
Configure Additional Settings
- Region: Select the region closest to your users for optimal latency
- Compute Resources:
- Minimum: 1 CPU, 2GB RAM (for small teams up to 10 users)
- Recommended: 2 CPU, 4GB RAM (for teams up to 50 users)
- High Usage: 4+ CPU, 8GB+ RAM (for large teams and heavy usage)
- Instances: Start with 1 instance (EspoCRM doesn’t natively support horizontal scaling)
-
Deploy Your Application
Click “Create” to start the deployment. Klutch.sh will:
- Automatically detect your Dockerfile in the repository root
- Build the Docker image with EspoCRM
- Attach the persistent volumes to the specified mount paths
- Start your EspoCRM container
- Assign a URL for accessing your EspoCRM instance
-
Access Your EspoCRM Instance
Once deployment is complete, you’ll receive a URL like
example-app.klutch.sh. Your EspoCRM instance will be accessible at:- Main Application:
https://example-app.klutch.sh/
Open the URL in your browser to complete the initial setup. Log in with the admin credentials you configured in the environment variables.
- Main Application:
Getting Started with EspoCRM
After deploying EspoCRM, here’s how to get started with configuring and using your CRM system.
Initial Configuration
-
Log In to Your EspoCRM Instance
Open your EspoCRM instance at
https://example-app.klutch.sh/and log in with your admin credentials. -
Change Admin Password
Immediately change your admin password from the default:
- Click on your username in the top-right corner
- Select “Preferences”
- Navigate to the “Password” section
- Set a strong, unique password
-
Configure System Settings
Navigate to Administration > Settings to configure:
- Company information and logo
- Email settings for sending emails
- Currency and locale settings
- Date and time formats
- System timezone
-
Set Up Email Integration
Configure email accounts for your users:
- Go to Administration > Email Accounts
- Add IMAP/SMTP accounts for receiving and sending emails
- Configure email templates for automated communications
Sample Code: EspoCRM API Integration
EspoCRM provides a powerful REST API for integrations. Here are examples of how to interact with your EspoCRM instance programmatically:
JavaScript/Node.js Example:
// EspoCRM API Client Exampleconst axios = require('axios');
class EspoCRMClient { constructor(baseUrl, apiKey) { this.baseUrl = baseUrl; this.apiKey = apiKey; this.client = axios.create({ baseURL: `${baseUrl}/api/v1`, headers: { 'Content-Type': 'application/json', 'X-Api-Key': apiKey } }); }
// Create a new contact async createContact(data) { try { const response = await this.client.post('/Contact', data); console.log('Contact created:', response.data); return response.data; } catch (error) { console.error('Error creating contact:', error.response?.data || error.message); throw error; } }
// Get contact by ID async getContact(contactId) { try { const response = await this.client.get(`/Contact/${contactId}`); return response.data; } catch (error) { console.error('Error fetching contact:', error.response?.data || error.message); throw error; } }
// Update a contact async updateContact(contactId, data) { try { const response = await this.client.put(`/Contact/${contactId}`, data); console.log('Contact updated:', response.data); return response.data; } catch (error) { console.error('Error updating contact:', error.response?.data || error.message); throw error; } }
// List contacts with filters async listContacts(params = {}) { try { const response = await this.client.get('/Contact', { params }); return response.data; } catch (error) { console.error('Error listing contacts:', error.response?.data || error.message); throw error; } }
// Create a new opportunity async createOpportunity(data) { try { const response = await this.client.post('/Opportunity', data); console.log('Opportunity created:', response.data); return response.data; } catch (error) { console.error('Error creating opportunity:', error.response?.data || error.message); throw error; } }
// Create a new lead async createLead(data) { try { const response = await this.client.post('/Lead', data); console.log('Lead created:', response.data); return response.data; } catch (error) { console.error('Error creating lead:', error.response?.data || error.message); throw error; } }
// Create a new account async createAccount(data) { try { const response = await this.client.post('/Account', data); console.log('Account created:', response.data); return response.data; } catch (error) { console.error('Error creating account:', error.response?.data || error.message); throw error; } }}
// Usage example// Note: Generate your API key in EspoCRM (see "Generating API Keys" section below)const crm = new EspoCRMClient('https://example-app.klutch.sh', 'your-api-key');
// Create a contactasync function example() { const newContact = await crm.createContact({ firstName: 'John', lastName: 'Doe', emailAddress: 'john.doe@example.com', phoneNumber: '+1-555-0123', accountId: 'account-id-here' });
// List contacts const contacts = await crm.listContacts({ maxSize: 20, offset: 0, orderBy: 'createdAt', order: 'desc' });
console.log('Contacts:', contacts);
// Create an opportunity const opportunity = await crm.createOpportunity({ name: 'New Business Deal', stage: 'Prospecting', amount: 50000, closeDate: '2024-12-31', probability: 50, accountId: 'account-id-here', assignedUserId: 'user-id-here' });}
example();Python Example:
import requestsimport json
class EspoCRMClient: def __init__(self, base_url, api_key): self.base_url = base_url self.api_key = api_key self.headers = { 'Content-Type': 'application/json', 'X-Api-Key': api_key }
def create_contact(self, data): """Create a new contact""" url = f"{self.base_url}/api/v1/Contact" response = requests.post(url, headers=self.headers, json=data) response.raise_for_status() return response.json()
def get_contact(self, contact_id): """Get contact by ID""" url = f"{self.base_url}/api/v1/Contact/{contact_id}" response = requests.get(url, headers=self.headers) response.raise_for_status() return response.json()
def update_contact(self, contact_id, data): """Update a contact""" url = f"{self.base_url}/api/v1/Contact/{contact_id}" response = requests.put(url, headers=self.headers, json=data) response.raise_for_status() return response.json()
def list_contacts(self, params=None): """List contacts with optional filters""" url = f"{self.base_url}/api/v1/Contact" response = requests.get(url, headers=self.headers, params=params) response.raise_for_status() return response.json()
def create_opportunity(self, data): """Create a new opportunity""" url = f"{self.base_url}/api/v1/Opportunity" response = requests.post(url, headers=self.headers, json=data) response.raise_for_status() return response.json()
def create_lead(self, data): """Create a new lead""" url = f"{self.base_url}/api/v1/Lead" response = requests.post(url, headers=self.headers, json=data) response.raise_for_status() return response.json()
def create_account(self, data): """Create a new account""" url = f"{self.base_url}/api/v1/Account" response = requests.post(url, headers=self.headers, json=data) response.raise_for_status() return response.json()
# Usage example# Note: Generate your API key in EspoCRM (see "Generating API Keys" section below)crm = EspoCRMClient('https://example-app.klutch.sh', 'your-api-key')
# Create a contactnew_contact = crm.create_contact({ 'firstName': 'Jane', 'lastName': 'Smith', 'emailAddress': 'jane.smith@example.com', 'phoneNumber': '+1-555-0456', 'accountId': 'account-id-here'})print(f'Contact created: {new_contact}')
# List contactscontacts = crm.list_contacts({ 'maxSize': 20, 'offset': 0, 'orderBy': 'createdAt', 'order': 'desc'})print(f'Found {len(contacts.get("list", []))} contacts')
# Create an opportunityopportunity = crm.create_opportunity({ 'name': 'Enterprise Deal', 'stage': 'Qualification', 'amount': 100000, 'closeDate': '2024-12-31', 'probability': 75, 'accountId': 'account-id-here', 'assignedUserId': 'user-id-here'})print(f'Opportunity created: {opportunity}')PHP Example:
<?php
class EspoCRMClient { private $baseUrl; private $apiKey;
public function __construct($baseUrl, $apiKey) { $this->baseUrl = $baseUrl; $this->apiKey = $apiKey; }
private function request($method, $endpoint, $data = null) { $url = $this->baseUrl . '/api/v1' . $endpoint;
$ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', 'X-Api-Key: ' . $this->apiKey ]);
if ($data) { curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); }
$response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch);
if ($httpCode >= 400) { throw new Exception("API request failed with status $httpCode: $response"); }
return json_decode($response, true); }
public function createContact($data) { return $this->request('POST', '/Contact', $data); }
public function getContact($contactId) { return $this->request('GET', "/Contact/$contactId"); }
public function updateContact($contactId, $data) { return $this->request('PUT', "/Contact/$contactId", $data); }
public function listContacts($params = []) { $query = http_build_query($params); return $this->request('GET', "/Contact?$query"); }
public function createOpportunity($data) { return $this->request('POST', '/Opportunity', $data); }
public function createLead($data) { return $this->request('POST', '/Lead', $data); }
public function createAccount($data) { return $this->request('POST', '/Account', $data); }}
// Usage example// Note: Generate your API key in EspoCRM (see "Generating API Keys" section below)$crm = new EspoCRMClient('https://example-app.klutch.sh', 'your-api-key');
// Create a contact$newContact = $crm->createContact([ 'firstName' => 'Bob', 'lastName' => 'Johnson', 'emailAddress' => 'bob.johnson@example.com', 'phoneNumber' => '+1-555-0789', 'accountId' => 'account-id-here']);echo "Contact created: " . print_r($newContact, true) . "\n";
// List contacts$contacts = $crm->listContacts([ 'maxSize' => 20, 'offset' => 0, 'orderBy' => 'createdAt', 'order' => 'desc']);echo "Found " . count($contacts['list'] ?? []) . " contacts\n";
// Create an opportunity$opportunity = $crm->createOpportunity([ 'name' => 'Strategic Partnership', 'stage' => 'Proposal', 'amount' => 75000, 'closeDate' => '2024-12-31', 'probability' => 60, 'accountId' => 'account-id-here', 'assignedUserId' => 'user-id-here']);echo "Opportunity created: " . print_r($opportunity, true) . "\n";
?>Generating API Keys
To use the EspoCRM API:
- Log in to EspoCRM as an administrator
- Go to Administration > API Users
- Create a new API user or generate an API key for an existing user
- Copy the API key and use it in your integrations
- Set appropriate permissions for the API user
Common Use Cases
1. Managing Contacts and Accounts
// Create an account (company)const account = await crm.createAccount({ name: 'Acme Corporation', type: 'Customer', industry: 'Technology', website: 'https://acme.com', billingAddress: { street: '123 Main St', city: 'New York', state: 'NY', postalCode: '10001', country: 'USA' }});
// Create a contact linked to the accountconst contact = await crm.createContact({ firstName: 'Alice', lastName: 'Williams', emailAddress: 'alice@acme.com', title: 'VP of Sales', accountId: account.id});2. Managing Sales Pipeline
// Create a leadconst lead = await crm.createLead({ firstName: 'Michael', lastName: 'Brown', status: 'New', source: 'Web Site', emailAddress: 'michael@example.com', phoneNumber: '+1-555-1234', description: 'Interested in our enterprise plan'});
// Convert lead to opportunityconst opportunity = await crm.createOpportunity({ name: 'Enterprise Plan - Michael Brown', accountName: 'Brown Industries', stage: 'Prospecting', amount: 25000, closeDate: '2024-06-30', probability: 25, leadId: lead.id});3. Task and Activity Management
// Create a taskconst response = await crm.client.post('/Task', { name: 'Follow up with client', status: 'Not Started', priority: 'High', dateStart: '2024-01-15 09:00:00', dateEnd: '2024-01-15 10:00:00', assignedUserId: 'user-id-here', parentType: 'Opportunity', parentId: 'opportunity-id-here'});
// Create a meetingconst meeting = await crm.client.post('/Meeting', { name: 'Sales Presentation', status: 'Planned', dateStart: '2024-01-20 14:00:00', dateEnd: '2024-01-20 15:00:00', assignedUserId: 'user-id-here', attendees: ['contact-id-1', 'contact-id-2']});Production Best Practices
Security Recommendations
- Strong Passwords: Use strong, unique passwords for admin accounts and database credentials. Change default passwords immediately after deployment.
- Environment Variables: Store all sensitive credentials (database passwords, API keys, SMTP credentials) as environment variables in Klutch.sh, never in your code or Dockerfile.
- HTTPS Only: Always use HTTPS for your EspoCRM instance. Klutch.sh provides SSL/TLS automatically.
- Regular Updates: Keep your EspoCRM Docker image updated to the latest stable version for security patches and bug fixes.
- API Security: Protect API keys and limit API user permissions to the minimum required for each integration.
- Role-Based Access Control: Configure user roles and permissions properly to restrict access to sensitive data.
- Two-Factor Authentication: Enable 2FA for admin accounts and critical user accounts.
- Backup Encryption: Encrypt database backups that contain sensitive customer data.
- File Upload Restrictions: Configure file upload restrictions to prevent malicious file uploads.
Performance Optimization
- Resource Allocation: Monitor your application and adjust CPU/memory based on actual usage patterns and user count.
- Database Optimization:
- Create appropriate indexes on frequently queried fields
- Regularly optimize database tables
- Monitor slow queries and optimize them
- Caching: EspoCRM includes built-in caching. Ensure adequate resources for cache operations.
- File Storage: Use persistent volumes with adequate IOPS for file operations.
- Email Processing: Configure scheduled jobs for email processing to avoid blocking the main application.
- Job Queue: Monitor background jobs and ensure they process efficiently.
- Browser Caching: Configure browser caching for static assets to reduce server load.
Backup and Recovery
- Regular Backups: Implement a backup strategy for your persistent volumes, especially
/var/www/html/datawhich contains uploaded files and configurations. - Database Backups: Schedule regular MySQL database backups:
Terminal window mysqldump -h hostname -u username -p espocrm > espocrm_backup_$(date +%Y%m%d).sql - Configuration Backups: Keep backups of your environment variables and configuration settings.
- Disaster Recovery Plan: Document your recovery procedures and test them regularly.
- Version Control: Keep your Dockerfile and configuration in version control (Git) for easy rollback.
- Backup Testing: Regularly test your backups by restoring them to a test environment.
- Backup Retention: Define and implement a backup retention policy (daily, weekly, monthly).
Monitoring and Logging
Monitor your EspoCRM instance for:
- Application Performance: Response times, page load times, and API latency
- Error Rates: Application errors, failed login attempts, and API errors
- Resource Usage: CPU, memory, disk I/O, and network usage patterns
- Database Performance: Query performance, connection pool usage, and slow queries
- User Activity: Active users, session counts, and usage patterns
- Email Delivery: Email sending success rates and bounce rates
- Background Jobs: Job queue status and processing times
- Security Events: Failed login attempts, suspicious activity, and access patterns
Scaling Considerations
- Vertical Scaling: Increase CPU and memory for your Klutch.sh instance as your team grows
- Volume Expansion: Monitor storage usage and expand volumes before reaching capacity
- Database Optimization: Regularly review and optimize database queries and indexes
- Archiving Strategy: Implement data archiving for old records to maintain performance
- User Training: Train users on best practices to optimize system usage
- Workflow Optimization: Regularly review and optimize business processes and workflows
Troubleshooting
Cannot Access EspoCRM
- Verify your app is deployed and running in the Klutch.sh dashboard
- Check that the internal port is set to 80
- Ensure HTTP traffic type is selected (not TCP)
- Review deployment logs for any startup errors
- Verify environment variables are correctly set, especially
ESPOCRM_SITE_URL
Database Connection Errors
- Verify database credentials are correct in environment variables
- Ensure database host is accessible from your Klutch.sh app
- Check that the database exists and user has proper permissions
- Verify database port (default 3306) is correct
- Review MySQL/MariaDB logs for connection issues
- Test database connectivity using MySQL client
Data Not Persisting
- Verify persistent volumes are correctly attached at the specified mount paths
- Check volume mount paths:
/var/www/html/data,/var/www/html/custom,/var/www/html/config - Ensure volumes have sufficient space allocated
- Review logs for permission or write errors
- Check that the application has write permissions to mounted directories
Email Sending Issues
- Verify SMTP environment variables are correctly set
- Test SMTP credentials with your email provider
- Check spam folders for sent emails
- Review EspoCRM logs for email sending errors (Administration > Jobs)
- Consider using a dedicated email service like SendGrid, Mailgun, or Amazon SES
- Verify SMTP port is not blocked by firewall
- Check email templates are properly configured
Performance Issues
- Monitor resource usage in the Klutch.sh dashboard
- Check database query performance in MySQL slow query log
- Review and optimize frequently used queries
- Consider increasing compute resources (CPU/RAM)
- Ensure proper indexing on database tables
- Review and optimize custom workflows and formulas
- Check background job processing efficiency
- Monitor disk I/O performance
Custom Modules Not Working
- Verify persistent volume is attached to
/var/www/html/custom - Check file permissions in the custom directory
- Review EspoCRM logs for module loading errors
- Ensure module files are correctly uploaded
- Clear cache after installing custom modules (Administration > Clear Cache)
- Verify module compatibility with your EspoCRM version
Session or Login Issues
- Check that
ESPOCRM_SITE_URLmatches your actual URL - Verify cookie settings in EspoCRM configuration
- Clear browser cache and cookies
- Check session storage in the database
- Review authentication logs for errors
- Ensure system time is synchronized
Additional Resources
- Klutch.sh Documentation
- Official EspoCRM Documentation
- EspoCRM Docker Image
- EspoCRM Installation Guide
- EspoCRM API Documentation
- Klutch.sh Volumes Guide
- Klutch.sh Networking Guide
- EspoCRM GitHub Repository
- EspoCRM Community Forum
Conclusion
Deploying EspoCRM to Klutch.sh provides a powerful, flexible CRM platform for managing customer relationships, sales pipelines, and business processes. With Docker-based deployment, persistent storage, and comprehensive configuration options, you can build a production-ready CRM system that scales with your business. By following this guide, you’ve set up a secure, high-performance EspoCRM instance ready to manage contacts, opportunities, and customer interactions with a complete suite of CRM features and powerful API integration capabilities.