catalog: lifecycle field replaces the retired/ directory move

Moving a template out of templates/ un-offers it but also makes the
controller's orphan detector see it as GONE for anyone already running the
app - flagging their working install Elavult with a Torles button. Withdrawing
an app must never take a working app away from a customer.

Optional lifecycle: available|hidden|abandoned in .felhom.yml instead.
plant-it returns to templates/ as the first abandoned app; retired/ removed.
Resolvability gate skips (and reports) non-available apps.
This commit is contained in:
2026-07-21 16:19:49 +02:00
parent 857ba53233
commit a32541684a
8 changed files with 161 additions and 32 deletions
+80
View File
@@ -0,0 +1,80 @@
# =============================================================================
# .felhom.yml - App metadata for felhom-controller
# =============================================================================
# --- Display info (shown on dashboard) ---
display_name: "Plant-it"
description: "Növénynapló és gondozás emlékeztető"
category: "home"
subdomain: "plants"
slug: "plant-it"
# --- Lifecycle ---
# abandoned: upstream stopped developing the self-hosted edition. NOT offered for new installs;
# anyone already running it keeps running it, with a permanent notice that no updates or security
# fixes will arrive. Evidence (2026-07-21): the `backend/` and `deployment/` directories are DELETED
# from upstream `main` (the project is now an Android app on F-Droid/Obtainium); the last server
# image `msdeluise/plant-it-server:0.10.0` was pushed 2024-12-10 and is a security-frozen Spring
# Boot 3.4.0; and it requires MySQL 8.0 + Redis, which this template never had.
#
# The compose below is deliberately LEFT AS-IS (it pins `msdeluise/plant-it:0.10.0`, a repository
# that does not exist — the real one is `-server`). It is not worth fixing: the app is not
# installable, and rewriting it would imply it is.
lifecycle: abandoned
# --- Resource hints (displayed on deploy screen) ---
resources:
mem_request: "50M"
mem_limit: "256M"
pi_compatible: true
needs_hdd: false
# --- Deploy fields (first deployment only) ---
deploy_fields:
- env_var: DOMAIN
label: "Domain"
type: domain
description: "A szerver domain neve"
locked_after_deploy: true
- env_var: SUBDOMAIN
label: "Aldomain"
type: subdomain
default: "plants"
required: true
locked_after_deploy: true
description: "Az alkalmazás aldomainje"
- env_var: JWT_SECRET
label: "JWT titkosítási kulcs"
type: secret
generate: "hex:32"
locked_after_deploy: true
# --- App info (info page content) ---
app_info:
tagline: "Növénynapló - emlékeztetők öntözésre, trágyázásra és fotónapló"
docs_url: "https://docs.plant-it.org/"
use_cases:
- 'Szobanövények és kerti növények nyilvántartása'
- 'Emlékeztetők öntözésre, trágyázásra, átültetésre'
- 'Fotónapló a növények fejlődéséről'
- 'Statisztikák és gondozási előzmények'
- 'Több felhasználó - a család együtt gondozhat'
first_steps:
- 'Nyisd meg a plants.DOMAIN címet a böngészőben'
- 'Hozd létre a fiókodat'
- 'Add hozzá az első növényt fotóval'
- 'Állíts be gondozási emlékeztetőket'
# --- Controller-side health probe ---
healthcheck:
checks:
- type: api
port: 8080
path: "/api/info"
expect:
status: 200
+50
View File
@@ -0,0 +1,50 @@
# Plant-it - Növénynapló és gondozás emlékeztető
# Domain: ${SUBDOMAIN}.${DOMAIN}
# Database: None (file-based)
# RAM: ~50M (mem_limit: 256M) | Pi-compatible: Yes
#
# Environment variables:
# DOMAIN - Your domain (e.g., demo-felhom.eu)
# JWT_SECRET - JWT titkosítási kulcs (auto-generated)
services:
plant-it:
image: msdeluise/plant-it:0.10.0
container_name: plant-it
restart: unless-stopped
environment:
- TZ=Europe/Budapest
- JWT_SECRET=${JWT_SECRET}
- USERS_LIMIT=-1
- UPLOAD_DIR=/upload-dir
- API_PORT=8080
volumes:
- plantit_data:/upload-dir
- plantit_db:/app/db
networks:
- traefik-public
deploy:
resources:
limits:
memory: 256M
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:8080/api/info"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
labels:
- "traefik.enable=true"
- "traefik.http.routers.plant-it.rule=Host(`${SUBDOMAIN}.${DOMAIN}`)"
- "traefik.http.routers.plant-it.entrypoints=websecure"
- "traefik.http.routers.plant-it.tls=true"
- "traefik.http.routers.plant-it.tls.certresolver=letsencrypt"
- "traefik.http.services.plant-it.loadbalancer.server.port=8080"
volumes:
plantit_data:
plantit_db:
networks:
traefik-public:
external: true