admin ac074b5176 fix(ghost): fix healthchecks for Ghost 6.x (301 redirects to external URL)
Ghost 6.x redirects all HTTP requests to the configured external URL.
- Docker healthcheck: use node http.get (accepts 301 as healthy)
- Controller probe: switch from api (expect 200) to http (any response)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 15:26:12 +01:00
2026-02-12 18:54:46 +01:00
2026-02-11 20:27:53 +01:00
2026-02-12 17:44:57 +01:00

Felhom App Catalog

Central repository for Felhom customer application templates.

Architecture

app-catalog-felhom.eu/          <- This repo (source of truth)
├── 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
│   ├── adventurelog/
│   ├── audiobookshelf/
│   ├── bentopdf/
│   ├── bookstack/
│   ├── calcom/
│   ├── calibre-web/
│   ├── claper/
│   ├── code-server/
│   ├── crafty-controller/
│   ├── docmost/
│   ├── emby/
│   ├── filebrowser/
│   ├── ghost/
│   ├── gitea/
│   ├── glance/
│   ├── gokapi/
│   ├── grafana/
│   ├── gramps-web/
│   ├── home-assistant/
│   ├── homebox/
│   ├── homepage/
│   ├── immich/
│   ├── jellyfin/
│   ├── kimai/
│   ├── komga/
│   ├── mealie/
│   ├── n8n/
│   ├── navidrome/
│   ├── nextcloud/
│   ├── onlyoffice/
│   ├── opengist/
│   ├── outline/
│   ├── paperless-ngx/
│   ├── papra/
│   ├── plant-it/
│   ├── plex/
│   ├── privatebin/
│   ├── radarr/
│   ├── rallly/
│   ├── romm/
│   ├── seerr/
│   ├── sonarr/
│   ├── tandoor/
│   ├── termix/
│   ├── uptime-kuma/
│   ├── vaultwarden/
│   ├── vikunja/
│   ├── wanderer/
│   ├── wger/
│   ├── wishlist/
│   └── zipline/
└── scripts/
    └── generate-customer.sh    # LEGACY — generates customer-specific templates for Portainer

How It Works (Controller-based deployments)

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)

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

.felhom.yml Format

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)

Field types

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

Generator types (for secret/password fields)

Generator Description
password:N N chars alphanumeric
hex:N N bytes hex-encoded
base64key:N base64: + N random bytes base64-encoded (Laravel APP_KEY format)
static:VAL Fixed value

Example .felhom.yml

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

App Catalog

App DB Type RAM (request / limit) Pi HDD Data Subdomain
ActualBudget None (file) 50M / 256M yes -- budget.*
AdventureLog PostgreSQL 100M / 384M yes -- travel.*
Audiobookshelf None (file) 100M / 512M yes ${HDD_PATH}/media/audiobooks/ audiobooks.*
BentoPDF None (file) 100M / 384M yes -- pdf.*
BookStack MariaDB 150M / 512M yes -- wiki.*
Cal.com PostgreSQL 200M / 768M no -- cal.*
Calibre-Web Automated None (file) 200M / 768M no ${HDD_PATH}/media/books/ books.*
Claper PostgreSQL 100M / 384M yes -- present.*
Code-Server None (file) 200M / 1024M no -- code.*
Crafty Controller None (file) 256M / 2048M no -- minecraft.*
Docmost PostgreSQL + Redis 200M / 768M no -- docs.*
Emby None (file) 512M / 2048M no ${HDD_PATH}/media/ emby.*
FileBrowser Quantum None (file) 50M / 256M yes ${HDD_PATH}/storage/filebrowser/ files.*
Ghost SQLite 150M / 512M no -- blog.*
Gitea SQLite 100M / 512M yes -- git.*
Glance None (file) 20M / 128M yes -- dashboard.*
Gokapi None (file) 30M / 128M yes -- share.*
Grafana None (file) 100M / 512M yes -- grafana.*
Gramps Web None (file) 100M / 384M yes -- family.*
Home Assistant None (file) 256M / 1024M yes -- ha.*
Homebox None (SQLite) 50M / 256M yes -- inventory.*
Homepage None (file) 50M / 256M yes -- home.*
Immich PostgreSQL + Redis 2048M / 4096M no ${HDD_PATH}/storage/immich/ photos.*
Jellyfin None (file) 512M / 2048M no ${HDD_PATH}/media/ media.*
Kimai MariaDB 100M / 384M yes -- time.*
Komga None (file) 200M / 512M yes ${HDD_PATH}/media/comics/ comics.*
Mealie None (SQLite) 200M / 1000M yes -- recipes.*
n8n None (file) 150M / 512M no -- auto.*
Navidrome None (file) 50M / 256M yes ${HDD_PATH}/media/music/ music.*
Nextcloud MariaDB + Redis 256M / 1024M no ${HDD_PATH}/storage/nextcloud/ cloud.*
OnlyOffice None (file) 512M / 2048M no -- office.*
OpenGist None (file) 30M / 128M yes -- gist.*
Outline PostgreSQL + Redis 200M / 768M no -- kb.*
Paperless-ngx PostgreSQL + Redis 500M / 1152M yes ${HDD_PATH}/storage/paperless/ paperless.*
Papra None (file) 50M / 256M yes -- papra.*
Plant-it None (file) 50M / 256M yes -- plants.*
Plex None (file) 512M / 2048M no ${HDD_PATH}/media/ plex.*
PrivateBin None (file) 30M / 128M yes -- paste.*
Radarr None (file) 150M / 512M yes ${HDD_PATH}/media/ radarr.*
Rallly PostgreSQL 50M / 256M yes -- poll.*
RomM MariaDB + Redis 300M / 1024M no ${HDD_PATH}/storage/romm/ arcade.*
Jellyseerr None (file) 100M / 384M yes -- requests.*
Sonarr None (file) 150M / 512M yes ${HDD_PATH}/media/ sonarr.*
Tandoor Recipes PostgreSQL 150M / 512M yes -- recipes.*
Termix None (file) 30M / 128M yes -- terminal.*
Uptime Kuma None (file) 50M / 256M yes -- status.*
Vaultwarden None (SQLite) 50M / 256M yes -- vault.*
Vikunja None (file) 50M / 256M yes -- tasks.*
Wanderer None (file) 100M / 384M yes -- hike.*
wger SQLite 100M / 384M yes -- fitness.*
Wishlist None (file) 30M / 128M yes -- wishes.*
Zipline PostgreSQL 100M / 512M no -- img.*

Variable types per app

App DOMAIN HDD_PATH Secrets
ActualBudget yes -- --
AdventureLog yes -- SECRET_KEY, DB_PASSWORD
Audiobookshelf yes yes --
BentoPDF yes -- --
BookStack yes -- APP_KEY, DB_PASSWORD
Cal.com yes -- NEXTAUTH_SECRET, CALENDSO_ENCRYPTION_KEY, DB_PASSWORD
Calibre-Web Automated yes yes --
Claper yes -- SECRET_KEY_BASE, DB_PASSWORD
Code-Server yes -- PASSWORD
Crafty Controller yes -- --
Docmost yes -- APP_SECRET, DB_PASSWORD
Emby yes yes --
FileBrowser Quantum yes yes --
Ghost yes -- --
Gitea yes -- --
Glance yes -- --
Gokapi yes -- --
Grafana yes -- GF_SECURITY_ADMIN_PASSWORD
Gramps Web yes -- GRAMPSWEB_SECRET_KEY
Home Assistant yes -- --
Homebox yes -- --
Homepage yes -- --
Immich yes yes DB_PASSWORD
Jellyfin yes yes --
Kimai yes -- DB_PASSWORD, ADMIN_EMAIL, ADMIN_PASSWORD
Komga yes yes --
Mealie yes -- --
n8n yes -- N8N_ENCRYPTION_KEY
Navidrome yes yes --
Nextcloud yes yes DB_PASSWORD, MYSQL_ROOT_PASSWORD, NEXTCLOUD_ADMIN_USER, NEXTCLOUD_ADMIN_PASSWORD
OnlyOffice yes -- JWT_SECRET
OpenGist yes -- --
Outline yes -- SECRET_KEY, UTILS_SECRET, DB_PASSWORD
Paperless-ngx yes yes PAPERLESS_SECRET_KEY, DB_PASSWORD, PAPERLESS_ADMIN_USER, PAPERLESS_ADMIN_PASSWORD
Papra yes -- --
Plant-it yes -- JWT_SECRET
Plex yes yes PLEX_CLAIM
PrivateBin yes -- --
Radarr yes yes --
Rallly yes -- SECRET_PASSWORD, DB_PASSWORD
RomM yes yes DB_PASSWORD, MYSQL_ROOT_PASSWORD, ROMM_AUTH_SECRET_KEY
Jellyseerr yes -- --
Sonarr yes yes --
Tandoor Recipes yes -- SECRET_KEY, DB_PASSWORD
Termix yes -- --
Uptime Kuma yes -- --
Vaultwarden yes -- ADMIN_TOKEN
Vikunja yes -- VIKUNJA_SERVICE_JWTSECRET
Wanderer yes -- MEILI_MASTER_KEY
wger yes -- SECRET_KEY
Wishlist yes -- --
Zipline yes -- CORE_SECRET, DB_PASSWORD

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
  • 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

# 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 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
Repository Purpose
app-catalog-felhom.eu This repo — templates + metadata
deploy-felhom-compose felhom-controller + deploy scripts
felhom.eu Website + k3s manifests
S
Description
No description provided
Readme 282 KiB
Languages
Shell 100%