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

  1. Templates contain Docker Compose files with {{DOMAIN}} and {{HDD_PATH}} placeholders
  2. Customer configs define which apps each customer gets, their domain, HDD path, and any version overrides
  3. render.sh generates per-customer Gitea repos with all placeholders substituted
  4. 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

  1. Create templates/<appname>/docker-compose.yml using {{DOMAIN}} placeholder
  2. Add to relevant customer configs in customers/
  3. Run ./scripts/render.sh to regenerate customer repos

Updating an app version

  1. Edit the image tag in templates/<appname>/docker-compose.yml
  2. Run ./scripts/render.sh — skips customers with version overrides
  3. Portainer auto-detects git changes and redeploys (if polling enabled)

Adding a new customer

  1. Create customers/<customer-id>.yaml
  2. Create the Gitea repo: customers/<customer-id>-stacks
  3. Run ./scripts/render.sh --customer <customer-id>
  4. Set up Portainer GitOps stacks on the customer node

Portainer Stack Setup (per app)

On the customer's Portainer:

  1. Stacks → Add Stack → Repository
  2. Repository URL: https://gitea.felhom.eu/customers/<customer-id>-stacks
  3. Compose path: <appname>/docker-compose.yml
  4. Add environment variables (secrets — DB passwords, API keys, etc.)
  5. Enable GitOps auto-update (optional, 5-minute polling)
  6. 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.*
S
Description
No description provided
Readme 282 KiB
Languages
Shell 100%