Cài đặt PostgreSQL với các flag bảo mật cần thiết
Chuẩn bị môi trường và cài đặt từ package
Chúng ta sẽ sử dụng gói cài đặt từ repository chính thức của PostgreSQL để đảm bảo tính tương thích và an toàn. Việc cài đặt từ source (compile từ source code) thường phức tạp hơn và dễ sai sót trong môi trường sản xuất nếu không có kinh nghiệm sâu về build system.
Trên hệ điều hành Linux (Ubuntu/Debian), chúng ta cần thêm repository chính thức, cập nhật cache và cài đặt với các tùy chọn kiểm tra checksum.
Thực hiện các lệnh sau trên từng nút (Node) của cụm (Node 1, Node 2, Node 3):
curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list
sudo apt-get update
sudo apt-get install -y postgresql-15 postgresql-contrib-15 postgresql-client-15
Kết quả mong đợi: Quá trình cài đặt hoàn tất, không có lỗi dependency. Các thư mục dữ liệu mặc định sẽ được tạo tại `/var/lib/postgresql/15/main`.
Thiết lập quyền sở hữu và bảo mật thư mục dữ liệu
Để đảm bảo tính bảo mật, thư mục dữ liệu của PostgreSQL phải thuộc quyền sở hữu của user `postgres` và chỉ có quyền đọc/ghi cho owner (700). Nếu không, PostgreSQL sẽ từ chối khởi động.
Thay đổi quyền sở hữu và mode của thư mục dữ liệu:
sudo chown -R postgres:postgres /var/lib/postgresql/15/main
sudo chmod -R 700 /var/lib/postgresql/15/main
Kết quả mong đợi: User `postgres` là chủ sở hữu duy nhất. Các user khác (kể cả root) không thể đọc trực tiếp nội dung thư mục này trừ khi chạy dưới quyền root, nhưng PostgreSQL sẽ chạy dưới quyền `postgres` nên an toàn.
Cấu hình file postgresql.conf
Tối ưu hóa bộ nhớ và tham số mạng
File cấu hình chính `postgresql.conf` nằm ở `/etc/postgresql/15/main/postgresql.conf`. Chúng ta cần điều chỉnh `shared_buffers` để tận dụng RAM cho bộ đệm dữ liệu, thiết lập `wal_level` chuẩn bị cho cơ chế Raft (replication), và giới hạn `max_connections` để tránh cạn kiệt tài nguyên hệ thống.
Tạo file cấu hình mới hoặc ghi đè nội dung quan trọng vào file hiện tại. Dưới đây là nội dung hoàn chỉnh cho các tham số cốt lõi:
listen_addresses = '*'
port = 5432
max_connections = 100
shared_buffers = 256MB
effective_cache_size = 768MB
wal_level = replica
wal_log_hints = on
max_wal_senders = 3
max_replication_slots = 3
synchronous_commit = on
checkpoint_completion_target = 0.9
Giải thích chi tiết:
- `wal_level = replica`: Bắt buộc để hỗ trợ streaming replication (nền tảng của Raft).
- `wal_log_hints = on`: Đảm bảo các thao tác WAL được ghi cho cả các thao tác hint, giúp recovery nhanh hơn.
- `synchronous_commit = on`: Đảm bảo dữ liệu được ghi vào disk trước khi trả về kết quả (tính nhất quán mạnh).
Kết quả mong đợi: Khi khởi động lại service, PostgreSQL sẽ áp dụng các cấu hình này. Tham số `wal_level` hiển thị là `replica`.
Kích hoạt SSL cho kết nối
Để chuẩn bị cho `pg_hba.conf` yêu cầu SSL, chúng ta phải bật SSL trong `postgresql.conf` và chỉ định đường dẫn đến chứng chỉ (certificate) và khóa riêng (private key).
Sửa file `/etc/postgresql/15/main/postgresql.conf` thêm các dòng sau:
ssl = on
ssl_cert_file = '/etc/ssl/certs/ssl-cert-snakeoil.pem'
ssl_key_file = '/etc/ssl/private/ssl-cert-snakeoil-key'
Giải thích: Trên Ubuntu/Debian, `ssl-cert-snakeoil` là chứng chỉ tự ký mặc định dùng cho môi trường nội bộ. Trong môi trường sản xuất, bạn nên thay thế bằng chứng chỉ CA uy tín hoặc tự ký nội bộ (CA riêng).
Kết quả mong đợi: File cấu hình đã cập nhật. Lưu ý: Cần restart service PostgreSQL để áp dụng thay đổi này.
Cấu hình file pg_hba.conf cho kết nối nội bộ qua SSL
Thiết lập chính sách truy cập
File `pg_hba.conf` nằm ở `/etc/postgresql/15/main/pg_hba.conf`. Mục tiêu là chỉ cho phép các nút trong cụm kết nối với nhau thông qua giao thức SSL. Kết nối không SSL sẽ bị từ chối.
Thay thế toàn bộ nội dung của file bằng cấu hình dưới đây để đảm bảo an toàn tuyệt đối:
local all postgres peer
local all all peer
hostssl all all 10.0.0.0/24 scram-sha-256
host all all 10.0.0.0/24 reject
hostssl all all 0.0.0.0/0 scram-sha-256
host all all 0.0.0.0/0 reject
Giải thích chi tiết:
- `local`: Kết nối qua Unix socket, dùng cho user postgres và local user, xác thực bằng `peer` (tên user hệ thống phải trùng tên user DB).
- `hostssl ... 10.0.0.0/24`: Cho phép kết nối từ mạng nội bộ (giả sử subnet của cụm là 10.0.0.x) BẮT BUỘC dùng SSL (`hostssl`).
- `host ... reject`: Từ chối bất kỳ kết nối TCP nào không dùng SSL từ subnet này.
- `scram-sha-256`: Sử dụng cơ chế băm mật khẩu an toàn (Secure Remote Password).
Kết quả mong đợi: Chỉ các kết nối có SSL mới được chấp nhận từ mạng nội bộ. Kết nối không SSL sẽ bị từ chối ngay lập tức.
Tạo role quản trị viên và khởi động dịch vụ
Khởi động lại PostgreSQL
Sau khi cấu hình xong cả `postgresql.conf` và `pg_hba.conf`, bạn phải khởi động lại dịch vụ để các thay đổi có hiệu lực. Nếu không, cấu hình mới sẽ không được áp dụng.
sudo systemctl restart postgresql
Kết quả mong đợi: Service khởi động thành công. Kiểm tra trạng thái bằng `sudo systemctl status postgresql` phải thấy `active (running)`.
Tạo role quản trị viên với quyền cao
Chúng ta cần tạo một role quản trị viên (superuser) để thực hiện các thao tác cấu hình phức tạp sau này (như tạo slot replication, backup). Role này sẽ được bảo vệ bởi mật khẩu mạnh.
Chuyển sang user `postgres` và sử dụng `psql` để tạo role:
sudo -u postgres psql -c "CREATE ROLE admin WITH LOGIN SUPERUSER PASSWORD 'SecureP@ssw0rd2024!';"
Giải thích:
- `SUPERUSER`: Cấp quyền cao nhất.
- `LOGIN`: Cho phép role này đăng nhập vào database.
- `PASSWORD`: Đặt mật khẩu mạnh tuân thủ chính sách bảo mật.
Kết quả mong đợi: Lệnh trả về `CREATE ROLE`. Role `admin` đã được tạo và có thể sử dụng để kết nối từ xa qua SSL.
Verify kết quả cấu hình
Để đảm bảo mọi thứ hoạt động đúng, thực hiện các bước kiểm tra sau:
sudo -u postgres psql -c "SHOW ssl;"
sudo -u postgres psql -c "SHOW wal_level;"
sudo -u postgres psql -c "SELECT usename FROM pg_user WHERE usename = 'admin';"
Kết quả mong đợi:
- Lệnh 1 trả về: `on` (SSL đã bật).
- Lệnh 2 trả về: `replica` (Chuẩn bị cho Raft).
- Lệnh 3 trả về: `admin` (Role đã tồn tại).
Thử kết nối từ xa (nếu đã cấu hình mạng) hoặc kiểm tra file log để đảm bảo không có lỗi từ chối kết nối SSL:
sudo tail -f /var/log/postgresql/postgresql-15-main.log
Điều hướng series:
Mục lục: Series: Xây dựng Database phân tán an toàn với PostgreSQL, Raft và TDE
« Phần 1: Chuẩn bị môi trường và kiến trúc tổng quan cho hệ thống phân tán
Phần 3: Triển khai cơ chế đồng bộ Raft cho tính nhất quán dữ liệu »