# ============================================================================= # PostgreSQL 15 - production Xpeditis # Cible : Hetzner CPX31 (4 vCPU / 8 Go), partage avec Redis (1,5 Go plafonne). # Budget memoire retenu pour PostgreSQL : ~6 Go. # ============================================================================= # --- Connexions -------------------------------------------------------------- listen_addresses = '*' # le confinement reseau est assure par le bind # Docker sur l'IP privee + UFW + pg_hba port = 5432 max_connections = 150 # 2 replicas backend x pool TypeORM + marge ops superuser_reserved_connections = 5 # --- TLS --------------------------------------------------------------------- # Obligatoire : pg_hba n'accepte que des lignes `hostssl`. Le reseau prive # Hetzner n'est pas chiffre par l'hyperviseur, c'est nous qui le chiffrons. ssl = on ssl_cert_file = '/var/lib/xpeditis/certs/server.crt' ssl_key_file = '/var/lib/xpeditis/certs/server.key' ssl_min_protocol_version = 'TLSv1.2' ssl_prefer_server_ciphers = on # --- Authentification -------------------------------------------------------- password_encryption = scram-sha-256 # --- Memoire ----------------------------------------------------------------- shared_buffers = 2GB effective_cache_size = 5GB maintenance_work_mem = 512MB work_mem = 16MB # par operation de tri/hash, pas par connexion huge_pages = try # --- Disque (SSD NVMe Hetzner) ---------------------------------------------- random_page_cost = 1.1 effective_io_concurrency = 200 max_worker_processes = 4 max_parallel_workers = 4 max_parallel_workers_per_gather = 2 max_parallel_maintenance_workers = 2 # --- WAL / archivage --------------------------------------------------------- wal_level = replica # suffisant pour PITR + futur standby physique wal_compression = on max_wal_size = 4GB min_wal_size = 1GB checkpoint_completion_target = 0.9 checkpoint_timeout = 15min archive_mode = on archive_command = 'wal-g wal-push %p' # Force la cloture d'un segment WAL toutes les 5 min meme sans activite : # c'est ce qui plafonne le RPO a 5 minutes de donnees perdues au maximum. archive_timeout = 300 # Conserve de quoi rattacher un standby sans repartir d'un basebackup. max_wal_senders = 5 wal_keep_size = 1GB max_replication_slots = 5 # --- Autovacuum -------------------------------------------------------------- # audit_logs et csv_rates subissent beaucoup d'ecritures : on vacuume plus tot # que les valeurs par defaut, sinon les index gonflent et les recherches # tarifaires ralentissent. autovacuum = on autovacuum_max_workers = 3 autovacuum_naptime = 30s autovacuum_vacuum_scale_factor = 0.05 autovacuum_analyze_scale_factor = 0.02 autovacuum_vacuum_cost_limit = 1000 # --- Delais de garde --------------------------------------------------------- statement_timeout = 300000 # 5 min : borne les requetes folles # tout en laissant passer les # imports CSV de grilles idle_in_transaction_session_timeout = 300000 # 5 min : libere les verrous oublies lock_timeout = 30000 tcp_keepalives_idle = 60 tcp_keepalives_interval = 10 tcp_keepalives_count = 6 # --- Observabilite ----------------------------------------------------------- shared_preload_libraries = 'pg_stat_statements' pg_stat_statements.max = 5000 pg_stat_statements.track = top track_io_timing = on track_functions = pl logging_collector = off # les logs partent sur stdout -> Docker -> Loki log_destination = 'stderr' log_min_duration_statement = 500 # trace toute requete > 500 ms log_line_prefix = '%m [%p] %q%u@%d %a ' log_checkpoints = on log_connections = on log_disconnections = on log_lock_waits = on log_temp_files = 0 log_autovacuum_min_duration = 1000 log_statement = 'ddl' # trace les changements de schema (migrations) log_timezone = 'Europe/Paris' # --- Localisation ------------------------------------------------------------ timezone = 'Europe/Paris' datestyle = 'iso, mdy' lc_messages = 'C' lc_monetary = 'C' lc_numeric = 'C' lc_time = 'C' default_text_search_config = 'pg_catalog.french'