Ro
Applications Azure

RomM on Ubuntu 24.04 on Azure User Guide

| Product: RomM on Ubuntu 24.04 LTS on Azure

Overview

This image runs RomM 5.0.0, the open source self-hosted ROM and retro-game library manager, on Ubuntu 24.04 LTS. RomM scans a folder of ROMs, organizes them by platform, enriches each game with cover art and metadata, and lets you browse, manage saves and states, and play many titles directly in the browser through the built-in EmulatorJS and Ruffle players.

The pinned upstream application is run as the official rommapp/romm container under a systemd service that starts it on boot and restarts it on failure, backed by a local MariaDB database on the same VM. The upstream image bundles its own Valkey instance for background tasks. RomM serves its web UI and REST API on port 8080. MariaDB is bound to loopback only and holds all library metadata.

What is included:

  • RomM 5.0.0 (official rommapp/romm image, pinned by digest), run by systemd
  • The RomM web UI and REST API on :8080
  • A per-VM administrator account generated on first boot and recorded in a root-only file
  • A per-VM MariaDB password and a per-VM application secret key generated on first boot
  • MariaDB, bound to loopback, holding platforms, games, users, saves and states
  • mariadb.service, docker.service and romm.service as systemd units, enabled and active
  • An empty library — no game content ships; you add your own legally owned ROMs
  • 24/7 cloudimg support

RomM is licensed under the GNU AGPL-3.0 and is shipped here unmodified. The exact upstream Corresponding Source for the pinned release is published at github.com/rommapp/romm (tag 5.0.0).

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 libraries and in-browser play. NSG inbound: allow 22/tcp from your management network and 8080/tcp for the web UI. RomM serves plain HTTP on port 8080; for production, front it with your own domain and TLS (see the final step).

You are responsible for supplying only game content you are legally entitled to use. The image ships with an empty library and no ROMs of any kind.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for RomM 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 8080. Then Review + create then Create.

Step 2 - Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name romm \
  --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 romm --port 8080 --priority 1010

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

RomM, MariaDB and Docker start automatically on first boot. Confirm the three units are active and the RomM container is up:

systemctl is-active mariadb docker romm
docker ps --format 'table {{.Names}}\t{{.Status}}'
ss -tln | grep -E ':8080 |:3306 '

You should see all three services active, the pinned rommapp/romm:5.0.0 container Up, and RomM listening on :8080 with MariaDB on loopback :3306.

mariadb, docker and the pinned rommapp/romm container active, with RomM listening on 8080 and MariaDB bound to loopback 3306

Step 5 - Retrieve your per-VM credentials

On the first boot of every instance, RomM generates a unique administrator account, a unique MariaDB password and a unique application secret key. The administrator credentials are written to a root-only file:

sudo cat /root/romm-credentials.txt

Note the ROMM_URL, ROMM_ADMIN_USERNAME and ROMM_ADMIN_PASSWORD — you will use them to sign in.

The per-VM RomM credentials file with the web UI URL, the administrator username and the administrator password (redacted)

Step 6 - Confirm the API health and administrator sign-in

RomM exposes an unauthenticated health endpoint and an OAuth2 token endpoint. Confirm the service is healthy and that the per-VM administrator credential authenticates (while a wrong password is rejected):

curl -s -o /dev/null -w 'heartbeat: %{http_code}\n' http://127.0.0.1:8080/api/heartbeat

U=$(sudo grep '^ROMM_ADMIN_USERNAME=' /root/romm-credentials.txt | cut -d= -f2-)
P=$(sudo grep '^ROMM_ADMIN_PASSWORD=' /root/romm-credentials.txt | cut -d= -f2-)

echo -n 'wrong password rejected: '
curl -s -o /dev/null -w '%{http_code}\n' -X POST http://127.0.0.1:8080/api/token \
  --data-urlencode grant_type=password --data-urlencode "username=$U" --data-urlencode 'password=wrong'

echo -n 'admin token accepted: '
curl -s -o /dev/null -w '%{http_code}\n' -X POST http://127.0.0.1:8080/api/token \
  --data-urlencode grant_type=password --data-urlencode "username=$U" --data-urlencode "password=$P" \
  --data-urlencode 'scope=me.read'

The health check returns 200, the wrong password is rejected with 401, and the per-VM administrator credential is accepted with 200.

The RomM health endpoint returning 200, a wrong password rejected with 401 and the per-VM administrator credential accepted with 200

Step 7 - Sign in to the web UI

Open http://<vm-public-ip>:8080 in a browser. Sign in with the ROMM_ADMIN_USERNAME and ROMM_ADMIN_PASSWORD from Step 5.

The RomM web UI sign-in page

Step 8 - Add your ROMs and scan the library

The library ships empty. Copy your own legally owned ROM files onto the VM, placing each system's files under its platform folder in the library:

/var/lib/romm/library/roms/<platform>/<your-rom-file>

For example, Nintendo Entertainment System files go under roms/nes/, Game Boy under roms/gb/, and so on (RomM recognizes the standard platform slugs). Then open the Scan page in the web UI, choose All platforms and Quick scan, and click Scan. RomM detects the new files, creates the platforms, and imports each game, pulling metadata where a provider is configured.

The RomM Scan page with the platform, metadata-provider and scan-type options and the live-progress panel

You can confirm the imported library from the API as well:

U=$(sudo grep '^ROMM_ADMIN_USERNAME=' /root/romm-credentials.txt | cut -d= -f2-)
P=$(sudo grep '^ROMM_ADMIN_PASSWORD=' /root/romm-credentials.txt | cut -d= -f2-)
AT=$(curl -s -X POST http://127.0.0.1:8080/api/token \
  --data-urlencode grant_type=password --data-urlencode "username=$U" --data-urlencode "password=$P" \
  --data-urlencode 'scope=platforms.read' | python3 -c 'import sys,json;print(json.load(sys.stdin)["access_token"])')
curl -s -H "Authorization: Bearer $AT" http://127.0.0.1:8080/api/platforms \
  | python3 -c 'import sys,json;[print(p["name"],"->",p.get("rom_count"),"roms") for p in json.load(sys.stdin)]'

The organized library shown through the RomM API: platforms with their game counts

Step 9 - Browse your organized library

Back on the Home page, RomM shows your library stats, a recently-added shelf and your platforms. The Platforms page lists each system with its game count, and clicking through opens the games for that platform where you can view details, manage saves and states, and launch supported titles in the browser.

The RomM home page after a scan, showing library stats, a recently-added game and the platform shelf

The RomM Platforms page showing an organized platform with its game count

Step 10 - Production hardening

RomM serves plain HTTP on port 8080 and points browsers at ROMM_BASE_URL, which is set to this VM's public address on every boot. For production:

  • Put RomM behind your own domain and a TLS-terminating reverse proxy or Azure Application Gateway, and restrict 8080/tcp in the NSG to your proxy.
  • Set ROMM_BASE_URL in /etc/romm/romm.env to your public HTTPS URL and restart with sudo systemctl restart romm.
  • Keep SSH (22/tcp) restricted to your management network.
  • Configure metadata providers (IGDB, ScreenScraper, SteamGridDB, RetroAchievements) in the web UI to enrich your library with cover art and metadata.

Maintenance

  • Service control: sudo systemctl restart romm (the application), sudo systemctl status romm.
  • Logs: sudo docker logs romm and sudo journalctl -u romm.
  • The OS applies security updates automatically via unattended-upgrades.
  • Your library, saves and states live under /var/lib/romm; back this path up, along with a MariaDB dump, to preserve your collection.

Source and licensing

RomM is free and open source under the GNU AGPL-3.0 and is shipped here unmodified. The complete Corresponding Source for the exact pinned release is available at github.com/rommapp/romm (tag 5.0.0). The cloudimg charge covers packaging, security patching, image maintenance and 24/7 support.

Support

cloudimg provides 24/7 support for this image. Contact us at support@cloudimg.co.uk.