feat: migrer stack vers Coolify (DB standalone + web Dockerfile)

- DB PostgreSQL extraite du compose (geree par Coolify avec backup R2)
- DATABASE_URL devient une variable externe injectee par Coolify
- Ajout apps/web/Dockerfile (nginx alpine servant le site statique)
- Labels Traefik: websecure->https, le->letsencrypt, reseau coolify
- Suppression code-server (remplace par workflow git)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Nicolas Fryder 2026-06-27 11:26:32 +02:00
parent d29992be79
commit 2a2cd0217a
3 changed files with 33 additions and 76 deletions

2
apps/web/Dockerfile Normal file
View file

@ -0,0 +1,2 @@
FROM nginx:alpine
COPY site/ /usr/share/nginx/html

View file

@ -1,13 +1,11 @@
BM_DB_PASSWORD= # URL complète vers la DB PostgreSQL (gérée séparément par Coolify)
DATABASE_URL=postgresql://bm:${BM_DB_PASSWORD}@db:5432/bm DATABASE_URL=postgresql://bm:PASSWORD@HOST:5432/bm
NOMINATIM_EMAIL= NOMINATIM_EMAIL=
NOMINATIM_USER_AGENT=bm-map/0.1 NOMINATIM_USER_AGENT=bm-map/0.1
BM_IMPORT_TOKEN= BM_IMPORT_TOKEN=
PGADMIN_EMAIL= PGADMIN_EMAIL=
PGADMIN_PASSWORD= PGADMIN_PASSWORD=
CODESERVER_PASSWORD=
BM_DOMAIN=bm.nicolasfryder.ovh
BM_CODE_DOMAIN=code.bm.nicolasfryder.ovh
TZ=Europe/Paris TZ=Europe/Paris
PUID=1001 PUID=1001
PGID=1001 PGID=1001

Before

Width:  |  Height:  |  Size: 302 B

After

Width:  |  Height:  |  Size: 260 B

View file

@ -1,20 +1,4 @@
services: services:
db:
image: postgis/postgis:16-3.4
environment:
POSTGRES_DB: bm
POSTGRES_USER: bm
POSTGRES_PASSWORD: ${BM_DB_PASSWORD}
volumes:
- bm_pg_data:/var/lib/postgresql/data
networks:
- bm_internal
healthcheck:
test: ["CMD-SHELL", "pg_isready -U bm -d bm"]
interval: 10s
timeout: 5s
retries: 10
redis: redis:
image: redis:7-alpine image: redis:7-alpine
command: ["redis-server", "--appendonly", "yes"] command: ["redis-server", "--appendonly", "yes"]
@ -23,20 +7,6 @@ services:
networks: networks:
- bm_internal - bm_internal
# ✅ SÉCURISÉ : Pre-build avec Dockerfile
geocoder-enqueue:
build:
context: ../apps/geocoder
working_dir: /app
environment:
DATABASE_URL: ${DATABASE_URL}
GEOCODE_ENQUEUE_BATCH: "90000"
command: ["python", "src/enqueue.py"]
networks:
- bm_internal
restart: "no"
# ✅ SÉCURISÉ : Pre-build avec Dockerfile
geocoder-worker: geocoder-worker:
build: build:
context: ../apps/geocoder context: ../apps/geocoder
@ -53,7 +23,6 @@ services:
networks: networks:
- bm_internal - bm_internal
restart: unless-stopped restart: unless-stopped
pgadmin: pgadmin:
image: dpage/pgadmin4:8 image: dpage/pgadmin4:8
environment: environment:
@ -64,14 +33,14 @@ services:
- pgadmin_data:/var/lib/pgadmin - pgadmin_data:/var/lib/pgadmin
networks: networks:
- bm_internal - bm_internal
- traefik_net - coolify
labels: labels:
- traefik.enable=true - traefik.enable=true
- traefik.docker.network=stack-vps_admin - traefik.docker.network=coolify
- traefik.http.routers.pgadmin.rule=Host(`pgadmin.bm.nicolasfryder.ovh`) - traefik.http.routers.pgadmin.rule=Host(`pgadmin.bm.nicolasfryder.ovh`)
- traefik.http.routers.pgadmin.entrypoints=websecure - traefik.http.routers.pgadmin.entrypoints=https
- traefik.http.routers.pgadmin.tls=true - traefik.http.routers.pgadmin.tls=true
- traefik.http.routers.pgadmin.tls.certresolver=le - traefik.http.routers.pgadmin.tls.certresolver=letsencrypt
- traefik.http.services.pgadmin.loadbalancer.server.port=80 - traefik.http.services.pgadmin.loadbalancer.server.port=80
api: api:
@ -79,74 +48,62 @@ services:
context: ../apps/api context: ../apps/api
environment: environment:
PORT: "3000" PORT: "3000"
DATABASE_URL: postgresql://bm:${BM_DB_PASSWORD}@db:5432/bm DATABASE_URL: ${DATABASE_URL}
BM_IMPORT_TOKEN: ${BM_IMPORT_TOKEN} BM_IMPORT_TOKEN: ${BM_IMPORT_TOKEN}
depends_on:
db:
condition: service_healthy
volumes: volumes:
- ./overrides/api/src/server.js:/app/src/server.js:ro - ./overrides/api/src/server.js:/app/src/server.js:ro
networks: networks:
- bm_internal - bm_internal
- traefik_net - coolify
labels: labels:
- traefik.enable=true - traefik.enable=true
- traefik.docker.network=coolify
- traefik.http.routers.bm-api.rule=Host(`bm.nicolasfryder.ovh`) - traefik.http.routers.bm-api.rule=Host(`bm.nicolasfryder.ovh`)
- traefik.http.routers.bm-api.entrypoints=websecure - traefik.http.routers.bm-api.entrypoints=https
- traefik.http.routers.bm-api.tls=true - traefik.http.routers.bm-api.tls=true
- traefik.http.routers.bm-api.tls.certresolver=le - traefik.http.routers.bm-api.tls.certresolver=letsencrypt
- traefik.http.services.bm-api.loadbalancer.server.port=3000
# ✅ SÉCURISÉ : Double auth + rate limiting web:
code: build:
image: lscr.io/linuxserver/code-server:latest context: ../apps/web
environment:
PUID: "1001"
PGID: "1001"
TZ: "Europe/Paris"
PASSWORD: ${CODESERVER_PASSWORD}
SUDO_PASSWORD: ${CODESERVER_PASSWORD}
DEFAULT_WORKSPACE: /workspace
volumes:
- bm_codeserver_config:/config
- /srv/stacks/bm:/workspace
networks: networks:
- bm_internal - coolify
- traefik_net
labels: labels:
- traefik.enable=true - traefik.enable=true
- traefik.docker.network=stack-vps_admin - traefik.docker.network=coolify
- traefik.http.routers.bm-code.rule=Host(`code.bm.nicolasfryder.ovh`) - traefik.http.routers.bm-web.rule=Host(`metalfrom.eu`) || Host(`www.metalfrom.eu`)
- traefik.http.routers.bm-code.entrypoints=websecure - traefik.http.routers.bm-web.entrypoints=https
- traefik.http.routers.bm-code.tls=true - traefik.http.routers.bm-web.tls=true
# ✅ AJOUTÉ : Double auth + rate limiting - traefik.http.routers.bm-web.tls.certresolver=letsencrypt
- traefik.http.routers.bm-code.middlewares=code-auth@file,code-ratelimit@file - traefik.http.routers.bm-web.tls.domains[0].main=metalfrom.eu
- traefik.http.services.bm-code.loadbalancer.server.port=8443 - traefik.http.routers.bm-web.tls.domains[0].sans=www.metalfrom.eu
- traefik.http.services.bm-web.loadbalancer.server.port=80
worker: worker:
build: build:
context: ../apps/worker context: ../apps/worker
environment: environment:
DB_DSN: postgresql://bm:${BM_DB_PASSWORD}@db:5432/bm DB_DSN: ${DATABASE_URL}
MA_LIST_URL: https://www.metal-archives.com/lists/FR MA_LIST_URL: https://www.metal-archives.com/lists/FR
MA_STATE_PATH: /app/ma_state.json MA_STATE_PATH: /app/ma_state.json
depends_on: depends_on:
db: db:
condition: service_healthy condition: service_healthy
volumes: volumes:
- /srv/stacks/bm/infra/ma_state.json:/app/ma_state.json:ro - worker_state:/app
networks: networks:
- bm_internal - bm_internal
restart: "no" restart: "no"
networks: networks:
traefik_net:
external: true
name: stack-vps_admin
bm_internal: bm_internal:
driver: bridge driver: bridge
coolify:
external: true
name: coolify
volumes: volumes:
bm_pg_data:
bm_redis_data: bm_redis_data:
bm_codeserver_config:
pgadmin_data: pgadmin_data:
worker_state: