This guide covers the layout and day-two configuration of the CloudSOE OpenMRS image on both AWS and Azure. It assumes you’ve finished one of the getting-started guides (AWS, Azure).

How the image is put together

Unlike our Apache-based images, OpenMRS 3 runs as the official Docker Compose deployment: a gateway container on port 80 in front of the O3 frontend, the OpenMRS backend and a MySQL database. The heavyweight database initialization was done at build time; first boot only rotated credentials and started the stack.

File locations

PathPurpose
/opt/openmrsCompose project directory
/opt/openmrs/docker-compose.ymlThe stack definition, pinned to the release that shipped in the image
/opt/openmrs/.envRelease tag plus the rotated MySQL passwords (root-only, mode 600)
/opt/openmrs/default-openmrs-credentials.txtRotated admin credentials (mode 600)
/usr/local/bin/openmrs-bootstrap-statusLive first-boot progress meter (safe to run any time)

Application data — the database and the OpenMRS data directory — lives in Docker named volumes, not in these paths.

Managing the stack

All the usual compose commands work from the project directory:

cd /opt/openmrs
sudo docker compose ps          # status of gateway, frontend, backend, db
sudo docker compose logs -f     # follow all logs (Ctrl+C to stop)
sudo docker compose restart     # restart the stack

The stack is started by the one-time openmrs-firstboot service; after its marker file (/var/lib/openmrs-firstboot.done) exists, the containers are managed by Docker’s restart handling like any compose project.

Database access

MySQL runs inside the db container. Both database passwords were rotated on first boot and live in /opt/openmrs/.env:

cd /opt/openmrs
DB_PASS=$(sudo grep '^OMRS_DB_PASSWORD=' .env | cut -d= -f2)
sudo docker compose exec db mysql -uopenmrs -p"$DB_PASS" openmrs

The backend reads its connection settings from openmrs-runtime.properties inside the openmrs-data volume — first boot keeps it in sync with the rotated password, so you shouldn’t need to touch it.

Adding TLS

The gateway serves plain HTTP on port 80 — put TLS in front before real use. Two good options:

  1. Cloud load balancer — an AWS Application Load Balancer or Azure Application Gateway with a managed certificate, forwarding to port 80 on the instance. TLS certificates, renewal and ciphers are handled for you.
  2. nginx + certbot on the host — install nginx as a reverse proxy on ports 80/443, move the gateway off port 80 (edit the published port in /opt/openmrs/docker-compose.yml), and use Let’s Encrypt with your domain.

If you terminate TLS at a load balancer, open port 443 there — the instance itself still only needs port 80 reachable from the load balancer.

Pointing a domain at your system

Create an A record for your domain pointing at the instance’s public IP (on AWS, allocate an Elastic IP first so the address survives stop/start; on Azure, set the public IP to Static). The O3 frontend uses relative URLs, so no application-side URL change is needed for basic access.

REST and FHIR APIs

The backend exposes the standard OpenMRS APIs through the gateway, authenticated with the same admin account:

curl -u admin:<password> http://<public-ip>/openmrs/ws/rest/v1/session
curl -u admin:<password> http://<public-ip>/openmrs/ws/fhir2/R4/Patient

Next steps

  • Tips & tricks — backups, updates, resource sizing and troubleshooting