Nouveau service apps/admin (admin.metalfrom.eu / admin.dev.metalfrom.eu) : - Frontend statique vanilla JS/CSS reprenant le design system du site (login, dashboard stats, table bands éditable, queue d'enrichissement, historique crawl_run, logs live, checkpoints, journal d'audit) - nginx reverse-proxy /admin/api/* et /admin/auth/* vers le service api interne (same-origin côté navigateur, pas de CORS cross-site nécessaire pour le cookie de session) apps/api : - Nouvelle auth dédiée au dashboard, séparée du token BM_IMPORT_TOKEN existant : login bcrypt + session JWT en cookie httpOnly/secure/ sameSite=strict, rate-limit + lockout après 5 échecs/15min, seeding du compte admin via env vars (jamais de mot de passe en clair en DB ou en git) - Routes /admin/api/* : stats, queue (breakdown priorité identique au crawler Python), bands (recherche/tri/pagination/édition + audit log), crawl-runs, crawl-checkpoints, logs, audit-log - trustProxy activé (Traefik + nginx en amont) apps/crawler : - log_event() écrit dans la nouvelle table crawl_log (run start/finish/ erreurs) pour que le dashboard affiche les logs sans exposer le socket Docker (choix délibéré : pas de docker.sock monté, accès DB only) migration 006_admin_dashboard.sql : admin_users, admin_login_attempts, admin_audit_log, crawl_log Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
135 lines
3.8 KiB
YAML
135 lines
3.8 KiB
YAML
services:
|
|
redis:
|
|
image: redis:7-alpine
|
|
command: ["redis-server", "--appendonly", "yes"]
|
|
volumes:
|
|
- bm_dev_redis_data:/data
|
|
networks:
|
|
- coolify
|
|
|
|
flaresolverr:
|
|
image: ghcr.io/flaresolverr/flaresolverr:latest
|
|
environment:
|
|
LOG_LEVEL: info
|
|
CAPTCHA_SOLVER: none
|
|
networks:
|
|
- coolify
|
|
labels:
|
|
- traefik.enable=false
|
|
restart: unless-stopped
|
|
|
|
crawler:
|
|
build:
|
|
context: apps/crawler
|
|
environment:
|
|
DATABASE_URL: ${DATABASE_URL}
|
|
FLARESOLVERR_URL: http://flaresolverr:8191
|
|
CRAWLER_SCHED_INCREMENTAL_H: "4"
|
|
CRAWLER_SCHED_ENRICH_H: "2"
|
|
CRAWLER_SCHED_FULL_DAY: "0"
|
|
depends_on:
|
|
- flaresolverr
|
|
networks:
|
|
- coolify
|
|
labels:
|
|
- traefik.enable=false
|
|
restart: unless-stopped
|
|
|
|
geocoder-worker:
|
|
build:
|
|
context: apps/geocoder
|
|
working_dir: /app
|
|
environment:
|
|
DATABASE_URL: ${DATABASE_URL}
|
|
NOMINATIM_BASE: "https://nominatim.openstreetmap.org"
|
|
NOMINATIM_EMAIL: ${NOMINATIM_EMAIL}
|
|
NOMINATIM_USER_AGENT: ${NOMINATIM_USER_AGENT}
|
|
NOMINATIM_MIN_DELAY: "1.05"
|
|
NOMINATIM_JITTER: "0.35"
|
|
GEOCODE_MAX_PER_RUN: "5000"
|
|
command: ["python", "src/worker.py"]
|
|
networks:
|
|
- coolify
|
|
labels:
|
|
- traefik.enable=false
|
|
restart: "no"
|
|
|
|
pgadmin:
|
|
image: dpage/pgadmin4:8
|
|
environment:
|
|
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_EMAIL}
|
|
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_PASSWORD}
|
|
PGADMIN_CONFIG_SERVER_MODE: "True"
|
|
volumes:
|
|
- bm_dev_pgadmin_data:/var/lib/pgadmin
|
|
networks:
|
|
- coolify
|
|
labels:
|
|
- traefik.enable=true
|
|
- traefik.docker.network=coolify
|
|
- traefik.http.routers.dev-pgadmin.rule=Host(`dev-pgadmin.metalfrom.eu`)
|
|
- traefik.http.routers.dev-pgadmin.entrypoints=https
|
|
- traefik.http.routers.dev-pgadmin.tls=true
|
|
- traefik.http.routers.dev-pgadmin.tls.certresolver=letsencrypt
|
|
- traefik.http.services.dev-pgadmin.loadbalancer.server.port=80
|
|
|
|
api:
|
|
build:
|
|
context: apps/api
|
|
environment:
|
|
PORT: "3000"
|
|
DATABASE_URL: ${DATABASE_URL}
|
|
BM_IMPORT_TOKEN: ${BM_IMPORT_TOKEN}
|
|
CORS_ORIGINS: ${CORS_ORIGINS:-https://dev.metalfrom.eu}
|
|
ADMIN_JWT_SECRET: ${ADMIN_JWT_SECRET}
|
|
ADMIN_SEED_USERNAME: ${ADMIN_SEED_USERNAME}
|
|
ADMIN_SEED_PASSWORD_HASH: ${ADMIN_SEED_PASSWORD_HASH}
|
|
networks:
|
|
- coolify
|
|
labels:
|
|
- traefik.enable=true
|
|
- traefik.docker.network=coolify
|
|
- traefik.http.routers.dev-api.rule=Host(`dev-api.metalfrom.eu`)
|
|
- traefik.http.routers.dev-api.entrypoints=https
|
|
- traefik.http.routers.dev-api.tls=true
|
|
- traefik.http.routers.dev-api.tls.certresolver=letsencrypt
|
|
- traefik.http.services.dev-api.loadbalancer.server.port=3000
|
|
|
|
admin:
|
|
build:
|
|
context: apps/admin
|
|
networks:
|
|
- coolify
|
|
labels:
|
|
- traefik.enable=true
|
|
- traefik.docker.network=coolify
|
|
- traefik.http.routers.dev-admin.rule=Host(`admin.dev.metalfrom.eu`)
|
|
- traefik.http.routers.dev-admin.entrypoints=https
|
|
- traefik.http.routers.dev-admin.tls=true
|
|
- traefik.http.routers.dev-admin.tls.certresolver=letsencrypt
|
|
- traefik.http.services.dev-admin.loadbalancer.server.port=80
|
|
|
|
web:
|
|
build:
|
|
context: apps/web
|
|
args:
|
|
API_BASE: https://dev-api.metalfrom.eu
|
|
networks:
|
|
- coolify
|
|
labels:
|
|
- traefik.enable=true
|
|
- traefik.docker.network=coolify
|
|
- traefik.http.routers.dev-web.rule=Host(`dev.metalfrom.eu`)
|
|
- traefik.http.routers.dev-web.entrypoints=https
|
|
- traefik.http.routers.dev-web.tls=true
|
|
- traefik.http.routers.dev-web.tls.certresolver=letsencrypt
|
|
- traefik.http.services.dev-web.loadbalancer.server.port=80
|
|
|
|
networks:
|
|
coolify:
|
|
external: true
|
|
name: coolify
|
|
|
|
volumes:
|
|
bm_dev_redis_data:
|
|
bm_dev_pgadmin_data:
|