5.3 KiB
5.3 KiB
Felhom App Catalog
Central repository for all Felhom customer application deployments.
Architecture
felhom-app-catalog/ ← This repo (source of truth)
├── templates/ # Docker Compose templates with placeholders
│ ├── actualbudget/
│ ├── docmost/
│ ├── filebrowser/
│ ├── homebox/
│ ├── immich/
│ ├── mealie/
│ ├── paperless-ngx/
│ ├── romm/
│ ├── stirling-pdf/
│ └── vaultwarden/
├── customers/ # Per-customer configuration (YAML)
│ ├── demo-felhom.yaml
│ └── pi-customer-1.yaml
├── scripts/
│ └── render.sh # Renders output from templates + customer configs
└── output/ # Generated monorepo (pushed to Gitea)
├── README.md
├── demo-felhom/
│ ├── actualbudget/docker-compose.yml
│ ├── immich/docker-compose.yml
│ └── ...
└── pi-customer-1/
├── actualbudget/docker-compose.yml
└── ...
The output/ directory is what gets pushed to:
https://gitea.dooplex.hu/admin/customers-felhom.eu
How It Works
- Templates contain Docker Compose files with
{{DOMAIN}}and{{HDD_PATH}}placeholders - Customer configs define which apps each customer gets, their domain, HDD path, and any version overrides
- render.sh substitutes all placeholders and generates the output directory
--pushcommits and pushes the output to the Gitea monorepo- Portainer GitOps on each customer node pulls from the same repo, using a different compose path per stack
Placeholder Reference
| Placeholder | Source | Example |
|---|---|---|
{{DOMAIN}} |
domain: in customer YAML |
demo-felhom.eu |
{{HDD_PATH}} |
hdd_path: in customer YAML |
/mnt/hdd_1 |
Storage Strategy
- HDD host paths (
{{HDD_PATH}}/storage/...): Large user data — photos, documents, ROMs - Named Docker volumes (on NVMe): Databases, app config, caches — need fast I/O
- Templates that don't use
{{HDD_PATH}}work without it (e.g. ActualBudget, Mealie) - If a template needs
{{HDD_PATH}}but the customer config doesn't sethdd_path:, the render script refuses that app and tells you what to fix
Workflow
Render & push
./scripts/render.sh # Render all customers locally
./scripts/render.sh --push # Render + commit + push to Gitea
./scripts/render.sh --customer demo-felhom # Render one customer only
./scripts/render.sh --dry-run # Preview what would happen
./scripts/render.sh --debug # Verbose output
The default Gitea repo URL is https://gitea.dooplex.hu/admin/customers-felhom.eu.git.
Override with: GITEA_REPO_URL=https://... ./scripts/render.sh --push
Adding a new app to the catalog
- Create
templates/<appname>/docker-compose.ymlusing{{DOMAIN}}and optionally{{HDD_PATH}} - Add the app name to relevant customer configs in
customers/ - Run
./scripts/render.sh --push
Updating an app version
- Edit the image tag in
templates/<appname>/docker-compose.yml - Run
./scripts/render.sh --push - Portainer auto-detects git changes and redeploys (if polling enabled)
Customers with version overrides keep their pinned version.
Adding a new customer
- Create
customers/<customer-id>.yaml(copy an existing one as template) - Run
./scripts/render.sh --push - Set up Portainer GitOps stacks on the customer node (see below)
Portainer Stack Setup (per app)
On the customer's Portainer, for each app:
- Stacks → Add Stack → Repository
- Repository URL:
https://gitea.dooplex.hu/admin/customers-felhom.eu - Compose path:
<customer-id>/<appname>/docker-compose.yml- Example:
demo-felhom/immich/docker-compose.yml
- Example:
- Add environment variables (secrets — DB passwords, API keys, etc.)
- Enable GitOps auto-update (optional, 5-minute polling)
- Deploy
Environment Variables
Secrets are never stored in Git. They live in Portainer's stack environment variables on each customer node. Each template documents required env vars in comments at the top of the compose file.
Version Pinning
In a customer YAML, you can pin specific app versions:
overrides:
immich_version: "v2.4.1" # Don't auto-update Immich for this customer
auto_update: false # Skip ALL updates for this customer
App Catalog
| App | DB Type | RAM | Pi | HDD Data | Subdomain |
|---|---|---|---|---|---|
| ActualBudget | None (file) | ~50MB | ✅ | — | budget.* |
| Docmost | PostgreSQL + Redis | ~200MB | ⚠️ | — | docs.* |
| FileBrowser | None (file) | ~30MB | ✅ | {{HDD_PATH}}/ |
files.* |
| Homebox | None (SQLite) | ~50MB | ✅ | — | inventory.* |
| Immich | PostgreSQL + Redis | ~4GB | ❌ | {{HDD_PATH}}/storage/immich/ |
photos.* |
| Mealie | None (SQLite) | ~200MB | ✅ | — | recipes.* |
| Paperless-ngx | PostgreSQL + Redis | ~500MB | ✅ | {{HDD_PATH}}/storage/paperless/ |
paperless.* |
| ROMM | MariaDB + Redis | ~300MB | ⚠️ | {{HDD_PATH}}/storage/romm/ |
arcade.* |
| Stirling-PDF | None | ~200MB | ✅ | — | pdf.* |
| Vaultwarden | None (SQLite) | ~50MB | ✅ | — | vault.* |