diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index e7e27bac..80d475f2 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -42,6 +42,11 @@ jobs: - name: Install dependencies run: uv sync --all-extras --dev + - name: Refresh generated snippets + run: | + uv run python -m scripts.gen_env_vars + uv run python -m scripts.gen_scheduled_tasks + - name: Set Git user run: | git config --global user.name ${{ secrets.GIT_NAME }} @@ -54,6 +59,7 @@ jobs: git checkout main - name: Build the documentation - run: uv run mike deploy --push --update-aliases ${{ github.event.inputs.version }} latest env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VERSION: ${{ github.event.inputs.version }} + run: uv run mike deploy --push --update-aliases $VERSION latest diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml new file mode 100644 index 00000000..eca43867 --- /dev/null +++ b/.github/workflows/pr-checks.yml @@ -0,0 +1,58 @@ +name: PR Checks + +on: + pull_request: + branches: [main] + +concurrency: + group: pr-checks-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + pull-requests: read + +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout repo + uses: actions/checkout@v4.3.0 + + - name: Install uv + uses: astral-sh/setup-uv@v6.7.0 + with: + enable-cache: true + cache-dependency-glob: uv.lock + + - name: Set up Python + uses: actions/setup-python@v6.0.0 + with: + python-version-file: .python-version + + - name: Install dependencies + run: uv sync --all-extras --dev + + - name: Build docs (strict) + run: uv run mkdocs build --strict + + - name: Verify redirect targets exist + run: uv run python -m scripts.check_redirects + + link-check: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Checkout repo + uses: actions/checkout@v4.3.0 + with: + fetch-depth: 0 + + - name: Get changed Markdown files + id: changed + run: | + base="${{ github.event.pull_request.base.sha }}" + head="${{ github.event.pull_request.head.sha }}" + files=$(git diff --name-only "$base" "$head" -- 'docs/**/*.md' | tr '\n' ' ') + echo "files=$files" >> "$GITHUB_OUTPUT" diff --git a/.gitignore b/.gitignore index c7ba7317..341a8182 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ site .cache .DS_Store *.kate-swp +__pycache__ +*.pyc diff --git a/.trunk/configs/.markdownlint.yaml b/.trunk/configs/.markdownlint.yaml index b40ee9d7..407b688f 100644 --- a/.trunk/configs/.markdownlint.yaml +++ b/.trunk/configs/.markdownlint.yaml @@ -1,2 +1,7 @@ # Prettier friendly markdownlint config (all formatting rules disabled) extends: markdownlint/style/prettier + +# MkDocs pages set the page title via frontmatter and repeat it as a body H1. +# Stop MD025 from counting the frontmatter title as a heading. +MD025: + front_matter_title: "" diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 11d46ccf..6b048475 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -27,6 +27,12 @@ lint: - taplo@0.9.3 - trufflehog@3.88.12 - yamllint@1.35.1 + ignore: + # Snippet partials are included into other pages via pymdownx.snippets, + # so they intentionally lack a top-level heading and standalone structure. + - linters: [markdownlint] + paths: + - docs/resources/snippets/** # actions: # enabled: # - trunk-announce diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index dc649691..9a2e52c0 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -22,7 +22,7 @@ community include: - Giving and gracefully accepting constructive feedback - Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience -- Focusing on what is best not just for us as individuals, but for the +- Focusing on what is best not just for us as individuals but for the overall community Examples of unacceptable behavior include: diff --git a/LICENSE b/LICENSE index 0e259d42..e6ef5e61 100644 --- a/LICENSE +++ b/LICENSE @@ -39,7 +39,7 @@ Work and the meaning and intended legal effect of CC0 on those rights. 1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and -Related Rights"). Copyright and Related Rights include, but are not +Related Rights"). Copyright and Related Rights include but are not limited to, the following: i. the right to reproduce, adapt, distribute, perform, display, @@ -60,7 +60,7 @@ vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. -2. Waiver. To the greatest extent permitted by, but not in contravention +2. Waiver. To the greatest extent permitted by but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes diff --git a/docs/API-and-Development/API-Reference.md b/docs/API-and-Development/API-Reference.md deleted file mode 100644 index 80d9db7a..00000000 --- a/docs/API-and-Development/API-Reference.md +++ /dev/null @@ -1,165 +0,0 @@ -# API Reference - -RomM provides a comprehensive REST API that allows you to programmatically interact with your RomM instance. Most API endpoints are authenticated and follow RESTful conventions. - -## Interactive Documentation - -RomM automatically generates interactive API documentation using OpenAPI (Swagger). You can access the interactive API docs directly from your running instance: - -- **Swagger UI**: Available at `http://your-instance:3000/api/docs` -- **ReDoc**: Available at `http://your-instance:3000/api/redoc` - -These interactive docs allow you to: - -- Browse all available endpoints -- View request/response schemas -- Test API calls directly from your browser -- Understand authentication requirements -- Download the OpenAPI specification - -## Base URL - -The API base URL is typically: - -```text -http://your-instance:3000/api -``` - -Replace `your-instance` with your actual RomM instance URL or IP address. - -## Authentication - -All API endpoints require authentication. RomM supports: - -- **Basic HTTP Authentication** - Username and password -- **OAuth2 Password Bearer** - Token-based authentication (recommended for API usage) - -When using OAuth2, you'll need to obtain a token from `/api/token` endpoint and include it in the `Authorization` header as `Bearer `. - -### OAuth2 Scopes - -The API uses OAuth2 scopes to control access to different resources: - -**Read Scopes:** - -- `me.read` - View your profile -- `roms.read` - View ROMs -- `platforms.read` - View platforms -- `assets.read` - View assets -- `firmware.read` - View firmware -- `roms.user.read` - View user-rom properties -- `collections.read` - View collections -- `users.read` - View users - -**Write Scopes:** - -- `me.write` - Modify your profile -- `assets.write` - Modify assets -- `roms.user.write` - Modify user-rom properties -- `collections.write` - Modify collections -- `roms.write` - Modify ROMs -- `platforms.write` - Modify platforms -- `firmware.write` - Modify firmware -- `users.write` - Modify users -- `tasks.run` - Run tasks - -## API Endpoints Overview - -The RomM API provides comprehensive endpoints for managing all aspects of your ROM collection: - -### Core Resources - -- **Platforms** - Manage and configure gaming platforms -- **ROMs** - Full CRUD operations for ROM files with extensive filtering, searching, and metadata matching -- **Collections** - Create and manage ROM collections, smart collections, and virtual collections -- **Users** - User management, authentication, invite links, and profiles - -### Supporting Features - -- **Authentication** - OAuth2 token management, OIDC login, password resets -- **Search** - Metadata provider search for ROMs and covers -- **Tasks** - Background task management and execution -- **Assets** - Save files, states, screenshots management -- **Firmware** - Upload and manage firmware files for emulation -- **Configuration** - System configuration, platform bindings, and exclusions -- **Feeds** - Integration feeds for WebRcade and Tinfoil -- **Statistics** - System statistics and resource tracking - -For complete endpoint documentation including request/response schemas, query parameters, and authentication requirements, visit the interactive API documentation at `/api/docs` or `/api/redoc` on your RomM instance. - -## Example Usage - -### Using cURL - -```bash -# Get all libraries -curl -u username:password http://your-instance:3000/api/libraries - -# Get a specific ROM -curl -u username:password http://your-instance:3000/api/roms/123 - -# Create a new ROM entry -curl -X POST -u username:password \ - -H "Content-Type: application/json" \ - -d '{"name": "New ROM", "platform_id": 1}' \ - http://your-instance:3000/api/roms -``` - -### Using Python - -```python -import requests -from requests.auth import HTTPBasicAuth - -# Setup authentication -auth = HTTPBasicAuth('username', 'password') -base_url = 'http://your-instance:3000/api' - -# Get all libraries -response = requests.get(f'{base_url}/libraries', auth=auth) -libraries = response.json() - -# Get a specific ROM -response = requests.get(f'{base_url}/roms/123', auth=auth) -rom = response.json() -``` - -### Using JavaScript/Node.js - -```javascript -const axios = require("axios"); - -// Setup authentication -const api = axios.create({ - baseURL: "http://your-instance:3000/api", - auth: { - username: "username", - password: "password", - }, -}); - -// Get all libraries -const libraries = await api.get("/libraries"); - -// Get a specific ROM -const rom = await api.get("/roms/123"); -``` - -## OpenAPI Specification - -You can download the complete OpenAPI specification from your RomM instance: - -```text -http://your-instance:3000/openapi.json -``` - -This specification can be imported into API testing tools like Postman, used to generate client libraries, or used for API mocking. - -## Getting Help - -For API-specific questions or issues: - -1. Check the interactive documentation at `/api/docs` or `/api/redoc` on your instance -2. Review the code in the [RomM repository](https://github.com/rommapp/romm) -3. Open an issue on [GitHub](https://github.com/rommapp/romm/issues) -4. Join the [Discord community](https://discord.com/invite/romm) diff --git a/docs/API-and-Development/Contributing.md b/docs/API-and-Development/Contributing.md deleted file mode 100644 index c60a4080..00000000 --- a/docs/API-and-Development/Contributing.md +++ /dev/null @@ -1,81 +0,0 @@ -# Contributing to RomM - -Thank you for considering contributing to RomM! This document outlines some guidelines to help you get started with your contributions. - -**If you're looking to implement a large feature or make significant changes to the project, it's best to open an issue first AND join the Discord to discuss your ideas with the maintainers.** - -## Code of Conduct - -Please note that this project adheres to the Contributor Covenant [code of conduct](https://github.com/rommapp/romm/blob/master/CODE_OF_CONDUCT.md). By participating in this project, you are expected to uphold this code. - -## AI Assistance Notice - -> [!IMPORTANT] -> -> If you are using **any kind of AI assistance** to contribute to RomM, it must be disclosed in the pull request. - -If you are using any kind of AI assistance while contributing to RomM **this must be disclosed in the pull request**, along with the extent to which AI assistance was used (e.g. docs only vs. code generation). If PR responses are being generated by an AI, disclose that as well. As a small exception, trivial tab-completion doesn't need to be disclosed. - -An example disclosure: - -> This PR was written primarily by Claude Code. - -Or a more detailed disclosure: - -> I consulted ChatGPT to understand the codebase but the solution -> was fully authored manually by myself. - -Failure to disclose this is rude to the human operators on the other end of the pull request, but it also makes it difficult to determine how much scrutiny to apply to the contribution. - -In a perfect world, AI assistance would produce equal or higher quality work than any human. That isn't the world we live in today, and in most cases it's generating slop. - -Please be respectful to maintainers and disclose AI assistance. - -## Contributing to the Docs - -If you would like to contribute to the project's [documentation](https://docs.romm.app), open a pull request against [the docs repo](https://github.com/rommapp/docs). We welcome any contributions that help improve the documentation (new pages, updates, or corrections). - -## Adding Translations - -If you would like to translate the project into another language, create a new folder under the `frontend/src/locales` directory, and follow the existing language files as a template. Once you've created the new language file, open a pull request to add it to the project. - -## How to Contribute Code - -1. Fork the repository. -2. Clone your forked repository: `git clone https://github.com/your-username/romm.git` -3. Checkout the `master` branch: `git checkout master` -4. Follow the steps in the [developer setup guide](https://github.com/rommapp/romm/blob/master/DEVELOPER_SETUP.md) -5. Create a new branch for your feature/fix: `git checkout -b feature-or-fix-name` -6. Make your changes and commit them with descriptive commit messages: `git commit -am 'Add feature XYZ'` -7. Push your changes to your fork: `git push origin feature-or-fix-name` -8. Open a pull request to the `master` branch of the original repository. - -## Pull Request Guidelines - -- Make sure your code follows the project's coding standards. -- Test your changes locally before opening a pull request. -- Update the documentation if necessary. -- Ensure all existing tests pass, and add new tests for new functionality. -- Use clear and descriptive titles and descriptions for your pull requests. - -## Code Style - -Follow the existing code style used throughout the project. If working with VSCode or a similar editor, consider installing these extensions: - -- [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) -- [Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python) -- [Pylance](https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance) -- [Ruff](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff) -- [Vue - Official](https://marketplace.visualstudio.com/items?itemName=Vue.volar) - -## Issue Reporting - -If you encounter any bugs or have suggestions for improvements, please [create an issue](https://github.com/rommapp/romm/issues) on GitHub. Provide as much detail as possible, including steps to reproduce the issue if applicable. - -## Licensing - -By contributing to RomM, you agree that your contributions will be licensed under the project's [LICENSE](https://github.com/rommapp/romm/blob/master/LICENSE). - ---- - -Thank you for contributing to RomM! Your help is greatly appreciated. diff --git a/docs/API-and-Development/index.md b/docs/API-and-Development/index.md deleted file mode 100644 index 969ae7e9..00000000 --- a/docs/API-and-Development/index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -search: - exclude: true ---- - -# API & Development - -Welcome to the RomM API & Development documentation. This section contains resources for developers looking to interact with RomM programmatically or contribute to its development. - -## Contents - -- **[API Reference](API-Reference.md)** - Complete API documentation with endpoints, schemas, and examples -- **[Contributing](Contributing.md)** - Guidelines for contributing code, translations, and documentation -- **[Development Setup](Development-Setup.md)** - How to set up your development environment diff --git a/docs/Getting-Started/Authentication.md b/docs/Getting-Started/Authentication.md deleted file mode 100644 index 0d58a7cf..00000000 --- a/docs/Getting-Started/Authentication.md +++ /dev/null @@ -1,65 +0,0 @@ - - -RomM provides support for various forms of authentication, granting flexibility in securing access to its features. - -### Setup - -You'll want to set the following environment variable before starting RomM: - -- `ROMM_AUTH_SECRET_KEY` is required and can be generated with `openssl rand -hex 32` - -### Sessions - -When the `/login` endpoint is called with valid credentials, a `session_id` is generated, stored as a cookie and sent to the browser. The same token is used to create a cache entry in Valkey (or in-memory if Valkey is disabled) which maps the token to the user. This way no sensitive information is stored on the client. - -### Roles - -A user can have one of the following roles: - -- VIEWER: Can view platforms and ROMs, download ROMs, and edit own profile -- EDITOR: Can create/edit/delete platforms and ROMs -- ADMIN: Can view all users, and create/edit/disable/delete users - -As permissions are additive, editors will have all permissions of the `viewer` role, and admins all those of the `editor` role. - -## Basic Authentication - -Requests can be made to protected API endpoints with an authorization header. The token is the base64 encoded value of `username:password`. - -Example using cURL: - -```bash -curl https://romm.local/api/platforms -H 'Authorization: Basic YWRtaW46aHVudGVyMg==' -``` - -## OAuth - -Along with the above forms of authentication, we've added an endpoint to generate expiring, scope-limited authentication tokens (`/api/token`). Successfully authenticating with that endpoint with return an `access_token` valid for 15 minutes, and a [`refresh_token`](https://oauth.net/2/grant-types/refresh-token/) valid for 2 weeks. The `refresh_token` can be used to generate a new `access_token` when needed. - -The `/api/token` endpoint requires a username, password, and a list of [scopes](https://oauth.net/2/scope/) in the format `read:roms write:roms read:platforms ...`. The list of scopes and endpoints are available to browse via Swagger UI or ReDoc (see next section). - -**Note: As of now, only the legacy [password grant type](https://oauth.net/2/grant-types/password/) is supported.** We plan to eventually add support for [Client Credentials](https://oauth.net/2/grant-types/client-credentials/). - -### OpenAPI - -The API endpoints are fully documented and compliant with the OpenAPI specification. Explore the API endpoints using the Swagger UI interface at `/api/docs` and the ReDoc interface at `/api/redoc`, or view the raw JSON at `/openapi.json`. - -For more information on OpenAPI, visit the [OpenAPI Specification](https://www.openapis.org/) website. - -## FAQ - -### Can I disable authentication? - -No, authentication is required and enabled by default. - -### I want to allow an EDITOR to edit ROMs but not delete them. Can I do that? - -At this time, fine-grain control over permissions within a role is not supported. This decision was taking in order to simplify user management in the client, and authentication/permission code on the server. - -### Is authentication safe/robust? Can I trust it? - -We've done our best to build an authentication system that is simple, clear and comprehensible. We have automated tests which verify that access is granted when it should be, and blocked when not (invalid credentials, missing permissions, expired access tokens, etc.). That being said, we welcome any reviews of our authentication and permission flows, PRs to fix issues, and new tests to cover edge cases. - -### I found an bug/issue with authentication. How do I report it? - -Please report bugs in our authentication/permission system privately by [submitting a vulnerability report](https://github.com/rommapp/romm/security/advisories/new). diff --git a/docs/Getting-Started/Configuration-File.md b/docs/Getting-Started/Configuration-File.md deleted file mode 100644 index 3b9ab30e..00000000 --- a/docs/Getting-Started/Configuration-File.md +++ /dev/null @@ -1,339 +0,0 @@ - - - -Below is a breakdown of each section of the `config.yml` file and its purpose. You can find a full example of the file in the [config.example.yml](https://github.com/rommapp/romm/blob/master/examples/config.example.yml) file. - ---- - -## Exclude Section - -Control which platforms, ROMs, or files to ignore during scanning. - -### Platforms - -Exclude entire platforms (folders) from being scanned. - -```yaml -exclude: - platforms: ["ps", "ngc", "gba"] -``` - -### ROMs - -Fine-tune which ROMs or files are excluded. - -#### Single File ROMs - -Applies to ROMs that are single files (not in subfolders). - -- **extensions**: Exclude files by extension - - Defaults to `["db", "ini", "tmp", "bak", "lock", "log", "cache", "crdownload"]` -- **names**: Exclude files by name or pattern (supports Unix wildcards) - - Defaults to `[".DS_Store", ".localized", ".Trashes", ".stfolder", "@SynoResource", "gamelist.xml"]` - -```yaml -exclude: - roms: - single_file: - extensions: ["xml", "txt"] - names: ["info.txt", "._*", "*.nfo"] -``` - -#### Multi-File ROMs - -Applies to ROMs stored as folders (multi-disc, with DLC, etc.). - -- **names**: Exclude entire folders by name - - Defaults to `["@eaDir", "__MACOSX", "$RECYCLE.BIN", ".Trash-*", ".stfolder", ".Spotlight-V100", ".fseventsd", ".DocumentRevisions-V100", "System Volume Information"]` -- **parts.names**: Exclude files by name or pattern from within multi-file ROM folders - - Defaults to `[".DS_Store", ".localized", ".Trashes", ".stfolder", "@SynoResource", "gamelist.xml"]` -- **parts.extensions**: Exclude files by extension from within multi-file ROM folders - - Defaults to `["db", "ini", "tmp", "bak", "lock", "log", "cache", "crdownload"]` - -```yaml -exclude: - roms: - multi_file: - names: ["final fantasy VII", "DLC"] - parts: - names: ["data.xml", "._*"] - extensions: ["xml", "txt"] -``` - ---- - -## System Section - -Customize how RomM interprets your folder and platform names. - -### Custom Folder Names - -Map your custom folder names to RomM's recognized platform names. - -```yaml -system: - platforms: - gc: "ngc" # Treats 'gc' folder as GameCube - psx: "ps" # Treats 'psx' folder as PlayStation -``` - -### Versions - -Associate a platform with its main version. This also tells RomM to fetch metadata from the main version source. - -```yaml -system: - versions: - naomi: "arcade" -``` - ---- - -## Filesystem Section - -Specify the folder name where your ROMs are located if it differs from the default. - -If your ROMs folder is named `my_roms` instead of `roms`: - -```yaml -filesystem: - roms_folder: "my_roms" -``` - -Disable file hash calculation for low power devices (e.g. Raspberry PI). - -```yaml -filesystem: - skip_hash_calculation: true -``` - ---- - -## Scan Section - -Configure metadata scanning priorities and media assets to download. - -### Priority - -Customize the order in which metadata providers are queried during scans. - -#### Metadata - -Controls metadata provider priority order. - -**Provider list in default order:** - -- `igdb` - IGDB (highest priority) -- `moby` - MobyGames -- `ss` - Screenscraper -- `ra` - RetroAchievements -- `launchbox` - Launchbox -- `gamelist` - ES-DE gamelist.xml -- `hasheous` - Hasheous -- `flashpoint` - Flashpoint Project -- `hltb` - HowLongToBeat (lowest priority) - -```yaml -scan: - priority: - metadata: - - "igdb" - - "ss" - - "moby" -``` - -#### Artwork - -Controls artwork provider priority order for cover art and screenshots. - -**Default:** Same as `priority.metadata` - -```yaml -scan: - priority: - artwork: - - "igdb" - - "ss" - - "moby" -``` - -#### Region - -Sets preferred region for cover art and game title (Screenscraper only). - -**Default:** `["us", "wor", "ss", "eu", "jp"]` - -```yaml -scan: - priority: - region: - - "us" - - "eu" - - "jp" -``` - -#### Language - -Sets preferred language for cover art and game title (Screenscraper only). - -**Default:** `["en", "fr"]` - -```yaml -scan: - priority: - language: - - "en" - - "es" - - "fr" -``` - -### Media - -Configures which media assets to download (Screenscraper and ES-DE gamelist.xml only). - -**Media types:** - -- `box2d` - Normal cover art (always enabled) -- `box3d` - 3D box art -- `miximage` - Mixed image of multiple media -- `physical` - Disc, cartridge, etc. -- `screenshot` - Screenshot (enabled by default) -- `title_screen` - Title screen -- `marquee` - Transparent logo -- `fanart` - User uploaded artwork -- `bezel` - Bezel displayed around the EmulatorJS window -- `manual` - Manual in PDF format (enabled by default) -- `video` - Gameplay video (warning: large file size) - -```yaml -scan: - media: - - box2d - - screenshot - - manual - - bezel -``` - -### Export gamelist.xml - -Automatically generate an ES-DE compatible gamelist.xml file placed in the platform folder for selected/discovered platforms. - -```yaml -scan: - export_gamelist: true -``` - ---- - -## EmulatorJS Section - -Configure EmulatorJS per-core options and controls. - -### Debug - -Enable debug mode to log available options to the browser console. - -```yaml -emulatorjs: - debug: true -``` - -### Cache Limit - -Cache limit per ROM in bytes. Set to `null` for unlimited. - -```yaml -emulatorjs: - cache_limit: 52428800 # 50 MB -``` - -### Disable batch bootup - -Skips the step that runs a batch file that sets soundcard information, mounts file systems, and attempts to run an `autorun.bat` file (try this if DOS games fail to boot). - -```yaml -emulatorjs: - disable_batch_bootup: true -``` - -### Disable auto-unload - -The emulator stops/shuts itself down when you navigate to a new page; this setting stops that behaviour (if that's something you want). - -```yaml -emulatorjs: - disable_auto_unload: true -``` - -### Netplay - -Enable [netplay](https://emulatorjs.org/docs4devs/netplay/#website-integration) and configure STUN/TURN servers. We recommend Google's public servers or [Metered's free tier](https://www.metered.ca/stun-turn). - -```yaml -emulatorjs: - netplay: - enabled: true - ice_servers: - - urls: "stun:stun.l.google.com:19302" - - urls: "stun:stun1.l.google.com:19302" - - urls: "stun:stun2.l.google.com:19302" - - urls: "turn:openrelay.metered.ca:80" - username: "openrelayproject" - credential: "openrelayproject" - - urls: "turn:openrelay.metered.ca:443" - username: "openrelayproject" - credential: "openrelayproject" -``` - - -!!! note - When netplay is enabled, EmulatorJS loads some assets (including localization files) from the nightly CDN (`https://cdn.emulatorjs.org/nightly/...`). This differs from stable mode, which uses local/bundled assets. Occasional temporary issues (e.g., 404 errors or untranslated UI elements) can occur if the nightly CDN has mismatches, but these usually resolve with the next EmulatorJS stable release integrated into RomM. - -### Settings - -Configure core-specific settings. Use `default` to apply settings to all cores. - -```yaml -emulatorjs: - settings: - parallel_n64: # Use the exact core name - vsync: disable - snes9x: - snes9x_region: ntsc - default: # These settings apply to all cores - fps: show -``` - -### Controls - -Map keyboard and controller controls for each player. - -**Example (2-player SNES):** - -```yaml -emulatorjs: - controls: - snes9x: - 0: # Player 1 - 0: # Button mapping - value: x # Keyboard mapping - value2: BUTTON_2 # Controller mapping - 1: # Player 2 - 0: - value: / - value2: BUTTON_2 -``` - -See [EmulatorJS documentation](https://emulatorjs.org/docs4devs/control-mapping/) for control mapping details. - ---- - - -!!! tip - You can find examples of full binded batocera or es-de config files. - - -!!! warning - Only uncomment or add the lines you need. Any omitted or empty sections will use RomM's defaults. - -For a full example, see the config.example.yml file. diff --git a/docs/Getting-Started/Environment-Variables.md b/docs/Getting-Started/Environment-Variables.md deleted file mode 100644 index 5e2a4e3b..00000000 --- a/docs/Getting-Started/Environment-Variables.md +++ /dev/null @@ -1,126 +0,0 @@ - - -This is a complete list of available environment variables; required variables are marked with a `✓`. - - -!!! tip - You can also set environment variables with a `_FILE` suffix, which will load the contents of the file specified in the variable into the variable without the suffix. For example, setting `ROMM_AUTH_SECRET_KEY_FILE=/run/secrets/romm_auth_secret_key` and creating a file with the secret key at the specified path will set `ROMM_AUTH_SECRET_KEY` to the contents of the file. [Learn more.](https://docs.docker.com/compose/how-tos/use-secrets/) - -## Application settings - -| Variable | Description | Required | Default | -| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | :------: | ------------------------- | -| ROMM_AUTH_SECRET_KEY | Generate a key with `openssl rand -hex 32` | ✓ | | -| DISABLE_CSRF_PROTECTION | Disables [CSRF protection](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html) (not recommended) | | `false` | -| DISABLE_DOWNLOAD_ENDPOINT_AUTH | Disable auth on download endpoint (WebRcade, Tinfoil) | | `false` | -| DISABLE_USERPASS_LOGIN | Disables login with username and password (when using OIDC) | | `false` | -| SESSION_MAX_AGE_SECONDS | Maximum age of a session (in seconds) | | `1209600` (14 days) | -| KIOSK_MODE | Read-only mode for public displays or kiosks | | `false` | -| SCAN_TIMEOUT | Timeout for the background scan/rescan tasks (in seconds) | | `14400` (4 hours) | -| SCAN_WORKERS | Number of worker processes for scanning tasks | | `1` | -| TASK_TIMEOUT | Timeout for the the rest of the background tasks (in seconds) | | `300` (5 minutes) | -| TASK_RESULT_TTL | How long to keep task results in Valkey (in seconds) | | `86400` (24 hours) | -| SEVEN_ZIP_TIMEOUT | Timeout for 7-Zip operations (in seconds) | | `60` | -| DISABLE_EMULATOR_JS | Disables playing in browser with [EmulatorJS](../Platforms-and-Players/EmulatorJS-Player.md) | | `false` | -| DISABLE_RUFFLE_RS | Disables playing flash games with [RuffleRS](../Platforms-and-Players/RuffleRS-Player.md) | | `false` | -| YOUTUBE_BASE_URL | Base URL for alternate frontends (Piped, Invidious, etc.) | | `https://www.youtube.com` | -| TZ | Sets the timezone | | `UTC` | -| ROMM_PORT | Port on which the application listens | | `8080` | -| ROMM_BASE_PATH | Base folder path for library, resources and assets | | `/romm` | -| ROMM_BASE_URL | Base url for properly display container logs links (like register or recover password) | | `0.0.0.0` | -| LOGLEVEL | Logging level for the app | | `INFO` | -| FORCE_COLOR | Forces color output | | `false` | -| NO_COLOR | Disables color output | | `false` | -| WEB_SERVER_CONCURRENCY | Number of processes running the app | | `1` | -| WEB_SERVER_KEEPALIVE | Waiting time for requests on a Keep-Alive connection (in seconds) | | `2` | -| WEB_SERVER_MAX_REQUESTS | Maximum number of requests a worker will process before restarting | | `1000` | -| WEB_SERVER_MAX_REQUESTS_JITTER | Random jitter to add to the maximum number of requests a worker will process before restarting | | `100` | -| WEB_SERVER_TIMEOUT | Timeout for web server requests (in seconds) | | `300` | -| WEB_SERVER_WORKER_CONNECTIONS | Maximum number of simultaneous clients a single process can handle | | `1000` | - -## Dependencies - -| Variable | Description | Required | Default | -| -------------- | ---------------------------------------------------------------------------------------------------------- | :------: | ----------- | -| DB_HOST | Host name of database instance | ✓ | | -| DB_PORT | Port number of database instance | | `3306` | -| DB_NAME | Should match MYSQL_DATABASE in MariaDB | | `romm` | -| DB_USER | Database username (in MariaDB, should match MARIADB_USER) | ✓ | | -| DB_PASSWD | Database password (in MariaDB, should match MARIADB_PASSWORD) | ✓ | | -| DB_QUERY_JSON | Extra query parameters for the database connection, in JSON format (e.g. `{"unix_socket": "/path/to/db"}`) | | | -| ROMM_DB_DRIVER | Database driver to use (options: `mariadb`, `mysql`, `postgresql`) | | `mariadb` | -| REDIS_HOST | Host name of Redis/Valkey instance | | `127.0.0.1` | -| REDIS_PORT | Port number of Redis/Valkey instance | | `6379` | -| REDIS_USERNAME | Username for Redis/Valkey instance | | | -| REDIS_PASSWORD | Password for Redis/Valkey instance | | | -| REDIS_DB | Database number for Redis/Valkey instance | | `0` | -| REDIS_SSL | Enable SSL for Redis/Valkey instance | | `false` | -| SENTRY_DSN | DSN for Sentry error tracking | | | - -## Metadata providers - -| Variable | Description | Required | Default | -| ------------------------------------ | -------------------------------------------------- | :------: | ------- | -| IGDB_CLIENT_ID | Client ID for IGDB API | | | -| IGDB_CLIENT_SECRET | Client secret for IGDB API | | | -| SCREENSCRAPER_USER | Screenscraper username | | | -| SCREENSCRAPER_PASSWORD | Screenscraper password | | | -| MOBYGAMES_API_KEY | MobyGames secret API key | | | -| STEAMGRIDDB_API_KEY | SteamGridDB secret API key | | | -| RETROACHIEVEMENTS_API_KEY | Retroachievements secret API key | | | -| REFRESH_RETROACHIEVEMENTS_CACHE_DAYS | Retroachievements metadata cache refresh (in days) | | `30` | -| LAUNCHBOX_API_ENABLED | Enable LaunchBox API integration | | `false` | -| PLAYMATCH_API_ENABLED | Enable PlayMatch API integration | | `false` | -| HASHEOUS_API_ENABLED | Enable Hasheous API integration | | `false` | -| FLASHPOINT_API_ENABLED | Enable Flashpoint API integration | | `false` | -| HLTB_API_ENABLED | Enable HowLongToBeat API integration | | `false` | - -## Authentication - -| Variable | Description | Required | Default | -| ---------------------------------- | ------------------------------------------------- | :------: | -------------------- | -| OIDC_ENABLED | Enable OpenID Connect (OIDC) authentication | | `false` | -| OIDC_PROVIDER | Name of the OIDC provider in use | | | -| OIDC_CLIENT_ID | Client ID for OIDC authentication | | | -| OIDC_CLIENT_SECRET | Client secret for OIDC authentication | | | -| OIDC_REDIRECT_URI | Absolute redirect URI for OIDC authentication | | | -| OIDC_SERVER_APPLICATION_URL | Absolute URL of the OIDC server application | | | -| OIDC_TLS_CACERTFILE | Path to a file containing trusted CA certificates | | | -| OAUTH_ACCESS_TOKEN_EXPIRE_SECONDS | Access token lifetime (in seconds) | | `1800` (30 minutes) | -| OAUTH_REFRESH_TOKEN_EXPIRE_SECONDS | Refresh token lifetime (in seconds) | | `604800` (7 days) | -| INVITE_TOKEN_EXPIRY_SECONDS | Invite token lifetime (in seconds) | | `600` (10 minutes) | -| OIDC_SERVER_METADATA_URL | URL to the OIDC provider metadata endpoint | | | -| OIDC_RP_INITIATED_LOGOUT | Enable RP-initiated logout flow | | `false` | -| OIDC_END_SESSION_ENDPOINT | OIDC end-session endpoint override URL | | `""` | -| OIDC_USERNAME_ATTRIBUTE | Attribute on OIDC user info used as the username | | `preferred_username` | -| OIDC_AUTOLOGIN | Skip click OIDC button on login page | | `false` | -| OIDC_CLAIM_ROLES | OIDC claim containing user roles | | | -| OIDC_ROLE_VIEWER | Role value mapping to viewer permissions | | | -| OIDC_ROLE_EDITOR | Role value mapping to editor permissions | | | -| OIDC_ROLE_ADMIN | Role value mapping to admin permissions | | | - -## Background tasks - -| Variable | Description | Required | Default | -| ------------------------------------------------ | --------------------------------------------------------------------- | :------: | ------------- | -| ENABLE_RESCAN_ON_FILESYSTEM_CHANGE | Enable re-scanning of library when filesystem changes | | `false` | -| RESCAN_ON_FILESYSTEM_CHANGE_DELAY | Delay before re-scanning library when filesystem changes (in minutes) | | `5` | -| ENABLE_SCHEDULED_RESCAN | Enable scheduled re-scanning of library | | `false` | -| SCHEDULED_RESCAN_CRON | Cron expression for scheduled re-scanning | | `"0 3 * * *"` | -| ENABLE_SCHEDULED_UPDATE_SWITCH_TITLEDB | Enable scheduled updating of Switch TitleDB index | | `false` | -| SCHEDULED_UPDATE_SWITCH_TITLEDB_CRON | Cron expression for scheduled updating of Switch TitleDB | | `"0 4 * * *"` | -| ENABLE_SCHEDULED_UPDATE_LAUNCHBOX_METADATA | Enable scheduled updating of LaunchBox metadata | | `false` | -| SCHEDULED_UPDATE_LAUNCHBOX_METADATA_CRON | Cron expression for scheduled updating of LaunchBox metadata | | `"0 4 * * *"` | -| ENABLE_SCHEDULED_CONVERT_IMAGES_TO_WEBP | Enable scheduled conversion of images to WebP format | | `false` | -| SCHEDULED_CONVERT_IMAGES_TO_WEBP_CRON | Cron expression for scheduled conversion of images to WebP format | | `"0 4 * * *"` | -| ENABLE_SCHEDULED_RETROACHIEVEMENTS_PROGRESS_SYNC | Enable scheduled syncing of Retroachievements progress | | `false` | -| SCHEDULED_RETROACHIEVEMENTS_PROGRESS_SYNC_CRON | Cron expression for scheduled syncing of Retroachievements progress | | `"0 4 * * *"` | - -## Development - -| Variable | Description | Required | Default | -| ------------ | -------------------------------------------------- | :------: | ----------- | -| DEV_MODE | Enable development mode (debugging, hot-reloading) | | `false` | -| DEV_HOST | Host for development server | | `127.0.0.1` | -| DEV_PORT | Port for development server | | `5000` | -| DEV_SQL_ECHO | Enable SQL query logging in development mode | | `false` | diff --git a/docs/Getting-Started/OIDC-Setup.md b/docs/Getting-Started/OIDC-Setup.md deleted file mode 100644 index 399b4ae6..00000000 --- a/docs/Getting-Started/OIDC-Setup.md +++ /dev/null @@ -1,75 +0,0 @@ -# OIDC Setup - -OpenID Connect (OIDC) allows you to authenticate to RomM using external identity providers, enabling Single Sign-On (SSO) and centralized user management. This setup eliminates the need to manage separate credentials for RomM. - -## What is OAuth2? - -OAuth2 (Open Authorization 2.0) is an industry-standard protocol for authorization. It allows applications (clients) to gain limited access to user accounts on an HTTP service without sharing the user’s credentials. Instead, it uses access tokens to facilitate secure interactions. OAuth2 is commonly used in scenarios where users need to authenticate via a third-party service. - -## What is OpenID Connect (OIDC)? - -OIDC (OpenID Connect) is an identity layer built on top of OAuth2. While OAuth2 primarily handles authorization, OIDC adds authentication, enabling applications to verify a user’s identity and obtain profile information. This makes OIDC suitable for SSO solutions, where user identity is central to access management. - -## How It Works - -1. Click the OIDC login button on RomM's login page -2. You're redirected to your identity provider -3. Authenticate with your credentials -4. You're redirected back to RomM and logged in automatically - -## Supported Identity Providers - -RomM supports OIDC authentication with the following identity providers: - -### [Authelia](../OIDC-Guides/OIDC-Setup-With-Authelia.md) - -An open-source authentication and authorization server providing two-factor authentication and SSO. Ideal for self-hosters looking for a lightweight solution. - -### [Authentik](../OIDC-Guides/OIDC-Setup-With-Authentik.md) - -An open-source identity provider with support for modern authentication protocols, MFA, and comprehensive user management. - -### [PocketID](../OIDC-Guides/OIDC-Setup-With-PocketID.md) - -A simple OIDC provider that exclusively supports passkey authentication - no passwords required. - -### [Zitadel](../OIDC-Guides/OIDC-Setup-With-Zitadel.md) - -An enterprise-grade, open-source identity and access management platform supporting OAuth2, OIDC, SAML, and passwordless authentication. - -### [Keycloak](../OIDC-Guides/OIDC-Setup-With-Keycloak.md) - -A popular open-source OIDC provider with extensive features for identity and access management. - -## General Setup Requirements - -Regardless of which provider you choose, you'll need to configure these environment variables in RomM: - -```env -OIDC_ENABLED=true -OIDC_PROVIDER= -OIDC_CLIENT_ID= -OIDC_CLIENT_SECRET= -OIDC_REDIRECT_URI=/api/oauth/openid -OIDC_SERVER_APPLICATION_URL= -``` - -## Important Notes - -- **Email matching**: Your email address in RomM must match the email in your identity provider -- **First-time users**: Users logging in via OIDC for the first time will be created automatically with viewer permissions -- **Existing users**: Users who already have an account in RomM need to ensure their email addresses match between RomM and the identity provider - -## Troubleshooting - -If you encounter issues with OIDC authentication: - -- Verify all environment variables are set correctly -- Check that the redirect URI matches exactly between RomM and your identity provider -- Ensure your email address in RomM matches your email in the identity provider -- Review the [Authentication Issues](../Troubleshooting/Authentication-Issues.md) documentation -- Check your identity provider's logs for any authentication errors - -## Next Steps - -Choose a provider from the list above and follow its specific setup guide. Each guide provides detailed step-by-step instructions for configuring both the identity provider and RomM. diff --git a/docs/Getting-Started/Quick-Start-Guide.md b/docs/Getting-Started/Quick-Start-Guide.md deleted file mode 100644 index 5fa99ed1..00000000 --- a/docs/Getting-Started/Quick-Start-Guide.md +++ /dev/null @@ -1,108 +0,0 @@ - - - -This quick start guide will help you get a RomM instance up and running. It is split into 3 parts: Prepare, Build and Configure. - -## Prepare - -There are a few things you need to have in place before you can start: - -- [Docker](https://docs.docker.com/get-docker/) installed and running on your system -- Your ROMs organized in the correct [folder structure](./Folder-Structure.md) -- The recommended [metadata providers](./Metadata-Providers.md) set up -- A copy of the [config.yml](./Configuration-File.md) in the config folder for your environment - - -!!! warning - RomM works without a metadata API for basic use, but may cause issues with plugins like Playnite. Setting up IGDB API keys is recommended to prevent setup problems. - -## Build - -Now that we have everything gathered, we can begin getting your instance set up! - -1. Download a copy of the latest docker-compose.example.yml file from GitHub -2. Edit the file and modify the following values to configure the database - - `MARIADB_ROOT_PASSWORD`: Sets the root password of the database. Use a unique and secure password (_use a password generator for simplicity_) - - `MARIADB_DATABASE`: Sets the database name for RomM. This can be modified - but it's not necessary - - `MARIADB_USER`: User to connect to the database with. This can be modified - but it's not necessary - - `MARIADB_PASSWORD`: Password for the user to connect to the database with. Use a unique and secure password (_use a password generator for simplicity_) -3. Modify the following values in the **environment** to configure the application. _-- Other values can be changed, but should not be done unless you know what you are doing, and are outside the scope of this guide_ - - `DB_NAME`: Name of the database set in the database section - - `DB_USER`: Name of the user to connect to the database - - `DB_PASSWD`: Password of the user to connect to the database -4. Run the following command in a terminal and save the output to the `ROMM_AUTH_SECRET_KEY` environment variable: - ```sh - openssl rand -hex 32 - ``` - It should look something like this: - ```sh - 03a054b6ca27e0107c5eed552ea66becd9f3a2a8a91e7595cd462a593f9ecd09 - ``` -5. Add your metadata sources API keys: - - IGDB: `IGDB_CLIENT_ID` and `IGDB_CLIENT_SECRET` - - ScreenScraper.fr: `SCREENSCRAPER_USER` and `SCREENSCRAPER_PASSWORD` - - RetroAchievements: `RETROACHIEVEMENTS_API_KEY` - - MobyGames: `MOBYGAMES_API_KEY` - - SteamGridDB: `STEAMGRIDDB_API_KEY` - - Hasheous: `HASHEOUS_API_ENABLED=true` - - PlayMatch: `PLAYMATCH_API_ENABLED=true` - - LaunchBox: `LAUNCHBOX_API_ENABLED=true` -6. Modify the following values in the **volumes** to configure the application - - `/path/to/library`: Path to the directory where your ROM files will be stored (usually the parent folder of the `roms` folder) - - `/path/to/assets`: Path to the directory where you will store your save files and other assets - - `/path/to/config`: Path to the directory where you will store the config.yml (store the `config.yml` file in this folder) -7. Save the file as _docker-compose.yml_ instead of _docker-compose.example.yml_. It should look something like this: - - - ???+ example "Example Docker Compose" - ``` yaml - --8<-- "quick-start.docker-compose.yml" - ``` - -8. Open the terminal and navigate to the directory containing the docker-compose file -9. Run `docker compose up -d` to kick off the docker pull. You will see it pull the container and set up the volumes and network: - - ```asciinema-player - { - "file": "../latest/resources/asciinema/quick-start-docker-compose.cast", - "title": "RomM docker compose install", - "preload": true, - "loop": true, - "auto_play": true, - "cols": 140, - "rows": 30, - "fit": "width", - "terminal_font_size": "small", - "terminal_line_height": "1.2", - "terminal_font_family": "Roboto Mono, Monaco, Consolas, monospace" - } - ``` - -10. Run `docker ps -f name=romm` to verify that the containers are running -11. Open a web browser and navigate to `http://localhost:80`, where you should be greeted with the RomM setup page -12. Go through the setup wizard, setting your admin username and password -13. Log in with the credentials you set in the last step - -## Configure - -### Importing your ROMs via scanner - -This method is generally the fastest and recommended for first time setup. You need your library properly mounted as a container volume: - -1. Log into RomM with your user credentials -2. Click the `Scan` button in the sidebar -3. Select the metadata providers you want to fetch metadata from -4. The system will now begin scanning the ROM files and applying metadata to them. You can click on any of the items that it has tagged to see the metadata it pulled without having to stop the scan -5. After the scan completes, click the RomM logo to go back to the main screen. You should see the platforms and recent games it has scanned. You are now ready to rock with RomM! - -### Uploading your ROMs via Web Interface - -This method is certainly viable, but not recommended if you have a lot of ROMs and/or multiple platforms. It is good for adding files after the fact as your collection grows, but wouldn't be recommended for the first setup, nor for multi-file ROMs: - -1. Log into RomM with your user credentials -2. Click the `Upload` button in the sidebar -3. Select the platform, then click `+ ADD` and select the ROMs you want to upload in the file selector that appears -4. Click `Upload` to begin uploading the ROMs -5. Repeat for all the `roms/platforms` you have - -upload dialog diff --git a/docs/Getting-Started/Reverse-Proxy.md b/docs/Getting-Started/Reverse-Proxy.md deleted file mode 100644 index 90adb9e6..00000000 --- a/docs/Getting-Started/Reverse-Proxy.md +++ /dev/null @@ -1,162 +0,0 @@ - - -Here are some basic configurations for popular reverse proxies. Additional configuration may be required depending on your specific setup. - -## Caddy - -```caddyfile -http://romm.mysite.com { - reverse_proxy romm:8080 -} -``` - -### Caddy + TLS (HTTPS) - -```caddyfile -romm.mysite.com { - encode zstd gzip - - header { - Strict-Transport-Security "max-age=31536000;" - X-XSS-Protection "1; mode=block" - X-Frame-Options "SAMEORIGIN" - X-Robots-Tag "noindex, nofollow" - -Server - -X-Powered-By - } - - reverse_proxy romm:8080 -} -``` - -## Nginx - -```nginx -server { - listen 80 default_server; - server_name romm.mysite.com; - client_max_body_size 0; - - location / { - include /config/nginx/proxy.conf; - include /config/nginx/resolver.conf; - set $upstream_app romm; - set $upstream_port 8080; - set $upstream_proto http; - proxy_pass $upstream_proto://$upstream_app:$upstream_port; - } -} -``` - -### Nginx + TLS (HTTPS) - -```nginx -server { - listen 80 default_server; - server_name _; - return 301 https://$host$request_uri; -} - -server { - listen 443 ssl http2; - listen [::]:443 ssl http2; - - server_name romm.mysite.com; - include /config/nginx/ssl.conf; - client_max_body_size 0; - - location / { - include /config/nginx/proxy.conf; - include /config/nginx/resolver.conf; - set $upstream_app romm; - set $upstream_port 8080; - set $upstream_proto http; - proxy_pass $upstream_proto://$upstream_app:$upstream_port; - - # Hide version - server_tokens off; - - # Security headers - add_header X-Frame-Options "SAMEORIGIN" always; - add_header X-Content-Type-Options "nosniff" always; - add_header X-XSS-Protection "1; mode=block" always; - add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; - add_header Referrer-Policy "no-referrer-when-downgrade" always; - } -} -``` - -## Nginx Proxy Manager - -Items marked with ❗ are important to set, as RomM may not work correctly otherwise! - -### ⚡ Details - -- Domain Names: `romm.example.com` (replace example with your own) -- Scheme: `http` -- Forward Hostname/IP: device IP (like 192.168.X.X) -- Forward Port: `8080` -- Cache Assets: `off` -- Block Common Exploits: `on` -- Websockets Support: `on` ❗ -- Access List: - (or configure as needed) - -### 🛡️ SSL - -Strongly recommended for security; enable this if you plan to use HTTPS. - -- SSL Certificate: "Request a new SSL Certificate" -- Force SSL: `on` -- HTTP/2 Support: `on` -- HSTS Enabled: `off` -- Email Address for Let's Encrypt: your email address -- I Agree to the TOS: `on` - -### ⚙️ Advanced - -Custom Nginx Configuration ❗ - -```yaml -proxy_max_temp_file_size 0; -``` - -| Details | SSL | Advanced | -| ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ | -| ![image](https://github.com/user-attachments/assets/e106a8e9-8b27-41ef-8ba2-d43c3b68b269) | ![image2](https://github.com/user-attachments/assets/6c82c785-792a-410a-80f2-d95839cba47b) | ![image3](https://github.com/user-attachments/assets/566ae834-99b5-42f3-b46b-306b8f73b5b4) | - -## Traefik - -### Using a configuration document - -```yaml -http: - romsdomainse: - entryPoints: - - "https" - rule: "Host(`roms.domain.se`)" - middlewares: - - default-headers - - https-redirectscheme - tls: - certResolver: http - service: romsdomainse - -services: - romsdomainse: - loadBalancer: - servers: - - url: "http://192.168.1.100:8080" - passHostHeader: true -``` - -### Using labels in docker compose - -```yaml -labels: - - "traefik.enable=true" - - "traefik.http.services.romm.loadbalancer.server.port=8080" - - "traefik.http.routers.romm.rule=Host(`romm.YOUR_DOMAIN.com`)" - - "traefik.http.routers.romm.entrypoints=websecure" - - "traefik.http.routers.romm.tls=true" - - "traefik.http.routers.romm.tls.certresolver=https" -``` diff --git a/docs/Integrations/Playnite-plugin.md b/docs/Integrations/Playnite-plugin.md deleted file mode 100644 index 9555dc65..00000000 --- a/docs/Integrations/Playnite-plugin.md +++ /dev/null @@ -1,50 +0,0 @@ - - - -
- romm[playnite] isotipo -
- -Playnite is an open source video game library manager with one simple goal: To provide a unified interface for all of your games. - -This plugin allows you to import your RomM library into Playnite. It queries the RomM API to create Playnite library entires for each of your games. Installing a game in Playnite will download it from RomM and store it on your system, allowing you to launch it in your emulator of choice. - -## Installation - -- Option A: Open this link in your browser to launch Playnite and install the plugin automatically: `playnite://playnite/installaddon/RomM_9700aa21-447d-41b4-a989-acd38f407d9f` -- Option B: Download the plugin from the [Playnite add-ons website](https://playnite.link/addons.html#RomM_9700aa21-447d-41b4-a989-acd38f407d9f) -- Option C: In Playnite, go to `Menu` -> `Add-ons...` -> `Browse` -> `Libraries`, search for `RomM`, and click `Install` -- Option D: Download the latest release from the [releases page](https://github.com/rommapp/playnite-plugin/releases/latest) and install it manually by dragging the `.pext` file onto Playnite - -## Setup - -### Emulators - -The plugin requires that you have **at least 1 emulator installed** on your system and configured in Playnite. You can use a built-in emulator or a custom one. **If no emulators are installed and configured, you won't be able to complete setup!** To set up an emulator, go to `Menu` -> `Library` -> `Configure Emulators...` -> `Add emulator...`. - -### Settings - -The plugin needs to be configured before it can be used. To do this, go to `Menu` -> `Library` -> `Configure Integrations...` -> `RomM`. - -#### Authentication - -You'll need to enter the host URL of your RomM instance, as well as a username and password. Passwords are stored in plaintext in Playnite, so it's recommended to use a separate account with the "VIEWER" role. **The host URL has the include the protocol (http/https) and should not include a trailing slash, e.g. `https://romm.example.com`.** - -#### Emulator path mappings - -| Field | Description | Example | Required | -| ---------------- | ---------------------------------------------------------- | ----------------- | -------- | -| Emulator | A built-in (or custom) emulator | Dolphin | ✓ | -| Emulator Profile | A built-in (or custom) emulator profile | Nintendo GameCube | ✓ | -| Platform | The platform or console | Nintendo GameCube | ✓ | -| Destination Path | The path where downloaded ROMs will be stored | `C:\roms\gc` | ✓ | -| Auto-extract | Whether compressed files should be extracted automatically | | | -| Enabled | Whether the mapping is enabled | | | - -## Importing your library - -Once you've set up the plugin, you can import your library by going to `Menu` -> `Library` -> `Import RomM library`. All games matching the emulator path mappings will be imported into Playnite. - -Installing a game will download it from RomM and store it in the destination path. You can then launch the game from Playnite, and it will be launched using the configured emulator. - -By default, compressed files will be extracted automatically into a folder matching the game's name. You can modify this behavior in the settings page. diff --git a/docs/Integrations/Tinfoil-integration.md b/docs/Integrations/Tinfoil-integration.md deleted file mode 100644 index 0d70a15f..00000000 --- a/docs/Integrations/Tinfoil-integration.md +++ /dev/null @@ -1,58 +0,0 @@ - - - -
- romm[tinfoil] isotipo -
- -Tinfoil is a homebrew application for the Nintendo Switch, primarily used for installing and managing software, including games and updates, that are not obtained through official channels. - -This will help you configure Tinfoil for your Switch to work with your RomM library. - -## Setup - -### Prepare - -Please note down the following in order to make this as smooth as possible, as well as some pre-reqs: - -- RomM updated to at least [3.5.0](https://github.com/rommapp/romm/releases/tag/3.5.0) -- Add `DISABLE_DOWNLOAD_ENDPOINT_AUTH=true` to your environment variables and restart the container -- The URL you use to access RomM - - This can either be `http` or `https` - - The system will prefer local access though to avoid reverse proxy issues -- Feed URL: `/api/feeds/tinfoil` -- The username and password you use to login to RomM - -### Configure - -Now it's time to configure your switch - Please follow the steps, this will assume you have Tinfoil installed and know how to use the basic functions of it. - -1. Open Tinfoil and go to File Browser -2. Scroll over to the selection and press - in order to access the new menu. -3. Enter these Options - - Protocol - `http` or `https` depending on your connection - - Host - Host of your RomM instance - - Port - Port of your RomM Instance - - Path - /api/feeds/tinfoil - - Username - Username of your RomM instance - - Password - Password of your RomM instance - - Title - Free text title, make it whatever you want. - - Enabled - Yes -4. Press X to save -5. Now close out of Tinfoil and go back in, so it can scan the TitleIDs - if everything is correct you will have this custom `motd`: - " RomM Switch Library" - -Now you will be able to see the files in "New Games" tab of Tinfoil OR you can access it within the "File Browser" section that you setup earlier. - -![Image of Tinfoil](../resources/tinfoil/tinfoilscreen.jpg) - -### Additional - -It didn't pull anything through to "New Games" and has not parsed any information about the titles?! - -That would be because the filename it has tried to pull had no TitleID (Improvement to RomM coming soon :tm:) - -Make sure the filename has the TitleID within the title like this: -![TitleID](../resources/tinfoil/titleid.jpg) - -Once this is done, the next time Tinfoil is opened it is always parsed and re-scanned. diff --git a/docs/Integrations/muOS-app.md b/docs/Integrations/muOS-app.md deleted file mode 100644 index 59e896ca..00000000 --- a/docs/Integrations/muOS-app.md +++ /dev/null @@ -1,34 +0,0 @@ - - - -
- romm[muos] isotipo -
- -muOS is a Custom Firmware (CFW) primarily for handheld devices. Configurable, themeable, friendly, easy-to-use. - -The muOS app connects to your RomM instance and allows you to fetch games wirelessly from your Anbernic device. - -## Setup - -### muOS - -We leverage the muOS [Archive Manager](https://muos.dev/installation/archive) to install/update the app. - -1. Head to the [latest release](https://github.com/rommapp/muos-app/releases/latest) and download the `RomM.muOS.x.x.x.muxapp` file. -2. Move the muxapp file to `/mnt/mmc/ARCHIVE` on your device. -3. Launch the manager from `Applications > Archive Manager` and select `RomM.muOS.x.x.x.muxapp`. -4. Once installed, make a copy of `/mnt/mmc/MUOS/application/RomM/env.template`, rename it to `/mnt/mmc/MUOS/application/RomM/.env`, edit it (any method is fine, we recommend SSH) and set `HOST`, `USERNAME` and `PASSWORD`. -5. Launch the app from `Applications > RomM` and start browsing your collection. - -### EmulationStation - -We use PortMaster to install the app on devices running EmulationStation. - -1. Download the `RomM App.sh` file and `RomM/` folder to the `roms/ports` on your device. -2. Make the `RomM App.sh` file executable by running `chmod +x RomM App.sh`. -3. Launch EmulationStation and navigate to the `Ports` section. - - -!!! note - Your device must connect to your RomM instance or home server over Wi-Fi. The easiest method is to keep them on the same network and set HOST to the server's IP and the port where RomM is running. Advanced users or those using reverse proxies can configure their network and DNS settings as needed, using a URL with a domain like `https://romm.domain.com`. diff --git a/docs/Integrations/pkgj-integration.md b/docs/Integrations/pkgj-integration.md deleted file mode 100644 index ddbd1cfa..00000000 --- a/docs/Integrations/pkgj-integration.md +++ /dev/null @@ -1,38 +0,0 @@ - - - -pkgj is a homebrew application for the PS Vita, primarily used for installing PS Vita and PSP Games. While its default configuration talks to a set of pre-defined URLs, you can configure it to talk to custom feeds. - -This will help you install PSP or PS Vita games from your RomM library over Wi-Fi - -## Setup - -### Prepare - -Please note down the following in order to make this as smooth as possible, as well as some pre-reqs: - -- Your PS Vita should already have the following installed: - - pkgj - - A method to access files to edit on your Vita, such as VitaShell -- The URL you use to access RomM - - This can either be `http` or `https` -- Feed URLs: - - `/api/feeds/pkgi/psp/game` - - `/api/feeds/pkgi/psp/dlc` - - `/api/feeds/pkgi/psvita/game` - - `/api/feeds/pkgi/psvita/dlc` - -### Configure - -1. Connect your PS Vita to your PC over USB using VitaShell -2. Open `/pkgj/config.txt` in a text editor to add the feed URLs -3. If you have PS Vita games in `.pkg` format, add a `url_games {romm_url}/api/feeds/pkgi/psvita/game` to the end of the file -4. If you have PS Vita DLCs in `.pkg` format, add a `url_dlcs {romm_url}/api/feeds/pkgi/psvita/dlc` to the end of the file -5. If you have PSP games in `.pkg` format, add a `url_psp_games {romm_url}/api/feeds/pkgi/psp/game` to the end of the file -6. If you have PSP DLCs in `.pkg` format, add a `url_psp_dlcs {romm_url}/api/feeds/pkgi/psp/dlc` to the end of the file -7. Save the file and disconnect from VitaShell -8. Open pkgj, Press `△` to open the menu and select "Refresh" - -### Additional - -If, during a Refresh, pkgj presents an error saying "can't get list: list is empty...", check whether you have any Games/DLCs for the feeds you've added in `.pkg` format. RomM won't list any Games in other formats such as `.iso`. diff --git a/docs/Maintenance/Migrating-to-new-machine.md b/docs/Maintenance/Migrating-to-new-machine.md deleted file mode 100644 index d3a31790..00000000 --- a/docs/Maintenance/Migrating-to-new-machine.md +++ /dev/null @@ -1,93 +0,0 @@ - - -## Migrating RomM to a new system - -Migrating RomM to a new system is possible, but all of the docker volumes must be copied for RomM to run correctly. - -Following the the setup in the [Quick Start Guide](https://docs.romm.app/latest/Getting-Started/Quick-Start-Guide/#build) these volumes are created be default - -RomM should be stopped before following this guide. - -```yaml -volumes: - mysql_data: - romm_resources: - romm_redis_data: - -services: - romm: - volumes: - - romm_resources - - romm_redis_data - romm-db: - volumes: - - mysql_data -``` - -These volumes will need to manually moved to the new system. This is a straightforward process that includes determining their location and then copying them. - -### Determining the docker root directory and copying the volumes - -1. First determine the docker root directory - -```bash -docker info | grep 'Docker Root Dir' -``` - -The expected output on a standard linux system: - -```bash -Docker Root Dir: /var/lib/docker -``` - -2. Double check that the volumes have been created by docker and are owned by the docker engine - -```bash -docker volume ls -``` - -Following the default quick start guide the following volumes will have been made - -```bash -DRIVER VOLUME NAME -local romm_mysql_data -local romm_romm_redis_data -local romm_romm_resources -``` - -3. Inspect each volume to get the exact location of the volume data - -```bash -docker volume inspect romm_mysql_data | grep Mountpoint -``` - -- The output of the `docker inspect` will return the exact storage location of the volumes data - -```bash -"Mountpoint": "/var/lib/docker/volumes/romm_mysql_data/_data", -``` - -4. Copy those volumes into a new location so that they can be safely migrated to a new system **each volume needs to be in its own folder** - -```bash -cp -r /var/lib/docker/volumes/romm_mysql_data/_data/ /your/new/path/romm_mysql_data - -cp -r /var/lib/docker/volumes/romm_romm_redis_data/_data /your/new/path/romm_romm_redis_data - -cp -r /var/lib/docker/volumes/romm_romm_resources/_data /your/new/path/romm_romm_resources -``` - -5. Update the `docker-compose.yml` volume paths with the newly copied data to determine RomM still loads correctly. - -```yaml -services: - romm: - volumes: - - /your/new/path/romm_romm_resources # romm_resources - - /your/new/path/romm_romm_redis_data # romm_redis_data - romm-db: - volumes: - - /your/new/path/romm_mysql_data # mysql_data -``` - -If RomM starts up correctly, then it is safe to copy all of your RomM folders to a new system. diff --git a/docs/Maintenance/Scheduled-Tasks.md b/docs/Maintenance/Scheduled-Tasks.md deleted file mode 100644 index 741589d2..00000000 --- a/docs/Maintenance/Scheduled-Tasks.md +++ /dev/null @@ -1,43 +0,0 @@ - - -## Scheduled tasks - -Scheduled tasks can be enabled and configured with the following environment variables: - -| Variable | Description | Value | -| ------------------------------------------ | ------------------------------------------------------------ | :-----------: | -| ENABLE_SCHEDULED_RESCAN | Enable scheduled re-scanning of library | `true` | -| SCHEDULED_RESCAN_CRON | Cron expression for scheduled re-scanning | `"0 3 * * *"` | -| ENABLE_SCHEDULED_UPDATE_SWITCH_TITLEDB | Enable scheduled updating of Switch TitleDB index | `true` | -| SCHEDULED_UPDATE_SWITCH_TITLEDB_CRON | Cron expression for scheduled updating of Switch TitleDB | `"0 4 * * *"` | -| ENABLE_SCHEDULED_UPDATE_LAUNCHBOX_METADATA | Enable scheduled updating of LaunchBox metadata | `true` | -| SCHEDULED_UPDATE_LAUNCHBOX_METADATA_CRON. | Cron expression for scheduled updating of LaunchBox metadata | `"0 5 * * *"` | - -### Scheduled re-scan - -Users can opt to enable scheduled re-scans, and set the interval using Cron notation. Not that the scan will **not completely re-scan** every file, only catching those which have been added/updated. - -### Switch titleDB update - -Support was added for Nintendo Switch ROMs with filenames using the [titleid/programid format](https://wiki.gbatemp.net/wiki/List_of_Switch_homebrew_titleID) (e.g. 0100000000010000.xci). If a file under the `switch` folder matches the regex, the scanner will use the index to attempt to match it to a game. If a match is found, the IGDB handler will use the matched name as the search term. - -The associated task updates the `/fixtures/switch_titledb.json` file at a regular interval to support new game releases. - -### LaunchBox metadata update - -RomM can also update the LaunchBox metadata database at a regular interval. This is onyl useful if you've enabled the LaunchBox metadata provider. The database is updated by downloading the latest version from the [LaunchBox Games Database](https://gamesdb.launchbox-app.com/) and replacing the existing one. - -## File system watcher - -RomM can also monitor the filesystem for events (files created/moved/deleted) and schedules a re-scan of the platform (or entire library is a new platform was added). - -The watcher can be enabled and configured with the following environment variables: - -| Variable | Description | Value | -| ---------------------------------- | ------------------------------------------------------------------- | :----: | -| ENABLE_RESCAN_ON_FILESYSTEM_CHANGE | Enable re-scanning of library when filesystem changes | `true` | -| RESCAN_ON_FILESYSTEM_CHANGE_DELAY | Delay in minutes before re-scanning library when filesystem changes | `5` | - -The watcher will monitor the `/library/roms` folder for changes to the filesystem, such as files being added, moved or deleted. It will ignore certain events (like modifying the file content or metadata), and will skip default OS files (like `.DS_Store` on mac). - -When a change is detected, a scan will be scheduled for sometime in the future (default 5 minutes). If other events are triggered between now and the time at which the scan starts, more platforms will be added to the scan list (or the scan may switch to a full scan). This is done to reduce the number of tasks scheduled when many big changes happen to the library (mass upload, new mount, etc.) diff --git a/docs/Maintenance/Upgrading-to-3.0.md b/docs/Maintenance/Upgrading-to-3.0.md deleted file mode 100644 index b5fbc8d8..00000000 --- a/docs/Maintenance/Upgrading-to-3.0.md +++ /dev/null @@ -1,61 +0,0 @@ - - -Version 3.0 of RomM introduces a number of breaking changes aimed at improving performance and usability, which will require some users to make specific changes before upgrading to ensure compatibility and to take full advantage of the new features. - -All of the following changes are reflected in the [example docker-compose.yml file](https://github.com/rommapp/romm/blob/master/examples/docker-compose.example.yml), which has been simplified greatly. **Please read this entire file carefully, as failing to do so may cause RomM to become inaccessible or unresponsive.** - -## Dropped support for SQLite - -We're removed support for SQLite as we've faced a number of engineering issues with it in the past, and MariaDB has proven more stable and robust. If you currently use SQLite, we'll automatically migrate your data from SQLite to MariaDB, but you'll **first need to make the following changes before upgrading to the latest image.** - -In your environment variables, change `ROMM_DB_DRIVER` to `mariadb` (or remove it completely as it's no longer needed). You'll then want to add the following environment variables: - -```yaml -- DB_HOST=mariadb -- DB_PORT=3306 -- DB_NAME=romm # Should match MYSQL_DATABASE in mariadb -- DB_USER=romm-user # Should match MYSQL_USER in mariadb -- DB_PASSWD= # Should match MYSQL_PASSWORD in mariadb -``` - -To setup a new MariaDB container, have a look at the [example docker-compose.yml file](https://github.com/rommapp/romm/blob/master/examples/docker-compose.example.yml). - -## Authentication as standard - -To support new features like EmulatorJS and saves/states management, we've decided to require authentication for all users. Anyone currently running RomM with authentication disabled will need to remove the `ROMM_AUTH_ENABLED` environment variable and add the following ones: - -```yaml -- ROMM_AUTH_SECRET_KEY= # Generate a key with `openssl rand -hex 32` -``` - -We understand that this requirement for authentication might conflict with the way some users currently share their collection with others (unrestricted access for all). However, given the exciting new features we've built, and the ones we're looking to build in the near future, we feel this is the right decision for the project. - -## Redis is now built-in - -As Redis is [required for authentication](../Getting-Started/Authentication.md) to work, we've integrated it directly into the docker image. If you're currently running the experimental Redis container, you can remove it, along with these environment variables: - -```yaml -- ENABLE_EXPERIMENTAL_REDIS -- REDIS_HOST -- REDIS_PORT -``` - -## Configuration folder - -Mounting the `config.yml` file is now done by mounting a `config` folder.. Place your existing `config.yml` file inside a folder and bind it to `/romm/config`: - -```yaml -- /path/to/config:/romm/config -``` - -Updated [config.example.yml](https://github.com/rommapp/romm/blob/master/examples/config.example.yml) - -## Support for saves, states and screenshots - -This version introduces preliminary support for uploading/downloading saves, states and screenshots (read more about it in the 3.0 release notes). We've added a new volume mapping for these types of files called `assets`, which you'll want to bind to a local folder (or volume) so they'll persist. In your volumes section, add the following mapping, where `/path/to/assets/` is some folder where you'll want to store these assets (and make sure that folder exists): - -```yaml -- /path/to/assets:/romm/assets -``` - -We recommend creating a folder next to your `library`/the one mapped to `/romm/library` in order to keep all your RomM files in the same place. diff --git a/docs/Miscellaneous/Brand-Guidelines.md b/docs/Miscellaneous/Brand-Guidelines.md deleted file mode 100644 index 8c024baf..00000000 --- a/docs/Miscellaneous/Brand-Guidelines.md +++ /dev/null @@ -1,64 +0,0 @@ - - - -We’ve put together some guidelines for those anyone who wants to use our name and logo. In this context, "RomM", "The RomM Project", "the project", "we", "us", and "our" refer to the RomM project. - -## The Logo - -
- romm isotipo -
-
- -The logo should always be used in its standard colors: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ColorHex Code
#371f69#371f69
#553e98#553e98
#ede5f8#ede5f8
#bea4e1#bea4e1
#e6c7a7#e6c7a7
#e1a38d#e1a38d
-
- -![Branding guidelines](../resources/romm/brand_guidelines/poster.png) - -## Do these things - -- Use our logo to link to any page or site owned or operated by the project. -- Use our logo in a blog post or news article about the project. -- Use our logo to inform others that your project integrates with RomM. -- Always use our logo in the colors provided. -- Always use our name in a way that makes it clear you are not affiliated with the project. - -If you're working on a project that integrates with RomM and would like to use/remix the logo, **please reach out to us first**. We'd love to hear about what you're working on! - -## Please don't do these things - -- Use our name or logo in any way that would suggest you are us, are endorsed by us, or are part of the project. -- Use our name or logo in a way that implies partnership, sponsorship, or endorsement. -- Use our name or logo as the name or logo for your project, product, service, social media account, company, or website. -- Use our name or logo to promote, advertise or sell any private business, closed-source software, commercial product, or paid service. diff --git a/docs/Miscellaneous/FAQs.md b/docs/Miscellaneous/FAQs.md deleted file mode 100644 index 6bb71f5e..00000000 --- a/docs/Miscellaneous/FAQs.md +++ /dev/null @@ -1,17 +0,0 @@ - - -### When will the next version of RomM be available? - -When it's ready. - -### When will the version after that one release? - -After the upcoming version is released. - -### When will X feature be available? - -Sometime between now and the heat death of the universe. - -### When will version `x.x.x` of RomM (or any of the RomM clients/apps/plugins) be released? - -Same as above question. diff --git a/docs/Navigation.md b/docs/Navigation.md index 2888b091..22ba5b90 100644 --- a/docs/Navigation.md +++ b/docs/Navigation.md @@ -7,56 +7,93 @@ search: - [Introduction](index.md) - Getting Started - - [Quick Start Guide](Getting-Started/Quick-Start-Guide.md) - - [Folder Structure](Getting-Started/Folder-Structure.md) - - [Configuration File](Getting-Started/Configuration-File.md) - - [Metadata Providers](Getting-Started/Metadata-Providers.md) - - [Environment Variables](Getting-Started/Environment-Variables.md) - - [Reverse Proxy](Getting-Started/Reverse-Proxy.md) -- Platforms and Players - - [Supported Platforms](Platforms-and-Players/Supported-Platforms.md) - - Web Players - - [EmulatorJS](Platforms-and-Players/EmulatorJS-Player.md) - - [MS-DOS](Platforms-and-Players/MS-DOS.md) - - [RuffleRS](Platforms-and-Players/RuffleRS-Player.md) - - [Custom Platforms](Platforms-and-Players/Custom-Platforms.md) -- System Setup Guides - - [Unraid](System-Setup/Unraid-Setup-Guide.md) - - [With Docker Compose](System-Setup/Unraid-Compose-Setup.md) - - [Synology Setup](System-Setup/Synology-Setup-Guide.md) - - [TrueNAS Setup](System-Setup/TrueNAS-Setup-Guide.md) -- Usage - - [User Management](Usage/UserManagement.md) - - [Library Management](Usage/LibraryManagement.md) - - [Administration](Usage/Administration.md) -- OIDC Setup - - [OIDC Setup](Getting-Started/OIDC-Setup.md) - - [With Authelia](OIDC-Guides/OIDC-Setup-With-Authelia.md) - - [With Authentik](OIDC-Guides/OIDC-Setup-With-Authentik.md) - - [With PocketID](OIDC-Guides/OIDC-Setup-With-PocketID.md) - - [With Zitadel](OIDC-Guides/OIDC-Setup-With-Zitadel.md) + - [Quick Start](getting-started/quick-start.md) + - [Folder Structure](getting-started/folder-structure.md) + - [Your First Scan](getting-started/first-scan.md) +- Install & Deploy + - [Overview](install/index.md) + - [Image Variants](install/image-variants.md) + - [Databases](install/databases.md) + - [Redis or Valkey](install/redis-or-valkey.md) + - [Reverse Proxy](install/reverse-proxy.md) + - [Unraid](install/unraid.md) + - [Synology](install/synology.md) + - [TrueNAS](install/truenas.md) + - [Kubernetes](install/kubernetes.md) + - [Backup & Restore](install/backup-and-restore.md) +- Administration + - [Overview](administration/index.md) + - [Users & Roles](administration/users-and-roles.md) + - [Invitations & Registration](administration/invitations-and-registration.md) + - [Authentication](administration/authentication.md) + - OIDC Setup + - [Overview](administration/oidc/index.md) + - [Authelia](administration/oidc/authelia.md) + - [Authentik](administration/oidc/authentik.md) + - [Keycloak](administration/oidc/keycloak.md) + - [PocketID](administration/oidc/pocketid.md) + - [Zitadel](administration/oidc/zitadel.md) + - [Metadata Providers](administration/metadata-providers.md) + - [Scanning & Watcher](administration/scanning-and-watcher.md) + - [Scheduled Tasks](administration/scheduled-tasks.md) + - [Server Stats](administration/server-stats.md) + - [Observability](administration/observability.md) + - [Firmware Management](administration/firmware-management.md) +- Using RomM + - [Overview](using/index.md) + - [Collections](using/collections.md) + - [Smart Collections](using/smart-collections.md) + - [Virtual Collections](using/virtual-collections.md) + - [Downloads](using/downloads.md) + - [Uploads](using/uploads.md) + - In-Browser Play + - [EmulatorJS](using/in-browser-play/emulatorjs.md) + - [MS-DOS](using/in-browser-play/ms-dos.md) + - [Ruffle](using/in-browser-play/ruffle.md) + - [Saves & States](using/saves-and-states.md) + - [RetroAchievements](using/retroachievements.md) + - [ROM Patcher](using/rom-patcher.md) + - [Netplay](using/netplay.md) + - [Console Mode](using/console-mode.md) + - [Account & Profile](using/account-and-profile.md) + - [Languages](using/languages.md) +- Platforms & Players + - [Overview](platforms/index.md) + - [Supported Platforms](platforms/supported-platforms.md) + - [Custom Platforms](platforms/custom-platforms.md) +- Integrations & Ecosystem + - [Overview](ecosystem/index.md) + - [First-Party Apps](ecosystem/first-party-apps.md) + - [Feed Clients](ecosystem/feed-clients.md) + - [Igir Collection Manager](ecosystem/igir.md) - API & Development - - [Development Setup](API-and-Development/Development-Setup.md) - - [API Reference](API-and-Development/API-Reference.md) - - [Authentication](Getting-Started/Authentication.md) - - [Contributing](API-and-Development/Contributing.md) -- Tools - - [Igir Collection Manager](Tools/Igir-Collection-Manager.md) -- Maintenance - - [Scheduled Tasks](Maintenance/Scheduled-Tasks.md) - - [Migrating RomM](Maintenance/Migrating-to-new-machine.md) - - [Upgrading to 3.0](Maintenance/Upgrading-to-3.0.md) -- Integrations - - [Playnite plugin](Integrations/Playnite-plugin.md) - - [muOS app](Integrations/muOS-app.md) - - [Tinfoil Integration](Integrations/Tinfoil-integration.md) - - [pkgj Integration](Integrations/pkgj-integration.md) + - [Overview](developers/index.md) + - [API Reference](developers/api-reference.md) + - [API Authentication](developers/api-authentication.md) + - [Client API Tokens](developers/client-api-tokens.md) + - [WebSockets](developers/websockets.md) + - [Device Sync Protocol](developers/device-sync-protocol.md) + - [SSH Sync](developers/ssh-sync.md) + - [Consuming OpenAPI](developers/openapi.md) + - [Development Setup](developers/development-setup.md) + - [Architecture](developers/architecture.md) + - [Contributing](developers/contributing.md) + - [Translations (i18n)](developers/i18n.md) +- Reference + - [Environment Variables](reference/environment-variables.md) + - [Configuration File](reference/configuration-file.md) + - [Exports](reference/exports.md) + - [Glossary](reference/glossary.md) - Troubleshooting - - [Scanning Issues](Troubleshooting/Scanning-Issues.md) - - [Authentication Issues](Troubleshooting/Authentication-Issues.md) - - [Synology Issues](Troubleshooting/Synology-Issues.md) - - [Miscellaneous Issues](Troubleshooting/Miscellaneous-Troubleshooting.md) - - [Kubernetes Issues](Troubleshooting/Kubernetes-Issues.md) -- Miscellaneous - - [FAQs](Miscellaneous/FAQs.md) - - [Branding Guidelines](Miscellaneous/Brand-Guidelines.md) + - [Overview](troubleshooting/index.md) + - [Scanning](troubleshooting/scanning.md) + - [Authentication](troubleshooting/authentication.md) + - [In-Browser Play](troubleshooting/in-browser-play.md) + - [Netplay](troubleshooting/netplay.md) + - [Synology](troubleshooting/synology.md) + - [Kubernetes](troubleshooting/kubernetes.md) +- About + - [FAQs](about/faqs.md) + - [Brand Guidelines](about/brand-guidelines.md) + - [License](about/license.md) + - [Credits](about/credits.md) diff --git a/docs/OIDC-Guides/OIDC-Setup-With-Authelia.md b/docs/OIDC-Guides/OIDC-Setup-With-Authelia.md deleted file mode 100644 index 44594913..00000000 --- a/docs/OIDC-Guides/OIDC-Setup-With-Authelia.md +++ /dev/null @@ -1,96 +0,0 @@ -# OIDC Setup With Authelia - -## A quick rundown of the technologies - -### What is Authelia? - -Authelia is an open-source authentication and authorization server providing two-factor authentication and single sign-on (SSO) for your applications via a web portal. It acts as a companion for reverse proxies by allowing, denying, or redirecting requests. Authelia can be deployed alongside your other services to centralize identity management. - -## Setting up a Provider and Application in Authelia - -### Step 1: Install and Configure Authelia - -Before setting up a provider and app, ensure that Authelia is installed and running by following the [getting started](https://www.authelia.com/integration/prologue/get-started/) and [OIDC provider](https://www.authelia.com/configuration/identity-providers/openid-connect/provider/) guides. - -### Step 2: Add a client - -First, in Authelia's `configuration.yml`, at `identity_providers` → `oidc` → `claims_policies` you'll need to add a Claims Policy if you do not already have one with the specified claims: - -```yaml -# identity_providers: -# oidc: -claims_policies: - with_email: # You can name this however you want - id_token: - [ - "email", - "email_verified", - "groups", - "alt_emails", - "preferred_username", - "name", - ] -``` - -To read more about claims_policies and why you need it for RomM, see [this section in the Authelia docs](https://www.authelia.com/integration/openid-connect/openid-connect-1.0-claims/#restore-functionality-prior-to-claims-parameter). - -Then, in the same `configuration.yml`, under `identity_providers` → `oidc` → `clients`, add a new entry: - -- A **random** `client_id` and `client_secret` - - See the [official recommendations](https://www.authelia.com/integration/openid-connect/frequently-asked-questions/#how-do-i-generate-a-client-identifier-or-client-secret) on how to generate these. -- `public` should be set to `false`. -- `redirect_uris` should include your RomM instance's URL + `/api/oauth/openid` (e.g., `http://romm.host.local/api/oauth/openid`). -- `claims_policy` is the name of the entry at claims_policies that you just added (or already had). -- `scopes` includes `openid`, `email` and `profile`. -- `token_endpoint_auth_method` should be set to `client_secret_basic`. -- `userinfo_signed_response_alg` should be set to `none`. - -Refer to the [official docs](https://www.authelia.com/configuration/identity-providers/openid-connect/clients/) for more details. - -This entry should look like this: - -```yaml -#identity_providers: -# oidc: -# clients: -- client_id: "" # read above for how generate - client_name: "RomM" # will be displayed in Authelia to users - client_secret: "$pbkdf2-sha512$randomly_generated" # read above for how generate - public: false - authorization_policy: "two_factor" # or one_factor, depending on your needs - grant_types: - - authorization_code - redirect_uris: - - "http://romm.host.local/api/oauth/openid" - claims_policy: "with_email" - scopes: - - "openid" - - "email" - - "profile" - - "groups" - userinfo_signed_response_alg: "none" - token_endpoint_auth_method: "client_secret_basic" -``` - -### Step 3: Configure RomM Environment Variables - -To enable OIDC authentication in RomM, you need to set the following environment variables: - -- `OIDC_ENABLED`: Set to `true` to enable OIDC authentication. -- `OIDC_PROVIDER`: The lowercase name of the provider (`authelia`). -- `OIDC_CLIENT_ID`: The client ID copied from the Authelia application. -- `OIDC_CLIENT_SECRET`: The generated output from `Random Password`. -- `OIDC_REDIRECT_URI`: The redirect URI configured in the Authelia provider, in the format `http://romm.host.local/api/oauth/openid`. -- `OIDC_SERVER_APPLICATION_URL`: The base URL for you Authelia instance, e.g. `http://authelia.host.local`. - -### Step 4: Set your Email in RomM - -In RomM, open your user profile and set your email address. This email **has to match** your user email in Authelia. - -![Set email](../resources/authelia/1-user-profile.png) - -### Step 5: Test the Integration - -After configuring the environment variables, restart (or stop and remove) your RomM instance and navigate to the login page. You should see an option to log in using OIDC. Click on the OIDC button, and you'll be redirected to Authelia for authentication. Once authenticated, you'll be redirected back to RomM. - -![Login with OIDC](../resources/authelia/2-romm-login.png) diff --git a/docs/OIDC-Guides/OIDC-Setup-With-Authentik.md b/docs/OIDC-Guides/OIDC-Setup-With-Authentik.md deleted file mode 100644 index c4af0328..00000000 --- a/docs/OIDC-Guides/OIDC-Setup-With-Authentik.md +++ /dev/null @@ -1,99 +0,0 @@ -# OIDC Setup With Authentik - -## A quick rundown of the technologies - -### What is Authentik? - -Authentik is an open-source identity provider (IdP) designed to manage authentication, authorization, and user management across applications. It supports modern authentication protocols and provides tools to simplify integration, including single sign-on (SSO), multi-factor authentication (MFA), and auditing capabilities. Authentik can be deployed alongside your other services to centralize identity management. - -## Setting up a Provider and Application in Authentik - -### Step 1: Install and Configure Authentik - -Before setting up a provider and app, ensure that Authentik is installed and running by following the [official installation guide.](https://docs.goauthentik.io/docs/install-config/install/docker-compose). - -1. Access Authentik via its web interface. -2. Log in as an administrator. -3. Navigate to the “Admin Interface” to configure the necessary components. - -![Authentik user dashboard](../resources/authentik/1-user-dashboard.png) - -### Step 2: Create a Property Mapping - -In version 2025.10 Authentik changed their default value for the `email_verified` field from true to false. -Since RomM requires a verified email address, without this property, the authentication would fail. - -1. **Navigate to Property Mappings** - - Go to the "Property Mappings" section in the Authentik admin interface `Customization > Property Mappings` -2. **Create a new Property Mapping** - - Select "Scope Mapping" - - Enter a Name like "RomM Email Verification" - - Set `email` as scope name. - - Set the following as the expression: - ```py - return { - "email": user.email, - "email_verified": True, - } - ``` - - It should look like this - ![Propperty Mapping](../resources/authentik/propperty-mapping.png) -3. **Click Create**. - -[Authentik docs reference](https://version-2025-10.goauthentik.io/add-secure-apps/providers/property-mappings/#scope-mappings-with-oauth2) - -### Step 3: Create a Provider - -A provider in Authentik acts as the bridge between RomM and Authentik. - -1. **Navigate to Providers**: - - Go to the "Providers" section in the Authentik admin interface. -2. **Create a New Provider**: - - Click on “Create” and choose the protocol (e.g., “OIDC Provider”). - ![Create a new provider](../resources/authentik/2-create-provider.png) -3. **Select "OAuth2/OpenID Provider"** - ![Select OAuth2 provider](../resources/authentik/3-new-provider.png) -4. **Configure Provider Settings**: - - **Name**: Assign a unique name to the provider (e.g., "RomM OIDC Provider"). - - **Authorization flow**: Select **implicit consent**. - - **Redirect URIs**: Add your RomM instance's URL + `/api/oauth/openid` (e.g., `http://romm.host.local/api/oauth/openid`). - - **Scopes**: Under "Advanced protocol settings", move the property mapping you created above from "Available Scopes" to "Selected Scopes". You'll also need to make sure any existing mappings of `email` or `email_verified` are disabled. Authentik has an `email` mapping by default, so make sure to check for this and remove it if it's present. -5. **Copy the Client ID and Secret**: - - You'll need these to set `OIDC_CLIENT_ID` and `OIDC_CLIENT_SECRET` in your RomM instance. - ![Provider settings](../resources/authentik/4-provider-secrets.png) -6. **Click Create**. - -### Step 3: Register an Application - -An app in Authentik represents the external service (in our case RomM) that will use the provider for authentication. - -1. **Navigate to Applications**: - - Go to the "Applications" section in the admin interface. - ![Applications](../resources/authentik/5-applications.png) -2. **Create a New Application**: - - Click on “Create” and configure the app settings: - **Name**: Provide a recognizable name (e.g., "RomM"). - **Slug**: Create a unique identifier for the app (e.g., `romm`). - **Provider**: Link the app to the previously created provider, "RomM OIDC Provider". - ![New application](../resources/authentik/6-new-application.png) -3. **Click Create**. - -### Step 4: Configure RomM Environment Variables - -To enable OIDC authentication in RomM, you need to set the following environment variables: - -- `OIDC_ENABLED`: Set to `true` to enable OIDC authentication. -- `OIDC_PROVIDER`: The lowercase name of the provider (`authentik`). -- `OIDC_CLIENT_ID`: The client ID copied from the Authentik application. -- `OIDC_CLIENT_SECRET`: The client secret copied from the Authentik application. -- `OIDC_REDIRECT_URI`: The redirect URI configured in the Authentik provider, in the format `http://romm.host.local/api/oauth/openid`. -- `OIDC_SERVER_APPLICATION_URL`: The URL of the Authentik application, e.g., `http://authentik.host.local/application/o/romm`. - -### Step 5: Set your Email in RomM - -In RomM, open your user profile and set your email address. This email **has to match** your user email in Authentik. - -![Set email](../resources/authentik/7-user-profile.png) - -### Step 6: Test the Integration - -After configuring the environment variables, restart (or stop and remove) your RomM instance and navigate to the login page. You should see an option to log in using OIDC. Click on the OIDC button, and you'll be redirected to Authentik for authentication. Once authenticated, you'll be redirected back to RomM. - -![Login with OIDC](../resources/authentik/8-romm-login.png) diff --git a/docs/OIDC-Guides/OIDC-Setup-With-Keycloak.md b/docs/OIDC-Guides/OIDC-Setup-With-Keycloak.md deleted file mode 100644 index d4becc0f..00000000 --- a/docs/OIDC-Guides/OIDC-Setup-With-Keycloak.md +++ /dev/null @@ -1,67 +0,0 @@ -# OIDC Setup With Keycloak - -## A quick rundown of the technologies - -### What is Keycloak? - -Keycloak is an open-source Identity and Access Management solution that provides single sign-on (SSO), OpenID Connect (OIDC), OAuth2, amongst other protocols. - -## Setting up a Provider and Application in Keycloak - -### Step 1: Install or access Keycloak - -Before setting up the OIDC client, ensure that Keycloak is installed and running by following the [setup guide](https://www.keycloak.org/getting-started). - -Log into the Admin Console and either create a new realm for RomM or reuse an existing one. - -### Step 2: Add a client - -1. In the Admin Console select your realm → **Clients** → **Create client**. -2. Leave `Client type` as `OpenID Connect` and enter a `Client ID` (for example `romm`). Click **Next**. -3. On the next page: - - Enable **Client authentication**. - - Leave only the **Standard flow** option enabled. - - Click **Next**. -4. Set the following URLs: - - **Root URL**: `http://romm.host.local` (replace with your RomM URL) - - **Valid Redirect URIs**: `http://romm.host.local/api/oauth/openid` (replace with your RomM URL) - - **Web origins**: `http://romm.host.local` (replace with your RomM URL) -5. Go to the **Credentials** tab and copy the **Client Secret** — you'll need this for the RomM configuration. - -### Step 3: Configure RomM Environment Variables - -To enable OIDC authentication in RomM, you need to set the following environment variables: - -- `OIDC_ENABLED`: Set to `true` to enable OIDC authentication. -- `OIDC_PROVIDER`: The lowercase name of the provider (`keycloak`). -- `OIDC_CLIENT_ID`: The client ID copied from the Keycloak application. -- `OIDC_CLIENT_SECRET`: The generated output from `Random Password`. -- `OIDC_REDIRECT_URI`: The redirect URI configured in the Keycloak provider, in the format `http://romm.host.local/api/oauth/openid`. -- `OIDC_SERVER_APPLICATION_URL`: The base URL for you Keycloak instance including the realm name, e.g. `http://keycloak.host.local/realms/`. - -### Step 5: Set your Email in RomM - -In RomM, open your user profile and set your email address. This email **has to match** your user email in Keycloak. - -Open the Keycloak Admin Console → Users and mark each RomM user's email as verified. Users without verified emails will not be able to log in. - -### Step 6: Test the Integration - -After configuring the environment variables, restart (or stop and remove) your RomM instance and navigate to the login page. You should see the option "LOGIN WITH KEYCLOAK". Click on it and you'll be redirected to Keycloak for authentication. Once authenticated, you'll be redirected back to RomM. - -Note that if the user already exists in RomM, they will be logged in with their existing account and permissions. If it's a new user, an account will be created for them with viewer permissions by default. To change the permissions for new users, see Step 8 below. - -### Step 7: (Optional) Disable password logins - -If you want to enforce OIDC logins and disable password-based logins, set the environment variable `PASSWORD_AUTH_ENABLED` to `false`. This will hide the password login option on the login page, ensuring that all users must authenticate via Keycloak. - -### Step 8: (Optional) Configure permissions for new users - -By default, new users logging in via OIDC will be created with viewer permissions. If you want to change this default behavior, you can set the environment variables: - -- `OIDC_CLAIM_ROLES`: Set to the name of the claim that contains the user's role -- `OIDC_ROLE_VIEWER`: The value of the role claim that maps to viewer permissions -- `OIDC_ROLE_EDITOR`: The value of the role claim that maps to editor permissions -- `OIDC_ROLE_ADMIN`: The value of the role claim that maps to admin permissions - -Configure Keycloak to include the appropriate role claim in the token diff --git a/docs/OIDC-Guides/OIDC-Setup-With-PocketID.md b/docs/OIDC-Guides/OIDC-Setup-With-PocketID.md deleted file mode 100644 index 3d65525c..00000000 --- a/docs/OIDC-Guides/OIDC-Setup-With-PocketID.md +++ /dev/null @@ -1,52 +0,0 @@ -# OIDC Setup With Pocket ID - -## A quick rundown of the technologies - -### What is Pocket ID? - -Pocket ID is a simple OIDC provider that allows users to authenticate with their passkeys to your services. - -The goal of Pocket ID is to be a simple and easy-to-use. There are other self-hosted OIDC providers like Keycloak or ORY Hydra but they are often too complex for simple use cases. - -Additionally, what makes Pocket ID special is that it only supports passkey authentication, which means you don’t need a password. - -## Setting up a client in Pocket ID - -### Step 1: Install and Configure Pocket ID - -Before setting up the OIDC client, ensure that Pocket ID is installed and running by following the [setup guide](https://github.com/stonith404/pocket-id#setup). - -### Step 2: Add a client - -Once you have logged in and configured a PassKey you now need to create an OIDC client, this will let Pocket ID know about the application that needs to be configured, and will give you the relevant keys to add to the RomM compose file. - -- Make sure within Application Configuration that "Emails Verified" is ticked, most OIDC apps will need this. -- Go to OIDC Client -- Click Add OIDC Client - - Name: RomM - - Callback URLs: `https://{host}/api/oauth/openid` -- Click Save -- Stay on this page, you will be shown your client secret only THIS time. - -### Step 3: Configure RomM Environment Variables - -To enable OIDC authentication in RomM, you need to set the following environment variables: - -- `OIDC_ENABLED`: Set to `true` to enable OIDC authentication. -- `OIDC_PROVIDER`: The lowercase name of the provider (`pocket-id`). -- `OIDC_CLIENT_ID`: The client ID copied from the Pocket ID application -- `OIDC_CLIENT_SECRET`: The client secret that is showing within your Pocket ID application. -- `OIDC_REDIRECT_URI`: The redirect URI configured in the Pocket ID provider, in the format `https://{host}/api/oauth/openid`. -- `OIDC_SERVER_APPLICATION_URL`: The authorization URL for you Pocket ID instance, e.g. `https://id.host.local`. - -### Step 4: Set your Email in RomM - -In RomM, open your user profile and set your email address. This email **has to match** your user email in Pocket ID. - -![Set email](../resources/authelia/1-user-profile.png) - -### Step 5: Test the Integration - -After configuring the environment variables, restart (or stop and remove) your RomM instance and navigate to the login page. You should see an option to log in using OIDC. Click on the OIDC button, and you'll be redirected to Pocket ID for authentication. Once authenticated, you'll be redirected back to RomM. - -![Login with OIDC](../resources/pocketid/2-romm-login.png) diff --git a/docs/OIDC-Guides/OIDC-Setup-With-Zitadel.md b/docs/OIDC-Guides/OIDC-Setup-With-Zitadel.md deleted file mode 100644 index d4ad92b2..00000000 --- a/docs/OIDC-Guides/OIDC-Setup-With-Zitadel.md +++ /dev/null @@ -1,82 +0,0 @@ -# OIDC Setup With Zitadel - -## A quick rundown of the technologies - -### What is Zitadel - -Zitadel is an enterprise-grade, open-source identity and access management (IAM) platform that supports OAuth2, OpenID Connect, SAML, and passwordless authentication. It's used to manage users, roles, and secure login for web and cloud applications. - -## Setting up a client in Zitadel - -### Step 1: Install and Configure Zitadel - -Before setting up the OIDC client, ensure that Zitadel is installed and running by following the [setup guide](https://zitadel.com/docs/self-hosting/deploy/overview). - -### Step 2: Create a Project - -Once you have logged in and changed the default password for your Zitadel organization, create a new Project (i.e Romm). This will be the basic settings for roles and authorization. - -In the "General" tab, there are options to allow the following: - -- Assert Roles on Authentication - -Unnecessary: Romm (at this time) does not allow granting permissions based on role, everyone gets viewer and will have to be changed manually using an admin account if desired. - -- Check authorization on Authentication - -Recommended: If you allow registration to your platform, then anyone who registers can instantly access Romm (although only as a viewer, which may not be a problem for some) - -- Check for Project on Authentication - -Optional: It could be used if you plan on separating users by organizations for other applications, but creating separate organizations is not typically useful for general self-hosting purposes - -### Step 2.5 (Optional: If you enabled "Check authorization on Authentication"): Grant user(s) access to the Project - -Click on the Authorization tab and click New. - -Enter the user(s) and click Continue - -It should say "No role has been created yet.", but this is fine, you can just click Save and it should bring you back to the Authorization page with your user(s) listed with no roles - -### Step 3: Create the application - -On the General tab, click the New button under Applications. - -(Check "I'm a pro. Skip this wizard." to enter the information quicker) - -- `Name`: RomM (or whatever you want) -- `Application Type`: Web -- `Grant Types`: Authorization Code -- `Response Types`: Code -- `Authentication Method`: Basic -- `Redirect URIs`: `https://romm.domain.com/api/oauth/openid` -- `Post Logout URIs`: `https://romm.domain.com/` - -Click Create. - -- Stay on this page or copy these down elsewhere, the secret will only show **this one time** - -### Step 3: Configure RomM Environment Variables - -To enable OIDC authentication in RomM, you need to set the following environment variables: - -- `OIDC_ENABLED`: Set to `true` to enable OIDC authentication. -- `OIDC_PROVIDER`: The name of the provider `Zitadel`. -- `OIDC_CLIENT_ID`: The client ID copied from the Zitadel application -- `OIDC_CLIENT_SECRET`: The client secret generated from the Zitadel application -- `OIDC_REDIRECT_URI`: The redirect URI configured in Zitadel `https://rom.domain.com/api/oauth/openid`. -- `OIDC_SERVER_APPLICATION_URL`: The domain for your Zitadel instance `https://zitadel.domain.com`. (The discovery URL for Zitadel is on the basedomain under /.well-known/openid-configuration) - -### Step 4: Enable claims from ID Token (this resolves the "Email is missing from token" error) - -Click close to finish creating the application and then go to the Token Settings tab. - -Check "User Info inside ID Token" and click Save - -### Step 5: Set your Email in RomM - -For your existing RomM admin account, open your user profile on Zitadel and set your email address. This email **has to match** your user email in Zitadel. - -### Step 6: Test the Integration - -After configuring the environment variables, restart (or stop and remove) your RomM instance and navigate to the login page. You should see the option "LOGIN WITH ZITADEL". Click on it and you'll be redirected to Zitadel for authentication. Once authenticated, you'll be redirected back to RomM. diff --git a/docs/Platforms-and-Players/Custom-Platforms.md b/docs/Platforms-and-Players/Custom-Platforms.md deleted file mode 100644 index 7566bbdd..00000000 --- a/docs/Platforms-and-Players/Custom-Platforms.md +++ /dev/null @@ -1,12 +0,0 @@ - - - -While RomM supports every platform listed in the [Supported Platforms page](../Platforms-and-Players/Supported-Platforms.md), the list is not exhaustive, and you may have ROMs in your library for other platforms. To load those files into RomM, place them in a folder for each platform, and give it a name that's **all lowercase**, with **`-` to separate words**, and with **no white spaces**. For example, `pocket-challenge-v2` would map to `Pocket Challenge V2`, and display the default platform icon in the app. - -Furthermore, only a portion of the supported platforms have custom icons built-in. If your library has platforms that aren't listed in [the platforms icons list](https://github.com/rommapp/romm/tree/master/frontend/assets/platforms), RomM will display a default fallback icon. - -If you'd like to load your own custom icons for missing platforms, you can mount `/var/www/html/assets/platforms` to some local folder and place all of your custom **`.ico`** platform icons in there. You'll also want to download the ones [provided in this project](https://github.com/rommapp/romm/tree/master/frontend/assets/platforms) and place them in the same folder. If you'd like to use your own icons for platforms already supported by RomM, just replace the file with another using the exact same name. - -**The name of the `.ico` file should match the slug of the platform on IGDB.** For example, the URL for the AmstradCPC is , so the filename should be `acpc.ico`. - -Screenshot 2023-09-15 at 10 45 04 AM diff --git a/docs/Platforms-and-Players/EmulatorJS-Player.md b/docs/Platforms-and-Players/EmulatorJS-Player.md deleted file mode 100644 index 7f2cd198..00000000 --- a/docs/Platforms-and-Players/EmulatorJS-Player.md +++ /dev/null @@ -1,118 +0,0 @@ - - -[EmulatorJS](https://emulatorjs.org/) is a web-based emulator for various system; that is, it allows you to run old games in your web browser. It's based on [`RetroArch`](https://www.retroarch.com) compiled with [`Emscripten`](https://emscripten.org/), which is a toolchain for compiling C and C++ code to WebAssembly. - - -!!! warning - - Emulation is a complex and resource-intensive process. As such, it may not work well in all browser, especially older or less powerful ones. If you're having trouble running a game, try using a different browser or device. - - PSP emulation with the `ppsspp` core and MS-DOS with the `dosbox-pure` core are not currently supported when using the Console mode. - - -!!! note - Some platforms may require multiple BIOS/firmware files to be loaded at the same time. To do this, create a **ZIP archive** containing all the firmware files for the emulator you've selected and upload it to the **firmware** section of the platform. This ZIP file will be recognized by EmulatorJS as the firmware bundle for the platform. Refer to the [EmulatorJS documentation](https://emulatorjs.org/docs/systems/) for the required list of files for each platform. - -### Saves and states - -Our integration with EmulatorJS automates the process of loading and save files and save states. Before starting the game, select a save and/or state file to load (if one is available). Anytime you manually save the game (or create a save state) by clicking the save or "save and quit" buttons, the save and state files stored with RomM will be updated, so there's no need to manually download or upload them. - -### Netplay - - -!!! warning - Netplay is currently not available. We are looking to bring it back at a later date. If you are an existing Netplay user, please disable this feature. Leaving it on will result in `failed to start game` errors and other intermittent issues. - -Netplay lets you play with friends remotely, in realtime with the build-in web player. As it emulates playing on the same console with two controllers while streaming the video to players 2+, it's best for 2-player, co-op, turn based and party games. - -Start by enabling netplay in your `config.yml`: - -```yaml -emulatorjs: - netplay: - enabled: true -``` - -If you require ICE servers for NAT traversal, we recommend a free-tier [Metered](https://www.metered.ca/stun-turn) account. Create new "TURN Credentials" and replace `` and `` with the entries under "Show ICE Server Array": - -```yaml -emulatorjs: - netplay: - ice_servers: - - urls: "stun:stun.relay.metered.ca:80" - - urls: "stun:stun.relay.metered.ca:80" - - urls: "turn:global.relay.metered.ca:80" - username: "" - credential: "" - - urls: "turn:global.relay.metered.ca:80?transport=tcp" - username: "" - credential: "" - - urls: "turn:global.relay.metered.ca:443" - username: "" - credential: "" - - urls: "turns:global.relay.metered.ca:443?transport=tcp" - username: "" - credential: "" -``` - -Alternatively, use the free STUN servers from Google and TURN servers via the OpenRelayProject: - -```yaml -emulatorjs: - netplay: - ice_servers: - - urls: "stun:stun.l.google.com:19302" - - urls: "stun:stun1.l.google.com:19302" - - urls: "stun:stun2.l.google.com:19302" - - urls: "turn:openrelay.metered.ca:80" - username: "openrelayproject" - credential: "openrelayproject" - - urls: "turn:openrelay.metered.ca:443" - username: "openrelayproject" - credential: "openrelayproject" -``` - -To host a game, start it, then hit the 🌐 icon in botton bar. Set your name, create a room (password optional), and other players should be able to see and join your room. **All players need access to your RomM server to join a room and play together.** - - -!!! note - When netplay is enabled, EmulatorJS loads some assets (including localization files) from the nightly CDN (`https://cdn.emulatorjs.org/nightly/...`). This differs from stable mode, which uses local/bundled assets. Occasional temporary issues (e.g., 404 errors or untranslated UI elements) can occur if the nightly CDN has mismatches, but these usually resolve with the next EmulatorJS stable release integrated into RomM. - -### Supported systems - -Note that only the following systems are currently supported: - -- 3DO -- Amiga -- Arcade/MAME -- Atari 2600 -- Atari 5200 -- Atari 7800 -- Atari Jaguar -- Atari Lynx -- Commodore 64 -- ColecoVision -- DOOM -- Neo Geo Pocket -- Neo Geo Pocket Color -- MS-DOS -- Nintendo 64 -- Nintendo Entertainment System (NES) -- Nintendo Family Computer (Famicom) -- Nintendo DS -- Game Boy -- Game Boy Color -- Game Boy Advance -- PC-FX -- PlayStation (PS) -- PlayStation Portable (PSP) -- Sega 32X -- Sega CD -- Sega Game Gear -- Sega Master System -- Sega Genesis/Megadrive -- Sega Saturn -- Super Nintendo Entertainment System (SNES) -- Super Famicom -- TurboGraphx-16/PC Engine -- Virtual Boy -- WonderSwan -- WonderSwan Color diff --git a/docs/Platforms-and-Players/MS-DOS.md b/docs/Platforms-and-Players/MS-DOS.md deleted file mode 100644 index 17c60e46..00000000 --- a/docs/Platforms-and-Players/MS-DOS.md +++ /dev/null @@ -1,602 +0,0 @@ - - - -[DOS](https://github.com/schellingb/dosbox-pure) is now supported in versions of RomM 4.0 and above thanks to the EmulatorJS player - Simply create a DOS platform to enable the integration - - -!!! info - I highly suggest you upload the games as .zip as the core can take advantage of unzipping and auto mounting options which are explained more below. - - -!!! info - Loading and saving states ARE supported so it's possible you only need to do the below steps once to load the game. - -#### Running Games - -Once you have the play button in the platform available for you there is some additional work you need to do in order to get the games playable and running. You first need to identify what DOS game you are trying to run, there would be three categories - -- Homebrew - - Made by an indie dev, usually just an .exe file which will work fine in DOS once mounted. -- Demo - - Most sites which offer DOS games are shareware demo versions, these function similiar to homebrew and will have all the files needed within the folder. -- Retail - - These will need the CD mounted alongside the game files in order to play the games, this can get tricky and will be a unique per game basis but once you have cracked it you won't need to modify it again. - -The official method to run the games from the EmulatorJS dev is the following (Only works for Homebrew and Demos): - -- Select commandline from the initial loading screen -- `mount A / -t floppy` - This will mount the location of the files -- `A:` - This will take you to the location of the files -- `dir` - to find the .EXE file -- `filename.exe` - This will run the .exe and run the game, you might need some additional configuration but that is purely on the dosbox side and you might need to run the setup.exe file or a file name similiar. - -#### Advanced Running Games - - -!!! warning - This is not for the faint of heart and will require a lot of trial and error. - -As the system is using DOSBOX pure it has a neat trick where it will run .CONF files it finds and automatically mount locations and run .exe files automatically, at the minute this is highly experimental and might be more effort then it is worth, but if you want the files running perfectly then I would suggest you look into this method, but it is extremely trail and error. - -When you run a game in DOSBOX Pure, before it runs and mounts anything it will look for a .conf file and follow those instructions, this way we can actually auto mount locations, mount the required CDs and play the game without typing anything, you just click play, the auto mount does everything in the background and you are presented with the game. - -This is an example using the doom shareware file which has all the files in the folder. - -- Check the folder and make sure there is an .exe file for the game, make sure there is no `*.ins`, `*.cue` or `*.bin` files, if these exist it usually means this is a CD required game and these instructions will not work -- Create a new text document named the same as the .exe (DOOM.conf) and add the following information: - -
- -DOOM.conf Example - -```shell -# This is the configurationfile for DOSBox 0.74. (Please use the latest version of DOSBox) -# Lines starting with a # are commentlines and are ignored by DOSBox. -# They are used to (briefly) document the effect of each option. - -[sdl] -# fullscreen: Start dosbox directly in fullscreen. (Press ALT-Enter to go back) -# fulldouble: Use double buffering in fullscreen. It can reduce screen flickering, but it can also result in a slow DOSBox. -# fullresolution: What resolution to use for fullscreen: original or fixed size (e.g. 1024x768). -# Using your monitor's native resolution with aspect=true might give the best results. -# If you end up with small window on a large screen, try an output different from surface. -# windowresolution: Scale the window to this size IF the output device supports hardware scaling. -# (output=surface does not!) -# output: What video system to use for output. -# Possible values: surface, overlay, opengl, openglnb, ddraw. -# autolock: Mouse will automatically lock, if you click on the screen. (Press CTRL-F10 to unlock) -# sensitivity: Mouse sensitivity. -# waitonerror: Wait before closing the console if dosbox has an error. -# priority: Priority levels for dosbox. Second entry behind the comma is for when dosbox is not focused/minimized. -# pause is only valid for the second entry. -# Possible values: lowest, lower, normal, higher, highest, pause. -# mapperfile: File used to load/save the key/event mappings from. Resetmapper only works with the defaul value. -# usescancodes: Avoid usage of symkeys, might not work on all operating systems. - -fullscreen=TRUE -fulldouble=false -fullresolution=Fixed -windowresolution=1280x800 -output=direct3d -autolock=true -sensitivity=100 -waitonerror=true -priority=higher,normal -mapperfile=mapper-0.74.map -usescancodes=true - -[dosbox] -# language: Select another language file. -# machine: The type of machine tries to emulate. -# Possible values: hercules, cga, tandy, pcjr, ega, vgaonly, svga_s3, svga_et3000, svga_et4000, svga_paradise, vesa_nolfb, vesa_oldvbe. -# captures: Directory where things like wave, midi, screenshot get captured. -# memsize: Amount of memory DOSBox has in megabytes. -# This value is best left at its default to avoid problems with some games, -# though few games might require a higher value. -# There is generally no speed advantage when raising this value. - -language= -machine=svga_s3 -captures=.\Captures\ -memsize=16 - -[render] -# frameskip: How many frames DOSBox skips before drawing one. -# aspect: Do aspect correction, if your output method doesn't support scaling this can slow things down!. -# scaler: Scaler used to enlarge/enhance low resolution modes. -# If 'forced' is appended, then the scaler will be used even if the result might not be desired. -# Possible values: none, normal2x, normal3x, advmame2x, advmame3x, advinterp2x, advinterp3x, hq2x, hq3x, 2xsai, super2xsai, supereagle, tv2x, tv3x, rgb2x, rgb3x, scan2x, scan3x. - -frameskip=0 -aspect=false -scaler=normal3x - -[cpu] -# core: CPU Core used in emulation. auto will switch to dynamic if available and appropriate. -# Possible values: auto, dynamic, normal, simple. -# cputype: CPU Type used in emulation. auto is the fastest choice. -# Possible values: auto, 386, 386_slow, 486_slow, pentium_slow, 386_prefetch. -# cycles: Amount of instructions DOSBox tries to emulate each millisecond. -# Setting this value too high results in sound dropouts and lags. -# Cycles can be set in 3 ways: -# 'auto' tries to guess what a game needs. -# It usually works, but can fail for certain games. -# 'fixed #number' will set a fixed amount of cycles. This is what you usually need if 'auto' fails. -# (Example: fixed 4000). -# 'max' will allocate as much cycles as your computer is able to handle. -# -# Possible values: auto, fixed, max. -# cycleup: Amount of cycles to decrease/increase with keycombo.(CTRL-F11/CTRL-F12) -# cycledown: Setting it lower than 100 will be a percentage. - -core=auto -cputype=auto -cycles=max -cycleup=10 -cycledown=20 - -[mixer] -# nosound: Enable silent mode, sound is still emulated though. -# rate: Mixer sample rate, setting any device's rate higher than this will probably lower their sound quality. -# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. -# blocksize: Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged. -# Possible values: 1024, 2048, 4096, 8192, 512, 256. -# prebuffer: How many milliseconds of data to keep on top of the blocksize. - -nosound=false -rate=22050 -blocksize=2048 -prebuffer=10 - -[midi] -# mpu401: Type of MPU-401 to emulate. -# Possible values: intelligent, uart, none. -# mididevice: Device that will receive the MIDI data from MPU-401. -# Possible values: default, win32, alsa, oss, coreaudio, coremidi, none. -# midiconfig: Special configuration options for the device driver. This is usually the id of the device you want to use. -# See the README/Manual for more details. - -mpu401=intelligent -mididevice=default -midiconfig= - -[sblaster] -# sbtype: Type of Soundblaster to emulate. gb is Gameblaster. -# Possible values: sb1, sb2, sbpro1, sbpro2, sb16, gb, none. -# sbbase: The IO address of the soundblaster. -# Possible values: 220, 240, 260, 280, 2a0, 2c0, 2e0, 300. -# irq: The IRQ number of the soundblaster. -# Possible values: 7, 5, 3, 9, 10, 11, 12. -# dma: The DMA number of the soundblaster. -# Possible values: 1, 5, 0, 3, 6, 7. -# hdma: The High DMA number of the soundblaster. -# Possible values: 1, 5, 0, 3, 6, 7. -# sbmixer: Allow the soundblaster mixer to modify the DOSBox mixer. -# oplmode: Type of OPL emulation. On 'auto' the mode is determined by sblaster type. All OPL modes are Adlib-compatible, except for 'cms'. -# Possible values: auto, cms, opl2, dualopl2, opl3, none. -# oplemu: Provider for the OPL emulation. compat might provide better quality (see oplrate as well). -# Possible values: default, compat, fast. -# oplrate: Sample rate of OPL music emulation. Use 49716 for highest quality (set the mixer rate accordingly). -# Possible values: 44100, 49716, 48000, 32000, 22050, 16000, 11025, 8000. - -sbtype=sb16 -sbbase=220 -irq=7 -dma=1 -hdma=5 -sbmixer=true -oplmode=auto -oplemu=default -oplrate=44100 - -[gus] -# gus: Enable the Gravis Ultrasound emulation. -# gusrate: Sample rate of Ultrasound emulation. -# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. -# gusbase: The IO base address of the Gravis Ultrasound. -# Possible values: 240, 220, 260, 280, 2a0, 2c0, 2e0, 300. -# gusirq: The IRQ number of the Gravis Ultrasound. -# Possible values: 5, 3, 7, 9, 10, 11, 12. -# gusdma: The DMA channel of the Gravis Ultrasound. -# Possible values: 3, 0, 1, 5, 6, 7. -# ultradir: Path to Ultrasound directory. In this directory -# there should be a MIDI directory that contains -# the patch files for GUS playback. Patch sets used -# with Timidity should work fine. - -gus=false -gusrate=44100 -gusbase=240 -gusirq=5 -gusdma=3 -ultradir=C:\ULTRASND - -[speaker] -# pcspeaker: Enable PC-Speaker emulation. -# pcrate: Sample rate of the PC-Speaker sound generation. -# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. -# tandy: Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'. -# Possible values: auto, on, off. -# tandyrate: Sample rate of the Tandy 3-Voice generation. -# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. -# disney: Enable Disney Sound Source emulation. (Covox Voice Master and Speech Thing compatible). - -pcspeaker=true -pcrate=44100 -tandy=auto -tandyrate=44100 -disney=true - -[joystick] -# joysticktype: Type of joystick to emulate: auto (default), none, -# 2axis (supports two joysticks), -# 4axis (supports one joystick, first joystick used), -# 4axis_2 (supports one joystick, second joystick used), -# fcs (Thrustmaster), ch (CH Flightstick). -# none disables joystick emulation. -# auto chooses emulation depending on real joystick(s). -# (Remember to reset dosbox's mapperfile if you saved it earlier) -# Possible values: auto, 2axis, 4axis, 4axis_2, fcs, ch, none. -# timed: enable timed intervals for axis. Experiment with this option, if your joystick drifts (away). -# autofire: continuously fires as long as you keep the button pressed. -# swap34: swap the 3rd and the 4th axis. can be useful for certain joysticks. -# buttonwrap: enable button wrapping at the number of emulated buttons. - -joysticktype=fcs -timed=true -autofire=false -swap34=false -buttonwrap=false - -[serial] -# serial1: set type of device connected to com port. -# Can be disabled, dummy, modem, nullmodem, directserial. -# Additional parameters must be in the same line in the form of -# parameter:value. Parameter for all types is irq (optional). -# for directserial: realport (required), rxdelay (optional). -# (realport:COM1 realport:ttyS0). -# for modem: listenport (optional). -# for nullmodem: server, rxdelay, txdelay, telnet, usedtr, -# transparent, port, inhsocket (all optional). -# Example: serial1=modem listenport:5000 -# Possible values: dummy, disabled, modem, nullmodem, directserial. -# serial2: see serial1 -# Possible values: dummy, disabled, modem, nullmodem, directserial. -# serial3: see serial1 -# Possible values: dummy, disabled, modem, nullmodem, directserial. -# serial4: see serial1 -# Possible values: dummy, disabled, modem, nullmodem, directserial. - -serial1=dummy -serial2=dummy -serial3=disabled -serial4=disabled - -[dos] -# xms: Enable XMS support. -# ems: Enable EMS support. -# umb: Enable UMB support. -# keyboardlayout: Language code of the keyboard layout (or none). - -xms=true -ems=true -umb=true -keyboardlayout=auto - -[ipx] -# ipx: Enable ipx over UDP/IP emulation. - -ipx=false - -[autoexec] -# Lines in this section will be run at startup. -# You can put your MOUNT lines here. - -@echo off -Mount C ".." -C: -cls -DOOM.exe -:exit -exit -``` - -
- -- Most of the file is explained but to go into the nitty gritty of the [autoexec] it will mount the local location as C:, it changes to C: it will clear the screen and automatically run the DOOM.exe executable, and will exit the previous shell, meaning it will run the game by just clicking play. -- Zip up the folder and add it to RomM's DOS platform, then just simply click play. If you hit a blank screen it means that something is wrong with the auto exec, and will need manual troubleshooting. - -### Advanced Running Retail Games - - -!!! info - At the minute DOS games redesigned by GOG are NOT supported, this is due to how they mount and use the locations. I am looking into how I can figure this out but I have had a 100% failure rate from the GOG DOS Games. - -Retail games usually require to run alongside a disk even if the game has been "installed" locally. I will use Dungeon Keeper Gold as an example for a retail game with a disc and the configuration needed. - -- Prepare the files like you did before, but this time with the disk images (`*.bin` & `*.cue`) and move them to a folder named CD within the folder. Only within this folder you should all the .bin files and the "matching" .cue sheet (remember .cue is just a text document pulling all these files together, like a playlist) -- Have a look at the KEEPER.cfg file, this file will say how the game was installed and the path it expects the installed files to be at. -- Create a new .conf document named the same as the .exe for me that would be KEEPER.conf - -
- -KEEPER.conf Example - -```shell -# This is the configurationfile for DOSBox 0.74. (Please use the latest version of DOSBox) -# Lines starting with a # are commentlines and are ignored by DOSBox. -# They are used to (briefly) document the effect of each option. - -[sdl] -# fullscreen: Start dosbox directly in fullscreen. (Press ALT-Enter to go back) -# fulldouble: Use double buffering in fullscreen. It can reduce screen flickering, but it can also result in a slow DOSBox. -# fullresolution: What resolution to use for fullscreen: original or fixed size (e.g. 1024x768). -# Using your monitor's native resolution with aspect=true might give the best results. -# If you end up with small window on a large screen, try an output different from surface. -# windowresolution: Scale the window to this size IF the output device supports hardware scaling. -# (output=surface does not!) -# output: What video system to use for output. -# Possible values: surface, overlay, opengl, openglnb, ddraw. -# autolock: Mouse will automatically lock, if you click on the screen. (Press CTRL-F10 to unlock) -# sensitivity: Mouse sensitivity. -# waitonerror: Wait before closing the console if dosbox has an error. -# priority: Priority levels for dosbox. Second entry behind the comma is for when dosbox is not focused/minimized. -# pause is only valid for the second entry. -# Possible values: lowest, lower, normal, higher, highest, pause. -# mapperfile: File used to load/save the key/event mappings from. Resetmapper only works with the defaul value. -# usescancodes: Avoid usage of symkeys, might not work on all operating systems. - -fullscreen=TRUE -fulldouble=false -fullresolution=Fixed -windowresolution=1280x800 -output=direct3d -autolock=true -sensitivity=100 -waitonerror=true -priority=higher,normal -mapperfile=mapper-0.74.map -usescancodes=true - -[dosbox] -# language: Select another language file. -# machine: The type of machine tries to emulate. -# Possible values: hercules, cga, tandy, pcjr, ega, vgaonly, svga_s3, svga_et3000, svga_et4000, svga_paradise, vesa_nolfb, vesa_oldvbe. -# captures: Directory where things like wave, midi, screenshot get captured. -# memsize: Amount of memory DOSBox has in megabytes. -# This value is best left at its default to avoid problems with some games, -# though few games might require a higher value. -# There is generally no speed advantage when raising this value. - -language= -machine=svga_s3 -captures=.\Captures\ -memsize=16 - -[render] -# frameskip: How many frames DOSBox skips before drawing one. -# aspect: Do aspect correction, if your output method doesn't support scaling this can slow things down!. -# scaler: Scaler used to enlarge/enhance low resolution modes. -# If 'forced' is appended, then the scaler will be used even if the result might not be desired. -# Possible values: none, normal2x, normal3x, advmame2x, advmame3x, advinterp2x, advinterp3x, hq2x, hq3x, 2xsai, super2xsai, supereagle, tv2x, tv3x, rgb2x, rgb3x, scan2x, scan3x. - -frameskip=0 -aspect=false -scaler=normal3x - -[cpu] -# core: CPU Core used in emulation. auto will switch to dynamic if available and appropriate. -# Possible values: auto, dynamic, normal, simple. -# cputype: CPU Type used in emulation. auto is the fastest choice. -# Possible values: auto, 386, 386_slow, 486_slow, pentium_slow, 386_prefetch. -# cycles: Amount of instructions DOSBox tries to emulate each millisecond. -# Setting this value too high results in sound dropouts and lags. -# Cycles can be set in 3 ways: -# 'auto' tries to guess what a game needs. -# It usually works, but can fail for certain games. -# 'fixed #number' will set a fixed amount of cycles. This is what you usually need if 'auto' fails. -# (Example: fixed 4000). -# 'max' will allocate as much cycles as your computer is able to handle. -# -# Possible values: auto, fixed, max. -# cycleup: Amount of cycles to decrease/increase with keycombo.(CTRL-F11/CTRL-F12) -# cycledown: Setting it lower than 100 will be a percentage. - -core=auto -cputype=auto -cycles=max -cycleup=10 -cycledown=20 - -[mixer] -# nosound: Enable silent mode, sound is still emulated though. -# rate: Mixer sample rate, setting any device's rate higher than this will probably lower their sound quality. -# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. -# blocksize: Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged. -# Possible values: 1024, 2048, 4096, 8192, 512, 256. -# prebuffer: How many milliseconds of data to keep on top of the blocksize. - -nosound=false -rate=22050 -blocksize=2048 -prebuffer=10 - -[midi] -# mpu401: Type of MPU-401 to emulate. -# Possible values: intelligent, uart, none. -# mididevice: Device that will receive the MIDI data from MPU-401. -# Possible values: default, win32, alsa, oss, coreaudio, coremidi, none. -# midiconfig: Special configuration options for the device driver. This is usually the id of the device you want to use. -# See the README/Manual for more details. - -mpu401=intelligent -mididevice=default -midiconfig= - -[sblaster] -# sbtype: Type of Soundblaster to emulate. gb is Gameblaster. -# Possible values: sb1, sb2, sbpro1, sbpro2, sb16, gb, none. -# sbbase: The IO address of the soundblaster. -# Possible values: 220, 240, 260, 280, 2a0, 2c0, 2e0, 300. -# irq: The IRQ number of the soundblaster. -# Possible values: 7, 5, 3, 9, 10, 11, 12. -# dma: The DMA number of the soundblaster. -# Possible values: 1, 5, 0, 3, 6, 7. -# hdma: The High DMA number of the soundblaster. -# Possible values: 1, 5, 0, 3, 6, 7. -# sbmixer: Allow the soundblaster mixer to modify the DOSBox mixer. -# oplmode: Type of OPL emulation. On 'auto' the mode is determined by sblaster type. All OPL modes are Adlib-compatible, except for 'cms'. -# Possible values: auto, cms, opl2, dualopl2, opl3, none. -# oplemu: Provider for the OPL emulation. compat might provide better quality (see oplrate as well). -# Possible values: default, compat, fast. -# oplrate: Sample rate of OPL music emulation. Use 49716 for highest quality (set the mixer rate accordingly). -# Possible values: 44100, 49716, 48000, 32000, 22050, 16000, 11025, 8000. - -sbtype=sb16 -sbbase=220 -irq=7 -dma=1 -hdma=5 -sbmixer=true -oplmode=auto -oplemu=default -oplrate=44100 - -[gus] -# gus: Enable the Gravis Ultrasound emulation. -# gusrate: Sample rate of Ultrasound emulation. -# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. -# gusbase: The IO base address of the Gravis Ultrasound. -# Possible values: 240, 220, 260, 280, 2a0, 2c0, 2e0, 300. -# gusirq: The IRQ number of the Gravis Ultrasound. -# Possible values: 5, 3, 7, 9, 10, 11, 12. -# gusdma: The DMA channel of the Gravis Ultrasound. -# Possible values: 3, 0, 1, 5, 6, 7. -# ultradir: Path to Ultrasound directory. In this directory -# there should be a MIDI directory that contains -# the patch files for GUS playback. Patch sets used -# with Timidity should work fine. - -gus=false -gusrate=44100 -gusbase=240 -gusirq=5 -gusdma=3 -ultradir=C:\ULTRASND - -[speaker] -# pcspeaker: Enable PC-Speaker emulation. -# pcrate: Sample rate of the PC-Speaker sound generation. -# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. -# tandy: Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'. -# Possible values: auto, on, off. -# tandyrate: Sample rate of the Tandy 3-Voice generation. -# Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. -# disney: Enable Disney Sound Source emulation. (Covox Voice Master and Speech Thing compatible). - -pcspeaker=true -pcrate=44100 -tandy=auto -tandyrate=44100 -disney=true - -[joystick] -# joysticktype: Type of joystick to emulate: auto (default), none, -# 2axis (supports two joysticks), -# 4axis (supports one joystick, first joystick used), -# 4axis_2 (supports one joystick, second joystick used), -# fcs (Thrustmaster), ch (CH Flightstick). -# none disables joystick emulation. -# auto chooses emulation depending on real joystick(s). -# (Remember to reset dosbox's mapperfile if you saved it earlier) -# Possible values: auto, 2axis, 4axis, 4axis_2, fcs, ch, none. -# timed: enable timed intervals for axis. Experiment with this option, if your joystick drifts (away). -# autofire: continuously fires as long as you keep the button pressed. -# swap34: swap the 3rd and the 4th axis. can be useful for certain joysticks. -# buttonwrap: enable button wrapping at the number of emulated buttons. - -joysticktype=fcs -timed=true -autofire=false -swap34=false -buttonwrap=false - -[serial] -# serial1: set type of device connected to com port. -# Can be disabled, dummy, modem, nullmodem, directserial. -# Additional parameters must be in the same line in the form of -# parameter:value. Parameter for all types is irq (optional). -# for directserial: realport (required), rxdelay (optional). -# (realport:COM1 realport:ttyS0). -# for modem: listenport (optional). -# for nullmodem: server, rxdelay, txdelay, telnet, usedtr, -# transparent, port, inhsocket (all optional). -# Example: serial1=modem listenport:5000 -# Possible values: dummy, disabled, modem, nullmodem, directserial. -# serial2: see serial1 -# Possible values: dummy, disabled, modem, nullmodem, directserial. -# serial3: see serial1 -# Possible values: dummy, disabled, modem, nullmodem, directserial. -# serial4: see serial1 -# Possible values: dummy, disabled, modem, nullmodem, directserial. - -serial1=dummy -serial2=dummy -serial3=disabled -serial4=disabled - -[dos] -# xms: Enable XMS support. -# ems: Enable EMS support. -# umb: Enable UMB support. -# keyboardlayout: Language code of the keyboard layout (or none). - -xms=true -ems=true -umb=true -keyboardlayout=auto - -[ipx] -# ipx: Enable ipx over UDP/IP emulation. - -ipx=false - -[autoexec] -# Lines in this section will be run at startup. -# You can put your MOUNT lines here. - -@echo off -Mount C ".." -C: -cd CD -imgmount d DUNGEO~8.CUE -t iso -fs iso -cd .. -cls -KEEPER.exe -:exit -exit -``` - -
- -- Notice the different in the automount commands - - Mount the games files to can - - Change to C: - - Change Directory to CD - - Using dosbox imgmount, mount the CD to the D path - - cd to the directory above where the .exe - - Clear the working out - - Run KEEPER.exe -- Once this is done, the game will run. Zip the files up and add to your RomM and give it a test. - -#### Advanced Game Troubleshooting - -If the games are not working and you go back to a blank dos looking screen, this will require some manual troubleshooting but I have found success with the following methods: - -- Remove the .exe in the .CONF file and investigate the automounts - - This means going to the C: and make sure the .exe is in the right place. - - Use the following command `type DEFAULT.cfg` to see the installation location, this is where the game is looking for the files, this should be set to a D: location. - - Browse to that location and see if the files are there and they are readable. -- The automount is simply following instructions, so it expects the files to be where you say, following this method is usually best to troubleshoot. - -Another way of troubleshooting is to use Retroarch and the core "dosbox-pure" because if it runs in here, it will run in RomM. Simply give it your ZIP and it will act the same as if you was doing it through RomM, once the .conf file is perfected add it back to the ZIP. diff --git a/docs/Platforms-and-Players/RuffleRS-Player.md b/docs/Platforms-and-Players/RuffleRS-Player.md deleted file mode 100644 index 68089843..00000000 --- a/docs/Platforms-and-Players/RuffleRS-Player.md +++ /dev/null @@ -1,7 +0,0 @@ - - -[Ruffle](https://ruffle.rs/) is a web-based player for flash games. With flash now discontinued, this is the best way to play your flash collection in the browser. - - -!!! important - Ruffle will only play games stored in platform folders called `flash` or `browser`. diff --git a/docs/Platforms-and-Players/Supported-Platforms.md b/docs/Platforms-and-Players/Supported-Platforms.md deleted file mode 100644 index d1a5e8bc..00000000 --- a/docs/Platforms-and-Players/Supported-Platforms.md +++ /dev/null @@ -1,660 +0,0 @@ - - - -Below is a list of all supported platforms/systems/consoles and their respective folder names. Supported platforms means RomM can fetch metadata from sources for those platforms. - - -!!! info - For platforms that can be playable in the browser, please check [EmulatorJS supported platforms](./EmulatorJS-Player.md) and [RuffleRS player](./RuffleRS-Player.md). - - -!!! danger - **The folder name is case-sensitive and must be used exactly as it appears in the list below.** - -
-

Filter providers

-
-
- - - - - - - - -
-
- 0 of 0 platforms shown -
-
-
- - - - - - -|Platform Name|Folder Name|Metadata Providers| -|---|---|---| -| 1292 Advanced Programmable Video System | `1292-advanced-programmable-video-system` | igdb logo mobygames logo | -| 3DO Interactive Multiplayer | `3do` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| 8-Bit Productions Commander X16 | `commander-x16` | hasheous logo | -| Aamber Pegasus | `pegasus` | launchbox logo | -| ABC 80 | `abc-80` | mobygames logo | -| Acorn Archimedes | `acorn-archimedes` | igdb logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Acorn Electron | `acorn-electron` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo | -| Advanced Pico Beena | `advanced-pico-beena` | igdb logo | -| Adventure Vision | `adventure-vision` | screenscraper logo mobygames logo launchbox logo hasheous logo | -| AirConsole | `airconsole` | igdb logo mobygames logo | -| Alice 32/90 | `alice-3290` | mobygames logo launchbox logo | -| Altair 680 | `altair-680` | mobygames logo | -| Altair 8800 | `altair-8800` | mobygames logo hasheous logo | -| Amazon Alexa | `amazon-alexa` | mobygames logo | -| Amazon Fire TV | `amazon-fire-tv` | igdb logo mobygames logo | -| Amiga | `amiga` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Amiga CD | `amiga-cd` | screenscraper logo | -| Amiga CD32 | `amiga-cd32` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Amstrad CPC | `acpc` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Amstrad GX4000 | `amstrad-gx4000` | igdb logo screenscraper logo launchbox logo hasheous logo | -| Amstrad PCW | `amstrad-pcw` | igdb logo mobygames logo hasheous logo | -| Analogue electronics | `analogueelectronics` | igdb logo | -| Android | `android` | igdb logo screenscraper logo mobygames logo launchbox logo | -| Antstream | `antstream` | mobygames logo | -| APF MP1000/Imagination Machine | `apf` | mobygames logo launchbox logo hasheous logo | -| Apogee BK-01 | `bk-01` | launchbox logo | -| Apple I | `apple` | mobygames logo hasheous logo | -| Apple II | `appleii` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Apple IIGS | `apple-iigs` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo | -| Apple III | `appleiii` | hasheous logo | -| Apple Lisa | `apple-lisa` | hasheous logo | -| Apple Pippin | `apple-pippin` | igdb logo hasheous logo | -| Arcade | `arcade` | igdb logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Arcadia 2001 | `arcadia-2001` | igdb logo screenscraper logo mobygames logo launchbox logo retroachivements logo | -| Arduboy | `arduboy` | igdb logo screenscraper logo mobygames logo hasheous logo retroachivements logo | -| Astral 2000 | `astral-2000` | mobygames logo | -| Atari 2600 | `atari2600` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Atari 5200 | `atari5200` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Atari 7800 | `atari7800` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Atari 8-bit | `atari8bit` | igdb logo screenscraper logo mobygames logo hasheous logo howlongtobeat logo | -| Atari 800 | `atari800` | launchbox logo | -| Atari Jaguar | `jaguar` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Atari Jaguar CD | `atari-jaguar-cd` | igdb logo launchbox logo retroachivements logo howlongtobeat logo | -| Atari Lynx | `lynx` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Atari ST/STE | `atari-st` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Atari VCS | `atari-vcs` | mobygames logo | -| Atari XEGS | `atari-xegs` | launchbox logo | -| Atom | `atom` | screenscraper logo mobygames logo launchbox logo hasheous logo | -| AY-3-8500 | `ay-3-8500` | igdb logo | -| AY-3-8603 | `ay-3-8603` | igdb logo | -| AY-3-8605 | `ay-3-8605` | igdb logo | -| AY-3-8606 | `ay-3-8606` | igdb logo | -| AY-3-8607 | `ay-3-8607` | igdb logo | -| AY-3-8610 | `ay-3-8610` | igdb logo | -| AY-3-8710 | `ay-3-8710` | igdb logo | -| AY-3-8760 | `ay-3-8760` | igdb logo | -| Bada | `bada` | mobygames logo | -| Bally Astrocade | `astrocade` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo | -| BBC Microcomputer System | `bbcmicro` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Benesse Pocket Challenge V2 | `pocket-challenge-v2` | hasheous logo | -| Benesse Pocket Challenge W | `pocket-challenge-w` | hasheous logo | -| BeOS | `beos` | mobygames logo | -| BGR Computers Excalibur 64 | `excalibur-64` | hasheous logo | -| Bit Corporation BIT 90 | `bit-90` | hasheous logo | -| Black Point | `black-point` | | -| BlackBerry OS | `blackberry` | igdb logo mobygames logo | -| Blacknut | `blacknut` | mobygames logo | -| Blu-ray Player | `blu-ray-player` | igdb logo mobygames logo | -| BREW | `brew` | mobygames logo | -| Browser (Flash/HTML5) | `browser` | igdb logo mobygames logo launchbox logo flashpoint logo howlongtobeat logo | -| Bubble | `bubble` | mobygames logo | -| Call-A-Computer time-shared mainframe computer system | `call-a-computer` | igdb logo | -| Cambridge Computer Z88 | `z88` | hasheous logo | -| Camputers Lynx | `camputers-lynx` | screenscraper logo mobygames logo launchbox logo hasheous logo | -| Casio CFX-9850 | `casio-cfx-9850` | hasheous logo | -| Casio FP-1000 & FP-1100 | `casio-fp-1000` | hasheous logo | -| Casio Loopy | `casio-loopy` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo | -| Casio PB-1000 | `casio-pb-1000` | hasheous logo | -| Casio Programmable Calculator | `casio-programmable-calculator` | mobygames logo | -| Casio PV-1000 | `casio-pv-1000` | screenscraper logo mobygames logo launchbox logo hasheous logo | -| Casio PV-2000 | `casio-pv-2000` | hasheous logo | -| CDC Cyber 70 | `cdccyber70` | igdb logo | -| Champion 2711 | `champion-2711` | mobygames logo | -| ClickStart | `clickstart` | mobygames logo | -| Coleco Adam | `colecoadam` | screenscraper logo mobygames logo launchbox logo | -| ColecoVision | `colecovision` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Colour Genie | `colour-genie` | screenscraper logo mobygames logo launchbox logo | -| Commodore 128 | `c128` | screenscraper logo mobygames logo launchbox logo hasheous logo | -| Commodore 16 | `c16` | igdb logo screenscraper logo mobygames logo hasheous logo | -| Commodore C64/128/MAX | `c64` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Commodore CDTV | `commodore-cdtv` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo | -| Commodore PET | `cpet` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Commodore Plus/4 | `c-plus-4` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Commodore VIC-20 | `vic-20` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo | -| Compal 80 | `compal-80` | mobygames logo | -| Compucolor I | `compucolor-i` | mobygames logo | -| Compucolor II | `compucolor-ii` | mobygames logo | -| Compucorp Programmable Calculator | `compucorp-programmable-calculator` | mobygames logo | -| COSMAC | `fred-cosmac` | mobygames logo | -| CP/M | `cpm` | mobygames logo | -| CreatiVision | `creativision` | screenscraper logo mobygames logo launchbox logo | -| Cybervision | `cybervision` | mobygames logo | -| Danger OS | `danger-os` | mobygames logo | -| Daydream | `daydream` | igdb logo | -| DEC GT40 | `gt40` | igdb logo | -| Dedicated console | `dedicated-console` | mobygames logo | -| Dedicated handheld | `dedicated-handheld` | mobygames logo | -| Didj | `didj` | mobygames logo | -| Digiblast | `digiblast` | igdb logo mobygames logo | -| DoJa | `doja` | mobygames logo | -| Donner Model 30 | `donner30` | igdb logo | -| DOS | `dos` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo | -| Dragon 32/64 | `dragon-32-slash-64` | igdb logo screenscraper logo mobygames logo launchbox logo | -| Dreamcast | `dc` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| DVD Player | `dvd-player` | igdb logo mobygames logo howlongtobeat logo | -| e-Reader / Card-e Reader | `e-reader-slash-card-e-reader` | igdb logo | -| ECD Micromind | `ecd-micromind` | mobygames logo | -| EDSAC | `edsac` | igdb logo | -| Elektor TV Games Computer | `elektor` | igdb logo retroachivements logo | -| Elektronika BK | `bk` | launchbox logo | -| Enterprise | `enterprise` | mobygames logo launchbox logo | -| Epoch Cassette Vision | `epoch-cassette-vision` | igdb logo mobygames logo | -| Epoch Game Pocket Computer | `epoch-game-pocket-computer` | screenscraper logo mobygames logo launchbox logo | -| Epoch Super Cassette Vision | `epoch-super-cassette-vision` | igdb logo screenscraper logo mobygames logo launchbox logo | -| Evercade | `evercade` | igdb logo mobygames logo howlongtobeat logo | -| Exelvision | `exelvision` | screenscraper logo mobygames logo launchbox logo | -| ExEn | `exen` | mobygames logo | -| Exidy Sorcerer | `exidy-sorcerer` | igdb logo screenscraper logo mobygames logo launchbox logo | -| Fairchild Channel F | `fairchild-channel-f` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo | -| Family Computer | `famicom` | igdb logo mobygames logo launchbox logo retroachivements logo | -| Family Computer Disk System | `fds` | igdb logo screenscraper logo launchbox logo hasheous logo | -| Feature phone | `mobile-custom` | mobygames logo | -| Ferranti Nimrod Computer | `nimrod` | igdb logo | -| FM Towns | `fm-towns` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| FM-7 | `fm-7` | igdb logo screenscraper logo mobygames logo launchbox logo howlongtobeat logo | -| Freebox | `freebox` | mobygames logo | -| G-cluster | `g-cluster` | mobygames logo | -| Galaksija | `galaksija` | mobygames logo | -| Gamate | `gamate` | igdb logo hasheous logo | -| Game & Watch | `g-and-w` | igdb logo screenscraper logo mobygames logo launchbox logo howlongtobeat logo | -| Game Boy | `gb` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Game Boy Advance | `gba` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Game Boy Color | `gbc` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Game Master | `hartung` | screenscraper logo launchbox logo | -| Game Wave | `game-wave` | mobygames logo launchbox logo | -| Game.com | `game-dot-com` | igdb logo screenscraper logo mobygames logo launchbox logo howlongtobeat logo | -| GameStick | `gamestick` | mobygames logo | -| Gear VR | `gear-vr` | igdb logo howlongtobeat logo | -| GIMINI | `gimini` | mobygames logo | -| Gizmondo | `gizmondo` | igdb logo mobygames logo howlongtobeat logo | -| Gloud | `gloud` | mobygames logo | -| Glulx | `glulx` | mobygames logo | -| GNEX | `gnex` | mobygames logo | -| Google Stadia | `stadia` | igdb logo mobygames logo howlongtobeat logo | -| GP2X | `gp2x` | mobygames logo | -| GP2X Wiz | `gp2x-wiz` | mobygames logo | -| GP32 | `gp32` | screenscraper logo mobygames logo launchbox logo | -| GVM | `gvm` | mobygames logo | -| Handheld Electronic LCD | `handheld-electronic-lcd` | igdb logo | -| HD DVD Player | `hd-dvd-player` | mobygames logo | -| Heath/Zenith H8/H89 | `heathzenith` | mobygames logo | -| Heathkit H11 | `heathkit-h11` | mobygames logo | -| Hector HRX | `hrx` | launchbox logo | -| Hitachi S1 | `hitachi-s1` | mobygames logo | -| HP 2100 | `hp2100` | igdb logo | -| HP 3000 | `hp3000` | igdb logo | -| HP 9800 | `hp-9800` | mobygames logo | -| HP Programmable Calculator | `hp-programmable-calculator` | mobygames logo | -| Hugo | `hugo` | mobygames logo | -| Hyper Neo Geo 64 | `hyper-neo-geo-64` | igdb logo | -| HyperScan | `hyperscan` | igdb logo mobygames logo launchbox logo | -| IBM 5100 | `ibm-5100` | mobygames logo | -| IBM PCjr | `pc-jr` | hasheous logo | -| Ideal-Computer | `ideal-computer` | mobygames logo | -| iiRcade | `iircade` | mobygames logo | -| Imlac PDS-1 | `imlac-pds1` | igdb logo | -| Intel 8008 | `intel-8008` | mobygames logo | -| Intel 8080 | `intel-8080` | mobygames logo | -| Intel 8086 / 8088 | `intel-8086` | mobygames logo | -| Intellivision | `intellivision` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Intellivision Amico | `intellivision-amico` | igdb logo | -| Interact Model One | `interact-model-one` | mobygames logo | -| Interton VC 4000 | `interton-vc-4000` | retroachivements logo | -| Interton Video 2000 | `interton-video-2000` | mobygames logo | -| iOS | `ios` | igdb logo mobygames logo launchbox logo | -| iPad | `ipad` | mobygames logo | -| iPod Classic | `ipod-classic` | mobygames logo | -| J2ME | `j2me` | mobygames logo | -| Jolt | `jolt` | mobygames logo | -| Jupiter Ace | `jupiter-ace` | screenscraper logo mobygames logo launchbox logo | -| KaiOS | `kaios` | mobygames logo | -| KIM-1 | `kim-1` | mobygames logo | -| Kindle Classic | `kindle` | mobygames logo | -| Laser 200 | `laser200` | mobygames logo | -| LaserActive | `laseractive` | igdb logo mobygames logo | -| LeapFrog Explorer | `leapfrog-explorer` | mobygames logo | -| Leapster | `leapster` | igdb logo mobygames logo | -| Leapster Explorer/LeadPad Explorer | `leapster-explorer-slash-leadpad-explorer` | igdb logo mobygames logo | -| LeapTV | `leaptv` | igdb logo mobygames logo | -| Legacy Computer | `legacy-computer` | igdb logo | -| Legacy Mobile Device | `mobile` | igdb logo howlongtobeat logo | -| Linux | `linux` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Luna | `luna` | mobygames logo howlongtobeat logo | -| Mac | `mac` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Maemo | `maemo` | mobygames logo | -| Magnavox Odyssey | `odyssey` | igdb logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Mainframe | `mainframe` | mobygames logo | -| Matsushita/Panasonic JR | `matsushitapanasonic-jr` | mobygames logo | -| Mattel Aquarius | `aquarius` | mobygames logo launchbox logo hasheous logo | -| MeeGo | `meego` | mobygames logo | -| Mega Duck/Cougar Boy | `mega-duck-slash-cougar-boy` | igdb logo launchbox logo retroachivements logo | -| Memotech MTX | `memotech-mtx` | mobygames logo | -| Memotech MTX512 | `mtx512` | launchbox logo | -| Meritum | `meritum` | mobygames logo | -| Meta Quest 2 | `meta-quest-2` | igdb logo | -| Meta Quest 3 | `meta-quest-3` | igdb logo | -| Microbee | `microbee` | mobygames logo hasheous logo | -| Microcomputer | `microcomputer` | igdb logo | -| Microsoft MSX2+ | `msx2plus` | launchbox logo | -| Microtan 65 | `microtan-65` | mobygames logo | -| Microvision | `microvision` | igdb logo mobygames logo | -| Mophun | `mophun` | mobygames logo | -| MOS Technology 6502 | `mos-technology-6502` | mobygames logo | -| Motorola 6800 | `motorola-6800` | mobygames logo | -| Motorola 68k | `motorola-68k` | mobygames logo | -| MRE | `mre` | mobygames logo | -| MSX | `msx` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| MSX Turbo R | `msx-turbo` | screenscraper logo | -| MSX2 | `msx2` | igdb logo launchbox logo hasheous logo | -| MUGEN | `mugen` | launchbox logo | -| N-Gage | `ngage` | igdb logo screenscraper logo mobygames logo launchbox logo howlongtobeat logo | -| N-Gage (service) | `ngage2` | mobygames logo | -| Namco System 22 | `system-32` | launchbox logo | -| Nascom | `nascom` | mobygames logo | -| NEC PC-6000 Series | `nec-pc-6000-series` | igdb logo hasheous logo | -| Neo Geo AES | `neogeoaes` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Neo Geo CD | `neo-geo-cd` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Neo Geo MVS | `neogeomvs` | igdb logo screenscraper logo mobygames logo launchbox logo | -| Neo Geo Pocket | `neo-geo-pocket` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Neo Geo Pocket Color | `neo-geo-pocket-color` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo | -| Neo Geo X | `neo-geo-x` | mobygames logo | -| New Nintendo 3DS | `new-nintendo-3ds` | igdb logo mobygames logo hasheous logo | -| NewBrain | `newbrain` | mobygames logo | -| Newton | `newton` | mobygames logo | -| Nintendo 3DS | `3ds` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Nintendo 64 | `n64` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Nintendo 64DD | `64dd` | igdb logo screenscraper logo launchbox logo hasheous logo | -| Nintendo DS | `nds` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Nintendo DSi | `nintendo-dsi` | igdb logo screenscraper logo mobygames logo hasheous logo retroachivements logo | -| Nintendo Entertainment System | `nes` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Nintendo GameCube | `ngc` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Nintendo Switch | `switch` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Nintendo Switch 2 | `switch-2` | igdb logo mobygames logo launchbox logo howlongtobeat logo | -| North Star | `northstar` | mobygames logo | -| Noval 760 | `noval-760` | mobygames logo | -| Nuon | `nuon` | igdb logo mobygames logo launchbox logo | -| Oculus Go | `oculus-go` | igdb logo mobygames logo howlongtobeat logo | -| Oculus Quest | `oculus-quest` | igdb logo mobygames logo howlongtobeat logo | -| Oculus Rift | `oculus-rift` | igdb logo | -| Oculus VR | `oculus-vr` | igdb logo | -| Odyssey 2 | `odyssey-2` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Ohio Scientific | `ohio-scientific` | mobygames logo | -| OnLive Game System | `onlive-game-system` | igdb logo mobygames logo howlongtobeat logo | -| OOParts | `ooparts` | igdb logo mobygames logo | -| OpenBOR | `openbor` | launchbox logo | -| Orao | `orao` | mobygames logo | -| Oric | `oric` | screenscraper logo mobygames logo | -| Oric Atmos | `atmos` | launchbox logo | -| OS/2 | `os2` | mobygames logo | -| Othello Multivision | `multivision` | launchbox logo hasheous logo | -| Ouya | `ouya` | igdb logo mobygames logo launchbox logo howlongtobeat logo | -| Palm OS | `palm-os` | igdb logo screenscraper logo mobygames logo | -| Palmtex | `palmtex` | | -| Panasonic Jungle | `panasonic-jungle` | igdb logo | -| Panasonic M2 | `panasonic-m2` | igdb logo | -| Pandora | `pandora` | mobygames logo | -| PC Booter | `pc-booter` | mobygames logo | -| PC Engine SuperGrafx | `supergrafx` | igdb logo screenscraper logo mobygames logo launchbox logo | -| PC-50X Family | `pc-50x-family` | igdb logo | -| PC-6001 | `pc-6001` | mobygames logo | -| PC-8000 | `pc-8000` | mobygames logo | -| PC-8800 Series | `pc-8800-series` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| PC-9800 Series | `pc-9800-series` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| PC-FX | `pc-fx` | igdb logo screenscraper logo mobygames logo launchbox logo retroachivements logo howlongtobeat logo | -| PDP-1 | `pdp1` | igdb logo | -| PDP-10 | `pdp10` | igdb logo | -| PDP-11 | `pdp11` | igdb logo | -| PDP-7 | `pdp-7` | igdb logo | -| PDP-8 | `pdp-8` | igdb logo | -| Pebble | `pebble` | mobygames logo | -| Philips CD-i | `philips-cd-i` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Philips VG 5000 | `philips-vg-5000` | screenscraper logo mobygames logo launchbox logo | -| Photo CD | `photocd` | mobygames logo | -| PICO | `pico` | screenscraper logo mobygames logo launchbox logo howlongtobeat logo | -| Pinball | `pinball` | launchbox logo | -| Pippin | `pippin` | mobygames logo | -| PLATO | `plato` | igdb logo | -| Playdate | `playdate` | igdb logo mobygames logo howlongtobeat logo | -| Playdia | `playdia` | igdb logo mobygames logo | -| PlayStation | `psx` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| PlayStation 2 | `ps2` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| PlayStation 3 | `ps3` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| PlayStation 4 | `ps4` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| PlayStation 5 | `ps5` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| PlayStation Now | `playstation-now` | mobygames logo howlongtobeat logo | -| PlayStation Portable | `psp` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| PlayStation Vita | `psvita` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| PlayStation VR | `psvr` | igdb logo howlongtobeat logo | -| PlayStation VR2 | `psvr2` | igdb logo | -| Plex Arcade | `plex-arcade` | mobygames logo | -| Plug & Play | `plug-and-play` | igdb logo howlongtobeat logo | -| PocketStation | `pocketstation` | igdb logo launchbox logo hasheous logo | -| Pokitto | `pokitto` | mobygames logo | -| Pokémon mini | `pokemon-mini` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo | -| Poly-88 | `poly-88` | mobygames logo | -| Polymega | `polymega` | igdb logo | -| R-Zone | `r-zone` | igdb logo | -| RCA Studio II | `rca-studio-ii` | mobygames logo launchbox logo hasheous logo | -| Research Machines 380Z | `research-machines-380z` | mobygames logo | -| Roku | `roku` | mobygames logo | -| SAM Coupé | `sam-coupe` | screenscraper logo mobygames logo launchbox logo | -| Satellaview | `satellaview` | igdb logo launchbox logo | -| SC/MP | `scmp` | mobygames logo | -| ScummVM | `scummvm` | launchbox logo | -| SD-200/270/290 | `sd-200270290` | mobygames logo | -| SDS Sigma 7 | `sdssigma7` | igdb logo | -| Sega 32X | `sega32` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Sega Advanced Pico Beena | `beena` | hasheous logo | -| Sega CD | `segacd` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Sega CD 32X | `segacd32` | igdb logo launchbox logo | -| Sega Dreamcast VMU | `vmu` | launchbox logo | -| Sega Game Gear | `gamegear` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Sega Hikaru | `hikaru` | launchbox logo | -| Sega Master System/Mark III | `sms` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Sega Mega Drive/Genesis | `genesis` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Sega Model 1 | `model1` | launchbox logo | -| Sega Model 2 | `model2` | launchbox logo | -| Sega Model 3 | `model3` | launchbox logo | -| Sega Pico | `sega-pico` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Sega Saturn | `saturn` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Sega SC-3000 | `sc3000` | launchbox logo hasheous logo | -| Sega ST-V | `stv` | launchbox logo | -| Sega System 16 | `system16` | launchbox logo | -| Sega System 32 | `system32` | launchbox logo | -| SG-1000 | `sg1000` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Sharp MZ-2200 | `sharp-mz-2200` | igdb logo | -| Sharp MZ-80B/2000/2500 | `sharp-mz-80b20002500` | mobygames logo launchbox logo | -| Sharp MZ-80K/700/800/1500 | `sharp-mz-80k7008001500` | mobygames logo | -| Sharp X1 | `x1` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Sharp X68000 | `sharp-x68000` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Sharp Zaurus | `sharp-zaurus` | mobygames logo | -| Signetics 2650 | `signetics-2650` | mobygames logo | -| Sinclair QL | `sinclair-ql` | igdb logo mobygames logo hasheous logo | -| Sinclair ZX81 | `zx81` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| SK-VM | `sk-vm` | mobygames logo | -| SMC-777 | `smc-777` | mobygames logo | -| Socrates | `socrates` | mobygames logo launchbox logo | -| Sol-20 | `sol-20` | igdb logo mobygames logo | -| Sony PSP Minis | `psp-minis` | launchbox logo | -| Sord M5 | `sord-m5` | mobygames logo launchbox logo | -| Spectravideo | `spectravideo` | screenscraper logo mobygames logo launchbox logo | -| SRI-500/1000 | `sri-5001000` | mobygames logo | -| SteamVR | `steam-vr` | igdb logo | -| Sufami Turbo | `sufami-turbo` | screenscraper logo | -| Super A'Can | `super-acan` | igdb logo screenscraper logo mobygames logo | -| Super Famicom | `sfam` | igdb logo mobygames logo launchbox logo hasheous logo retroachivements logo | -| Super NES CD-ROM System | `super-nes-cd-rom-system` | igdb logo | -| Super Nintendo Entertainment System | `snes` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Super Vision 8000 | `super-vision-8000` | mobygames logo launchbox logo hasheous logo | -| Sure Shot HD | `sure-shot-hd` | mobygames logo | -| SwanCrystal | `swancrystal` | igdb logo | -| SWTPC 6800 | `swtpc-6800` | mobygames logo | -| Symbian | `symbian` | mobygames logo | -| TADS | `tads` | mobygames logo | -| Taito Type X | `type-x` | launchbox logo | -| Taito X-55 | `taito-x-55` | screenscraper logo mobygames logo | -| Tandy Vis | `tandy-vis` | | -| Tapwave Zodiac | `zod` | igdb logo launchbox logo | -| Tatung Einstein | `tatung-einstein` | igdb logo mobygames logo | -| Tektronix 4050 | `tektronix-4050` | mobygames logo | -| Tele-Spiel ES-2201 | `tele-spiel` | mobygames logo | -| Telstar Arcade | `telstar-arcade` | mobygames logo | -| Terebikko / See 'n Say Video Phone | `terebikko-slash-see-n-say-video-phone` | igdb logo | -| Terminal | `terminal` | mobygames logo | -| Texas Instruments TI-82 | `ti-82` | hasheous logo | -| Texas Instruments TI-83 | `ti-83` | hasheous logo | -| Texas Instruments TI-99 | `ti-99` | igdb logo screenscraper logo mobygames logo | -| Thomson MO5 | `thomson-mo5` | igdb logo screenscraper logo mobygames logo | -| Thomson TO | `thomson-to` | screenscraper logo mobygames logo | -| TI Programmable Calculator | `ti-programmable-calculator` | mobygames logo | -| TI-99/4A | `ti-994a` | mobygames logo launchbox logo | -| Tiki 100 | `tiki-100` | mobygames logo | -| TIM | `tim` | mobygames logo | -| Timex Sinclair 2068 | `timex-sinclair-2068` | mobygames logo | -| Tizen | `tizen` | mobygames logo | -| Tomahawk F1 | `tomahawk-f1` | mobygames logo | -| Tomy Tutor | `tomy-tutor` | mobygames logo launchbox logo | -| Tomy Tutor / Pyuta / Grandstand Tutor | `tomy-tutor-slash-pyuta-slash-grandstand-tutor` | igdb logo | -| Triton | `triton` | mobygames logo | -| TRS-80 | `trs-80` | igdb logo mobygames logo launchbox logo hasheous logo | -| TRS-80 Color Computer | `trs-80-color-computer` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo | -| TRS-80 MC-10 | `trs-80-mc-10` | mobygames logo | -| TRS-80 Model 100 | `trs-80-model-100` | mobygames logo | -| TurboGrafx-16/PC Engine | `tg16` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Turbografx-16/PC Engine CD | `turbografx-cd` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| tvOS | `tvos` | mobygames logo | -| Uzebox | `uzebox` | igdb logo screenscraper logo retroachivements logo | -| V.Flash | `vflash` | mobygames logo | -| V.Smile | `vsmile` | igdb logo screenscraper logo mobygames logo launchbox logo | -| VC 4000 | `vc-4000` | igdb logo launchbox logo | -| Vector-06C | `06c` | launchbox logo | -| Vectrex | `vectrex` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Versatile | `versatile` | mobygames logo | -| VideoBrain | `videobrain` | mobygames logo | -| Videopac+ G7400 | `videopac-g7400` | screenscraper logo mobygames logo launchbox logo | -| Virtual Boy | `virtualboy` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Virtual Console | `vc` | igdb logo | -| VIS | `vis` | mobygames logo | -| visionOS | `visionos` | igdb logo | -| Visual Memory Unit / Visual Memory System | `visual-memory-unit-slash-visual-memory-system` | igdb logo | -| Wang 2200 | `wang2200` | mobygames logo | -| WASM-4 | `wasm-4` | retroachivements logo | -| Watara/QuickShot Supervision | `supervision` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo | -| watchOS | `watchos` | mobygames logo | -| webOS | `webos` | mobygames logo | -| Wii | `wii` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Wii U | `wiiu` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Windows | `win` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| Windows 3.x | `win3x` | screenscraper logo mobygames logo launchbox logo | -| Windows Apps | `windows-apps` | mobygames logo | -| Windows Mixed Reality | `windows-mixed-reality` | igdb logo | -| Windows Mobile | `windows-mobile` | igdb logo mobygames logo | -| Windows Phone | `winphone` | igdb logo mobygames logo howlongtobeat logo | -| WIPI | `wipi` | mobygames logo | -| WonderSwan | `wonderswan` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo howlongtobeat logo | -| WonderSwan Color | `wonderswan-color` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo retroachivements logo | -| WoW Action Max | `action-max` | launchbox logo hasheous logo | -| XaviXPORT | `xavixport` | mobygames logo launchbox logo | -| Xbox | `xbox` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Xbox 360 | `xbox360` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Xbox Cloud Gaming | `xboxcloudgaming` | mobygames logo | -| Xbox One | `xboxone` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Xbox Series X/S | `series-x-s` | igdb logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| Xerox Alto | `xerox-alto` | mobygames logo | -| Z-machine | `z-machine` | screenscraper logo mobygames logo | -| Zeebo | `zeebo` | igdb logo mobygames logo howlongtobeat logo | -| Zilog Z80 | `z80` | mobygames logo | -| Zilog Z8000 | `zilog-z8000` | mobygames logo | -| ZiNc | `zinc` | launchbox logo | -| Zodiac | `zodiac` | mobygames logo | -| Zune | `zune` | mobygames logo | -| ZX Spectrum | `zxs` | igdb logo screenscraper logo mobygames logo launchbox logo hasheous logo howlongtobeat logo | -| ZX Spectrum Next | `zx-spectrum-next` | mobygames logo | -| ZX80 | `zx80` | mobygames logo hasheous logo | diff --git a/docs/System-Setup/Synology-Setup-Guide.md b/docs/System-Setup/Synology-Setup-Guide.md deleted file mode 100644 index 8ac0c6a3..00000000 --- a/docs/System-Setup/Synology-Setup-Guide.md +++ /dev/null @@ -1,119 +0,0 @@ - - -## External Written Guides - -While you can follow the below guide, [Marius Bogdan Lixandru](https://mariushosting.com/) has written excellent guides which focus on Synology infrastructure and with support for both MariaDB and PostGresSQL: - -- [How to Install RomM on Your Synology NAS (MariaDB)](https://mariushosting.com/how-to-install-romm-on-your-synology-nas/) -- [How to Install RomM With PostgreSQL on Your Synology NAS](https://mariushosting.com/how-to-install-romm-with-postgresql-on-your-synology-nas/) - -We suggest following the above guides if they fit your setup, and the guide below is available for all other use cases. - -## Prerequisites - -This guide assumes you're familiar with Docker and have basic knowledge of server management. You'll need: - -- A Synology NAS or similar server -- Docker installed -- Basic command line knowledge -- Access to manage network settings - -## Setup Process - -### 1. Folder Structure Setup - -#### ROM Storage Folders - -Create the following directory structure for game assets and configuration: - -```bash -mkdir -p /volume1/data/media/games/assets -mkdir -p /volume1/data/media/games/config -``` - -#### ROM Library Structure - -RomM requires a **very specific folder structure** for rom files: - -```bash -mkdir -p /volume1/data/media/games/library/roms -mkdir -p /volume1/data/media/games/library/bios -``` - -Note: For supported platforms and their specific folder names, refer to the [official RomM docs](../Platforms-and-Players/Supported-Platforms.md). - -#### Docker Data Folders - -Create these folders for project and container data: - -```bash -mkdir -p /volume1/docker/romm-project/ -mkdir -p /volume1/docker/romm/resources -mkdir -p /volume1/docker/romm/redis-data -mkdir -p /volume1/docker/mariadb-romm -``` - -### 2. Network Bridge Setup - -Create a new network bridge named `rommbridge` following standard Docker networking practices. You can use [this guide](https://drfrankenstein.co.uk/step-3-setting-up-a-docker-bridge-network-in-container-manager/) for reference. - -### 3. Key Generation - -#### Authentication Key - -Generate your authentication key using: - -```bash -openssl rand -hex 32 -> 03a054b6ca27e0107c5eed552ea66bacd9f3a2a8a91e7595cd462a593f9ecd09 -``` - -Save the output - you'll need it for the `ROMM_AUTH_SECRET_KEY` in your configuration. - -#### API Integration Setup - -Follow the dedicated docs page for [API key generation](../Getting-Started/Metadata-Providers.md) to set up your API keys. - -### 4. MariaDB Configuration - - -!!! important - - This guide uses a dedicated MariaDB container for RomM, but you can use an existing MariaDB instance if preferred - - We're using MariaDB version 10.7 for compatibility - - The container uses port 3306 internally, mapped to 3309 externally - - A simplified health check is implemented for stability - -### 5. Docker Compose Configuration - -Create a `docker-compose.yml` file with the following content: - - -???+ example "Example Docker Compose" - ``` yaml - --8<-- "synology.docker-compose.yml" - ``` - -### 6. Initial Launch - -1. Start the containers using Docker Compose -2. **Be patient!** The container can take a few minutes to setup on first launch -3. Monitor progress through container logs -4. Access RomM through your browser at `http://your-server-ip:7676` - - -!!! important - - Replace placeholder values (UIDs, GIDs, passwords, API keys) with your own - - Ensure proper permissions on all created directories - - Back up your configuration after successful setup - - Monitor logs during initial startup for any errors - -## Troubleshooting - -- If the web interface shows "page not found," wait for initial setup to complete -- For database connection issues, verify MariaDB container health status -- Check logs for both containers if experiencing issues -- Ensure all volumes are properly mounted with correct permissions - -## Contributing - -This guide is an abridged version of ChopFoo's original guide. If you have any suggestions or improvements, please submit a pull request to the [RomM docs](https://github.com/rommapp/docs). diff --git a/docs/System-Setup/TrueNAS-Setup-Guide.md b/docs/System-Setup/TrueNAS-Setup-Guide.md deleted file mode 100644 index 41d5211e..00000000 --- a/docs/System-Setup/TrueNAS-Setup-Guide.md +++ /dev/null @@ -1,74 +0,0 @@ - - -## Prerequisites - -This guide assumes you're familiar with Docker and have basic knowledge of TrueNAS. You'll need: - -- A running TrueNAS installation -- Your games setup in the [required folder structure](https://github.com/rommapp/romm/blob/master/README.md) - -## Setup Process - -### Install through the TrueNAS App Catalog (Recommended) - -#### Step 1: Navigate to RomM app - -Navigate to the App Catalog via Apps (Left navigation bar) -> Discover Apps -> RomM -> Install - -![RomM app](../resources/truenas/appstore.png) - -#### Step 2: Installation configuration - -Step through the installation UI. You will need to supply various credentials per the [Quick Start Guide](../Getting-Started/Quick-Start-Guide.md). Most of the default values will work. - -Note: You will likely want to set certain Storage Configurations to a Dataset within TrueNAS, such as your RomM Library and Assets storage. If you do this, ensure you provide ACL access to the UserID specified above (default: 568, apps user). - -![RomM Library Example](../resources/truenas/app-config.png) - -#### Step 3: Save your configuration - -Save, and you're done! If the app will not boot, refer to [Troubleshooting](#troubleshooting) or head on over to the [Discord](https://discord.gg/P5HtHnhUDH). - -### Install via YAML - -This installation path should only be used in the event that there is a bug with installing through the App Catalog, or you wish to have more flexibility than is provided by the installation UI. - -#### Step 1: Navigate to YAML install - -Navigate to the `Install via YAML` page via Apps (Left navigation bar) -> Discover Apps -> Install via YAML - -![Install via YAML](../resources/truenas/install-via-yaml.png) - -#### Step 2: Paste in the following YML - -Replace any empty values with credentials you've created per the [Quick Start Guide](../Getting-Started/Quick-Start-Guide.md). - - -???+ example "Example Docker Compose" - ``` yaml - --8<-- "truenas.docker-compose.yml" - ``` - -#### Step 3: Save the configuration - -Save, and you're done! If the app will not boot, refer to [Troubleshooting](#troubleshooting) or head on over to the [Discord](https://discord.gg/P5HtHnhUDH). - -## Troubleshooting - -### General - -- Ensure you have replaced empty values (UIDs, GIDs, passwords, API keys) with your own -- Ensure proper permissions are applied within TrueNAS -- Monitor logs via the app bash terminal during for any errors if the app is encountering issues - -### Specific Issues - -#### Permissions issues inside the docker image - -If you are encountering permissions issues with folders internal to the docker image (not your TrueNAS dataset), consider temporarily setting the user to root (user: 0). If you do this, it is recommended you fix local file permissions via shell and return access back to a non-root user. - -In my particular setup, I had to create a user/group in TrueNAS with uid:gid of 1000:1000 and auxiliary group `apps` due to hard-coded values in the RomM docker image. This resolved outstanding issues I had with my instance of RomM talking to its Redis instance. - -## Contributing - -If you have any suggestions or improvements, please submit a pull request to the [RomM docs](https://github.com/rommapp/docs). diff --git a/docs/System-Setup/Unraid-Compose-Setup.md b/docs/System-Setup/Unraid-Compose-Setup.md deleted file mode 100644 index b7d6dcd1..00000000 --- a/docs/System-Setup/Unraid-Compose-Setup.md +++ /dev/null @@ -1,61 +0,0 @@ - - -## Prerequisites - -Before getting started, install the [Community Apps plugin](https://forums.unraid.net/topic/38582-plug-in-community-applications/) for Unraid. - -Install [Docker Compose Addon](https://forums.unraid.net/topic/114415-plugin-docker-compose-manager/) from the CA (Community Apps Store) - -![Docker Compose Addon](../resources/unraid/docker-compose.png) - -### Docker Tab - -You will now see Compose option under the Docker Containers in your Docker Tab in Unraid - -![Docker Compose Section](../resources/unraid/unraid-start.png) - -## Installation - -Click **Add New Stack** - -- Name it **RomM** and click **OK** - -- Click the **Gear Icon**, edit stack, then edit the compose file - -![Edit Stack](../resources/unraid/edit-stack.png) - -- Add in the example Docker Compose from our [example docker-compose.yml](https://github.com/rommapp/romm/blob/master/examples/docker-compose.example.yml) - -- Add your environment variables, for example: API keys, MariaDB info, and metadata providers - - - You can use secrets and fill in information in a separate `.env` file - -![Edit Compose](../resources/unraid/unraid-compose.png) - -- Click the **Gear Icon**, edit stack, then edit the environment file - - - Fill in any environment variables if you used secrets, etc. - -- Make sure to click **Save Changes** after each edit to the compose and environment files - -![Edit Env](../resources/unraid/romm-env.png) - - -!!! warning - You need to make sure you are following either Folder Structure A or B (Recommend A Type) [RomM Folder Structure](https://docs.romm.app/latest/Getting-Started/Folder-Structure/) - - -!!! warning - It's strongly recommended to backup the `appdata` folder (or mount it in a safe location) before updating, since tearing down the container will wipe the resources (covers, screenshots, etc.) - -## Finish - -- Click Compose Up - -![Compose Up Working](../resources/unraid/docker-compose-loading.png) - -Grab `IP:Port` from romm, and open tab in browser in `http://IP:Port` and it should take you to setup screen - -![Compose Up](../resources/unraid/docker-compose-up.png) - -![Romm Setup](../resources/unraid/unraid-success.png) diff --git a/docs/System-Setup/Unraid-Setup-Guide.md b/docs/System-Setup/Unraid-Setup-Guide.md deleted file mode 100644 index 944d61b9..00000000 --- a/docs/System-Setup/Unraid-Setup-Guide.md +++ /dev/null @@ -1,67 +0,0 @@ - - -## Prerequisites - -Before getting started, install the [Community Apps plugin](https://forums.unraid.net/topic/38582-plug-in-community-applications/) for Unraid. - -### Docker network - -You'll want to create a custom bridge-type network for both containers to communicate with each other. This will prevent a number of common issues Unraid users tend to come across during setup. This can be done with the following command: `docker network create romm`, and you can verify it worked with `docker network ls`. - -![console output](https://github.com/user-attachments/assets/bac31998-1911-4085-b115-8dd93d519b8b) - -### MariaDB - -MariaDB is required to run RomM, so install it from the plugin registry. Only the [official](https://hub.docker.com/_/mariadb) and [linuxserver](https://github.com/linuxserver/docker-mariadb/pkgs/container/mariadb) versions are supported, but **the official version is preferred**. - -![community apps search results for MariaDB](https://github.com/user-attachments/assets/76f4b6ef-5b63-454f-9357-d2920b9afd0e) - -Now fill in all the environment variables; descriptions of the options and sensible defaults are listed in the [example docker-compose.yml](https://github.com/rommapp/romm/blob/master/examples/docker-compose.example.yml) file. - - -!!! warning - The network type must be set to `Custom: romm` - -![MariaDB environment variables](https://github.com/user-attachments/assets/a11906c5-25b2-46f1-906b-451a9ee39dca) - -## Installation - -From the Unraid dashboard, click `APPS` in the navigation bar. In the search bar, search for `romm`, and install the app listed as "OFFICIAL". This one is maintained by our team and is the most up-to-date. - -![RomM official app](https://github.com/user-attachments/assets/57c4d47a-8604-4e8d-b05a-84dd68dda124) - -## Configuration - -Configure the required environment variables, ports and paths as per the [example docker-compose.yml](https://github.com/rommapp/romm/blob/master/examples/docker-compose.example.yml) file. - - -!!! warning - The network type must also be set to `Custom: romm` - -![RomM docker tab](https://github.com/user-attachments/assets/4c4210c2-ed00-4790-a945-65cbe33620b0) - -Apply the changes, then head to the `DOCKER` tab. You should see both containers in a running state, and can access RomM using the IP:PORT of the container (highlighted below). - -![RomM and MariaDB running](https://github.com/user-attachments/assets/cba26de1-d2c9-4fff-88d8-bc7701f0dd88) - - -!!! warning - It's strongly recommended to backup the `appdata` folder (or mount it in a safe location) before updating, since tearing down the container will wipe the resources (covers, screenshots, etc.) - -## Video tutorial - -[DemonWarriorTech](https://www.youtube.com/@DemonWarriorTech) has published [How to Install RomM on Unraid (Beginner Friendly)](https://www.youtube.com/watch?v=Oo5obHNy2iw) on installing and running RomM on Unraid for Beginners with an in depth instructions and explanation of the software install and how to use it. - -[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/Oo5obHNy2iw/0.jpg)](https://www.youtube.com/watch?v=Oo5obHNy2iw) - -[AlienTech42](https://www.youtube.com/@AlienTech42) has published [a great video](https://www.youtube.com/watch?v=ls5YcsFdwLQ) on installing and running RomM on Unraid. While a bit out of date vis-a-vis install instructions, it's still very useful for general setup and debugging. Check it out! - -[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/ls5YcsFdwLQ/0.jpg)](https://www.youtube.com/watch?v=ls5YcsFdwLQ) - -## Unraid community support - -You can find a [support thread](https://forums.unraid.net/topic/149738-support-eurotimmy-romm-rom-manager-by-zurdi15/) in the unraid forums. - -## Shout-outs - -We want to give a special shout-out to @Smurre95 and @sfumat0 for their help documenting this process, and working towards getting RomM listed in CA. 🤝 diff --git a/docs/Tools/Igir-Collection-Manager.md b/docs/Tools/Igir-Collection-Manager.md deleted file mode 100644 index 3af40c25..00000000 --- a/docs/Tools/Igir-Collection-Manager.md +++ /dev/null @@ -1,124 +0,0 @@ - - -[Igir](https://igir.io/) is a zero-setup ROM collection manager that sorts, filters, extracts or archives, patches, and reports on collections of any size on any OS. It can be used to rename your ROMs to match the RomM database, and to move them into a new directory structure. - -## Setup - -### Directory structure - -The directory structure is important for running the bulk ROM renaming script. Before running the bulk ROM renaming script, set up your directories as follows: - -```md -. -├── dats/ # DAT files from no-intro.org -├── roms/ # Original ROM collection -├── roms-unverified/ # Working copy of ROMs -└── igir-romm-cleanup.sh -``` - -### Initial Setup Steps - -1. Create a working copy of your ROMs: - - ```bash - cp -r roms/ roms-unverified/ - ``` - - This provides a safe working environment and allows for easy script adjustment if needed. - -2. Download DAT Files: - - - For cartridge-based systems: - - Visit [No-Intro.org Daily Download](https://datomatic.no-intro.org/index.php?page=download&op=daily) - - Download the latest DAT compilation - - For optical media (e.g., PlayStation): - - Visit [redump.org](http://redump.org/downloads/) - - Download platform-specific DAT files - - Extract the DAT files to your `dats` directory. You can optionally extract a subset of the .dat files into the directory instead. - -## Configuration - -Create the cleanup script `igir-romm-cleanup.sh` with the contents below: - -```bash -#!/usr/bin/env bash -set -ou pipefail -cd "$(dirname "${0}")" - -INPUT_DIR=roms-unverified -OUTPUT_DIR=roms-verified - -# Documentation: https://igir.io/ -# Uses dat files: https://datomatic.no-intro.org/index.php?page=download&op=daily -time npx -y igir@latest \ - move \ - extract \ - report \ - test \ - -d dats/ \ - -i "${INPUT_DIR}/" \ - -o "${OUTPUT_DIR}/{romm}/" \ - --input-checksum-quick false \ - --input-checksum-min CRC32 \ - --input-checksum-max SHA256 \ - --only-retail -``` - -Make the script executable: - -```bash -chmod a+x igir-romm-cleanup.sh -``` - -## Usage - -### Run the script - -Run the script. It will generate a new output directory named `roms-verified`, moving the files from `roms-unverified` if its checksum matches any of the known checksums in the DAT files provided. Any ROMs not identified will remain in the `roms-unverified` directory. - -### Manually move over remaining files - -The script may not identify all of the ROMs in your input directory. You can choose to migrate them over manually: - -```bash -npx -y igir@latest \ - move \ - -i roms-unverified/ \ - -o roms-verified/ \ - --dir-mirror -``` - -This will move your ROMs from the input to the output directory, preserving the subdirectory structure. It also cleans up file extensions in the process. - -### Reorganize multi-disc games - -The Igir script will move games that have multiple discs to separate folders. This can confuse RomM's game detection, and those games need to be reorganized into single folders with many discs. - -To do this enter your platform directory, such as `ps` or `psx` and run the following: - -```bash -ls -d Disc | while read file; do - game=$(echo "${file}" | sed -E 's/ ?(Disc.*//') - mkdir -p "${game}" - mv "${file}" "${game}" - m3u="${game}/${game}.m3u" - touch "${m3u}" - echo "${file}" >> "${m3u}" -done -``` - -This will find any directory with `(Disc` in the name and move the files into a new directory without the `(Disc #)` string. For example: - -Before: - -```bash -Final Fantasy VII (Disc 1) (USA) -Final Fantasy VII (Disc 2) (USA) -``` - -Gets combined to: - -```bash -Final Fantasy VII (USA) -``` diff --git a/docs/Troubleshooting/Authentication-Issues.md b/docs/Troubleshooting/Authentication-Issues.md deleted file mode 100644 index 3ff41883..00000000 --- a/docs/Troubleshooting/Authentication-Issues.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Troubleshooting Authentication -description: Troubleshooting issues relating to authentication ---- - -### Error: `403 Forbidden` - -When authentication is enabled, most endpoints will return a `403 Forbidden` response if you're not authenticated, or if your sessions is in a broken state. The session key can be reset by [clearing your cookies](https://support.google.com/accounts/answer/32050). - -CSRF protection is also enabled, which helps to mitigates [CSRF attacks](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html) (useful if your instance is public). If you encounter a `Forbidden (403) CSRF verification failed` error, simply reloading your browser should force it to fetch a fresh CSRF cookie. - -### Error: `Unable to login: CSRF token verification failed` - -This error is known to happen on Chrome, but could happen in other browsers; manually clear your cookies (specifically one called `csrftoken`) and hard reload your browser window (CMD+SHIFT+R on macOS, CTRL+F5 on Windows). - -### Error: `400 Bad Request` on the Websocket endpoint - -If you're running RomM behind a reverse-proxy (Caddy, Nginx, etc.), ensure that Websockets are supported and enabled. This may vary depending on the reverse proxy solution being used. In the case of Nginx Proxy Manager, enable the "Websockets Support" toggle when editing the proxy host. diff --git a/docs/Troubleshooting/Kubernetes-Issues.md b/docs/Troubleshooting/Kubernetes-Issues.md deleted file mode 100644 index cec85010..00000000 --- a/docs/Troubleshooting/Kubernetes-Issues.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Kubernetes Troubleshooting -description: Troubleshooting Kubernetes issues ---- - -### Error: `invalid host in "tcp://:8080" of the "listen" directive in /etc/nginx/conf.d/default.conf:7` - -By default, Kubernetes will grab information about the service object linked to a pod and inject it as an environment variable into the pod. In RomM, this leads to the pod attempting to bind to the service IP address, leading to the above fatal error. - -To resolve thes error, this default Kubernetes behaviour needs to be disabled by setting the `enableServiceLinks` value in the pod spec to `false`. - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: romm - namespace: romm - ... -spec: - ... - template: - ... - spec: - enableServiceLinks: false - ... -``` diff --git a/docs/Troubleshooting/Miscellaneous-Troubleshooting.md b/docs/Troubleshooting/Miscellaneous-Troubleshooting.md deleted file mode 100644 index 2438d3c6..00000000 --- a/docs/Troubleshooting/Miscellaneous-Troubleshooting.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: Miscellaneous Troubleshooting -description: Troubleshooting miscellaneous issues ---- - -### Restarting the container when using SQLite drops all the data/requires a full re-scan - -Verify that the database is mapped to a persistent storage volume in your docker compose or Unraid template. - -```yaml -"/path/to/database:/romm/database" # [Optional] Only needed if ROMM_DB_DRIVER=sqlite or not set -``` - -### Error: `Could not get twitch auth token: check client_id and client_secret` - -This is likely due to mis-configured environment variables; verify that `CLIENT_ID` and `CLIENT_SECRET` are set correctly, and that both match the values in IGDB. - -### How to view RomM logs to assist with troubleshooting - -Each platform may have different logs, but check the stdout logs for docker. For example when using the recommended docker compose setup `docker logs -f romm` will display a continuous stream of the log. Most lines start with `INFO`, `WARNING`, or `ERROR` diff --git a/docs/Troubleshooting/Scanning-Issues.md b/docs/Troubleshooting/Scanning-Issues.md deleted file mode 100644 index 3e2f5fa2..00000000 --- a/docs/Troubleshooting/Scanning-Issues.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Troubleshooting Scanning -description: Troubleshooting issues relating to library scanning ---- - -### Scan is skipping all platforms/ends instantly - -There are a few common reasons why a scan may end instantly/without scanning platforms - -- Badly mounted library: verify that you mounted your ROMs folder at `/romm/library` -- Incorrect permissions: the app needs to read the files and folders in your library, check their permissions with `ls -lh` -- Invalid folder structure: verify that your folder structure matches the one in the [README](https://github.com/rommapp/romm#-folder-structure) - -### ROMs not found for platform X, check `romm` folder structure - -This is the same issue as the one above, and can be quickly solved by verifying your folder structure. RomM expects a library with a folder named `roms` in it, for example: - -- `/server/media/library:/romm/library` -- `/server/media/games/roms:/romm/library/roms` - -### Scan does not recognize a platform - -When scanning the folders mounted in `/library/roms`, the scanner tries to match the folder name with the platform's slug in IGDB. If you notice that the scanner isn't detecting a platform, verify that the folder name matches the slug in the URL of the [platform in IGDB](https://www.igdb.com/platforms). For example, the Nintendo 64DD has the URL , so the folder should be named `64dd`. - -### Scan times out after ~4 hours - -The background scan task times out after 4 hours, which can happen if you have a very large library. The easiest work around is to keep running scans every 4 hours, **without** checking the "Complete re-scan" option. You can also change the timeout via [environment variable](../Getting-Started/Environment-Variables.md) `SCAN_TIMEOUT`. - -### Scan stops before finishing a platform - -Check the logs for RomM, you should find a line that looks like `ERROR: [RomM][scan_handler][2025-04-12 11:48:55]` that explains why the scanner stopped. This can often happen due to a corrupted file or a file the [python zipfile library](https://docs.python.org/3/library/zipfile.html) cannot handle, such as old DOS zip files with backslashes instead of forward slashes. - -### When scanning a very large library with many platforms it is difficult to keep track of which systems have scanned in - -The easiest method is to check the logs via this command, which will list all the scanned platforms since the RomM container was started `docker logs romm 2>/dev/null|egrep 'scan_handler.*Identified as.*🎮'` - -Here is an example output: - -```text -$ docker logs romm 2>/dev/null|egrep 'scan_handler.*Identified as.*🎮' -INFO: [RomM][scan_handler][2025-04-12 11:37:40] Identified as PlayStation 🎮 -INFO: [RomM][scan_handler][2025-04-12 14:39:32] Identified as DOS 🎮 -INFO: [RomM][scan_handler][2025-04-13 12:50:42] Identified as WonderSwan 🎮 -``` diff --git a/docs/Troubleshooting/Synology-Issues.md b/docs/Troubleshooting/Synology-Issues.md deleted file mode 100644 index ec5ebb17..00000000 --- a/docs/Troubleshooting/Synology-Issues.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Troubleshooting Synology -description: Troubleshooting issues when using Synology products ---- - -### ErrNo 13: Access Denied - -We have noticed recently a spate of access denied on Synology systems via Portainer or even docker manager. The ErrNo13 is directly related to Synology and it is a simple permission issue. To fix it please do the following: - -1. Make sure SSH is enabled on your Synology product. Refer to here if it is not [Enable SSH](https://kb.synology.com/en-uk/DSM/tutorial/How_to_login_to_DSM_with_root_permission_via_SSH_Telnet) -2. Connect to SSH and login as your admin username and password (Same login used to login to DSM web page) -3. Take a note on your user:group you can find this by typing ID when logged into SSH. -4. Type the following commands in the SSH window. - -`sudo chown -R user:group /path/to/library` - -`sudo chmod -R a=,a+rX,u+w,g+w /path/to/library` - -`sudo chown -R user:group /path/to/assets` - -`sudo chmod -R a=,a+rX,u+w,g+w /path/to/assets` - -`sudo chown -R user:group /path/to/config` - -`sudo chmod -R a=,a+rX,u+w,g+w /path/to/config` - -You will find the relevant directories in your compose, this is basically the folders where you store your RomM information and we are just resetting permissions. Restart the containers and you should now have no issues scanning information in! - -Any issues please ask in the Discord. - -Thanks to [Docker IDs - DrFrankenstein](https://drfrankenstein.co.uk/step-2-setting-up-a-restricted-docker-user-and-obtaining-ids/) for the guidance from his blog. diff --git a/docs/Usage/Administration.md b/docs/Usage/Administration.md deleted file mode 100644 index 8a565ab4..00000000 --- a/docs/Usage/Administration.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Administration -description: Navigating and using the Administration Menu ---- - -Clicking on your Profile icon from any screen opens the Administration Drawer. This drawer will look slightly different based on your role. The options available can include **Profile**, **User Interface**, **Library Management**, **Administration**, **Server Stats**, and **About**. - -## Profile - -All users can access this screen. From here you can change your username, password, and email. - -Additionally, you can submit your RetroAchievements username and synchronize your achievements here. - -## User Interface - -From here you can: - -- Change your language -- Adjust the color scheme of RomM -- Control which ribbons are visible on the home screen -- Configure how to group your platforms -- Set what information to display on game cards -- Configure autogenerated collections and their sources - -## Library Management - -From this screen you can: - -- Edit platform bindings and versions on the Config tab -- Manage missing games on the Missing Games tab - -## Administration - -From this page you can manage users and check scheduled and manual tasks. - -## Server Stats - -This area displays the number of platforms, games, saves, states, and screenshots on the server, as well as how much disk space this consumes. Platforms can be filtered here to show how much each platform contributes to total size and game count. - -## About - -This pop-up displays your RomM version with links to the community Discord, GitHub, and documentation. diff --git a/docs/Usage/LibraryManagement.md b/docs/Usage/LibraryManagement.md deleted file mode 100644 index 5486c6e4..00000000 --- a/docs/Usage/LibraryManagement.md +++ /dev/null @@ -1,150 +0,0 @@ ---- -title: Library Management -description: Adding, Removing, and Managing Platforms and Games. ---- - -## The Library View - -The default library view shows a few ribbons: **Recently Added**, **Continue Playing**, **Platforms**, and **Collections**. Games and Platforms are presented as cards that can be interacted with. - -The menu bar is constantly visible and includes tools to **Search**, **List Platforms**, **Manage Collections**, **Scan**, go into **Console Mode**, and **Upload** content as well as access your administration panel. - -In all views, a grid icon is present in the upper right of the screen or container. This can be toggled to collapse or expand the container. - -### Game and Platform cards - -Platform cards can be clicked to go directly to the platform. A game card can be interacted with in several ways: putting your mouse over it allows you to download the game, play the game if the system is supported, or open a context menu giving you the option to manually match game information using a metadata agent, edit existing data, refresh the metadata, and add or remove the game from favourites or collections. - -![game card](https://raw.githubusercontent.com/rommapp/docs/refs/heads/main/docs/resources/usage/gameCard.png) -![context menu](https://raw.githubusercontent.com/rommapp/docs/refs/heads/main/docs/resources/usage/ContextMenu.png) - -Clicking a platform will take you to the platform view, while clicking a game will take you to the game view. - -### Filters - -Filters are present on nearly every screen in RomM, allowing you to quickly drill down to see only the information relevant to your search. - -If you perform a search first, the listed filters will be taken from the metadata of all present games. For example, if you searched for the word "Fox", and then clicked filters and selected a Language, the list of languages available will be taken from the displayed games. - -#### Toggles - -The filters that can be toggled include: - -- **Show Unmatched** - Show only games that have not yet been matched at all. -- **Show Matched** - Show only games that have been matched. -- **Show Favourites** - Show only games that are Favourites. -- **Show Duplicates** - Show only games that have multiple copies. -- **Show Playables** - Show only games that can be played in a browser. -- **Show Missing** - Shows only games that exist in the database but are otherwise not present. -- **Show Verified** - Shows only games that have matched to Hasheous. -- **Show RetroAchievements** - Shows only games that have support on the RetroAchievements website. - -Next there is a platform dropdown. This allows you to select a platform you want to restrict your view to showing. - -After this you can filter by metadata: Game Genre, Franchise, Collections, Company, Age Rating, Region, and Language. -One additional filter exists after these: Status. This allows you to use the "personal" data tab on any game to track your progress of the game (never played, backlogged, complete, etc). - -## The Menu bar - -The menu bar is designed for quick access to the tools of your RomM server. - -### Search - -Simply typing text into the search bar will bring up game cards for each game that matches the query. To the left of the search bar are two icons: the view filters and the new collection button. - -![search bar](https://raw.githubusercontent.com/rommapp/docs/refs/heads/main/docs/resources/usage/SearchBar.png) - -### List Platforms - -The Platforms button opens a drawer listing all of the known platforms in RomM. Clicking on any of these will create a search that is limited to that platform. - -### Collections - -The Collections button opens a drawer listing all of your manually created collections which is specific to each user, as well as your autogenerated collections created by RomM. Clicking a collection will take you to the collection view. - -### Scan - -This is where you'll scan for new platforms and games. `Metadata sources` can be selected to determine which providers will be used to fetch metadata. Use the `Platforms` dropdown to restrict your scan to specific platforms. - -The `Scan options` dropdown allows you to choose a specific type of scan to perform: - -- **New Platforms**: This will only look for platforms that are not already in RomM. -- **Quick Scan**: Scans for games that are not in the library yet (fastest). -- **Unmatched Games**: Attempts to match games that are not matched with the selected metadata sources. - - For example, selecting `IGDB` and `ScreenScraper` will scan games that are **not matched** with IGDB **or** ScreenScraper. -- **Update Metadata**: Updates the metadata for games that have been matched with selected metadata sources using the external ID (e.g. IGDB ID). - - For example, selecting `IGDB` and `ScreenScraper` will update the metadata for games that **are matched** with IGDB **or** ScreenScraper, and will use `igdb_id` and/or `ssfr_id` to refetch the metadata from the respective providers. -- **Recalculate Hashes**: Recalculates hashes for all files in the selected platforms. -- **Total Rescan**: Rescans and rematches all games in the selected platforms (slowest). - - This will wipe all existing metadata matches, including the external IDs, and attempt to match them again, like on a fresh scan. _Saves, states and notes will be preserved._ - -### Console - -This button will take you to a new full screen UI that's especially good for navigation with a controller. - -### Upload - -This button allows you to upload games directly to RomM from the user interface. Simply select a platform and then either click to browse to a ROM or drag and drop it onto the interface. - -### Recently Added - -After a scan is performed, the most recently added games can be found on this ribbon. - -### Continue Playing - -After a game has been played for any amount of time, it's added to this row. The context menu gains a new option for games located on this ribbon: remove from playing. This helps prevent the ribbon from being cluttered by games you wanted to test but do not plan on playing long term. - -### Platforms - -The list of platforms presented here will be matched by RomM by directory structure. See [Supported Platforms page](../Platforms-and-Players/Supported-Platforms.md) for more information about naming your directories. - -### Favourites and Collections - -This ribbon contains all the games you've marked as favourites, and any collections you've created or that have been generated by RomM. - -## Platform View - -The platform view shows all of the games for a specific platform. There is a button to show the platform drawer, the platform firmware, as well as the usual filter button. - -### Platform Drawer - -The platform view drawer has a large icon representing the platform, along with its title. - -Below that is a button to upload ROMs and a button to initiate scans. - -Below that is a line showing how many metadata providers are being used for that platform. - -Next comes all the metadata for the platform itself: the name, folder name, category, generation, and so on. - -Following that are the platform settings, which consists of the style of cover used in the game cards for that platform. - -Finally, in the Danger Zone, is a Delete Platform button. This removes the platform from the database, it does NOT touch the files on your system. If you delete a platform in this way, scanning for new platforms will restore it, and all games will have to have their metadata re-matched. - -![platform drawer](https://raw.githubusercontent.com/rommapp/docs/refs/heads/main/docs/resources/usage/PlatformView.png) - -### Firmware - -Next to the platform drawer button is the firmware button. This allows you to review all of the firmware for that system, and upload firmware using the user interface. - -Uploading firmware will open a file browse dialog box. Simply select the BIOS file or files you wish to upload and click "Upload". - -## Collection View - -The Collection View is similar to the Platform View. It has a Platform drawer next to the filters, much like how the Platform View has the Platform Drawer, but lacks the Firmware button. - -The Collection metadata will be shown, which includes a game count, who owns the collection, the privacy of the collection, and the ability to delete the collection. - -## Game View - -The game view is broken down into two distinct parts. - -The first container is the poster, with the usual download, play (if the system allows for playing in a web browser) and context menu as well as a new button: copy download link. - -The second container is the game tabs: Details, Game Data, and Personal tabs. These are containers for information about the game, how RomM sees the save data, and your personal notes. Additional tabs may be visible here depending on your configuration, including the Game Manual, data from How Long to Beat, screenshots, as well as related games. -The Details tab includes metadata for the game. This will show where the data comes from, the platform and year of release, as well as the file information like regions and collections. This is the information that is used for filtering. - -The Game Data tab includes save files and save states, the ability to upload and download them, as well as delete them. This data is personal to the logged in user. - -Finally the Personal tab has check boxes denoting if a game is backlogged, being played, or if it should be hidden. User data such as rating, difficulty, % completed, and the status of the game can also be set here. RetroAchievements can be viewed from this tab for supported matched games. - -If How Long To Beat is enabled as a metadata provider, there will also be a tab here for viewing that data as well. diff --git a/docs/Usage/UserManagement.md b/docs/Usage/UserManagement.md deleted file mode 100644 index 5422e27f..00000000 --- a/docs/Usage/UserManagement.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: User Management -description: Adding, Removing, and Managing your Users. ---- - -The Administration panel contains the tools used to manage users on the server. The first user created will always be given the admin role. - -Users can manage their own game saves, save states, their profile icon, and the "Personal" data tab on games. - -## Adding Users - -Adding a user is as simple as providing a username, password, email address, and selecting a role. Users can be added manually using the "Add" button or by inviting a user via link. When inviting a user, you only need to set a role; they will be prompted to complete the rest of the information. - -### Roles Explained - -**Admin** - The highest authority role. This grants full permission to do everything on the server. - -**Editor** - Can edit platforms and games (adding, removing, or scanning for new content) and make collections public. - -**Viewer** - The most restricted role. Can play games and interact with the Personal data tab. - -## Removing Users - -Removing a user is as simple as clicking the red delete icon and confirming the operation. diff --git a/docs/about/brand-guidelines.md b/docs/about/brand-guidelines.md new file mode 100644 index 00000000..571bceef --- /dev/null +++ b/docs/about/brand-guidelines.md @@ -0,0 +1,84 @@ +--- +title: Brand Guidelines +description: How to use the name, logo, and colors +--- + + + +# Brand Guidelines + +In this context, "RomM", "The RomM Project", "the project", "we", "us", and "our" refer to the RomM project and organization. + +## The logo + +
+ RomM logo +
+
+
+ +The logo should always be used in its standard colors: + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ColorHex
#371f69#371f69
#553e98#553e98
#ede5f8#ede5f8
#bea4e1#bea4e1
#e6c7a7#e6c7a7
#e1a38d#e1a38d
+
+ +![Branding guidelines poster](../resources/romm/brand_guidelines/poster.png) + +## Do these things + +- Use our logo to link to any page or site operated by the project. +- Use our logo in a blog post or news article about the project. +- Use our logo to inform others that your project integrates with RomM. +- Always use our logo in the colors provided. +- Always use our name in a way that makes clear you are not affiliated with the project. + +If you're building something that integrates with RomM and would like to use/remix the logo, **please reach out first** via [Discord](https://discord.gg/romm). We'd love to hear about it. + +## Please don't + +- Use our name or logo in any way that suggests you are us, are endorsed by us, or are part of the project. +- Use our name or logo in a way that implies partnership, sponsorship, or endorsement. +- Use our name or logo as the name or logo for your project, product, service, social media account, company, or website. +- Use our name or logo to promote, advertise, or sell any private business, closed-source software, commercial product, or paid service. + +## Downloadables + +The logo assets live at [rommapp/romm/tree/master/frontend/assets/](https://github.com/rommapp/romm/tree/master/frontend/assets/): + +- `isotipo.svg`/`isotipo.png`: the mark (circular logo) +- `logotipo.svg`/`logotipo.png`: the wordmark +- `social_preview.png`: GitHub social preview + +## Questions + +Ask on [Discord](https://discord.gg/romm) or open an issue. diff --git a/docs/about/credits.md b/docs/about/credits.md new file mode 100644 index 00000000..0f931943 --- /dev/null +++ b/docs/about/credits.md @@ -0,0 +1,90 @@ +--- +title: Credits +description: The humans, projects, and services that make RomM possible. +--- + +# Credits + +This project exists because a lot of people contributed code, designs, translations, ideas, and, most importantly, running bug reports back to the project. Thanks to every one of them. + +## Contributors + +[Every contributor](https://github.com/rommapp/romm/graphs/contributors) to [rommapp/romm](https://github.com/rommapp/romm), plus contributors to the surrounding repos: + +- [rommapp/argosy-launcher](https://github.com/rommapp/argosy-launcher/graphs/contributors) +- [rommapp/grout](https://github.com/rommapp/grout/graphs/contributors) +- [rommapp/playnite-plugin](https://github.com/rommapp/playnite-plugin/graphs/contributors) +- [rommapp/docs](https://github.com/rommapp/docs/graphs/contributors) + +## Translators + +The 19 locales exist because individual community members took the time to translate the UI. See each locale folder's commit history at [rommapp/romm/tree/master/frontend/src/locales](https://github.com/rommapp/romm/tree/master/frontend/src/locales) for per-locale credit. + +## Community apps + +Built by the community, not the RomM team. Full list in the [Community section in the RomM README](https://github.com/rommapp/romm/#community). + +## Financial supporters + +Donors via [Open Collective](https://opencollective.com/romm) make continued development possible. The project wouldn't exist without you. Thank you! ❤️ + +## Upstream projects + +This stack stands on an enormous amount of open-source work. In rough order of "how visible they are to users": + +### In-browser emulation + +- [EmulatorJS](https://emulatorjs.org/) +- [Ruffle](https://ruffle.rs/) +- [dosbox-pure](https://github.com/schellingb/dosbox-pure) + +### Metadata sources + +- [IGDB](https://www.igdb.com/) +- [ScreenScraper](https://screenscraper.fr/) +- [MobyGames](https://www.mobygames.com/) +- [RetroAchievements](https://retroachievements.org/) +- [SteamGridDB](https://www.steamgriddb.com/) +- [Hasheous](https://hasheous.org/) +- [PlayMatch](https://github.com/RetroRealm/playmatch) +- [LaunchBox Games Database](https://gamesdb.launchbox-app.com/) +- [TheGamesDB](https://thegamesdb.net/) +- [Flashpoint Archive](https://flashpointproject.github.io/flashpoint-database/) +- [HowLongToBeat](https://howlongtobeat.com/) +- [Libretro](https://www.libretro.com/) + +### Backend stack + +- [FastAPI](https://fastapi.tiangolo.com/) + [Starlette](https://www.starlette.io/) +- [SQLAlchemy](https://www.sqlalchemy.org/) + [Alembic](https://alembic.sqlalchemy.org/) +- [RQ](https://python-rq.org/) +- [MariaDB](https://mariadb.org/)/[PostgreSQL](https://www.postgresql.org/)/[MySQL](https://www.mysql.com/) +- [Redis](https://redis.io/)/[Valkey](https://valkey.io/) +- [nginx](https://nginx.org/) with [`mod_zip`](https://github.com/evanmiller/mod_zip) +- [uv](https://docs.astral.sh/uv/) + +### Frontend stack + +- [Vue 3](https://vuejs.org/) +- [Vuetify](https://vuetifyjs.com/) +- [Pinia](https://pinia.vuejs.org/) +- [Vite](https://vitejs.dev/) +- [socket.io](https://socket.io/) +- [vue-i18n](https://vue-i18n.intlify.dev/) +- [rom-patcher-js](https://www.marcrobledo.com/RomPatcher.js/) +- [vite-plugin-pwa](https://vite-pwa-org.netlify.app/) + +### Docs stack + +- [MkDocs](https://www.mkdocs.org/) + [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) +- [mike](https://github.com/jimporter/mike) for docs versioning +- [asciinema](https://asciinema.org/) for terminal recordings + +## Missing? + +Open a PR against this page. Credit is cheap, and we want to give it where it's due. + +## See also + +- [License](license.md) +- [Contributing](../developers/contributing.md) diff --git a/docs/about/faqs.md b/docs/about/faqs.md new file mode 100644 index 00000000..8a342f4d --- /dev/null +++ b/docs/about/faqs.md @@ -0,0 +1,171 @@ +--- +title: FAQs +description: Answers to the questions users most often ask +--- + +# FAQs + +## What is RomM? + +RomM (ROM Manager) allows you to scan your library, pull metadata, browse a clean UI, play in the browser, sync to handhelds, and run it all on your own hardware. + + +!!! note "RomM is server software you run on a homelab box or NAS" + It is not a desktop app, and there's no `.exe` or `.appimage`. You'll need basic Linux + Docker skills to set it up. **Games and copyrighted material aren't provided.** + +## Is it free? + +Yes! Licensed under [AGPL-3.0](license.md), the core will always be free. Other repos under our umbrella use equally permissive licenses, and there's no tracking or upsells. + +## How does it compare to [X other manager]? + +The emphasis here is self-hosted + multi-user + in-browser-play + the companion-app ecosystem. If those matter, try it, but if you just want a local Windows app that scans a folder, tools like LaunchBox may fit better. + +## Do I need metadata API keys? + +It runs without any but games won't match against a metadata source, so you won't get covers, descriptions, or ratings. + +## Is RomM legal? + +The software is legal but what you put in it depends on your jurisdiction. **We don't ship ROMs or firmware, don't help you find them, and can't give legal advice.** + +## Can I run RomM on [X]? + +Probably! Supported deployment paths: + +- Docker Compose (Linux, macOS, Windows with WSL2) +- Unraid/Synology/TrueNAS SCALE +- Kubernetes + +See [Install & Deploy](../install/index.md). + +Not supported: + +- Bare metal without containers (undocumented but _should_ work) +- TrueNAS CORE (FreeBSD) +- Windows without WSL + +## How much RAM/CPU does it need? + +- **Minimum** (small library, 1 user): 512 MB RAM, any modest CPU +- **Comfortable** (thousands of ROMs, a few users, occasional scans): 2 GB RAM, 2 cores + +Heaviest CPU usage is during scans, as hashing and network-bound metadata calls may cause spikes. + +## How do I update? + +```sh +docker compose pull rommapp/romm +docker compose up -d romm +``` + +Read the [upstream release notes](https://github.com/rommapp/romm/releases) before minor or major version upgrades. + +## Why can't I see a specific platform? + +The platform folder name probably doesn't match a known slug. Check [Supported Platforms](../platforms/supported-platforms.md), and fix it by either renaming the folder or updating the [`system.platforms`](../reference/configuration-file.md#systemplatforms) binding in `config.yml`. + +## Why are my ROMs unmatched after a scan? + +Most common reasons: + +- No metadata providers configured +- Filename too generic (no tags, unusual naming) +- Wrong platform detection + +Full troubleshooting steps can be found in [Scanning Troubleshooting](../troubleshooting/scanning.md). + +## My scan finds platforms but no games inside them + +This is almost always a mount-depth issue. The scanner expects the _parent_ of your `roms/` folder mounted to `/romm/library`, not the `roms/` folder itself. If your files live at `/opt/romm/library/roms/gbc/game.gbc`, mount `/opt/romm/library` to `/romm/library`, then re-scan. + +See [Folder Structure](../getting-started/folder-structure.md) and [Scanning Troubleshooting](../troubleshooting/scanning.md) for the full layout and common mount mistakes. + +## Why is my metadata wrong or incomplete? + +Metadata isn't owned, only pulled from third parties like IGDB and ScreenScraper. If a field is missing or wrong, the fix has to happen upstream on the provider's site. Cross-check against another provider if one is consistently off for your library. + +## Why am I getting a "Configuration file not Mounted!" error? + +A `config.yml` is read from `/config` at startup. If the mount/file is missing or unreadable, startup bails with this error (see [Configuration File](../reference/configuration-file.md) for the schema and an example you can drop in). + +## Can I play PS3 or newer consoles in the browser? + +**No.** In-browser emulation handles 4th-gen and earlier systems well. Saturn, PS1, and N64 are hit-or-miss. PSP and newer are mostly unplayable. Browser play is a bonus, as this is a library manager first, and standalone emulators remain the right tool for modern systems (see [Supported Platforms](../platforms/supported-platforms.md) for the current list). + +## Why is browser emulation laggy or not loading? + +A few common causes: + +- **Browser**: use a Chromium-based browser (Chrome, Edge, Brave). Firefox and Safari might run EmulatorJS poorly. +- **HTTPS**: PSP and DOS cores require the site served over `https://`. Accessing by IP won't work, so you need a [Reverse Proxy](../install/reverse-proxy.md) with TLS. +- **Hardware**: EmulatorJS runs entirely in the browser, so CPU-heavy cores need a capable (modern) browser. + +Full troubleshooting steps can be found in [In-Browser Play](../troubleshooting/in-browser-play.md). + +## Can I share my library with friends? + +Add them as users via the invite flow, then either: + +- Expose your instance publicly behind a [Reverse Proxy](../install/reverse-proxy.md) with TLS. +- Keep it private and share access over a VPN or Tailscale. + +See [Invitations & Registration](../administration/invitations-and-registration.md). + +## Can guests browse without an account? + +Absolutely, just set `KIOSK_MODE=true` in your environment variables and anonymous visitors get read-only access (see [Authentication → Kiosk mode](../administration/authentication.md#kiosk-mode)). + +## How do I back up? + +`mysqldump` the DB + rsync the `/romm/assets` and `/romm/config` volumes nightly. Full procedure and test-restore protocol in [Backup & Restore](../install/backup-and-restore.md). + +## Can I use RomM without the internet? + +You need internet for: + +- First-time scan with metadata providers (they're online APIs) +- Pulling the Docker image on install or upgrade +- OIDC login (if you use a cloud IdP) + +After the initial setup, browsing and playing can work offline. In-browser play downloads the emulator bundle on first launch, then caches it. + +## Why is scan X slow? + +Several possibilities, in rough order of likelihood: + +1. Hashing large files on spinning disks. +2. Metadata providers rate-limiting (mostly ScreenScraper). +3. Many files on a network mount with high latency. + +[Scanning Troubleshooting → Hash calculations are slow](../troubleshooting/scanning.md#hash-calculations-are-slow). + +## When will [feature X] be added? + +We don't give ETAs on individual features. Open (or upvote) an issue at [rommapp/romm](https://github.com/rommapp/romm/issues) to make the interest visible. + +## I found a bug, or I need help + +For bugs, open an issue at [rommapp/romm](https://github.com/rommapp/romm/issues). For questions, ask in `#romm-support` on [Discord](https://discord.gg/romm). Either way, include: + +- RomM version +- Deployment (Docker Compose/Unraid/K8s/etc.) +- Your `docker-compose.yml` with credentials and API keys redacted +- Container logs (`docker logs romm`) +- Exact reproduction steps + +## Who runs RomM? + +A small team of maintainers plus a chunk of active community contributors. Support the project via [Open Collective](https://opencollective.com/romm) if you'd like! + +## Where's can I find you? + +- **Discord**: [discord.gg/romm](https://discord.gg/romm) +- **GitHub**: [rommapp/romm](https://github.com/rommapp/romm) +- **Website**: [romm.app](https://romm.app/) +- **Demo**: [demo.romm.app](https://demo.romm.app/) + +## See also + +- [Glossary](../reference/glossary.md) if the vocabulary is new +- [Troubleshooting](../troubleshooting/index.md) if something's broken diff --git a/docs/about/license.md b/docs/about/license.md new file mode 100644 index 00000000..6bdaa834 --- /dev/null +++ b/docs/about/license.md @@ -0,0 +1,65 @@ +--- +title: License +description: How RomM is licensed, and what that means for you. +--- + +# License + +## Core app: AGPLv3 + +The main [RomM application](https://github.com/rommapp/romm) is licensed under the [GNU Affero General Public License v3.0](https://choosealicense.com/licenses/AGPLv3/). In short, AGPLv3 says: + +- **You can** use RomM privately, commercially, or at any scale. +- **You can** modify the source code however you want. +- **You must** make your modifications available under AGPLv3 if you distribute them _or_ run them as a network-accessible service for others. +- **You must** preserve copyright and license notices. + +If you host a modified RomM and other people use it over the network, you owe them the source. This prevents the "hosted SaaS fork without upstream contributions" failure mode that's common with plain GPL. For most self-hosters this has zero practical effect, since you're running an unmodified version for yourself and the license doesn't constrain you. For companies thinking about shipping a modified RomM commercially, understand the AGPL obligations first. + +Full license text: [rommapp/romm/blob/master/LICENSE](https://github.com/rommapp/romm/blob/master/LICENSE). + +## Companion apps: varies + +The RomM umbrella hosts several projects under different licenses: + +| Project | License | +| --------------------------------------------------------------------- | ------- | +| [rommapp/romm](https://github.com/rommapp/romm) | AGPLv3 | +| [rommapp/argosy-launcher](https://github.com/rommapp/argosy-launcher) | AGPLv3 | +| [rommapp/grout](https://github.com/rommapp/grout) | MIT | +| [rommapp/playnite-plugin](https://github.com/rommapp/playnite-plugin) | AGPLv3 | +| [rommapp/docs](https://github.com/rommapp/docs) (what you're reading) | CC0 | + +Companion repos use more permissive licenses AGPLv3 or MIT because they're smaller, more-replaceable, and don't host the library. The AGPL network-service clause doesn't offer the same protection benefits there. + +## Third-party components + +Several third-party components ship with their own licenses: [EmulatorJS](https://emulatorjs.org/), [Ruffle](https://ruffle.rs/), Vue, FastAPI, and a long list of smaller dependencies. Their licenses apply to their respective code, and none of them override AGPLv3 on the RomM code itself. View the full list via `uv tree` in the backend and `npm ls` in the frontend. Redistribution respects each upstream's terms. + +## FAQ + +### Can I use RomM at work/for my company's gaming night? + +Yes. AGPL doesn't restrict private or commercial use. + +### Can I fork RomM and relicense my fork? + +No. AGPL is a strong copyleft, so forks remain AGPL, and while you can add your own changes under AGPL you can't relicense the original code. + +### Can I charge money for RomM-as-a-service? + +Yes, but you owe your users the source, so you can't run a modified closed-source hosted RomM for paying customers. + +### Can I sell ROMs through RomM? + +No, as the sale of ROMs is not permitted in most jurisdictions. + +### Is there a commercial/dual-license option? + +Please reach out to us if you're interested in commercial licensing. We may be open to dual-licensing arrangements for certain use cases! + +## See also + +- [Credits](credits.md) +- [AGPLv3 overview](https://choosealicense.com/licenses/agpl-3.0/) +- Full license text: [LICENSE](https://github.com/rommapp/romm/blob/master/LICENSE) diff --git a/docs/administration/authentication.md b/docs/administration/authentication.md new file mode 100644 index 00000000..7cef2749 --- /dev/null +++ b/docs/administration/authentication.md @@ -0,0 +1,110 @@ +--- +title: Authentication +description: Configure how users sign in. +--- + +# Authentication + +This page is the **operator-side** authentication reference, the knobs you turn on the server to control how people sign in. The **client-side** reference ("how do I actually authenticate an API call?") is in [API Authentication](../developers/api-authentication.md). + +Authentication flows RomM supports: + +- **Username + password** (default): local account, bcrypt-hashed, stored in the DB +- **OIDC**: single sign-on via an external IdP +- **Client API Tokens**: long-lived per-user tokens for companion apps and scripts +- **Device pairing**: short codes for bootstrapping a token onto a handheld +- **Kiosk mode**: unauthenticated read-only access, handy for public demos + +## Session config + +Sessions are cookie-based and stored in Redis. Relevant env vars: + +| Variable | Default | What it controls | +| ------------------------------------ | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ROMM_AUTH_SECRET_KEY` | _(required)_ | HS256 signing key for session tokens and JWTs. Generate with `openssl rand -hex 32`. **Never rotate this casually**, because it invalidates every active session and every outstanding invite link. | +| `ROMM_AUTH_SECRET_KEY_FILE` | | Read the secret from a file (e.g. via Docker secrets) instead of an env var. | +| `SESSION_MAX_AGE_SECONDS` | 86400 (24 h) | How long a session cookie lives before the user has to sign in again. | +| `OAUTH_ACCESS_TOKEN_EXPIRE_SECONDS` | 900 (15 min) | Short-lived OAuth2 access token TTL. | +| `OAUTH_REFRESH_TOKEN_EXPIRE_SECONDS` | 2592000 (30 d) | Refresh token TTL for OAuth2. | +| `DISABLE_CSRF_PROTECTION` | `false` | Disable CSRF middleware. Only do this behind a trusted reverse proxy that strips unwanted cross-origin traffic. | + +## Local (username + password) + +Local accounts are created via [invitations, registration, admin setup, or the Setup Wizard](invitations-and-registration.md), and passwords are bcrypt-hashed. + +**Disable local password login entirely** (force OIDC-only): + +```yaml +environment: + - DISABLE_USERPASS_LOGIN=true +``` + + +!!! warning "Keep a way in" + Before setting `DISABLE_USERPASS_LOGIN=true`, confirm that at least one Admin account can sign in via OIDC. If OIDC breaks and you've already disabled local login, your only way in is editing the container env. + +### Admin-triggered password reset + +Until email-based self-serve reset lands, admins set passwords manually for any user. The next login on that account will use the new password but existing sessions remain valid until they expire. + +## OIDC + +See [OIDC Setup](oidc/index.md) for the full walkthrough. One-liner config sketch: + +```yaml +environment: + - OIDC_ENABLED=true + - OIDC_PROVIDER=keycloak + - OIDC_CLIENT_ID=... + - OIDC_CLIENT_SECRET=... + - OIDC_SERVER_APPLICATION_URL=https://auth.example.com + - OIDC_REDIRECT_URI=https://demo.romm.app/api/oauth/openid +``` + +When OIDC is configured, an OIDC sign-in option is offered alongside username/password. Set `OIDC_AUTOLOGIN=true` to redirect straight to the IdP without the user having to choose. + +## Client API Tokens + +For anything long-lived (a companion app, a cron job, a script) use **Client API Tokens** instead of storing a password. Each token: + +- Belongs to a specific user +- Carries a **subset** of that user's scopes (you choose which at creation time) +- Has an optional expiry (no expiry = never expires until manually revoked) +- Can be "paired" to a device via a short code + +Each user gets up to 25 active tokens. The API side ("how do I send this thing in a request?") lives in [API Authentication](../developers/api-authentication.md). + +## Kiosk mode + +Grants unauthenticated, read-only access to nearly every GET endpoint. Anyone reaching the instance can browse but only a logged-in admin can write, scan, upload, or manage users. + +```yaml +environment: + - KIOSK_MODE=true +``` + +Appropriate for: + +- Shared-terminal demos +- Public-facing "display" instances +- `demo.romm.app` + +Authenticated users (when you do sign in) will still see the full UI with all actions available to their role. + +## Download-endpoint auth bypass + +```yaml +environment: + - DISABLE_DOWNLOAD_ENDPOINT_AUTH=true +``` + +Skips auth on `GET /api/roms/{id}/content/…` and the firmware download endpoint. Exists so third-party apps that can't carry a bearer header (like dumb emulators loading a ROM by URL) can still pull files. **Only enable this when the public internet can't reach RomM directly**, i.e. there's auth or an IP allowlist at the reverse-proxy layer. Otherwise you've just made your library world-downloadable. + +## Revoking access + +To fully cut a user off, an admin needs to: + +1. Revoke all of the user's Client API Tokens. +2. Disable or delete the user account. + +Disabling preserves the account row (useful for audit/future re-enable). Deletion removes the user record and personal data, with the caveats covered in [Users & Roles → Editing and deleting users](users-and-roles.md#editing-and-deleting-users). diff --git a/docs/administration/firmware-management.md b/docs/administration/firmware-management.md new file mode 100644 index 00000000..f429545f --- /dev/null +++ b/docs/administration/firmware-management.md @@ -0,0 +1,48 @@ +--- +title: Firmware Management +description: Upload, associate, and serve BIOS/firmware files for emulation. +--- + +# Firmware Management + +Many emulated platforms require BIOS or firmware to boot, or to reach a certain level of stability. RomM tracks firmware files **per platform**, stores them on disk, and serves them to in-browser players (EmulatorJS/Ruffle) and companion apps that request them. + +Firmware is **not** ROM. Keep the two separate: + +- `/romm/library/roms/`: game ROMs, homebrew, demos, etc. +- `/romm/library/bios/`: system firmware + + +!!! important "Legality varies by jurisdiction" +RomM does not ship games or firmware, and the team cannot help you obtain BIOS files. Always check your local laws and the emulator's documentation for guidance on what you can legally use. + +## Ingesting firmware + +1. Put the file in the right `bios/` folder (see [Folder Structure](../getting-started/folder-structure.md)) +2. Run a scan → Firmware is picked up alongside ROMs +3. Navigate to the platform's gallery and click the `CPU` icon in the top left +4. Firmware files will display at the bottom of the page + +## Platform-specific firmware + +Every emulator has its own requirements: which files it needs, specific hashes, naming conventions. The [Supported Platforms](../platforms/supported-platforms.md) table flags which platforms need firmware for EmulatorJS playback. + +Common examples: + +| Platform | Typical firmware file | Where to put it | +| ----------------- | ------------------------------------------------- | --------------- | +| PlayStation (PSX) | `scph1001.bin`, `scph5501.bin`, `scph5502.bin` | `bios/ps/` | +| Game Boy Advance | `gba_bios.bin` | `bios/gba/` | +| Sega CD | `bios_CD_U.bin`, `bios_CD_E.bin`, `bios_CD_J.bin` | `bios/segacd/` | +| Saturn | `saturn_bios.bin`, `mpr-17933.bin` | `bios/saturn/` | +| Nintendo DS | `firmware.bin`, `bios9.bin`, `bios7.bin` | `bios/nds/` | + +File naming matters as emulators look for specific filenames. Double-check against the emulator core's documentation if something won't boot. + +## Integration with companion apps + +Handheld syncers (Grout, Argosy, DeckRommSync) can pull firmware alongside ROMs. They use the same Client API Token auth as for ROMs, so scope the token to include `firmware.read`. + +## Backups + +Firmware files are user-owned data, so back them up! If you're backing up the `/romm/library` volume, firmware is already covered (see [Backup & Restore](../install/backup-and-restore.md)). diff --git a/docs/administration/index.md b/docs/administration/index.md new file mode 100644 index 00000000..f5367a73 --- /dev/null +++ b/docs/administration/index.md @@ -0,0 +1,40 @@ +--- +title: Administration +description: Running RomM for yourself and others. +--- + +# Administration + +Administration is everything you do **as the operator** of a RomM instance: managing accounts, controlling access, configuring metadata sources, scheduling scans, watching the library for changes, monitoring the server, and keeping data safe. + +The end-user equivalent (how to actually play the games, build collections, upload saves) lives in [Using RomM](../using/index.md). + +## Where things live + +### Users & access + +- **[Users & Roles](users-and-roles.md)**: roles, the scope model, how permissions add up +- **[Invitations & Registration](invitations-and-registration.md)**: invite links, public signup, first-user setup +- **[Authentication](authentication.md)**: session config, password reset, Client API Tokens for devices +- **[OIDC Setup](oidc/index.md)**: Authelia, Authentik, Keycloak, PocketID, Zitadel, SSO + role mapping + +### Content & library + +- **[Metadata Providers](metadata-providers.md)**: all providers, credentials, priority ordering +- **[Scanning & Watcher](scanning-and-watcher.md)**: how scans work, scan modes, filesystem watcher +- **[Firmware Management](firmware-management.md)**: BIOS/firmware uploads for emulation + +### Operations + +- **[Scheduled Tasks](scheduled-tasks.md)**: what runs in the background and how to tune it +- **[Server Stats](server-stats.md)**: the stats page and what its numbers mean +- **[Observability](observability.md)**: logs, Sentry, OpenTelemetry, `/heartbeat` + +### Configuration + +- **[Environment Variables](../reference/environment-variables.md)**: every env var, grouped by area +- **[Configuration File](../reference/configuration-file.md)**: the `config.yml` schema + +### Keeping data safe + +- **[Backup & Restore](../install/backup-and-restore.md)**: routine backups, restore drill, host migration diff --git a/docs/administration/invitations-and-registration.md b/docs/administration/invitations-and-registration.md new file mode 100644 index 00000000..be688836 --- /dev/null +++ b/docs/administration/invitations-and-registration.md @@ -0,0 +1,56 @@ +--- +title: Invitations & Registration +description: Inviting users, the first-user flow, and role assignment. +--- + +# Invitations & Registration + +There are three ways a new account ends up on a RomM instance: + +1. **First-admin setup**: the person who completes the Setup Wizard. +2. **Invite link**: an admin generates a one-shot link carrying a pre-assigned role. +3. **OIDC auto-provisioning**: first login through your IdP creates a matching account (covered in [OIDC Setup](oidc/index.md)). + +## First-admin setup + +When a fresh RomM container starts against an empty database, hitting any page redirects to the **Setup Wizard**. The wizard collects a username, email, and password. The resulting account is **always an Admin**, regardless of any env var. + +To skip the wizard (e.g. when provisioning via automation and you'll create users through the API), set: + +```yaml +environment: + - DISABLE_SETUP_WIZARD=true +``` + +You'll then need to create the first admin via the API or by injecting a database row at deploy time, because the UI won't offer a setup flow. + +## Invite links + +The recommended way to add users, because it avoids you ever touching their password. + +1. **Administration → Users → Invite.** Pick a role (Viewer, Editor, Admin). +2. RomM generates a single-use URL → copy it and send it to the invitee. +3. When they open it, they pick their own username and password. +4. RomM creates the account with the role you chose and logs them straight in. + +Invite tokens are **single-use** and **time-limited**. Defaults: + +| Setting | Default | Env var | +| ------- | ---------- | ----------------------------- | +| Expiry | 600 (10 m) | `INVITE_TOKEN_EXPIRY_SECONDS` | + +Expired links return a clear error on the `/register` page. Generate a new one from the Users panel. + +## Role assignment at sign-up + +| Sign-up method | Role assigned | +| ----------------------- | ------------------------------------------------------------ | +| First-user Setup Wizard | Admin (always) | +| Invite link | Whatever role the admin picked when generating the link | +| OIDC first login | Default Viewer, or mapped from claims via `OIDC_CLAIM_ROLES` | + +Changing a user's role afterwards is a normal admin action (see [Users & Roles](users-and-roles.md)). + +## Password reset + +Admins can reset passwords manually in **Administration → Users → Edit → New password**. A temporary password will be printed to the container's logs. diff --git a/docs/Getting-Started/Metadata-Providers.md b/docs/administration/metadata-providers.md similarity index 79% rename from docs/Getting-Started/Metadata-Providers.md rename to docs/administration/metadata-providers.md index 1246b101..3d7f0626 100644 --- a/docs/Getting-Started/Metadata-Providers.md +++ b/docs/administration/metadata-providers.md @@ -1,7 +1,7 @@ -RomM supports multiple metadata providers to enrich your game library with titles, descriptions, cover art, and achievements. You don't need all providers, so this guide covers [popular combos](#popular-combos) and [setup instructions](#setup-instructions). +Multiple metadata providers are supported to enrich your game library with titles, descriptions, cover art, and achievements. You don't need all providers, so this guide covers [popular combos](#popular-combos) and [setup instructions](#setup-instructions). ## Popular combos @@ -57,7 +57,7 @@ To access the IGDB API you'll need a Twitch account and a valid phone number for - Client Type: `Confidential` -!!! important +!!! important The name you pick has to be unique! Picking an existing name will fail silently, with no error messages. We recommend using `romm-`, like `romm-3fca6fd7f94dea4a05d029f654c0c44b` Note the client ID and secret that appear on screen, and use them to set `IGDB_CLIENT_ID` and `IGDB_CLIENT_SECRET` in your environment variables. @@ -85,7 +85,7 @@ To access the MobyGames API, [create a MobyGames account](https://www.mobygames. ### LaunchBox -The [LaunchBox](https://gamesdb.launchbox-app.com/) Games Database is a community-driven database that provides metadata, cover art, and screenshots. Like the Launchbox desktop application, RomM downloads the entire database locally and matches games based on their exact filenames. +The [LaunchBox](https://gamesdb.launchbox-app.com/) Games Database is a community-driven database that provides metadata, cover art, and screenshots. Like the Launchbox desktop application, the entire database is downloaded locally and matches games based on their exact filenames. To enable LaunchBox, set `LAUNCHBOX_API_ENABLED=true` and `ENABLE_SCHEDULED_UPDATE_LAUNCHBOX_METADATA=true` in your environment variables. You can customize scheduled updates of the database by setting the frequency on the cron job with `SCHEDULED_UPDATE_LAUNCHBOX_METADATA_CRON` (defaults to 5:00 AM every day). @@ -111,13 +111,13 @@ To access the SteamGridDB API, you need to login to their [website](https://www. ### RetroAchievements -RomM is able to display your achievements from [RetroAchievements](https://retroachievements.org/). To sync it with your RomM instance, you need to generate an API key from your RetroAchievements account in your [settings](https://retroachievements.org/settings). +Achievements are displayed from [RetroAchievements](https://retroachievements.org/). To sync, you need to generate an API key from your RetroAchievements account in your [settings](https://retroachievements.org/settings). Copy the key shown and use it to set `RETROACHIEVEMENTS_API_KEY` and perform a `UNMATCHED` scan targeting the platform you want to match with RetroAchievements. After that, each user needs to set their own username in their profile and sync it with RetroAchievements. A new `Achievements` tab will appear in the `Personal` tab in the game details. -To avoid unnecessary API calls, a cached file with the RA database is stored in RomM. Refresh time for that cache file can be changed with the environment variable `REFRESH_RETROACHIEVEMENTS_CACHE_DAYS`. +To avoid unnecessary API calls, a cached file with the RA database is stored locally. Refresh time for that cache file can be changed with the environment variable `REFRESH_RETROACHIEVEMENTS_CACHE_DAYS`. ??? Screenshots @@ -126,17 +126,17 @@ To avoid unnecessary API calls, a cached file with the RA database is stored in ### Flashpoint -The [Flashpoint Project Database](https://flashpointproject.github.io/flashpoint-database/) is a project that enables metadata for 180,000+ flash and browser-based games. Enable this metadata source with the `FLASHPOINT_API_ENABLED=true` environment variable. If you are adding this provider to an existing RomM setup, perform a `UNMATCHED` scan with Flashpoint selected to update an existing platform. +The [Flashpoint Project Database](https://flashpointproject.github.io/flashpoint-database/) is a project that enables metadata for 180,000+ flash and browser-based games. Enable this metadata source with the `FLASHPOINT_API_ENABLED=true` environment variable. If you are adding this provider to an existing setup, perform a `UNMATCHED` scan with Flashpoint selected to update an existing platform. -### How Long To Beat +### HowLongToBeat -The [How Long To Beat](https://howlongtobeat.com/) project provides game completion times for more than 84,000 games. Enable this metadata source with the `HLTB_API_ENABLED=true` environment variable. If you are adding this provider to an existing RomM setup, perform a `UNMATCHED` scan with How Long To Beat selected to update an existing platform. +The [HowLongToBeat](https://howlongtobeat.com/) project provides game completion times for more than 84,000 games. Enable this metadata source with the `HLTB_API_ENABLED=true` environment variable. If you are adding this provider to an existing setup, perform a `UNMATCHED` scan with HowLongToBeat selected to update an existing platform. Game completion times will be added to a new tab on the details page for supported matched games. ### ES-DE gamelist.xml -EmulationStation, and it's modern successor ES-DE, use a custom XML format to store game metadata. RomM can parse this format and import the assets as cover art and screenshots. You'll need to store the gamelist.xml file and any related assets under the platform folder: +EmulationStation, and its modern successor ES-DE, use a custom XML format to store game metadata. RomM parses this format and imports the assets as cover art and screenshots. You'll need to store the gamelist.xml file and any related assets under the platform folder: ```yaml @@ -159,7 +159,7 @@ library/ - + ./game.gba @@ -221,7 +221,7 @@ Here are the text properties that will be read from `gamelist.xml`. #### ES-DE media -RomM has two ways of mapping media files: first it looks at `gamelist.xml` for properties, and it falls back to looking at nested folders for images that have the same name as the ROM. +There are two ways media files are mapped: first it looks at `gamelist.xml` for properties, and it falls back to looking at nested folders for images that have the same name as the ROM. | Property Name | Folder Name | Description | | ------------- | ------------- | -------------------------------------- | @@ -241,11 +241,11 @@ RomM has two ways of mapping media files: first it looks at `gamelist.xml` for p #### ES-DE settings -Here are the settings you need to change so RomM can read your artwork and gamelist.xml files from the same folder that holds your ROMs. +Here are the settings you need to change to read your artwork and gamelist.xml files from the same folder that holds your ROMs. 1. Open the ES-DE settings file: - - Linux / macOS: `~/ES-DE/settings/es_settings.xml` + - Linux/macOS: `~/ES-DE/settings/es_settings.xml` - Windows: `C:\Program Files\ES-DE\settings\es_settings.xml` 2. Make these two edits (add the lines if they don’t exist): @@ -255,12 +255,12 @@ Here are the settings you need to change so RomM can read your artwork and gamel ``` - - `MediaDirectory="/path/to/ROMs/folder"` download artwork into the same directory that contains the ROMs (should match `ROMDirectory`) - - `LegacyGamelistFileLocation="true"` forces gamelist.xml to be written next to the ROMs instead of inside the ES-DE config folder +- `MediaDirectory="/path/to/ROMs/folder"` download artwork into the same directory that contains the ROMs (should match `ROMDirectory`) +- `LegacyGamelistFileLocation="true"` forces gamelist.xml to be written next to the ROMs instead of inside the ES-DE config folder 3. If you already have scraped artwork, copy/move the systems from `~/ES-DE/downloaded_media/` and `~/ES-DE/gamelists/` into your ROMs folder -After a restart, ES-DE will place new artwork and the updated gamelist.xml directly in `roms//`, which is the layout RomM expects. +After a restart, ES-DE will place new artwork and the updated gamelist.xml directly in `roms//`, which is the expected layout. ## Metadata Tags in Filenames @@ -273,4 +273,38 @@ Scans will now parse custom metadata tags in the filename that match specific pa (launchbox-xxxx) for [Launchbox](https://gamesdb.launchbox-app.com/) (hltb-xxxx) for [HowLongToBeat](https://howlongtobeat.com/) -Filenames will not be renamed by RomM to add tags, as they are a non-standard formatting system and could create conflicts with other software. +Filenames will not be renamed to add tags, as they are a non-standard formatting system and could create conflicts with other software. + +## Priority and conflict resolution + +When multiple providers return different values for the same field, the winner is determined by `scan.priority.metadata` and `scan.priority.artwork` in `config.yml`. Defaults: + +```yaml +scan: + priority: + metadata: + - igdb + - moby + - ss + - ra + - launchbox + - gamelist + - hasheous + - flashpoint + - hltb + artwork: + - igdb + - moby + - ss + - ra + - launchbox + - libretro + - gamelist + - hasheous + - flashpoint + - hltb +``` + +Reorder these lists to taste. For example, put `ss` first if you prefer ScreenScraper boxart, or move `hltb` up if you care about completion times more than descriptions. + +See the full [Configuration File reference](../reference/configuration-file.md) for everything `scan.priority` can do diff --git a/docs/administration/observability.md b/docs/administration/observability.md new file mode 100644 index 00000000..2e371b63 --- /dev/null +++ b/docs/administration/observability.md @@ -0,0 +1,131 @@ +--- +title: Observability +description: Logs, error tracking and telemetry +--- + +# Observability + +It's often handy to know what's happening under the hood, especially when debugging a scan or task. the observability stack includes: + +- **Container logs**: always available, the first stop +- **`/api/heartbeat`** endpoint: health + config summary for uptime monitors +- **Sentry**: opt-in error tracking with stack traces +- **OpenTelemetry**: opt-in distributed tracing + metrics + +## Logs + +```yaml +environment: + - LOG_LEVEL=INFO # DEBUG | INFO | WARNING | ERROR + - FORCE_COLOR=0 # 1 to force colour even when not a TTY + - NO_COLOR=1 # 1 to disable colour entirely +``` + +`INFO` is the default and the sane choice for production. Drop to `DEBUG` only while debugging a specific issue, because `DEBUG` is chatty. + +### Reading logs + +Log lines are prefixed with module + timestamp: + +```text +INFO: [RomM][scan_handler][2026-04-18 11:37:40] Identified as PlayStation 🎮 +ERROR: [RomM][ra_handler][2026-04-18 11:48:55] Invalid RetroAchievements API key +WARNING: [RomM][config_manager][2026-04-18 12:01:12] config.yml not found, using defaults +``` + +Some useful grep commands: + +```sh +docker logs romm 2>&1 | grep ERROR +docker logs romm 2>&1 | grep -iE 'auth|oidc|oauth' +docker logs romm 2>&1 | grep -iE 'scan_handler.*Identified' +``` + +## `/api/heartbeat` + +A single-request endpoint to fetch health and config information. Works when not logged in, though some fields only appear for authenticated callers. + +```http +GET /api/heartbeat +``` + +Wire this to your uptime monitor. A failure here means that the process is down or the DB/Valkey is unreachable. + +```bash +# Basic uptime check +curl -fsS https://demo.romm.app/api/heartbeat > /dev/null \ + && echo "up" \ + || echo "down" +``` + +Per-metadata provider health: + +```http +GET /api/heartbeat/metadata/[igdb/ss/ra/...] +``` + +Useful when a scan is matching poorly and you want to know whether a provider is down on their side or misconfigured on yours. + +## Sentry + +Opt-in error tracking: + +```yaml +environment: + - SENTRY_DSN=https://abc123@sentry.example.com/42 +``` + +What's sent: + +- Stack traces for unhandled exceptions +- Per-request timing on slow endpoints +- Redacted URL parameters (secrets stripped) + +What's not sent: ROM filenames, user credentials, metadata provider API keys. Sensitive parameters are filtered before reporting. + +## OpenTelemetry + +If you're already using OpenTelemetry with your other apps and want unified observability: + +```yaml +environment: + - OTEL_ENABLED=true + - OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317 + - OTEL_SERVICE_NAME=romm + - OTEL_RESOURCE_ATTRIBUTES=deployment.environment=prod +``` + +Standard [OTEL env vars](https://opentelemetry.io/docs/specs/otel/protocol/exporter/) apply. The app emits: + +- **Traces**: HTTP request spans, DB query spans, RQ job spans +- **Metrics**: request counts, durations, queue depth, scan progress +- **Logs**: structured log correlation with trace IDs + +Exporters: + +- OTLP gRPC (default, port `4317`) +- OTLP HTTP (port `4318`): set `OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf`. + +Send to an OpenTelemetry Collector, then fan out to Tempo/Jaeger/Honeycomb/Datadog/Grafana/whatever you run. + +## Task status + +Live task state is also exposed programmatically: + +```http +GET /api/tasks/status +Authorization: Bearer +``` + +Returns an array of every scheduled/manual/watcher task with current status (`idle`, `queued`, `running`, `failed`) and last run time. Scrape this into your monitoring to alert on "Folder Scan hasn't run in 48 hours", which usually means RQ workers are dead. + +## Anti-patterns + +- **Don't parse unstructured log lines** for metrics (use OTEL instead) +- **Don't log at DEBUG in production** as the volume is real and scans will drown in it +- **Don't scrape HTML pages for health checks**; HTML changes between versions while the API endpoint is stable + +## Minimum recommended stack + +- Default `INFO` logs into the container logs → forwarded to Loki/Promtail/whatever you already run +- `/api/heartbeat` hit every 60 seconds from Uptime Kuma/Gatus diff --git a/docs/administration/oidc/authelia.md b/docs/administration/oidc/authelia.md new file mode 100644 index 00000000..e4d17899 --- /dev/null +++ b/docs/administration/oidc/authelia.md @@ -0,0 +1,95 @@ +--- +title: OIDC with Authelia +description: Wire up SSO to Authelia +--- + +# OIDC with Authelia + +[Authelia](https://www.authelia.com/) is a lightweight open-source authentication and authorisation server with two-factor auth and SSO. Before starting, read the [OIDC Setup overview](index.md), as it covers the RomM-side settings common to every provider. + +## 1. Prerequisites + +Authelia installed and running, with its OIDC provider enabled: + +- [Authelia getting started](https://www.authelia.com/integration/prologue/get-started/) +- [OIDC provider configuration](https://www.authelia.com/configuration/identity-providers/openid-connect/provider/) + +## 2. Add a claims policy + +In Authelia's `configuration.yml` under `identity_providers.oidc.claims_policies`, add a policy that emits the claims RomM needs (name it whatever you like): + +```yaml +identity_providers: + oidc: + claims_policies: + with_email: + id_token: + - email + - email_verified + - groups + - alt_emails + - preferred_username + - name +``` + +Background on why this is needed: [Authelia claims parameter restoration](https://www.authelia.com/integration/openid-connect/openid-connect-1.0-claims/#restore-functionality-prior-to-claims-parameter). + +## 3. Register the RomM client + +Under `identity_providers.oidc.clients`, add: + +```yaml +identity_providers: + oidc: + clients: + - client_id: "" # see note below + client_name: "RomM" + client_secret: "$pbkdf2-sha512$" # see note below + public: false + authorization_policy: "two_factor" # or one_factor + grant_types: + - authorization_code + redirect_uris: + - "https://demo.romm.app/api/oauth/openid" + claims_policy: "with_email" # must match the policy name above + scopes: + - openid + - email + - profile + - groups + userinfo_signed_response_alg: "none" + token_endpoint_auth_method: "client_secret_basic" +``` + +To generate IDs and secrets, see [Authelia's FAQ](https://www.authelia.com/integration/openid-connect/frequently-asked-questions/#how-do-i-generate-a-client-identifier-or-client-secret). The full client schema is available in the [Authelia clients reference](https://www.authelia.com/configuration/identity-providers/openid-connect/clients/). + +## 4. Configure RomM + +In the `romm` service environment: + +```yaml +environment: + - OIDC_ENABLED=true + - OIDC_PROVIDER=authelia + - OIDC_CLIENT_ID= + - OIDC_CLIENT_SECRET= + - OIDC_REDIRECT_URI=https://demo.romm.app/api/oauth/openid + - OIDC_SERVER_APPLICATION_URL=https://auth.example.com + - ROMM_BASE_URL=https://demo.romm.app +``` + +`OIDC_REDIRECT_URI` must match what you put in `redirect_uris` exactly (scheme, host, path, no trailing slash). For role mapping from Authelia groups, see [OIDC Setup → Role mapping](index.md#role-mapping). + +## 5. Set your email + +In RomM → **Profile** → set your email to exactly the same address Authelia has for you. RomM matches OIDC users to existing accounts by email. + +![Set email](../../resources/authelia/1-user-profile.png) + +## 6. Test + +Restart, navigate to `/login` and click the **Login with OIDC** button. You're redirected to Authelia → authenticate → bounced back and signed in! + +![Login with OIDC](../../resources/authelia/2-romm-login.png) + +If it doesn't work, head to [Authentication Troubleshooting](../../troubleshooting/authentication.md). diff --git a/docs/administration/oidc/authentik.md b/docs/administration/oidc/authentik.md new file mode 100644 index 00000000..7a3abc68 --- /dev/null +++ b/docs/administration/oidc/authentik.md @@ -0,0 +1,107 @@ +--- +title: OIDC with Authentik +description: Wire up SSO to Authentik +--- + +# OIDC with Authentik + +[Authentik](https://goauthentik.io/) is a full-featured open-source IdP with MFA, flows, and a sizeable audit/admin surface. Before starting, read the [OIDC Setup overview](index.md), as it covers the RomM-side settings common to every provider. + +## 1. Prerequisites + +Authentik installed and running via their [install guide](https://docs.goauthentik.io/docs/install-config/install/docker-compose). + +Log in as admin and open **Admin Interface**. + +![Authentik user dashboard](../../resources/authentik/1-user-dashboard.png) + +## 2. Create a property mapping (Authentik 2025.10+) + + +!!! important "Authentik 2025.10 breaking change" + In version 2025.10, Authentik changed the default of `email_verified` from `true` to `false`. A verified email is required, so without this property mapping, authentication silently fails. + +In **Customization → Property Mappings → Create → Scope Mapping**: + +- **Name**: `RomM Email Verification` +- **Scope name**: `email` +- **Expression**: + +```py +return { + "email": user.email, + "email_verified": True, +} +``` + +![Property Mapping](../../resources/authentik/propperty-mapping.png) + +Click **Create**. Upstream reference: [Authentik scope mappings](https://version-2025-10.goauthentik.io/add-secure-apps/providers/property-mappings/#scope-mappings-with-oauth2). + +## 3. Create a provider + +**Admin → Providers → Create**. + +![Create a new provider](../../resources/authentik/2-create-provider.png) + +Choose **OAuth2/OpenID Provider**. + +![Select OAuth2 provider](../../resources/authentik/3-new-provider.png) + +Configure: + +- **Name**: `RomM OIDC Provider` +- **Authorization flow**: implicit consent +- **Redirect URIs**: `https://demo.romm.app/api/oauth/openid` +- **Scopes**: Under "Advanced protocol settings", move the property mapping you created above from "Available Scopes" to "Selected Scopes". You'll also need to make sure any existing mappings of `email` or `email_verified` are disabled. Authentik has an `email` mapping by default, so make sure to check for this and remove it if it's present. + +Copy the generated **Client ID** and **Client Secret**. You'll use them as `OIDC_CLIENT_ID`/`OIDC_CLIENT_SECRET` on the app side. + +![Provider settings](../../resources/authentik/4-provider-secrets.png) + +Click **Create**. + +## 4. Register the application + +**Admin → Applications → Create**. + +![Applications](../../resources/authentik/5-applications.png) + +- **Name**: `RomM` +- **Slug**: `romm` +- **Provider**: the `RomM OIDC Provider` you just made + +![New application](../../resources/authentik/6-new-application.png) + +Click **Create**. + +## 5. Configure + +```yaml +environment: + - OIDC_ENABLED=true + - OIDC_PROVIDER=authentik + - OIDC_CLIENT_ID= + - OIDC_CLIENT_SECRET= + - OIDC_REDIRECT_URI=https://demo.romm.app/api/oauth/openid + - OIDC_SERVER_APPLICATION_URL=https://auth.example.com/application/o/romm + - ROMM_BASE_URL=https://demo.romm.app +``` + +Note that `OIDC_SERVER_APPLICATION_URL` points at the per-application URL (`/application/o/`), not the Authentik root. + +For role mapping from Authentik groups, see [OIDC Setup → Role mapping](index.md#role-mapping). + +## 6. Set your email + +In **Profile** → set your email to exactly the same address Authentik has for you. + +![Set email](../../resources/authentik/7-user-profile.png) + +## 7. Test + +Restart, navigate to `/login` and click the **Login with OIDC** button. You're redirected to Authentik → authenticate → bounced back and signed in! + +![Login with OIDC](../../resources/authentik/8-romm-login.png) + +If it doesn't work, head to [Authentication Troubleshooting](../../troubleshooting/authentication.md). diff --git a/docs/administration/oidc/index.md b/docs/administration/oidc/index.md new file mode 100644 index 00000000..e52095c0 --- /dev/null +++ b/docs/administration/oidc/index.md @@ -0,0 +1,114 @@ +--- +title: OIDC Setup +description: Wire up to an OpenID Connect provider for SSO and centralised user management +--- + +# OIDC Setup + +OpenID Connect (OIDC) lets users sign in through an external identity provider: Authelia, Authentik, Keycloak, PocketID, Zitadel, Okta, Auth0, or anything standards-compliant. Single sign-on across your homelab, no app-specific password to manage, centralised MFA, and map OIDC groups/claims to roles. + + +!!! note "OIDC is optional" + The local user system works fine without OIDC. Enable OIDC when you already run an IdP and want auth to follow suit, or when you want to unify user management across multiple apps. + +## How it works + +1. User clicks the OIDC login button on `/login`. +2. They're redirected to your provider. +3. They authenticate (password, passkey, MFA, whatever your provider enforces). +4. Provider redirects back to `{ROMM_BASE_URL}/api/oauth/openid` with an authorisation code. +5. The code is exchanged for an ID token, the user's email and role claims are read, and either a matching local user is created on the fly or an existing one is logged in. + +## Provider guides + +Pick your provider and follow the step-by-step instructions. They all end with the same set of app-side env vars. The guides just differ on how to register the app and where to find the client ID/secret. + +- [Authelia](authelia.md) +- [Authentik](authentik.md) +- [Keycloak](keycloak.md) +- [PocketID](pocketid.md) +- [Zitadel](zitadel.md) + +Not listed? Most standards-compliant OIDC providers work: Okta, Auth0, Google Workspace, Microsoft Entra, etc. Use one of the above as a template and consult your provider's docs for the registration side. + +## Minimum config + +Whichever provider you pick, set these in the `romm` service's environment: + +```yaml +environment: + - OIDC_ENABLED=true + - OIDC_PROVIDER= + - OIDC_CLIENT_ID= + - OIDC_CLIENT_SECRET= + - OIDC_SERVER_APPLICATION_URL=https://auth.example.com + - OIDC_REDIRECT_URI=https://demo.romm.app/api/oauth/openid + - ROMM_BASE_URL=https://demo.romm.app # must match your reverse-proxy URL +``` + +`OIDC_REDIRECT_URI` must exactly match what you register at the provider (same scheme, host, path, no trailing slash). + +## Role mapping + +By default, new OIDC users are provisioned as **Viewers**. To let your IdP assign roles based on group membership, set: + +```yaml +environment: + - OIDC_CLAIM_ROLES=groups # which claim to read + - OIDC_ROLE_VIEWER=romm-viewer,guests # group names → Viewer + - OIDC_ROLE_EDITOR=romm-editor + - OIDC_ROLE_ADMIN=romm-admin,platform-admins +``` + +On every login, the claim named by `OIDC_CLAIM_ROLES` is read (often `groups`, sometimes `realm_access.roles` on Keycloak, check your provider's token output). Whichever role has a matching value wins. If nothing matches, the user stays/becomes a Viewer. + +Roles are re-evaluated on **every login**, so demoting someone on the IdP side takes effect the next time they sign in. + +## Autologin + +To bypass the login page entirely and redirect straight to the IdP: + +```yaml +environment: + - OIDC_AUTOLOGIN=true +``` + +Useful when you want this to feel like a native part of your SSO stack. Combine with `DISABLE_USERPASS_LOGIN=true` to lock out local accounts entirely. + + +!!! warning "Keep one local admin" + Don't set `DISABLE_USERPASS_LOGIN=true` without first confirming an admin account exists on the IdP side and can log in. If OIDC breaks and you've disabled local login, you're locked out until you fix the container env. + +## RP-Initiated Logout + +When set, hitting "Sign out" in RomM also signs the user out at the IdP: + +```yaml +environment: + - OIDC_RP_INITIATED_LOGOUT=true + - OIDC_END_SESSION_ENDPOINT=https://auth.example.com/application/o/end-session/ +``` + +The endpoint URL is provider-specific, check the per-provider guides or your IdP's docs. + +## Username source + +By default the local part of the email (the bit before `@`) becomes the username, but you can override it with: + +```yaml +environment: + - OIDC_USERNAME_ATTRIBUTE=preferred_username +``` + +## Important notes + +- **Email must match** between OIDC and any existing local account, otherwise OIDC creates a new account alongside the old one. +- **HTTPS is required** in production, as OIDC will refuse to redirect to a plain-HTTP `ROMM_BASE_URL`. +- Large drift between the RomM host and IdP will lead to **clock skew** and cause ID-token validation to fail. + +## Troubleshooting + +Common failures and fixes live in [Authentication Troubleshooting](../../troubleshooting/authentication.md). Two of the usual suspects: + +- `redirect_uri_mismatch`: `OIDC_REDIRECT_URI` differs from what's registered at the provider. Even a trailing slash can matter! +- User created but stuck at Viewer: check `OIDC_CLAIM_ROLES` points at a claim that actually exists in the token, and the group names match exactly (case-sensitive). diff --git a/docs/administration/oidc/keycloak.md b/docs/administration/oidc/keycloak.md new file mode 100644 index 00000000..e73d247f --- /dev/null +++ b/docs/administration/oidc/keycloak.md @@ -0,0 +1,89 @@ +--- +title: OIDC with Keycloak +description: Wire up SSO to Keycloak +--- + +# OIDC with Keycloak + +[Keycloak](https://www.keycloak.org/) is the heavyweight open-source IAM standard. Before starting, read the [OIDC Setup overview](index.md), as it covers the RomM-side settings common to every provider. + +## 1. Prerequisites + +Keycloak installed and running via their [getting started guide](https://www.keycloak.org/getting-started). + +Log into the **Admin Console** and either create a new realm for the app or reuse an existing one. + +## 2. Add a client + +In the Admin Console, select your realm → **Clients** → **Create client**. + +1. **Client type**: `OpenID Connect`. +2. **Client ID**: `romm` (or something unique). +3. Click **Next**. +4. On the capability page: + - Enable **Client authentication** + - Leave only **Standard flow** enabled + - Click **Next** +5. Set URLs: + - **Root URL**: `https://demo.romm.app` + - **Valid Redirect URIs**: `https://demo.romm.app/api/oauth/openid` + - **Web origins**: `https://demo.romm.app` +6. Save, then head to the **Credentials** tab and copy the **Client Secret**. + +## 3. Configure + +```yaml +environment: + - OIDC_ENABLED=true + - OIDC_PROVIDER=keycloak + - OIDC_CLIENT_ID=romm + - OIDC_CLIENT_SECRET= + - OIDC_REDIRECT_URI=https://demo.romm.app/api/oauth/openid + - OIDC_SERVER_APPLICATION_URL=https://keycloak.example.com/realms/ + - ROMM_BASE_URL=https://demo.romm.app +``` + +`OIDC_SERVER_APPLICATION_URL` must include the realm (`.../realms/`), not just the Keycloak root. + +## 4. Set email + verify in Keycloak + +In **Profile** → set your email to the same address Keycloak has for you. + +On the Keycloak side, go to **Admin Console → Users** and mark each user's email as **verified**. Users with unverified emails will be rejected on login. + +## 5. Test + +Restart, navigate to `/login` and click the **Login with OIDC** button. You're redirected to Keycloak → authenticate → bounced back and signed in! + +If a local user already exists with a matching email, they're signed into that account. Otherwise a new account is created with Viewer permissions. + +If it doesn't work, head to [Authentication Troubleshooting](../../troubleshooting/authentication.md). + +## 6. (Optional) Disable local password logins + +Force users through Keycloak: + +```yaml +environment: + - DISABLE_USERPASS_LOGIN=true +``` + + +!!! warning + Before flipping this, confirm at least one Admin account can sign in via OIDC, otherwise a broken OIDC flow locks you out. + +## 7. (Optional) Role mapping + +By default, new OIDC users come in as Viewers. To map Keycloak roles/groups to local roles: + +```yaml +environment: + - OIDC_CLAIM_ROLES=groups # or realm_access.roles, depending on your token + - OIDC_ROLE_VIEWER=romm-viewer + - OIDC_ROLE_EDITOR=romm-editor + - OIDC_ROLE_ADMIN=romm-admin +``` + +Configure Keycloak's client to include the role/group claim in the ID token (usually via a **Group Membership** or **Realm Role** client scope mapper). Values in the claim are compared against the `OIDC_ROLE_*` env vars on every login, so demoting in Keycloak takes effect on the user's next sign-in. + +See [OIDC Setup → Role mapping](index.md#role-mapping) for the generic version. diff --git a/docs/administration/oidc/pocketid.md b/docs/administration/oidc/pocketid.md new file mode 100644 index 00000000..402cd497 --- /dev/null +++ b/docs/administration/oidc/pocketid.md @@ -0,0 +1,51 @@ +--- +title: OIDC with PocketID +description: Wire up SSO to PocketID +--- + +# OIDC with PocketID + +[PocketID](https://github.com/stonith404/pocket-id) is a minimalist OIDC provider that **only** supports passkey authentication, with no passwords. Before starting, read the [OIDC Setup overview](index.md), as it covers the RomM-side settings common to every provider. + +## 1. Prerequisites + +PocketID installed, running, and your admin passkey already registered via their [PocketID setup guide](https://github.com/stonith404/pocket-id#setup). + +## 2. Add the client + +In PocketID admin: + +1. **Application Configuration**: make sure **Emails Verified** is ticked as we now require verified emails. +2. Go to **OIDC Client** → **Add OIDC Client**. +3. Fill in: + - **Name**: `RomM` + - **Callback URLs**: `https://demo.romm.app/api/oauth/openid` +4. **Save**. Stay on this page as the client secret only displays **once**. +5. Copy both the Client ID and Client Secret now. + +## 3. Configure RomM + +```yaml +environment: + - OIDC_ENABLED=true + - OIDC_PROVIDER=pocket-id + - OIDC_CLIENT_ID= + - OIDC_CLIENT_SECRET= + - OIDC_REDIRECT_URI=https://demo.romm.app/api/oauth/openid + - OIDC_SERVER_APPLICATION_URL=https://id.example.com + - ROMM_BASE_URL=https://demo.romm.app +``` + +`OIDC_SERVER_APPLICATION_URL` is the root URL of your PocketID instance. + +## 4. Set your email + +RomM → **Profile** → set your email to exactly the same address PocketID has for you. + +## 5. Test + +Restart, navigate to `/login` and click the **Login with OIDC** button. You're redirected to PocketID → authenticate → bounced back and signed in! + +![Login with OIDC](../../resources/pocketid/2-romm-login.png) + +If it doesn't work, head to [Authentication Troubleshooting](../../troubleshooting/authentication.md). diff --git a/docs/administration/oidc/zitadel.md b/docs/administration/oidc/zitadel.md new file mode 100644 index 00000000..25302118 --- /dev/null +++ b/docs/administration/oidc/zitadel.md @@ -0,0 +1,70 @@ +--- +title: OIDC with Zitadel +description: Wire up SSO to Zitadel +--- + +# OIDC with Zitadel + +[Zitadel](https://zitadel.com/) is an enterprise-grade open-source IAM platform supporting OAuth2, OIDC, SAML, and passwordless. Before starting, read the [OIDC Setup overview](index.md), as it covers the RomM-side settings common to every provider. + +## 1. Prerequisites + +Zitadel installed and running via their [self-hosted deployment docs](https://zitadel.com/docs/self-hosting/deploy/overview). Change the default organization password before you go further! + +## 2. Create a project + +Create a new project (e.g. `RomM`). This holds the client and its auth settings. On the **General** tab, **Check authorization on Authentication** is recommended. If turned off, anyone who can register in Zitadel can sign into RomM (as a Viewer). Turn this on if Zitadel registration is open. + +### 2.5 (Optional) Grant users to the project + +If you enabled **Check authorization on Authentication**: + +1. **Authorization** tab → **New**. +2. Select user(s) → **Continue**. +3. "No role has been created yet" is fine, just **Save**. +4. The user appears in the authorization list with no roles. + +## 3. Create the application + +On the project's **General** tab, under **Applications**, click **New**. Tick **I'm a pro. Skip this wizard** for the fast path. + +- **Name**: `RomM` +- **Application Type**: `Web` +- **Grant Types**: `Authorization Code` +- **Response Types**: `Code` +- **Authentication Method**: `Basic` +- **Redirect URIs**: `https://demo.romm.app/api/oauth/openid` +- **Post Logout URIs**: `https://demo.romm.app/` + +Click **Create**. The **client secret is shown once**, copy it now! + +## 4. Enable claims in the ID Token + +Without this, RomM throws "Email is missing from token" on login. Open the application's **Token Settings** tab → tick **User Info inside ID Token** → **Save**. + +## 5. Configure + +```yaml +environment: + - OIDC_ENABLED=true + - OIDC_PROVIDER=zitadel + - OIDC_CLIENT_ID= + - OIDC_CLIENT_SECRET= + - OIDC_REDIRECT_URI=https://demo.romm.app/api/oauth/openid + - OIDC_SERVER_APPLICATION_URL=https://zitadel.example.com + - ROMM_BASE_URL=https://demo.romm.app +``` + +Zitadel's OIDC discovery URL is at `/.well-known/openid-configuration`, which is handy for debugging. + +For role mapping from Zitadel, see [OIDC Setup → Role mapping](index.md#role-mapping). + +## 6. Set email + Zitadel + +In RomM → **Profile** → set your email to exactly the same address your Zitadel user has. + +## 7. Test + +Restart, navigate to `/login` and click the **Login with OIDC** button. You're redirected to Zitadel → authenticate → bounced back and signed in! + +If it doesn't work, head to [Authentication Troubleshooting](../../troubleshooting/authentication.md). diff --git a/docs/administration/scanning-and-watcher.md b/docs/administration/scanning-and-watcher.md new file mode 100644 index 00000000..a6556d43 --- /dev/null +++ b/docs/administration/scanning-and-watcher.md @@ -0,0 +1,124 @@ +--- +title: Scanning & Watcher +description: Scanning your library, scan modes, and the filesystem watcher +--- + +# Scanning & Watcher + +RomM keeps its catalogue in sync with your filesystem through three mechanisms: + +1. **Manual scans** you trigger through the web UI +2. **Scheduled scans** (default: nightly) run by the task runner +3. **The filesystem watcher** reacting to files landing in or leaving your library + +All three share the same scan engine and the same set of **scan modes**. + +## Scan modes + +Every scan picks one mode. Modes differ in what they touch, so use the most-targeted mode that accomplishes what you want. + +| Mode | What it does | When to use | +| ----------------- | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | +| **New Platforms** | Only scans platform folders not already in the DB. | After mounting a new ROM set (very fast). | +| **Quick** | Skips files that already exist in the DB, with no metadata refresh. | Default for scheduled runs and the watcher. | +| **Unmatched** | Re-runs metadata matching against ROMs currently missing external IDs. | After adding a new metadata provider, or when some titles didn't match on the first scan. | +| **Update** | Re-fetches metadata for all already-matched ROMs. | When metadata providers have meaningfully changed (e.g. IGDB restructured). | +| **Hashes** | Recalculates CRC/MD5/SHA1 hashes. | After upgrading from a version that didn't hash or when you suspect file corruption. | +| **Complete** | Full rescan, recalculating hashes and re-fetching metadata for everything. | Rarely, since it takes a long time. | + +You can further scope a scan to specific **platforms** and specific **metadata providers**, useful when only one provider has changed (e.g. just enabled Hasheous → Unmatched scan, Hasheous selected, on all platforms). + +## Manual scans + +A manual scan can be scoped to specific platforms and a chosen subset of metadata providers, and hashing can be skipped (helpful on low-power hosts). A running scan survives browser refreshes, and the log streams over a websocket so multiple users can watch the same scan in progress. + +## Scheduled scans + +Configured via env vars (full table in [Scheduled Tasks](scheduled-tasks.md)): + +| Variable | Default | Purpose | +| -------------------- | ----------- | ------------------------------------------------------------------------------------------------------------ | +| `SCAN_INTERVAL_CRON` | `0 0 * * *` | Cron expression for the scheduled library scan. Runs a **Quick** scan by default. | +| `SCAN_TIMEOUT` | `14400` | Hard cap in seconds: scans that exceed this are killed and logged. | +| `SCAN_WORKERS` | `1` | Concurrent worker processes for scanning; leave as auto unless you're tuning. | +| `SEVEN_ZIP_TIMEOUT` | `60` | Per-archive timeout in seconds for `.7z` extraction during scan; raise if scanning huge compressed ROM sets. | + +To disable scheduled scans entirely, either unset the cron or set it to something unreachable (`SCAN_INTERVAL_CRON=0 0 31 2 *`). + +## Filesystem watcher + +The watcher tails your library folder and schedules scans in response to file events (files added, moved, or deleted). It's off by default, so enable it with: + +```yaml +environment: + - ENABLE_RESCAN_ON_FILESYSTEM_CHANGE=true + - RESCAN_ON_FILESYSTEM_CHANGE_DELAY=5 # minutes before acting on an event +``` + +Behaviour: + +- Watches `/romm/library` (and everything under it) recursively +- Debounces bursts of events: the delay (default 10 seconds) lets a large `cp` or `rsync` settle before scanning. +- Batches scans intelligently: many events → a single consolidated scan, not one scan per file +- Ignores content modifications and metadata-only changes, caring only about files appearing or disappearing (not `chmod`) +- Skips OS noise (`.DS_Store`, `Thumbs.db`, `.tmp`, etc.) +- If a whole new platform folder appears, switches to a **New Platforms** scan to pick it up cleanly + +### When **not** to enable the watcher + +- **Slow/high-latency filesystems** (SMB mounts, rclone mounts, anything not local disk): the watcher reacts to every event, flaky mounts generate a lot of them, so use scheduled scans instead. +- **Libraries under active write load from other tools** (e.g. IGIR constantly tagging files): the watcher will re-scan on every change, at best noisy and at worst a scan loop. + +### Watcher vs scheduled scan + +| | Watcher | Scheduled scan | +| ---------------------------- | ----------------------- | ------------------------ | +| Latency | Seconds | Up to your cron interval | +| CPU cost | Only when files change | Constant cadence | +| Works over SMB/NFS | Flakily | Reliably | +| Catches renames | Yes | Yes | +| Survives a container restart | Yes, re-arms on startup | Yes | + +You can run both, where the watcher handles day-to-day additions, and the scheduled scan is a safety net. + +## What gets excluded + +Scans respect the `exclude:` tree in [`config.yml`](../reference/configuration-file.md): + +```yaml +exclude: + platforms: + - steam # skip entire platform folder + roms: + single_file: + extensions: [nfo, txt, bak] # single files with these exts + names: ["*.sample.*"] # Unix glob patterns + multi_file: + names: [extras] # folder names to skip + parts: + names: [thumb.png] # files inside multi-file dirs + extensions: [nfo] +``` + +Full schema in [Configuration File](../reference/configuration-file.md). + +## Region and language preference + +Also in `config.yml`: + +```yaml +scan: + priority: + region: [us, wor, ss, eu, jp] + language: [en, fr] +``` + +When a metadata provider returns multiple regional variants (Japanese cover, US cover, European cover…), we pick according to this order, and the same goes for localised titles. + +## Metadata source priority + +Who wins when two providers disagree is covered in [Metadata Providers](metadata-providers.md#priority-and-conflict-resolution), though the short version is `scan.priority.metadata` and `scan.priority.artwork` in `config.yml`. + +## Troubleshooting + +Scans that hang, miss files, or match weirdly: [Scanning Troubleshooting](../troubleshooting/scanning.md). diff --git a/docs/administration/scheduled-tasks.md b/docs/administration/scheduled-tasks.md new file mode 100644 index 00000000..d2af3f5c --- /dev/null +++ b/docs/administration/scheduled-tasks.md @@ -0,0 +1,62 @@ +--- +title: Scheduled Tasks +description: Runs tasks in the background, reschedule and trigger them on demand +--- + +# Scheduled Tasks + +RomM runs background work through **RQ** (Redis Queue). Tasks fall into four categories: + +- **Scheduled**: cron-driven, run on their own +- **Watcher**: triggered by filesystem events +- **Manual**: user-triggered from the UI or API +- **Enqueued**: side effects of user actions (a scan on the `/scan` page, a metadata refresh on a ROM edit, etc.) + +## The full table + +--8<-- "scheduled-tasks.md" + +## Configuring cadence + +Every scheduled task takes a standard 5-field cron expression: + +- `0 3 * * *`: 3 AM daily +- `0 */6 * * *`: every 6 hours, on the hour +- `*/30 * * * *`: every 30 minutes +- `0 2 * * 0`: 2 AM every Sunday + +Set the env var and restart the container; the scheduler picks up the new schedule the moment RomM comes back up. + +## Enabling a scheduled task + +Each task has an `ENABLE_*` environment variable, like `ENABLE_SCHEDULED_UPDATE_LAUNCHBOX_METADATA=true` which enables the LaunchBox sync. Check the [env var reference](../reference/environment-variables.md) for the full list. Some tasks are enabled by default, others aren't. + +## Triggering a task manually + +### From the Administration page + +**Administration → Tasks** shows every task with a "Run" button. Admins (anyone with `tasks.run` scope) can trigger: + +### From the API + +```http +POST /api/tasks/run/{task_name} +Authorization: Bearer +``` + +## Monitoring tasks + +- **Live**: Administration → Tasks page shows every task's current status (queued, running, idle, failed). +- **API**: `GET /api/tasks/status` for a JSON summary. Wire this to an uptime monitor if you want alerts. +- **Logs**: `docker logs romm` → look for `rq.worker` lines. + +A task that's been "running" for hours is usually a scan that hit `SCAN_TIMEOUT`, and the logs will say so. Tasks that fail leave a stack trace in the container logs, and the RQ `failed` queue retains the last few for inspection. + +## Tuning for small hosts + +On a Raspberry Pi or NAS with 2 GB of RAM and/or a single CPU core: + +- Raise the cron intervals (daily → weekly) for the nightlies +- Set `SCAN_WORKERS=1` to avoid concurrent scan processes +- Enable the watcher but raise `RESCAN_ON_FILESYSTEM_CHANGE_DELAY` to 30+ minutes +- Disable image conversion if you don't care about WebP (`ENABLE_SCHEDULED_CONVERT_IMAGES_TO_WEBP=false`). diff --git a/docs/administration/server-stats.md b/docs/administration/server-stats.md new file mode 100644 index 00000000..7cfea37e --- /dev/null +++ b/docs/administration/server-stats.md @@ -0,0 +1,52 @@ +--- +title: Server Stats +description: "The numbers Mason! What do they mean?" +--- + +# Server Stats + +**Administration → Server Stats** is an admin-only page that reports what's on disk and in the catalogue. + +## What's shown + +### Top-line counts + +| Metric | What it counts | +| ---------------- | --------------------------------------------------------------------------------- | +| **Platforms** | Every platform RomM has seen at least one ROM for. Deleted platforms don't count. | +| **Games** | Total ROM entries. A multi-file game (folder with multiple files) counts as 1. | +| **Saves** | User save files across all users. | +| **States** | Emulator save states across all users. | +| **Screenshots** | User-uploaded screenshots. Provider-fetched screenshots aren't counted here. | +| **Size on disk** | Total disk usage of all ROMs, saves, states, and screenshots. | + +### Per-platform breakdown + +Under the summary, it's a table sorted by name, size or game count. For each platform, you can see: + +- Game count +- Size on disk (in bytes and by percentage of total) +- Region distribution (how many games tagged USA, Japan, Europe, World, etc.) +- Metadata coverage (how many games have metadata from each provider) + +When you want to know "which platform is eating my disk?" or "which platform has the worst match rate?" + +## API + +The same data is available programmatically: + +```http +GET /api/stats +GET /api/stats?include_platform_stats=true +Authorization: Bearer +``` + +Wire to your monitoring stack via the API rather than scraping the HTML page (see the [API Reference](../developers/api-reference.md)). + +## Troubleshooting + +- **Numbers look stale**: stats are computed on page load, not cached +- **Disk sizes look wrong**: if your compose mounts a path that's smaller than the host dataset (e.g. you mounted a sub-directory), it will only see that subset +- **"Platform stats couldn't load"**: the DB query timed out on a very large library + +For anything else, see [Troubleshooting](../troubleshooting/index.md). diff --git a/docs/administration/users-and-roles.md b/docs/administration/users-and-roles.md new file mode 100644 index 00000000..127e306d --- /dev/null +++ b/docs/administration/users-and-roles.md @@ -0,0 +1,62 @@ +--- +title: Users & Roles +description: User management, roles, and the scope model +--- + +# Users & Roles + +RomM is multi-user from the start. The first user created during Setup is always an **Admin**, and everyone after that gets the role you assign when creating the account. + +## Roles + +| Role | Who it's for | Default scopes | +| ---------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------------- | +| **Admin** | You, and anyone you fully trust. | All scopes, including user management and task execution. | +| **Editor** | Household members who help curate the library. | Read everything, edit ROMs/platforms/collections, upload, but no user management. | +| **Viewer** | Guests, kids, anyone who should only play and track their own progress. | Read the library, manage their own saves/states/screenshots/profile. | + +Roles are a convenience layer on top of **scopes** (see the scope matrix below for exactly what each role grants). You can't create custom roles (yet), so if you need finer-grained access, use the most restrictive role and rely on [Client API Tokens](../developers/client-api-tokens.md) for per-app customisation. + +## Scope matrix + +RomM authorisation is scope-based. Every API call and UI action maps to one or more scopes, and OAuth tokens and OIDC sessions carry a subset of them. Nineteen scopes total, grouped by resource: + +| Scope | Purpose | Viewer | Editor | Admin | +| ------------------- | ----------------------------------------------- | :----: | :----: | :---: | +| `me.read` | View own profile | ✓ | ✓ | ✓ | +| `me.write` | Edit own profile | ✓ | ✓ | ✓ | +| `roms.read` | Browse ROMs | ✓ | ✓ | ✓ | +| `roms.user.read` | View own per-ROM data (rating, playtime, notes) | ✓ | ✓ | ✓ | +| `roms.user.write` | Edit own per-ROM data | ✓ | ✓ | ✓ | +| `platforms.read` | Browse platforms | ✓ | ✓ | ✓ | +| `assets.read` | View own saves/states/screenshots | ✓ | ✓ | ✓ | +| `assets.write` | Upload saves/states/screenshots | ✓ | ✓ | ✓ | +| `collections.read` | Browse collections | ✓ | ✓ | ✓ | +| `collections.write` | Create/edit collections | - | ✓ | ✓ | +| `roms.write` | Edit ROM metadata | - | ✓ | ✓ | +| `platforms.write` | Edit/create platforms | - | ✓ | ✓ | +| `firmware.read` | List firmware | - | ✓ | ✓ | +| `firmware.write` | Upload/delete firmware | - | ✓ | ✓ | +| `devices.read` | View own paired devices | ✓ | ✓ | ✓ | +| `devices.write` | Manage own paired devices | ✓ | ✓ | ✓ | +| `users.read` | List all users | - | - | ✓ | +| `users.write` | Create/edit/delete users | - | - | ✓ | +| `tasks.run` | Trigger background tasks (scan, cleanup, etc.) | - | - | ✓ | + +## Creating users + +Three paths: + +- **Admin adds directly**: set username, email, password, and role, and the account is usable immediately. +- **Invite link**: better when you don't want to handle someone else's password. The admin generates a single-use link with a pre-assigned role, and the recipient picks their own credentials. Invite links expire after 600 seconds by default, configurable via [`INVITE_TOKEN_EXPIRY_SECONDS`](../reference/environment-variables.md). +- **OIDC**: if you've wired up OIDC, new identities can be provisioned on first login. Role mapping from OIDC claims is covered in [OIDC Setup](oidc/index.md). + +## Editing and deleting users + +Admins can change any user's role, reset their password, or delete the account. Role changes take effect on next login. You can't delete the last admin or delete yourself while signed in. + +Deleting a user keeps their contributions (collections they made public, ROM metadata edits) but removes their personal data from the database (per-ROM ratings, saves, states, play sessions, paired devices, API tokens). It does not delete any files from disk. + +## API tokens (advanced) + +Each user can issue up to 25 **Client API Tokens**. Tokens carry a subset of the user's scopes and are the right way to authenticate companion apps (Argosy, Grout, Playnite, custom scripts). The pairing flow for devices is covered in [Client API Tokens](../developers/client-api-tokens.md), and the API side is in [API Authentication](../developers/api-authentication.md). diff --git a/docs/developers/api-authentication.md b/docs/developers/api-authentication.md new file mode 100644 index 00000000..55edfbb8 --- /dev/null +++ b/docs/developers/api-authentication.md @@ -0,0 +1,146 @@ +--- +title: API Authentication +description: How to authenticate to the API +--- + +# API Authentication + +The API accepts multiple authentication modes: + +| Mode | Who it's for | How the credential is carried | +| -------------------- | -------------------------------------------------------- | ------------------------------------------------ | +| **Session cookie** | Browser UI | `Cookie: session=…` after `POST /api/auth/login` | +| **HTTP Basic** | Quick scripts, curl one-liners | `Authorization: Basic ` | +| **OAuth2 Bearer** | Automation, CI, third-party apps | `Authorization: Bearer ` | +| **Client API Token** | Companion apps (Argosy, Grout, Playnite, custom scripts) | `Authorization: Bearer rmm_` | + +All of them resolve to the same scope model. See the [scope matrix in Users & Roles](../administration/users-and-roles.md#scope-matrix). A request is allowed if the active identity holds all scopes the endpoint requires. + +## Base URL + +```text +https:///api +``` + +When the app is behind a reverse proxy (as it should be when hosted in public), that's your public URL. When running locally without a proxy, the container listens on port `80`. + +## Session login (browsers) + +```http +POST /api/auth/login +Content-Type: application/x-www-form-urlencoded + +username=alice&password=s3cret +``` + +Response sets a `romm_session` cookie, and subsequent requests from the same browser are authenticated automatically. + +Log out: + +```http +POST /api/auth/logout +``` + +For OIDC logins, hitting `/api/auth/logout` also triggers RP-Initiated Logout if your OIDC provider supports it (configured via `OIDC_END_SESSION_ENDPOINT`). + +## HTTP Basic + +```bash +curl -u alice:s3cret https://demo.romm.app/api/roms +``` + +```python +import requests +from requests.auth import HTTPBasicAuth +r = requests.get("https://demo.romm.app/api/roms", + auth=HTTPBasicAuth("alice", "s3cret")) +``` + +## OAuth2 Bearer token + +The RomM backend implements the OAuth2 password grant, where you exchange credentials for a short-lived access token and a refresh token. Access and refresh token expiry times are configurable via `OAUTH_ACCESS_TOKEN_EXPIRE_SECONDS` and `OAUTH_REFRESH_TOKEN_EXPIRE_SECONDS`. + +```http +POST /api/token +Content-Type: application/x-www-form-urlencoded + +grant_type=password&username=alice&password=s3cret&scope=roms.read%20roms.write +``` + +```json +{ + "access_token": "eyJhbGciOi...", + "refresh_token": "eyJhbGciOi...", + "token_type": "bearer", + "expires": 1800, + "refresh_expires": 604800 +} +``` + +Access tokens are HS256-signed JWTs valid for `OAUTH_ACCESS_TOKEN_EXPIRE_SECONDS` seconds. Send them as: + +```http +Authorization: Bearer eyJhbGciOi... +``` + +Refresh before expiry: + +```http +POST /api/token +Content-Type: application/x-www-form-urlencoded + +grant_type=refresh_token&refresh_token=eyJhbGciOi... +``` + +Request only the scopes you need and RomM will issue a token with the intersection of what you asked for and what the user has. + +## Client API tokens (for companion apps) + +For anything long-lived (a running companion app, a cron job, a CI integration), use **Client API Tokens** instead of OAuth2. They're issued per-user from **Administration → Client API Tokens**, carry a subset of the user's scopes, and don't expire unless you set an expiry. + +Token format: `rmm_` + 64 hex chars. Use it as a bearer: + +```bash +curl -H "Authorization: Bearer rmm_abcdef0123456789..." \ + https://demo.romm.app/api/roms +``` + +Each user gets up to 25 active tokens. Tokens can be paired with a device via the [pairing flow](client-api-tokens.md), useful when you don't want to type a long token on a handheld. + +## OIDC + +Users signing in through an OIDC provider get a regular RomM session, same as username/password login. For the API side this means you can't use an OIDC access token directly. Authenticate the user through the browser first (they'll be redirected to the OIDC provider, then back to RomM), then use the resulting session cookie, **or** mint a Client API Token for programmatic use. + +OIDC provider setup lives in [Administration → OIDC](../administration/oidc/index.md). + +## Which scopes do I need? + +Every endpoint in the [API Reference](api-reference.md) lists its required scopes. The short version: + +- **Read**-ish endpoints want the matching `*.read` scope. +- **Write**-ish endpoints want `*.write`. +- **Admin**-ish endpoints want `users.read`, `users.write`, or `tasks.run`. + +## Errors + +| HTTP | Meaning | +| ------------------ | ----------------------------------------------------------------------- | +| `401 Unauthorized` | No credential, expired credential, bad credential. | +| `403 Forbidden` | Authenticated but the identity lacks a required scope. | +| `404 Not Found` | The resource doesn't exist, or, for privacy, the identity can't see it. | + +When debugging a 403, check: + +1. The **user's role** in Administration → Users. +2. The **token's scopes** (for OAuth2/Client API Tokens). Scopes are narrower than the user's role by default. +3. The endpoint's scope requirements in the [API Reference](api-reference.md). + +## OpenAPI + +The full machine-readable schema is served at `/openapi.json`. It's the source of truth for generated clients, Postman collections, and the in-docs [API Reference](api-reference.md). + +```bash +curl https://demo.romm.app/openapi.json > romm-openapi.json +``` + +See [Consuming OpenAPI](openapi.md) for codegen tips. diff --git a/docs/developers/api-reference.md b/docs/developers/api-reference.md new file mode 100644 index 00000000..13493bab --- /dev/null +++ b/docs/developers/api-reference.md @@ -0,0 +1,39 @@ +--- +title: API Reference +description: Catalogue of the API. Authoritative interactive docs live on each instance. +--- + +## Interactive docs + +Every RomM instance hosts two renderings of its own spec: + +- **Swagger UI** at `{romm_url}/api/docs`: explore + try endpoints inline +- **ReDoc** at `{romm_url}/api/redoc`: cleaner reading layout + +The raw spec: + +```text +{romm_url}/openapi.json +``` + +For code generation, see [Consuming OpenAPI](openapi.md). + +## WebSockets + +REST isn't the only surface. Two socket.io endpoints cover live-update and coordination use cases: [WebSockets](websockets.md). + +## Versioning + +The API follows SemVer along with the rest of RomM: + +- **Breaking changes only in major versions.** Endpoint removal, required-parameter changes, incompatible response-schema shifts +- **Minor versions add** endpoints, optional parameters, optional response fields. +- **Patch versions fix** bugs without schema changes. + +## See also + +- [API Authentication](api-authentication.md): auth modes in detail +- [Consuming OpenAPI](openapi.md): codegen + schema validation +- [WebSockets](websockets.md): socket.io endpoints +- [Client API Tokens](client-api-tokens.md): recommended companion-app auth +- [Device Sync Protocol](device-sync-protocol.md): sync endpoints in depth diff --git a/docs/developers/architecture.md b/docs/developers/architecture.md new file mode 100644 index 00000000..44d85332 --- /dev/null +++ b/docs/developers/architecture.md @@ -0,0 +1,138 @@ +--- +title: Architecture +description: High-level walkthrough of the codebase +--- + +# Architecture + +What you need to know to find your way around `rommapp/romm` before you start changing things. The exhaustive deep-dives live alongside the code at [`docs/BACKEND_ARCHITECTURE.md`](https://github.com/rommapp/romm/blob/main/docs/BACKEND_ARCHITECTURE.md) and [`docs/FRONTEND_ARCHITECTURE.md`](https://github.com/rommapp/romm/blob/main/docs/FRONTEND_ARCHITECTURE.md). This page is the orientation pass. + +## Repo layout + +```text +rommapp/romm +├── backend/ # Python FastAPI application +│ ├── endpoints/ # Route handlers + socket.io under sockets/ +│ ├── handler/ # Business logic: database/, metadata/, filesystem/, auth/ +│ ├── adapters/services/# External API clients (IGDB, Moby, SS, SGDB, RA, ...) +│ ├── models/ # SQLAlchemy ORM +│ ├── tasks/ # RQ jobs: scheduled/ and manual/ +│ ├── alembic/ # 80+ DB migrations +│ └── config/ # Env vars + YAML config.json manager +├── frontend/ # Vue 3 + Vuetify SPA (main UI + Console Mode) +│ └── src/ +│ ├── views/ # Page-level components +│ ├── components/ # ~168 components, organised by feature +│ ├── console/ # Console Mode SPA (own router, layout, input bus) +│ ├── stores/ # 18 Pinia stores +│ ├── services/ # Axios API modules + socket.io + browser cache +│ └── __generated__/# TS types generated from the backend OpenAPI spec +├── docker/ # nginx config, entrypoint, Dockerfiles +└── examples/ # Reference docker-compose.yml and config.yml +``` + +## Runtime topology + +A running RomM container hosts several cooperating processes: + +```ascii +┌─────────────────────────────────────────────────────────┐ +│ docker container │ +│ │ +│ ┌───────┐ HTTP ┌──────────┐ python ┌──────────┐ │ +│ │ nginx │─────────→│ gunicorn │─────────→│ FastAPI │ │ +│ │ :8080 │ │ :5000 │ │ backend │──┐ +│ └───┬───┘ └──────────┘ └──────────┘ │ SQL +│ │ static files (SPA, EmulatorJS, Ruffle) ↓ +│ │ ┌──────────┐ +│ │ │ MariaDB │ +│ ↓ │ (or PG/│ +│ /library /assets /resources │ MySQL) │ +│ (host bind mounts) └──────────┘ +│ │ +│ ┌──────────┐ ┌──────────────────────┐ │ +│ │ RQ │←───────→│ Valkey │ │ +│ │ workers │ jobs │ (embedded or external)│ │ +│ └──────────┘ └──────────────────────┘ │ +└─────────────────────────────────────────────────────────┘ +``` + +## Request lifecycle + +Every request runs the middleware stack in order, CORS → CSRF → authentication → Valkey-backed session → context vars (aiohttp + httpx clients), before FastAPI dispatches to the endpoint. Handlers do the actual work and Pydantic schemas serialise the response. + +## Backend + +### Layers + +The backend follows a fairly conventional layering. Endpoints handle request validation and response serialisation, while the actual business logic lives in handlers organised by concern: `handler/database/` for per-entity CRUD, `handler/metadata/` for provider-specific normalisation, `handler/filesystem/` for I/O, and `handler/auth/` for the multi-method auth backend. Models are SQLAlchemy ORM, and adapters wrap the external APIs. + +### Authentication + +`HybridAuthBackend` walks methods in order of session cookie (looked up in Valkey), HTTP Basic (bcrypt), OAuth2 Bearer JWT (HS256), Client API Token (`rmm_...`, SHA-256 lookup), OIDC, kiosk mode if enabled. Token plaintext is never stored as we hash on creation and compare hashes on every request. + +### Metadata providers + +Each provider has a handler under `handler/metadata/` that normalises responses into a common shape. Priority is configurable in `config.yml` (`scan.priority.metadata`), where first match wins per field, with manual overrides on top. + +Hashing can be platform-aware: `.chd` files pull their SHA1 values straight from the file header, PICO-8 cartridges (`.p8.png`) get a special-cased extractor, and the RetroAchievements per-platform algorithm runs through `rahasher.py`. Switch and PS3/4/5 skip hashing entirely, since those ROMs aren't reasonably hashable in the first place and have no TOSEC/No-Intro entries. + +### Configuration + +Environment variables (100+ of them, all listed in `env.template`) cover infrastructure concerns, while `config.yml` covers everything to do with the library, scanning, and emulator behaviour. The config is read, validated, and written back through the singleton `ConfigManager`. + +### Background jobs + +RQ workers run scheduled jobs (rescans, Switch TitleDB refresh, LaunchBox refresh, image-to-WebP conversion, RA progress sync, netplay cleanup) and manual tasks (`cleanup_missing_roms`, `cleanup_orphaned_resources`, `sync_folder_scan`). Each scheduled task is gated by an `ENABLE_SCHEDULED_*` env var and tunable via the matching `*_CRON`. Operator-side detail in [Scheduled Tasks](../administration/scheduled-tasks.md). + +## Frontend + +### Stack + +The frontend is a Vue 3 SPA written in TypeScriptusing the Composition API and `