TL;DR
Mở /etc/postgresql/*/main/pg_hba.conf, đổi phương thức xác thực peer thành md5 (hoặc scram-sha-256 với PostgreSQL 14+), sau đó reload PostgreSQL.
# Trước:
local all all peer
# Sau:
local all all md5
sudo systemctl reload postgresql
Lỗi Gặp Phải
FATAL: Peer authentication failed for user "myapp"
Lỗi này xảy ra khi bạn kết nối vào PostgreSQL qua Unix socket cục bộ mà tên người dùng hệ điều hành không khớp với role PostgreSQL bạn đang yêu cầu. Lưu ý: lỗi này hoàn toàn không liên quan đến mật khẩu sai. Peer auth thậm chí không kiểm tra mật khẩu.
Nguyên Nhân
Về mặt kỹ thuật, pg_hba.conf (host-based authentication) kiểm soát cách xác thực mọi kết nối đến. Phương thức peer hỏi hệ điều hành: "Người dùng hiện tại là ai?" — rồi kiểm tra xem tên đó có khớp với role PostgreSQL được yêu cầu không.
Giả sử bạn đang đăng nhập với tên ubuntu và chạy:
psql -U postgres
PostgreSQL thấy người dùng hệ điều hành là ubuntu, role yêu cầu là postgres. Không khớp — bị từ chối. Hầu hết các cài đặt Debian/Ubuntu mặc định như sau:
local all postgres peer
local all all peer
Ổn cho việc truy cập cấp hệ thống qua sudo -u postgres psql. Nhưng khi ứng dụng kết nối bằng thông tin xác thực riêng, peer auth sẽ bị lỗi.
Cách Sửa
Cách 1: Chuyển sang md5 hoặc scram-sha-256 (Cách Phổ Biến Nhất)
Đầu tiên, tìm file pg_hba.conf:
# Hỏi PostgreSQL trực tiếp:
sudo -u postgres psql -c "SHOW hba_file;"
# Đường dẫn thông thường:
# Debian/Ubuntu: /etc/postgresql/14/main/pg_hba.conf
# RHEL/CentOS: /var/lib/pgsql/14/data/pg_hba.conf
Mở file và cập nhật các dòng local từ peer sang md5:
sudo nano /etc/postgresql/14/main/pg_hba.conf
# Đổi dòng này:
local all all peer
# Thành dòng này:
local all all md5
Với PostgreSQL 14+, scram-sha-256 là lựa chọn tốt hơn — đây là mã hóa mật khẩu mặc định từ phiên bản đó và mạnh hơn đáng kể so với MD5:
local all all scram-sha-256
Reload để áp dụng mà không ngắt các kết nối đang hoạt động:
sudo systemctl reload postgresql
Một điều nữa: đảm bảo người dùng database thực sự đã có mật khẩu.
sudo -u postgres psql
ALTER USER myapp WITH PASSWORD 'your_password_here';
\q
Cách 2: Kết Nối Bằng Người Dùng Hệ Điều Hành Tương Ứng
Muốn giữ xác thực peer? Thì người dùng hệ điều hành chạy lệnh cần khớp với role PostgreSQL:
# Cho postgres superuser:
sudo -u postgres psql
# Cho người dùng riêng của ứng dụng:
sudo -u myapp psql -d myapp_db
Tiện cho các tác vụ bảo trì một lần. Không dùng được cho kết nối ứng dụng cần tự xác thực.
Cách 3: Giới Hạn Thay Đổi Cho Một Người Dùng Cụ Thể
Thay vì chuyển tất cả sang xác thực mật khẩu, thêm một rule cụ thể phía trên rule mặc định bắt-tất-cả. Các rule trong pg_hba.conf khớp từ trên xuống dưới — rule đầu tiên khớp sẽ thắng.
# pg_hba.conf — các rule cụ thể đặt trước:
local myapp_db myapp md5
local all all peer
Lúc này myapp xác thực bằng mật khẩu với myapp_db, trong khi superuser postgres và mọi thứ khác vẫn dùng peer auth.
Cách 4: Dùng TCP Thay Vì Unix Socket
Đây là cách giải quyết ít hiển nhiên hơn. Kết nối Unix socket tuân theo các rule local trong pg_hba.conf. Kết nối TCP — kể cả đến 127.0.0.1 — tuân theo các rule host, thường mặc định là md5:
psql -h 127.0.0.1 -U myapp -d myapp_db
Xác nhận các dòng host của bạn cho phép xác thực mật khẩu:
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
Tham Khảo Các Phương Thức pg_hba.conf
- peer — Tên người dùng hệ điều hành phải khớp với role DB. Không kiểm tra mật khẩu. Chỉ dùng cho local socket.
- md5 — Yêu cầu mật khẩu, lưu dưới dạng hash MD5. Được hỗ trợ rộng rãi trên mọi client.
- scram-sha-256 — Yêu cầu mật khẩu, hash mạnh hơn. Cần PostgreSQL 10+ trên cả server và client.
- trust — Không xác thực gì cả. Chỉ dùng cho dev cục bộ — không bao giờ dùng production.
- reject — Luôn từ chối. Hữu ích để chặn rõ ràng các IP hoặc người dùng cụ thể.
Kiểm Tra Sau Khi Sửa
# Kết nối với tư cách người dùng ứng dụng:
psql -U myapp -d myapp_db
# Bạn sẽ thấy dấu nhắc như:
# myapp_db=>
# Kiểm tra xem người dùng có mật khẩu chưa:
sudo -u postgres psql -c "SELECT usename, passwd IS NOT NULL AS has_password FROM pg_shadow WHERE usename = 'myapp';"
# Xác nhận các rule pg_hba đã được tải đúng:
sudo -u postgres psql -c "SELECT * FROM pg_hba_file_rules;"
Không còn lỗi peer khi kết nối? Bạn đã xong.
Mẹo
Chuyển sang xác thực bằng mật khẩu nghĩa là mọi người dùng database đều cần mật khẩu thực — đừng bỏ qua bước đó. Nếu cần tạo mật khẩu mạnh, ToolCraft's Password Generator chạy hoàn toàn trên trình duyệt mà không gửi gì lên server, điều này rất đáng lưu ý khi tạo thông tin xác thực database.
Ngoài ra: sau khi chỉnh pg_hba.conf, luôn dùng reload thay vì restart. Reload áp dụng cấu hình mới cho các kết nối đến mà không ảnh hưởng đến kết nối hiện có. Restart chỉ cần thiết cho các thay đổi postgresql.conf — và PostgreSQL sẽ thông báo những thay đổi nào yêu cầu restart.
# Reload không gây gián đoạn:
sudo systemctl reload postgresql
# Hoặc từ bên trong psql:
SELECT pg_reload_conf();

