Keycloak、authentik 和 Zitadel:一台 VPS 选哪个
比较一台小型 VPS 部署 Keycloak、authentik 和 Zitadel 的真实内存门槛:authentik 至少 2 GB,Zitadel 低于 4 GB 不建议,并说明无 SSO 应用的兼容性差异。
一台 VPS 适合哪种 SSO 服务器
Keycloak、authentik 和 Zitadel 都是自托管单点登录(SSO)服务器。只要有人希望服务器上的所有应用共用一个登录入口,通常就会考虑它们。在一台小型 VPS 上,它们不能互相替代。对于运行三四个自托管应用的服务器,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、服务器和 worker。
Keycloak 发布了 3 个项目中最具体的数值。其容量规划指南指出:“一个 Pod 的基础内存使用量(包括 Realm 数据缓存和 10,000 个缓存会话)为 1250 MB RAM。”这 1250 MB 仅供 Java 进程使用,不包括数据库。同一页面还说明了容器内存限制为何如此重要:Keycloak 会将内存限制的 70% 用作堆,并额外使用约 300 MB 非堆内存。为容器分配 1 GB 时,计算出的堆约为 717 MB,同时仍需要这 300 MB 非堆内存。因此,在任何会话数据进入缓存之前,内存限制就已经用完。
Zitadel 的 compose 页面同样要求 2 GB,即 2048 MB,但这个数值只适用于首次运行。应参考其生产环境页面。Zitadel 进程本身需要“约 512MB RAM,并且可以使用少于 1 个 CPU 核心运行”。数据库才是主要的内存消耗来源:“每 100 个请求/秒(req/s)约需要 1 个 CPU 核心,每个核心需要 4GB RAM”。密码哈希还要求“为此提供 4 个可用的 CPU 核心”,因为登录请求突增会转化为 CPU 峰值。官方 v4 compose 在不添加其他组件的情况下会运行 4 个容器:Traefik 作为代理、Zitadel API、独立的 Login UI 容器,以及 PostgreSQL。Redis 和 OpenTelemetry collector 位于可选的 compose profile 后面。
因此,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 的生产环境指南还说明,所有进出服务器的通信都要求使用安全通道,因此 HTTPS 在生产环境中不是可选项。
Zitadel 是上文所述的四容器堆栈。
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 用于加密数据库中密钥的 32 字符密钥,因此丢失它就意味着无法再访问这些密钥。如果您刚开始运行这类堆栈,VPS 的 Docker Compose 基础知识介绍了卷和 restart policy 的配置选择;这些选择决定了身份提供商能否在重启后继续运行。
每个产品支持哪些协议?
三者都支持 OpenID Connect(OIDC)。它是构建在 OAuth 2.0 之上的登录层,现代应用通常使用它。三者也都支持 SAML 2.0(安全断言标记语言)。这是较早的标准,企业软件仍会发布支持该标准的版本。真正的区别在于 LDAP(轻量级目录访问协议):同一个词涵盖了两种相反的用途。
从 LDAP 读取表示 SSO 服务器针对现有目录验证密码。Keycloak 通过用户联合实现这一点。Zitadel 也支持此功能:其文档介绍了如何“在 ZITADEL 中将 LDAP 服务器连接为身份提供商”。
提供 LDAP 服务表示仅支持 LDAP 的应用可以像连接目录一样,绑定到您的 SSO 服务器。只有 authentik 支持此功能。其 LDAP provider 通过专用 LDAP outpost,使“authentik 数据库中的所有用户和组都可以通过 LDAP 目录搜索”,并支持在端口 636 上使用 LDAPS。它是只读的,因此绑定和搜索可用,但写入不可用。一次性代码通过分号追加到密码后,如 password;123456 所示;绑定期间不支持 SMS authenticator。
如果您的应用列表中有一个应用只支持 LDAP,那么比较到此结束。Keycloak 和 Zitadel 无法响应该绑定请求,因此您需要在它们旁边运行第二个目录,并保持两套用户列表同步。
没有登录功能的应用怎么办?
前向身份验证可以解决这个问题。这也是自托管服务器经常遇到的情况。反向代理会先向 SSO 服务器询问请求是否获准,然后再将请求转发到上游。后端应用无需了解 SSO。它接收的是已经由代理检查过的请求,通常用户名会放在请求头中。
authentik 的代理提供程序支持文档中列出的3种模式。“Proxy”模式让 authentik outpost 直接将流量转发到上游应用。“Forward auth (single application)”模式保留现有反向代理处理流量,仅使用 authentik 执行身份验证检查。“Forward auth (domain level)”模式使用一个提供程序保护同一父域名下的所有应用。域级模式更方便,但有一项文档明确说明的限制:它“无法为每个受保护的应用强制执行不同的应用级授权规则”,因此该域名下的所有应用共享同一组策略。
Keycloak 没有这些功能。它配套的代理 Keycloak Gatekeeper 后来更名为 Louketo Proxy,随后在 GitHub 上归档,最后一次提交是在2023年8月。要保护不支持 OIDC 的应用,需要在应用前面运行一个独立组件,通常是 oauth2-proxy,并将其指向 Keycloak 客户端。Zitadel 也没有自己的前向身份验证模式,因此同样需要安装、监控和升级额外组件。
正是这个额外的代理层让反向代理配置不再简单。因此,在配置身份验证中间件之前,请先阅读Traefik 如何为多个 Docker Compose 应用提供入口。
升级路径有多复杂?
截至 August 2026,当前版本分别为 Keycloak 26.7.1、authentik 2026.5.6 和 Zitadel v4.16.3。三者都会对 PostgreSQL 执行架构迁移,因此每次升级都会修改数据库。每次升级前都要先备份数据库。这个习惯比本次比较中的任何功能都更重要。
authentik 的规则最严格,而且说明得很明确:“升级必须按照主版本顺序进行;不能从较旧的主版本直接跳到最新版本。”在升级到下一个主版本前,先将当前版本更新到最新补丁版本;同时,“authentik 不支持降级”。对于按日历版本发布的项目,如果落后一年,原本的一次升级就会变成一连串升级,每次升级都有自己的数据库迁移。
Keycloak 的升级指南规定了操作顺序:先查看上一版本中的迁移变更,再升级服务器,最后升级适配器。数据库迁移会自动运行;也可以将迁移导出后手动应用,这适合需要在变更生效前先查看内容的情况。Keycloak 的成本在于阅读这些变更。其发行说明包含弃用项和行为变更,容易被跳过,但遗漏后处理成本很高。
Zitadel 将 init 和 setup 阶段与运行中的服务器分开。其生产环境指南建议保持两者分离,以免扩容时重复执行 setup。在单台 VPS 上,这主要意味着 setup 步骤必须先完成,API 才会报告健康状态。因此,compose 文件提供了健康检查,启动命令使用 --wait。
每个项目适合谁,以及各自的不足
Keycloak 是 Red Hat 的身份服务器,面向使用 realm、组、角色映射和现有企业目录的组织。它是这三个项目中标准实现最完整的一个。在运行四个自托管应用的 2 GB VPS 上,它的表现就不理想了,其中一半应用还不支持 OIDC。JVM 会占用 1250 MB 内存。您需要学习为企业设计的 realm 模型。对于真正需要保护的应用,您仍然要安装 oauth2-proxy。
authentik 面向自托管用户,其功能列表体现了这一点。它内置 forward auth 和 LDAP provider,并通过可视化编辑器构建登录流程。当您需要厂商支持合同,或需要更新节奏不必每隔几周变化一次的发布分支时,它就不合适了。使用日历版本、没有降级路径且不能跳过版本,会带来实际的运维工作。对于实际问题只是配置一个 OIDC client 的情况,登录流程编辑器又是一个需要单独学习的完整模型。
Zitadel 面向将身份验证集成到所发布产品中的开发者,并将强大的 API 和多租户作为一等功能。对于当前场景,它恰好不合适。四个容器、不支持 forward auth,以及按每个核心 4 GB 配置的数据库,对于一台运行密码管理器和 wiki 的 VPS 来说,架构并不匹配。
我会在一台 VPS 上运行什么,以及如何运行
如果一台 VPS 上运行三个或四个自托管应用,请使用 authentik。三者都会提供登录界面。决定性因素是,部分应用永远不会支持 OIDC,而 authentik 内置了 forward auth,可以直接解决这个问题,不需要再部署旁边的其他组件。
如果条件允许,为它分配 4 GB;只有在旁边的应用都很小的情况下,才使用 2 GB。不要让端口 9000 暴露在公网,将 TLS 终止放在前置反向代理上。每天夜间导出 PostgreSQL,并将备份存储在服务器之外,因为没有备份的身份提供商会成为其后所有应用的单点故障。使用专用的非特权账户运行整个堆栈,不要使用 root:在 VPS 上设置最小权限用户介绍了所需的账户和文件所有权配置。
如果所有受保护的应用都已支持 OIDC 或 SAML,或者需要 Keycloak realm 提供的细粒度角色模型,请改用 Keycloak。如果你正在为其他用户构建注册使用的应用,并且需要它的 API 和租户模型,请选择 Zitadel。这两者都不适用于本文讨论的单台服务器运行三个应用的场景。
你首先会遇到的故障模式
Keycloak 重启后没有数据。 你使用 start-dev 启动了它,该方式使用本地开发数据库。在没有卷的容器中,删除容器也会删除 realm。改用 start,并通过 KC_DB=postgres 将其连接到实际数据库。
小型主机上的 authentik worker 容器消失。 worker 和 server 使用同一个镜像,并且都会运行 Python 进程;PostgreSQL 也需要占用 2 GB 主机内存中的一部分。运行 docker compose ps 确认哪个服务退出,然后检查 dmesg 中是否存在因内存不足而被终止的记录,再开始查找应用本身的错误。
Zitadel 的 Console 在代理后无法工作。 Zitadel API 使用 gRPC,因此到上游的整个连接都必须使用 HTTP/2。要求页面要求反向代理支持到上游的 HTTP/2 连接,并列出了经过测试的 Traefik v3.x、NGINX v1.x、Caddy v2.x 和 Apache httpd 2.4.x 版本。如果代理将到上游的连接降级为 HTTP/1.1,登录页面可以加载,但 Console 会失败。
每个应用都会将您重定向回登录页面。 SSO 服务器的公网 URL 必须与应用中配置的 URL 完全一致,包括 scheme 和端口。Keycloak 将其称为 hostname 设置,Zitadel 将其称为 external domain。两者不一致时,应用会将您重定向到一个服务器不认为属于自己的登录地址,浏览器便会在两个地址之间反复跳转。
FAQ
2 GB VPS 适合哪一个?
authentik 和 Keycloak。authentik 的明确要求是主机至少有 2 个 CPU 核心和 2 GB RAM;Keycloak 的容量指南则显示,在不包含数据库的情况下,服务器基础内存需求为 1250 MB。安装受保护的应用后,两者在 2 GB 环境中都很紧张,因此建议至少使用 4 GB。Zitadel 为首次运行公布的需求是 2 GB,但其生产环境指南要求密码哈希使用 4 个 CPU 核心,并且每个数据库核心需要 4 GB RAM,因此 2 GB 无法用于实际部署。
Keycloak 或 Zitadel 能保护没有自身登录功能的应用吗?
不能单独实现。两者都不自带 forward auth 组件。Keycloak 的旧配套代理 Louketo Proxy 已在 GitHub 上归档,最后一次提交时间为 2023 年 8 月,因此不应再基于它构建。您可以在反向代理和应用之间放置 oauth2-proxy 或类似组件,并将其指向 SSO 服务器上的 OIDC 客户端。authentik 则原生支持此功能,可在其代理提供程序中使用 “Forward auth (single application)” 或 “Forward auth (domain level)” 模式。
哪一个可以充当只支持 LDAP 的应用的 LDAP 服务器?
authentik。其 LDAP 提供程序运行在 outpost 上,可让应用通过 LDAP 查询 authentik 中的用户和组,并在端口 636 上提供 LDAPS。它是只读的,因此可以执行绑定和搜索,但不能写入。Keycloak 和 Zitadel 的方向相反:两者都将现有 LDAP 目录作为用户来源读取,但都不会响应来自应用的 LDAP 绑定请求。
升级 authentik 时可以跳过版本吗?
不可以。文档规定,升级必须遵循主版本的顺序,不应从较旧的主版本直接升级到最新版本。首先升级到当前版本系列中的最新补丁版本,然后每次只跨越一个版本。每次升级前都要备份 PostgreSQL,因为 authentik 不支持降级,并且迁移只会向前执行。