Applications Azure

EspoCRM on Ubuntu 24.04 on Azure User Guide

| Product: EspoCRM on Ubuntu 24.04 LTS on Azure

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.service and espocrm-cron.timer as systemd units, enabled and active
  • 24/7 cloudimg support

EspoCRM leads list

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.

Service status and HTTPS web interface

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.

Per-VM credentials file with passwords masked

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.

Default password rejected while the per-VM administrator is accepted

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/.

EspoCRM sign-in page

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.

EspoCRM dashboard

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.

Leads list in the web interface

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.

Lead detail view

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.

Version, stack and first-boot service

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.