Răspuns scurt
- Securizezi baza de date PostgreSQL sau MySQL în producție punând-o să asculte doar pe localhost sau pe rețeaua privată, niciodată pe adresa publică.
- Folosești autentificare scram-sha-256 în pg_hba.conf, caching_sha2_password în MySQL 8 sau ed25519 în MariaDB, și ștergi orice cont root sau postgres accesibil de la distanță.
- Creezi câte un rol pe aplicație, cu drepturi doar pe tabelele de care are nevoie, și separi rolul de migrare de rolul de rulare.
- Criptezi conexiunea aplicație–bază cu TLS chiar și în rețeaua privată și ții parolele într-un manager de secrete, nu în cod.
- Faci backup logic zilnic plus arhivare continuă a WAL pentru restaurare la un moment dat și testezi lunar.
- PostgreSQL: unde ascultă
- listen_addresses = 'localhost' sau IP-ul privat
- PostgreSQL: metoda de autentificare
- scram-sha-256, nu md5 și nu trust
- MySQL: legare și conturi
- bind-address = 127.0.0.1; fără 'root'@'%'
- Restaurare la un moment dat
- pgBackRest sau WAL-G; mysqlbinlog pentru MySQL
Prima linie: baza nu se vede din internet
Cele mai multe baze de date compromise nu au fost sparte, ci găsite. Un PostgreSQL pe 5432 sau un MySQL pe 3306 deschis către lume primește încercări de autentificare la câteva minute după pornire. Baza ascultă pe localhost dacă aplicația e pe același server, altfel pe adresa din rețeaua privată. Firewall-ul blochează portul dinspre exterior, ca a doua plasă, iar administratorul intră prin SSH sau VPN.
Roluri mici, parole bune, conexiuni criptate
Aplicația nu are nevoie de superuser. Creează un rol de rulare cu SELECT, INSERT, UPDATE și DELETE pe schema ei și unul separat pentru migrări, folosit doar din pipeline. Un SQL injection dintr-un formular rămâne atunci limitat la tabelele aplicației, nu la toată instanța. Parolele lungi, generate, stau într-un manager de secrete. TLS între aplicație și bază pare exagerat în rețeaua privată, dar acoperă un vecin compromis pe același switch.
- rol per aplicație, fără SUPERUSER și fără CREATEDB
- rol de migrare separat, folosit doar din CI
- pg_hba.conf cu hostssl și scram-sha-256
- MySQL: REQUIRE SSL pe conturile aplicației
Backup care se poate restaura
Un dump zilnic pierde până la 24 de ore de date: pentru un magazin din Chișinău, comenzi pierdute și facturi de refăcut. Arhivarea continuă a WAL în PostgreSQL, cu pgBackRest sau WAL-G, permite restaurarea la orice minut, de pildă dinaintea unui DELETE greșit; în MySQL, jurnalul binar face același lucru. Backupul pleacă criptat de pe server, iar restaurarea se repetă lunar pe o mașină curată.
Datele personale și obligațiile din Moldova
Baza unui magazin, a unei clinici sau a unei firme de outsourcing conține date cu caracter personal. Legea nr. 195/2024, în vigoare din 23 august 2026, cere măsuri tehnice și organizatorice adecvate riscului și notificarea CNPDCP la o încălcare a securității, fără întârziere nejustificată și, unde e posibil, în cel mult 72 de ore. Clienții din UE cer prin contractul de prelucrare criptare, control al accesului și jurnalizare; rolurile și jurnalul de conexiuni sunt dovada.
Setări de securitate pentru PostgreSQL și MySQL în producție| Aspect | PostgreSQL | MySQL / MariaDB | Ce previne |
|---|
| Unde ascultă | listen_addresses = 'localhost' sau IP privat | bind-address = 127.0.0.1 sau IP privat | descoperirea bazei din internet |
|---|
| Autentificare | scram-sha-256 în pg_hba.conf | MySQL 8: caching_sha2_password (implicit); MariaDB: ed25519 sau mysql_native_password | atacuri pe hash-uri slabe |
|---|
| Conturi privilegiate | postgres doar local, prin peer | fără 'root'@'%' | acces administrativ de la distanță |
|---|
| Criptare în tranzit | hostssl + ssl = on | require_secure_transport = ON | interceptare în rețea |
|---|
| Restaurare la moment | arhivare WAL cu pgBackRest / WAL-G | binlog + mysqlbinlog | pierderea unei zile de date |
|---|
Comenzi și configurări
PostgreSQL: rol de aplicație cu drepturi minimeCREATE ROLE magazin_app LOGIN PASSWORD 'parola-lunga-generata';
GRANT CONNECT ON DATABASE magazin TO magazin_app;
GRANT USAGE ON SCHEMA public TO magazin_app;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO magazin_app;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO magazin_app;
pg_hba.conf: doar local și doar criptat, cu scram# TYPE DATABASE USER ADDRESS METHOD
local all postgres peer
hostssl magazin magazin_app 10.10.0.0/24 scram-sha-256
host all all 0.0.0.0/0 reject
# în postgresql.conf: password_encryption = scram-sha-256, ssl = on
MySQL: legare locală și cont fără acces de la distanță# /etc/mysql/mysql.conf.d/mysqld.cnf
# aplicația pe ACELAȘI server: bind-address = 127.0.0.1
# aplicația pe ALT nod: bind-address = IP-ul din rețeaua privată (exemplul de mai jos)
bind-address = 10.10.0.10
require_secure_transport = ON
-- în consolă
DROP USER IF EXISTS 'root'@'%';
-- MySQL 8:
CREATE USER 'magazin_app'@'10.10.0.%' IDENTIFIED WITH caching_sha2_password BY 'parola-lunga-generata' REQUIRE SSL;
-- MariaDB nu are caching_sha2_password:
-- INSTALL SONAME 'auth_ed25519';
-- CREATE USER 'magazin_app'@'10.10.0.%' IDENTIFIED VIA ed25519 USING PASSWORD('parola-lunga-generata') REQUIRE SSL;
GRANT SELECT, INSERT, UPDATE, DELETE ON magazin.* TO 'magazin_app'@'10.10.0.%';
Exemple din practică
Clinică privată din Chișinău, programări online
MySQL asculta pe toate interfețele, cu root accesibil de oriunde, fiindcă dezvoltatorul se conecta de acasă. După legarea pe localhost, tunel SSH și un cont dedicat aplicației, încercările de autentificare din jurnal au dispărut.
Outsourcing din Bălți, PostgreSQL pentru un client olandez
Contractul de prelucrare cerea criptare în tranzit și restaurare la un moment dat. Echipa a trecut pe hostssl cu scram-sha-256 și pgBackRest cu arhivare WAL într-un bucket separat. Testul lunar de restaurare e acum o linie în raportul către client.
Retailer din Cahul, ERP pe server dedicat
Aplicația folosea contul postgres, superuser, pentru tot, iar un plugin de raportare defect a putut citi tabelele de salarii. Acum fiecare modul are rolul lui, iar rapoartele rulează pe o replică de citire, doar pe schema de vânzări.
Greșeli frecvente
- Lași listen_addresses = '*' sau bind-address = 0.0.0.0 fiindcă „firewall-ul oprește oricum”, dezactivat apoi la un restart.
- Aplicația se conectează ca postgres sau root, deci orice defect din cod dă control total pe instanță.
- Ții parola bazei în fișierul de configurare comis în Git, alături de codul aplicației.
- Ai backup zilnic, dar nu ai încercat niciodată să-l restaurezi și nu știi cât durează.
- Păstrezi md5 sau trust în pg_hba.conf, moștenite din instalarea inițială.
Cum te ajută 4hosting
- PostgreSQL & ClickHouse proiectează replicarea, backupul PITR și tuningul bazei pe VPS-urile și serverele dedicate 4hosting.
- Hardening & Compliance verifică accesul, secretele și cheile, cu raport de anexat la contractul de prelucrare cu clientul din UE.
- Orele de DevOps incluse (1–8 lunar la VPS, 10 la dedicate și GPU) configurează pgBackRest sau arhivarea binlog și testul lunar de restaurare; le ceri din panoul de client; orele se consumă în luna calendaristică, fără reportare.
- Datacentere în UE, la Frankfurt, cu DPA conform articolului 28 GDPR; factură în euro.
Întrebări conexe
Trebuie să criptez și discul pe care stă baza de date?
Criptarea la repaus acoperă furtul fizic al discului sau un snapshot copiat. Pe un VPS sau server dedicat în datacenter, riscul principal rămâne accesul logic, deci prioritatea sunt rețeaua, rolurile și backupul. Criptarea discului se adaugă după, mai ales dacă o cere contractul.
Pot lăsa phpMyAdmin sau pgAdmin pe server pentru administrare?
Doar în spatele VPN-ului sau al unui tunel SSH, niciodată pe un URL public. Panourile web de administrare sunt printre primele ținte scanate, iar un phpMyAdmin vechi a cauzat multe compromiteri. Alternativa e clientul local, prin tunel.