steps/<key>.felhom.yml: gate rule 4b, writer, backfill (8) (R-664)
gates / gates (push) Successful in 2s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-09-24 11:45:34 +02:00
parent 635c7e68f7
commit cf7cf8456f
15 changed files with 1321 additions and 2 deletions
+13
View File
@@ -1,3 +1,16 @@
## Every step keeps its own `.felhom.yml` (2026-09-24 night, R-664)
**No `image:` line moved.** Controller v0.269.0 reads them.
- `steps/<step_key(to)>.felhom.yml` beside every step's compose: the box judges a step with ITS probe, memory
request and applied record, not the head's. `ladder.step_meta_file`, `ladder.strip_ladder_block` (a step's copy
carries no ladder).
- **Gate rule 4b:** a step without its `.felhom.yml`, or one without a healthcheck while the template has one, is
refused. Decoys: the file missing; a file with the right NAME and no healthcheck (red-proof: rule off → both pass
wrongly). Suite 86 cases OK.
- **Writer:** `--write-ladder` also keeps the superseded step's `.felhom.yml`. **Backfill** (`steps_meta_backfill.py`,
one-off): 8 files, each from the newest commit whose compose names that step's images.
## Every step keeps its own definition — the box can climb one step at a time (2026-09-24, `09` §6.4 part 5, R-653, R-656, R-663)
**No `image:` line moved.** The box half ships in controller v0.268.0.
+9
View File
@@ -22,6 +22,8 @@ WHAT IT CHECKS, per template that carries `update_ladder:` (format and field rul
4. every entry but the newest carries its OWN definition at `steps/<step_key(to)>.yml`, whose
images per service are EXACTLY that entry's `to` (`09` §6.4 part 5: the box pins that file, one
step per press). The name alone is not the fact: the file's own `image:` lines are read.
4b. ... and its own `.felhom.yml` at `steps/<step_key(to)>.felhom.yml` (R-664), with a healthcheck
when the template has one.
A template WITHOUT a ladder passes here — it has never been moved since the gate existed, and its
first move is refused by the twin unless that move brings the first entry.
@@ -65,6 +67,13 @@ def check_app(app_dir):
got = ladder.images_in(open(sp, encoding="utf-8").read())
if got != to:
problems.append("%s names %s, but entry %d's `to` is %s" % (ladder.step_file(to), got, i + 1, to))
# rule 4b (R-664, 2026-09-24): the step's own .felhom.yml — the box judges the step with it.
smp = os.path.join(app_dir, ladder.step_meta_file(to))
if not os.path.isfile(smp):
problems.append("entry %d of %d has no %s — the box would judge the step with the head's probe (R-664)"
% (i + 1, len(entries), ladder.step_meta_file(to)))
elif "healthcheck:" not in open(smp, encoding="utf-8").read() and "healthcheck:" in open(os.path.join(app_dir, ".felhom.yml"), encoding="utf-8").read():
problems.append("%s carries no healthcheck: while the template does — not a real step file" % ladder.step_meta_file(to))
if entries:
current = ladder.images_in(open(comp, encoding="utf-8").read())
head = entries[-1].get("to")
+16
View File
@@ -210,3 +210,19 @@ def step_key(to):
def step_file(to):
"""The step definition's path RELATIVE to the template directory."""
return "steps/%s.yml" % step_key(to)
def step_meta_file(to):
"""The step's own `.felhom.yml` (R-664, 2026-09-24): its probe, memory limits and applied record — the
box judges the step with it. RELATIVE to the template directory."""
return "steps/%s.felhom.yml" % step_key(to)
def strip_ladder_block(felhom_text):
"""A `.felhom.yml` without its update_ladder block (and the header comment the writer puts above it):
a step's own copy carries no ladder — only the template's is read for one."""
lines = felhom_text.splitlines()
for i, l in enumerate(lines):
if l.startswith("# update_ladder") or l.startswith("update_ladder:"):
return "\n".join(lines[:i]).rstrip("\n") + "\n"
return felhom_text
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env python3
"""steps_meta_backfill.py — ONE-OFF (2026-09-24 night, R-664): write `steps/<key>.felhom.yml` beside every step
file, from the NEWEST commit whose compose names that step's images — the .felhom.yml served WITH that
definition — without its update_ladder block. Never overwrites."""
import os, subprocess, sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import ladder # noqa: E402
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
def git(*a):
return subprocess.run(["git", "-C", ROOT] + list(a), capture_output=True, text=True, check=True).stdout
def main():
n = 0
for app in sorted(os.listdir(os.path.join(ROOT, "templates"))):
d = os.path.join(ROOT, "templates", app)
fy = os.path.join(d, ".felhom.yml")
if not os.path.isfile(fy):
continue
entries, _, errs = ladder.parse(open(fy, encoding="utf-8").read())
if errs or len(entries) < 2:
continue
commits = git("log", "--format=%H", "--", "templates/%s" % app).split()
for i, e in enumerate(entries[:-1]):
dst = os.path.join(d, ladder.step_meta_file(e["to"]))
if os.path.exists(dst):
continue
for c in commits:
try:
comp = git("show", "%s:templates/%s/docker-compose.yml" % (c, app))
except subprocess.CalledProcessError:
continue
if ladder.images_in(comp) == e["to"]:
meta = git("show", "%s:templates/%s/.felhom.yml" % (c, app))
open(dst, "w", encoding="utf-8").write(ladder.strip_ladder_block(meta))
print("WROTE %-10s entry %d -> %s from %s" % (app, i + 1, ladder.step_meta_file(e["to"]), c[:12]))
n += 1
break
else:
print("MISS %-10s entry %d" % (app, i + 1))
print("steps_meta_backfill: %d written" % n)
if __name__ == "__main__":
main()
+9 -2
View File
@@ -437,16 +437,23 @@ def test_record_cases(clone):
two = ladder_of(tr_entry({"navidrome": prev}, mid, {"navidrome": TR_D1}),
tr_entry(mid, frm, {"navidrome": TR_D1}))
step_rel = "templates/navidrome/" + _l.step_file(mid)
meta_rel = "templates/navidrome/" + _l.step_meta_file(mid)
meta_body = lambda t: _l.strip_ladder_block(io.open(os.path.join(clone, NF), encoding="utf-8").read())
step_body = lambda t: swap_image("navidrome", old, mid["navidrome"])(io.open(os.path.join(clone, NC), encoding="utf-8").read())
case_tr_static("FACT: a two-step ladder with NO steps/ file for the first step", clone,
[(NF, two)], 1, ("has no definition",))
case_tr_static("GENUINE: a two-step ladder whose first step carries its definition", clone,
[(NF, two), (step_rel, step_body)], 0)
[(NF, two), (step_rel, step_body), (meta_rel, meta_body)], 0)
case_tr_static("DECOY: the steps/ file has the right NAME and names the head's image", clone,
[(NF, two), (step_rel, lambda t: io.open(os.path.join(clone, NC), encoding="utf-8").read())],
[(NF, two), (step_rel, lambda t: io.open(os.path.join(clone, NC), encoding="utf-8").read()), (meta_rel, meta_body)],
1, ("names",))
case_tr_static("DECOY: the step's definition sits beside the template under another name", clone,
[(NF, two), ("templates/navidrome/steps/0.2.0.yml", step_body)], 1, ("has no definition",))
# R-664: the step's own .felhom.yml
case_tr_static("FACT: the step has its compose but no .felhom.yml", clone,
[(NF, two), (step_rel, step_body)], 1, ("R-664",))
case_tr_static("DECOY: the step's .felhom.yml exists by NAME and holds no healthcheck", clone,
[(NF, two), (step_rel, step_body), (meta_rel, lambda t: "display_name: Navidrome\n")], 1, ("not a real step file",))
def main():
gate = os.path.join(ROOT, "scripts", "check-engine-major.py")
+3
View File
@@ -122,6 +122,9 @@ class WriterTest(unittest.TestCase):
sp = os.path.join(self.tmp, "templates", "navidrome", ladder.step_file({"navidrome": "deluan/navidrome:" + NEXT}))
self.assertTrue(os.path.isfile(sp), out)
self.assertEqual(open(sp).read(), at_step1, "the step file must be the definition AS SERVED, fixes included")
smp = os.path.join(self.tmp, "templates", "navidrome", ladder.step_meta_file({"navidrome": "deluan/navidrome:" + NEXT}))
self.assertTrue(os.path.isfile(smp), "the step's own .felhom.yml (R-664) was not written")
self.assertNotIn("update_ladder:", open(smp).read())
import subprocess
r = subprocess.run([sys.executable, os.path.join(HERE, "check-test-record.py"), "--root", self.tmp,
"navidrome"], capture_output=True, text=True)
+4
View File
@@ -832,6 +832,10 @@ def write_ladder(argv) -> int:
sp.parent.mkdir(parents=True, exist_ok=True)
sp.write_text(comp)
print(f"STEP {app}: the superseded step {cur} keeps its definition at {ladder.step_file(cur)}")
smp = tdir / ladder.step_meta_file(cur)
if not smp.exists(): # R-664: and its own .felhom.yml, without the ladder
smp.write_text(ladder.strip_ladder_block(fy_p.read_text()))
print(f"STEP {app}: … and its .felhom.yml at {ladder.step_meta_file(cur)}")
# move the compose, per service, on that service's own image: line
out, svc = [], None
for line in comp.splitlines():
@@ -0,0 +1,119 @@
# =============================================================================
# .felhom.yml - App metadata for felhom-controller
# =============================================================================
# --- Display info (shown on dashboard) ---
display_name: "Emby"
description: "Személyes média szerver élő TV és DVR támogatással"
category: "media"
subdomain: "emby"
slug: "emby"
# catalog_since: the date THIS repo last changed this app's pinned images. Any commit that
# changes an image: line must set this to the same day (see CLAUDE.md).
catalog_since: "2026-09-22"
# --- Resource hints (displayed on deploy screen) ---
resources:
mem_request: "512M"
mem_limit: "2048M"
pi_compatible: false
needs_hdd: true
# --- Backup classification (referential coupling; see felhom.eu documentation/audits/SPIKE-backup-classification-2026-07-14.md) ---
backup:
userdata:
- path: media
class: excluded # pure reader of the shared tree (:ro); state lives in volumes
# --- Deploy fields (first deployment only) ---
deploy_fields:
- env_var: DOMAIN
label: "Domain"
type: domain
description: "A szerver domain neve"
locked_after_deploy: true
- env_var: SUBDOMAIN
label: "Aldomain"
type: subdomain
default: "emby"
required: true
locked_after_deploy: true
description: "Az alkalmazás aldomainje"
- env_var: HDD_PATH
label: "Médiatár útvonal"
type: path
required: true
placeholder: "/mnt/felhom-drives/hdd_1"
description: "A külső merevlemez elérési útja"
locked_after_deploy: true
# --- App info (info page content) ---
app_info:
tagline: "Személyes média szerver élő TV és DVR támogatással"
docs_url: "https://emby.media/support/articles/Home.html"
use_cases:
- 'Filmek, sorozatok, zene és fotók kezelése egy helyen'
- 'Élő TV nézés és felvétel (DVR) TV tunerrel'
- 'Automatikus transzkódolás bármilyen eszközhöz'
- 'Szülői felügyelet és felhasználói profilok'
- 'Szinkronizálás offline megtekintéshez mobilon'
first_steps:
- 'Nyisd meg az emby.DOMAIN címet a böngészőben'
- 'Kövesd a beállítás varázslót'
- 'Hozd létre az admin fiókot'
- 'Add hozzá a médiatárat a /media mappából'
- 'Telepítsd az Emby alkalmazást eszközeidre'
prerequisites:
- 'Külső HDD szükséges a médiafájlok tárolásához'
- 'Legalább 2 GB szabad RAM ajánlott'
- 'Emby Premiere előfizetés a prémium funkciókhoz (opcionális)'
# --- Controller-side health probe ---
healthcheck:
checks:
- type: api
port: 8096
path: "/emby/system/ping"
expect:
status: 200
# --- English copy (localisation slice 5, R-560) --------------------------------------------
# The Hungarian above is UNCHANGED. A box on English reads this block field by field; a missing
# field shows the Hungarian one; a controller older than 0.257.0 ignores the block entirely.
i18n:
en:
description: 'A personal media server with live TV and recording'
app_info:
tagline: 'A personal media server with live TV and recording'
use_cases:
- 'Films, series, music and photos in one place'
- 'Watch and record live TV, with a TV tuner'
- 'It re-encodes on the fly for whatever device you are on'
- 'Parental controls and a profile for each person'
- 'Sync to a phone to watch offline'
first_steps:
- 'Open emby.DOMAIN in your browser'
- 'Follow the setup wizard'
- 'Create the admin account'
- 'Add your library from the /media folder'
- 'Install the Emby app on your devices'
prerequisites:
- 'An external hard drive is needed to keep the media files on'
- 'At least 2 GB of free RAM is recommended'
- 'An Emby Premiere subscription for the premium features (optional)'
deploy_fields:
- env_var: DOMAIN
label: 'Domain'
description: 'The server domain name'
- env_var: SUBDOMAIN
label: 'Subdomain'
description: 'The subdomain this app answers on'
- env_var: HDD_PATH
label: 'Media library path'
description: 'The path to the external hard drive'
placeholder: '/mnt/felhom-drives/hdd_1'
@@ -0,0 +1,94 @@
# =============================================================================
# .felhom.yml - App metadata for felhom-controller
# =============================================================================
# --- Display info (shown on dashboard) ---
display_name: "Ghost"
description: "Professzionális blog és hírlevél platform"
category: "productivity"
subdomain: "blog"
slug: "ghost"
# catalog_since: the date THIS repo last changed this app's pinned images. Any commit that
# changes an image: line must set this to the same day (see CLAUDE.md).
catalog_since: "2026-09-22"
# Bare "/" is the public blog; the admin panel / setup wizard lives at /ghost/.
open_path: "/ghost/"
# --- Resource hints (displayed on deploy screen) ---
resources:
mem_request: "150M"
mem_limit: "512M"
pi_compatible: false
needs_hdd: false
# --- Deploy fields (first deployment only) ---
deploy_fields:
- env_var: DOMAIN
label: "Domain"
type: domain
description: "A szerver domain neve"
locked_after_deploy: true
- env_var: SUBDOMAIN
label: "Aldomain"
type: subdomain
default: "blog"
required: true
locked_after_deploy: true
description: "Az alkalmazás aldomainje"
# --- App info (info page content) ---
app_info:
tagline: "Professzionális blog és hírlevél platform"
docs_url: "https://ghost.org/docs/"
use_cases:
- 'Professzionális blog indítása és üzemeltetése'
- 'Hírlevél küldés beépített email funkcióval'
- 'SEO-optimalizált tartalom publikálás'
- 'Tagság és fizetős tartalom kezelés'
- 'Markdown és vizuális szerkesztő'
first_steps:
- 'Nyisd meg a blog.DOMAIN/ghost/ címet a böngészőben'
- 'Hozd létre az admin fiókot a beállítás varázslóban'
- 'Írd meg és publikáld az első posztodat'
- 'Személyre szabd a témát és beállításokat'
prerequisites:
- 'x86 processzor szükséges'
# --- Controller-side health probe ---
healthcheck:
checks:
- type: http
port: 2368
# --- English copy (localisation slice 5, R-560) --------------------------------------------
# The Hungarian above is UNCHANGED. A box on English reads this block field by field; a missing
# field shows the Hungarian one; a controller older than 0.257.0 ignores the block entirely.
i18n:
en:
description: 'A professional blog and newsletter platform'
app_info:
tagline: 'A professional blog and newsletter platform'
use_cases:
- 'Start and run a professional blog'
- 'Send a newsletter with the built-in e-mail feature'
- 'Publish content that search engines can read'
- 'Memberships and paid content'
- 'A Markdown editor and a visual one'
first_steps:
- 'Open blog.DOMAIN/ghost/ in your browser'
- 'Create the admin account in the setup wizard'
- 'Write and publish your first post'
- 'Make the theme and the settings your own'
prerequisites:
- 'An x86 processor is needed'
deploy_fields:
- env_var: DOMAIN
label: 'Domain'
description: 'The server domain name'
- env_var: SUBDOMAIN
label: 'Subdomain'
description: 'The subdomain this app answers on'
@@ -0,0 +1,144 @@
# =============================================================================
# .felhom.yml — App metadata for felhom-controller
# =============================================================================
# Place alongside docker-compose.yml in each stack directory:
# /opt/docker/stacks/immich/.felhom.yml
# =============================================================================
# --- Display info (shown on dashboard) ---
display_name: "Immich"
description: "Fotók és videók kezelése (Google Photos alternatíva)"
category: "media"
subdomain: "photos"
# --- Asset slug ---
slug: "immich"
# catalog_since: the date THIS repo last changed this app's pinned images. Any commit that
# changes an image: line must set this to the same day (see CLAUDE.md).
catalog_since: "2026-09-22"
# --- Resource hints (displayed on deploy screen) ---
resources:
mem_request: "2048M"
mem_limit: "4096M"
pi_compatible: false
needs_hdd: true
# --- Backup classification (referential coupling; see felhom.eu documentation/audits/SPIKE-backup-classification-2026-07-14.md) ---
backup:
hdd:
- path: appdata/immich
class: mandatory # managed upload library — DB-referenced (SQ3: restore-without = broken)
userdata:
- path: media/photos
class: optional # external library, :ro — precious but re-scanned (explicit overrides ro-default)
# --- Deploy fields ---
deploy_fields:
- env_var: DOMAIN
label: "Domain"
type: domain
description: "A szerver domain neve"
locked_after_deploy: true
- env_var: SUBDOMAIN
label: "Aldomain"
type: subdomain
default: "photos"
required: true
locked_after_deploy: true
description: "Az alkalmazás aldomainje"
- env_var: DB_PASSWORD
label: "Adatbázis jelszó"
type: secret
generate: "password:24"
locked_after_deploy: true
- env_var: HDD_PATH
label: "Adattárolási útvonal"
type: path
required: true
placeholder: "/mnt/felhom-drives/hdd_1"
description: "A külső merevlemez elérési útja, ahol a fotók és videók tárolódnak"
locked_after_deploy: true
# --- App info (info page content) ---
app_info:
tagline: 'Google Photos alternatíva - automatikus fotó mentés és rendszerezés'
docs_url: 'https://immich.app/docs/overview/introduction'
use_cases:
- 'Fotók és videók automatikus mentése telefonról'
- 'Arc- és tárgyfelismerés gépi tanulással'
- 'Térképes megjelenítés helyszín alapján'
- 'Emlékek és visszatekintések automatikus generálása'
- 'Albumok létrehozása és megosztása családtagokkal'
first_steps:
- 'Nyisd meg a photos.DOMAIN címet a böngészőben'
- 'Hozd létre az admin fiókot'
- 'Telepítsd az Immich alkalmazást a telefonodra (Android/iOS)'
- 'Állítsd be az automatikus feltöltést az alkalmazásban'
- 'Hívd meg a családtagokat külön fiókokkal'
# MOUNT-READY, REGISTRATION PENDING: a megosztott média/photos mappa be van csatolva
# /external/photos néven (csak olvasható), de az Immich CSAK akkor látja, ha az
# adminfelületen (Administration → External Libraries) regisztrálod a /external/photos
# útvonalat. Compose ezt NEM teszi meg automatikusan — ez egy telepítés utáni lépés.
- 'Külső könyvtár (opcionális): Administration → External Libraries → add /external/photos'
prerequisites:
- 'Külső HDD szükséges a fotók és videók tárolásához'
- 'Legalább 4 GB szabad RAM ajánlott (gépi tanulás funkciókhoz)'
- 'x86 processzor szükséges (nem fut Raspberry Pi-n)'
# --- Controller-side health probe ---
healthcheck:
# container: no exact match and FOUR `immich-*` containers, so the old prefix rule picked whichever the
# container list happened to yield first — it could have been `immich-postgres` (R-630)
container: immich-server
checks:
- type: api
port: 2283
path: "/api/server/ping"
expect:
status: 200
# --- English copy (localisation slice 5, R-560) --------------------------------------------
# The Hungarian above is UNCHANGED. A box on English reads this block field by field; a missing
# field shows the Hungarian one; a controller older than 0.257.0 ignores the block entirely.
i18n:
en:
description: 'Photos and videos in one place (a Google Photos alternative)'
app_info:
tagline: 'A Google Photos alternative - your photos back themselves up and sort themselves'
use_cases:
- 'Photos and videos back themselves up from your phone'
- 'It recognises faces and objects on its own'
- 'See where a photo was taken, on a map'
- 'Memories and look-backs, put together for you'
- 'Build albums and share them with the household'
first_steps:
- 'Open photos.DOMAIN in your browser'
- 'Create the admin account'
- 'Install the Immich app on your phone (Android/iOS)'
- 'Turn on automatic upload in the app'
- 'Invite the household, each with their own account'
- 'An external library (optional): Administration -> External Libraries -> add /external/photos'
prerequisites:
- 'An external hard drive is needed to keep the photos and videos on'
- 'At least 4 GB of free RAM is recommended (for the machine learning features)'
- 'An x86 processor is needed (it does not run on a Raspberry Pi)'
deploy_fields:
- env_var: DOMAIN
label: 'Domain'
description: 'The server domain name'
- env_var: SUBDOMAIN
label: 'Subdomain'
description: 'The subdomain this app answers on'
- env_var: DB_PASSWORD
label: 'Database password'
- env_var: HDD_PATH
label: 'Data storage path'
description: 'The path to the external hard drive where the photos and videos are kept'
placeholder: '/mnt/felhom-drives/hdd_1'
@@ -0,0 +1,103 @@
# =============================================================================
# .felhom.yml - App metadata for felhom-controller
# =============================================================================
# --- Display info (shown on dashboard) ---
display_name: "n8n"
description: "Workflow automatizálás vizuális szerkesztővel"
category: "productivity"
subdomain: "auto"
slug: "n8n"
# catalog_since: the date THIS repo last changed this app's pinned images. Any commit that
# changes an image: line must set this to the same day (see CLAUDE.md).
catalog_since: "2026-09-22"
# --- Resource hints (displayed on deploy screen) ---
resources:
mem_request: "512M"
mem_limit: "1536M"
pi_compatible: false
needs_hdd: false
# --- Deploy fields (first deployment only) ---
deploy_fields:
- env_var: DOMAIN
label: "Domain"
type: domain
description: "A szerver domain neve"
locked_after_deploy: true
- env_var: SUBDOMAIN
label: "Aldomain"
type: subdomain
default: "auto"
required: true
locked_after_deploy: true
description: "Az alkalmazás aldomainje"
- env_var: N8N_ENCRYPTION_KEY
label: "Titkosítási kulcs"
type: secret
generate: "hex:16"
locked_after_deploy: true
# --- App info (info page content) ---
app_info:
tagline: "Vizuális workflow automatizálás - Zapier/IFTTT alternatíva"
docs_url: "https://docs.n8n.io/"
use_cases:
- 'Alkalmazások összekapcsolása vizuális workflow szerkesztővel'
- 'Automatizálás: email, Telegram, webhook, fájl feldolgozás'
- '400+ integráció (Google, Slack, Notion, GitHub, stb.)'
- 'Időzített feladatok (cron) és webhook triggerek'
- 'AI munkafolyamatok LLM integrációval'
first_steps:
- 'Nyisd meg az auto.DOMAIN címet a böngészőben'
- 'Hozd létre az admin fiókot'
- 'Próbálj ki egy sablon workflow-t a Template galériából'
- 'Hozd létre az első saját munkafolyamatot'
prerequisites:
- 'x86 processzor szükséges'
# --- Controller-side health probe ---
healthcheck:
checks:
- type: api
port: 5678
path: "/healthz"
expect:
status: 200
# --- English copy (localisation slice 5, R-560) --------------------------------------------
# The Hungarian above is UNCHANGED. A box on English reads this block field by field; a missing
# field shows the Hungarian one; a controller older than 0.257.0 ignores the block entirely.
i18n:
en:
description: 'Workflow automation with a visual editor'
app_info:
tagline: 'Visual workflow automation - a Zapier/IFTTT alternative'
use_cases:
- 'Wire apps together in a visual workflow editor'
- 'Automate e-mail, Telegram, webhooks and file handling'
- '400+ integrations (Google, Slack, Notion, GitHub and more)'
- 'Scheduled jobs (cron) and webhook triggers'
- 'AI workflows with an LLM in them'
first_steps:
- 'Open auto.DOMAIN in your browser'
- 'Create the admin account'
- 'Try a ready-made workflow from the Template gallery'
- 'Build your first workflow of your own'
prerequisites:
- 'An x86 processor is needed'
deploy_fields:
- env_var: DOMAIN
label: 'Domain'
description: 'The server domain name'
- env_var: SUBDOMAIN
label: 'Subdomain'
description: 'The subdomain this app answers on'
- env_var: N8N_ENCRYPTION_KEY
label: 'Encryption key'
@@ -0,0 +1,117 @@
# =============================================================================
# .felhom.yml - App metadata for felhom-controller
# =============================================================================
# --- Display info (shown on dashboard) ---
display_name: "Navidrome"
description: "Könnyű zene szerver Subsonic API támogatással"
category: "media"
subdomain: "music"
slug: "navidrome"
# catalog_since: the date THIS repo last changed this app's pinned images. Any commit that
# changes an image: line must set this to the same day (see CLAUDE.md).
catalog_since: "2026-09-22"
# --- Resource hints (displayed on deploy screen) ---
resources:
mem_request: "50M"
mem_limit: "256M"
pi_compatible: true
needs_hdd: true
# --- Backup classification (referential coupling; see felhom.eu documentation/audits/SPIKE-backup-classification-2026-07-14.md) ---
backup:
userdata:
- path: media/music
class: excluded # re-rippable bulk, :ro, shared tree
# --- Deploy fields (first deployment only) ---
deploy_fields:
- env_var: DOMAIN
label: "Domain"
type: domain
description: "A szerver domain neve"
locked_after_deploy: true
- env_var: SUBDOMAIN
label: "Aldomain"
type: subdomain
default: "music"
required: true
locked_after_deploy: true
description: "Az alkalmazás aldomainje"
- env_var: HDD_PATH
label: "Zenegyűjtemény útvonal"
type: path
required: true
placeholder: "/mnt/felhom-drives/hdd_1"
description: "A külső merevlemez elérési útja, ahol a zenefájlok tárolódnak"
locked_after_deploy: true
# --- App info (info page content) ---
app_info:
tagline: "Könnyű zene szerver - streameld a saját zenegyűjteményedet"
docs_url: "https://www.navidrome.org/docs/"
use_cases:
- 'Saját zenegyűjtemény streamelése bármilyen eszközről'
- 'Subsonic API kompatibilis mobil alkalmazások használata'
- 'Lejátszási listák, kedvencek és értékelések kezelése'
- 'Automatikus metaadat és borítókép letöltés'
- 'Több felhasználó külön könyvtárral és beállításokkal'
first_steps:
- 'Nyisd meg a music.DOMAIN címet a böngészőben'
- 'Az első felhasználó automatikusan admin lesz'
- 'Hozd létre a fiókodat és várd meg az első szkennelést'
- 'Telepíts Subsonic-kompatibilis alkalmazást (pl. Subtracks, play:Sub)'
- 'Add meg a szerver címet: https://music.DOMAIN'
prerequisites:
- 'Külső HDD szükséges a zenefájlok tárolásához'
- 'Zenefájlok mappákba rendezve (pl. Előadó/Album/szám.flac)'
# --- Controller-side health probe ---
healthcheck:
checks:
- type: api
port: 4533
path: "/ping"
expect:
status: 200
# --- English copy (localisation slice 5, R-560) --------------------------------------------
# The Hungarian above is UNCHANGED. A box on English reads this block field by field; a missing
# field shows the Hungarian one; a controller older than 0.257.0 ignores the block entirely.
i18n:
en:
description: 'A light music server with Subsonic API support'
app_info:
tagline: 'A light music server - stream your own music collection'
use_cases:
- 'Stream your own music collection to any device'
- 'Use any Subsonic-compatible phone app'
- 'Playlists, favourites and ratings'
- 'Details and cover art arrive on their own'
- 'Several people, each with their own library and settings'
first_steps:
- 'Open music.DOMAIN in your browser'
- 'The first user becomes the admin automatically'
- 'Create your account and wait for the first scan'
- 'Install a Subsonic-compatible app (Subtracks or play:Sub, for example)'
- 'Give it the server address: https://music.DOMAIN'
prerequisites:
- 'An external hard drive is needed to keep the music files on'
- 'Music files sorted into folders (Artist/Album/track.flac, for example)'
deploy_fields:
- env_var: DOMAIN
label: 'Domain'
description: 'The server domain name'
- env_var: SUBDOMAIN
label: 'Subdomain'
description: 'The subdomain this app answers on'
- env_var: HDD_PATH
label: 'Music collection path'
description: 'The path to the external hard drive where the music files are kept'
placeholder: '/mnt/felhom-drives/hdd_1'
@@ -0,0 +1,171 @@
# =============================================================================
# .felhom.yml - App metadata for felhom-controller
# =============================================================================
# --- Display info (shown on dashboard) ---
display_name: "Nextcloud"
description: "Saját felhő tárhely - Google Drive/Dropbox alternatíva"
category: "files"
subdomain: "cloud"
slug: "nextcloud"
# catalog_since: the date THIS repo last changed this app's pinned images. Any commit that
# changes an image: line must set this to the same day (see CLAUDE.md).
catalog_since: "2026-09-22"
# --- Resource hints (displayed on deploy screen) ---
resources:
mem_request: "256M"
mem_limit: "1024M"
pi_compatible: false
needs_hdd: true
# --- Backup classification (referential coupling; see felhom.eu documentation/audits/SPIKE-backup-classification-2026-07-14.md) ---
backup:
hdd:
- path: appdata/nextcloud
class: mandatory # THE user files — oc_filecache/shares reference them
# --- Deploy fields (first deployment only) ---
deploy_fields:
- env_var: DOMAIN
label: "Domain"
type: domain
description: "A szerver domain neve"
locked_after_deploy: true
- env_var: SUBDOMAIN
label: "Aldomain"
type: subdomain
default: "cloud"
required: true
locked_after_deploy: true
description: "Az alkalmazás aldomainje"
- env_var: DB_PASSWORD
label: "Adatbázis jelszó"
type: secret
generate: "password:24"
locked_after_deploy: true
- env_var: MYSQL_ROOT_PASSWORD
label: "MariaDB root jelszó"
type: secret
generate: "password:24"
locked_after_deploy: true
- env_var: NEXTCLOUD_ADMIN_USER
label: "Admin felhasználónév"
type: text
default: "admin"
locked_after_deploy: true
- env_var: NEXTCLOUD_ADMIN_PASSWORD
label: "Admin jelszó"
type: password
generate: "password:16"
description: "Első bejelentkezéshez. Utána a webes felületen módosítható."
locked_after_deploy: false
- env_var: HDD_PATH
label: "Adattárolási útvonal"
type: path
required: true
placeholder: "/mnt/felhom-drives/hdd_1"
description: "A külső merevlemez elérési útja"
locked_after_deploy: true
# --- App info (info page content) ---
app_info:
tagline: "A saját Google Drive-od - fájlok, naptár, névjegyek egy helyen"
default_creds: "Az admin fiók adatait a telepítéskor adod meg"
docs_url: "https://docs.nextcloud.com/server/latest/user_manual/"
use_cases:
- 'Fájlok szinkronizálása és megosztása eszközök között'
- 'Naptár és névjegyek szinkronizálás (CalDAV/CardDAV)'
- 'Dokumentumok közös szerkesztése (OnlyOffice integrációval)'
- 'Fotó és videó automatikus feltöltés telefonról'
- 'Alkalmazásbolt - kibővíthető funkciók (Notes, Tasks, Forms, stb.)'
first_steps:
- 'Nyisd meg a cloud.DOMAIN címet a böngészőben'
- 'Jelentkezz be a telepítéskor megadott admin fiókkal'
- 'Telepítsd a Nextcloud asztali alkalmazást a számítógépedre'
- 'Telepítsd a Nextcloud mobil alkalmazást a telefonodra'
- 'Hívd meg a családtagokat felhasználói fiókok létrehozásával'
prerequisites:
- 'Külső HDD szükséges a fájlok tárolásához'
- 'Legalább 1 GB szabad RAM (Nextcloud + MariaDB + Redis)'
- 'x86 processzor ajánlott a legjobb teljesítményhez'
# --- Controller-side health probe ---
healthcheck:
checks:
- type: api
port: 80
path: "/status.php"
expect:
status: 200
body_contains: "installed"
# --- App-email mapping (apps → in-controller shim → hub → Resend) ---
# Nextcloud (Symfony Mailer) has no env to skip TLS cert verification and opportunistically STARTTLS-upgrades,
# so it can't use the self-signed :2525 listener → tls_mode=plaintext points it at :2526 (STARTTLS NOT
# advertised → no upgrade attempted; plaintext on the single-tenant app bridge — accepted posture).
# Nextcloud SPLITS the From into local-part + domain, so from_var=MAIL_FROM_ADDRESS (local) +
# from_domain_var=MAIL_DOMAIN → nextcloud@felhom.eu. No security_var (SMTP_SECURE stays empty = no TLS);
# SMTP_NAME/PASSWORD unset (no auth). The official image reads these via getenv() on every boot.
smtp_mapping:
tls_mode: plaintext
host_var: SMTP_HOST
port_var: SMTP_PORT
from_var: MAIL_FROM_ADDRESS
from_domain_var: MAIL_DOMAIN
from_local: nextcloud
# --- English copy (localisation slice 5, R-560) --------------------------------------------
# The Hungarian above is UNCHANGED. A box on English reads this block field by field; a missing
# field shows the Hungarian one; a controller older than 0.257.0 ignores the block entirely.
i18n:
en:
description: 'Your own cloud storage - a Google Drive/Dropbox alternative'
app_info:
tagline: 'Your own Google Drive - files, calendar and contacts in one place'
default_creds: 'You set the admin account details at install time'
use_cases:
- 'Sync and share files between your devices'
- 'Calendar and contact sync (CalDAV/CardDAV)'
- 'Work on a document together (with the OnlyOffice integration)'
- 'Photos and videos upload themselves from your phone'
- 'An app store - more features when you want them (Notes, Tasks, Forms and more)'
first_steps:
- 'Open cloud.DOMAIN in your browser'
- 'Sign in with the admin account you set at install time'
- 'Install the Nextcloud desktop app on your computer'
- 'Install the Nextcloud mobile app on your phone'
- 'Invite the household by creating an account for each of them'
prerequisites:
- 'An external hard drive is needed to keep the files on'
- 'At least 1 GB of free RAM (Nextcloud + MariaDB + Redis)'
- 'An x86 processor is recommended for the best speed'
deploy_fields:
- env_var: DOMAIN
label: 'Domain'
description: 'The server domain name'
- env_var: SUBDOMAIN
label: 'Subdomain'
description: 'The subdomain this app answers on'
- env_var: DB_PASSWORD
label: 'Database password'
- env_var: HDD_PATH
label: 'Data storage path'
description: 'The path to the external hard drive'
placeholder: '/mnt/felhom-drives/hdd_1'
- env_var: MYSQL_ROOT_PASSWORD
label: 'MariaDB root password'
- env_var: NEXTCLOUD_ADMIN_USER
label: 'Admin user name'
- env_var: NEXTCLOUD_ADMIN_PASSWORD
label: 'Admin password'
description: 'For the first sign-in. You can change it in the app afterwards.'
@@ -0,0 +1,236 @@
# =============================================================================
# .felhom.yml — App metadata for felhom-controller
# =============================================================================
# --- Display info (shown on dashboard) ---
display_name: "RomM"
description: "Retró játékgyűjtemény kezelő"
category: "media"
subdomain: "arcade"
slug: "romm"
# catalog_since: the date THIS repo last changed this app's pinned images. Any commit that
# changes an image: line must set this to the same day (see CLAUDE.md).
catalog_since: "2026-09-22"
# --- Resource hints (displayed on deploy screen) ---
resources:
mem_request: "300M"
mem_limit: "1280M"
pi_compatible: false
needs_hdd: true
# --- Backup classification (referential coupling; see felhom.eu documentation/audits/SPIKE-backup-classification-2026-07-14.md) ---
backup:
userdata:
- path: roms
class: optional # ruled: curated ROM sets often not re-acquirable
hdd:
- path: appdata/romm/resources
class: excluded # scraper cache, re-derivable
# --- Customer-facing folder annotation (R-75) ---
data_paths:
- path: roms
root: userdata
role: library
label: "ROM gyűjtemény"
# --- Deploy fields (first deployment only) ---
deploy_fields:
- env_var: DOMAIN
label: "Domain"
type: domain
description: "A szerver domain neve"
locked_after_deploy: true
- env_var: SUBDOMAIN
label: "Aldomain"
type: subdomain
default: "arcade"
required: true
locked_after_deploy: true
description: "Az alkalmazás aldomainje"
- env_var: DB_PASSWORD
label: "Adatbázis jelszó"
type: secret
generate: "password:24"
locked_after_deploy: true
- env_var: MYSQL_ROOT_PASSWORD
label: "MariaDB root jelszó"
type: secret
generate: "password:24"
locked_after_deploy: true
- env_var: ROMM_AUTH_SECRET_KEY
label: "Hitelesítési titkosítási kulcs"
type: secret
generate: "hex:32"
locked_after_deploy: true
- env_var: HDD_PATH
label: "Adattárolási útvonal"
type: path
required: true
placeholder: "/mnt/felhom-drives/hdd_1"
description: "A külső merevlemez elérési útja, ahol a ROM-ok és borítóképek tárolódnak"
locked_after_deploy: true
# --- App info (info page content) ---
app_info:
tagline: "Retró játékgyűjtemény kezelő, böngésző és lejátszó"
default_creds: "admin / admin"
docs_url: "https://github.com/rommapp/romm/wiki"
use_cases:
- "Retró játékgyűjtemény rendszerezése és böngészése webes felületen"
- "Játékok metaadatainak automatikus letöltése — borítók, leírások, értékelések"
- "Platformonkénti szűrés és keresés a teljes gyűjteményben"
- "ROM fájlok webes feltöltése és letöltése"
- "Többfelhasználós hozzáférés a háztartás tagjai számára"
first_steps:
- "Nyisd meg az arcade.DOMAIN címet a böngészőben"
- "Jelentkezz be az alapértelmezett admin / admin fiókkal"
- "Változtasd meg azonnal a jelszót a Settings menüben"
- "Töltsd fel a ROM fájlokat a Fájlkezelőben (FileBrowser) a roms/ mappába, platform mappákba rendezve (pl. roms/gba/, roms/snes/)"
- "Indíts egy Scan-t a bal oldali menüben a ROM-ok beolvasásához"
- "Opcionális: állíts be metaadat-szolgáltatókat a borítóképek és leírások automatikus letöltéséhez (lásd lent)"
prerequisites:
- "Külső HDD szükséges a ROM fájlok és borítóképek tárolásához"
- "Legalább 1 GB szabad RAM ajánlott (MariaDB + Redis + RomM)"
- "ROM fájlok platform mappákba rendezve (pl. roms/gba/, roms/snes/)"
# --- Optional config (configurable before or after deployment) ---
optional_config:
- group: "Metaadat-szolgáltatók"
description: "Játékok borítóinak, leírásainak és értékeléseinek automatikus letöltéséhez. Legalább az IGDB beállítása ajánlott. Mindegyik ingyenesen használható regisztráció után."
fields:
- env_var: IGDB_CLIENT_ID
label: "IGDB Client ID"
type: text
help_url: "https://api-docs.igdb.com/#getting-started"
help_text: "1) Regisztrálj / jelentkezz be a Twitch fejlesztői portálon (dev.twitch.tv). 2) Hozz létre egy új alkalmazást (bármilyen névvel). 3) Másold be a Client ID-t."
- env_var: IGDB_CLIENT_SECRET
label: "IGDB Client Secret"
type: secret_input
help_text: "A Twitch alkalmazásod Client Secret-je (a „New Secret\" gombbal generálhatod)."
- env_var: STEAMGRIDDB_API_KEY
label: "SteamGridDB API Key"
type: text
help_url: "https://www.steamgriddb.com/profile/preferences/api"
help_text: "Regisztrálj a SteamGridDB oldalon, majd a Preferences → API fül alatt kattints a „Generate API key\" gombra."
- env_var: SCREENSCRAPER_USER
label: "ScreenScraper felhasználónév"
type: text
help_url: "https://www.screenscraper.fr/"
help_text: "Regisztrálj a screenscraper.fr oldalon. A felhasználóneved lesz az API felhasználónév."
- env_var: SCREENSCRAPER_PASSWORD
label: "ScreenScraper jelszó"
type: secret_input
help_text: "A screenscraper.fr fiókod jelszava."
- env_var: MOBYGAMES_API_KEY
label: "MobyGames API Key"
type: text
help_url: "https://www.mobygames.com/info/api/"
help_text: "Regisztrálj a MobyGames oldalon, majd az API oldalon igényelj kulcsot. Részletes játékinformációkat és krediteket biztosít."
# --- Controller-side health probe ---
healthcheck:
checks:
- type: http
port: 8080
# --- English copy (localisation slice 5, R-560) --------------------------------------------
# The Hungarian above is UNCHANGED. A box on English reads this block field by field; a missing
# field shows the Hungarian one; a controller older than 0.257.0 ignores the block entirely.
i18n:
en:
description: "Retro game collection manager"
data_paths:
- path: roms
label: "ROM collection"
deploy_fields:
- env_var: DOMAIN
label: "Domain"
description: "The server domain name"
- env_var: SUBDOMAIN
label: "Subdomain"
description: "The subdomain this app answers on"
- env_var: DB_PASSWORD
label: "Database password"
- env_var: MYSQL_ROOT_PASSWORD
label: "MariaDB root password"
- env_var: ROMM_AUTH_SECRET_KEY
label: "Sign-in encryption key"
- env_var: HDD_PATH
label: "Data storage path"
placeholder: "/mnt/felhom-drives/hdd_1"
description: "The path to the external hard drive where the ROMs and cover art are kept"
app_info:
tagline: "Retro game collection manager, browser and player"
default_creds: "admin / admin"
use_cases:
- "Sort and browse a retro game collection in your browser"
- "Game details download themselves - cover art, descriptions, ratings"
- "Filter and search the whole collection by platform"
- "Upload and download ROM files in your browser"
- "Several people in the household can have their own account"
first_steps:
- "Open arcade.DOMAIN in your browser"
- "Sign in with the default admin / admin account"
- "Change the password straight away, in the Settings menu"
- "Upload the ROM files into the roms/ folder in the File manager (FileBrowser), sorted into platform folders (for example roms/gba/, roms/snes/)"
- "Start a Scan from the menu on the left to read the ROMs in"
- "Optional: set up metadata providers so cover art and descriptions download themselves (see below)"
prerequisites:
- "An external hard drive is needed to keep the ROM files and cover art on"
- "At least 1 GB of free RAM is recommended (MariaDB + Redis + RomM)"
- "ROM files sorted into platform folders (for example roms/gba/, roms/snes/)"
optional_config:
- match_group: "Metaadat-szolgáltatók"
group: "Metadata providers"
description: "So that cover art, descriptions and ratings download themselves. IGDB is the one worth setting up first. All of them are free after you sign up."
fields:
- env_var: IGDB_CLIENT_ID
label: "IGDB Client ID"
help_text: '1) Sign up or sign in on the Twitch developer portal (dev.twitch.tv). 2) Create a new application (any name will do). 3) Copy the Client ID across.'
- env_var: IGDB_CLIENT_SECRET
label: "IGDB Client Secret"
help_text: 'The Client Secret of your Twitch application (the "New Secret" button makes one).'
- env_var: STEAMGRIDDB_API_KEY
label: "SteamGridDB API Key"
help_text: 'Sign up on SteamGridDB, then select the "Generate API key" button under Preferences -> API.'
- env_var: SCREENSCRAPER_USER
label: "ScreenScraper user name"
help_text: 'Sign up on screenscraper.fr. Your account name is the API user name.'
- env_var: SCREENSCRAPER_PASSWORD
label: "ScreenScraper password"
help_text: 'The password of your screenscraper.fr account.'
- env_var: MOBYGAMES_API_KEY
label: "MobyGames API Key"
help_text: 'Sign up on MobyGames, then ask for a key on the API page. It gives detailed game information and credits.'
@@ -0,0 +1,236 @@
# =============================================================================
# .felhom.yml — App metadata for felhom-controller
# =============================================================================
# --- Display info (shown on dashboard) ---
display_name: "RomM"
description: "Retró játékgyűjtemény kezelő"
category: "media"
subdomain: "arcade"
slug: "romm"
# catalog_since: the date THIS repo last changed this app's pinned images. Any commit that
# changes an image: line must set this to the same day (see CLAUDE.md).
catalog_since: "2026-09-23"
# --- Resource hints (displayed on deploy screen) ---
resources:
mem_request: "300M"
mem_limit: "1280M"
pi_compatible: false
needs_hdd: true
# --- Backup classification (referential coupling; see felhom.eu documentation/audits/SPIKE-backup-classification-2026-07-14.md) ---
backup:
userdata:
- path: roms
class: optional # ruled: curated ROM sets often not re-acquirable
hdd:
- path: appdata/romm/resources
class: excluded # scraper cache, re-derivable
# --- Customer-facing folder annotation (R-75) ---
data_paths:
- path: roms
root: userdata
role: library
label: "ROM gyűjtemény"
# --- Deploy fields (first deployment only) ---
deploy_fields:
- env_var: DOMAIN
label: "Domain"
type: domain
description: "A szerver domain neve"
locked_after_deploy: true
- env_var: SUBDOMAIN
label: "Aldomain"
type: subdomain
default: "arcade"
required: true
locked_after_deploy: true
description: "Az alkalmazás aldomainje"
- env_var: DB_PASSWORD
label: "Adatbázis jelszó"
type: secret
generate: "password:24"
locked_after_deploy: true
- env_var: MYSQL_ROOT_PASSWORD
label: "MariaDB root jelszó"
type: secret
generate: "password:24"
locked_after_deploy: true
- env_var: ROMM_AUTH_SECRET_KEY
label: "Hitelesítési titkosítási kulcs"
type: secret
generate: "hex:32"
locked_after_deploy: true
- env_var: HDD_PATH
label: "Adattárolási útvonal"
type: path
required: true
placeholder: "/mnt/felhom-drives/hdd_1"
description: "A külső merevlemez elérési útja, ahol a ROM-ok és borítóképek tárolódnak"
locked_after_deploy: true
# --- App info (info page content) ---
app_info:
tagline: "Retró játékgyűjtemény kezelő, böngésző és lejátszó"
default_creds: "admin / admin"
docs_url: "https://github.com/rommapp/romm/wiki"
use_cases:
- "Retró játékgyűjtemény rendszerezése és böngészése webes felületen"
- "Játékok metaadatainak automatikus letöltése — borítók, leírások, értékelések"
- "Platformonkénti szűrés és keresés a teljes gyűjteményben"
- "ROM fájlok webes feltöltése és letöltése"
- "Többfelhasználós hozzáférés a háztartás tagjai számára"
first_steps:
- "Nyisd meg az arcade.DOMAIN címet a böngészőben"
- "Jelentkezz be az alapértelmezett admin / admin fiókkal"
- "Változtasd meg azonnal a jelszót a Settings menüben"
- "Töltsd fel a ROM fájlokat a Fájlkezelőben (FileBrowser) a roms/ mappába, platform mappákba rendezve (pl. roms/gba/, roms/snes/)"
- "Indíts egy Scan-t a bal oldali menüben a ROM-ok beolvasásához"
- "Opcionális: állíts be metaadat-szolgáltatókat a borítóképek és leírások automatikus letöltéséhez (lásd lent)"
prerequisites:
- "Külső HDD szükséges a ROM fájlok és borítóképek tárolásához"
- "Legalább 1 GB szabad RAM ajánlott (MariaDB + Redis + RomM)"
- "ROM fájlok platform mappákba rendezve (pl. roms/gba/, roms/snes/)"
# --- Optional config (configurable before or after deployment) ---
optional_config:
- group: "Metaadat-szolgáltatók"
description: "Játékok borítóinak, leírásainak és értékeléseinek automatikus letöltéséhez. Legalább az IGDB beállítása ajánlott. Mindegyik ingyenesen használható regisztráció után."
fields:
- env_var: IGDB_CLIENT_ID
label: "IGDB Client ID"
type: text
help_url: "https://api-docs.igdb.com/#getting-started"
help_text: "1) Regisztrálj / jelentkezz be a Twitch fejlesztői portálon (dev.twitch.tv). 2) Hozz létre egy új alkalmazást (bármilyen névvel). 3) Másold be a Client ID-t."
- env_var: IGDB_CLIENT_SECRET
label: "IGDB Client Secret"
type: secret_input
help_text: "A Twitch alkalmazásod Client Secret-je (a „New Secret\" gombbal generálhatod)."
- env_var: STEAMGRIDDB_API_KEY
label: "SteamGridDB API Key"
type: text
help_url: "https://www.steamgriddb.com/profile/preferences/api"
help_text: "Regisztrálj a SteamGridDB oldalon, majd a Preferences → API fül alatt kattints a „Generate API key\" gombra."
- env_var: SCREENSCRAPER_USER
label: "ScreenScraper felhasználónév"
type: text
help_url: "https://www.screenscraper.fr/"
help_text: "Regisztrálj a screenscraper.fr oldalon. A felhasználóneved lesz az API felhasználónév."
- env_var: SCREENSCRAPER_PASSWORD
label: "ScreenScraper jelszó"
type: secret_input
help_text: "A screenscraper.fr fiókod jelszava."
- env_var: MOBYGAMES_API_KEY
label: "MobyGames API Key"
type: text
help_url: "https://www.mobygames.com/info/api/"
help_text: "Regisztrálj a MobyGames oldalon, majd az API oldalon igényelj kulcsot. Részletes játékinformációkat és krediteket biztosít."
# --- Controller-side health probe ---
healthcheck:
checks:
- type: http
port: 8080
# --- English copy (localisation slice 5, R-560) --------------------------------------------
# The Hungarian above is UNCHANGED. A box on English reads this block field by field; a missing
# field shows the Hungarian one; a controller older than 0.257.0 ignores the block entirely.
i18n:
en:
description: "Retro game collection manager"
data_paths:
- path: roms
label: "ROM collection"
deploy_fields:
- env_var: DOMAIN
label: "Domain"
description: "The server domain name"
- env_var: SUBDOMAIN
label: "Subdomain"
description: "The subdomain this app answers on"
- env_var: DB_PASSWORD
label: "Database password"
- env_var: MYSQL_ROOT_PASSWORD
label: "MariaDB root password"
- env_var: ROMM_AUTH_SECRET_KEY
label: "Sign-in encryption key"
- env_var: HDD_PATH
label: "Data storage path"
placeholder: "/mnt/felhom-drives/hdd_1"
description: "The path to the external hard drive where the ROMs and cover art are kept"
app_info:
tagline: "Retro game collection manager, browser and player"
default_creds: "admin / admin"
use_cases:
- "Sort and browse a retro game collection in your browser"
- "Game details download themselves - cover art, descriptions, ratings"
- "Filter and search the whole collection by platform"
- "Upload and download ROM files in your browser"
- "Several people in the household can have their own account"
first_steps:
- "Open arcade.DOMAIN in your browser"
- "Sign in with the default admin / admin account"
- "Change the password straight away, in the Settings menu"
- "Upload the ROM files into the roms/ folder in the File manager (FileBrowser), sorted into platform folders (for example roms/gba/, roms/snes/)"
- "Start a Scan from the menu on the left to read the ROMs in"
- "Optional: set up metadata providers so cover art and descriptions download themselves (see below)"
prerequisites:
- "An external hard drive is needed to keep the ROM files and cover art on"
- "At least 1 GB of free RAM is recommended (MariaDB + Redis + RomM)"
- "ROM files sorted into platform folders (for example roms/gba/, roms/snes/)"
optional_config:
- match_group: "Metaadat-szolgáltatók"
group: "Metadata providers"
description: "So that cover art, descriptions and ratings download themselves. IGDB is the one worth setting up first. All of them are free after you sign up."
fields:
- env_var: IGDB_CLIENT_ID
label: "IGDB Client ID"
help_text: '1) Sign up or sign in on the Twitch developer portal (dev.twitch.tv). 2) Create a new application (any name will do). 3) Copy the Client ID across.'
- env_var: IGDB_CLIENT_SECRET
label: "IGDB Client Secret"
help_text: 'The Client Secret of your Twitch application (the "New Secret" button makes one).'
- env_var: STEAMGRIDDB_API_KEY
label: "SteamGridDB API Key"
help_text: 'Sign up on SteamGridDB, then select the "Generate API key" button under Preferences -> API.'
- env_var: SCREENSCRAPER_USER
label: "ScreenScraper user name"
help_text: 'Sign up on screenscraper.fr. Your account name is the API user name.'
- env_var: SCREENSCRAPER_PASSWORD
label: "ScreenScraper password"
help_text: 'The password of your screenscraper.fr account.'
- env_var: MOBYGAMES_API_KEY
label: "MobyGames API Key"
help_text: 'Sign up on MobyGames, then ask for a key on the API page. It gives detailed game information and credits.'