How to Install EspoCRM on Ubuntu 24.04 VPS: Self-Hosted Open-Source CRM
Owning your customer relationship management system means owning your pipeline data. No per-seat fees, no API throttling, no "we changed our pricing tier" emails. This guide walks you through installing EspoCRM Community Edition on an Ubuntu 24.04 VPS from a fresh SSH session to a production-ready CRM with Nginx, PHP 8.3, MariaDB, TLS, and cron-driven background jobs.
Skip the setup? Deploy a LEMP-ready VPS in one click and run EspoCRM on your own infrastructure starting at EUR 7.99/month. Launch the CloudCore Starter and follow this guide end to end.
Table of Contents
What is EspoCRM?
EspoCRM is an open-source customer relationship management platform written in PHP and licensed under the GNU GPL v3. It ships with the full set of CRM primitives you would expect: accounts, contacts, leads, opportunities, cases, calendar, email, tasks, documents, campaigns, and reports. A modern single-page-application frontend sits on top of a clean REST API, and the data model can be extended from the administration UI without touching code.
Unlike heavier Java-based suites such as SuiteCRM or vTiger, EspoCRM runs comfortably on a 1 GB VPS and installs in minutes on a standard LEMP stack. Unlike proprietary Salesforce or HubSpot, every record lives in a MariaDB database you control, and the source code is open for audit on GitHub.
Common deployment scenarios include:
- Agencies and consultancies tracking pipeline, contracts, and project handoffs across many small clients without paying per-seat SaaS fees.
- B2B sales teams running outbound sequences alongside a campaign module for cold email and nurture.
- Support desks using the Cases module with email-to-case and IMAP inbound processing.
- Internal CRMs for regulated industries (legal, healthcare, finance) where data residency and auditability outweigh the convenience of a hosted service.
- Product companies building a customer-facing portal via the Portal module and embedding EspoCRM data via its REST/GraphQL-style API.
Why Self-Host EspoCRM?
- Flat, predictable cost -- A single VPS hosts unlimited users. Going from 5 seats to 50 seats does not change your monthly bill, unlike Salesforce, HubSpot, or Pipedrive.
- Full data ownership -- Every contact, deal, email, and attachment lives in a database you can dump, encrypt, and move at will. No exports gated behind premium tiers.
- GDPR and data-residency friendly -- Pick a VPS region that matches your legal jurisdiction. No subprocessor sprawl, no cross-border transfer debates.
- Customizable to the schema level -- Add fields, entities, relationships, and layouts from the admin panel. Build complex automations with Workflows and BPM (available in Advanced Pack) without SaaS vendor lock-in.
- API-first -- The REST API exposes every entity. Integrate with Mautic, n8n, Zapier, or your own apps without paying for "API access" add-ons.
- Runs on modest hardware -- A 2 vCPU / 4 GB RAM VPS comfortably serves 20-40 active users with room for Nginx, MariaDB, and a Redis cache on the same box.
EspoCRM vs. Other Self-Hosted CRMs
| CRM | Stack | Min. RAM | Best For |
|---|---|---|---|
| EspoCRM | PHP 8.x + MariaDB + Nginx | 1 GB | Lightweight, fast install, modern SPA UI, paid packs optional |
| SuiteCRM | PHP + MySQL (heavy) | 4 GB | Sugar CRM fork, enterprise features but slower UI |
| Vtiger Open Source | PHP + MySQL | 2 GB | Traditional CRM, good module library |
| Odoo CRM | Python + PostgreSQL | 4 GB | Tight coupling with ERP/inventory if you need the full suite |
| Twenty | TypeScript + PostgreSQL | 2 GB | Modern alternative, smaller ecosystem, still maturing |
Prerequisites
Before you begin, make sure you have:
- A VPS running Ubuntu 24.04 LTS with root or sudo access
- SSH access to the server
- At least 1 GB of RAM (2 GB+ recommended for 10+ concurrent users)
- At least 10 GB of free disk space for the application, attachments, and database
- A domain name with an A record pointing to your VPS (needed for TLS)
- Port 80 and 443 open in any upstream firewall
Recommended Plan: CloudCore Starter>
For most small-team EspoCRM deployments, the CloudCore Starter plan is the right size:>
- 2 vCPU cores
- 4 GB RAM
- 60 GB NVMe SSD
- Unmetered bandwidth
- EUR 7.99/month>
This covers Nginx, PHP-FPM, MariaDB, and EspoCRM with headroom for 20-40 active users and plenty of room for attachments.
Connect to your server via SSH before running the rest of the guide:
ssh root@your-server-ipIf you are not logging in as root, prepend sudo to the commands below.
Step 1: Update System Packages
Always start with a fresh package index and security upgrades.
sudo apt update && sudo apt upgrade -yInstall a couple of utilities used throughout the rest of the guide:
sudo apt install -y unzip curl wget ca-certificates software-properties-common lsb-release gnupgIf the kernel was updated, reboot:
sudo rebootReconnect over SSH once the VPS is back online.
Step 2: Install Nginx, PHP 8.3, and MariaDB
EspoCRM 8.x runs on PHP 8.1 or newer. Ubuntu 24.04 ships PHP 8.3 in its default repositories, which is the version we will use.
Install Nginx
sudo apt install -y nginx
sudo systemctl enable --now nginxVerify Nginx is serving the default page:
curl -I http://localhostExpected output:
HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)If you are setting this up on a blank LEMP server, our LEMP stack guide covers this step in more depth.
Install PHP 8.3 and Required Extensions
EspoCRM needs a specific set of PHP extensions. Install PHP-FPM plus every extension the installer validates at startup:
sudo apt install -y php8.3-fpm php8.3-cli php8.3-common \
php8.3-mysql php8.3-mbstring php8.3-zip php8.3-curl \
php8.3-gd php8.3-xml php8.3-imap php8.3-intl \
php8.3-bcmath php8.3-exif php8.3-ldapExtension breakdown:
- mbstring, intl, xml -- multibyte string handling, internationalization, and XML parsing (used across UI, translations, imports)
- zip -- upgrade packages and import/export workflows
- curl -- outbound HTTP (webhooks, integrations, upgrade downloader)
- gd, exif -- image processing for contact photos and attachments
- mysqli, pdo_mysql -- MariaDB driver (bundled in
php8.3-mysql) - imap -- inbound email, email-to-case, and IMAP monitors
- bcmath -- high-precision currency math
- ldap -- optional, enables LDAP/Active Directory authentication (you can omit if not needed)
- json -- bundled into PHP 8.x core, no separate package required
sudo systemctl enable --now php8.3-fpm
sudo systemctl status php8.3-fpmInstall MariaDB
sudo apt install -y mariadb-server mariadb-client
sudo systemctl enable --now mariadbCheck the version (EspoCRM requires MariaDB 10.3+ or MySQL 5.7+):
mariadb --versionExpected output:
mariadb Ver 15.1 Distrib 10.11.x-MariaDB, for debian-linux-gnuFor a detailed MariaDB tuning walkthrough, see our MariaDB on Ubuntu 24.04 guide.
Step 3: Secure MariaDB and Create the Database
Run the interactive hardening script:
sudo mariadb-secure-installationAnswer the prompts as follows:
- Enter current root password: press Enter (no password on fresh install)
- Switch to unix_socket authentication:
n - Set root password:
Yand pick a strong password - Remove anonymous users:
Y - Disallow root login remotely:
Y - Remove test database:
Y - Reload privilege tables:
Y
sudo mariadb -u root -pInside the MariaDB shell:
CREATE DATABASE espocrm CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'espocrm'@'localhost' IDENTIFIED BY 'CHANGE_ME_STRONG_PASSWORD';
GRANT ALL PRIVILEGES ON espocrm.* TO 'espocrm'@'localhost';
FLUSH PRIVILEGES;
EXIT;Replace CHANGE_ME_STRONG_PASSWORD with a strong, randomly generated password. You will reuse this during the web installer step.
Step 4: Tune PHP for EspoCRM
EspoCRM's default validation flags memory_limit, max_execution_time, and post_max_size when they are below its recommended thresholds. Edit the PHP-FPM configuration:
sudo nano /etc/php/8.3/fpm/php.iniFind and update these values (use Ctrl+W to search in nano):
memory_limit = 256M
max_execution_time = 180
max_input_time = 180
post_max_size = 50M
upload_max_filesize = 50M
date.timezone = UTCSet date.timezone to match your business timezone (for example, Europe/Berlin or America/New_York) or leave it at UTC and adjust inside EspoCRM per user.
Restart PHP-FPM to apply:
sudo systemctl restart php8.3-fpmStep 5: Download and Extract EspoCRM
Download the latest stable release. Check espocrm.com/download for the current version; we use 8.4.x as the example below.
cd /tmp
wget https://www.espocrm.com/downloads/EspoCRM-8.4.0.zipExtract it into /var/www/:
sudo unzip EspoCRM-8.4.0.zip -d /var/www/
sudo mv /var/www/EspoCRM-8.4.0 /var/www/espocrmSet ownership to the web server user. On Ubuntu, both Nginx and PHP-FPM run as www-data:
sudo chown -R www-data:www-data /var/www/espocrm
sudo find /var/www/espocrm -type d -exec chmod 755 {} \;
sudo find /var/www/espocrm -type f -exec chmod 644 {} \;
sudo chmod -R 775 /var/www/espocrm/data /var/www/espocrm/custom /var/www/espocrm/client/custom /var/www/espocrm/application/Espo/ModulesThe last command ensures the directories EspoCRM writes to (cache, uploads, custom metadata) are group-writable.
Step 6: Configure the Nginx Server Block
EspoCRM uses a front-controller pattern: every request that does not map to a real file is routed through index.php. Replace crm.example.com with your actual domain below.
sudo tee /etc/nginx/sites-available/espocrm > /dev/null <<'EOF' server { listen 80; server_name crm.example.com;root /var/www/espocrm/public; index index.php;
client_max_body_size 50M;
access_log /var/log/nginx/espocrm.access.log; error_log /var/log/nginx/espocrm.error.log;
# Front-controller routing location / { try_files $uri $uri/ /index.php?$query_string; }
location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php8.3-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_read_timeout 180; }
# Block access to sensitive paths location ~ /\.(?!well-known).* { deny all; }
location ~* ^/(data|application|custom|vendor)/ { deny all; return 403; }
# Static asset caching location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf)$ { expires 30d; add_header Cache-Control "public, no-transform"; } } EOF
Enable the site and remove the default:
sudo ln -s /etc/nginx/sites-available/espocrm /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginxnginx -t must report syntax is ok and test is successful before reloading. If it does not, re-read the config file carefully -- a stray brace usually hides on the line number in the error.
For the broader Nginx tuning checklist, see our Nginx on Ubuntu 24.04 guide.
Step 7: Enable TLS with Let's Encrypt
EspoCRM transmits authentication tokens, CRM data, and potentially sensitive customer information. HTTPS is non-negotiable.
Install Certbot with the Nginx plugin:
sudo apt install -y certbot python3-certbot-nginxRequest and install the certificate (Certbot will update the Nginx server block automatically):
sudo certbot --nginx -d crm.example.com --agree-tos --redirect -m [email protected] --no-eff-emailCertbot's systemd timer handles renewals. Confirm it is active:
sudo systemctl status certbot.timerFor a deeper look at automation and wildcard certificates, see our Let's Encrypt on Ubuntu 24.04 guide.
Step 8: Run the Web Installer
Open your browser and navigate to:
https://crm.example.com/The EspoCRM installer launches automatically on first visit. Walk through each step:
memory_limit is flagged, revisit Step 4.localhost
- Database name: espocrm
- User name: espocrm
- Password: the password you set in Step 3
data/config.php, runs the initial schema rebuild, and drops you at the login screen.Log in with the admin account you just created. You are now looking at a clean EspoCRM dashboard.
Step 9: Configure the Cron Scheduler
EspoCRM relies on a per-minute cron job to run scheduled jobs: email fetching, workflow actions, notifications, reminders, cleanup tasks, and the internal job queue. Without this cron, IMAP inbound email, scheduled reports, and workflow automations will not fire.
Open the www-data crontab:
sudo crontab -u www-data -eIf prompted to select an editor, pick nano (option 1).
Add this line and save:
* cd /var/www/espocrm; /usr/bin/php -f cron.php > /dev/null 2>&1Verify the cron entry is installed:
sudo crontab -u www-data -lInside EspoCRM, go to Administration -> Scheduled Jobs after a few minutes. Each enabled job should show a recent "Last Run" timestamp. If they remain "Never", see the Troubleshooting section.
Post-Install: Email, Integrations, and Mobile
With the core CRM online, the highest-value next configuration steps are email and integrations.
Outbound SMTP (System Email Account)
Go to Administration -> Outbound Emails and enter your SMTP details. Use a transactional provider such as Mailgun, Postmark, Brevo, or your own Mailcow instance. Example settings:
- SMTP Host:
smtp.mailgun.org - SMTP Port:
587 - Authentication:
Yes - SMTP Security:
TLS - Username / Password: from your provider
Inbound IMAP (Personal and Group Inboxes)
EspoCRM can monitor IMAP mailboxes and convert incoming messages into Leads or Cases.
- Personal accounts -- Each user adds their own IMAP account from their profile page. Mail imported this way is automatically linked to matching Contacts/Leads by sender address.
- Group email accounts -- Go to Administration -> Group Email Accounts to create shared inboxes (for example,
[email protected]or[email protected]) that feed leads/cases to a team. - Case distribution rules -- Configure round-robin, least-busy, or direct-assignment rules for inbound cases on the Group Email Account record.
Google, Microsoft, and Calendar Integration
Administration -> Integrations exposes OAuth setup for:
- Google -- Gmail OAuth for IMAP/SMTP, Google Calendar two-way sync, Contacts sync
- Microsoft / Office 365 -- OAuth for Exchange Online, Outlook Calendar
- Calendar / iCal -- Generic iCal feed URL per user for read-only sync to external calendars
LDAP and SAML Single Sign-On
- LDAP / Active Directory -- Under Administration -> Authentication, switch the method to
LDAPand point EspoCRM at your directory server. Requires thephp8.3-ldapextension you installed in Step 2. - SAML SSO -- Available in the Advanced Pack. Federates authentication with Okta, Azure AD, JumpCloud, etc.
- API Keys / HMAC -- For machine-to-machine access, create dedicated API users under Administration -> API Users.
Mobile App
EspoCRM offers official iOS and Android apps. Users enter your CRM URL (https://crm.example.com) and their credentials. The apps are Community-Edition-compatible and support offline read plus most day-to-day actions.
Advanced Pack (Paid)
The official Advanced Pack adds features many teams eventually want:
- Workflow automation with conditions, actions, and scheduled triggers
- Business Process Management (BPM) designer
- Report builder with scheduled email delivery
- Formula library extensions and inventory modules (via the separate Sales Pack)
Backup and Upgrades
Daily Backup Script
Create a simple backup script that dumps the database and tars the application directory:
sudo tee /usr/local/bin/espocrm-backup.sh > /dev/null <<'EOF'
#!/bin/bash
set -e
BACKUP_DIR=/var/backups/espocrm
DATE=$(date +%Y-%m-%d)
mkdir -p "$BACKUP_DIR"
mariadb-dump -u espocrm -p'CHANGE_ME_STRONG_PASSWORD' espocrm | gzip > "$BACKUP_DIR/db-$DATE.sql.gz"
tar -czf "$BACKUP_DIR/files-$DATE.tar.gz" -C /var/www espocrm
find "$BACKUP_DIR" -type f -mtime +14 -delete
EOF
sudo chmod 700 /usr/local/bin/espocrm-backup.shSchedule it nightly:
echo "15 3 * root /usr/local/bin/espocrm-backup.sh" | sudo tee /etc/cron.d/espocrm-backupFor off-site durability, sync /var/backups/espocrm to S3, Backblaze B2, or a second VPS with rclone.
Upgrades
EspoCRM has a built-in upgrade flow. Go to Administration -> Upgrade -- if a newer release is available, the panel downloads the upgrade package, applies database migrations, and swaps files atomically. Always take a backup before clicking the upgrade button.
For manual upgrades (useful when behind a strict egress firewall), download the upgrade package from espocrm.com/upgrade, upload it via the admin panel's "Upload Upgrade Package" option, and follow the prompts.
Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
500 Internal Server Error on first load | PHP-FPM socket wrong, missing extension, or permission error | Tail logs: sudo tail -f /var/log/nginx/espocrm.error.log /var/log/php8.3-fpm.log. Verify fastcgi_pass matches the socket in /etc/php/8.3/fpm/pool.d/www.conf. |
| Installer stuck on "Permission denied" / "Cannot write to data/" | Ownership not www-data or group bits missing | sudo chown -R www-data:www-data /var/www/espocrm && sudo chmod -R 775 /var/www/espocrm/data /var/www/espocrm/custom /var/www/espocrm/client/custom |
System requirements check fails on memory_limit or max_execution_time | php.ini values not raised or FPM not restarted | Re-apply Step 4 and run sudo systemctl restart php8.3-fpm. |
| Scheduled Jobs all stay at "Never" | www-data crontab missing, or wrong path in cron line | Run sudo crontab -u www-data -l and confirm the line exists. Test manually: sudo -u www-data php -f /var/www/espocrm/cron.php. |
| Outbound email test fails with TLS error | Wrong port/security combo or blocked port 465/587 on VPS | Try port 587 with STARTTLS. Check upstream firewall allows outbound SMTP. Some providers also block port 25. |
| Inbound IMAP: "IMAP extension not loaded" | php8.3-imap missing | sudo apt install -y php8.3-imap && sudo systemctl restart php8.3-fpm |
413 Request Entity Too Large on attachment upload | client_max_body_size or upload_max_filesize too small | Raise Nginx client_max_body_size, PHP upload_max_filesize, and post_max_size to match expected attachment size. Reload both. |
| Upgrade fails halfway through | Insufficient disk, permissions mid-swap, or timeout | Check /var/www/espocrm/data/upgrades/ logs. Restore from backup, raise max_execution_time to 600, retry. |
Clean URLs work on / but /#Account/view/... 404s on deep link | Missing try_files fallback | Verify the location / block in the Nginx config uses try_files $uri $uri/ /index.php?$query_string;. Reload Nginx. |
Useful Log Locations
# EspoCRM application log
sudo tail -f /var/www/espocrm/data/logs/espo.logNginx
sudo tail -f /var/log/nginx/espocrm.error.logPHP-FPM
sudo tail -f /var/log/php8.3-fpm.logMariaDB
sudo tail -f /var/log/mysql/error.logThe EspoCRM application log at data/logs/espo.log is the single most useful diagnostic file -- it captures PHP errors, job queue failures, and integration warnings with full stack traces.
FAQ
What are the minimum system requirements for EspoCRM?
EspoCRM 8.x officially requires PHP 8.1+ (we used 8.3), MariaDB 10.3+ or MySQL 5.7+, and a standard web server (Nginx or Apache). At the VPS level, 1 GB of RAM is the floor for a handful of users; 2-4 GB is comfortable for small teams. Disk requirements start small -- the application itself is under 200 MB -- but attachments, cached PDFs, and the database grow over time. Provisioning 10 GB minimum, 60 GB for multi-year production use is a safe baseline.
Is EspoCRM Community Edition really free?
Yes. EspoCRM is released under GPL v3, which grants you the right to run, inspect, modify, and redistribute the software. There are no user caps, no feature gates on the core CRM, and no phone-home telemetry. EspoCRM's commercial business is built on optional paid extensions (Advanced Pack, Sales Pack, Real Estate, VoIP integrations) and a managed-cloud offering. If you self-host and stick to the Community Edition, you will never see an invoice from them.
How many users can one VPS support?
On a 2 vCPU / 4 GB RAM VPS, EspoCRM comfortably supports 20-40 active users. Bottlenecks appear first in PHP-FPM worker count (raise pm.max_children in /etc/php/8.3/fpm/pool.d/www.conf) and then in MariaDB. For 100+ users, move to 4 vCPU / 8 GB, split MariaDB to a dedicated server, and add a Redis cache. The single-server deployment above easily covers agencies, small sales teams, and departmental CRMs.
Can EspoCRM replace Salesforce or HubSpot?
For most small and mid-size use cases, yes. EspoCRM covers accounts, contacts, leads, opportunities, activities, campaigns, cases, documents, and reports. The Advanced Pack adds workflows, BPM, and advanced reporting that close the gap with mid-tier Salesforce editions. What EspoCRM does not ship is the massive third-party app marketplace that Salesforce and HubSpot enjoy, nor deep native marketing automation at the level of HubSpot Marketing Hub. Pair EspoCRM with Mautic (for marketing automation) and n8n (for integrations) and you have a fully self-hosted stack that competes with the mid-tier SaaS bundles at a fraction of the cost.
How do I migrate data from another CRM?
EspoCRM has a built-in Import tool at Administration -> Import that accepts CSV files for any entity. Map columns to fields, preview the import, and either create or update records. For more complex migrations (preserving activity history, notes, relationships), use the REST API with a small script. Export from your source CRM as CSV or via its API, transform to EspoCRM's schema, and POST to /api/v1/Account, /api/v1/Contact, /api/v1/Opportunity, etc. The API documentation lives at docs.espocrm.com/development/api.
Next Steps
Your EspoCRM instance is live. Here are the highest-leverage follow-ups:
- Connect Mautic for marketing automation -- Run Mautic alongside EspoCRM on the same or a separate VPS and use the Mautic-EspoCRM plugin to sync contacts and campaign results back into the CRM.
- Add n8n for no-code integrations -- Self-host n8n to connect EspoCRM to Slack, Stripe, Calendly, WhatsApp, and hundreds of other services without writing integration code.
- Set up role-based access -- Define Teams and Roles under Administration -> Users / Roles so sales, support, and leadership see only the records they should.
- Customize the data model -- Add custom entities (Projects, Subscriptions, Contracts), fields, and layouts from Administration -> Entity Manager to fit your business process instead of bending your process to a generic CRM.
- Automate with Workflows -- Install the Advanced Pack if you need conditional automations such as "when a Lead's status changes to Qualified, create an Opportunity and assign to the round-robin queue".
- Explore the developer docs -- The full EspoCRM documentation covers customization, formula scripting, custom entities, and API integration in depth.
Need a VPS That Is Ready for EspoCRM?>
Our CloudCore Starter gives you exactly the hardware profile this guide assumes -- Ubuntu 24.04, 2 vCPU, 4 GB RAM, 60 GB NVMe, full root access -- for EUR 7.99/month.>
- Deployed in under 90 seconds
- Full root / SSH access from minute one
- Daily snapshots available as an add-on
- Scale up vCPU and RAM without reprovisioning
- EU and US data centers>
Launch Your CloudCore Starter and have EspoCRM running before your next stand-up.