# Felhom App Catalog Central repository for Felhom customer application templates. ## Architecture ``` app-catalog-felhom.eu/ <- This repo (source of truth) ├── templates.json # Portainer App Templates index (LEGACY — Portainer-only setups) ├── templates/ # Docker Compose templates with ${VAR} env var syntax │ ├── actualbudget/ │ │ ├── docker-compose.yml │ │ └── .felhom.yml # App metadata for felhom-controller │ ├── docmost/ │ ├── filebrowser/ │ ├── homebox/ │ ├── immich/ │ ├── mealie/ │ ├── paperless-ngx/ │ ├── romm/ │ ├── stirling-pdf/ │ └── vaultwarden/ └── scripts/ └── generate-customer.sh # LEGACY — generates customer-specific templates for Portainer ``` ## How It Works (Controller-based deployments) The **felhom-controller** syncs directly from this repo: 1. Controller periodically pulls this repo (configurable interval, default 15m) 2. Copies `docker-compose.yml` and `.felhom.yml` from `templates//` to `/opt/docker/stacks//` 3. **Never overwrites** `app.yaml` (deployed config/secrets) or `.env` files 4. Only copies files if content has actually changed (SHA-256 comparison) 5. After sync, triggers a stack rescan so new/updated apps appear on the dashboard 6. Manual sync available via "Sablonok frissítése" button on the Alkalmazások page ### Controller git config (in controller.yaml) ```yaml git: repo_url: "https://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git" branch: "main" sync_interval: "15m" username: "" # Optional, for private repos token: "" # Optional, for private repos ``` ## .felhom.yml Format Each app template has a `.felhom.yml` metadata file that the controller uses for: - Display info on the dashboard (name, description, category, subdomain) - Resource hints (memory request/limit, Pi compatibility, HDD requirement) - Deploy fields (what the user fills in during first deployment) ### Field types | Type | Description | |------|-------------| | `domain` | Auto-filled from controller config, read-only | | `secret` | Auto-generated, hidden from user (user sees "Generated ✓") | | `password` | Auto-generated but shown, user can override | | `path` | Filesystem path (validated for existence) | | `text` | Free text input | | `select` | Dropdown with predefined options | | `boolean` | Toggle switch | ### Generator types (for secret/password fields) | Generator | Description | |-----------|-------------| | `password:N` | N chars alphanumeric | | `hex:N` | N bytes hex-encoded | | `static:VAL` | Fixed value | ### Example .felhom.yml ```yaml display_name: "Paperless-ngx" description: "Dokumentumok digitalizálása és rendszerezése" category: "productivity" subdomain: "paperless" slug: "paperless-ngx" resources: mem_request: "500M" mem_limit: "1152M" pi_compatible: true needs_hdd: true deploy_fields: - env_var: DOMAIN label: "Domain" type: domain locked_after_deploy: true - 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/hdd_1" locked_after_deploy: true ``` ## App Catalog | App | DB Type | RAM (request / limit) | Pi | HDD Data | Subdomain | |-----|---------|----------------------|-----|----------|-----------| | ActualBudget | None (file) | 50M / 256M | yes | -- | budget.* | | Docmost | PostgreSQL + Redis | 200M / 768M | no | -- | docs.* | | FileBrowser | None (file) | 30M / 128M | yes | `${HDD_PATH}/storage/filebrowser/` | files.* | | Homebox | None (SQLite) | 50M / 256M | yes | -- | inventory.* | | Immich | PostgreSQL + Redis | 2048M / 4096M | no | `${HDD_PATH}/storage/immich/` | photos.* | | Mealie | None (SQLite) | 200M / 1000M | yes | -- | recipes.* | | Paperless-ngx | PostgreSQL + Redis | 500M / 1152M | yes | `${HDD_PATH}/storage/paperless/` | paperless.* | | ROMM | MariaDB + Redis | 300M / 1024M | no | `${HDD_PATH}/storage/romm/` | arcade.* | | Stirling-PDF | None | 200M / 512M | yes | -- | pdf.* | | Vaultwarden | None (SQLite) | 50M / 256M | yes | -- | vault.* | ### Variable types per app | App | DOMAIN | HDD_PATH | Secrets | |-----|:------:|:--------:|---------| | ActualBudget | yes | -- | -- | | Docmost | yes | -- | APP_SECRET, DB_PASSWORD | | FileBrowser | yes | yes | -- | | Homebox | yes | -- | -- | | Immich | yes | yes | DB_PASSWORD | | Mealie | yes | -- | -- | | Paperless-ngx | yes | yes | PAPERLESS_SECRET_KEY, DB_PASSWORD, PAPERLESS_ADMIN_USER, PAPERLESS_ADMIN_PASSWORD | | ROMM | yes | yes | DB_PASSWORD, MYSQL_ROOT_PASSWORD, ROMM_AUTH_SECRET_KEY | | Stirling-PDF | yes | -- | -- | | Vaultwarden | yes | -- | ADMIN_TOKEN | ### Storage strategy - **HDD host paths** (`${HDD_PATH}/storage/...`): Large user data — photos, documents, ROMs - **Named Docker volumes** (on internal SSD): Databases, app config, caches — need fast I/O - Templates without `${HDD_PATH}` work without an external HDD (e.g., ActualBudget, Mealie) ### Docker Compose template standards All templates follow these standards (enforced via audit): - `${DOMAIN}` variable syntax for all domain references (not hardcoded) - `deploy.resources.limits.memory` on every service container - Healthchecks on every service (appropriate for service type) - `restart: unless-stopped` on every service - `TZ=Europe/Budapest` on every service - `traefik-public` external network + internal network for DB services - Explicit `container_name:` on every service - Header comment block with: app name, domain, DB type, RAM, Pi compatibility - `depends_on` with `condition: service_healthy` for DB/Redis dependencies ## Legacy: Portainer-based deployments The `generate-customer.sh` script and `templates.json` are kept for Portainer-only setups where the felhom-controller is not used. For controller-based deployments, these are not needed. ### Legacy workflow ```bash # Generate customer templates (on your workstation) ./scripts/generate-customer.sh --customer demo-felhom \ --domain demo-felhom.eu --hdd-path /mnt/hdd_1 --push ``` ## Adding a New App 1. Create `templates//docker-compose.yml` following the template standards above 2. Create `templates//.felhom.yml` following the metadata format 3. Commit and push — the controller will pick it up on next sync 4. (Legacy) If also needed for Portainer: add entry to `templates.json` and `generate-customer.sh` ## Related Repositories | Repository | Purpose | |------------|---------| | [app-catalog-felhom.eu](https://gitea.dooplex.hu/admin/app-catalog-felhom.eu) | This repo — templates + metadata | | [deploy-felhom-compose](https://gitea.dooplex.hu/admin/deploy-felhom-compose) | felhom-controller + deploy scripts | | [felhom.eu](https://gitea.dooplex.hu/admin/felhom.eu) | Website + k3s manifests |