SSD Nodes Learn Hosting plans →
Hướng dẫn Matt ConnorBởi Matt Connor · Cập nhật ngày 2026-08-28

Authentik: SSO tự host cho mọi ứng dụng

Chạy Authentik bằng Docker Compose để dùng một lần đăng nhập cho mọi app: biến môi trường, bootstrap akadmin và forward auth với Traefik.

Một lần đăng nhập cho mọi ứng dụng bạn host

Authentik là một máy chủ SSO (single sign-on) tự host: người dùng chỉ cần đăng nhập một lần, sau đó mọi ứng dụng phía sau nó đều chấp nhận session đó thay vì yêu cầu mật khẩu riêng. Cài đặt sử dụng file Docker Compose chính thức và 2 secret được tạo tự động. Phần cần suy nghĩ kỹ nằm ở bước tiếp theo: trỏ reverse proxy vào Authentik và đưa một ứng dụng hiện có vào phía sau forward auth.

Authentik chạy dưới dạng 3 service trong file Compose đó: một database PostgreSQL, một tiến trình server và một tiến trình worker. Container server cũng chạy outpost tích hợp sẵn. Đây là component trả lời câu hỏi “request này đã đăng nhập chưa?” cho mọi ứng dụng được bảo vệ. Version 2026.5 là bản release hiện tại tính đến tháng 7 năm 2026. Project yêu cầu host có ít nhất 2 CPU core và 2 GB RAM. Hãy xem đây là mức tối thiểu. PostgreSQL và worker đều giữ lại memory sau khi máy đã chạy được 1 ngày.

Bạn cần Docker Engine cùng plugin Compose v2. Bạn có thể xác nhận bằng docker compose version. Nếu lệnh này in ra lỗi thay vì phiên bản, hãy cài plugin trước khi tiếp tục. Phần cơ bản được trình bày trong chạy ứng dụng bằng Docker Compose trên VPS.

Bạn cũng cần một DNS A record trỏ đến server, trong các ví dụ dưới đây là auth.example.com, vì Authentik tạo redirect URL dựa trên hostname mà browser đã sử dụng.

Chạy stack bằng một user thông thường thuộc group docker thay vì root. User thuộc group này có quyền tương đương root trên host. Vì vậy, chỉ cấp quyền này cho một deploy account và không cấp cho ai khác, theo nguyên tắc trong tài khoản user có quyền tối thiểu trên VPS.

Install with the official Compose file

sudo install -d -o "$USER" -g "$USER" /opt/authentik
cd /opt/authentik
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 -d

docker compose ps should list three containers, with postgresql reporting healthy and server and worker reporting running. The first start runs the database migrations, so give it a minute before the web interface answers.

Both generated values matter, for different reasons. PG_PASS is the PostgreSQL password, and it has a hard limit of 99 characters. AUTHENTIK_SECRET_KEY signs sessions and tokens, so changing it later logs every user out and invalidates every API token you have issued. Keep .env at mode 600 and keep a copy somewhere safe, because a database restored without its matching secret key is a database nobody can log into.

The Compose file reads both values with the ${PG_PASS:?database password required} form, which means Compose refuses to start when the file is missing. Running docker compose up -d from the wrong directory prints required variable AUTHENTIK_SECRET_KEY is missing a value: secret key required and stops. That message is a path problem, not a config problem.

Các biến môi trường quan trọng

Mọi thiết lập khác đều nằm trong cùng file .env. Authentik ánh xạ dấu gạch dưới kép thành một khóa cấu hình lồng nhau, vì vậy AUTHENTIK_EMAIL__HOST sẽ thiết lập email.host. Dấu gạch dưới đơn bị bỏ qua mà không có cảnh báo. Đây là lý do phổ biến nhất khiến một thiết lập có vẻ không có tác dụng.

  • AUTHENTIK_BOOTSTRAP_PASSWORD thiết lập password của user akadmin tích hợp khi khởi động lần đầu, vì vậy bạn không bao giờ phải nhập password vào một web form public. AUTHENTIK_BOOTSTRAP_EMAILAUTHENTIK_BOOTSTRAP_TOKEN cũng thiết lập địa chỉ và API token của user đó theo cách tương tự.
  • COMPOSE_PORT_HTTPCOMPOSE_PORT_HTTPS chuyển các port public khỏi giá trị mặc định là 9000 và 9443.
  • AUTHENTIK_EMAIL__HOST, AUTHENTIK_EMAIL__PORT, AUTHENTIK_EMAIL__USERNAME, AUTHENTIK_EMAIL__PASSWORD, AUTHENTIK_EMAIL__USE_TLSAUTHENTIK_EMAIL__FROM cấu hình mail outbound. Nếu thiếu các biến này, Authentik sẽ thử localhost trên port 25, khiến mail đặt lại password kết thúc bằng lỗi kết nối trong worker log.
  • AUTHENTIK_LOG_LEVEL=debug bật mức chi tiết cần thiết khi login flow hoạt động sai. Sau đó đặt lại thành info.
  • Theo mặc định, AUTHENTIK_ERROR_REPORTING__ENABLEDfalse. Chỉ đặt thành true nếu bạn chấp nhận gửi crash report cho upstream.

Đây là các secret trong một file plain text, vì vậy hãy bảo vệ directory này như mọi credential store khác. Password manager như một instance Vaultwarden tự host là nơi lưu bản sao khôi phục phù hợp hơn so với một note trên laptop.

Đăng nhập lần đầu và tài khoản quản trị

Mở http://SERVER_IP:9000 trong trình duyệt. Authentik hiển thị quy trình thiết lập ban đầu và yêu cầu bạn đặt mật khẩu cho user akadmin mặc định. Nếu bạn đã đặt AUTHENTIK_BOOTSTRAP_PASSWORD, bước đó đã hoàn tất và bạn sẽ chuyển thẳng đến trang đăng nhập.

Tạo một user admin thông thường cho chính bạn trong Directory rồi vào Users, thêm user đó vào group authentik Admins và đăng nhập bằng account này. Giữ akadmin làm account break-glass, với mật khẩu dài được lưu ngoại tuyến. Làm việc hằng ngày bằng một built-in account dùng chung sẽ phá hỏng audit log, vì mọi event đều ghi akadmin và không ghi ai đã thực hiện. Điều này cũng áp dụng cho các hệ thống phía sau Authentik: một thứ như harness OneCLI tự host, cấp agent riêng cho từng người chỉ tạo được trail dễ đọc nếu identity gửi đến nó thuộc về một người cụ thể, thay vì một login được cả team dùng chung.

Đặt Authentik phía sau reverse proxy

Publish cổng 9000 ra Internet vẫn hoạt động, nhưng bạn muốn dùng TLS (transport layer security) và một hostname thực. Nếu bạn đã chạy cấu hình trong Traefik làm reverse proxy cho nhiều ứng dụng Compose, hãy kết nối Authentik vào cùng network bên ngoài proxy bằng một file override. Tạo docker-compose.override.yml cạnh compose.yml:

services:
  server:
    networks:
      - default
      - proxy
    labels:
      traefik.enable: "true"
      traefik.docker.network: proxy
      traefik.http.routers.authentik.rule: Host(`auth.example.com`)
      traefik.http.routers.authentik.entrypoints: websecure
      traefik.http.routers.authentik.tls.certresolver: le
      traefik.http.services.authentik.loadbalancer.server.port: "9000"

networks:
  proxy:
    external: true

Áp dụng bằng docker compose up -d. Compose tự động merge file override, nên service server vẫn giữ toàn bộ cấu hình từ file chính thức và có thêm các label. Kiểm tra bằng curl -I https://auth.example.com/if/user/; lệnh này phải trả về HTTP/2 200. Nếu Traefik trả về 404 page not found, container chưa nằm trong network proxy và Traefik không thể route đến một container mà nó không thể kết nối.

Sau khi hostname hoạt động, hãy bind các cổng đã publish vào 127.0.0.1 trong file override để chỉ có thể truy cập thông qua proxy.

Bảo vệ một ứng dụng bằng forward auth

Proxy provider của Authentik có 3 mode, và chọn sai có thể mất cả giờ để xử lý. Proxy nghĩa là chính outpost chuyển tiếp traffic đến ứng dụng upstream. Forward auth (single application) nghĩa là reverse proxy của bạn vẫn chuyển traffic, còn Authentik chỉ xác nhận request đã đăng nhập hay chưa. Forward auth (domain level) bảo vệ mọi ứng dụng dưới cùng một parent domain bằng một provider duy nhất, nhưng phải đánh đổi khả năng đặt rule authorization riêng cho từng ứng dụng. Khi dùng Traefik ở phía trước, bạn nên chọn forward auth (single application). Nếu cần một ứng dụng cụ thể để thực hành, một workspace AFFiNE tự host là lựa chọn đầu tiên phù hợp. Đây là loại công cụ nội bộ bạn muốn truy cập được từ các thiết bị của mình và không cho nơi nào khác truy cập. Công cụ dùng chung cho team càng cho thấy rõ lợi ích này: đặt một support desk Chatwoot tự host phía sau cùng provider, để mọi người xử lý inbox chỉ cần đăng nhập một lần trong ngày thay vì tiếp tục chia sẻ thêm một password.

Trong giao diện web, mở Applications rồi mở Providers, tạo một Proxy Provider, chọn chế độ forward auth single application và đặt external host là https://app.example.com. Tạo một Application trỏ đến provider đó. Sau đó mở Outposts, chỉnh sửa authentik Embedded Outpost và đưa ứng dụng mới vào danh sách selected applications. Outpost chỉ xử lý các ứng dụng đã được gán cho nó. Vì vậy, nếu bỏ qua bước cuối, provider dù được cấu hình đúng vẫn không trả về kết quả.

Khai báo middleware một lần trên container Authentik rồi tham chiếu middleware đó từ mọi ứng dụng cần bảo vệ:

      traefik.http.middlewares.authentik.forwardauth.address: http://server:9000/outpost.goauthentik.io/auth/traefik
      traefik.http.middlewares.authentik.forwardauth.trustForwardHeader: "true"
      traefik.http.middlewares.authentik.forwardauth.authResponseHeaders: X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid,X-authentik-jwt,X-authentik-meta-jwks,X-authentik-meta-outpost,X-authentik-meta-provider,X-authentik-meta-app,X-authentik-meta-version

authResponseHeaders là danh sách các header mà Traefik sao chép từ response của Authentik vào request gửi đến upstream. Nếu bỏ qua phần này, ứng dụng vẫn được bảo vệ nhưng không biết người dùng là ai. Vì vậy, mọi thành phần đọc X-authentik-username để tự động đăng nhập vẫn ở trạng thái chưa đăng nhập. Khoảng thiếu này dễ thấy nhất khi đặt trước một ứng dụng có cơ chế sign-in riêng, chẳng hạn một trình theo dõi bài tập openGym tự host với tính năng đăng nhập bằng passkey. Khi đó, các header quyết định người dùng chỉ cần một prompt hay phải qua 2 prompt cho cùng một trang.

Ứng dụng được bảo vệ cần 2 router, không phải 1:

    labels:
      traefik.enable: "true"
      traefik.http.routers.myapp.rule: Host(`app.example.com`)
      traefik.http.routers.myapp.entrypoints: websecure
      traefik.http.routers.myapp.tls.certresolver: le
      traefik.http.routers.myapp.middlewares: authentik@docker
      traefik.http.routers.myapp-auth.rule: Host(`app.example.com`) && PathPrefix(`/outpost.goauthentik.io/`)
      traefik.http.routers.myapp-auth.entrypoints: websecure
      traefik.http.routers.myapp-auth.tls.certresolver: le
      traefik.http.routers.myapp-auth.priority: "15"
      traefik.http.routers.myapp-auth.service: authentik

Router thứ hai là phần mọi người thường bỏ sót. Sau khi đăng nhập, Authentik đưa browser quay lại một path bên dưới /outpost.goauthentik.io/ trên hostname của ứng dụng, không phải trên auth.example.com. Nếu không có router chuyển tiếp path prefix đó đến service Authentik, request sẽ đến ứng dụng của bạn. Ứng dụng trả về 404 và quá trình đăng nhập không hoàn tất. Giá trị priority cao hơn là yếu tố khiến rule cho path cụ thể được ưu tiên hơn rule Host() thông thường trên cùng domain.

Hãy kiểm tra bằng cửa sổ browser riêng tư. Bạn sẽ được chuyển đến auth.example.com, đăng nhập rồi quay lại ứng dụng. docker compose logs -f server ở phía Authentik in ra một authorization event cho mỗi lần thử. Qua đó, bạn biết request có đến được Authentik hay không.

Những lỗi bạn thực sự sẽ gặp

Vòng lặp redirect vô hạn giữa ứng dụng và trang đăng nhập. Host bên ngoài trên provider không khớp với host mà browser sử dụng, thường là http:// trên provider khác với https:// trên thanh địa chỉ. Khi đó session cookie được đặt cho một origin khác, nên mỗi lần quay lại đều bị xem là request anonymous mới. Hãy sửa external host và xóa cookie của cả hai domain trước khi kiểm tra lại.

404 tại /outpost.goauthentik.io/start. Outpost router chưa được cấu hình hoặc có priority thấp hơn catch-all router của host đó.

Ứng dụng tải được nhưng không hề yêu cầu đăng nhập. Nhãn middlewares trỏ đến một middleware không tồn tại. Traefik không cảnh báo lỗi này, nên typo trong authentik@docker đơn giản chỉ khiến không có middleware nào chạy. Mở Traefik dashboard và xác nhận router có liệt kê middleware đó.

Authentik trả về 403 sau khi đăng nhập thành công. User đã được authenticate nhưng chưa được authorize: ứng dụng có policy binding hoặc yêu cầu group mà user này không đáp ứng. Events log trong admin interface sẽ cho biết policy đã từ chối request.

Khi Keycloak phù hợp hơn

Keycloak là dự án lâu đời hơn, được Red Hat hỗ trợ, và phù hợp hơn cho các nhu cầu identity enterprise truyền thống: federation SAML quy mô lớn, làm broker cho đăng nhập từ nhiều identity provider bên ngoài cùng lúc, và export, import realm như một quy trình migration được tài liệu hóa. Với một số tổ chức, việc có hỗ trợ thương mại phía sau cũng là một điểm quan trọng trên giấy tờ. Đổi lại, Keycloak không có proxy riêng. Vì vậy, để bảo vệ một app không hỗ trợ OIDC (OpenID Connect), bạn phải chạy thêm một thành phần như oauth2-proxy bên cạnh nó. Built-in proxy provider của Authentik đã tích hợp sẵn phần này. Đó là lý do phần lớn self-hoster có nhiều app hỗn hợp thường chọn Authentik.

Sao lưu và nâng cấp

Có 3 thành phần cần thiết để khôi phục: database PostgreSQL, thư mục ./data.env.

cd /opt/authentik
docker compose exec -T postgresql pg_dump -U authentik authentik | gzip > authentik-$(date +%F).sql.gz

Lưu dump đó cùng với .env. Chỉ dump thôi là chưa đủ, vì secret key bảo vệ dữ liệu session và token nằm trong .env.

Nâng cấp chỉ là đổi tag. Đặt AUTHENTIK_TAG trong .env thành bản release bạn muốn, rồi chạy docker compose pull theo sau là docker compose up -d. Đọc release notes trước, vì Authentik dùng phiên bản theo ngày và một số bản release có migration yêu cầu bạn nâng cấp từ đúng bản trước đó. Tạo database dump trước khi pull, không phải sau đó.

FAQ

Authentik có miễn phí khi tự host không?

Bản open source miễn phí và bao gồm mọi thành phần đã nêu: proxy provider, forward auth, OIDC (OpenID Connect), SAML và flows engine. Gói enterprise trả phí bổ sung support và một số tính năng enterprise, nhưng các tính năng trong bài này không cần licence.

Có cần Traefik để dùng Authentik không?

Không. Forward auth hoạt động với nginx thông qua auth_request và với Caddy thông qua forward_auth. Mẫu cấu hình trong mọi trường hợp đều giống nhau: reverse proxy hỏi Authentik về từng request, còn path prefix /outpost.goauthentik.io/ trên hostname được bảo vệ phải được route đến Authentik thay vì đến app.

Vì sao app được bảo vệ cứ chuyển qua lại giữa trang đăng nhập và lỗi?

External host được cấu hình trên proxy provider không khớp với URL mà browser đang sử dụng, thường là http so với https. Session cookie được cấp cho một origin nhưng lại được đọc trên origin khác, nên Authentik luôn nhận request ẩn danh. Sửa external host, sau đó xóa cookie của cả 2 hostname trước khi test lại.

Authentik cần bao nhiêu RAM?

Tính đến July 2026, mức tối thiểu được tài liệu ghi nhận là 2 CPU core và 2 GB RAM, bao gồm PostgreSQL, server và worker. Trên máy có 2 GB RAM, worker là process đầu tiên bị kernel kill khi thiếu memory, biểu hiện là background task và email gửi đi bị dừng trong khi trang đăng nhập vẫn hoạt động. Hãy cấp 4 GB nếu cùng server đó cũng chạy các app bạn đang bảo vệ.