EspoCRM on Ubuntu 24.04 on Azure User Guide
Overview
EspoCRM is a free, open source customer relationship management platform. It brings accounts, contacts, leads, opportunities, cases, calendars, email, documents and an activity stream together in one web application, with a Kanban sales pipeline, role based access control, customer portals, bulk import and export, and a full REST API. The cloudimg image delivers EspoCRM fully installed and configured on Ubuntu 24.04 — served by nginx over HTTPS with PHP 8.3 (php-fpm and OPcache), backed by MySQL 8.0. The application is already installed and the database schema built, so you land directly on the sign-in screen with no setup wizard to complete. Backed by 24/7 cloudimg support.
What is included:
- EspoCRM 10.0.3 (AGPL-3.0 licensed), served from
/var/www/espocrm/public - nginx (TLS on :443, with :80 redirected to HTTPS) + PHP 8.3 (php8.3-fpm with OPcache) + MySQL 8.0, all from Ubuntu 24.04 main
- A per-VM self-signed TLS certificate generated on first boot, so the web interface loads over a secure context
- A systemd timer (
espocrm-cron.timer) that runs EspoCRM's scheduled jobs every minute - Per-VM administrator password, MySQL password and application secret keys (
cryptKey,hashSecretKey), all generated at first boot and written to a root-only file — the image ships no known credential nginx.service,php8.3-fpm.service,mysql.serviceandespocrm-cron.timeras systemd units, enabled and active- 24/7 cloudimg support

Prerequisites
An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting point; scale up for more users or heavier workloads. NSG inbound: allow 22/tcp from your management network and 443/tcp (HTTPS) plus 80/tcp (which redirects to HTTPS) from your users.
Step 1 — Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for EspoCRM by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22) and HTTPS (443). Then Review + create and Create.
Step 2 — Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name espocrm \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name espocrm --port 443 --priority 1010
Step 3 — Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 — Confirm the services are running
The four services that back EspoCRM should all report active, the web interface answers HTTP 200 over HTTPS, and the plain HTTP port redirects to it:
systemctl is-active nginx php8.3-fpm mysql espocrm-cron.timer
curl -ks -o /dev/null -w 'web ui https -> %{http_code}\n' https://127.0.0.1/
curl -s -o /dev/null -w 'http redirect -> %{http_code}\n' http://127.0.0.1/
Expected: four lines of active, then web ui https -> 200 and http redirect -> 301.

Step 5 — Retrieve your administrator credentials
On the first boot of every VM, a one-shot service (espocrm-firstboot.service) generates credentials that are unique to that VM: a fresh administrator password, a fresh MySQL password, and fresh application secret keys (cryptKey and hashSecretKey). It also generates a per-VM self-signed TLS certificate and sets the VM's own address as the site URL. No shared or default credentials ship in the image.
sudo cat /root/espocrm-credentials.txt
The file (mode 0600, root only) contains the administrator username (espocrm.admin.user, which is admin), the administrator password (espocrm.admin.pass), the web interface URL, and the database credentials.

The image is secure by default: a blank or guessed password is rejected, while the per-VM administrator from the credentials file authenticates successfully. You can prove both from the VM's own shell against EspoCRM's REST API — each sends an Espo-Authorization header (a base64 of username:password) to /api/v1/App/user and prints the HTTP status (a successful sign-in returns 200; a rejected one returns 401):
U=$(sudo grep '^espocrm.admin.user=' /root/espocrm-credentials.txt | cut -d= -f2-)
P=$(sudo grep '^espocrm.admin.pass=' /root/espocrm-credentials.txt | cut -d= -f2-)
BAD=$(printf '%s:%s' "$U" password | base64 | tr -d '\n')
curl -ks -o /dev/null -w 'default password -> HTTP %{http_code}\n' -H "Espo-Authorization: $BAD" https://127.0.0.1/api/v1/App/user
GOOD=$(printf '%s:%s' "$U" "$P" | base64 | tr -d '\n')
curl -ks -o /dev/null -w 'per-VM admin -> HTTP %{http_code}\n' -H "Espo-Authorization: $GOOD" https://127.0.0.1/api/v1/App/user
Expected: default password -> HTTP 401 and per-VM admin -> HTTP 200.

Step 6 — Sign in to the web interface
Browse to https://<vm-public-ip>/ and sign in with the administrator username (admin) and the password from the credentials file. Because the image ships a per-VM self-signed certificate, your browser shows a one-time certificate warning on first visit — click through it, or install your own domain certificate into /etc/nginx/ssl/.

After signing in you land on the dashboard, which shows your activity stream and dashlets. From the dashboard you can jump to any part of the CRM using the navigation menu.

Step 7 — Manage your customer records
From the navigation menu you manage Accounts, Contacts, Leads, Opportunities, Cases, Calendar, Emails, Documents and more. The application ships ready for your own data: choose Leads → Create Lead, fill in the name, email, status and source, and save. Each list view supports search, filtering, inline editing, mass actions and export.

Open any record to see its full detail view, with the overview and details panels, related activities, the assigned user and team, and the stream of updates. Leads convert into an Account, Contact and Opportunity in one action, so nothing is re-keyed as a relationship progresses.

Step 8 — Confirm the version and the stack
sudo -u www-data php /var/www/espocrm/command.php version
php -r 'echo PHP_VERSION."\n";'
mysql --version
systemctl is-active espocrm-firstboot.service
Expected: EspoCRM 10.0.3, PHP 8.3.x, MySQL 8.0.x, and the first-boot service active.

First-boot service and security model
A one-shot espocrm-firstboot.service runs After=mysql.service and Before=nginx.service, so the per-VM credentials and TLS certificate are in place before the first page is ever served. It rotates the MySQL password in lock-step with EspoCRM's stored database configuration, regenerates the application cryptKey and hashSecretKey, rotates the administrator password, sets the site URL from the VM's own address, and writes the credentials file at mode 0600 (root only) before dropping a sentinel so it runs exactly once.
systemctl status espocrm-firstboot.service --no-pager | head -6
sudo stat -c '%a %U:%G %n' /root/espocrm-credentials.txt
Administration from the CLI
Admin tasks use EspoCRM's console command as the www-data user, for example to clear the cache or rebuild after a configuration change:
sudo -u www-data php /var/www/espocrm/command.php clear-cache
Common operations include rebuild (apply schema changes), app-check (health check), and config:get <param> / config:set <param> <value> to inspect and change configuration. Scheduled jobs — email sending, reminders, webhooks, cleanup — run through espocrm-cron.timer, which invokes php /var/www/espocrm/cron.php every minute, so leave that timer enabled.
Enabling HTTPS with your own domain
The image already serves HTTPS with a per-VM self-signed certificate. For production, point a real domain at the VM's public IP, open 443/tcp in the NSG, then replace the self-signed certificate with a trusted one using Let's Encrypt (replace the domain):
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.com
After the certificate is issued, set the new address as the site URL so EspoCRM generates correct absolute links in emails and notifications:
sudo -u www-data php /var/www/espocrm/command.php config:set siteUrl https://your-domain.com
sudo -u www-data php /var/www/espocrm/command.php clear-cache
Backup and maintenance
The database lives in MySQL and the application tree, including uploaded documents, under /var/www/espocrm — snapshot the OS disk in Azure for a point-in-time backup, or dump the database with (the database password is in the credentials file):
sudo mysqldump espocrm > espocrm-backup.sql
Keep the OS patched with sudo apt update && sudo apt upgrade (unattended security upgrades are enabled by default). The stack restarts cleanly with sudo systemctl restart nginx php8.3-fpm mysql espocrm-cron.timer.
Support
This image is backed by 24/7 cloudimg support. Contact us by email and chat for help with EspoCRM deployment, upgrades, data modelling, custom entities and fields, workflows, roles and access control, portals, import and export, REST API integration, email configuration, performance tuning and database administration.
All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.