catalog: re-pin wanderer to the current upstream shape, retire plant-it, add the resolvability gate

wanderer: ghcr.io/flomp/wanderer:0.16.0 is a ghost - upstream split the app
into web+db images, moved registry and renamed the org. Restructured to
upstream's own v0.20.0 compose (3 services, new /data/plugins volume, second
public hostname for PocketBase, meilisearch pinned DOWN to upstream's v1.36.0
per the R-42 ruling).

plant-it: retired. The repo name was wrong (plant-it-server) but upstream has
DELETED self-hosting; last server image is 2024-12-10 and it needs MySQL+Redis
the template never had. Moved to retired/ rather than deleted - reversible.

R-41 slice 1: check-image-resolvable.py. Encodes two traps - manifest inspect
exits 0 while printing toomanyrequests, and the inverse, where the first sweep
called 24 of 65 pins dead because Hub throttled it. Ambiguity is INCONCLUSIVE,
never an accusation.
This commit is contained in:
2026-07-21 15:30:15 +02:00
parent 34d50a33ac
commit b3eabfd611
12 changed files with 575 additions and 71 deletions
-67
View File
@@ -1,67 +0,0 @@
# =============================================================================
# .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"
# --- 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
@@ -1,50 +0,0 @@
# 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
+17 -3
View File
@@ -11,8 +11,8 @@ slug: "wanderer"
# --- Resource hints (displayed on deploy screen) ---
resources:
mem_request: "100M"
mem_limit: "384M"
mem_request: "350M"
mem_limit: "1024M"
pi_compatible: true
needs_hdd: false
@@ -32,16 +32,30 @@ deploy_fields:
locked_after_deploy: true
description: "Az alkalmazás aldomainje"
- env_var: SUBDOMAIN_DB
label: "Adatbázis aldomain"
type: subdomain
default: "hike-db"
required: true
locked_after_deploy: true
description: "A PocketBase adatbázis aldomainje - a böngésző KÖZVETLENÜL ezt hívja, ezért saját nevet kap"
- env_var: MEILI_MASTER_KEY
label: "Keresőmotor kulcs"
type: secret
generate: "hex:16"
locked_after_deploy: true
- env_var: POCKETBASE_ENCRYPTION_KEY
label: "Adatbázis titkosítási kulcs"
type: secret
generate: "hex:16"
locked_after_deploy: true
# --- App info (info page content) ---
app_info:
tagline: "Túra tervező - útvonalak, GPX nyomok és domborzati térképek"
docs_url: "https://github.com/Flomp/wanderer"
docs_url: "https://wanderer.to/"
use_cases:
- 'Túra útvonalak tervezése és mentése'
+85 -14
View File
@@ -1,40 +1,65 @@
# Wanderer - Túra tervező és nyomkövetéssel
# Domain: ${SUBDOMAIN}.${DOMAIN}
# Database: None (file-based)
# RAM: ~100M (mem_limit: 384M) | Pi-compatible: Yes
# Domain: ${SUBDOMAIN}.${DOMAIN} (web) + ${SUBDOMAIN_DB}.${DOMAIN} (PocketBase API)
# Database: PocketBase (wanderer-db) + Meilisearch (kereső)
# RAM: ~350M (mem_limit: 1024M összesen) | Pi-compatible: Yes
#
# RE-PINNED 2026-07-21. The old template pinned a SINGLE image `ghcr.io/flomp/wanderer:0.16.0`,
# which does not resolve — upstream split the app into two images AND moved registry:
# ghcr.io/flomp/wanderer → docker.io/flomp/wanderer-web + docker.io/flomp/wanderer-db
# (the GitHub org also renamed Flomp → open-wanderer). The project is alive: v0.20.0, 2026-07-07.
# Structure below follows upstream's own docker-compose.yml at tag v0.20.0.
#
# Environment variables:
# DOMAIN - Your domain (e.g., demo-felhom.eu)
# MEILI_MASTER_KEY- Keresőmotor kulcs (auto-generated)
# DOMAIN - Your domain (e.g., demo-felhom.eu)
# SUBDOMAIN / SUBDOMAIN_DB - web and PocketBase hostnames
# MEILI_MASTER_KEY - Keresőmotor kulcs (auto-generated)
# POCKETBASE_ENCRYPTION_KEY - PocketBase adatbázis kulcs (auto-generated, PONTOSAN 32 karakter)
#
# WHY TWO HOSTNAMES: `PUBLIC_POCKETBASE_URL` is a PUBLIC (browser-side) variable — the user's
# browser talks to PocketBase directly, so it cannot be an internal-only address. Upstream's own
# reverse-proxy example uses two hostnames for exactly this reason.
services:
wanderer:
image: ghcr.io/flomp/wanderer:0.16.0
# container_name MUST equal the stack dir name — the controller's health probe finds the
# Traefik-exposed container by that exact name (REUSE.md §2).
image: flomp/wanderer-web:v0.20.0
container_name: wanderer
restart: unless-stopped
depends_on:
wanderer-search:
condition: service_healthy
wanderer-db:
condition: service_healthy
environment:
- TZ=Europe/Budapest
- MEILI_URL=http://wanderer-search:7700
- MEILI_MASTER_KEY=${MEILI_MASTER_KEY}
- ORIGIN=https://${SUBDOMAIN}.${DOMAIN}
- PUBLIC_POCKETBASE_URL=https://${SUBDOMAIN_DB}.${DOMAIN}
- BODY_SIZE_LIMIT=Infinity
- PUBLIC_DISABLE_SIGNUP=false
- UPLOAD_FOLDER=/app/uploads
- PUBLIC_MAP_MAX_POLYLINES=100
- OVERPASS_API_URL=https://overpass-api.de
- VALHALLA_URL=https://valhalla1.openstreetmap.de
- NOMINATIM_URL=https://nominatim.openstreetmap.org
volumes:
- wanderer_data:/app/pb_data
- wanderer_uploads:/app/uploads
networks:
- traefik-public
- wanderer-internal
deploy:
resources:
limits:
memory: 384M
memory: 512M
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:3000"]
# The web image ships curl on PATH. No dedicated /health route exists — upstream probes root.
test: ["CMD", "curl", "--fail", "http://127.0.0.1:3000/"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
start_period: 40s
labels:
- "traefik.enable=true"
- "traefik.http.routers.wanderer.rule=Host(`${SUBDOMAIN}.${DOMAIN}`)"
@@ -43,8 +68,52 @@ services:
- "traefik.http.routers.wanderer.tls.certresolver=letsencrypt"
- "traefik.http.services.wanderer.loadbalancer.server.port=3000"
wanderer-db:
# PocketBase (custom upstream build). Built FROM scratch — no shell, no package manager; a
# static curl is baked in at /curl, which is why the healthcheck calls that absolute path.
image: flomp/wanderer-db:v0.20.0
container_name: wanderer-db
restart: unless-stopped
depends_on:
wanderer-search:
condition: service_healthy
environment:
- TZ=Europe/Budapest
- MEILI_URL=http://wanderer-search:7700
- MEILI_MASTER_KEY=${MEILI_MASTER_KEY}
- POCKETBASE_ENCRYPTION_KEY=${POCKETBASE_ENCRYPTION_KEY}
- ORIGIN=https://${SUBDOMAIN}.${DOMAIN}
volumes:
- wanderer_data:/pb_data
# /data/plugins is NEW and REQUIRED as of v0.20.0 — the Strava/Komoot/Hammerhead
# integrations moved into a WASM plugin sandbox that lives here.
- wanderer_plugins:/data/plugins
networks:
- traefik-public
- wanderer-internal
deploy:
resources:
limits:
memory: 256M
healthcheck:
test: ["CMD", "/curl", "--fail", "http://127.0.0.1:8090/health"]
interval: 15s
timeout: 5s
retries: 10
start_period: 20s
labels:
- "traefik.enable=true"
- "traefik.http.routers.wanderer-db.rule=Host(`${SUBDOMAIN_DB}.${DOMAIN}`)"
- "traefik.http.routers.wanderer-db.entrypoints=websecure"
- "traefik.http.routers.wanderer-db.tls=true"
- "traefik.http.routers.wanderer-db.tls.certresolver=letsencrypt"
- "traefik.http.services.wanderer-db.loadbalancer.server.port=8090"
wanderer-search:
image: getmeili/meilisearch:v1.49
# Pinned to upstream's own v0.20.0 compose (R-42 ruling: a sidecar pin follows the app
# template's proposed pin, never the newest tag independently). Campaign 7 had bumped this to
# v1.49 while the app image was dead; upstream specifies v1.36.0.
image: getmeili/meilisearch:v1.36.0
container_name: wanderer-search
restart: unless-stopped
environment:
@@ -59,14 +128,16 @@ services:
limits:
memory: 256M
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:7700/health"]
interval: 10s
test: ["CMD", "curl", "--fail", "http://127.0.0.1:7700/health"]
interval: 15s
timeout: 5s
retries: 5
retries: 10
start_period: 20s
volumes:
wanderer_data:
wanderer_plugins:
wanderer_uploads:
wanderer_meili_data:
networks: