# ============================================================================= # Noeud de donnees Xpeditis - production # ============================================================================= # Deploye sur db-01 uniquement, dans /opt/xpeditis/data-node. # # docker compose -f docker-compose.data.yml --env-file .env.data up -d # # Regles non negociables appliquees ici : # - Aucun port publie sur 0.0.0.0 : bind explicite sur l'IP privee. # - Aucun mot de passe en dur : tout vient de .env.data (chiffre SOPS en Git). # - PostgreSQL exige TLS (hostssl) pour toute connexion venant du reseau. # - Les conteneurs ne peuvent pas escalader leurs privileges. name: xpeditis-data services: postgres: build: context: . dockerfile: Dockerfile.postgres image: xpeditis/postgres-walg:15 container_name: xpeditis-postgres restart: unless-stopped stop_grace_period: 60s # Bind sur l'IP privee : injoignable depuis Internet, meme si UFW tombe. ports: - "${PRIVATE_IP}:5432:5432" environment: POSTGRES_DB: "${POSTGRES_DB}" POSTGRES_USER: "${POSTGRES_USER}" POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}" PGDATA: /var/lib/postgresql/data/pgdata # scram-sha-256 pour tous les mots de passe (jamais md5). POSTGRES_INITDB_ARGS: "--auth-host=scram-sha-256 --auth-local=scram-sha-256 --data-checksums" TZ: Europe/Paris # --- WAL-G : archivage continu vers Hetzner Object Storage -------------- WALG_S3_PREFIX: "${WALG_S3_PREFIX}" AWS_ACCESS_KEY_ID: "${WALG_ACCESS_KEY_ID}" AWS_SECRET_ACCESS_KEY: "${WALG_SECRET_ACCESS_KEY}" AWS_ENDPOINT: "${WALG_S3_ENDPOINT}" AWS_REGION: "${WALG_S3_REGION}" AWS_S3_FORCE_PATH_STYLE: "true" # Chiffrement cote client : meme si le bucket fuite, les sauvegardes # restent illisibles sans la cle privee libsodium. WALG_LIBSODIUM_KEY: "${WALG_LIBSODIUM_KEY}" WALG_COMPRESSION_METHOD: brotli WALG_DELTA_MAX_STEPS: "6" WALG_UPLOAD_CONCURRENCY: "2" PGHOST: /var/run/postgresql volumes: - /var/lib/xpeditis/pgdata:/var/lib/postgresql/data - ./conf/postgresql.conf:/etc/postgresql/postgresql.conf:ro - ./conf/pg_hba.conf:/etc/postgresql/pg_hba.conf:ro - /var/lib/xpeditis/certs:/var/lib/xpeditis/certs:ro - ./backup:/opt/backup:ro - /var/lib/xpeditis/dumps:/var/lib/xpeditis/dumps command: - postgres - -c - config_file=/etc/postgresql/postgresql.conf - -c - hba_file=/etc/postgresql/pg_hba.conf healthcheck: test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB} -h /var/run/postgresql"] interval: 10s timeout: 5s retries: 6 start_period: 30s networks: - internal security_opt: - no-new-privileges:true shm_size: 512mb deploy: resources: limits: cpus: "3.0" memory: 6g logging: driver: json-file options: max-size: "50m" max-file: "5" redis: image: redis:7.4-alpine container_name: xpeditis-redis restart: unless-stopped stop_grace_period: 30s ports: - "${PRIVATE_IP}:6379:6379" # requirepass passe en ligne de commande : redis.conf ne sait pas lire # de variable d'environnement, et on refuse d'ecrire le mot de passe # dans un fichier versionne. command: - redis-server - /usr/local/etc/redis/redis.conf - --requirepass - "${REDIS_PASSWORD}" volumes: - ./conf/redis.conf:/usr/local/etc/redis/redis.conf:ro - /var/lib/xpeditis/redis:/data healthcheck: test: ["CMD-SHELL", "redis-cli -a \"$${REDIS_PASSWORD}\" --no-auth-warning ping | grep -q PONG"] interval: 10s timeout: 5s retries: 6 start_period: 10s environment: REDIS_PASSWORD: "${REDIS_PASSWORD}" TZ: Europe/Paris networks: - internal security_opt: - no-new-privileges:true sysctls: # Evite les pertes de connexion sous charge sur le backlog TCP. net.core.somaxconn: 1024 deploy: resources: limits: cpus: "1.0" memory: 1500m logging: driver: json-file options: max-size: "20m" max-file: "3" # Exportateur Prometheus PostgreSQL : alimente les tableaux de bord Grafana # heberges sur app-01 (scrape via le reseau prive). postgres-exporter: image: prometheuscommunity/postgres-exporter:v0.15.0 container_name: xpeditis-postgres-exporter restart: unless-stopped depends_on: postgres: condition: service_healthy ports: - "${PRIVATE_IP}:9187:9187" environment: # Connexion par le reseau interne du compose (jamais par l'IP publiee), # en TLS obligatoire comme toute autre connexion reseau. DATA_SOURCE_NAME: "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?sslmode=require" networks: - internal security_opt: - no-new-privileges:true deploy: resources: limits: cpus: "0.25" memory: 128m logging: driver: json-file options: max-size: "10m" max-file: "2" # Sous-reseau fixe : il est reference explicitement dans pg_hba.conf, il ne doit # donc pas changer d'un `docker compose up` a l'autre. networks: internal: driver: bridge ipam: config: - subnet: 172.28.0.0/24