Deployment guide

Romm

Overview

RomM 5.0.0 is an open source, self-hosted ROM and retro-game library manager. It scans a folder of ROMs, organizes them by platform, and enriches each game with cover art and metadata. You can browse the library, manage saves and states, and play many titles directly in the browser through the built-in EmulatorJS and Ruffle players.

This SecureAnyCloud image runs RomM on Ubuntu 24.04 LTS as the official rommapp/romm container, started on boot and restarted on failure by a systemd service. A local MariaDB database on the same VM holds all library metadata and is bound to loopback only. The upstream image bundles its own Valkey instance for background tasks. RomM serves its web UI and REST API on port 8080.

What you get:

  • 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 enabled, active systemd units
  • An empty library. No game content ships, so you add your own legally owned ROMs
  • 24/7 SecureAnyCloud 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

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting size. Size up for larger libraries and in-browser play.

Configure the network security group (NSG) to allow inbound 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 Step 10).

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 SecureAnyCloud, and select Create.

On the Basics tab, 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.

Select Review + create, then Create.

Step 2 - Deploy from the Azure CLI

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:romm-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name romm \
  --image sac1647283583153:romm-ubuntu-24-04:default:latest \
  --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 that the three units are active and that the RomM container is up:

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

All three services report active, the pinned rommapp/romm:5.0.0 container shows Up, and RomM listens on :8080 with MariaDB on loopback :3306.

Step 5 - Retrieve your per-VM credentials

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

sudo cat /root/romm-credentials.txt

Note the ROMM_URL, ROMM_ADMIN_USERNAME and ROMM_ADMIN_PASSWORD values. You use them to sign in.

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

RomM exposes an unauthenticated health endpoint and an OAuth2 token endpoint. Run the following checks to confirm that the service is healthy, that the per-VM administrator credential authenticates, and that 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.

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.

Step 8 - Add your ROMs and scan the library

The library ships empty. Copy your own legally owned ROM files onto the VM. Place 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 select Scan. RomM detects the new files, creates the platforms and imports each game. It pulls metadata where a provider is configured.

You can also confirm the imported library from the API:

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)]'

Step 9 - Browse your organized library

Return to 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.

Select a platform to open its games. There you can view details, manage saves and states, and launch supported titles in the browser.

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, do the following:

  • 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. Restart the application with sudo systemctl restart romm and check it with sudo systemctl status romm.
  • Logs. Read them with sudo docker logs romm and sudo journalctl -u romm.
  • Security updates. The OS applies security updates automatically through unattended upgrades.
  • Backups. Your library, saves and states live under /var/lib/romm. Back up this path, 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 SecureAnyCloud charge covers packaging, security patching, image maintenance and 24/7 support.

Support

SecureAnyCloud images come with 24/7 support. For questions about this RomM image or help with your deployment, contact sales@secureanycloud.com.

Deploy on Azure

Launch RomM on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure