Files
app-catalog-felhom.eu/README.md
T

138 lines
5.3 KiB
Markdown

# 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
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** substitutes all placeholders and generates the output directory
4. **`--push`** commits and pushes the output to the Gitea monorepo
5. **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 set `hdd_path:`, the render script refuses that app and tells you what to fix
## Workflow
### Render & push
```bash
./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
1. Create `templates/<appname>/docker-compose.yml` using `{{DOMAIN}}` and optionally `{{HDD_PATH}}`
2. Add the app name to relevant customer configs in `customers/`
3. Run `./scripts/render.sh --push`
### Updating an app version
1. Edit the image tag in `templates/<appname>/docker-compose.yml`
2. Run `./scripts/render.sh --push`
3. Portainer auto-detects git changes and redeploys (if polling enabled)
Customers with version overrides keep their pinned version.
### Adding a new customer
1. Create `customers/<customer-id>.yaml` (copy an existing one as template)
2. Run `./scripts/render.sh --push`
3. Set up Portainer GitOps stacks on the customer node (see below)
## Portainer Stack Setup (per app)
On the customer's Portainer, for each app:
1. **Stacks → Add Stack → Repository**
2. Repository URL: `https://gitea.dooplex.hu/admin/customers-felhom.eu`
3. Compose path: `<customer-id>/<appname>/docker-compose.yml`
- Example: `demo-felhom/immich/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:
```yaml
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.* |