From 4e4b7c0c66557ab153883e8b545fb2db88345355 Mon Sep 17 00:00:00 2001 From: patrick Date: Thu, 16 Jul 2026 19:56:22 -0400 Subject: [PATCH] add romm role --- roles/romm/README.md | 76 +++++++++++++++++++++++++++++ roles/romm/defaults/main.yml | 50 +++++++++++++++++++ roles/romm/meta/main.yml | 25 ++++++++++ roles/romm/templates/.env.j2 | 43 ++++++++++++++++ roles/romm/templates/compose.yml.j2 | 41 ++++++++++++++++ 5 files changed, 235 insertions(+) create mode 100644 roles/romm/README.md create mode 100644 roles/romm/defaults/main.yml create mode 100644 roles/romm/meta/main.yml create mode 100644 roles/romm/templates/.env.j2 create mode 100644 roles/romm/templates/compose.yml.j2 diff --git a/roles/romm/README.md b/roles/romm/README.md new file mode 100644 index 0000000..f707b32 --- /dev/null +++ b/roles/romm/README.md @@ -0,0 +1,76 @@ +# RomM + +Deploy RomM (Rom Manager) using Docker Compose. + +## Description + +RomM is a self-hosted ROM manager and player for retro game libraries, with metadata scraping from ScreenScraper, RetroAchievements, SteamGridDB, and Hasheous. + +## Variables + +### Required + +| Variable | Default | Description | +|----------|---------|-------------| +| `romm_db_password` | `""` | MariaDB password for the RomM user | +| `romm_db_root_password` | `""` | MariaDB root password | +| `romm_auth_secret_key` | `""` | Auth secret; generate with `openssl rand -hex 32` | +| `romm_library_path` | `{{ app_dir }}/library` | Host path holding the ROM library | + +### Optional — Deployment + +| Variable | Default | Description | +|----------|---------|-------------| +| `romm_http_port` | `8080` | Web interface port | +| `romm_container_version` | `latest` | RomM image tag | +| `romm_db_container_version` | `latest` | MariaDB image tag | +| `romm_assets_path` | `{{ app_dir }}/assets` | Uploaded saves, states, screenshots | +| `romm_config_path` | `{{ app_dir }}/config` | Location of `config.yml` | +| `romm_resources_path` | `{{ app_dir }}/resources` | Fetched metadata (covers, screenshots) | +| `romm_mysql_data_path` | `{{ app_dir }}/mysql-data` | MariaDB data directory | +| `romm_redis_data_path` | `""` | Optional host path to persist RomM's in-container Redis cache. Leave empty to use the ephemeral default. | +| `romm_db_name` | `romm` | MariaDB database name | +| `romm_db_user` | `romm-user` | MariaDB username | + +### Optional — Metadata providers + +All metadata providers are optional. See the [RomM metadata providers docs](https://docs.romm.app/latest/getting-started/metadata-providers) for how to obtain credentials. Empty credentials and disabled toggles are omitted from the rendered `.env` — no need to null out unused providers. + +| Variable | Default | Description | +|----------|---------|-------------| +| `romm_igdb_client_id` | `""` | IGDB client ID | +| `romm_igdb_client_secret` | `""` | IGDB client secret | +| `romm_screenscraper_user` | `""` | ScreenScraper username | +| `romm_screenscraper_password` | `""` | ScreenScraper password | +| `romm_mobygames_api_key` | `""` | MobyGames API key (paid subscription) | +| `romm_launchbox_api_enabled` | `false` | Enable the LaunchBox provider | +| `romm_launchbox_scheduled_update_enabled` | `false` | Enable scheduled LaunchBox metadata refresh | +| `romm_launchbox_scheduled_update_cron` | `""` | Cron expression for the LaunchBox refresh (defaults to RomM's built-in schedule when unset) | +| `romm_hasheous_api_enabled` | `true` | Enable the Hasheous provider | +| `romm_playmatch_api_enabled` | `false` | Enable the Playmatch provider | +| `romm_steamgriddb_api_key` | `""` | SteamGridDB API key | +| `romm_retroachievements_api_key` | `""` | RetroAchievements API key | +| `romm_flashpoint_api_enabled` | `false` | Enable the Flashpoint provider | +| `romm_hltb_api_enabled` | `false` | Enable the HowLongToBeat provider | + +By default, backups include `assets`, `config`, `resources`, and `mysql-data`. The `library` directory is excluded (typically large and often on separate storage), and the Redis cache is not mounted at all by default (RomM's built-in Redis is ephemeral). Override `app_backup_subdirectories` to change this. + +Runtime environment variables for the `romm` service are rendered to `{{ app_dir }}/.env` (loaded via `env_file:` in the compose file), so the compose file itself stays short. The `romm-db` service reads the three shared DB values (`DB_NAME`, `DB_USER`, `DB_PASSWD`) from the same `.env` via compose's `${VAR}` interpolation, so there's a single source of truth for the DB credentials. `MARIADB_ROOT_PASSWORD` stays inline in the compose file — it's DB-only and shouldn't be injected into the RomM container. `app_compose_validate` is disabled because compose validation runs against a temp path where the `.env` isn't co-located. + +## Example + +```yaml +- role: patrickj.docker_apps.romm + vars: + romm_http_port: 8080 + romm_library_path: /mnt/storage/roms + romm_db_password: "{{ vault_romm_db_password }}" + romm_db_root_password: "{{ vault_romm_db_root_password }}" + romm_auth_secret_key: "{{ vault_romm_auth_secret_key }}" + romm_igdb_client_id: "{{ vault_romm_igdb_client_id }}" + romm_igdb_client_secret: "{{ vault_romm_igdb_client_secret }}" + romm_screenscraper_user: "{{ vault_romm_screenscraper_user }}" + romm_screenscraper_password: "{{ vault_romm_screenscraper_password }}" + romm_retroachievements_api_key: "{{ vault_romm_retroachievements_api_key }}" + romm_steamgriddb_api_key: "{{ vault_romm_steamgriddb_api_key }}" +``` diff --git a/roles/romm/defaults/main.yml b/roles/romm/defaults/main.yml new file mode 100644 index 0000000..c047172 --- /dev/null +++ b/roles/romm/defaults/main.yml @@ -0,0 +1,50 @@ +--- +app_name: romm + +# Container configuration +romm_container_name: "{{ app_name | default('romm') }}" +romm_container_version: latest +romm_db_container_name: "{{ app_name | default('romm') }}-db" +romm_db_container_version: latest +romm_restart_policy: "{{ app_restart_policy | default('unless-stopped') }}" + +# Network configuration +romm_http_port: 8080 + +# Volume paths +romm_library_path: "{{ app_dir }}/library" +romm_assets_path: "{{ app_dir }}/assets" +romm_config_path: "{{ app_dir }}/config" +romm_resources_path: "{{ app_dir }}/resources" +romm_mysql_data_path: "{{ app_dir }}/mysql-data" +# Optional: persist the in-container Redis cache to a host path. +# Leave empty to use RomM's built-in ephemeral Redis (default). +romm_redis_data_path: "" + +# Database configuration +romm_db_name: romm +romm_db_user: romm-user +romm_db_password: "" +romm_db_root_password: "" + +# Auth +# Generate romm_auth_secret_key with: openssl rand -hex 32 +romm_auth_secret_key: "" + +# Metadata providers +# All providers are optional; RomM ignores empty credentials and disabled toggles. +# See https://docs.romm.app/latest/getting-started/metadata-providers +romm_igdb_client_id: "" +romm_igdb_client_secret: "" +romm_screenscraper_user: "" +romm_screenscraper_password: "" +romm_mobygames_api_key: "" # paid subscription required +romm_launchbox_api_enabled: false +romm_launchbox_scheduled_update_enabled: false +romm_launchbox_scheduled_update_cron: "" +romm_hasheous_api_enabled: true +romm_playmatch_api_enabled: false +romm_steamgriddb_api_key: "" +romm_retroachievements_api_key: "" +romm_flashpoint_api_enabled: false +romm_hltb_api_enabled: false diff --git a/roles/romm/meta/main.yml b/roles/romm/meta/main.yml new file mode 100644 index 0000000..ff4620a --- /dev/null +++ b/roles/romm/meta/main.yml @@ -0,0 +1,25 @@ +--- +galaxy_info: + author: Patrick Jaroszewski + description: Deploy RomM with Docker Compose + license: MIT + +dependencies: + - role: patrickj.docker_apps.docker_compose_app + vars: + app_role_name: romm + app_subdirectories: >- + {{ + [romm_library_path, romm_assets_path, romm_config_path, + romm_resources_path, romm_mysql_data_path] + + ([romm_redis_data_path] if romm_redis_data_path else []) + }} + app_backup_subdirectories: + - "{{ romm_assets_path }}" + - "{{ romm_config_path }}" + - "{{ romm_resources_path }}" + - "{{ romm_mysql_data_path }}" + app_extra_templates: + - src: "{{ app_templates_path }}/.env.j2" + dest: "{{ app_dir }}/.env" + app_compose_validate: false diff --git a/roles/romm/templates/.env.j2 b/roles/romm/templates/.env.j2 new file mode 100644 index 0000000..2ea4fb9 --- /dev/null +++ b/roles/romm/templates/.env.j2 @@ -0,0 +1,43 @@ +DB_HOST={{ romm_db_container_name }} +DB_NAME={{ romm_db_name }} +DB_USER={{ romm_db_user }} +DB_PASSWD={{ romm_db_password }} +ROMM_AUTH_SECRET_KEY={{ romm_auth_secret_key }} +{% if romm_igdb_client_id %} +IGDB_CLIENT_ID={{ romm_igdb_client_id }} +IGDB_CLIENT_SECRET={{ romm_igdb_client_secret }} +{% endif %} +{% if romm_screenscraper_user %} +SCREENSCRAPER_USER={{ romm_screenscraper_user }} +SCREENSCRAPER_PASSWORD={{ romm_screenscraper_password }} +{% endif %} +{% if romm_mobygames_api_key %} +MOBYGAMES_API_KEY={{ romm_mobygames_api_key }} +{% endif %} +{% if romm_launchbox_api_enabled %} +LAUNCHBOX_API_ENABLED=true +{% endif %} +{% if romm_launchbox_scheduled_update_enabled %} +ENABLE_SCHEDULED_UPDATE_LAUNCHBOX_METADATA=true +{% endif %} +{% if romm_launchbox_scheduled_update_cron %} +SCHEDULED_UPDATE_LAUNCHBOX_METADATA_CRON={{ romm_launchbox_scheduled_update_cron }} +{% endif %} +{% if romm_hasheous_api_enabled %} +HASHEOUS_API_ENABLED=true +{% endif %} +{% if romm_playmatch_api_enabled %} +PLAYMATCH_API_ENABLED=true +{% endif %} +{% if romm_steamgriddb_api_key %} +STEAMGRIDDB_API_KEY={{ romm_steamgriddb_api_key }} +{% endif %} +{% if romm_retroachievements_api_key %} +RETROACHIEVEMENTS_API_KEY={{ romm_retroachievements_api_key }} +{% endif %} +{% if romm_flashpoint_api_enabled %} +FLASHPOINT_API_ENABLED=true +{% endif %} +{% if romm_hltb_api_enabled %} +HLTB_API_ENABLED=true +{% endif %} diff --git a/roles/romm/templates/compose.yml.j2 b/roles/romm/templates/compose.yml.j2 new file mode 100644 index 0000000..449e16d --- /dev/null +++ b/roles/romm/templates/compose.yml.j2 @@ -0,0 +1,41 @@ +--- +services: + romm: + image: "rommapp/romm:{{ romm_container_version }}" + container_name: "{{ romm_container_name }}" + restart: "{{ romm_restart_policy }}" + env_file: + - .env + volumes: + - "{{ romm_resources_path }}:/romm/resources" +{% if romm_redis_data_path %} + - "{{ romm_redis_data_path }}:/redis-data" +{% endif %} + - "{{ romm_library_path }}:/romm/library" + - "{{ romm_assets_path }}:/romm/assets" + - "{{ romm_config_path }}:/romm/config" + ports: + - "{{ romm_http_port }}:8080" + depends_on: + {{ romm_db_container_name }}: + condition: service_healthy + restart: true + + {{ romm_db_container_name }}: + image: "mariadb:{{ romm_db_container_version }}" + container_name: "{{ romm_db_container_name }}" + restart: "{{ romm_restart_policy }}" + environment: + - MARIADB_ROOT_PASSWORD={{ romm_db_root_password }} + - MARIADB_DATABASE=${DB_NAME} + - MARIADB_USER=${DB_USER} + - MARIADB_PASSWORD=${DB_PASSWD} + volumes: + - "{{ romm_mysql_data_path }}:/var/lib/mysql" + healthcheck: + test: [CMD, healthcheck.sh, --connect, --innodb_initialized] + start_period: 30s + start_interval: 10s + interval: 10s + timeout: 5s + retries: 5