Self-Hosting EspoCRM with Docker Compose
What Is EspoCRM?
EspoCRM is a mature open-source CRM that handles contacts, accounts, leads, opportunities, email integration, calendar, and workflow automation. It’s been around since 2014 and has a significantly more polished UI than most open-source CRM alternatives. Think of it as a practical Salesforce replacement for small to mid-size teams — it does 80% of what Salesforce does at 0% of the cost.
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- 1 GB of free RAM (2 GB recommended for 5+ concurrent users)
- 5 GB of free disk space
- A domain name (required for email integration and WebSocket)
Docker Compose Configuration
EspoCRM needs four services: the main app, a background job daemon, a WebSocket server (optional but recommended), and MariaDB. All three EspoCRM services share the same Docker image with different entrypoints.
Create a docker-compose.yml:
services:
espocrm:
image: espocrm/espocrm:9.3.3
container_name: espocrm
depends_on:
espocrm-db:
condition: service_healthy
environment:
ESPOCRM_DATABASE_PLATFORM: Mysql
ESPOCRM_DATABASE_HOST: espocrm-db
ESPOCRM_DATABASE_USER: espocrm
ESPOCRM_DATABASE_PASSWORD: changeme_strong_password # CHANGE — must match DB
ESPOCRM_ADMIN_USERNAME: admin
ESPOCRM_ADMIN_PASSWORD: changeme_admin_password # CHANGE
ESPOCRM_SITE_URL: "http://localhost:8080" # CHANGE to your public URL
volumes:
- espocrm-data:/var/www/html # App files, config, uploads
ports:
- "8080:80" # Web UI
restart: unless-stopped
espocrm-daemon:
image: espocrm/espocrm:9.3.3
container_name: espocrm-daemon
entrypoint: docker-daemon.sh
volumes:
- espocrm-data:/var/www/html # Must share volume with main app
restart: unless-stopped
espocrm-websocket:
image: espocrm/espocrm:9.3.3
container_name: espocrm-websocket
entrypoint: docker-websocket.sh
environment:
ESPOCRM_CONFIG_USE_WEB_SOCKET: "true"
ESPOCRM_CONFIG_WEB_SOCKET_URL: "ws://localhost:8081"
ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBSCRIBER_DSN: "tcp://*:7777"
ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBMISSION_DSN: "tcp://espocrm-websocket:7777"
volumes:
- espocrm-data:/var/www/html # Must share volume with main app
ports:
- "8081:8080" # WebSocket for real-time updates
restart: unless-stopped
espocrm-db:
image: mariadb:11.7
container_name: espocrm-db
environment:
MARIADB_ROOT_PASSWORD: changeme_root_password # CHANGE
MARIADB_DATABASE: espocrm
MARIADB_USER: espocrm
MARIADB_PASSWORD: changeme_strong_password # CHANGE — must match app
volumes:
- espocrm-db-data:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 20s
start_period: 10s
timeout: 10s
retries: 3
restart: unless-stopped
volumes:
espocrm-data:
espocrm-db-data:
Before starting: Change all changeme passwords. Update ESPOCRM_SITE_URL to your actual access URL — this is critical for email links, calendar invites, and API responses.
docker compose up -d
Initial Setup
- Open
http://your-server-ip:8080in your browser - Log in with the admin credentials you set (
admin/ your password) - Complete the setup wizard — configure your company name, timezone, and date format
- Navigate to Administration → Integrations to connect email (IMAP/SMTP)
First Steps
| Step | Where | What to Do |
|---|---|---|
| 1 | Administration → Outbound Emails | Configure SMTP for sending emails |
| 2 | Administration → Personal Email Accounts | Connect IMAP for email tracking |
| 3 | Leads or Contacts | Import existing contacts from CSV |
| 4 | Administration → Roles | Set up user roles and permissions |
| 5 | Administration → Workflows | Create automation rules |
Key Features
EspoCRM ships with a comprehensive feature set out of the box:
| Module | What It Does |
|---|---|
| Contacts & Accounts | People and organizations with custom fields, relationships, activity history |
| Leads | Lead capture, scoring, and conversion to contacts/opportunities |
| Opportunities | Sales pipeline with stages, probability, and revenue forecasting |
| Calendar | Shared calendars, meeting scheduling, reminders |
| Full email integration (IMAP/SMTP), email-to-lead conversion, mass email | |
| Calls & Meetings | Log calls, schedule meetings, track outcomes |
| Workflows | Trigger-based automation (e.g., send email when deal stage changes) |
| Reports | Visual reports and dashboards with charts |
| Knowledge Base | Internal documentation and FAQ system |
| Stream | Activity feed showing all interactions per record |
Configuration
Email Integration
EspoCRM’s email features are one of its strongest selling points. To enable them:
- Outbound (SMTP): Administration → Outbound Emails → add your SMTP server
- Personal inbox: Click your avatar → Personal Email Accounts → add IMAP
- Group inbox: Administration → Group Email Accounts → add a shared inbox (e.g., sales@yourcompany.com)
Emails automatically link to contacts based on email address matching.
Custom Fields and Entities
EspoCRM’s entity manager lets you create custom record types and fields without writing code:
- Administration → Entity Manager
- Create a new entity or extend an existing one
- Add custom fields (text, number, enum, multi-enum, date, currency, and more)
- Define relationships between entities
Workflow Automation
Navigate to Administration → Workflows to create automation rules:
- Trigger types: After record created, after record updated, scheduled, sequential
- Actions: Send email, create record, update record, notify users, execute formula
- Conditions: Filter which records trigger the workflow
Example: automatically send a follow-up email 3 days after a deal enters “Proposal Sent” stage.
Reverse Proxy
For production with HTTPS, update your compose and reverse proxy configuration.
Update ESPOCRM_SITE_URL to your HTTPS domain:
ESPOCRM_SITE_URL: "https://crm.example.com"
For the WebSocket URL:
ESPOCRM_CONFIG_WEB_SOCKET_URL: "wss://crm.example.com/ws"
Caddy example (handling both HTTP and WebSocket):
crm.example.com {
reverse_proxy localhost:8080
handle /ws {
reverse_proxy localhost:8081
}
}
See our Reverse Proxy Guide for Nginx Proxy Manager and Traefik configurations.
Backup
Back up the database and application volume:
# Database dump
docker exec espocrm-db mariadb-dump -u root -p'your_root_password' espocrm > espocrm-backup-$(date +%Y%m%d).sql
# Application data (config, uploads, extensions)
docker run --rm -v espocrm-data:/data -v $(pwd):/backup \
alpine tar czf /backup/espocrm-data-$(date +%Y%m%d).tar.gz /data
Restore:
cat espocrm-backup-20260224.sql | docker exec -i espocrm-db mariadb -u root -p'your_root_password' espocrm
See our Backup Strategy Guide for automated approaches.
Troubleshooting
Scheduled Jobs Not Running
Symptom: Emails not being fetched, workflows not triggering, notifications not sent.
Fix: The espocrm-daemon service must be running. It handles all background jobs:
docker ps | grep espocrm-daemon
docker logs espocrm-daemon
The daemon must share the same volume as the main app (espocrm-data:/var/www/html). If the volume isn’t shared, the daemon can’t access the application code.
WebSocket Connection Failed
Symptom: Browser console shows WebSocket connection errors. UI doesn’t update in real-time.
Fix: Check that:
espocrm-websocketis runningESPOCRM_CONFIG_WEB_SOCKET_URLmatches how users access the WebSocket (includingws://vswss://for HTTPS)ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBMISSION_DSNuses the container name (tcp://espocrm-websocket:7777)- Port 8081 is accessible (or routed through your reverse proxy)
Email Sending Fails
Symptom: Outbound emails stuck in queue, no delivery.
Fix: Check SMTP settings in Administration → Outbound Emails. Test with the “Send Test Email” button. Common issues:
- Wrong port (use 587 for STARTTLS, 465 for SSL)
- Authentication required but not configured
- Firewall blocking outbound SMTP
ESPOCRM_SITE_URL Mismatch
Symptom: Login redirects loop, links in emails point to the wrong URL, API calls fail.
Fix: ESPOCRM_SITE_URL must exactly match the URL users type in their browser. If behind a reverse proxy with HTTPS, it must be https://your-domain.com — not http://localhost:8080. After changing, restart the container.
Resource Requirements
| Metric | Value |
|---|---|
| RAM (idle) | ~300 MB (app) + ~100 MB (daemon) + ~80 MB (websocket) + ~150 MB (MariaDB) |
| RAM (active, 5+ users) | 800 MB - 1.5 GB |
| CPU | Low-Medium |
| Disk | ~500 MB for application + database growth |
Verdict
EspoCRM is the most mature and feature-complete self-hosted CRM you can deploy today. The email integration is genuinely useful (not a checkbox feature), workflow automation covers real business processes, and the entity manager means you can customize it without touching code. It’s been actively developed since 2014 — the kind of stability that matters when you’re putting customer data into a system.
The main drawback is that the UI, while functional, isn’t as modern as newer alternatives like Twenty CRM. If you care more about a polished developer experience and GraphQL APIs, Twenty is worth looking at. But for raw CRM capability — lead management, email tracking, workflow automation, reporting — EspoCRM has years of refinement that newer tools haven’t matched yet.
Frequently Asked Questions
How does EspoCRM compare to Salesforce?
EspoCRM covers about 80% of Salesforce’s core CRM functionality — contacts, leads, opportunities, email integration, workflows, and reporting — at zero cost. What you lose: Salesforce’s AppExchange ecosystem, advanced AI scoring, and enterprise-scale multi-org support. For small to mid-size teams (<100 users), EspoCRM handles the same workflows.
Can EspoCRM integrate with my existing email?
Yes. EspoCRM has deep email integration via IMAP (incoming) and SMTP (outgoing). Emails are automatically linked to contacts based on address matching. You can set up personal email accounts per user and group/shared inboxes. Works with Gmail, Outlook, or any IMAP/SMTP provider.
Does EspoCRM support LDAP or SSO?
Yes. LDAP/Active Directory authentication is supported natively under Administration → Authentication. This means agents can log in with their existing corporate credentials. OAuth2-based SSO requires a third-party module or custom integration.
How many users can EspoCRM handle?
The free version has no user limits. With the Docker Compose setup above (1-2 GB RAM), 10-20 concurrent users is comfortable. For 50+ concurrent users, increase RAM to 4+ GB and consider MySQL replication for read performance.
Can I migrate from another CRM to EspoCRM?
EspoCRM supports CSV import for contacts, accounts, leads, and opportunities. For Salesforce migrations, export your data as CSV from Salesforce and import into EspoCRM. The entity manager lets you create matching custom fields before import. There’s no automated one-click migration tool.
What’s the difference between EspoCRM and SuiteCRM?
SuiteCRM is a fork of SugarCRM with a Salesforce-like interface and more features (campaigns, projects, contracts). EspoCRM has a cleaner UI, better email integration, and is lighter on resources. EspoCRM is better for teams focused on sales pipeline and email; SuiteCRM is better if you need marketing campaigns and project management built in.
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments