From cf623d46bcb50f8b80b6d8e1f4dcfa935ca358f2 Mon Sep 17 00:00:00 2001 From: Daniel Maksymilian Syrnicki Date: Tue, 21 Apr 2026 11:43:16 +0200 Subject: [PATCH] docs(apps): document the new path setting type Mirror of the core repo's apps/README.md update. Keeps the two copies in lockstep since app authors may land on either one. Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/README.md | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/apps/README.md b/apps/README.md index 13e750f..b4ca1ce 100644 --- a/apps/README.md +++ b/apps/README.md @@ -47,10 +47,42 @@ Rules enforced by `furtka/manifest.py`: - `volumes` — short names, strings. Namespaced to `furtka__` at runtime. - `ports` — integers. Informational only; compose owns the actual port binding. - `settings[].name` — must match `^[A-Z_][A-Z0-9_]*$`. This name becomes both the env-var key and the form-field ID. -- `settings[].type` — one of `text`, `password`, `number`. +- `settings[].type` — one of `text`, `password`, `number`, `path`. - `settings[].required` — if true, the install refuses when the value is empty. - `settings[].default` — optional string. Used to pre-fill the form and the bootstrapped `.env`. +### Path-type settings (host bind mounts) + +Use `"type": "path"` when the app should point at an existing folder on the host — media libraries, document archives, photo backups. The value is written to `.env` like any other setting, and compose consumes it via `${VAR}` substitution as a bind mount. + +```json +{ + "name": "MEDIA_PATH", + "label": "Medienordner", + "description": "Absoluter Pfad zu deinem Medien-Ordner, z.B. /mnt/media.", + "type": "path", + "required": true +} +``` + +```yaml +services: + app: + volumes: + - ${MEDIA_PATH}:/media:ro +``` + +The installer (`install_from` and `update_env`) refuses values that: + +- aren't absolute (must start with `/`), +- don't exist on the host, +- aren't directories, +- resolve (after `Path.resolve()`) into a system-path deny-list: `/`, `/etc`, `/root`, `/boot`, `/proc`, `/sys`, `/dev`, `/bin`, `/sbin`, `/usr/bin`, `/usr/sbin`, `/var/lib/furtka`. + +Traversal like `/mnt/../etc` is caught too — the deny-list check runs on the resolved path. + +Path settings sit alongside manifest-declared volumes. Use `manifest.volumes` for internal state the app owns (databases, caches, config), and path settings for user data the container should mount and — usually — read without owning. Mounting read-only (`:ro`) is a good default for data the app only consumes. + ## `docker-compose.yaml` - File extension is `.yaml`. The compose runner hardcodes this — `.yml` will not be found.