d18ffd54a7d6a6c9d2d06125abb105080bbf91e5
Felhom App Catalog
Central repository for all Felhom customer application deployments.
Architecture
felhom-app-catalog/
├── templates/ # Docker Compose templates ({{DOMAIN}} placeholder)
│ ├── actualbudget/
│ ├── docmost/
│ ├── filebrowser/
│ ├── homebox/
│ ├── immich/
│ ├── mealie/
│ ├── romm/
│ ├── stirling-pdf/
│ └── vaultwarden/
├── customers/ # Per-customer configuration
│ ├── demo-felhom.yaml
│ └── pi-customer-1.yaml
├── scripts/
│ └── render.sh # Renders customer repos from templates
└── README.md
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 generates per-customer Gitea repos with all placeholders substituted
- Portainer GitOps on each customer node pulls from their repo and deploys
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)
Workflow
Adding a new app to the catalog
- Create
templates/<appname>/docker-compose.ymlusing{{DOMAIN}}placeholder - Add to relevant customer configs in
customers/ - Run
./scripts/render.shto regenerate customer repos
Updating an app version
- Edit the image tag in
templates/<appname>/docker-compose.yml - Run
./scripts/render.sh— skips customers with version overrides - Portainer auto-detects git changes and redeploys (if polling enabled)
Adding a new customer
- Create
customers/<customer-id>.yaml - Create the Gitea repo:
customers/<customer-id>-stacks - Run
./scripts/render.sh --customer <customer-id> - Set up Portainer GitOps stacks on the customer node
Portainer Stack Setup (per app)
On the customer's Portainer:
- Stacks → Add Stack → Repository
- Repository URL:
https://gitea.felhom.eu/customers/<customer-id>-stacks - Compose path:
<appname>/docker-compose.yml - 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.* |
Description
Languages
Shell
100%