Op
Applications Azure

OpenEMR on Ubuntu 24.04 on Azure User Guide

| Product: OpenEMR on Ubuntu 24.04 LTS on Azure

Overview

OpenEMR is the leading free and open source Electronic Health Records and medical practice management system, used by practices, clinics and hospitals around the world. It brings together patient demographics, scheduling and the calendar, clinical encounters, prescriptions, billing and a patient portal in one web console, gated by OpenEMR's own user and access control. The cloudimg image ships OpenEMR 8.2 served by nginx and PHP 8.3 FPM on a hardened, fully patched Ubuntu 24.04 LTS base, together with a bundled local MariaDB server so the appliance is complete and useful on its own. OpenEMR runs behind an nginx reverse proxy on port 80. The bundled MariaDB listens only on the loopback interface (127.0.0.1:3306) and keeps its data, along with patient documents, on a dedicated Azure data disk. A unique administrator password is generated on the first boot of every VM, and the notorious OpenEMR default login is removed. Backed by 24/7 cloudimg support.

What is included:

  • OpenEMR 8.2 served by nginx and PHP 8.3 FPM, managed by systemd
  • A bundled MariaDB server holding the OpenEMR database, already installed and ready
  • A ready to use clinical console served on :80, with the full schema and seed data in place
  • A per VM administrator password generated on first boot and recorded in a root only file
  • No default login: the well known OpenEMR admin and pass credential is removed, the admin is set to a unique per VM secret, and no known or blank credential authenticates
  • OpenEMR post install hardening: the web installer and upgrade scripts are removed so they cannot be re run
  • MariaDB bound to 127.0.0.1 only, never exposed to the network
  • A dedicated Azure data disk carrying both the MariaDB database and OpenEMR patient documents
  • All required PHP extensions and OpenEMR's recommended PHP limits preconfigured
  • nginx.service, php8.3-fpm.service and mariadb.service as enabled systemd units
  • An unauthenticated /healthz endpoint for Azure Load Balancer health probes
  • 24/7 cloudimg support

Important: patient data and healthcare compliance

OpenEMR handles Protected Health Information (PHI). This image is a ready to run starting point, not a compliance guarantee. Before you enter any real patient information you must complete the production steps in this guide: add your own domain and TLS so the console is served over HTTPS, follow OpenEMR's own hardening guidance, and put in place the controls your jurisdiction's healthcare regulations require (for example HIPAA in the United States). You are responsible for the security, privacy and regulatory compliance of the data you store in OpenEMR.

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting point; size up for larger or busier practices. NSG inbound: allow 22/tcp from your management network and 80/tcp (and 443/tcp once you add TLS) for the console. OpenEMR serves plain HTTP on port 80 out of the box; for production, terminate TLS in front of it with your own domain before entering patient data. The bundled MariaDB is never exposed: it listens on 127.0.0.1 only, so port 3306 stays off the network.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for OpenEMR 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 HTTP (80). Review the dedicated data disk on the Disks tab, then Review + create then Create.

Step 2 - Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name openemr \
  --image <marketplace-image-urn> \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

Then open port 80 to the console:

az vm open-port --resource-group <your-rg> --name openemr --port 80

Step 3 - Confirm the services are running

SSH in as azureuser and confirm nginx, PHP FPM and MariaDB are all active. Note that MariaDB listens only on 127.0.0.1:3306 while nginx serves the console on port 80.

systemctl is-active nginx php8.3-fpm mariadb openemr-firstboot
ss -tlnp | grep -E ':80 |:3306 ' | sed 's/  */ /g'

The nginx, php8.3-fpm, mariadb and openemr-firstboot services active, with nginx on port 80 and MariaDB bound to loopback 127.0.0.1:3306

Step 4 - Retrieve the per VM administrator password

Every VM generates its own OpenEMR administrator password on first boot and writes it, along with the login user and the console URL, to a root only credentials file. Read it with sudo:

sudo cat /root/openemr-credentials.txt

The per VM OpenEMR credentials file, showing the admin login user, the generated password and the console URL, with the production PHI and compliance warning

You sign in to the console as user admin with the OPENEMR_ADMIN_PASSWORD from this file. On the box itself you can also run sudo mariadb to reach the database directly over the local socket without a password.

Step 5 - Sign in to the clinical console

Browse to http://<vm-public-ip>/. You are taken to the OpenEMR sign in page. Enter username admin and the password from Step 4, and choose your language.

The OpenEMR sign in page showing the username, password and language fields

Once signed in you land on the main clinical console. The calendar is front and centre, with the top navigation giving you access to the finder, patient records, fees, procedures, reports and administration.

The OpenEMR main clinical console showing the calendar day view, the providers panel and the top navigation for Calendar, Finder, Patient, Fees, Procedures, Admin and Reports

Step 6 - Find and add patients

Open Patient then the finder (or click Finder in the top navigation) to search your patient list by name, phone, social security number, date of birth or external identifier, or click Add New Patient to register someone. On a fresh install the list is empty and ready for your data.

The OpenEMR patient finder showing the Add New Patient action, the Patient List and Recent Patients tabs, and the search by name, home phone, SSN, date of birth and external identifier columns

Step 7 - Administration and global settings

Open Admin then Globals to reach the configuration screen. From the sections down the left (Appearance, Locale, Features, Security, Notifications, Billing, Portal and more) you control how OpenEMR looks and behaves for your practice. This is where you set your locale, tune security, and configure the patient portal and connectors.

The OpenEMR administration globals configuration screen showing the Appearance, Branding, Locale, Features, Security, Billing and Portal sections and the theme and dashboard settings

Step 8 - No known or default credentials

OpenEMR ships with a well known default administrator login (admin and pass). The cloudimg image removes it: the administrator account is set to a unique per VM secret on first boot, the default password no longer works, and the web installer and upgrade scripts are removed so they cannot be re run. You can prove the credential model with the built in round-trip check, which confirms the per VM administrator signs in through OpenEMR's own login form while the default pass and common weak guesses are all rejected:

mariadb --protocol=socket -uroot -N -e "SELECT CONCAT(username,'  (per-VM admin account)') FROM openemr.users_secure WHERE username='admin'"
sudo bash /usr/local/sbin/openemr-cred-roundtrip.sh

The admin account present in the OpenEMR users_secure table, and the round-trip check confirming the per VM admin authenticates via the OpenEMR login form while the default pass and weak guesses are rejected

Step 9 - Verify the stack and where your data lives

Confirm the OpenEMR version, the health endpoint, the dedicated data disk and the installed schema. The MariaDB database lives on the data disk mounted at /data (bind mounted onto /var/lib/mysql), and OpenEMR's patient documents, EDI and ERA directories live on the same disk, so all of your clinical data is kept separate from the operating system disk and rides with the VM:

mariadb --protocol=socket -uroot -N -e "SELECT CONCAT('OpenEMR ',v_major,'.',v_minor,'.',v_patch) FROM openemr.version"
curl -sI http://127.0.0.1/healthz | head -1
findmnt -no SOURCE,TARGET,FSTYPE,SIZE /data; findmnt -no SOURCE,TARGET /var/lib/mysql

The OpenEMR version, the healthz endpoint returning 200, the ext4 data disk mounted at /data and bind mounted onto /var/lib/mysql, and the table, user and clinical list option counts

Adding your own domain and TLS (required before entering patient data)

The appliance serves plain HTTP on port 80. Before you enter any real patient information you must serve OpenEMR over HTTPS with your own domain. Front OpenEMR with your domain and a TLS certificate, then set your site address under Admin then Globals so portal and links resolve correctly. You can terminate TLS with Azure Application Gateway, an nginx or Caddy reverse proxy, or a managed load balancer with a certificate for your domain. Open 443/tcp in your NSG and restrict 80/tcp accordingly.

Security and compliance notes

  • OpenEMR handles Protected Health Information. This image is a starting point, not a compliance guarantee. You are responsible for meeting your jurisdiction's healthcare regulations (for example HIPAA), including access controls, audit logging, encryption in transit and at rest, and business associate agreements where applicable.
  • OpenEMR serves plain HTTP on port 80. Put it behind your own TLS terminating reverse proxy or Azure Application Gateway with a certificate for your domain before handling patient data.
  • The bundled MariaDB listens on 127.0.0.1 only and is never reachable from the network. Administer it through OpenEMR or over SSH.
  • The administrator password is unique per VM and no known, default or blank credential authenticates. Keep /root/openemr-credentials.txt protected and change the password from within OpenEMR if you share access. Create individual named accounts for each clinician rather than sharing the admin login.
  • OpenEMR's web installer and upgrade scripts are removed from this image as part of its post install hardening.
  • Restrict inbound 80/tcp and 443/tcp in your NSG to the networks that need the console.

Trademark

OpenEMR is a project name used here for identification only. This image is an independent packaging of the open source OpenEMR software (licensed under the GNU General Public License, version 3) by cloudimg and is not affiliated with, sponsored by, or endorsed by the OpenEMR project or the OEMR organisation.

Support

This image is maintained by cloudimg with 24/7 support. If you need help deploying or operating OpenEMR on Azure, contact us at cloudimg.co.uk.