Doc status: Active
Admin settings use grouped rows at /admin/settings (one sheet, section headings, whole row → destination; ?section= redirects). In the rail, Settings unfolds into four icon sub-sections whose pages are buttons in the top bar — see navigation.md. Chrome is the React admin top bar (frontend/admin-app); many forms remain Jinja until migrated. Live React bodies include Dashboard, Libraries/Scans hubs, Themes, Plugins, Announcements, Support inbox, and the Integrations hub (the same grouped rows as Settings: Metadata & art · Stores & ownership · Messaging & identity · Acquisition, with deep links into classic forms).
Integrations inventory API: GET /api/admin/integrations/inventory (admin) returns {integrations[{id,name,category,status,configured,enabled,admin_href,settings_href,notes}], count, hub_href} covering IGDB, SteamGridDB, Giant Bomb, HLTB, RetroAchievements, Meta/Quest, SMTP, OIDC, Support, community chat, LiveKit, Arr connectors, and ownership register links — so the hub is not IGDB-only. The React Integrations page renders a Provider inventory grouped by category (with status + notes) under the grouped rows. RetroAchievements connects under Integrations → Metadata & art → Artwork & secondary; the inventory deep-link uses the supported #artwork tab. Classic /admin/integrations artwork tab anchors (#steamgriddb, #giantbomb, #hltb, #retroachievements, #meta_quest, #ownership, #livekit, #support, #indexers, #community, #email, #igdb) deep-link the same surfaces.
Fresh-install setup: The six-step wizard creates the admin, optionally configures SMTP and feature preferences, optionally collects IGDB plus Steam Web API, SteamGridDB, Giant Bomb, MobyGames, and TheGamesDB credentials, and can save OIDC issuer/client details without enabling SSO. It then offers to create a first library and queue its initial scan. The API-key fields are opt-in; empty values preserve existing credentials and secrets are never rendered back into the form. HowLongToBeat can be toggled without a key. OIDC remains disabled during setup so the new admin can verify its issuer and callback before enabling an authentication provider. Keyless catalogue sources continue to work without setup. Integrations that require container environment values (for example LiveKit and *arr endpoints) remain visible in the Integrations inventory and require deployment configuration. Every step can be skipped; setup can finish without a library.
The flow follows the optional, ordered setup used by Plex and Jellyfin: establish the administrator first, let the operator skip optional services, and offer initial library creation before entering normal use. See Plex Basic Setup Wizard and Jellyfin Setup Wizard Walkthrough.
Newsletter: /admin/newsletter stays available when SMTP or the newsletter feature is off. The page explains which prerequisite is missing and keeps sent history readable; sending is disabled until both the feature and a working SMTP sender are configured.
Browser play engine (BP-0 / BP-1): GET/PUT /api/browser-player-settings stores admin defaults under GlobalSettings.settings.browser_player. The only selectable default today is webretro; emulatorjs is reserved until that shell ships. Optional bool nostalgist_nes_pilot (default off) points NES only at /static/vendor/nostalgist/play.html (vendored Nostalgist + WebRetro nestopia WASM). Toggle it on Admin → Emulators. Browse payloads include browser_player / browser_players_available / nostalgist_nes_pilot. See browser-play.md and browser-play-engines.md.
Export packs: Admin → Settings → Extend → Plugins & exports (and member Systems secondary section) download ES-DE gamelist.xml (/api/export/esde) and Pegasus metadata (/api/export/pegasus). Paths are portable under library roots — NAS/home mounts are not leaked.
Server logs: Admin → Ops → Full log (/admin/ops?open=full-log). Legacy /admin/server_logs redirects.
Worker caps (scan/turbo): New installs default scan threads 1, turbo threads 4, turbo batch 100; runtime hard-caps via ONEIRODEX_SCAN_THREAD_CAP / ONEIRODEX_IMAGE_DOWNLOAD_THREAD_CAP / ONEIRODEX_IMAGE_DOWNLOAD_BATCH_CAP — not Compose SCAN_* env vars. See libraries-and-scans.md · unraid-deploy.md.
- Done (uncommitted): Admin → Settings → Scan / match policy (
/admin/scan_match) — ReactScanMatchSettingsPage(Jinja SPA shell) + Settings hub card · admin vitest 7/7 claimed · BEGET/PUT/api/admin/scan-match/configlive (scoring / dupe / peel wired · pytest claimed 13+21). - Persist:
GlobalSettings(settings.scan_matchJSON +propose_only_scan). Unset keys use defaults below. - Defaults:
match_high_threshold0.92 ·match_ambiguous_gap0.08 ·dupe_title_threshold0.85 ·peel_profileconservative· Stage C safe variant toggles on (enable_year_drop_variant·enable_pack_peel_variant·enable_edition_peel_variant·enable_sequel_numeral_variant). - Honesty: propose-only never auto-imports (even high-confidence). API refuses mega-library / depth-3 family walk keys.
scanThreadCountstays on Server Settings / worker caps. - Propose-only also remains on Server Settings (
proposeOnlyScan/propose_only_scan) with a link to this page. - Post-ship: Reset Themes not required for this API (UI shell already shipped). Details: libraries-and-scans.md.
Settings hub shows On/Off (and Storage “Apply off”) as pills beside the module title so you can see state without opening each page. Badge CSS ships in admin-app.css — Reset Themes is not required for the hub look; an admin SPA rebuild is.
Product modules default on. Disable during setup → Features, under Admin → Features, or via .env / Compose.
Member chrome (Server Settings): showHelpButton and showTrailers default on. They are baked into every member SPA shell on load (data-show-help / data-show-trailers), including Systems / Chat / Collections — not only Discover and Favorites. A missing JSON key must not hide those More destinations.
Stays off by default: OIDC_ENABLED (SSO/auth).
Safety locks (also off): ENABLE_AI_AUTO_APPLY, ALLOW_HARDLINK_APPLY.
Patch catalog: operator YAML/JSON at PATCH_CATALOG_PATH — Oneirodex does not scrape romhacking.net or similar sites.
| Env / module | Default | Notes |
|---|---|---|
Most ENABLE_* product flags |
on | See .env.example |
ENABLE_MALWARE_SCAN |
on | ClamAV when reachable + heuristics; blocks/skips on match; Admin → Features |
MALWARE_SCAN_BLOCK_ON_HIT |
on | Skip library adds on heuristic warn or ClamAV hit |
CLAMAV_* |
host 127.0.0.1:3310 (native) / clamav:3310 (Compose profile) |
Optional docker compose --profile clamav up -d |
ENABLE_LIVEKIT |
on | Needs LIVEKIT_* + compose profile for actual SFU |
ENABLE_VR_BROWSE |
on | /vr catalogue |
ENABLE_PCDOS_BROWSER |
on | Needs vendored dosbox WASM |
ENABLE_FREE_GAMES |
on | News free-games poller + API |
NOTIFY_APPRISE_URLS / NOTIFY_NTFY_URL |
unset | Notification bus (INSP-6): Apprise API notify URL(s) and/or an ntfy topic. Every admin alert that passes its admin_notify_* flag is also POSTed there (one event per alert); NOTIFY_SOCIAL_TO_BUS=true adds the social kinds (friend requests, mentions, DMs, free games), still gated by each member's own in-app preference. Test with POST /api/admin/notify-bus/test. Nothing bundled; a dead endpoint is logged once and never breaks the in-app notice. A per-member topic is sized in H-I |
ENABLE_GAME_ASSISTS |
on | Assist packs, and since INSP-45 the companion overlay links: PUT /api/games/<uuid>/assists takes overlay_links: [{label, url, kind}] (map / guide / clip / wiki / other; http(s) pages only — a file: URL is 422) and every PC title also gets a PCGamingWiki deep link with no pack at all. The stay-open Friends window shows them for the game on screen (/social-companion?game=<uuid>, the desktop companion passes the last launched title). Links beside the game — no memory access, no injection, nothing read from a running process |
ENABLE_SAVE_PATHS |
on | Save location row on PC details pages (INSP-1): one keyless fetch a day of the community save-location manifest, indexed into static/library/save_paths/ (SAVE_PATHS_MANIFEST_URL, SAVE_PATHS_CACHE_DIR). Downloads are streamed with a 64 MiB decoded-body limit. Paths keep their <winAppData>-style placeholders; the desktop companion expands them for its own PC when asked to Open save folder, and refuses when a placeholder is unknown there. Nothing is synced or copied — the multi-device save story is sized in H-I |
ENABLE_MOD_CATALOG |
on | Browse catalogue in a game's Mods panel: Thunderstore and Modrinth, read-only, keyless. A hit is a name, version, loader and registry page — never a file. Integrations lists both plus CurseForge as declined |
ENABLE_MOD_CATALOG |
on | Browse catalogue in a game's Mods panel: Thunderstore, Modrinth and GameBanana (keyless) plus Nexus Mods behind NEXUS_API_KEY, all read-only. A hit is a name, version, loader and registry page — never a file. Integrations lists the four plus CurseForge as declined |
NEXUS_API_KEY |
unset | Personal key from your Nexus account page; turns on the Nexus tab (trending + latest for the game). Browse only — Nexus's terms forbid third-party download automation, and nothing here downloads |
ENABLE_ANTICHEAT_COMPAT |
on | Community anti-cheat compatibility list, one keyless fetch a day into static/library/anticheat/; downloads are streamed with a 16 MiB decoded-body and 100,000-row limit. Details show the status as community reports. ANTICHEAT_FEED_URL / ANTICHEAT_CACHE_PATH override the source and the file. Integrations lists it as Anti-cheat reports, configured once the first fetch has landed |
ENABLE_EMAIL_DIGEST |
on | Scheduler on; members still opt in |
ENABLE_LOGIN_RATE_LIMIT |
on | In-process login / password-reset rate limit |
OIDC_ENABLED |
off | Also requires Admin → Integrations toggle |
BIOS_IMPORT_SOURCE |
unset | Folder of dumps you already own. Boot copies missing names (never overwrites). Admin → Emulators Scan collection uses the same path. emulator-bios.md |
- Env:
ENABLE_ARR_MODULE,ENABLE_ARR_HARDLINK_PIPELINE, plus optional Prowlarr/Jackett/qBittorrent URLs in.env. - Admin toggle via Arr settings /
PUT /api/arr/module(env or DB enable). - On by default; disable under Features if you are not using Acquire.
- Native indexers: Admin → Arr registry stores Torznab/Newznab entries in
GlobalSettings.arr_settings.indexers(add one, JSON/CSV bulk, curated presets with empty API keys). Search merges enabled native endpoints and configured Prowlarr and Jackett. - Admin UI: Arr page shows indexer table (ready/enabled/source, toggle, delete), add-one form, bulk JSON/CSV import, preset multi-select + Enable selected, hub URL fields, and
indexer_warningsfrom status/search. - APIs:
GET/POST /api/arr/indexers,POST /api/arr/indexers/bulk,POST /api/arr/indexers/enable-presets,PUT|PATCH|DELETE /api/arr/indexers/<id>. - Native indexer URLs use outbound SSRF checks (no LAN); hub URLs still respect
ALLOW_PRIVATE_LAN_URLS. Hub URLs (Prowlarr, Jackett, qBittorrent, Transmission, SABnzbd, NZBGet) are re-checked every time they are called, and every redirect hop is re-checked too, not only when you save them. Connector failures are logged by exception type and host/path only — never the?apikey=query string — and the Acquire / Arr download and search routes answer with fixed wording ("Could not reach the download service", "The download service did not respond in time", "…returned an error (401)"), never the exception text, because that text holds the request URL (SABnzbd and AllDebrid send the key in the query string) and the address the host name resolved to; the details are in the server log. Outbound requests dial the address the host name resolved to (unless a proxy applies, see Outbound proxies and URL forms), so a host name this server cannot resolve is refused when it is used (URL host could not be resolved) even though it can still be saved while DNS is down; use an IP address or fix DNS/extra_hosts. A connector URL that carries credentials (http://user:pw@proxy.lan) keeps them across same-origin redirects, andhttp://hostredirecting tohttps://hoston the default ports keeps its credentials and API-key header the wayrequestsdoes; any other origin change drops them, and the log says which headers were dropped (names only). - Preset pack:
oneirodex/data/indexer_presets.json(no secrets; admin-only display names). - Remote path mapping (
ARR_REMOTE_PATH_MAP) — set this whenever your download client runs in a different container than Oneirodex, which is the normal Unraid/Compose layout. qBittorrent reports paths from its mounts (/downloads/…), Oneirodex sees the same bytes somewhere else (/storage/downloads/…), and without a mapping the hardlink pipeline stats a path that does not exist here. The preview then says "no source file found" — true, but baffling when the file is plainly on disk.- Format:
remote=>localpairs joined by|.=>because Windows paths contain colons;|because paths can contain commas. - Example:
ARR_REMOTE_PATH_MAP=/downloads=>/storage/downloads|/data/torrents=>/mnt/user/torrents - Longest remote prefix wins, so a specific mapping beats a general one. A prefix only matches at a path separator, so
/downloadsnever matches/downloads-old. - Leave empty when client and app share a filesystem view — unmapped paths pass through untouched.
- When no mapping is set and a lookup fails, the preview reason now names the path it tried and points at this setting instead of just saying "not found".
- Format:
- Quality / release profiles (P1-12):
GlobalSettings.quality_profiles(multi-profile JSON). Admin → Quality profiles SPA at/admin/quality_profiles(QualityProfilesPage: list · set active · new · delete · edit · score probe; Jinja is an SPA shell). APIs:GET/POST /api/quality-profiles,PUT /api/quality-profiles/active,GET/PUT/DELETE /api/quality-profiles/<id>. Active profile scores Arr search and extends scan name-clean with blocked/excluded terms.
- Env:
ENABLE_AI_ASSIST,ENABLE_AI_AUTO_APPLY,OLLAMA_BASE_URL,OLLAMA_MODEL. - Admin AI page: enable + Ollama URL/model (
PUT /api/ai/config) and Test. - Ollama-only by default; never required for core library use.
ENABLE_HARDLINK_HELPERSandALLOW_HARDLINK_APPLYare env-only safety gates (no DB toggle).ALLOW_HARDLINK_APPLYstays off by product default.- Admin page: Settings → Storage (
/admin/storage) — ReactStoragePage(Jinja emptied to SPA shell). - Status API:
GET /api/storage/status—helpers_enabled·allow_apply·games_path·games_exists/games_readable/games_writable·degrade_reason(RO / apply-off honesty). - Preview / apply:
POST /api/storage/hardlink/preview·POST /api/storage/hardlink/apply(apply gated by helpers andALLOW_HARDLINK_APPLY). Preview surfaces readable reasons, including destination parent not writable (read-only mount?). - Hub / page banners explain why Apply is disabled when helpers/apply are off or the games mount is RO.
- Env:
ENABLE_LIVEKIT,LIVEKIT_URL,LIVEKIT_API_KEY,LIVEKIT_API_SECRET. - Compose:
docker compose --profile livekit up -d— livekit-unraid.md. - Plugin registry:
rtc.livekit(configured when env is complete).
- Env:
ENABLE_REMOTE_PLAY(off by default), optionalSUNSHINE_BASE_URL/WOLF_BASE_URL, hint vars — see.env.example. - Admin: Settings → Remote play (
/admin/remote_play) orPUT /api/admin/remote-play/config. - Members:
GET /api/remote-play/status; game details Play via Moonlight copies host + hints. - No Wolf/GOW in Oneirodex image — operator runs Sunshine/Wolf on a GPU host; LAN URLs need
ALLOW_PRIVATE_LAN_URLS=true. - Plugin registry:
remote_play.moonlight.
- DB:
GlobalSettings.loading_icon_mode(rotate|lock, default rotate),loading_icon_id(catalogue id or null). - Public bootstrap:
GET /api/loading-icon(no admin auth — member/admin loading UIs). - Admin:
GET/PUT /api/admin/loading-icon/config— lock requires a catalogue id; rotate clears id. - Catalogue ids:
ring,orbit,pulse,blocks,scan,arcade— visuals are SPA/theme-owned.
- Env:
ENABLE_MALWARE_SCAN,MALWARE_SCAN_BLOCK_ON_HIT,CLAMAV_HOST,CLAMAV_PORT,CLAMAV_SOCKET. - Compose:
docker compose --profile clamav up -d— docker-compose-deploy.md. - Library scans skip/block adds on heuristic filename match or ClamAV hit when
MALWARE_SCAN_BLOCK_ON_HIT=true(default). - Admin status:
GET /api/admin/malware-scan/statusor Admin → Features.
- Env:
ENABLE_CHALLENGE_SOLVER(off by default),CHALLENGE_SOLVER_URL,CHALLENGE_SOLVER_PROVIDER,CHALLENGE_SOLVER_TIMEOUT_MS,CHALLENGE_SOLVER_MAX_TIER(default 5; admin may raise). - Optional token CAPTCHA API:
CHALLENGE_TOKEN_API_URL,CHALLENGE_TOKEN_API_KEYwhenprovider=token_api. - Compose:
docker compose --profile challenge up -d(Ops) — FlareSolverr-compatible TRAWL sidecar on LAN only. - Admin → Features: enable, solver URL, provider, max tier, Test solver; status
GET /api/admin/challenge-solver/status?probe=1. - Opt-in only — not bulk-enabled with OIDC/AI apply locks. Solver URL validated via
validate_connector_http_url+ALLOW_PRIVATE_LAN_URLS. - Acquire (*arr search / debrid HTTP) retries once through the solver when a challenge page is detected and the module is on.
- Env:
ENABLE_AMBIENT_LIGHTING(off by default),LIGHTING_PROVIDER(off|hyperion|homeassistant). - Hyperion:
HYPERION_URL, optionalHYPERION_TOKEN,HYPERION_PRIORITY(default 50),AMBIENT_ACCENT_COLOR. - Home Assistant:
HA_URL,HA_TOKEN,HA_LIGHT_ENTITIES, optionalHA_PLAY_SCENE/HA_STOP_SCENE. - Play session start/stop hooks fire-and-forget — never block play launch. Child accounts never trigger lighting.
- Admin → Features: enable, provider, connector fields, Test; status
GET /api/admin/ambient-lighting/status?probe=1. - URLs validated via
validate_connector_http_url+ALLOW_PRIVATE_LAN_URLS.
- Env:
SUPPORT_GITHUB_TOKEN,SUPPORT_GITHUB_REPO— support-inbox.md. - No Discord webhooks; library events notify admins in-app (
admin_notify_*).
- Admin → Settings → Art studio or
/admin/art_studio(React; admin/ops only). Tabs: Studio · Backup & stock (#stock) · System marks (#marks) · Pick & queue (#images). - Local Pillow renderer — aurora tokens (
--gt-*), no paid cloud AI. Preview/generate use artistic compositions by default (artistic: trueonPOST /admin/api/art-studio/preview; optionalartistic: falsefor legacy flat A/B). Idle title scale is 1.3× (floor 0.85×); the slider always poststitle_scale. - Title-first studio: large live preview stage; typing a title debounces preview. System / platform selector + preview size toggles (200×300 · 400×600 · 960×540 wide). Soft-fails preview lag with toast.
- Actions: Preview · Generate pack · Download ZIP · Set as fallback · Apply to game UUID.
- Backup & stock (
#stock): thumbnail grid of platform packs + stock motifs fromGET /admin/api/art-studio/stock; ungenerated packs auto-callPOST …/stock/generateon apply. Select → preview → Use as library default / Set fallback viaPOST /admin/api/art-studio/apply(mode=fallback|library). Soft empty state if catalog 404. Library create/edit Jinja Choose image links here. - Library default covers panel shows current
default_cover.jpg/default_library.jpgwith Regenerate defaults CTA. - Batch placeholders (collapsed) for no-cover titles via
POST /admin/api/art-studio/batch-generate(alias:apply-batch) first, thenPOST /admin/api/covers/batch/apply(generate_only) fallback. - Auto-pick (ImagesPage):
POST /admin/api/covers/batch/applywithpolicy=sgdb_then_igdb_then_generate(library / platform / service filters). Mass search:POST /admin/api/covers/batch/search. - Single-title picker:
POST /admin/api/covers/search+POST /admin/api/covers/apply. Identify chips fromGET /api/search_metadata/sources(Meta Quest / Epic / itch / Giant Bomb / MobyGames / TheGamesDB) search viaGET /api/search_metadata?source=. OptionalMOBYGAMES_API_KEY/THEGAMESDB_API_KEY— empty results when unset. - Remote artwork downloads are streamed and capped at 25 MiB; a larger provider response is refused before it is written to the library.
- Queue rows show
failure_reason(andlast_errorfallback); list responses surfaceimage_save_path.errorwhen the images volume is not writable. - API:
POST /admin/api/art-studio/preview|generate|apply|apply-batch,GET /admin/api/art-studio/download/<pack_id>,POST /admin/api/art-studio/batch-generate,GET /admin/api/art-studio/stock,POST /admin/api/art-studio/stock/generate,GET /admin/api/art-studio/system-marks,GET /admin/api/art-studio/system-marks/lab,POST /admin/api/art-studio/system-marks/generate; covers mass tools under/admin/api/covers/*. - Systems hub marks (AI): Art Studio tab System marks (
#marks) lists per-theme progress and can generate missing / force-redo viaGET/POST /admin/api/art-studio/system-marks. The Lab on that tab generates one theme×platform pair (editable prompt, preview, attempt log) viaGET …/system-marks/labandPOST …/generatewithplatforms+ optionalprompt. Square WebPs land understatic/library/system-marks/<theme>/<platform>.webp. RequiresENABLE_AI_ARTWORK+AI_ARTWORK_URL. CLI:python scripts/generate_system_marks.py --all. Full batch regen is ops-gated (quality hold). - System templates: generated covers use per-system palette + glyph (NES/SNES/PS1/Switch/PC/…) so 200×300 tiles stay readable — not a generic subtitle-only placeholder.
- Meta Quest Store: identify
GET /api/search_metadata?source=meta_quest|meta|quest· ownership CSVPOST /api/ownership/meta_quest/csv·META_QUEST_API_MODE/META_QUEST_UNOFFICIAL_GRAPHQL(off by default) (local strategy notes). - Store connections (admin):
/admin/ownership(Integrations → Ownership registers) lists each member's store links with one state per store (Linked, Syncing, Partly synced, Reconnect needed, Sync failed, …), the last sync's redacted reason ("Admin can fix" marks operator-side causes such as a refused household token or a missing server key), record counts and which sign-in a sync uses (member / household / unknown — a GOG, Amazon or Xbox sign-in saved before LIB-04 on a server that has a household token for that store; older versions stored the household token on member accounts unmarked, so ask those members to reconnect after upgrading). It never shows tokens, store account IDs or title lists. Retry sync runs a member's sync with their own saved sign-in (not offered when only the member can fix it); Stop sync is offered only for GOG / Epic / Amazon, which stop between pages. Household configuration appears as presence flags. API:GET /api/admin/ownership/connections,POST …/<user_id>/<store>/sync|cancel. - Ownership register: members link Steam / GOG / Epic / Amazon under More → Ownership. Steam Web API, unofficial GOG Galaxy refresh token, unofficial Epic device auth, unofficial Amazon Nile/Heroic token — IDs and names only, never a download. Household env:
STEAM_WEB_API_KEY,GOG_REFRESH_TOKEN,EPIC_DEVICE_AUTH,AMAZON_REFRESH_TOKEN/AMAZON_DEVICE_SERIAL/AMAZON_NILE_JSON. Xbox and PlayStation (INSP-42) are register-only, unofficial and opt-in: CSV import always works; live sync runs only whenENABLE_UNOFFICIAL_STORE_SYNCnames the store (xbox,psnorall; unset = off, decision G5) and the optional client is installed (requirements-optional.txt:xbox-webapi,psnawp) and a member saved a token on the Ownership page (xbox-webapitokens JSON; PSNnpsso). Without any of the three the sync button says which is missing in one sentence; the Integrations rows and pluginsstore.xbox/store.psnread disabled until opted in, available until the client exists. Household fallbacksXBOX_TOKENS_JSON,XBOX_CLIENT_ID/XBOX_CLIENT_SECRET,PSN_NPSSO. IDs and names only; a 401 fails closed; nothing is ever downloaded. Nintendo stays CSV. - Disk failures (read-only
IMAGE_SAVE_PATH/ generated-pack folder, out of space) surface as a JSONerrorand show in the red alert banner instead of a bare 500 — check the message for the exact path/permission problem. If applying a pack to a game fails partway (DB error after the file was written), the orphaned file is cleaned up automatically. - Artwork picker: steamgriddb-artwork.md · libraries-and-scans.md.
Optional, off by default, and self-hosted only. This is the one feature that talks to an endpoint outside the process, so it stays opt-in.
| Flag | Effect |
|---|---|
ENABLE_AI_ARTWORK |
Master switch — default false |
AI_ARTWORK_URL |
Your endpoint, e.g. http://sdnext:7860. No default; generation refuses without it |
AI_ARTWORK_ENGINE |
a1111 (default) — the A1111 REST API, which AUTOMATIC1111, SD.Next and Forge all implement |
- Calls
POST /sdapi/v1/txt2imgon your endpoint. Nothing leaves your network; there is no hosted provider and no API key to buy. AI_ARTWORK_ENGINE=comfyuiis recognised but not implemented — it raises a clear error naming the missing workflow rather than silently producing nothing. Usea1111for now.- Generated rows are marked
is_generatedwithgenerated_by. Regenerating replaces only the previous generated image, so hand-picked or scraped art is never clobbered. - Routes:
POST /admin/api/artwork/generate(one game) ·POST /admin/api/artwork/generate/batch(fill missing covers). - Compose ships an SD.Next sidecar under the
artworkprofile (docker compose --profile artwork up -d) — seedocker-compose.yml. That service overrides the image's CMD:saladtechnologies/sdnext:lateststill passes--skip-tests, which its pinned SD.Next checkout does not define, so the stock command dies at argparse with unrecognized arguments before the server ever binds. Its volumes mount at/webui/data/modelsand/webui/outputs— the image has no/app. Its healthcheck probes withwget, because the image ships nocurl: acurlprobe fails with "executable file not found" and the container sits unhealthy forever while serving fine. - GPU is opt-in and never assumed. The sidecar runs on CPU by default —
extremely slow, but it runs.
docker-compose.ymlrequests no GPU at all, because an NVIDIA reservation on a host without a loaded driver fails container create (nvml error: driver not loaded) and takes the whole stack update with it. If the Docker host has the driver and the NVIDIA Container Toolkit, opt in withCOMPOSE_FILE=docker-compose.yml:docker-compose.gpu.yml. - GPU on a different machine? Do not start the profile. On a Windows GPU
box use
docker-compose.artwork-local.yml(artwork-gpu-workstation.md) and setAI_ARTWORK_URL=http://<host>:7860— the backend only makes an HTTP call. Making that turnkey (pairing, health, queueing) is backlog GPU-N.
Prefer to supply your own art instead? See theme-fonts-and-images.md.
| Flag | Effect |
|---|---|
SCAN_CHECK_FRESHNESS |
Check version / updates / DLC after a library scan — default false |
SCAN_FRESHNESS_LIMIT |
Titles checked per run; default 50 |
Off by default deliberately: each check is outbound store HTTP traffic, so a routine scan must not start doing it without being asked. The cap keeps a large first scan from turning into thousands of requests.
| Flag | Effect |
|---|---|
FONT_PATH |
Where uploaded/dropped-in fonts live. Empty = static/library/fonts |
FONT_MAX_BYTES |
Per-file upload cap; default 8388608 (8MB) |
Font files are operator-supplied — the registry ships the faces, not the binaries. Full guide: theme-fonts-and-images.md.
| Flag | Effect |
|---|---|
ENABLE_VR_BROWSE |
Member VR catalogue |
DAT_HASH_INNER_ARCHIVE |
Open zip/7z/rar and hash the inner dump when the outer archive hash misses (default on) |
ENABLE_FREE_GAMES |
News free-games poller + API (default on) |
ENABLE_MOD_CATALOG |
Read-only mod registry browse (Thunderstore, Modrinth, GameBanana, Nexus) in the Mods panel (default on) |
NEXUS_API_KEY |
Personal Nexus Mods key; browse only (unset = the Nexus tab says it needs a key) |
ENABLE_ANTICHEAT_COMPAT |
Community anti-cheat list, daily fetch + details fact (default on) |
ANTICHEAT_FEED_URL |
Where the list is fetched from (default: the public games.json) |
ANTICHEAT_CACHE_PATH |
Where the fetched file lives (default static/library/anticheat/games.json) |
FREE_GAMES_POLL_HOURS |
Free-games refresh interval (default 3) |
ENABLE_EMAIL_DIGEST |
Batched digest scheduler (default on; members still opt in) |
EMAIL_DIGEST_INTERVAL_HOURS |
Digest poll interval (default 24; clamp 1–168) |
ENABLE_PCDOS_BROWSER |
Allow PC DOS browser play when dosbox WASM is vendored (default on; still needs WASM on disk) |
ENABLE_LOGIN_RATE_LIMIT |
In-process login / password-reset rate limit (default on) |
LOGIN_RATE_LIMIT_ATTEMPTS |
Max failures per window (default 10) |
LOGIN_RATE_LIMIT_WINDOW_SECONDS |
Window seconds (default 300) |
OIDC_ENABLED + Admin Integrations |
SSO (also see OIDC runbooks) |
| Custom chat emoji | Admin → Integrations → Community → Manage custom chat emoji (max 20) |
ALLOW_PRIVATE_LAN_URLS |
Allow admin *arr/Ollama/ambient-lighting/game-server-health connector URLs on RFC1918 and the Tailscale/CGNAT range 100.64.0.0/10 (user/indexer fetches stay blocked; cloud metadata endpoints — 169.254.169.254, 100.100.100.200 (Alibaba), 168.63.129.16 (Azure wire server), 192.0.0.192 (Oracle), fd00:ec2::254 and fd00:ec2::23 (AWS IPv6) — are never reachable, by address or by a name that resolves to one, and not when the IPv4 address is wrapped in IPv6: IPv4-mapped, NAT64 64:ff9b::/96 and 64:ff9b:1::/48, 6to4, Teredo, IPv4-compatible and SIIT forms are unwrapped and checked too). The check runs on every request and every redirect hop. An Ollama URL from OLLAMA_BASE_URL (or the built-in 127.0.0.1 default) is the operator's own choice and stays reachable with the flag off; one saved in Admin is held to the flag |
CHEAT_STORAGE_MAX_BYTES |
Total .cht storage across every game (default 0 = 256 MB). Each game is also capped at 200 files of 1 MB; a new file past either bound is refused with 409 conflict, and the count-then-write check holds a lock file in the cheats folder, so simultaneous uploads cannot exceed it even from several worker processes. A value that is not a whole number of bytes (256MB) is ignored with a warning in the log, as it is for EMULATOR_BIOS_MAX_BYTES |
OIDC_LOCK_ROLES |
Don’t overwrite roles on every SSO login |
ENABLE_CHALLENGE_SOLVER |
off — BYO FlareSolverr/TRAWL sidecar for challenged acquire fetches |
CHALLENGE_SOLVER_MAX_TIER |
Default 5 (admin may increase) |
Server-side fetches (connectors, indexers, metadata and artwork providers, notification webhooks) follow the standard proxy variables the way requests does: HTTP_PROXY, HTTPS_PROXY, ALL_PROXY and NO_PROXY (host names, .suffix entries, IP addresses, CIDR ranges, or *).
- No proxy applies (variable unset, or the host matches
NO_PROXY): Oneirodex connects to the address it just checked and keeps the host name onHost/ TLS, so a name that changes its answer between the check and the connection cannot steer the call (DNS-rebinding protection). - A proxy applies: the host name is checked as usual (loopback, private, link-local and cloud-metadata addresses stay refused), then the name goes to the proxy, which resolves it and connects. HTTPS uses
CONNECT host:443with normal SNI, so name-based proxy rules and virtual hosts work. Oneirodex cannot pin a connection the proxy makes, so DNS-rebinding protection then rests with the proxy, on every redirect hop too. Configure the proxy to refuse loopback, private (RFC 1918 / ULA), link-local and cloud-metadata destinations, or list your LAN hosts inNO_PROXYand let everything else go out. IPv6 addresses that embed IPv4 are checked for the well-known NAT64, 6to4, Teredo and mapped forms only; a site-specific NAT64 prefix is not recognised. A name this server cannot resolve is passed on for the proxy to decide; without a proxy it is refused (URL host could not be resolved). - The proxy decision uses the host name in the URL, not the address it resolves to. A LAN connector configured by name (
http://nas.lan:8989) needsnas.lan(or.lan) inNO_PROXY, otherwise its API key goes to the proxy; one configured by IP address matchesNO_PROXYentries for that IP or its CIDR range. Invalid URL: a URL is refused when Python andrequestswould read a different host out of it, or when its host part holds characters RFC 3986 does not allow (a backslash, a space,^,|, braces) or an impossible port.http://127.0.0.1\@example.com/isexample.comto one parser and127.0.0.1to the other. Percent-encode special characters in credentials embedded in a connector URL (@becomes%40), or use the separate username/password fields.
ENABLE_MOD_TRACKING(default on) — per-game mod registry at/api/games/<uuid>/mods(librarian/admin CRUD; members read; child read-only). Summary:GET /api/mods/summary. Each row carriesid,name,version,source_url,notes,enabled,load_orderand — since INSP-36 —loader: the mod loader it needs (bepinex,melonloader,smapi,lovely,forge,fabric,quilt,neoforge,manual,noneare the suggested words, any slug is kept). The pack has adefault_loaderrows inherit (PATCH /api/games/<uuid>/mods/pack, ordefault_loaderon the bulkPUT). Bodies are validated (422on unknown fields). The companion only reads the loader — its apply result says Needs BepInEx installed — not managed here; nothing installs a loader. The details page has a Mods panel: everyone sees the tracked list; a librarian gets the default loader, an add form and Browse catalogue —GET /api/games/<uuid>/mods/catalog?source=thunderstore|modrinth|gamebanana|nexus&q=(librarian). The answer saysstatus: okwith hits, orstatus: unavailablewithhits: nulland a note when the registry had no data — never a silent empty list. Add to list files the hit through the ordinaryPOSTwith the registry page assource_url. Profiles (INSP-37): a pack can hold up to 32 named sets of mod ids (GET|POST /api/games/<uuid>/mods/profiles,DELETE …/profiles/<id>);POST …/profiles/<id>/activateis the one-click enable set — the profile's rows on, every other row off,active_profileremembered — which is exactly what the companion's next Apply mods stages.GET …/profiles/<id>/exportreturns anod-mod:code (base64url JSON: name, default loader, and each mod's name / version / loader / source page — never a file);POST …/profiles/import {code}creates the profile on this game from what it already tracks (matched by id, then bysource_url) and returns the rest asmissing— nothing is invented. Members can read and copy codes; writes are librarian. Compat and freshness (INSP-38/39): a row may listrequires(ids of rows that must be staged first; unknown ids are pruned on read) andlatest_seen_version.GET …/modsalso returnsloader_conflicts— enabled rows whoseloaderdisagrees with the packdefault_loader(both set, neithermanual/none); the panel says so and the companion refuses to apply that set until the rows or the default agree. The catalogue drawer marks hits the pack already tracks (tracked_id, by source URL) and, when the registry's version differs,update_available; Mark updated to vX is an ordinary row write. Thunderstore hits carrydependencies(package names) and Add with N needed files them first, then the hit pointing at them. The companion refuses an empty or short download (Content-Lengthmismatch) before writing it, and re-stages fromsource_urlon the next apply — that is the integrity repair.- Game servers — admin CRUD at
/api/game-servers; members/children read join info only. Ops summaryservices.game_serversincludes TCP/HTTP health chips; per-server status:GET /api/game-servers/<uuid>/status.
Related: libraries-and-scans.md · docker-compose-deploy.md · oidc-sso.md · troubleshooting.md
- API:
GET/POST /api/tokens,DELETE /api/tokens/{id}— any logged-in member. - Presets:
POSTbody"preset": "companion"(read:library+write:download) or"preset": "thin"(read:library+read:social+write:presence; no download). List response includesscope_presets. - Thin protocol: heartbeat accepts
device_kind(companion|thin|browser);GET /api/client/capabilitiesadvertises allows/denies. Install/update command queue delivers only tocompanion+ download/lifecycle scopes. - UI: member SPA Account → API tokens (
/tokens) — create with companion/thin presets, copy one-time secret, revoke. API /@oneirodex/api-client/ OpenAPI still work. See desktop-companion.md · thin-client.md.