Vũ Văn HảiFull-stack · AI-native
Hướng dẫnBlog
Trao đổi dự án

© 2026 Vũ Văn Hải · Viết từ kinh nghiệm triển khai thật.

Trang chủHướng dẫnBlogRSS
  1. Hướng dẫn
  2. /Database
  3. /Cài đặt PostgreSQL trên VPS an toàn

Cài đặt PostgreSQL trên VPS an toàn

Cài và cấu hình PostgreSQL trên VPS Ubuntu/Debian cho production: tạo database và user, mở kết nối từ xa an toàn (SSL + pg_hba + UFW), và hiểu transaction isolation.

Cập nhật: 21 thg 9, 20264 phút đọc
PostgreSQLVPSBảo mật
Mục lục
  • 1. Cài đặt PostgreSQL
  • 2. Tạo database và user
  • 3. Mở kết nối từ xa an toàn
  • Cấu hình listen address
  • Cấu hình pg_hba.conf (quan trọng nhất)
  • Tường lửa UFW + restart
  • 4. Kiểm tra kết nối
  • Phụ lục: Transaction isolation
  • Tham khảo

Bài này cài PostgreSQL trên VPS Ubuntu/Debian theo hướng an toàn cho production: cài đặt, tạo database và user, mở kết nối từ xa có kiểm soát (chỉ đúng IP + bắt buộc SSL), và cuối bài giải thích transaction isolation để bạn chọn đúng mức.

Thay <username>, <password>, <database_name>, <server-ip> bằng giá trị thật của bạn. IP ví dụ 203.0.113.42 chỉ là placeholder.

1. Cài đặt PostgreSQL

sudo apt update
sudo apt install postgresql postgresql-contrib
sudo systemctl start postgresql.service

Mặc định PostgreSQL KHÔNG tự khởi động lại sau khi VPS reboot. Bật auto-start:

sudo systemctl enable postgresql
sudo service postgresql status

2. Tạo database và user

Vào prompt của PostgreSQL:

sudo -u postgres psql

Tạo user, đặt vài mặc định (encoding, isolation, timezone) rồi tạo database:

CREATE USER <username> WITH ENCRYPTED PASSWORD '<password>';

ALTER ROLE <username> SET client_encoding TO 'utf8';
ALTER ROLE <username> SET default_transaction_isolation TO 'read committed';
ALTER ROLE <username> SET timezone TO 'UTC';

CREATE DATABASE <database_name>
    WITH OWNER = <username>
    ENCODING = 'UTF8'
    TEMPLATE = template0;
\q

3. Mở kết nối từ xa an toàn

Nếu cần kết nối từ máy local hay server khác, làm theo các bước dưới. Nguyên tắc: chỉ cho đúng IP, bắt buộc SSL, và chặn ở cả tường lửa lẫn pg_hba.conf.

Trên máy cần kết nối, lấy IP public của nó:

curl ifconfig.me

Ghi lại IP đó (ví dụ 203.0.113.42).

Cấu hình listen address

sudo nano /etc/postgresql/16/main/postgresql.conf

Thay 16 bằng version PostgreSQL của bạn (ls /etc/postgresql/ để xem). Sửa:

# Chỉ nghe trên localhost và IP public của server
listen_addresses = 'localhost,<server-ip>'
port = 5432

# BẮT BUỘC: bật SSL để mã hóa kết nối
ssl = on

TUYỆT ĐỐI không dùng listen_addresses = '*' trên production.

Cấu hình pg_hba.conf (quan trọng nhất)

File này quyết định AI được phép kết nối.

sudo nano /etc/postgresql/16/main/pg_hba.conf

Xóa/comment dòng nguy hiểm (nếu có), rồi thêm rule chỉ cho đúng IP + bắt buộc SSL vào cuối file:

# NGUY HIỂM - cho phép mọi IP: host all all 0.0.0.0/0 md5
# Rule an toàn: chỉ đúng IP + bắt buộc SSL
hostssl    all    all    203.0.113.42/32    scram-sha-256

Ý nghĩa từng cột:

Thành phầnNghĩa
hostsslBắt buộc kết nối SSL
all (thứ nhất)Áp cho mọi database
all (thứ hai)Áp cho mọi user
203.0.113.42/32Chỉ đúng IP này (/32 = một IP)
scram-sha-256Phương thức xác thực mạnh nhất

Mẹo: thay all bằng tên database và user cụ thể để siết phạm vi hơn nữa.

Tường lửa UFW + restart

# Chỉ cho đúng IP vào port 5432
sudo ufw allow from 203.0.113.42 to any port 5432
# Chặn mọi IP khác
sudo ufw deny 5432
sudo ufw status

sudo systemctl restart postgresql

Hai lớp bảo vệ (UFW + pg_hba.conf) bổ trợ nhau.

4. Kiểm tra kết nối

Xác nhận PostgreSQL đang nghe đúng IP:

sudo ss -lntp | grep 5432

Thử kết nối từ máy local:

psql -h <server-ip> -U <username> -d <database_name>

Phụ lục: Transaction isolation

Khi nhiều request/user cùng đọc-ghi database một lúc, có thể gặp: dirty read (đọc dữ liệu chưa commit), non-repeatable read (đọc cùng bản ghi ra kết quả khác nhau), phantom read (truy vấn sau xuất hiện thêm bản ghi "ma"), lost update (hai request ghi đè nhau). Isolation level quyết định cho phép hay chặn các hiện tượng này.

MứcDirty readNon-repeatablePhantomHiệu năng
READ UNCOMMITTEDKhông (PostgreSQL map về READ COMMITTED)Có thểCó thểCao
READ COMMITTEDKhôngCó thểCó thểCao
REPEATABLE READKhôngKhôngCó thểTrung bình
SERIALIZABLEKhôngKhôngKhôngChậm

PostgreSQL mặc định READ COMMITTED - hợp cho khoảng 90% ứng dụng. Với mức này, mỗi SELECT chỉ thấy dữ liệu đã commit, không thấy dữ liệu transaction khác đang sửa mà chưa commit:

Bảng accounts: id=1, balance=1000

Transaction A                     Transaction B
BEGIN;
UPDATE accounts
  SET balance = 500
  WHERE id = 1;
-- chưa COMMIT
                                  SELECT balance FROM accounts WHERE id = 1;
                                  --> 1000 (không thấy dữ liệu chưa commit)
COMMIT;
                                  SELECT balance FROM accounts WHERE id = 1;
                                  --> 500

Chọn mức nào:

Trường hợpKhuyến nghị
API CRUD thông thườngREAD COMMITTED
Báo cáo, thống kêREAD COMMITTED
Đơn hàng, đặt chỗREPEATABLE READ hoặc SELECT ... FOR UPDATE
Tài chính, kế toánSERIALIZABLE

Vì sao nên SET isolation cho ROLE? PostgreSQL vẫn mặc định READ COMMITTED, nhưng app/migration/script có thể tự đổi mức khác. Đặt cố định ở ROLE đảm bảo mọi kết nối của user đó hành xử nhất quán, tránh việc vô tình đổi mức - dễ debug và dự đoán hơn.

ALTER ROLE app_user SET default_transaction_isolation TO 'read committed';

Tham khảo

  • Tài liệu PostgreSQL
  • pg_hba.conf
Bài tiếp theoMẹo DBeaver: phóng to icon toolbar và sửa lỗi TimeZone

Bài liên quan

  • Migrate database PostgreSQL giữa hai VPS bằng pg_dump và psql

    Di chuyển toàn bộ một database PostgreSQL (schema lẫn data) từ VPS nguồn sang VPS đích qua máy local: dump bằng pg_dump, restore trong một transaction, verify số dòng, cutover và rollback an toàn.

    Database

    Database
  • Kết nối PostgreSQL trên VPS qua SSH Tunnel từ máy local

    Dùng SSH Tunnel để máy dev kết nối PostgreSQL trên VPS mà không phải mở port 5432 ra internet, kèm cách cấu hình DATABASE_URL cho môi trường local và production.

    Database

    Database
  • Tối ưu hiệu suất VPS: swap, PostgreSQL và DB pool

    Tối ưu VPS Ubuntu 16GB RAM chạy nhiều Docker container cùng PostgreSQL: thêm swap để tránh OOM Killer, chỉnh cấu hình PostgreSQL cho RAM lớn và SSD, rồi tăng connection pool trong ứng dụng.

    Database

    Database

Viết bởi Vũ Văn Hải

Tôi là Hải, full-stack developer ở TP. Hồ Chí Minh. Các bài ở đây đúc kết từ những hệ thống tôi tự dựng và vận hành. Cần dựng hoặc gỡ rối một hệ thống tương tự? Cứ nhắn tôi.

Trao đổi dự ánXem thêm hướng dẫn

Thấy sai sót hoặc lệnh không còn chạy? Báo cho tôi

Mục lục

  • 1. Cài đặt PostgreSQL
  • 2. Tạo database và user
  • 3. Mở kết nối từ xa an toàn
  • Cấu hình listen address
  • Cấu hình pg_hba.conf (quan trọng nhất)
  • Tường lửa UFW + restart
  • 4. Kiểm tra kết nối
  • Phụ lục: Transaction isolation
  • Tham khảo