mirror of
https://github.com/R0m1k3/PleinR.git
synced 2026-10-11 17:27:54 +02:00
Audit de sécurité complet de l'application, puis correctifs du lot A validés : - Seed : plus aucun compte de démonstration (mot de passe « changeme123 ») sans SEED_DEMO=true. L'administrateur initial reçoit un mot de passe aléatoire affiché une fois dans les journaux (ou SEED_ADMIN_PASSWORD) et doit le changer à la première connexion. docker-compose ne fournit plus de mot de passe par défaut. - Mots de passe temporaires : la colonne users.temp_password (en clair) est supprimée (migration 0011). Création d'adhérent, réinitialisation, rattrapage des comptes manquants, approbation de demande et invitation staff renvoient les identifiants, affichés une seule fois par le composant OneTimeCredentials, sans redirection. L'invitation staff, qui ne communiquait jamais le mot de passe, redevient utilisable et impose le changement à la première connexion. - Sessions JWT limitées à 7 jours (30 auparavant). - En-têtes : Strict-Transport-Security ajouté, X-Powered-By supprimé. - docker-compose : port Postgres publié sur 127.0.0.1 uniquement. - Image Docker sur node:22 (Node 20 en fin de vie). - Dépendances : next 15.5.25, pg 8.23, nanoid 3.3.18 (avis GHSA-2v37-7h3g-55p8). Vérifié en local : tests, typage, build de production, migration + seed sur un Postgres 16, et parcours navigateur complet (première connexion, changement forcé, création / réinitialisation / invitation avec affichage unique, cookie de session à 7 jours). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RAQsCp4nnZbwexCg7NDBHE
97 lines
4.0 KiB
YAML
97 lines
4.0 KiB
YAML
# Plein R — single application container + external Postgres container.
|
|
#
|
|
# The app (Next.js) runs in ONE container. Postgres runs as a SEPARATE
|
|
# (external) container. For a managed/already-existing Postgres, delete the
|
|
# `postgres` service below and point DATABASE_URL at your instance.
|
|
|
|
services:
|
|
postgres:
|
|
image: postgres:16-alpine
|
|
container_name: pleinr-postgres
|
|
restart: unless-stopped
|
|
environment:
|
|
POSTGRES_USER: ${POSTGRES_USER:-pleinr}
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-pleinr}
|
|
POSTGRES_DB: ${POSTGRES_DB:-pleinr}
|
|
volumes:
|
|
- pgdata:/var/lib/postgresql/data
|
|
ports:
|
|
# Lié à 127.0.0.1 : la base ne doit jamais être joignable depuis le réseau.
|
|
# Retirez le préfixe uniquement pour un accès distant volontaire (et protégé).
|
|
- "127.0.0.1:54329:5432"
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-pleinr} -d ${POSTGRES_DB:-pleinr}"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 12
|
|
networks:
|
|
- internal
|
|
|
|
app:
|
|
build: .
|
|
container_name: pleinr-app
|
|
restart: unless-stopped
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
environment:
|
|
# Use the UNIQUE container name (not the generic "postgres" alias) to avoid
|
|
# name collisions with other "postgres" containers on the shared proxy
|
|
# network. pleinr-postgres only exists on our internal network.
|
|
DATABASE_URL: postgres://${POSTGRES_USER:-pleinr}:${POSTGRES_PASSWORD:-pleinr}@pleinr-postgres:5432/${POSTGRES_DB:-pleinr}
|
|
# Optional: if left empty, the container generates and persists one
|
|
# automatically (see docker-entrypoint.sh + the app-data volume).
|
|
AUTH_SECRET: ${AUTH_SECRET:-}
|
|
# IMPORTANT behind a reverse proxy: set AUTH_URL to your public URL so the
|
|
# login redirect points to the right host, e.g.
|
|
# AUTH_URL=https://pleinr.ffnancy.fr
|
|
AUTH_URL: ${AUTH_URL:-}
|
|
# Lets Auth.js trust the X-Forwarded-* headers from the proxy.
|
|
AUTH_TRUST_HOST: "true"
|
|
# URL publique, reprise dans le texte des posts Facebook / LinkedIn.
|
|
NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL:-}
|
|
# Chiffrement des jetons réseaux stockés en base (à défaut : AUTH_SECRET).
|
|
SOCIAL_TOKEN_KEY: ${SOCIAL_TOKEN_KEY:-}
|
|
# Repli historique : la configuration normale se fait dans le backoffice.
|
|
FACEBOOK_PAGE_ID: ${FACEBOOK_PAGE_ID:-}
|
|
FACEBOOK_PAGE_ACCESS_TOKEN: ${FACEBOOK_PAGE_ACCESS_TOKEN:-}
|
|
FACEBOOK_GRAPH_VERSION: ${FACEBOOK_GRAPH_VERSION:-}
|
|
LINKEDIN_ORGANIZATION_URN: ${LINKEDIN_ORGANIZATION_URN:-}
|
|
LINKEDIN_ORGANIZATION_ID: ${LINKEDIN_ORGANIZATION_ID:-}
|
|
LINKEDIN_ACCESS_TOKEN: ${LINKEDIN_ACCESS_TOKEN:-}
|
|
LINKEDIN_API_VERSION: ${LINKEDIN_API_VERSION:-}
|
|
SEED_ON_START: ${SEED_ON_START:-true}
|
|
SEED_ADMIN_EMAIL: ${SEED_ADMIN_EMAIL:-admin@plein-r.fr}
|
|
# Vide = un mot de passe aléatoire est généré au premier démarrage et
|
|
# affiché une seule fois dans les journaux du conteneur.
|
|
SEED_ADMIN_PASSWORD: ${SEED_ADMIN_PASSWORD:-}
|
|
# Comptes de démonstration (mot de passe connu) : jamais en production.
|
|
SEED_DEMO: ${SEED_DEMO:-false}
|
|
SEED_ADMIN_NAME: ${SEED_ADMIN_NAME:-Administrateur Plein R}
|
|
ports:
|
|
# Host port rarely used (container stays on 3000). App reachable at http://HOST:8413
|
|
- "8413:3000"
|
|
volumes:
|
|
# Persists the auto-generated AUTH_SECRET across restarts.
|
|
- appdata:/app/data
|
|
networks:
|
|
# "internal" is shared with Postgres; "proxy" is the external network
|
|
# shared with the reverse proxy (e.g. Nginx Proxy Manager) so it can reach
|
|
# the app by name: forward to pleinr-app:3000
|
|
- internal
|
|
- proxy
|
|
|
|
volumes:
|
|
pgdata:
|
|
appdata:
|
|
|
|
networks:
|
|
# Private network for app <-> Postgres communication.
|
|
internal:
|
|
driver: bridge
|
|
proxy:
|
|
# The reverse proxy's existing network. Must already exist (created by the
|
|
# NPM/nginx stack). Override the name with PROXY_NETWORK if it differs.
|
|
external: true
|
|
name: ${PROXY_NETWORK:-nginx_default}
|