ข้ามไปยังเนื้อหา

Production Checklist

โหมด start-dev มีไว้สำหรับการพัฒนาในเครื่องเท่านั้น โหมดนี้ปิด optimised build ใช้ embedded H2 database สร้าง self-signed certificate และผ่อนปรนการตรวจสอบ hostname ค่าเริ่มต้นเหล่านี้ไม่ปลอดภัยใน production เมื่อพร้อม go live มีสี่สิ่งที่คุณต้องจัดการ

โดยค่าเริ่มต้น start-dev ใช้ embedded H2 database ที่อยู่ภายใน container รีสตาร์ท container แล้วข้อมูลทั้งหมดหาย ใน production ให้ชี้ Keycloak ไปยัง external database — PostgreSQL คือตัวเลือกที่แนะนำ

ตั้งค่า environment variable เหล่านี้:

KC_DB=postgres
KC_DB_URL=jdbc:postgresql://db-host:5432/keycloak
KC_DB_USERNAME=keycloak
KC_DB_PASSWORD=<secret>

Keycloak ฝัง hostname ของตัวเองใน token issuer, OIDC discovery document และการตรวจสอบ redirect หาก hostname ไม่ถูกต้อง token จะถูกปฏิเสธโดย client ตั้งค่าอย่างชัดเจน:

KC_HOSTNAME=auth.example.com

สำหรับการทดสอบในเครื่องหลัง reverse proxy คุณอาจต้องใช้ KC_HOSTNAME_STRICT=false ด้วย แต่อย่าใช้ flag นี้ใน production

Keycloak ต้องให้บริการผ่าน HTTPS มีสองตัวเลือกทั่วไป:

  • Edge termination (แนะนำ): reverse proxy (Nginx, Traefik, AWS ALB) จัดการ TLS และส่งต่อ plain HTTP ไปยัง Keycloak บอก Keycloak ให้เชื่อถือ proxy header:

    KC_PROXY_HEADERS=xforwarded
  • Passthrough: Keycloak จัดการ TLS เอง ให้ certificate และ private key ผ่าน KC_HTTPS_CERTIFICATE_FILE และ KC_HTTPS_CERTIFICATE_KEY_FILE

ใน production ให้รัน kc.sh build ก่อน kc.sh start ขั้นตอน build คอมไพล์ provider configuration, augment Quarkus app และ cache classpath scanning — ลดเวลา startup จาก ~30 วินาที เป็น ~3 วินาที การ deploy ด้วย Docker ส่วนใหญ่ทำในรูปแบบ multi-stage Dockerfile:

Terminal window
# Build stage
kc.sh build --db=postgres
# Runtime stage
kc.sh start --optimized

นี่คือ docker run ขั้นต่ำที่รวมสี่สิ่งที่ต้องมีทั้งหมด:

docker run -d --name keycloak \
  -p 8080:8080 \
  -e KC_DB=postgres \
  -e KC_DB_URL=jdbc:postgresql://db:5432/keycloak \
  -e KC_DB_USERNAME=keycloak \
  -e KC_DB_PASSWORD=${DB_PASSWORD} \
  -e KC_HOSTNAME=auth.example.com \
  -e KC_PROXY_HEADERS=xforwarded \
  -e KEYCLOAK_ADMIN=admin \
  -e KEYCLOAK_ADMIN_PASSWORD=${ADMIN_PASSWORD} \
  quay.io/keycloak/keycloak:latest \
  start --optimized

ส่ง DB_PASSWORD และ ADMIN_PASSWORD จาก secrets manager ของคุณ — อย่า hardcode ใน command

การคลิกใน admin console ด้วยมือไม่สามารถทำซ้ำได้ Export configuration ของ realm เป็น JSON และ commit ไปยัง version control:

Terminal window
# Export a realm
/opt/keycloak/bin/kc.sh export --realm my-app --file /tmp/my-app-realm.json
# Import on startup
/opt/keycloak/bin/kc.sh start --import-realm

วาง my-app-realm.json ไว้ใน /opt/keycloak/data/import/ แล้ว Keycloak จะ import อัตโนมัติตอน start ครั้งแรก ทำให้ realm configuration สามารถทำซ้ำได้ทุก environment

state ของ Keycloak อยู่ใน external database ทั้งหมด Backup database โดยใช้กลไก backup มาตรฐานของ database provider ของคุณ container เองไม่มี state และไม่จำเป็นต้อง backup — เพียงตรวจสอบว่า realm export JSON อยู่ใน version control เป็น baseline ของ configuration

ตัวเลือกBenefitCost
Edge TLS termination (reverse proxy)ดูแล certificate ที่จุดเดียว (Nginx/Traefik/ALB) รองรับ rolling cert renewal ได้ง่ายต้องตั้งค่า KC_PROXY_HEADERS ให้ถูกต้อง มิฉะนั้น Keycloak จะมองเห็น protocol/host ผิดและ redirect พัง
TLS passthrough (Keycloak จัดการเอง)ไม่ต้องพึ่ง proxy เพิ่ม เหมาะกับ deployment ที่เรียบง่ายต้องจัดการ certificate lifecycle เองภายใน Keycloak ทุก instance
Optimised build (kc.sh build ล่วงหน้า)ลดเวลา startup จาก ~30 วินาที เหลือ ~3 วินาที เหมาะกับ container ที่ scale ขึ้น-ลงบ่อยต้องเพิ่มขั้นตอน build แยกใน CI/CD และ rebuild image ทุกครั้งที่เปลี่ยน provider config
  • รัน start-dev ใน production — ยังใช้ embedded H2 database, self-signed certificate และผ่อนปรนการตรวจสอบ hostname ทำให้ข้อมูลหายเมื่อ container restart และเปิดช่องโหว่ด้านความปลอดภัยหลายจุดพร้อมกัน
  • เปิด /metrics หรือ /health endpoint ออกสู่ public โดยไม่จำกัดการเข้าถึง — endpoint เหล่านี้เปิดเผยข้อมูล internal ของระบบ ควรจำกัดให้เข้าถึงได้เฉพาะจาก internal network หรือ monitoring system เท่านั้น
  • ไม่ตั้งค่า KC_HOSTNAME ให้ตรงกับ domain จริง — ทำให้ token issuer และ OIDC discovery document ไม่ตรงกับที่ client คาดหวัง client จะปฏิเสธ token แม้ Keycloak ทำงานปกติทุกอย่าง

💡 ตัวอย่างจากของจริง

Production checklist มาตรฐานของทีม platform — ทีม infrastructure ส่วนใหญ่ผูก external PostgreSQL, fixed hostname ผ่าน DNS, TLS ผ่าน reverse proxy และ multi-node clustering เข้าด้วยกันเป็น deployment template เดียว แล้วใช้ realm export/import เพื่อให้ config เดิมซ้ำได้ทุก environment

High-availability clustering — องค์กรที่ต้องการ uptime สูงรัน Keycloak หลาย instance หลัง load balancer โดยแชร์ external database ตัวเดียวกัน ทำให้ instance ใดตายไปหนึ่งตัว session ของผู้ใช้ก็ยังไม่หลุด

start-dev ใช้ database ใดเป็นค่าเริ่มต้น?
KC_PROXY_HEADERS=xforwarded บอกอะไรกับ Keycloak?
ทำไมคุณควรรัน kc.sh build ก่อน kc.sh start ใน production?
คุณทำให้ Keycloak import realm อัตโนมัติตอน startup ครั้งแรกได้อย่างไร?