SSD Nodes Learn 🎉 VPS เริ่ม $5.50/เดือน
คู่มือ Matt Connorโดย Matt Connor

ภาษี SSO ในซอฟต์แวร์ Self-hosted คืออะไรและทำไมต้องจ่าย

ทำความเข้าใจเหตุผลที่ผู้พัฒนาซอฟต์แวร์จำกัดฟีเจอร์ OIDC และ SAML ไว้ในแผนชำระเงิน พร้อมรายการตรวจสอบสำคัญที่คุณควรพิจารณาก่อนติดตั้งแอปพลิเคชันเพื่อจัดการระบบยืนยันตัวตนให้มีประสิทธิภาพ

ภาษี SSO คืออะไร

ภาษี SSO ในซอฟต์แวร์แบบ self-hosted คือรูปแบบที่ตัวแอปพลิเคชันเปิดให้ใช้งานฟรี แต่ฟีเจอร์ Single Sign-On (SSO) กลับเป็นสิ่งเดียวที่คุณต้องจ่ายเงินซื้อ คุณสามารถรันซอฟต์แวร์ทั้งหมดบน VPS ของคุณเองได้โดยไม่ต้องใช้ licence key หรือจำกัดจำนวนผู้ใช้งาน แต่เมื่อคุณเปิดหน้าเอกสารประกอบเพื่อตั้งค่าการยืนยันตัวตน คุณจะพบว่า OpenID Connect (OIDC) หรือ SAML (security assertion markup language) ถูกจำกัดไว้เฉพาะในแผนแบบเสียค่าใช้จ่ายเท่านั้น

เรื่องนี้มีความสำคัญมากกว่าฟีเจอร์ทั่วไปที่ถูกกั้นด้วยกำแพงราคา เพราะ SSO คือสิ่งที่ทำให้ชุดบริการแบบ self-hosted ทำงานเสมือนเป็นระบบเดียวกัน Identity Provider (IdP) ช่วยให้คุณมีบัญชีผู้ใช้เพียงหนึ่งบัญชีต่อคน มีนโยบายรหัสผ่านชุดเดียว มีจุดเดียวสำหรับเปิดใช้งาน multi-factor authentication (MFA) และมีจุดเดียวสำหรับระงับสิทธิ์การเข้าถึง หากไม่มี SSO แต่ละแอปจะเก็บฐานข้อมูลผู้ใช้แยกกัน และคุณจะต้องคอยดูแลจัดการข้อมูลในแต่ละแอปด้วยตนเอง

รูปแบบนี้มีมานานพอที่จะมีตารางคะแนนสาธารณะ โดย SSO Wall of Shame ที่ sso.tax ได้รวบรวมรายชื่อผู้ให้บริการที่เรียกเก็บค่าธรรมเนียมในราคาสูงสำหรับการใช้งาน SSO โดยมีข้อมูลย้อนหลังไปถึงปี 2018 ซึ่งผู้จัดทำได้ตั้งเกณฑ์ไว้อย่างเป็นธรรมว่า "หากการรองรับ SSO ของคุณทำให้ราคาเพิ่มขึ้นเพียง 10% คุณจะไม่อยู่ในรายการนี้" รายชื่อส่วนใหญ่ในนั้นเป็นซอฟต์แวร์แบบปิด แต่ตรรกะการตั้งราคาแบบเดียวกันนี้กำลังปรากฏในโครงการโอเพนซอร์สที่คุณโฮสต์ด้วยตัวเองเช่นกัน

เหตุผลที่ผู้ดูแลโครงการนำ Single Sign-on ไปไว้ในระดับที่ต้องชำระเงิน

มีเหตุผลสองประการและทั้งสองประการเป็นเหตุผลที่ตรงไปตรงมา SSO มีค่าใช้จ่ายในการสนับสนุนสูง และเป็นหนึ่งในฟีเจอร์ไม่กี่อย่างที่องค์กรขนาดใหญ่ยอมจ่ายเงินซื้อ

ต้นทุนในการสนับสนุนเป็นเรื่องจริงเนื่องจากการเชื่อมต่อระบบยืนยันตัวตนไม่มีวันเสร็จสิ้น IdP แต่ละรายมีการจัดรูปแบบ claim ที่แตกต่างกันเล็กน้อย การจับคู่กลุ่ม (group mapping), ระยะเวลาของเซสชัน (session lifetime), URL สำหรับเปลี่ยนเส้นทาง (redirect URL) และความคลาดเคลื่อนของเวลา (clock skew) ล้วนทำให้เกิดบั๊กในการเข้าสู่ระบบ และบั๊กการเข้าสู่ระบบจะทำให้ผู้ใช้ทุกคนเข้าใช้งานไม่ได้พร้อมกัน ดังนั้นตั๋วแจ้งปัญหาเหล่านี้จึงมีความเร่งด่วน จากนั้นจึงมีคำขอติดตามผลตามมา เช่น กลุ่มที่ซ้อนกัน (nested groups), การจับคู่บทบาท (role mapping), การจัดเตรียมผู้ใช้อัตโนมัติด้วย SCIM (System for Cross-domain Identity Management) และบันทึกการตรวจสอบ (audit log) ที่ทีมกำกับดูแลจะเข้ามาตรวจสอบ

ในด้านรายได้นั้นเป็นเรื่องของตัวเลขทางธุรกิจไม่ใช่เจตนาที่ไม่ดี บริษัทที่ไม่สามารถเชื่อมต่อแอปพลิเคชันเข้ากับ IdP ของตนเองได้จะไม่นำแอปนั้นไปใช้งานเลย ดังนั้น SSO จึงเป็นเส้นแบ่งที่ชัดเจนระหว่างผู้ใช้ที่จ่ายเงินและผู้ใช้ที่ไม่จ่ายเงิน โครงการแบบ open core จำเป็นต้องกำหนดเส้นแบ่งนั้นไว้ที่ใดที่หนึ่ง และ SSO ก็เป็นฟีเจอร์ที่วางอยู่บนเส้นแบ่งนั้นได้อย่างเหมาะสมที่สุด ซึ่งเป็นเหตุผลว่าทำไมหลายโครงการจึงเลือกใช้ฟีเจอร์นี้

ข้อแก้ไขหนึ่งสำหรับข้อร้องเรียนที่พบบ่อยคือ ให้ตรวจสอบ changelog ก่อนที่คุณจะสรุปว่าฟีเจอร์ถูกถอดออกไป เพราะการถอดฟีเจอร์จะปรากฏอยู่ใน release notes จากโครงการที่ผมตรวจสอบสำหรับบทความนี้ ฟีเจอร์ SSO แบบชำระเงินถูกสร้างขึ้นมาสำหรับระดับที่ต้องชำระเงินตั้งแต่ต้น ผมไม่พบกรณีที่มีการถอดฟีเจอร์ SSO แบบฟรีที่เคยใช้งานได้ออกไป Grafana เป็นตัวอย่างทั่วไปในเรื่องนี้ หน้า SAML ของ Grafana มีหมายเหตุบรรทัดเดียวระบุว่า "Available in Grafana Enterprise and Grafana Cloud" ในขณะที่การใช้งาน OAuth ทั่วไปกับ issuer ของคุณเองยังคงใช้งานได้ในรุ่น open source

ต้นทุนที่แท้จริงของภาษี SSO

จำนวนเงินเป็นเพียงส่วนน้อยเท่านั้น แพ็กเกจแบบชำระเงินจะคิดราคาต่อผู้ใช้งาน ดังนั้นค่าใช้จ่ายจะเพิ่มขึ้นตามขนาดทีมของคุณ ในขณะที่การโฮสต์และการอัปเกรดซอฟต์แวร์ยังคงเป็นหน้าที่ของคุณ

ต้นทุนที่มากกว่าคือภาระงานด้านการจัดการตัวตนแบบทำมือ ซึ่งส่งผลกระทบใน 4 ด้านดังนี้:

  • ต้องมีที่เก็บรหัสผ่านแยกกันในแต่ละแอป ดังนั้นหากมีการใช้รหัสผ่านซ้ำ จะกลายเป็นช่องโหว่ของทุกแอปที่ใช้รหัสผ่านนั้นร่วมกัน
  • การยกเลิกสิทธิ์การเข้าถึงต้องอาศัยความจำ คุณต้องจำให้ได้ว่าพนักงานแต่ละคนเคยเข้าถึงบริการใดบ้าง และบริการที่คุณลืมนั่นแหละคือจุดที่สำคัญที่สุด
  • การตั้งค่า MFA ต้องทำแยกกันทีละแอป หากแอปนั้นรองรับฟีเจอร์ดังกล่าว
  • การใช้บัญชีเข้าสู่ระบบร่วมกัน ซึ่งเป็นสิ่งที่เกิดขึ้นจริงในทีมขนาดเล็กภายใต้แรงกดดันนี้

ประเด็นสุดท้ายนี้ควรค่าแก่การกล่าวถึงเป็นพิเศษ เมื่อทีมใช้บัญชีผู้ดูแลระบบบัญชีเดียวในโปรแกรมจัดการเอกสาร บันทึกการตรวจสอบ (audit trail) จะระบุชื่อผู้ใช้งานเพียงชื่อเดียวสำหรับทุกกิจกรรม ทำให้คุณไม่สามารถทราบได้ว่าใครเป็นผู้ลบใบแจ้งหนี้ นอกจากนี้ การกำหนดสิทธิ์รายบุคคลจะใช้งานไม่ได้อีกต่อไปเนื่องจากมีผู้ใช้งานเพียงบัญชีเดียว นี่คือความเสียหายที่แท้จริงจากภาษี SSO เพราะมันบีบให้ทีมขนาดเล็กต้องหันไปใช้บัญชีร่วมกัน ซึ่งเป็นทางเลือกที่แย่กว่าทางเลือกอื่นทั้งหมด

รายการตรวจสอบก่อนที่คุณจะเริ่มใช้งานสิ่งใดก็ตาม

ให้ดำเนินการตรวจสอบนี้ก่อนที่จะถึงขั้นตอน docker compose up ไม่ใช่หลังจากที่แอปพลิเคชันมีเอกสารสะสมอยู่แล้ว 400 ฉบับ

  1. เปิดหน้าการยืนยันตัวตนในเอกสารประกอบและอ่านหมายเหตุเกี่ยวกับระดับการใช้งานที่ด้านบน ฟีเจอร์ที่ต้องชำระเงินจะมีป้ายกำกับหรือประโยคระบุความพร้อมใช้งานกำกับไว้หนึ่งบรรทัด
  2. ยืนยันว่าแอปพลิเคชันรองรับ OIDC หรือ SAML กับผู้ให้บริการยืนยันตัวตน (issuer) ของคุณเอง ไม่ใช่แค่รายการผู้ให้บริการสาธารณะที่กำหนดไว้ตายตัว
  3. ตรวจสอบการจับคู่บทบาท (role) และกลุ่ม (group) การสร้างผู้ใช้เป็นเพียงครึ่งหนึ่งของงาน ส่วนที่เหลือที่สร้างความลำบากคือการกำหนดสิทธิ์ด้วยตนเองในแอปพลิเคชันจำนวนสิบรายการ
  4. ตรวจสอบว่าแอปพลิเคชันยอมรับชื่อผู้ใช้ที่ผ่านการยืนยันตัวตนผ่าน header จาก proxy ที่เชื่อถือได้หรือไม่ และคุณสามารถระบุได้หรือไม่ว่าแอปพลิเคชันนั้นเชื่อถือ proxy ตัวใด
  5. อ่านประวัติใบอนุญาตใน git และตรวจสอบว่าผู้ร่วมพัฒนาได้ลงนามใน CLA (contributor licence agreement) หรือไม่
  6. ตรวจสอบขั้นตอนการยกเลิกสิทธิ์ (offboarding) ค้นหาว่าเกิดอะไรขึ้นกับ API (application programming interface) tokens และเซสชันที่ยังคงค้างอยู่ เมื่อบัญชี IdP ถูกปิดใช้งาน

ข้อ 2 คือจุดที่ทำให้เกิดความผิดหวังมากที่สุด ปุ่ม "Sign in with Google" ไม่ใช่ OIDC กับผู้ให้บริการยืนยันตัวตนของคุณ แต่มันคือการเชื่อมต่อแบบตายตัวกับผู้ให้บริการรายเดียว การรองรับที่แท้จริงจะต้องให้คุณระบุ issuer URL และข้อมูลที่เหลือจะถูกดึงมาผ่านกระบวนการ discovery คุณสามารถยืนยันฝั่งของผู้ให้บริการของคุณได้ด้วยคำสั่งเดียว

curl -s https://id.example.com/.well-known/openid-configuration \
  | jq '.issuer, .authorization_endpoint, .token_endpoint'

จะมี URL สามรายการส่งกลับมาจากผู้ให้บริการที่ทำงานปกติ ผลลัพธ์ที่ว่างเปล่าหรือ 404 มักหมายความว่า path ของ discovery ไม่ถูกต้อง ซึ่ง path ดังกล่าวจะขึ้นอยู่กับผู้ให้บริการแต่ละราย เช่น Keycloak จะเผยแพร่ข้อมูลนี้ไว้ที่ /realms/<realm>/.well-known/openid-configuration หากแอปพลิเคชันไม่มีช่องสำหรับระบุ issuer URL เลย แสดงว่าแอปพลิเคชันนั้นไม่สามารถสื่อสารกับ IdP ของคุณได้ ไม่ว่ารายการฟีเจอร์จะระบุไว้อย่างไรก็ตาม

ข้อ 6 มักเป็นปัญหาที่พบหลังจากมีคนลาออกไปแล้วหลายสัปดาห์ การปิดใช้งานบัญชีใน IdP จะหยุดการเข้าสู่ระบบใหม่ แต่จะไม่เพิกถอน API token ที่แอปพลิเคชันออกให้ก่อนหน้านี้ เนื่องจากแอปพลิเคชันตรวจสอบ token นั้นด้วยตัวเองและไม่เคยสอบถาม IdP เกี่ยวกับเรื่องนี้ ดังนั้นขั้นตอนการยกเลิกสิทธิ์จึงมีสองส่วนคือ ปิดใช้งานบัญชีใน IdP จากนั้นลบผู้ใช้หรือ token ของผู้ใช้นั้นภายในแอปพลิเคชันแต่ละรายการ

ความหมายที่แท้จริงของป้ายกำกับระดับบริการ

ข้อมูลเหล่านี้ได้รับการตรวจสอบกับเอกสารของแต่ละโปรเจกต์ในเดือนสิงหาคม 2026 โดยเริ่มจากฝั่งบริการแบบเสียค่าใช้จ่ายก่อน

Grafana ระบุว่า SAML "มีให้ใช้งานใน Grafana Enterprise และ Grafana Cloud" รวมถึงฟีเจอร์ team sync และ SCIM provisioning ส่วน Generic OAuth, GitHub OAuth, LDAP (lightweight directory access protocol) และ auth proxy นั้นมีอยู่ในรุ่น open source ดังนั้นผู้ที่ทำ self-host ขนาดเล็กจึงยังสามารถล็อกอินผ่านผู้ให้บริการของตนเองได้ เส้นแบ่งของการเสียค่าใช้จ่ายจึงอยู่ที่ SAML ไม่ใช่ที่ระบบ single sign-on โดยรวม ซึ่งเป็นรายละเอียดที่คำว่า "SSO tax" มักจะเหมารวมไปทั้งหมด

Metabase มีความชัดเจนกว่า โดยเอกสารระบุว่า "การยืนยันตัวตนด้วย SAML มีให้ใช้งานเฉพาะในแผน Pro และ Enterprise เท่านั้น (ทั้งแบบ self-hosted และบน Metabase Cloud)" ส่วนรุ่น open source จะรองรับเฉพาะการล็อกอินด้วยรหัสผ่านและ LDAP

Passbolt ระบุในเอกสาร SSO ว่าเป็นฟีเจอร์สำหรับรุ่น Pro และ Cloud ดังนั้นรุ่น community จึงไม่มีฟีเจอร์นี้ โดยผู้ให้บริการที่ระบุไว้ในเอกสารประกอบด้วย Keycloak และ Entra ID

คราวนี้มาดูอีกฝั่งหนึ่ง เนื่องจากรูปแบบนี้ไม่ได้เป็นมาตรฐานสากลเสมอไป

  • GitLab Self-Managed ระบุ "Tier: Free, Premium, Ultimate" ไว้ในหน้า SAML ดังนั้นการใช้ SAML กับ GitLab ของคุณเองจึงไม่มีค่าใช้จ่าย
  • Paperless-ngx กำหนดค่า OIDC ผ่าน django-allauth ด้วย PAPERLESS_SOCIALACCOUNT_PROVIDERS, ซ่อนฟอร์มล็อกอินภายในด้วย PAPERLESS_DISABLE_REGULAR_LOGIN และแมป claim เข้ากับกลุ่มผู้ใช้งานด้วย PAPERLESS_SOCIAL_ACCOUNT_SYNC_GROUPS
  • Planka รับค่า OIDC_ISSUER, OIDC_CLIENT_ID และ OIDC_CLIENT_SECRET, กำหนดค่าเริ่มต้นของ scope เป็น openid profile email และเลื่อนระดับผู้ใช้งานเป็นผู้ดูแลระบบจาก role claim ด้วย OIDC_ADMIN_ROLES
  • BookStack สลับการใช้งานด้วย AUTH_METHOD=oidc จากนั้นแมปกลุ่มของผู้ให้บริการเข้ากับบทบาทภายในระบบด้วย OIDC_USER_TO_GROUPS=true และ OIDC_GROUPS_CLAIM
  • Vaultwarden ได้ปล่อย "การรองรับ SSO ด้วย OpenID Connect" ในเวอร์ชัน 1.35.0 เมื่อวันที่ 27 ธันวาคม 2025 ซึ่งมาจาก pull request ของผู้ร่วมพัฒนาที่เคยทำฟีเจอร์นี้ไว้ใน fork
  • listmonk รองรับการล็อกอินด้วย OIDC ควบคู่ไปกับบทบาทผู้ใช้งานมาตั้งแต่เวอร์ชัน v4.0.0

ควรใช้ข้อมูลนี้ประกอบการตัดสินใจก่อนที่คุณจะเริ่มใช้งานจริง Planka kanban board และ ทางเลือกอื่นแทน Trello สำหรับการทำ self-hosted ไม่ได้จัดการเรื่องตัวตนผู้ใช้งานเหมือนกันทั้งหมด เช่นเดียวกับ BookStack, Wiki.js และ Outline การรองรับ OIDC ฟรีเป็นฟีเจอร์ที่คุณสามารถนำมาพิจารณาได้เช่นเดียวกับขีดจำกัดพื้นที่จัดเก็บข้อมูลหรือแอปบนมือถือ หากคุณกำลังอยู่ในขั้นตอนการวางแผน สิ่งที่ควรทำ self-host ในปี 2026 เป็นจุดเริ่มต้นที่ดี และทั้ง โปรแกรมจัดการเอกสาร Paperless-ngx และ Vaultwarden ก็รองรับ OIDC ฟรีในปัจจุบัน

เหตุใด reverse proxy ที่อยู่หน้าแอปพลิเคชันจึงไม่ใช่ Single Sign-On

วิธีแก้ปัญหาที่นิยมใช้กันคือ forward auth โดย reverse proxy จะพักคำขอแต่ละรายการไว้ก่อน แล้วสอบถามบริการยืนยันตัวตนว่าเบราว์เซอร์นี้ได้ลงชื่อเข้าใช้แล้วหรือไม่ จากนั้นจึงส่งคำขอต่อไปยังแอปพลิเคชัน authentik เรียกฟีเจอร์นี้ว่า proxy provider ซึ่งมีโหมด forward auth สำหรับแอปพลิเคชันเดียวและสำหรับทั้งโดเมน ส่วน Authelia และ oauth2-proxy ก็ทำหน้าที่ในลักษณะเดียวกัน

ตัวอย่าง site block ของ Caddy จะมีหน้าตาเป็นดังนี้ โดยอ้างอิงตามตัวอย่างของ authentik เอง

app.example.com {
  forward_auth http://authentik-outpost:9000 {
    uri /outpost.goauthentik.io/auth/caddy
    copy_headers X-Authentik-Username X-Authentik-Email X-Authentik-Groups
    trusted_proxies private_ranges
  }
  reverse_proxy app:8000
}

การใช้ตัวพิมพ์ใหญ่และตัวพิมพ์เล็กในชื่อ header เหล่านั้นมีความสำคัญใน Caddy เพราะหากชื่อไม่ตรงกัน ข้อมูลที่ได้รับจะเป็นค่าว่าง ในทุกคำขอที่ได้รับการอนุมัติ outpost จะตั้งค่า X-authentik-username, X-authentik-email, X-authentik-groups และค่าอื่นๆ เพิ่มเติม

สิ่งที่คุณจะได้รับจากวิธีนี้คือ ไม่มีใครสามารถเข้าถึงแอปพลิเคชันได้โดยไม่ผ่านผู้ให้บริการยืนยันตัวตนของคุณก่อน ดังนั้นฟอร์มล็อกอินที่ยังไม่ได้แพตช์จึงไม่ถูกเปิดเผยต่ออินเทอร์เน็ตอีกต่อไป และการทำ MFA จะถูกบังคับใช้กับทุกบริการที่อยู่หลัง proxy ในคราวเดียว

สิ่งที่คุณจะไม่ได้รับคือ การยืนยันตัวตนภายในตัวแอปพลิเคชัน แอปพลิเคชันยังคงมีบัญชีผู้ใช้ของตนเองและมีระบบจัดการการลงชื่อเข้าใช้แยกต่างหาก หากทุกคนผ่าน proxy เข้ามาแล้วใช้งานบัญชีผู้ดูแลระบบบัญชีเดียวกัน คุณก็จะมีเพียงประตูด้านหน้าที่แข็งแกร่ง แต่มีเซสชันที่ไม่ระบุตัวตนอยู่ข้างหลัง ประวัติการใช้งาน (audit log) จะยังคงแสดงชื่อผู้ใช้เพียงชื่อเดียว และไม่สามารถกำหนดสิทธิ์ที่แตกต่างกันระหว่างบุคคลได้ การเรียกการตั้งค่าแบบนี้ว่า SSO ถือเป็นความผิดพลาดด้านความปลอดภัย เพราะกระบวนการยกเลิกสิทธิ์ (offboarding) จะทำได้เพียงครึ่งเดียวเท่านั้น การลบชื่อบุคคลออกจาก IdP ของคุณจะปิดประตูด้านหน้าได้จริง แต่ API token ที่บุคคลนั้นสร้างไว้ภายในแอปพลิเคชันจะยังคงใช้งานได้สำหรับทุกคนที่สามารถเข้าถึงแอปพลิเคชันได้โดยตรง

แอปพลิเคชันบางตัวยอมรับชื่อผู้ใช้จาก proxy ซึ่งช่วยให้คุณระบุตัวตนผู้ใช้ได้โดยไม่ต้องใช้ SSO แบบเสียค่าใช้จ่าย การตั้งค่านี้จะมีชื่อเรียกต่างกันไปในแต่ละโปรเจกต์

Grafana เรียกสิ่งนี้ว่า auth proxy และปิดการใช้งานมาเป็นค่าเริ่มต้น ชื่อ header จะถูกตั้งเป็น X-WEBAUTH-USER โดยอัตโนมัติ และคุณสามารถกำหนดให้ชี้ไปยัง header ใดก็ได้ที่ proxy ของคุณตั้งค่าไว้

[auth.proxy]
enabled = true
header_name = X-authentik-username
header_property = username
auto_sign_up = true
whitelist = 10.0.0.5

whitelist คือบรรทัดที่ผู้คนมักมองข้าม เอกสารของ Grafana ระบุไว้อย่างชัดเจนว่ามีไว้เพื่อป้องกันไม่ให้ผู้ใช้ปลอมแปลง header ดังนั้นค่านี้ควรระบุเฉพาะที่อยู่ของ proxy ของคุณเท่านั้น Gitea มีฟีเจอร์เดียวกันภายใต้ชื่อเรียกอื่น และมีการตั้งค่าเริ่มต้นที่ปลอดภัยกว่า

[security]
ENABLE_REVERSE_PROXY_AUTHENTICATION = true
REVERSE_PROXY_AUTHENTICATION_USER = X-WEBAUTH-USER
REVERSE_PROXY_TRUSTED_PROXIES = 10.0.0.5/32
REVERSE_PROXY_LIMIT = 1

REVERSE_PROXY_TRUSTED_PROXIES มีค่าเริ่มต้นเป็น 127.0.0.0/8,::1/128 และ REVERSE_PROXY_LIMIT คือจำนวน proxy ที่ Gitea จะเชื่อถือในห่วงโซ่การเชื่อมต่อ การตั้งค่าขีดจำกัดนี้เป็นศูนย์จะเป็นการปิดการจัดการ header โดยสมบูรณ์

Paperless-ngx มีการตั้งค่า PAPERLESS_ENABLE_HTTP_REMOTE_USER ร่วมกับ PAPERLESS_HTTP_REMOTE_USER_HEADER_NAME และเอกสารประกอบได้ระบุคำเตือนที่ควรใช้กับการตั้งค่าเหล่านี้ทั้งหมดว่า:

การตั้งค่านี้จะอนุญาตให้ยืนยันตัวตนได้เพียงแค่เพิ่ม header Remote-User: <username> เข้าไปในคำขอ โปรดใช้งานด้วยความระมัดระวัง!

กฎสองข้อที่จะช่วยให้การยืนยันตัวตนผ่าน header ปลอดภัยคือเรื่องของการเข้าถึง ข้อแรก แอปพลิเคชันต้องไม่สามารถเข้าถึงได้จากภายนอกยกเว้นผ่าน proxy เท่านั้น เพราะใครก็ตามที่สามารถเปิด socket เชื่อมต่อกับแอปได้จะสามารถส่ง header ดังกล่าวและสวมรอยเป็นผู้ใช้ใดก็ได้ ใน Docker การใช้ ports: ["8000:8000"] จะเป็นการเปิดพอร์ตบนทุก interface ดังนั้นให้ bind ไปที่ loopback address ด้วย ports: ["127.0.0.1:8000:8000"] หรือยกเลิกการเปิดพอร์ตสาธารณะแล้วนำ proxy ไปไว้ใน Docker network เดียวกันแทน ข้อสอง proxy ต้องลบ header ใดๆ ที่ส่งมาจากฝั่งไคลเอนต์ทิ้ง เพื่อให้ค่าที่แอปพลิเคชันได้รับเป็นค่าที่ proxy ของคุณกำหนดขึ้นหลังจากการยืนยันตัวตนแล้วเท่านั้น

ให้ตรวจสอบทั้งสองกรณี โดยรันคำสั่งแรกจากเครื่องภายนอก VPS ของคุณ และรันคำสั่งที่สองบนเซิร์ฟเวอร์โดยตรง

curl -si -H "Remote-User: admin" http://203.0.113.10:8000/ | head -n 1
ss -ltnp | grep 8000

คำสั่ง curl ควรจะเชื่อมต่อไม่สำเร็จ และ ss ควรแสดงผลเป็น 127.0.0.1:8000 แทนที่จะเป็น 0.0.0.0:8000 หากบรรทัดแรกแสดงเป็น HTTP/1.1 302 Found หมายความว่าแอปพลิเคชันกำลังตอบรับการเชื่อมต่อจากอินเทอร์เน็ตสาธารณะโดยตรง ซึ่งทำให้ใครก็ตามสามารถล็อกอินเป็นผู้ใช้ใดก็ได้เพียงแค่ระบุชื่อผู้ใช้ใน header

เมื่อไม่มี SSO ให้ใช้ฟรี ให้ตัดสินใจเลือกแทนการบ่น

มี 4 ทางเลือก โดยเรียงลำดับตามที่ผมจะทดลองใช้ดังนี้:

  1. เลือกแอปที่รองรับ OIDC หากมีสองโปรเจกต์ที่ทำงานเหมือนกัน แต่มีหนึ่งโปรเจกต์ที่เชื่อมต่อกับ identity provider ของคุณได้ฟรี นั่นคือความแตกต่างที่แท้จริงในแง่ของต้นทุนการดำเนินงาน
  2. ใช้ forward auth อย่างตรงไปตรงมา สำหรับเครื่องมือดูแลระบบที่มีบัญชีเดียวและผู้ดูแลคนเดียว การใช้ proxy วางไว้ด้านหน้าก็เพียงพอแล้ว และการจัดการตัวตนรายบุคคลภายในแอปนั้นไม่ได้ให้ประโยชน์เพิ่มเติมใดๆ
  3. จ่ายเงิน หากแอปนั้นเป็นหัวใจสำคัญในการทำงานของคุณและราคาต่อที่นั่งเหมาะสมกับขนาดทีมของคุณ เงินจำนวนนั้นจะช่วยให้โปรเจกต์ได้รับการดูแลรักษาต่อไป และทางเลือกอื่นคือการที่คุณต้องเสียเวลาส่วนตัวมาดูแลเอง
  4. สอบถามไปยัง upstream หลังจากค้นหาใน issue tracker แล้ว การรองรับ OIDC ของ Vaultwarden เกิดขึ้นได้ผ่าน fork ของผู้ร่วมพัฒนาและ pull request ที่ค้างมานาน ดังนั้นคำขอฟีเจอร์ที่มีการเขียนโค้ดรองรับมาให้พร้อมบางครั้งก็ถูกบรรจุลงในรุ่นฟรีได้เช่นกัน

ไม่มีวิธีใดที่ใช้งานได้หากคุณไม่มี identity provider เป็นของตัวเอง ซึ่งเป็นส่วนประกอบแรกที่คุณต้องสร้างขึ้น การรัน authentik บน VPS จะช่วยให้คุณมีผู้ให้บริการ OIDC และ SAML รวมถึง outpost สำหรับ forward auth ที่กล่าวถึงข้างต้น และ การเปรียบเทียบระหว่าง Keycloak, authentik และ Zitadel จะช่วยสรุปข้อดีข้อเสียหากคุณยังไม่ต้องการตัดสินใจในตอนนี้

ประวัติการอนุญาตใช้งาน และเหตุผลที่ต้องมีในรายการตรวจสอบ

รายการตรวจสอบข้อสุดท้ายเกี่ยวข้องกับอนาคต เนื่องจากโครงสร้างระดับการใช้งานในปัจจุบันเป็นเพียงภาพรวม ณ ขณะนั้นเท่านั้น มีกรณีศึกษาที่บันทึกไว้อย่างชัดเจนสองกรณีที่แสดงให้เห็นว่าสถานการณ์เปลี่ยนแปลงไปอย่างรวดเร็วเพียงใด ทั้งในแง่บวกและแง่ลบ HashiCorp ได้นำ Business Source License 1.1 มาใช้กับทุกรุ่นที่จะปล่อยออกมาในอนาคตเมื่อวันที่ 10 สิงหาคม 2023 ในขณะที่รุ่นก่อนหน้ายังคงอยู่ภายใต้ MPL 2.0 (Mozilla Public License) ส่วน Redis ได้เปลี่ยนไปใช้ SSPL (Server Side Public License) ในเดือนมีนาคม 2024 จากนั้นประกาศเมื่อวันที่ 1 พฤษภาคม 2025 ว่า Redis 8 จะเผยแพร่ภายใต้ AGPLv3 (GNU Affero General Public License) ด้วยเช่นกัน

ให้มองทั้งสองกรณีนี้เป็นหลักฐานเชิงกลไกมากกว่าแรงจูงใจ สัญญาอนุญาตที่คุณอ่านในวันนี้มีผลกับเวอร์ชันที่คุณติดตั้งในวันนี้ และโครงการที่ถือครองลิขสิทธิ์ทั้งหมดของตนเองสามารถเปลี่ยนเงื่อนไขของรุ่นถัดไปได้โดยลำพัง นี่คือเหตุผลที่คำถามเรื่อง CLA อยู่ในรายการตรวจสอบ เนื่องจากความยินยอมในการโอนลิขสิทธิ์ในวงกว้างคือสิ่งที่ทำให้การเปลี่ยนสัญญาอนุญาตฝ่ายเดียวเกิดขึ้นได้

ตรวจสอบประวัติของโครงการด้วยตัวคุณเองก่อนที่คุณจะสร้างระบบบนโครงการนั้น

git clone --filter=blob:none https://github.com/paperless-ngx/paperless-ngx.git
cd paperless-ngx
git log --follow --oneline -- LICENSE

รายการ commit สั้นๆ ซึ่งส่วนใหญ่มาจากการนำเข้าครั้งแรก เป็นสัญญาณที่ดี แต่หากมีการเขียนไฟล์สัญญาอนุญาตใหม่หลายครั้ง หมายความว่าคุณควรตรวจสอบข้อความในแต่ละ commit ก่อนที่จะวางแผนโดยอิงจากเงื่อนไขปัจจุบัน

FAQ

ภาษี SSO คืออะไร

ภาษี SSO คือแนวทางปฏิบัติในการเรียกเก็บค่าธรรมเนียมสำหรับฟีเจอร์ Single Sign-on ในฐานะฟีเจอร์ระดับพรีเมียม ในขณะที่ส่วนอื่นของผลิตภัณฑ์เปิดให้ใช้งานฟรีหรือมีราคาถูก สำหรับซอฟต์แวร์แบบ self-hosted สิ่งนี้มักปรากฏในรูปแบบของแอปพลิเคชันโอเพนซอร์สที่คุณสามารถรันได้โดยไม่ต้องใช้ license key แต่การล็อกอินผ่าน OIDC หรือ SAML กลับถูกจำกัดไว้ในระดับที่ต้องชำระเงิน ชื่อนี้มีที่มาจาก SSO Wall of Shame ที่ sso.tax ซึ่งคอยติดตามผู้ให้บริการที่เรียกเก็บค่าธรรมเนียมส่วนนี้ในราคาแพง ผลกระทบสำหรับผู้ที่ทำ self-host คือทุกแอปจะแยกฐานข้อมูลผู้ใช้ของตนเอง ทำให้การสร้างและลบบัญชีต้องทำด้วยมือ

Reverse proxy ที่ใช้ forward auth เหมือนกับ SSO หรือไม่

ไม่เหมือนกัน Forward auth ทำหน้าที่ปกป้องทางเข้าหลัก โดย proxy ของคุณจะตรวจสอบกับ identity provider ก่อนที่คำขอใดๆ จะเข้าถึงแอปได้ แต่แอปที่อยู่ด้านหลังยังคงใช้บัญชีของตนเองอยู่ ดังนั้นหากทุกคนเข้าสู่ระบบผ่านจุดเดียวกัน คุณจะได้ session แบบไม่ระบุตัวตนเพียงชุดเดียว และ log การตรวจสอบที่มีชื่อเพียงชื่อเดียว ระบบจะกลายเป็น identity รายบุคคลที่แท้จริงก็ต่อเมื่อแอปอ่านชื่อผู้ใช้จาก header เท่านั้น ซึ่ง Grafana auth proxy, Gitea reverse proxy authentication และ PAPERLESS_ENABLE_HTTP_REMOTE_USER ของ Paperless-ngx สามารถทำได้ทั้งหมด การตั้งค่าเหล่านี้จะปลอดภัยก็ต่อเมื่อแอปไม่สามารถเข้าถึงได้จากช่องทางอื่นนอกจากผ่าน proxy เท่านั้น เนื่องจาก header เป็นเพียงข้อความธรรมดาที่ client ใดๆ ก็สามารถส่งมาได้

แอป self-hosted ใดบ้างที่มี OIDC ในรุ่นฟรี

ตรวจสอบข้อมูลจากเอกสารโครงการ ณ เดือนสิงหาคม 2026: Paperless-ngx, Planka, BookStack, Gitea, listmonk และ Vaultwarden ทั้งหมดรองรับ OIDC ในรุ่นฟรี และ GitLab Self-Managed ระบุว่า SAML อยู่ในระดับ Tier: Free สำหรับ Grafana รุ่นโอเพนซอร์สรองรับการทำ generic OAuth กับ issuer ของคุณเอง ในขณะที่ SAML เป็นฟีเจอร์ระดับ Enterprise โปรดตรวจสอบหน้าการตั้งค่าการยืนยันตัวตนของโครงการนั้นๆ ก่อนติดตั้ง เนื่องจากรายการเหล่านี้อาจเปลี่ยนแปลงตามการ releases

ฉันควรจ่ายเงินเพื่อปลดล็อกฟีเจอร์ Single Sign-on หรือไม่

ให้ตัดสินใจโดยพิจารณาจากตัวเลขสองค่า ได้แก่ จำนวนคนที่ต้องการบัญชีผู้ใช้ และจำนวนแอปที่คุณต้องดูแลด้วยมือหากไม่ใช้ฟีเจอร์นี้ สำหรับผู้ดูแลระบบหนึ่งหรือสองคน การใช้ forward auth หน้าบัญชีภายในก็เพียงพอแล้ว และการจ่ายเงินในระดับพรีเมียมอาจไม่คุ้มค่าเท่าไรนัก สำหรับทีมที่มีการเข้าออกของพนักงาน การพลาดลบบัญชีเพียงหนึ่งบัญชีในช่วง offboarding อาจมีต้นทุนสูงกว่าค่า license และการชำระเงินนั้นยังเป็นการสนับสนุนการบำรุงรักษาที่คุณต้องพึ่งพา หากราคาไม่เหมาะสม ทางเลือกที่ใช้งานได้จริงคือการเลือกแอปที่มี OIDC มาให้ในตัว แทนที่จะพยายามหาวิธีเลี่ยงข้อจำกัดในแอปที่ไม่มีฟีเจอร์นี้