Files
PleinR/docker-compose.yml
T
Claude 19d1104ab0 Connexion Facebook / LinkedIn en OAuth depuis le backoffice
Les jetons se posaient à la main dans docker-compose. Un écran Backend ›
Réseaux sociaux permet désormais de coller les identifiants de l'application,
cliquer Connecter, choisir la page, et ne plus y revenir.

- Table `social_accounts` : identifiants, jetons et cible par réseau. Tous les
  secrets sont chiffrés en AES-256-GCM (`src/lib/crypto.ts`), clé
  `SOCIAL_TOKEN_KEY` avec repli sur `AUTH_SECRET`.
- Routes `api/social/[network]/{connect,callback}` : `state` anti-CSRF en cookie
  httpOnly, échange du code, récupération des pages administrées. Aucun jeton ne
  transite par une URL — les cibles sont relistées côté serveur au moment de la
  sélection.
- Facebook : jeton utilisateur longue durée puis jeton de PAGE, qui n'expire
  pas. LinkedIn : jeton 60 jours, rafraîchi automatiquement si l'application a
  obtenu les jetons de rafraîchissement programmatiques.
- Faute de quoi le backoffice affiche la date d'expiration, un bandeau sur le
  tableau de bord à J-7 et un bouton Reconnecter.
- `social.ts` lit les identifiants via `social-accounts.ts` : base d'abord,
  variables d'environnement ensuite. Les installations existantes continuent de
  fonctionner sans modification.
- Le secret d'application n'est jamais renvoyé au navigateur : champ vide =
  valeur conservée.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QXNXRC4j5VLfKvpyyisrnb
2026-07-24 23:00:08 +00:00

92 lines
3.7 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:
# Host port rarely used (container stays on 5432). Change the left side if needed.
- "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}
SEED_ADMIN_PASSWORD: ${SEED_ADMIN_PASSWORD:-changeme123}
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}