一登錄中心)
goauthentik / authentik 這個項目我會直接把它當(dāng)成一套自建系統(tǒng)的統(tǒng)一登錄入口來用。它是一個開源的、基于 Go 實現(xiàn)的身份認(rèn)證和單點登錄平臺也就是常說的 IdP核心解決的是“一套賬號登錄多個內(nèi)部應(yīng)用”的問題。如果你手頭有 NAS、代碼倉庫、監(jiān)控面板、運維平臺這類系統(tǒng)不想每個地方單獨維護(hù)一套用戶名密碼authentik 值得先跑一遍。它最值得關(guān)注的點不是某個花哨的界面功能而是把登錄、授權(quán)、MFA、LDAP 目錄服務(wù)都集中到了同一個地方并且能通過標(biāo)準(zhǔn)協(xié)議和外部應(yīng)用對接。下面按我從零部署到接入應(yīng)用的路徑把關(guān)鍵步驟和容易踩的坑拆開說。1. 先搞懂 goauthentik / authentik 在認(rèn)證體系里的位置1.1 goauthentik 和 authentik 是什么關(guān)系項目標(biāo)題里的 goauthentik 并不是某個分支版本而是 authentik 在 GitHub 上的組織和倉庫名。簡單說goauthentik/authentik 就是這個項目的源碼倉庫平時大家討論的 authentik 產(chǎn)品本身也來自這里。后端選擇 Go帶來的直接好處是部署體量和內(nèi)存占用比不少 Java 系身份認(rèn)證產(chǎn)品輕。實際跑起來之后一個 docker-compose 項目里會同時出現(xiàn)多個服務(wù)包括 server、worker、PostgreSQL、Redis。server 負(fù)責(zé)對外提供 API 和頁面worker 負(fù)責(zé)執(zhí)行后臺任務(wù)比如策略判斷、流處理、憑證校驗。兩者共用同一個鏡像只是啟動命令不同。剛開始接觸時不要以為“goauthentik”是一個只靠單一二進(jìn)制就包打天下的工具它仍然需要依賴數(shù)據(jù)庫和緩存這一點要先有預(yù)期。1.2 它適合放在什么位置authentik 在自托管體系里的定位可以概括成一句話面向應(yīng)用提供認(rèn)證能力面向用戶提供統(tǒng)一登錄入口。它常見的落地方式有三種作為 OIDC/OAuth2 服務(wù)端讓 Grafana、GitLab、Nextcloud 這類支持標(biāo)準(zhǔn)協(xié)議的應(yīng)用跳轉(zhuǎn)登錄。作為 LDAP 認(rèn)證源給只支持 LDAP 的老系統(tǒng)或網(wǎng)絡(luò)設(shè)備提供用戶校驗。作為反向代理認(rèn)證網(wǎng)關(guān)在 Nginx 或 Traefik 后面統(tǒng)一攔截未登錄請求。它和同類方案經(jīng)常放在一起對比我看到的典型選擇可以整理成一個表格方案部署方式協(xié)議廣度配置復(fù)雜度Authelia單容器或二進(jìn)制重定向認(rèn)證為主較簡單低Keycloak容器或獨立服務(wù)OIDC、SAML高功能重authentikdocker-composeOIDC、SAML、LDAP、代理認(rèn)證中等Casdoor容器或二進(jìn)制OIDC 為主中等如果只是兩三個應(yīng)用并且只做簡單登錄用 Authelia 會更輕概念也更少。一旦開始考慮多協(xié)議、用戶分組、MFA、審批流程、審計日志這些“組織級需求”authentik 的組件化設(shè)計才更有優(yōu)勢。我個人的體會是authentik 的復(fù)雜度屬于“需要理解流程和策略但不需要像 Keycloak 那樣配置大量領(lǐng)域模型”的程度。2. 部署之前環(huán)境、資源、網(wǎng)絡(luò)策略要確定的內(nèi)容2.1 我推薦的最低資源邊界直接給結(jié)論我個人的最低推薦是 2 核 CPU、4G 內(nèi)存、40G 以上磁盤。更低配置能不能跑能跑通但數(shù)據(jù)庫連接、worker 后臺任務(wù)和頁面響應(yīng)速度都會變差。如果只是 docker-compose 啟一個學(xué)習(xí)環(huán)境1G 內(nèi)存也未必起不來但我不建議拿這種配置去做真實的日常認(rèn)證服務(wù)。資源占用和接入應(yīng)用的數(shù)量有關(guān)。10 個以內(nèi)應(yīng)用的統(tǒng)一登錄上面的配置一般夠用。如果是幾十個應(yīng)用、每天大量登錄跳轉(zhuǎn)就要關(guān)注 PostgreSQL 的連接數(shù)、Redis 的緩存命中率和 worker 的任務(wù)堆積情況。我一般會先用小規(guī)模跑幾天再根據(jù)內(nèi)存和 CPU 曲線決定是否需要擴容。2.2 域名、反代端口和 HTTPS 策略authentik 啟動后默認(rèn)會同時監(jiān)聽 HTTP 9000 和 HTTPS 9443 兩個端口。容器內(nèi)部的配置是這樣實際部署時我通常不會直接對外暴露這兩個端口而是在前面放一層 Nginx 或 Caddy把 443 端口的請求轉(zhuǎn)發(fā)到 9000。這里要提前統(tǒng)一一個判斷標(biāo)準(zhǔn)所有回調(diào)地址、Provider 地址、應(yīng)用跳轉(zhuǎn)地址盡量使用同一個對外域名不要一會兒用 IP一會兒用內(nèi)網(wǎng)域名。OIDC 對回調(diào)地址、Host 頭、Scheme 非常敏感域名和端口不一致是最常見的登錄失敗原因。HTTPS 建議直接交給反向代理處理內(nèi)部 9000 端口保持 HTTP 即可。如果反代配置不正確最常見的問題是回調(diào)地址被寫成了http://127.0.0.1:9000導(dǎo)致登錄成功后回不到應(yīng)用。2.3 持久化目錄和備份邊界PostgreSQL 和 Redis 都涉及數(shù)據(jù)持久化。PostgreSQL 存用戶、權(quán)限、Flow、Stage、Provider 這類核心數(shù)據(jù)Redis 主要存會話和緩存。Redis 丟了可以恢復(fù)PostgreSQL 丟了就等于整個認(rèn)證體系重建。我部署時會把持久化目錄單獨拎出來比如/data/authentik/postgresql、/data/authentik/redis而不是讓 Docker 默認(rèn) volume 埋在系統(tǒng)盤里。這樣后面?zhèn)浞?、遷移、升級時目錄結(jié)構(gòu)一眼就能看明白。3. 最小落地部署docker-compose 跑起來3.1 準(zhǔn)備 .env 環(huán)境變量authentik 官方推薦用 docker-compose 部署。環(huán)境變量中最重要的是密鑰和數(shù)據(jù)庫配置。authentik 會把環(huán)境變量里AUTHENTIK_開頭、用雙下劃線分隔的部分映射成配置項例如AUTHENTIK_SECRET_KEY對應(yīng)全局密鑰AUTHENTIK_POSTGRESQL__HOST對應(yīng) PostgreSQL 地址。生成密鑰可以用這樣一條命令openssl rand -base64 48把輸出結(jié)果填到.env文件里。示例結(jié)構(gòu)大致如下AUTHENTIK_SECRET_KEY這里填上面命令生成的一長串隨機值 AUTHENTIK_POSTGRESQL__PASSWORD獨立創(chuàng)建一個數(shù)據(jù)庫密碼 AUTHENTIK_REDIS__HOSTredis注意.env文件的換行和引號會影響讀取不要粘貼之后隨手加空格。密鑰一旦生成后續(xù)升級和恢復(fù)都要使用同一個值不能隨便更換。3.2 一個可參考的 docker-compose 服務(wù)結(jié)構(gòu)下面這個 YAML 是演示用結(jié)構(gòu)具體鏡像版本和參數(shù)以官方倉庫最新的 compose 文件為準(zhǔn)services: postgresql: image: docker.io/library/postgres:16-alpine environment: POSTGRES_PASSWORD: ${AUTHENTIK_POSTGRESQL__PASSWORD} volumes: - /data/authentik/postgresql:/var/lib/postgresql/data restart: unless-stopped redis: image: docker.io/library/redis:7-alpine volumes: - /data/authentik/redis:/data restart: unless-stopped server: image: ghcr.io/goauthentik/server:latest command: server environment: AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY} AUTHENTIK_POSTGRESQL__HOST: postgresql AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_POSTGRESQL__PASSWORD} AUTHENTIK_REDIS__HOST: redis ports: - 9000:9000 - 9443:9443 depends_on: - postgresql - redis restart: unless-stopped worker: image: ghcr.io/goauthentik/server:latest command: worker environment: AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY} AUTHENTIK_POSTGRESQL__HOST: postgresql AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_POSTGRESQL__PASSWORD} AUTHENTIK_REDIS__HOST: redis depends_on: - postgresql - redis restart: unless-stopped實際使用時要特別注意server 和 worker 必須使用同一個鏡像版本避免出現(xiàn) API 和后臺任務(wù)邏輯不一致的情況。3.3 啟動順序和驗證先把目錄和.env文件準(zhǔn)備好然后執(zhí)行docker compose up -d docker compose ps如果服務(wù)沒有全部進(jìn)入 running 狀態(tài)不要急著配置頁面先看日志docker compose logs -f server docker compose logs -f worker首次啟動通常會有數(shù)據(jù)庫初始化和遷移過程日志里出現(xiàn)大量遷移輸出是正常的需要耐心等。啟動完成后瀏覽器訪問http://服務(wù)器IP:9000。如果一切正常應(yīng)該能看到 authentik 的引導(dǎo)頁面用于創(chuàng)建初始管理員賬號如果你在環(huán)境變量里預(yù)置了 bootstrap 管理員相關(guān)的配置也會自動完成初始化。注意第一次打開時不要一上來就反復(fù)刷新。如果服務(wù)還在遷移數(shù)據(jù)庫頁面可能會短暫不可用等日志穩(wěn)定后再試。4. 第一次真正接入應(yīng)用OIDC/OAuth2 流程拆解4.1 在 authentik 里新建 Provider 和應(yīng)用authentik 管理后臺分為 Admin 和 User 兩個入口。Admin 界面用于配置User 界面是普通用戶登錄后的門戶。接入一個支持 OIDC 的應(yīng)用要先創(chuàng)建 Provider。Provider 是技術(shù)服務(wù)端它定義了使用什么協(xié)議、回調(diào)地址、客戶端類型。創(chuàng)建完成后authentik 會生成對應(yīng)的 Client ID 和 Client Secret這兩個值要復(fù)制給第三方應(yīng)用使用。然后創(chuàng)建 Application。Application 是面向用戶的可視化入口可以配置名稱、圖標(biāo)、顯示位置并且必須綁定一個 Provider。綁定之后用戶登錄門戶里才會出現(xiàn)這個應(yīng)用圖標(biāo)點擊圖標(biāo)才能跳轉(zhuǎn)到第三方應(yīng)用。這里經(jīng)常有一個理解偏差Provider 是協(xié)議層面的“服務(wù)端”Application 是展示層面的“應(yīng)用入口”兩者不是一回事。如果只創(chuàng)建 Provider 不創(chuàng)建 Application外部應(yīng)用可能仍然能調(diào)通但用戶門戶里不會出現(xiàn)入口排查時會一頭霧水。4.2 第三方應(yīng)用側(cè)要填哪些地址支持 OIDC 的應(yīng)用一般需要配置這幾項授權(quán)地址/application/o/authorize/Token 地址/application/o/token/用戶信息地址/application/o/userinfo/回調(diào)地址必須和 Provider 里的 Redirect URI 完全一致完整 URL 由你自己的對外域名拼接而成例如https://auth.example.com/application/o/authorize/。不是所有客戶端的字段名稱都叫“授權(quán)地址”有的叫 Authorization Endpoint有的叫 Login URL但含義一致。常見的不兼容情況是末尾斜杠不一致。比如 Provider 里填了https://app.example.com/callback第三方應(yīng)用里卻寫成https://app.example.com/callback/OIDC 會嚴(yán)格判斷這兩個地址不相同導(dǎo)致認(rèn)證失敗。4.3 驗證登錄流程的方法先用一個不影響生產(chǎn)的小應(yīng)用驗證建議流程如下未登錄狀態(tài)下打開第三方應(yīng)用。應(yīng)用跳轉(zhuǎn)回 authentik 登錄頁。用戶輸入用戶名密碼。瀏覽器跳回應(yīng)用應(yīng)用拿到 token。應(yīng)用請求用戶信息并建立本地會話。整個過程中最重要的是觀察瀏覽器 Network 面板里的 302 跳轉(zhuǎn)順序。正常情況下請求會從第三方應(yīng)用跳到 authentik 的 authorize 地址再跳回應(yīng)用的回調(diào)地址。如果回調(diào)地址匹配不上瀏覽器會直接顯示“Invalid redirect URI”或類似的錯誤提示。提示第一次接入時先不要強制 MFA也不要隱藏注冊入口先用默認(rèn)登錄流程跑通再逐層加策略。5. 深入 authentik 的核心概念Flow、Stage、Policy、Outpost5.1 Flow 和 Stage 是認(rèn)證流程的骨架authentik 和其他簡單認(rèn)證工具最大的不同是它把登錄邏輯拆成了 Flow 和 Stage。Flow 可以理解成一條認(rèn)證流水線比如“登錄流程”“注冊流程”“密碼找回流程”。Stage 是流水線上的一個具體環(huán)節(jié)比如“用戶名密碼校驗”“TOTP 校驗”“WebAuthn 校驗”“寫入 Session”。默認(rèn)的登錄 Flow 看起來可能只是一個登錄框其實背后是由多個 Stage 組成的。自定義場景時可以插入一個新的 Stage比如在密碼校驗之后加一個“必須完成 MFA”的階段。理解了這個模型很多看似復(fù)雜的需求就會變成“在哪個 Flow 的哪個位置插入什么 Stage”的問題。5.2 Policy 和 Binding 決定誰能通過Policy 是 authentik 里的判斷規(guī)則。它可以綁定到 Flow、Stage、Application、Provider 上決定當(dāng)前用戶或當(dāng)前請求是否滿足繼續(xù)執(zhí)行的條件。常見的 Policy 有用戶是否屬于某個組屬性是否滿足表達(dá)式是否已經(jīng)完成 MFA請求 IP 或瀏覽器信息判斷Binding 指的是“把 Policy 綁定到某個對象”的動作。比如你要實現(xiàn)“只允許運維組訪問 Grafana”可以在 Application 綁定一個用戶組策略效果比在 Provider 里寫死更靈活。Provider 只管協(xié)議Application 管訪問控制后面換協(xié)議時不需要重寫權(quán)限。5.3 Outpost 是連接外部代理認(rèn)證的組件Outpost 是 authentik 用來管理某些外部服務(wù)連接的組件使用代理 Provider 時需要部署。它的作用大致是作為反向代理認(rèn)證的后端接收請求檢查 authentik 的會話狀態(tài)沒有登錄就跳轉(zhuǎn)登錄頁登錄后放行并把用戶信息傳給后端應(yīng)用。學(xué)習(xí)階段可以先不碰 Outpost。先通過 OIDC 接入一兩個應(yīng)用理解 Flow 和 Policy 之后再去看代理認(rèn)證會更順。否則上來就部署 Outpost概念疊加在一起出了問題很難定位是 Outpost 連不上 authentik還是反代配置轉(zhuǎn)發(fā)錯地址。6. 擴展能力MFA、LDAP、反向代理認(rèn)證6.1 MFA 的強制和測試方式authentik 支持 TOTP 驗證碼、WebAuthn 通行密鑰、DUO 等。我的建議是先以 TOTP 或 WebAuthn 為主因為它們不需要額外的第三方服務(wù)。配置 MFA 的路徑通??梢赃@樣理解在登錄 Flow 里加入 MFA Stage并通過 Policy 判斷“用戶是否已經(jīng)綁定 MFA 設(shè)備”。如果用戶沒綁定先跳轉(zhuǎn)注冊 MFA 的階段如果已綁定直接驗證即可。關(guān)鍵點是不要一上來就把 MFA 設(shè)為全局強制。先在一個測試用戶身上驗證完整流程確認(rèn)用戶綁定、登錄、解綁都正常再逐步放開策略。否則批量用戶登錄時才發(fā)現(xiàn)設(shè)備綁定失敗會造成大面積登錄卡頓。6.2 LDAP Provider 適合哪些場景LDAP 適合那些不支持 OIDC/SAML 的應(yīng)用比如一些舊系統(tǒng)只允許配置 LDAP 地址和 bind 賬號。authentik 提供 LDAP Provider 后會生成一個對外的 LDAP 地址和端口外部應(yīng)用可以通過它讀取用戶目錄和校驗密碼。使用 LDAP Provider 時需要把 base DN、bind DN、密碼這些信息填到外部應(yīng)用里。這里要提前糾正一個預(yù)期authentik 的 LDAP 主要用于用戶認(rèn)證和基礎(chǔ)目錄查詢不是完整的企業(yè) AD復(fù)雜目錄同步、Exchange 集成這類功能不要過度期待。它能把 authentik 的用戶帶到支持 LDAP 的應(yīng)用里但目錄數(shù)據(jù)結(jié)構(gòu)相對簡潔。6.3 反向代理認(rèn)證接入思路反向代理認(rèn)證適合的場景是應(yīng)用不支持 OIDC/SAML但可以通過統(tǒng)一網(wǎng)關(guān)轉(zhuǎn)發(fā)。部署方式大致是創(chuàng)建一個 Proxy Provider填寫你要保護(hù)的外部域名再部署 outpost由 outpost 監(jiān)聽一個本地端口反向代理把需要保護(hù)的路徑轉(zhuǎn)發(fā)到 outpost由 outpost 判斷會話。認(rèn)證成功之后后端應(yīng)用會從請求頭里讀到 authentik 寫入的用戶信息例如用戶名、郵箱、組。使用這個模式時要注意反代必須把原始 Host 頭和用戶請求 IP 透傳給 outpost否則 Cookie 校驗和會話識別可能失敗。7. 排查鏈路啟動失敗、登錄回跳、回調(diào)報錯的定位順序7.1 容器起不來先看數(shù)據(jù)庫和 Redis遇到容器起不來不要先懷疑 authentik 本身先按這個順序查docker compose ps看哪些服務(wù)是 restarting。docker compose logs postgresql看數(shù)據(jù)庫是否正常啟動。docker compose logs redis看緩存是否正常。docker compose logs server看 authentik 的報錯信息。最常見的問題是 PostgreSQL 密碼不一致。比如.env里的AUTHENTIK_POSTGRESQL__PASSWORD和 compose 文件中POSTGRES_PASSWORD取值不一致導(dǎo)致 server 連接數(shù)據(jù)庫失敗。另一個常見問題是AUTHENTIK_SECRET_KEY為空或在遷移后更換了所有簽名和加密信息都會失效。這里我遇到過最多的情況是容器一直 restarting日志里提示數(shù)據(jù)庫連接被拒絕。改完密碼統(tǒng)一之后啟動就正常了和 authentik 本身的鏡像沒有任何關(guān)系。7.2 登錄后回不到應(yīng)用回調(diào)地址和 Host 頭優(yōu)先登錄后回不到第三方應(yīng)用90% 是回調(diào)地址不一致。檢查三個位置authentik Provider 里的 Redirect URI。第三方應(yīng)用里配置的 Redirect URI。瀏覽器網(wǎng)絡(luò)請求里實際跳轉(zhuǎn)的 redirect_uri 參數(shù)。三個必須完全一致包括協(xié)議、域名、端口、路徑、末尾斜杠。另外一種情況是反向代理沒有保留 Host 頭。Nginx 中至少要設(shè)置proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $remote_addr;如果 Host 頭不對OIDC 的 issuer 和回調(diào)拼接就會出錯表現(xiàn)是頁面能打開但跳轉(zhuǎn)后報錯或循環(huán)重定向。7.3 頁面能進(jìn)但沒有用戶或權(quán)限不對登錄頁面能正常打開但用戶登錄后看不到應(yīng)用或者訪問應(yīng)用被拒絕優(yōu)先檢查授權(quán)邏輯。用戶是通過注冊流程創(chuàng)建的還是通過 LDAP 同步的。用戶是否綁定了正確的組。Application 上綁定了哪些 Policy是否限制了用戶組。注冊流程是否默認(rèn)禁用或要求審批。這類問題通常不會出現(xiàn)在 server 日志里而會出現(xiàn)在 worker 日志中。可以執(zhí)行docker compose logs -f workerworker 負(fù)責(zé)執(zhí)行策略和流程階段權(quán)限判斷失敗時往往能在里面看到對應(yīng)錯誤。7.4 會話失效和 Cookie 設(shè)置使用 HTTPS 反代時Cookie 的 Secure 屬性會影響瀏覽器是否發(fā)送 Cookie。如果反代配置了 HTTPS但 authentik 認(rèn)為自己運行在 HTTP 環(huán)境可能不會設(shè)置 Secure Cookie瀏覽器端行為會變得奇怪。處理辦法是確保反代正確傳遞X-Forwarded-Proto并且在瀏覽器開發(fā)者工具里查看Set-Cookie和后續(xù)請求的Cookie頭確認(rèn)域名、路徑、Secure 屬性都符合預(yù)期。8. 生產(chǎn)化之前務(wù)必確認(rèn)的幾個邊界8.1 版本固定和升級順序?qū)W習(xí)環(huán)境可以直接使用 latest 鏡像但生產(chǎn)環(huán)境不建議長期跟隨 latest。每次升級都可能導(dǎo)致數(shù)據(jù)遷移不固定的版本會讓環(huán)境難以重現(xiàn)。我建議的升級順序是備份 PostgreSQL。記錄當(dāng)前版本號。查看官方升級說明確認(rèn)有沒有特殊的遷移步驟。修改鏡像版本標(biāo)簽。執(zhí)行docker compose up -d。觀察 server 和 worker 日志。用測試賬號完成一次完整登錄。升級完成后不要馬上把舊版本鏡像刪掉保留一份備用確認(rèn)運行幾天沒問題再清理。8.2 備份策略要覆蓋數(shù)據(jù)庫和密鑰備份 authentik最核心的是備份 PostgreSQL 數(shù)據(jù)庫??梢杂胮g_dump導(dǎo)出也可以直接快照數(shù)據(jù)庫目錄。Redis 數(shù)據(jù)是緩存和會話丟失后用戶會重新登錄一般不作為關(guān)鍵備份對象。比數(shù)據(jù)庫更隱蔽的是.env里的密鑰。AUTHENTIK_SECRET_KEY如果丟失或更換所有基于簽名的 token、會話、授權(quán)碼都會失效?;謴?fù)舊數(shù)據(jù)庫時必須使用舊的密鑰否則業(yè)務(wù)無法銜接。備份時可以把.env單獨保存到安全位置不要寫進(jìn)博客或倉庫明文。8.3 什么時候不建議上 authentik如果你的場景只有兩三個內(nèi)部系統(tǒng)并且所有系統(tǒng)都只是簡單登錄直接上 authentik 會有一種“殺雞用牛刀”的感覺。Flow、Stage、Application、Policy 這些概念需要學(xué)習(xí)成本維護(hù)也需要額外精力。這種情況下使用更輕量的單容器認(rèn)證轉(zhuǎn)發(fā)工具能把問題更快解決。反過來如果團(tuán)隊已經(jīng)有很多應(yīng)用協(xié)議需求混雜還需要分組授權(quán)、MFA、統(tǒng)一審計這時 authentik 的組件化設(shè)計才會真正體現(xiàn)出價值。它的復(fù)雜度不是無意義的只是要把配置成本和長期收益一起評估。我自己的體會是先跑通默認(rèn) Flow再考慮 MFA 和 LDAP先接一個 OIDC 應(yīng)用再想批量接入。踩過幾次之后我發(fā)現(xiàn)很多問題不是 authentik 能力不夠而是前置環(huán)境、域名、回調(diào)地址和密鑰沒有處理干凈。只要把這些基礎(chǔ)項盯住這套系統(tǒng)能穩(wěn)定承擔(dān)整個內(nèi)部應(yīng)用體系的登錄入口。