183 lines
6.9 KiB
Markdown
183 lines
6.9 KiB
Markdown
# 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/<app>/` to `/opt/docker/stacks/<app>/`
|
|
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/<appname>/docker-compose.yml` following the template standards above
|
|
2. Create `templates/<appname>/.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 |
|