updated app templates

This commit is contained in:
2026-02-14 13:39:44 +01:00
parent 1deacc08cb
commit 6d7e64da93
20 changed files with 609 additions and 207 deletions
+121 -142
View File
@@ -6,9 +6,11 @@ Central repository for Felhom customer application templates.
```
app-catalog-felhom.eu/ <- This repo (source of truth)
├── templates.json # Portainer App Templates index (generic, with env var prompts)
├── 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/
@@ -19,112 +21,103 @@ app-catalog-felhom.eu/ <- This repo (source of truth)
│ ├── stirling-pdf/
│ └── vaultwarden/
└── scripts/
└── generate-customer.sh # Generates customer-specific templates with baked-in secrets
└── generate-customer.sh # LEGACY — generates customer-specific templates for Portainer
```
The output is pushed to:
**https://gitea.dooplex.hu/admin/customers-felhom.eu**
## How It Works (Controller-based deployments)
```
customers-felhom.eu/ <- Generated per-customer deployments
├── demo-felhom/
│ ├── templates.json # Customer Portainer templates (zero env vars, zero-touch deploy)
│ ├── secrets.env # Reference copy of all generated secrets
│ ├── actualbudget/docker-compose.yml
│ ├── docmost/docker-compose.yml
│ └── ...
└── pi-customer-1/
├── templates.json
├── secrets.env
├── actualbudget/docker-compose.yml
└── ...
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
```
## How It Works
## .felhom.yml Format
1. **Templates** in this repo contain Docker Compose files with `${DOMAIN}`, `${HDD_PATH}`, and `${SECRET}` placeholders
2. **`generate-customer.sh`** substitutes all values (domain, HDD path, auto-generated passwords) and produces customer-specific compose files + a Portainer `templates.json` with zero env vars
3. **`docker-setup.sh`** on the customer node starts Portainer with `--templates` pointing at the customer's generated `templates.json`
4. **Customer** opens Portainer -> Templates -> picks an app -> clicks Deploy -> **done**
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)
## Workflow
### Field types
### 1. Generate customer templates (on your workstation)
| 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 |
```bash
# Full setup: all apps, with HDD
./scripts/generate-customer.sh --customer demo-felhom \
--domain demo-felhom.eu --hdd-path /mnt/hdd_1 --push
### Generator types (for secret/password fields)
# Raspberry Pi: lightweight apps only, no HDD yet
./scripts/generate-customer.sh --customer pi-customer-1 \
--domain pi-customer-1.local \
--apps actualbudget,filebrowser,mealie,stirling-pdf,vaultwarden --push
| Generator | Description |
|-----------|-------------|
| `password:N` | N chars alphanumeric |
| `hex:N` | N bytes hex-encoded |
| `static:VAL` | Fixed value |
# Preview without creating files
./scripts/generate-customer.sh --customer test --domain test.local --dry-run
### 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
```
Options:
- `--customer ID` -- Customer identifier (required)
- `--domain DOMAIN` -- Customer domain (required)
- `--hdd-path PATH` -- External HDD mount path (optional; apps needing it show a field in Portainer if omitted)
- `--apps LIST` -- Comma-separated app list (default: all available)
- `--push` -- Git commit and push to customers-felhom.eu repo
- `--dry-run` -- Show what would be done
- `--debug` -- Verbose output
## App Catalog
### 2. Set up customer server
```bash
sudo ./docker-setup.sh --domain demo-felhom.eu --customer demo-felhom \
--email certs@felhom.eu --cf-token <cloudflare-api-token>
```
### 3. Deploy apps
Open `https://portainer.<domain>` -> **Templates** -> pick an app -> **Deploy the stack**.
All fields (domain, passwords, secrets) are pre-filled. If HDD_PATH wasn't set during generation, apps that need it will show one field to fill in.
### Re-generating after changes
Re-running `generate-customer.sh` for an existing customer preserves all previously generated secrets (idempotent). Only new apps or new secrets are generated.
```bash
# Add an app to an existing customer
./scripts/generate-customer.sh --customer demo-felhom \
--domain demo-felhom.eu --hdd-path /mnt/hdd_1 --push
```
## Environment Variables & Secrets
Secrets are auto-generated by `generate-customer.sh` and baked directly into the compose files and Portainer templates. They are **not** stored separately on the customer node -- they live in the customers-felhom.eu Git repo (which is private on your Gitea).
A `secrets.env` reference file is generated alongside the compose files for easy lookup.
### Secret definitions
Defined in `generate-customer.sh` via the `APP_SECRET_DEFS` array:
```bash
APP_SECRET_DEFS=(
"docmost:APP_SECRET:hex:32"
"docmost:DB_PASSWORD:password:24"
"immich:DB_PASSWORD:password:24"
"paperless-ngx:PAPERLESS_SECRET_KEY:hex:32"
"paperless-ngx:DB_PASSWORD:password:24"
"paperless-ngx:PAPERLESS_ADMIN_USER:static:admin"
"paperless-ngx:PAPERLESS_ADMIN_PASSWORD:password:16"
"romm:DB_PASSWORD:password:24"
"romm:MYSQL_ROOT_PASSWORD:password:24"
"romm:ROMM_AUTH_SECRET_KEY:hex:32"
"vaultwarden:ADMIN_TOKEN:hex:32"
"vaultwarden:SIGNUPS_ALLOWED:static:true"
)
```
Types: `password:LENGTH` (alphanumeric), `hex:LENGTH` (crypto), `static:VALUE` (fixed).
| 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
@@ -141,63 +134,49 @@ Types: `password:LENGTH` (alphanumeric), `hex:LENGTH` (crypto), `static:VALUE` (
| Stirling-PDF | yes | -- | -- |
| Vaultwarden | yes | -- | ADMIN_TOKEN |
## App Catalog
| App | DB Type | RAM | Pi | HDD Data | Subdomain |
|-----|---------|-----|-----|----------|-----------|
| ActualBudget | None (file) | ~50MB | yes | -- | budget.* |
| Docmost | PostgreSQL + Redis | ~200MB | maybe | -- | docs.* |
| FileBrowser | None (file) | ~30MB | yes | `${HDD_PATH}/storage/filebrowser/` | files.* |
| Homebox | None (SQLite) | ~50MB | yes | -- | inventory.* |
| Immich | PostgreSQL + Redis | ~4GB | no | `${HDD_PATH}/storage/immich/` | photos.* |
| Mealie | None (SQLite) | ~200MB | yes | -- | recipes.* |
| Paperless-ngx | PostgreSQL + Redis | ~500MB | yes | `${HDD_PATH}/storage/paperless/` | paperless.* |
| ROMM | MariaDB + Redis | ~300MB | maybe | `${HDD_PATH}/storage/romm/` | arcade.* |
| Stirling-PDF | None | ~200MB | yes | -- | pdf.* |
| Vaultwarden | None (SQLite) | ~50MB | yes | -- | vault.* |
### 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
- **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` using `${DOMAIN}` and optionally `${HDD_PATH}`
2. Add a template entry in `templates.json` with env definitions, description, logo, and notes
3. If the app needs secrets, add entries to `APP_SECRET_DEFS` in `generate-customer.sh`
4. Re-run `generate-customer.sh --push` for each customer
### templates.json entry format
```json
{
"type": 3,
"title": "App Name",
"description": "Short description.",
"categories": ["category"],
"platform": "linux",
"logo": "https://example.com/logo.png",
"note": "<b>Access:</b> https://subdomain.&lt;DOMAIN&gt;",
"repository": {
"url": "https://gitea.dooplex.hu/admin/app-catalog-felhom.eu",
"stackfile": "templates/appname/docker-compose.yml"
},
"env": [
{
"name": "DOMAIN",
"label": "Domain",
"description": "Your server domain (e.g., demo-felhom.eu)"
}
]
}
```
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 + generation script |
| [customers-felhom.eu](https://gitea.dooplex.hu/admin/customers-felhom.eu) | Generated per-customer compose files + templates |
| [deploy-portainer](https://gitea.dooplex.hu/admin/deploy-portainer) | `docker-setup.sh` -- server provisioning |
| [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 |