คำตอบสั้น ๆ: ติดตั้ง Keycloak 26 โหมด production ด้วย Docker Compose คู่กับ PostgreSQL หลัง HTTPS สร้างผู้ดูแลถาวร แยก realm พนักงานจาก master และสร้าง client แรกสำหรับ SSO
คู่มือนี้อธิบาย Keycloak ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย
Keycloak คือระบบจัดการตัวตนและ Single Sign-On (SSO) แบบโอเพนซอร์ส ให้พนักงานล็อกอินครั้งเดียวแล้วเข้าได้ทุกแอปที่เชื่อมไว้ผ่านมาตรฐาน OpenID Connect หรือ SAML 2.0 รองรับการยืนยันตัวตนหลายขั้น (OTP) การดึงผู้ใช้จาก LDAP หรือ Active Directory และการปิดบัญชีพนักงานที่ลาออกจากจุดเดียว เหมาะกับองค์กรที่มีแอปภายในหลายตัว เช่น Git Server, Wiki, Grafana และระบบ CI
เมื่อทำตามคู่มือนี้จบ คุณจะมี Keycloak 26 ในโหมด production คู่กับ PostgreSQL อยู่หลัง HTTPS ใช้บัญชีผู้ดูแลถาวรแทนบัญชีชั่วคราวตอนติดตั้ง มี realm สำหรับพนักงานแยกจาก realm master และมี client แรกพร้อมเชื่อมกับแอป
สิ่งที่ต้องเตรียม
- Cloud VPS ที่ใช้ Ubuntu 24.04 พร้อม Docker Engine และ Compose plugin ขนาดเริ่มต้นราว 2 vCPU / RAM 4 GB เพราะรันบน Java เป็นค่าประมาณ ปรับตามจำนวนผู้ใช้และการล็อกอินพร้อมกัน
- ซับโดเมน เช่น
sso.example.comและ Nginx Proxy Manager พร้อมเครือข่ายproxy - บัญชี SMTP สำหรับอีเมลยืนยันและลืมรหัสผ่าน
- รายชื่อแอปที่จะเชื่อม SSO และ URL callback ของแต่ละแอป
ก่อนเริ่มควรเข้าใจสองคำ realm คือพื้นที่แยกกันของผู้ใช้และการตั้งค่า ส่วน client คือแอปแต่ละตัวที่ขอให้ระบบยืนยันตัวตนแทน
ขั้นตอนที่ 1: เตรียม .env และรหัสผ่าน
sudo install -d -o $USER /opt/sso
cd /opt/sso
cat > .env <<EOF
DB_PASSWORD=$(openssl rand -hex 24)
KC_BOOTSTRAP_ADMIN_USERNAME=tempadmin
KC_BOOTSTRAP_ADMIN_PASSWORD=$(openssl rand -base64 18)
EOF
chmod 600 .env
cat .env
บัญชี tempadmin เป็นบัญชีชั่วคราวสำหรับเข้าครั้งแรกเท่านั้น ระบบจะแสดงคำเตือนจนกว่าคุณจะสร้างผู้ดูแลถาวรและลบบัญชีนี้
ขั้นตอนที่ 2: เขียน compose.yaml ในโหมด production
services:
db:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_DB: sso
POSTGRES_USER: sso
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- ./postgres:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U sso -d sso"]
interval: 10s
retries: 5
keycloak:
image: quay.io/keycloak/keycloak:26.8
container_name: keycloak
command: start
restart: unless-stopped
environment:
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://db:5432/sso
KC_DB_USERNAME: sso
KC_DB_PASSWORD: ${DB_PASSWORD}
KC_HOSTNAME: https://sso.example.com
KC_HTTP_ENABLED: "true"
KC_PROXY_HEADERS: xforwarded
KC_HEALTH_ENABLED: "true"
KC_BOOTSTRAP_ADMIN_USERNAME: ${KC_BOOTSTRAP_ADMIN_USERNAME}
KC_BOOTSTRAP_ADMIN_PASSWORD: ${KC_BOOTSTRAP_ADMIN_PASSWORD}
depends_on:
db:
condition: service_healthy
networks:
- default
- proxy
networks:
proxy:
external: true
command: startคือโหมด production ต่างจากstart-devที่ใช้ฐานข้อมูลในตัวและไม่ควรใช้จริงKC_HOSTNAMEใส่เป็น URL เต็ม ทำให้ลิงก์ในอีเมลและค่า issuer ของ token ถูกต้องเสมอKC_HTTP_ENABLEDและKC_PROXY_HEADERSจำเป็นเมื่อ HTTPS สิ้นสุดที่ reverse proxy แล้วส่งต่อเป็น HTTP พร้อม headerX-Forwarded-*- พอร์ต 9000 สำหรับ health และ metrics ไม่ได้ publish และไม่ควรเปิดผ่าน proxy
docker compose up -d
docker compose logs -f keycloak
การเริ่มครั้งแรกใช้เวลาราว 1–2 นาที เพราะระบบ build การตั้งค่าและสร้างตารางในฐานข้อมูล รอจนล็อกแสดงว่าเริ่มทำงานในโหมด production แล้ว
ขั้นตอนที่ 3: เปิด HTTPS และจำกัดหน้าแอดมิน
ใน Nginx Proxy Manager เพิ่ม Proxy Host กรอก Domain Names sso.example.com, Forward Hostname keycloak, Forward Port 8080 เปิด Block Common Exploits ขอใบรับรองพร้อม Force SSL และ HSTS
เส้นทาง /realms/ และ /resources/ ต้องเข้าถึงได้จากทุกที่ เพราะผู้ใช้ล็อกอินผ่านเส้นทางเหล่านี้ แต่ /admin/ ควรจำกัดเฉพาะ IP สำนักงานหรือ VPN ในแท็บ Custom Locations กด Add Location ใส่ location /admin/ ส่งต่อไปที่ keycloak พอร์ต 8080 แล้วใส่คำสั่งนี้ในช่องคอนฟิกเพิ่มเติมของ location นั้น
allow 198.51.100.0/24;
deny all;