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

  1. Open http://your-server-ip:8080 in your browser
  2. Log in with the admin credentials you set (admin / your password)
  3. Complete the setup wizard — configure your company name, timezone, and date format
  4. Navigate to Administration → Integrations to connect email (IMAP/SMTP)

First Steps

StepWhereWhat to Do
1Administration → Outbound EmailsConfigure SMTP for sending emails
2Administration → Personal Email AccountsConnect IMAP for email tracking
3Leads or ContactsImport existing contacts from CSV
4Administration → RolesSet up user roles and permissions
5Administration → WorkflowsCreate automation rules

Key Features

EspoCRM ships with a comprehensive feature set out of the box:

ModuleWhat It Does
Contacts & AccountsPeople and organizations with custom fields, relationships, activity history
LeadsLead capture, scoring, and conversion to contacts/opportunities
OpportunitiesSales pipeline with stages, probability, and revenue forecasting
CalendarShared calendars, meeting scheduling, reminders
EmailFull email integration (IMAP/SMTP), email-to-lead conversion, mass email
Calls & MeetingsLog calls, schedule meetings, track outcomes
WorkflowsTrigger-based automation (e.g., send email when deal stage changes)
ReportsVisual reports and dashboards with charts
Knowledge BaseInternal documentation and FAQ system
StreamActivity feed showing all interactions per record

Configuration

Email Integration

EspoCRM’s email features are one of its strongest selling points. To enable them:

  1. Outbound (SMTP): Administration → Outbound Emails → add your SMTP server
  2. Personal inbox: Click your avatar → Personal Email Accounts → add IMAP
  3. 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:

  1. Administration → Entity Manager
  2. Create a new entity or extend an existing one
  3. Add custom fields (text, number, enum, multi-enum, date, currency, and more)
  4. 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:

  1. espocrm-websocket is running
  2. ESPOCRM_CONFIG_WEB_SOCKET_URL matches how users access the WebSocket (including ws:// vs wss:// for HTTPS)
  3. ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBMISSION_DSN uses the container name (tcp://espocrm-websocket:7777)
  4. 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

MetricValue
RAM (idle)~300 MB (app) + ~100 MB (daemon) + ~80 MB (websocket) + ~150 MB (MariaDB)
RAM (active, 5+ users)800 MB - 1.5 GB
CPULow-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.

Comments