Files
app-catalog-felhom.eu/templates/wanderer/docker-compose.yml
T
admin b3eabfd611 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.
2026-07-21 15:30:15 +02:00

147 lines
5.5 KiB
YAML

# Wanderer - Túra tervező és nyomkövetéssel
# 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)
# 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:
# 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_uploads:/app/uploads
networks:
- traefik-public
- wanderer-internal
deploy:
resources:
limits:
memory: 512M
healthcheck:
# 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: 40s
labels:
- "traefik.enable=true"
- "traefik.http.routers.wanderer.rule=Host(`${SUBDOMAIN}.${DOMAIN}`)"
- "traefik.http.routers.wanderer.entrypoints=websecure"
- "traefik.http.routers.wanderer.tls=true"
- "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:
# 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:
- MEILI_MASTER_KEY=${MEILI_MASTER_KEY}
- MEILI_NO_ANALYTICS=true
volumes:
- wanderer_meili_data:/meili_data
networks:
- wanderer-internal
deploy:
resources:
limits:
memory: 256M
healthcheck:
test: ["CMD", "curl", "--fail", "http://127.0.0.1:7700/health"]
interval: 15s
timeout: 5s
retries: 10
start_period: 20s
volumes:
wanderer_data:
wanderer_plugins:
wanderer_uploads:
wanderer_meili_data:
networks:
traefik-public:
external: true
wanderer-internal: