Cài đặt Keycloak trên CentOS Stream 9: Dựng hệ thống SSO chuẩn Production với PostgreSQL 16 và Nginx

Quick start: Dựng cụm Keycloak và PostgreSQL trong 5 phút

Doanh nghiệp vận hành chục ứng dụng nội bộ từ Jira, GitLab đến CRM thường đối mặt cùng một vấn đề: người dùng quên mật khẩu liên tục. Khi một nhân sự nghỉ việc, IT phải rà soát và thu hồi tài khoản thủ công trên từng hệ thống. Việc này vừa tốn thời gian, vừa dễ sót lọt. Keycloak xử lý triệt để bài toán này qua mô hình Single Sign-On (SSO): một tài khoản truy cập mọi dịch vụ, quản lý quyền tập trung trên một giao diện duy nhất.

Dưới đây là các bước dựng nhanh cụm dịch vụ trên CentOS Stream 9 với Java 17, PostgreSQL 16 và Keycloak Quarkus.

1. Cài đặt OpenJDK 17 và PostgreSQL 16

# Cập nhật hệ điều hành và cài các gói phụ trợ
sudo dnf update -y
sudo dnf install -y java-17-openjdk-headless wget tar

# Thêm repository chính thức của PostgreSQL cho EL9
sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
sudo dnf -qy module disable postgresql
sudo dnf install -y postgresql16-server postgresql16

# Khởi tạo dữ liệu và bật service
sudo /usr/pgsql-16/bin/postgresql-16-setup initdb
sudo systemctl enable --now postgresql-16

2. Khởi tạo Database và User cho Keycloak

Từ PostgreSQL 15 trở đi, quyền tạo object trên schema public đã bị khóa mặc định. Bạn cần gán quyền trực tiếp trên schema của database keycloak:

sudo -u postgres psql -c "CREATE DATABASE keycloak;"
sudo -u postgres psql -c "CREATE USER keycloak WITH ENCRYPTED PASSWORD 'MatKhauSieuKho2026!';"
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE keycloak TO keycloak;"

# Kết nối vào đúng database keycloak để cấp quyền schema public
sudo -u postgres psql -d keycloak -c "GRANT ALL ON SCHEMA public TO keycloak;"

3. Tải Keycloak và chạy kiểm tra ở chế độ Development

cd /opt
sudo wget https://github.com/keycloak/keycloak/releases/download/24.0.2/keycloak-24.0.2.tar.gz
sudo tar -xvzf keycloak-24.0.2.tar.gz
sudo mv keycloak-24.0.2 keycloak

# Khởi tạo tài khoản admin ban đầu và chạy thử ở port 8080
export KEYCLOAK_ADMIN=admin
export KEYCLOAK_ADMIN_PASSWORD=AdminSecurePass123!
/opt/keycloak/bin/kc.sh start-dev

Truy cập http://<IP-server>:8080 để kiểm tra trang Admin Console trước khi chuyển sang cấu hình production.

Kiến trúc vận hành: Tại sao cần Keycloak, PostgreSQL và Nginx?

Để phục vụ từ vài trăm đến hàng chục nghìn active session ổn định, mô hình 3 tầng phân tách trách nhiệm rõ ràng:

  • Keycloak (Identity Provider – IdP): Đảm nhận toàn bộ luồng xác thực OIDC, OAuth2 và SAML 2.0. Keycloak sinh JWT token, xử lý refresh token, quản lý phiên đăng nhập và phân quyền RBAC cho các ứng dụng client.
  • PostgreSQL (Storage Layer): Lưu trữ bền vững tài khoản, realm, client secret và audit log. Keycloak tích hợp sẵn database H2, nhưng H2 chỉ phục vụ thử nghiệm cục bộ và sẽ hỏng dữ liệu khi chịu tải đồng thời.
  • Nginx (Reverse Proxy & SSL Termination): Đóng vai trò chốt chặn bảo vệ Keycloak. Nginx giải mã HTTPS, kiểm soát SSL cipher, nén header và điều phối gói tin an toàn vào port nội bộ 8080.

Cấu hình Keycloak Production Mode kết nối PostgreSQL

Mở file /opt/keycloak/conf/keycloak.conf và thiết lập thông số kết nối:

# /opt/keycloak/conf/keycloak.conf

# Database configuration
db=postgres
db-username=keycloak
db-password=MatKhauSieuKho2026!
db-url=jdbc:postgresql://127.0.0.1:5432/keycloak

# Reverse proxy configuration (chuẩn mới cho Keycloak 24+)
proxy-headers=xforwarded
http-enabled=true
hostname=sso.example.com

Chạy build lại ứng dụng để Quarkus tối ưu hóa cấu hình trước khi chạy daemon:

cd /opt/keycloak
sudo ./bin/kc.sh build

Triển khai Production với Systemd, SELinux và Nginx

1. Tạo user riêng biệt và cấu hình Systemd Service

Không bao giờ chạy tiến trình ứng dụng bằng user root trên môi trường production:

sudo useradd -r -d /opt/keycloak -s /sbin/nologin keycloak
sudo chown -R keycloak:keycloak /opt/keycloak

# Tạo file unit systemd
sudo tee /etc/systemd/system/keycloak.service << 'EOF'
[Unit]
Description=Keycloak Identity Provider Server
After=network.target postgresql-16.service
Wants=postgresql-16.service

[Service]
Type=exec
User=keycloak
Group=keycloak
ExecStart=/opt/keycloak/bin/kc.sh start --optimized
Restart=on-failure
RestartSec=10
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now keycloak

2. Cấu hình Nginx Reverse Proxy kèm HTTPS

Cài đặt Nginx:

sudo dnf install -y nginx
sudo systemctl enable --now nginx

Tạo virtual host tại /etc/nginx/conf.d/keycloak.conf. Lưu ý tăng kích thước buffer để tránh lỗi 502 Bad Gateway khi Keycloak trả về header chứa cookie hoặc JWT token lớn:

server {
    listen 80;
    server_name sso.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name sso.example.com;

    ssl_certificate /etc/pki/tls/certs/sso.example.com.crt;
    ssl_certificate_key /etc/pki/tls/private/sso.example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;

        # Buffer headers xử lý JWT token dung lượng lớn
        proxy_buffer_size 128k;
        proxy_buffers 4 256k;
        proxy_busy_buffers_size 256k;
    }
}

Kiểm tra cú pháp và kích hoạt cấu hình:

sudo nginx -t
sudo systemctl reload nginx

Kinh nghiệm thực tế khi vận hành Keycloak

1. Lỗi SELinux chặn kết nối giữa Nginx và Keycloak

Sau khi thiết lập xong Nginx, người quản trị thường gặp lỗi 502 Bad Gateway. Khi kiểm tra /var/log/nginx/error.log, bạn sẽ thấy dòng thông báo Permission denied while connecting to upstream. SELinux trên RHEL/CentOS 9 mặc định chặn tiến trình web kết nối ra mạng nội bộ. Bạn chỉ cần bật cờ boolean:

sudo setsebool -P httpd_can_network_connect 1

2. Cân đối RAM và Heap Size cho JVM

Phiên bản Keycloak nền Quarkus khởi động trong khoảng 3 đến 5 giây, nhanh hơn gấp nhiều lần nền tảng WildFly cũ (thường mất 30-45 giây). Dung lượng RAM chiếm dụng ban đầu chỉ khoảng 450MB. Tuy nhiên, khi hệ thống chạm mốc 1.000 người dùng trực tuyến, JVM sẽ tự mở rộng bộ nhớ.

Trên máy chủ 4GB RAM, bạn nên khống chế heap size rõ ràng. Tạo file /opt/keycloak/conf/kc.opts:

JAVA_OPTS_APPEND="-Xms512m -Xmx2048m -XX:+UseG1GC"

3. Thiết lập bắt buộc 2FA/MFA cho Master Realm

Máy chủ IdP là đích ngắm hàng đầu của các cuộc tấn công leo thang đặc quyền. Đăng nhập vào Master Realm, chọn mục Authentication > Required Actions, sau đó đánh dấu bật Configure OTP và đặt thành Default Action. Mọi tài khoản quản trị viên sẽ bị buộc liên kết Google Authenticator hoặc YubiKey ngay lần đăng nhập đầu tiên.

Share: