EspoCRM 10.0.11
Overview
This guide shows you how to launch and use the SecureAnyCloud EspoCRM 10.0.11 on Ubuntu 24.04 AMI on Amazon EC2. The image is one software version of the SecureAnyCloud ERP and CRM listing on AWS Marketplace. You select it when you subscribe and launch.
EspoCRM is an open source customer relationship management application. It brings accounts, contacts, leads, opportunities, cases, emails, meetings, calls, tasks, a calendar, documents, a knowledge base and an activity stream together in one web application. It also provides role-based access control, customer portals, import and export, workflows through scheduled jobs and a full REST API.
What you get:
- No default login. The administrator password and EspoCRM's application keys (
cryptKey,hashSecretKey) are generated on your instance's first boot, and the password is written to/root/espocrm-credentials.txt(root only). The image ships no known password, and EspoCRM refuses blank and common passwords such asadminandpassword. - No database password. EspoCRM signs in to MySQL as the MySQL user
www-dataover the local unix socket, authenticated by the operating system (auth_socket). Only processes running as thewww-datauser get in, so there is no database password to store, leak or rotate. - No install wizard. EspoCRM is installed and its database built from the command line. The web install wizard is deleted from disk and its URL answers 404, so nobody who reaches the instance first can take it over.
- HTTPS from the first boot. nginx serves EspoCRM on port 443 with a certificate generated on your instance. Port 80 redirects to HTTPS, and requests for a host name the instance does not serve are dropped.
- Fail closed. nginx, PHP-FPM and the scheduled jobs start only after first boot has finished. If first boot cannot finish, nothing is served.
- A hardened MySQL. MySQL 8.0 listens on
127.0.0.1only, with the X protocol,LOAD DATA LOCAL, the binary log and the general query log switched off. MySQL'srootaccount works only from the instance itself (sudo mysql), and no MySQL account has a password. - Hardened defaults. nginx, PHP-FPM, MySQL, the scheduled jobs and the first-boot service are blocked from the instance metadata service, and the AMI requires IMDSv2. EspoCRM receives the configured host name and the real client address from the connection, never values a client sends.
- Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
- No firmware update timer. The
fwupd-refreshtimer is switched off (masked), because EC2 instances have no firmware it can update. Thefwupdpackage stays installed.
What is on the image: EspoCRM 10.0.11 (the upstream release, checksum verified), nginx 1.24, PHP 8.3 FPM with OPcache, MySQL 8.0 (all from Ubuntu 24.04), cloud-init and the AWS Systems Manager agent. PHP is Ubuntu's 8.3.6-0ubuntu0.24.04.13 build or later, which fixes CVE-2026-109618 and CVE-2026-109619 (USN-8948-1). Every image build checks each installed PHP package against that version and stops if one is older.
Default user: ubuntu; Architecture: x86_64; Recommended instance type: m5.large
Prerequisites
- An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route to the internet (or a private route you use for management).
- A security group that allows TCP 22 (SSH) from your admin network, and TCP 443 (EspoCRM) and TCP 80 (redirects to HTTPS) from the networks your users work from. Never open 3306, because MySQL listens on the loopback address only.
Launch the instance
In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Select EspoCRM 10.0.11 on Ubuntu 24.04 as the software version, choose your Region, and select Launch through EC2.
Choose m5.large, your key pair and the security group described above. The root volume holds the database and uploaded files, so give it room to grow, for example 30 GiB or more for a busy CRM.
Alternatively, launch with the AWS CLI. Replace the values in angle brackets:
aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
--instance-type m5.large --key-name <your-key-pair> \
--security-group-ids <your-security-group> --subnet-id <your-subnet> \
--block-device-mappings 'DeviceName=/dev/sda1,Ebs={VolumeSize=30,VolumeType=gp3}' \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=espocrm}]'First boot takes well under a minute after the instance is running.
Connect to your instance
Version SSH user
EspoCRM 10.0.11 on Ubuntu 24.04 ubuntu
ssh -i <your-key.pem> ubuntu@<public-ip>Check the services
On first boot, the instance sets the passwords, keys and certificate, and then nginx, PHP-FPM and the scheduled jobs start. Confirm that all services are active:
systemctl is-active nginx php8.3-fpm mysql espocrm-cron.timer espocrm-firstboot
sudo test -f /var/lib/sac/data/espocrm-firstboot.done && echo FIRSTBOOT_DONEAll five units are active, and the first-boot marker is present:
active active active active active FIRSTBOOT_DONEOnly SSH and nginx listen on network ports. MySQL listens on the loopback address, and PHP-FPM uses a local socket:
sudo ss -lntp | awk 'NR>1 {print $4, $6}' | grep -v '127.0.0.5' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g' | sort0.0.0.0:22 users:(("sshd"),("systemd")) 0.0.0.0:443 users:(("nginx"),("nginx"),("nginx")) 0.0.0.0:80 users:(("nginx"),("nginx"),("nginx")) 127.0.0.1:3306 users:(("mysqld")) [::]:22 users:(("sshd"),("systemd")) [::]:443 users:(("nginx"),("nginx"),("nginx")) [::]:80 users:(("nginx"),("nginx"),("nginx"))Get your URL and password
sudo cat /root/espocrm-credentials.txtOnly root can read the file:
# EspoCRM 10.0.11 - generated on first boot by espocrm-firstboot.service
# These credentials are unique to this instance; none was baked into the image. Keep this file secret. espocrm.url=https://<public-ip>/ espocrm.admin.user=admin espocrm.admin.pass=<ESPOCRM_ADMIN_PASSWORD> espocrm.db.name=espocrm espocrm.db.user=www-data
# EspoCRM signs in to MySQL as www-data over the unix socket (auth_socket): no database password exists.
# The certificate is self signed (minted on this instance): accept the browser warning once, or install
# your own. Port 80 redirects to https. Change the name EspoCRM is served as (also its siteUrl):
#
sudo espocrm-set-hostname <your-dns-name>
# MySQL listens on 127.0.0.1:3306 only; on the instance 'sudo mysql' is root over the unix socket, and
# 'sudo -u www-data mysql -u www-data espocrm' opens EspoCRM's database as the application user. # EspoCRM CLI:
sudo -u www-data php /var/www/espocrm/command.php <command>
# User guide: https://secureanycloud.com/stacks/espocrm-10-0-11/The URL uses the instance's public IP address from the EC2 instance metadata. The certificate also names the public DNS name and the private IP address, so https://<public-dns-name>/ works too.
If you stop and start the instance without an Elastic IP, the boot service picks up the new address, issues a new certificate for it and updates EspoCRM's site URL. To serve EspoCRM under your own DNS name, see Step 7.
Sign in
Browse to the URL from the credentials file. Your browser warns once about the self-signed certificate. Accept it, or install your own certificate (Step 7). Sign in as admin with the password from the credentials file.
After you sign in, you land on the home dashboard, with the navigation for accounts, contacts, leads, opportunities, activities and support on the left. Add your own users under Administration > Users and sign in as them for day-to-day work.
Work with your customer records
Choose Leads > Create Lead, fill in the name, account, status and source, and save. Every list supports search, filters, mass actions and export. A lead converts into an account, a contact and an opportunity in one action.
Use Administration to configure system settings, outbound email (SMTP), authentication options, roles and teams, scheduled jobs, currencies and extensions. Set up outbound email first, so that password recovery and notifications can reach your users.
The scheduled jobs (email sending and fetching, reminders, cleanup) run every minute from espocrm-cron.timer as the www-data user. Leave that timer enabled.
Your own DNS name and certificate
Point a DNS record at the instance. An Elastic IP keeps the address stable. Then set the name EspoCRM is served as. This command mints a new self-signed certificate for the name and updates nginx, EspoCRM's site URL (used in the links in emails) and the URL in /root/espocrm-credentials.txt. It also keeps the name across reboots:
sudo espocrm-set-hostname <your-domain>To use a certificate from a public or internal certificate authority instead, for example one issued by Let's Encrypt for <your-domain>, copy it over the generated pair and reload nginx. If you run espocrm-set-hostname again, it replaces your certificate with a self-signed one:
sudo install -m 0644 <your-domain>.crt /etc/nginx/ssl/espocrm.crt
sudo install -m 0600 <your-domain>.key /etc/nginx/ssl/espocrm.key
sudo nginx -t && sudo systemctl reload nginxSecurity checks
The shipped round-trip script signs in as the admin administrator with this instance's password. It proves that wrong, blank, admin and password passwords are refused, and it creates, reads and deletes a lead. It also checks that MySQL lets the www-data user into EspoCRM's database over the socket, while refusing the same account from any other user and refusing any password login over TCP. The script hands credentials to curl and mysql in root-only temporary files, never on a command line:
sudo bash /usr/local/sbin/espocrm-cred-roundtrip.shOK per-instance admin signs in over HTTPS (200); wrong, blank, 'admin' and 'password' refused (401); Lead create/read/delete; MySQL app user www-data: socket login as www-data only, other OS users and TCP passwords refusedNext, confirm four behaviours. The install wizard is not on disk and its URL answers 404. The API refuses requests without a login. Plain HTTP redirects to HTTPS on the configured name. A host name the instance does not serve gets no answer at all:
H=$(sudo grep '^espocrm.url=' /root/espocrm-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#') for p in / /api/v1/App/user /install/ /install/index.php; do curl -sk -o /dev/null -w "%{http_code} $p\n" --resolve "$H:443:127.0.0.1" "https://$H$p" done curl -s -o /dev/null -w 'http:// -> %{http_code} %{redirect_url}\n' --resolve "$H:80:127.0.0.1" "http://$H/" curl -sk -o /dev/null -w 'unknown host name -> %{http_code}\n' --resolve "other.example:443:127.0.0.1" https://other.example/ || true test -e /var/www/espocrm/install || echo "install wizard: not on disk"200 / 401 /api/v1/App/user 404 /install/ 404 /install/index.php http:// -> 301 https://<public-ip>/ unknown host name -> 000 install wizard: not on diskThe instance generated its own certificate, which names its own addresses:
H=$(sudo grep '^espocrm.url=' /root/espocrm-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#')
echo | openssl s_client -connect 127.0.0.1:443 -servername "$H" 2>/dev/null | openssl x509 -noout -subject -ext subjectAltNamesubject=CN = <public-ip>, O = sac X509v3 Subject Alternative Name: IP Address:<public-ip>, DNS:<public-dns-name>, IP Address:<private-ip>, IP Address:127.0.0.1, DNS:localhostNone of the services can reach the instance metadata service. Verify this with:
systemctl show nginx php8.3-fpm mysql espocrm-cron espocrm-firstboot -p Id -p IPAddressDenyIPAddressDeny=168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32 Id=nginx.service IPAddressDeny=168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32 Id=php8.3-fpm.service IPAddressDeny=168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32 Id=mysql.service IPAddressDeny=168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32 Id=espocrm-cron.service IPAddressDeny=168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32 Id=espocrm-firstboot.servicenginx hands PHP the configured host name and the client address from the connection, never values a client sends. EspoCRM's login history therefore records the real address of every sign-in:
grep -E 'fastcgi_param (HTTP_HOST|HTTPS|HTTP_X_FORWARDED_FOR|HTTP_X_REAL_IP|HTTP_FORWARDED) ' /etc/nginx/sac-espocrm-fastcgi.conffastcgi_param HTTP_HOST $espo_host; fastcgi_param HTTPS on; fastcgi_param HTTP_X_FORWARDED_FOR $remote_addr; fastcgi_param HTTP_X_REAL_IP $remote_addr; fastcgi_param HTTP_FORWARDED "";MySQL runs with the SecureAnyCloud settings. Its only accounts are the application user www-data and root, both over the unix socket with no password:
sudo mysql -e "SELECT @@bind_address, @@local_infile, @@log_bin, @@general_log; SELECT user, host, plugin FROM mysql.user WHERE user NOT LIKE 'mysql.%' ORDER BY user, host;" cat /etc/sac/espocrm-release.txt@@bind_address @@local_infile @@log_bin @@general_log 127.0.0.1 0 0 0 user host plugin root localhost auth_socket www-data localhost auth_socket sac: EspoCRM 10.0.11 (AGPL-3.0-or-later) from github.com/espocrm/espocrm releases, sha256 cdd04f7efa52a59025ef824c75b06e0a84cf986724a8c5bc4b56fcd2ce8e0ab1; install wizard removed.Versions and the command line
sudo -u www-data php /var/www/espocrm/command.php version php -r 'echo PHP_VERSION."\n";' mysqld --version nginx -v10.0.11 8.3.6 /usr/sbin/mysqld Ver 8.0.46-0ubuntu0.24.04.4 for Linux on x86_64 ((Ubuntu)) nginx version: nginx/1.24.0 (Ubuntu)EspoCRM's console runs as the www-data user. For example, run sudo -u www-data php /var/www/espocrm/command.php clear-cache. Use rebuild after a configuration change, or app-check for a health check.
Changing passwords
- EspoCRM
admin: In EspoCRM, open your own user record (your name in the top-right menu) and choose Change Password from its menu. Alternatively, run the command below on the instance. It asks for the new password at a prompt, so the password never appears on a command line. Then update or deleteespocrm.admin.passin/root/espocrm-credentials.txt:
sudo -u www-data php /var/www/espocrm/command.php set-password admin- Other users reset their own password from the sign-in page once outbound email is set up (Administration > Outbound Emails). Password recovery links always point at the configured site URL, never a host name taken from the request.
Backup and maintenance
The database lives in MySQL (/var/lib/mysql), and uploaded files live under /var/www/espocrm/data/upload. The simplest backup is an EBS snapshot of the root volume. To take a logical backup of the database while EspoCRM is running, use:
sudo mysqldump --single-transaction --routines --triggers espocrm | gzip > <backup-dir>/espocrm-$(date +%F).sql.gz
sudo tar -czf <backup-dir>/espocrm-files-$(date +%F).tar.gz -C /var/www/espocrm data/upload customOperating system, nginx, PHP and MySQL security updates install automatically from Ubuntu. Run sudo apt-get update && sudo apt-get upgrade to apply everything else. To upgrade EspoCRM itself, use Administration > Upgrade or run sudo -u www-data php /var/www/espocrm/command.php upgrade. Take a snapshot first.
Component Path
EspoCRM /var/www/espocrm (web root /var/www/espocrm/public)
EspoCRM configuration /var/www/espocrm/data/config.php, config-internal.php (www-data only)
MySQL settings /etc/mysql/mysql.conf.d/99-sac-espocrm.cnf
nginx site /etc/nginx/sites-available/sac-espocrm
Certificate and key /etc/nginx/ssl/
Scheduled jobs espocrm-cron.timer / espocrm-cron.service
Boot service /usr/local/sbin/espocrm-firstboot.sh
Host name helper /usr/local/sbin/espocrm-set-hostname
Credentials /root/espocrm-credentials.txt (mode 0600)
Security recommendations
- Allow port 22 from your admin network only, and allow ports 80 and 443 only from the networks your users work from. Never open 3306 to the internet.
- Use your own DNS name and a certificate your browsers trust (Step 7).
- Create a named user for each person with a role that limits what they can see, and keep
adminfor administration. - Turn on two-factor authentication under Administration > Authentication. Change the admin password if it may have been shared (Step 10). Keep the operating system patched, and snapshot the volume regularly.
- EspoCRM 10.0.11 is the newest release at build time. One published advisory still applies to it: GHSA-r277-qh74-r86f (medium). A user who can edit PDF templates can show image attachments they could not otherwise open, if they know the attachment ID. The issue is fixed in EspoCRM 10.1.0. Until you upgrade (Step 11), give edit access to PDF templates only to administrators, which is the EspoCRM default for new roles.
Support and licensing
EspoCRM is open source software licensed under the GNU Affero General Public License version 3 or later, with the additional term that its user interface keeps showing the "EspoCRM" name. SecureAnyCloud ships it unmodified. There is no per-user licence fee. The AMI price covers SecureAnyCloud's hardening, first-boot setup and support.
EspoCRM is a trademark of its owner. SecureAnyCloud is not affiliated with or endorsed by EspoCRM, Inc.
- Email: sales@secureanycloud.com
- Website: https://secureanycloud.com
- Support: 24/7, with a 24-hour response SLA
Deploy on AWS
Launch EspoCRM 10.0.11 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com