Vấn đề phân mảnh mật khẩu trong các hệ thống Self-Hosted
Hệ thống homelab thường mở rộng rất nhanh. Thứ khởi đầu chỉ là một Plex server đơn lẻ và một container Pi-hole sẽ sớm phình to thành 15 hay 20 dịch vụ khác nhau. Chẳng mấy chốc, bạn sẽ phải vật lộn quản lý các thông tin đăng nhập riêng biệt trên khắp Portainer, Proxmox, TrueNAS, Grafana và Nextcloud.
Mức độ bảo mật nhanh chóng trở nên thiếu nhất quán. Một số công cụ hỗ trợ sẵn TOTP hoặc khóa bảo mật phần cứng. Những công cụ khác lại chỉ dựa vào HTTP basic auth cơ bản. Thậm chí một vài tiện ích cũ hơn hoàn toàn không có xác thực, khiến chúng dễ bị xâm nhập nếu mở ra ngoài mạng nội bộ. Việc cập nhật thông tin đăng nhập biến thành một công việc tẻ nhạt. Tệ hơn nữa, việc thu hồi quyền truy cập của một tài khoản bị xâm nhập đồng nghĩa với việc bạn phải đăng nhập thủ công vào từng dashboard một.
Một Identity Provider (IdP) tập trung sẽ giải quyết triệt để tình trạng hỗn loạn này. Thay vì để từng ứng dụng tự quản lý thông tin đăng nhập riêng lẻ, bạn gom toàn bộ yêu cầu đăng nhập qua một cổng bảo mật duy nhất được thắt chặt.
Các khái niệm cốt lõi: Cách Authentik bảo vệ hệ thống của bạn
Authentik là nền tảng quản lý danh tính mã nguồn mở, self-hosted được thiết kế với độ linh hoạt cao. Nó hoạt động như một nguồn chân lý duy nhất (single source of truth) cho toàn bộ danh tính trong mạng của bạn.
1. Identity Provider (IdP) so với Service Provider (SP)
Trong kiến trúc này, Authentik đóng vai trò là Identity Provider (IdP). Nó lưu trữ tài khoản người dùng, xác minh mật khẩu và kiểm tra tính hợp lệ của mã 2FA. Các ứng dụng riêng lẻ của bạn (như Grafana, Vaultwarden hoặc Paperless-ngx) đóng vai trò là Service Providers (SP). Khi bạn truy cập vào một ứng dụng, nó sẽ ủy quyền toàn bộ quá trình bắt tay xác thực cho Authentik thay vì tự xử lý mật khẩu.
2. Các giao thức xác thực được hỗ trợ
- OpenID Connect (OIDC) / OAuth2: Tiêu chuẩn vàng cho các ứng dụng web hiện đại. Ứng dụng client sẽ chuyển hướng bạn đến Authentik, nhận lại một JSON Web Token (JWT) đã ký số, sau đó trích xuất tên người dùng, email và quyền thành viên nhóm.
- SAML 2.0: Giao thức dựa trên XML được sử dụng rộng rãi trong các phần mềm doanh nghiệp, thiết bị chuyển mạch mạng và hypervisor như VMware ESXi hoặc Proxmox VE.
- Forward Auth (Proxy Provider): Dành riêng cho các ứng dụng cũ không có sẵn tính năng xác thực (chẳng hạn như qBittorrent hoặc Radarr). Authentik kết nối trực tiếp với reverse proxy của bạn (Traefik, Nginx Proxy Manager hoặc Caddy) để chặn lưu lượng HTTP đến ngay tại rìa mạng, ngăn chặn các yêu cầu trái phép trước khi chúng chạm tới container.
3. Mức độ tiêu thụ tài nguyên và kiến trúc
Một cụm Authentik tiêu chuẩn yêu cầu khoảng 1.5 GB đến 2.5 GB RAM ở trạng thái nghỉ và chạy trên bốn container chuyên biệt:
- PostgreSQL 16: Lưu trữ hồ sơ người dùng, phân quyền (role binding), các bước xác thực (flow stage) và nhật ký kiểm toán (audit event).
- Redis (Alpine): Lưu cache các phiên hoạt động, quản lý ngưỡng giới hạn tần suất (rate-limiting) và điều phối hàng đợi tác vụ nền Celery.
- Authentik Server: Vận hành giao diện quản trị, cổng tự phục vụ cho người dùng và các API endpoint cốt lõi (lắng nghe trên cổng
9000và9443). - Authentik Worker: Xử lý các tác vụ bất đồng bộ, gửi email, đồng bộ danh bạ LDAP và dọn dẹp hệ thống theo lịch trình.
Thực hành: Triển khai Authentik trên Docker
Bước 1: Thiết lập cấu trúc thư mục và tạo mã bí mật (Secret)
Tạo thư mục chính cho Authentik và sinh các chuỗi mã hóa dài trên 50 ký tự dùng để ký session và làm thông tin đăng nhập cơ sở dữ liệu.
mkdir -p ~/homelab/authentik
cd ~/homelab/authentik
mkdir -p ./media ./custom-templates ./certs
Tạo các chuỗi ngẫu nhiên an toàn bằng openssl và ghi vào file .env:
# Tạo các khóa bảo mật mạnh
AUTHENTIK_SECRET_KEY=$(openssl rand -base64 36)
PG_PASSWORD=$(openssl rand -base64 24)
# Ghi các biến môi trường
cat <<EOF > .env
PG_PASS=${PG_PASSWORD}
AUTHENTIK_SECRET_KEY=${AUTHENTIK_SECRET_KEY}
AUTHENTIK_ERROR_REPORTING__ENABLED=false
AUTHENTIK_DISABLE_UPDATE_CHECK=false
AUTHENTIK_DISABLE_STARTUP_ANALYTICS=false
EOF
Bước 2: Viết cấu hình Docker Compose
Tạo file docker-compose.yml trong thư mục với cấu hình healthcheck rõ ràng nhằm đảm bảo thứ tự khởi động chính xác giữa các dịch vụ:
services:
postgresql:
image: docker.io/library/postgres:16-alpine
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
start_period: 20s
interval: 30s
timeout: 5s
retries: 5
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${PG_PASS}
POSTGRES_USER: authentik
POSTGRES_DB: authentik
env_file:
- .env
redis:
image: docker.io/library/redis:alpine
command: --save 60 1 --loglevel warning
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
start_period: 20s
interval: 30s
timeout: 3s
retries: 5
volumes:
- redis_data:/data
server:
image: ghcr.io/goauthentik/server:2024.8.3
restart: unless-stopped
command: server
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
volumes:
- ./media:/media
- ./custom-templates:/templates
env_file:
- .env
ports:
- "9000:9000"
- "9443:9443"
depends_on:
postgresql:
condition: service_healthy
redis:
condition: service_healthy
worker:
image: ghcr.io/goauthentik/server:2024.8.3
restart: unless-stopped
command: worker
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
volumes:
- ./media:/media
- ./custom-templates:/templates
- ./certs:/certs
- /var/run/docker.sock:/var/run/docker.sock
env_file:
- .env
depends_on:
postgresql:
condition: service_healthy
redis:
condition: service_healthy
volumes:
postgres_data:
redis_data:
Khởi động cụm dịch vụ:
docker compose up -d
Theo dõi log trong quá trình migration cơ sở dữ liệu ban đầu (thường mất khoảng 30–60 giây trên ổ SSD hiện đại):
docker compose logs -f server
Bước 3: Khởi tạo tài khoản quản trị viên ban đầu
Mở trình duyệt và truy cập vào http://<SERVER_IP>:9000/if/flow/initial-setup/.
- Đặt mật khẩu master mạnh cho tài khoản mặc định
akadmin. - Đăng nhập vào trang quản trị tại
http://<SERVER_IP>:9000. - Đi tới Directory > Users và tạo tài khoản admin thường dùng hàng ngày của bạn. Thêm tài khoản này vào nhóm
authentik Admins, sau đó đăng xuất khỏiakadmin.
Bước 4: Cấu hình ứng dụng OIDC (Ví dụ: Grafana)
Việc kết nối một ứng dụng qua OIDC yêu cầu hai thành phần liên kết với nhau: một Provider (endpoint giao thức) và một Application (mục hiển thị ứng dụng cho người dùng).
- Đi tới Applications > Providers và nhấn Create.
- Chọn OAuth2/OpenID Provider và cấu hình các tham số sau:
- Name:
Grafana-OIDC - Authentication Flow:
default-authentication-flow - Authorization Flow:
default-provider-authorization-explicit-consent - Client Type:
Confidential - Redirect URI:
https://grafana.internal.home/login/generic_oauth
- Name:
- Lưu provider và ghi lại Client ID cùng Client Secret vừa được tạo.
- Đi tới Applications > Applications, nhấn Create, đặt tên là
Grafana, slug làgrafana, và gắn providerGrafana-OIDCđã tạo ở bước trước vào.
Bây giờ, hãy khớp các giá trị này vào cấu hình Grafana của bạn (file grafana.ini hoặc biến môi trường của container):
[auth.generic_oauth]
enabled = true
client_id = YOUR_CLIENT_ID
client_secret = YOUR_CLIENT_SECRET
scopes = openid profile email
auth_url = https://auth.internal.home/application/o/authorize/
token_url = https://auth.internal.home/application/o/token/
api_url = https://auth.internal.home/application/o/userinfo/
Bước 5: Bắt buộc xác thực đa yếu tố với WebAuthn và TOTP
Thắt chặt an ninh cho tất cả các ứng dụng phía sau cùng một lúc bằng cách thêm bước 2FA bắt buộc vào luồng đăng nhập chính:
- Điều hướng đến Flows and Stages > Flows và mở
default-authentication-flow. - Chọn Stage Bindings và chỉnh sửa mục
default-authentication-mfa-validation. - Chuyển thiết lập xác thực thiết bị từ Optional sang Enforce MFA.
- Authentik giờ đây sẽ bắt buộc người dùng đăng ký passkey, YubiKey (FIDO2) hoặc ứng dụng xác thực TOTP trước khi cấp quyền truy cập vào bất kỳ dashboard nào phía sau.
Mở rộng sang các dịch vụ còn lại trong hệ thống
Khi IdP đã đi vào hoạt động, việc tích hợp thêm các dịch vụ mới chỉ mất vài phút. Các ứng dụng hỗ trợ sẵn OAuth2 có thể kết nối trực tiếp với các OIDC provider. Với mọi dịch vụ khác, việc triển khai Authentik Outpost forward proxy kết hợp cùng Nginx Proxy Manager hoặc Traefik sẽ đưa toàn bộ giao diện web cũ về sau hàng rào bảo mật 2FA tập trung.
Bạn sẽ có một dashboard duy nhất để kiểm tra các phiên hoạt động, phân quyền theo nhóm và thu hồi quyền truy cập ngay lập tức trên toàn bộ homelab của mình.

