單一 VPS 適合用 Keycloak、authentik 還是 Zitadel?
比較 Keycloak、authentik 與 Zitadel 在單一 VPS 的 RAM 下限、無 SSO 應用程式支援,以及各自的限制,並說明為何少於 4 GB 不建議使用 Zitadel。
哪一個 SSO 伺服器適合單一 VPS
Keycloak、authentik 與 Zitadel 都是自架的單一登入(SSO)伺服器。當有人想在伺服器上的所有應用程式共用一組登入資訊時,通常會考慮這些方案。但在一台小型 VPS 上,三者並不能互相替代。對於執行 3 或 4 個自架應用程式的主機,authentik 是較安全的預設選擇,因為只有它能在沒有內建登入功能的應用程式前方提供登入畫面。當你要保護的每個應用程式都已支援標準通訊協定,且主機能提供 Java 虛擬機器(JVM)所需的記憶體時,Keycloak 才是合適的選擇。Zitadel 是為透過 API 發布產品的開發者打造;若記憶體少於 4 GB,我不建議嘗試使用它。
先選擇方案,再進行安裝。完成選擇後,VPS 上的 authentik 實作安裝指南會逐步說明設定方式。
每個產品實際需要多少 RAM?
先從資源下限開始,因為它會在功能比較前決定候選清單。以下數字是各專案截至 2026 年 8 月自行發布的資料。這些是供應商建議,不是負載測試結果。
The data behind this chart
[
{
"label": "authentik",
"vendor_min_ram_mb": 2048,
"base_containers": 3
},
{
"label": "Keycloak",
"vendor_min_ram_mb": 1250,
"base_containers": 2
},
{
"label": "Zitadel",
"vendor_min_ram_mb": 2048,
"base_containers": 4
}
]authentik 的 Docker Compose 安裝頁面要求「至少具備 2 個 CPU 核心和 2 GB RAM 的主機」,也就是 2048 MB;其發布的 compose 檔案會執行 3 個容器:PostgreSQL、server 和 worker。
Keycloak 發布了 3 個產品中最具體的數字。其容量規劃指南指出:「包含 Realm 資料快取和 10,000 個快取工作階段的 Pod,基礎記憶體使用量為 1250 MB RAM。」這 1250 MB 只涵蓋 Java 程序本身,不包含資料庫。同一頁也說明了容器記憶體限制為何如此重要:Keycloak 會將記憶體限制的 70% 用作 heap,並額外使用約 300 MB 的 non-heap 記憶體。若將容器限制設為 1 GB,系統會計算出約 717 MB 的 heap,同時仍需要 300 MB 的 non-heap 記憶體。因此,在任何工作階段資料進入快取前,限制額度就已經用完。
Zitadel 的 compose 頁面同樣要求 2 GB,也就是相同的 2048 MB,但這是首次執行的需求。應閱讀其正式環境頁面。Zitadel 程序本身需要「約 512MB RAM,且可在少於 1 個 CPU 核心的環境中運作」。資料庫才是耗用資源的主要部分:「每 100 requests per second (req/s) 約需要 1 個 CPU 核心,每個核心需要 4GB RAM。」密碼雜湊接著需要「提供 4 個 CPU 核心供此用途使用」,因為大量登入會轉化為 CPU 尖峰。官方 v4 compose 在未新增其他元件前會執行 4 個容器:Traefik 作為 proxy、Zitadel API、獨立的 Login UI 容器,以及 PostgreSQL。Redis 和 OpenTelemetry collector 則位於選用的 compose profiles 後方。
因此,Keycloak 和 authentik 可在 4 GB VPS 上執行,並為受保護的應用程式保留一些資源。Zitadel 可在 2 GB 上啟動,但每次登入時都會與自身的 PostgreSQL 競爭記憶體。我不會在低於 4 GB 的環境執行 Zitadel;如果同一台主機也要提供應用程式,我會希望配置 8 GB。
每個元件實際在你的主機上執行的內容
authentik 由 PostgreSQL 及同一個映像的兩個副本組成,分別是 server 與 worker。server 回應 HTTP 請求,並內含 outpost。worker 執行目錄同步與電子郵件等背景工作。已發布的安裝方式很簡短。
wget https://docs.goauthentik.io/compose.yml
echo "PG_PASS=$(openssl rand -base64 36 | tr -d '\n')" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')" >> .env
docker compose pull
docker compose up -dserver 發布 9000 與 9443 埠。首次造訪 9000 埠時,會執行初始設定流程,讓你設定預設 akadmin 使用者的密碼。在該埠可從網際網路連線之前,先在前方設定使用正式憑證的反向代理。
Keycloak 由一個程序及你提供的資料庫組成。快速入門設定只需一個容器。
docker run -p 127.0.0.1:8080:8080 \
-e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
-e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
quay.io/keycloak/keycloak:26.7.1 start-devstart-dev 用於初步查看。它使用本機開發資料庫,且不啟用 TLS(傳輸層安全性),因此以此方式啟動的容器日後移除時,也會一併刪除你的 realm。正式環境應改用 start,透過 KC_DB 連接正式 PostgreSQL,並透過 KC_HOSTNAME 使用公開主機名稱。Keycloak 的正式環境指南也指出,與 server 之間的所有通訊都必須使用安全通道,因此 HTTPS 並非可選設定。
Zitadel 就是前文所述的 4 個容器堆疊。
mkdir zitadel-compose && cd zitadel-compose
curl -fsSLO https://raw.githubusercontent.com/zitadel/zitadel/main/deploy/compose/docker-compose.yml
curl -fsSLO https://raw.githubusercontent.com/zitadel/zitadel/main/deploy/compose/.env.example
cp .env.example .env
docker compose up -d --wait首次啟動前,先在 .env 設定 ZITADEL_MASTERKEY。這是 Zitadel 用來加密資料庫中 secret 的 32 字元金鑰,因此遺失後就無法存取這些 secret。如果你不熟悉執行這類堆疊,VPS 的 Docker Compose 基礎會說明 volume 與 restart policy 的選擇;這些設定會決定你的身分提供者能否在重新開機後繼續運作。
各項服務支援哪些通訊協定?
三者都支援 OpenID Connect (OIDC)。這是建置在 OAuth 2.0 之上的登入層,現代應用程式普遍使用。三者也都支援 SAML 2.0 (security assertion markup language)。這是較舊的標準,企業軟體仍持續發布支援版本。真正的差異在於 LDAP (lightweight directory access protocol)。同一個詞涵蓋兩種相反的用途。
從 LDAP 讀取表示 SSO 伺服器會使用既有目錄驗證密碼。Keycloak 透過 user federation 實現此功能。Zitadel 也支援此功能:其文件說明如何「將 LDAP 伺服器連線為 ZITADEL 中的 identity provider」。
提供 LDAP 服務表示只支援 LDAP 的應用程式,可以像連線至目錄一樣,向 SSO 伺服器執行 bind。只有 authentik 支援此功能。其 LDAP provider 會透過專用的 LDAP outpost,讓「authentik 資料庫中的所有使用者與群組都能透過 LDAP 目錄搜尋」,並可在 port 636 使用 LDAPS。此功能為唯讀,因此 bind 和 search 可以運作,但無法寫入。一次性代碼會以分號附加在密碼後方,例如 password;123456;bind 期間不支援 SMS authenticators。
如果清單中有一個應用程式只支援 LDAP,比較就到此為止。Keycloak 和 Zitadel 無法回應該 bind,因此必須在它們旁邊另外執行一個目錄,並同步維護兩份使用者清單。
沒有登入功能的應用程式怎麼辦?
Forward auth 是解法,也是自架伺服器經常遇到的情境。反向代理會先向 SSO 伺服器確認請求是否允許,再將請求轉送到上游。後方的應用程式不需要知道 SSO 的存在。它收到的是代理層已經檢查過的請求,通常使用標頭傳遞使用者名稱。
authentik 的 proxy provider 提供 3 種文件化模式。「Proxy」會讓 authentik outpost 直接將流量轉送到上游應用程式。「Forward auth (single application)」會讓現有的反向代理處理流量,authentik 只負責驗證請求。「Forward auth (domain level)」則使用單一 provider,保護同一個上層網域下的所有應用程式。Domain level 最方便,但有文件明載的限制:「cannot enforce different application-level authorization rules for each protected application」,因此該網域下的所有應用程式都共用同一組政策。
Keycloak 沒有這些功能。它的配套 proxy Keycloak Gatekeeper 後來改名為 Louketo Proxy,之後又在 GitHub 封存,最後一次 commit 是 2023 年 8 月。若要保護不支援 OIDC 的應用程式,必須在其前方執行獨立元件,通常是 oauth2-proxy,並將它指向 Keycloak client。Zitadel 也沒有自有的 forward auth 模式,因此同樣需要額外安裝、監控及升級元件。
這個額外的轉送層會讓反向代理設定不再簡單。因此,在將 auth middleware 接入之前,請先閱讀 Traefik 如何放置在多個 Docker Compose 應用程式前方。
升級路徑有多複雜?
截至 2026 年 8 月,目前的版本為 Keycloak 26.7.1、authentik 2026.5.6 和 Zitadel v4.16.3。這 3 個產品都會對 PostgreSQL 執行資料庫結構遷移,因此每次升級都會變更資料庫。每次升級前都要先備份資料庫。這個習慣比本次比較中的任何功能都更重要。
authentik 的規則最嚴格,而且明確說明:「升級必須依照主要版本的順序進行;不得從較舊的主要版本直接跳到最新版本。」在升到下一個版本前,先升級目前版本中的最新修補版本;此外,「authentik 不支援降級」。採用曆年版本的專案若落後 1 年,單次升級就會變成一連串升級,而每次升級都有自己的資料庫遷移。
Keycloak 的升級指南列出應遵循的順序:先檢閱上一個版本的遷移變更,再升級伺服器,最後升級 adapters。資料庫遷移會自動執行;也可以將其匯出後手動套用,適合想在變更套用前先檢閱內容的情況。Keycloak 的成本在於檢閱工作。其版本說明包含容易略過、但忽略後代價很高的棄用項目與行為變更。
Zitadel 將 init 和 setup 階段與執行中的伺服器分開,並在正式環境指南中建議維持分離,避免擴展時重複執行 setup。對單一 VPS 而言,這主要表示 setup 步驟必須在 API 回報健康狀態前完成;因此 compose 檔案提供 health checks,而啟動命令使用 --wait。
各專案適用的對象,以及各自的限制
Keycloak 是 Red Hat 的身分識別伺服器,適合具備 realm、群組、角色對應及既有企業目錄的組織。三者之中,它對標準的實作最完整。若在 2 GB VPS 上執行 4 個自架應用程式,其中一半不支援 OIDC,Keycloak 就不適合。JVM 會占用 1250 MB。你必須學習為企業環境設計的 realm 模型,最後仍要為實際需要保護的應用程式安裝 oauth2-proxy。
authentik 是為自架服務使用者打造的,功能清單即可反映這一點。它內建 forward auth 與 LDAP provider,並可在視覺化編輯器中建立登入流程。若你需要供應商支援合約,或需要不會每隔幾週就變更的版本發布週期,authentik 就不適合。採用日曆版本控制、沒有降級路徑,也不能跳過版本,會增加實際的維運工作。當你的實際問題只是一個 OIDC client 時,還必須學習完整的流程編輯器模型。
Zitadel 是為將身分驗證嵌入所發布產品的開發人員打造的,具備強大的 API,並將多租戶列為一級功能。在這個案例中,它正好不適合。4 個容器、不支援 forward auth,以及每個 core 需要配置 4 GB 的資料庫,並不適合在同一台 VPS 上,讓 password manager 與 wiki 位於其後方。
我會在一台 VPS 上執行的方式
如果一台 VPS 上有三或四個自架應用程式,建議執行 authentik。這三者都會提供登入畫面。決定因素在於,部分應用程式永遠不會支援 OIDC,而 authentik 內建 forward auth,可直接處理這種情況,不必再搭配另一個元件。
如果可以,為它配置 4 GB;只有在旁邊的應用程式規模較小時,才配置 2 GB。不要讓 port 9000 暴露在公開網際網路上,並在前方的反向代理終止 TLS。每晚建立 PostgreSQL 傾印,並儲存到主機外部,因為沒有備份的身分識別提供者會成為其後所有應用程式的單一故障點。請使用專用的非特權帳號執行整個 stack,不要使用 root:在 VPS 上設定最小權限使用者涵蓋所需的帳號與檔案擁有權設定。
如果所有受保護的應用程式都已支援 OIDC 或 SAML,或需要 Keycloak realm 提供的細緻角色模型,請改用 Keycloak。如果你要建立讓其他人註冊的應用程式,並且需要其 API 與 tenant model,請選擇 Zitadel。這兩者都不適用於本文所討論的單一主機執行三個應用程式的情境。
你最先會遇到的故障模式
Keycloak 重新啟動後沒有資料。 你使用 start-dev 啟動它,而該設定使用本機開發資料庫。在沒有 volume 的容器中,移除容器也會移除 realm。請改用 start,並透過 KC_DB=postgres 指向實際的資料庫。
小型主機上的 authentik worker 容器消失。 worker 與 server 使用相同的 image,且兩者都會執行 Python 程序;PostgreSQL 也需要分配 2 GB 主機記憶體。執行 docker compose ps,確認是哪個服務已結束,再檢查 dmesg 是否有 out-of-memory kill,之後再尋找應用程式本身的錯誤。
Zitadel 的 Console 無法在 proxy 後方運作。 Zitadel API 使用 gRPC,因此到 upstream 的整條連線都必須使用 HTTP/2。需求頁面要求 reverse proxy 支援到 upstream 的 HTTP/2 連線,並列出經測試的 Traefik v3.x、NGINX v1.x、Caddy v2.x 與 Apache httpd 2.4.x 版本。若 proxy 將到 upstream 的連線降級為 HTTP/1.1,登入頁面會正常載入,但 Console 會失敗。
每個應用程式都將你導回登入畫面。 SSO server 的公開 URL 必須與應用程式中設定的 URL 完全一致,包括 scheme 與 port。Keycloak 將此設定稱為 hostname,Zitadel 則稱為 external domain。兩者不一致時,應用程式會將你重新導向至一個 server 不認為屬於自己的登入位置,瀏覽器便會在兩者之間反覆重新導向。
FAQ
3 種方案中,哪一種適合 2 GB VPS?
authentik 和 Keycloak。authentik 的明確需求是主機至少具備 2 個 CPU 核心與 2 GB RAM;Keycloak 的 sizing guide 則指出,伺服器本身在計入資料庫前的基礎記憶體需求為 1250 MB。加入受保護的應用程式後,兩者在 2 GB 上都相當吃緊,因此建議將 4 GB 視為較舒適的最低配置。Zitadel 的首次執行需求為 2 GB,但其正式環境建議為密碼雜湊配置 4 個 CPU 核心,且每個資料庫核心需 4 GB RAM,因此 2 GB 並不適合正式部署。
Keycloak 或 Zitadel 能保護沒有內建登入功能的應用程式嗎?
不能單獨做到。兩者都沒有隨附 forward auth 元件。Keycloak 過去的搭配 proxy Louketo Proxy 已在 GitHub 封存,最後一次 commit 是 2023 年 8 月,因此不適合作為新的建置基礎。請在反向代理與應用程式之間放置 oauth2-proxy 或類似元件,並將其指向 SSO 伺服器上的 OIDC client。authentik 則原生支援此功能,可在 Forward auth (single application) 或 Forward auth (domain level) 模式下使用其 proxy provider。
哪一種可以作為只支援 LDAP 的應用程式之 LDAP 伺服器?
authentik。其 LDAP provider 在 outpost 上執行,讓應用程式可透過 LDAP 搜尋 authentik 中的使用者與群組;port 636 也提供 LDAPS。此功能是唯讀的,因此 bind 與 search 可以運作,但無法寫入。Keycloak 和 Zitadel 的方向相反:兩者都會將既有 LDAP directory 作為使用者來源讀取,且都不會回應應用程式發出的 LDAP bind。
升級 authentik 時可以跳過版本嗎?
不可以。文件指出,升級必須依 major release 的順序進行,不應從較舊的 major version 直接升至最新版本。請先升級至各版本中的最新 patch release,再一次升級一個版本。每個步驟前都應備份 PostgreSQL,因為 authentik 不支援降級,且 migration 只能向前執行。