DockerでAuthentikを構築:自宅ラボ(HomeLab)向けにSSO・2FA・OIDCを一元化する

HomeLab tutorial - IT technology blog
HomeLab tutorial - IT technology blog

セルフホスト環境における「パスワード乱立」の課題

自宅ラボ(HomeLab)の規模は急速に拡大しがちです。最初は1台のPlexサーバーやPi-holeコンテナから始まったものが、あっという間に15〜20もの独立したサービスへと増えていきます。気づけば、Portainer、Proxmox、TrueNAS、Grafana、Nextcloudなど、サービスごとに個別のログイン情報を管理する事態に陥ってしまいます。

その結果、セキュリティレベルにバラつきが生じます。TOTPやハードウェアセキュリティキーに最初から対応しているツールもあれば、プレーンなHTTP基本認証(Basic認証)にしか対応していないものもあります。古いツールの中には認証機能自体が存在せず、ローカルサブネット外に公開すれば無防備になってしまうものさえあります。認証情報の更新は面倒な作業になり、万が一アカウントが侵害された場合、すべてのダッシュボードに手動でログインしてアクセス権を取り消さなければなりません。

一元化されたIDプロバイダー(IdP)を導入すれば、この混乱を解消できます。各アプリケーションに個別に認証情報を管理させるのではなく、すべてのログインリクエストを堅牢に保護された単一のゲートウェイに集約します。

基本概念:Authentikがシステムを保護する仕組み

Authentikは、高い柔軟性を備えたオープンソースのセルフホスト型IDプラットフォームです。ネットワーク全体のアイデンティティにおける「信頼できる唯一の情報源(Single Source of Truth)」として機能します。

1. IDプロバイダー(IdP)とサービスプロバイダー(SP)

このアーキテクチャにおいて、AuthentikはIDプロバイダー(IdP)として動作します。ユーザーアカウントの保持、パスワードの検証、2要素認証トークンの検証を担います。一方、個々のアプリケーション(Grafana、Vaultwarden、Paperless-ngxなど)はサービスプロバイダー(SP)として機能します。アプリへアクセスする際、アプリ側でパスワードを直接処理するのではなく、認証ハンドシェイク全体をAuthentikへ委譲します。

2. サポートされている認証プロトコル

  • OpenID Connect (OIDC) / OAuth2: 現代のWebアプリケーションにおけるデファクトスタンダード。クライアントアプリがユーザーをAuthentikにリダイレクトし、署名付きJSON Web Token (JWT) を受け取って、ユーザー名・メールアドレス・所属グループ情報を取得します。
  • SAML 2.0: エンタープライズソフトウェア、ネットワークスイッチ、VMware ESXiやProxmox VEなどのハイパーバイザーで広く利用されているXMLベースのプロトコル。
  • Forward Auth (Proxy Provider): 認証機能を一切持たないレガシーアプリ(qBittorrentやRadarrなど)向け。Authentikがリバースプロキシ(Traefik、Nginx Proxy Manager、Caddy)と連携してネットワークエッジで受信HTTPトラフィックをインターセプトし、不正なリクエストがコンテナに到達する前にブロックします。

3. リソースフットプリントとアーキテクチャ

標準的なAuthentikスタックは、アイドル時におよそ1.5 GB〜2.5 GBのRAMを消費し、4つの専用コンテナで構成されます:

  • PostgreSQL 16: ユーザーレコード、ロールの紐付け、フローステージ、監査イベントを保存。
  • Redis (Alpine): アクティブセッションのキャッシュ、レート制限の閾値管理、Celeryバックグラウンドキューの連携処理。
  • Authentik Server: 管理者UI、ユーザーセルフサービスポータル、コアAPIエンドポイントを提供(ポート9000および9443でリッスン)。
  • Authentik Worker: 非同期タスク、メール送信、LDAPディレクトリ同期、定期クリーンアップを処理。

実践手順:DockerでAuthentikをデプロイする

ステップ 1: ディレクトリ構造の作成とシークレットの生成

Authentik用のホームディレクトリを作成し、セッション署名およびデータベース認証情報用として50文字以上の暗号学的に安全な文字列を生成します。

mkdir -p ~/homelab/authentik
cd ~/homelab/authentik
mkdir -p ./media ./custom-templates ./certs

opensslを使用してセキュアなランダム文字列を生成し、.envファイルに書き込みます:

# 強力なキーを生成
AUTHENTIK_SECRET_KEY=$(openssl rand -base64 36)
PG_PASSWORD=$(openssl rand -base64 24)

# 環境変数を書き込む
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

ステップ 2: Docker Compose設定ファイルの作成

サービスが適切な順序で起動するように、明示的なヘルスチェックを含めたdocker-compose.ymlファイルを作成します:

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:

スタックを起動します:

docker compose up -d

初期データベースマイグレーションの実行ログを追跡します(最新のSSD環境であれば通常30〜60秒程度で完了します):

docker compose logs -f server

ステップ 3: 管理者の初期プロビジョニング

ブラウザを開き、http://<SERVER_IP>:9000/if/flow/initial-setup/ にアクセスします。

  1. 組み込みの akadmin アカウント用に強固なマスターパスワードを設定します。
  2. http://<SERVER_IP>:9000 から管理コンソールにログインします。
  3. Directory > Users に移動し、普段使用する管理者アカウントを作成します。このアカウントを authentik Admins グループに追加し、akadmin からサインアウトします。

ステップ 4: OIDCアプリケーションの設定(例:Grafana)

OIDC経由でアプリケーションを連携するには、Provider(プロトコルエンドポイント)と Application(ユーザー向けカタログエントリ)という2つのリンクされたコンポーネントが必要です。

  1. Applications > Providers に移動し、Create をクリックします。
  2. OAuth2/OpenID Provider を選択し、以下のパラメータを設定します:
    • 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
  3. Providerを保存し、生成された Client ID と Client Secret を控えておきます。
  4. Applications > Applications に移動し、Create をクリックして、Nameに Grafana、Slugに grafana を設定し、前ステップで作成した Grafana-OIDC Providerを紐付けます。

続いて、Grafanaの設定ファイル(grafana.ini またはコンテナ環境変数)にこれらの値を反映させます:

[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/

ステップ 5: WebAuthnおよびTOTPによる多要素認証の強制

コア認証フローに必須の2FAステージを追加することで、配下のすべてのアプリケーションを一括で保護します:

  1. Flows and Stages > Flows に移動し、default-authentication-flow を開きます。
  2. Stage Bindings を選択し、default-authentication-mfa-validation エントリを編集します。
  3. デバイス検証の設定を Optional から Enforce MFA に変更します。
  4. これにより、ユーザーはパスキー、YubiKey (FIDO2)、またはTOTP認証システムを登録しない限り、配下のダッシュボードにアクセスできなくなります。

他のサービスへの展開

IdPが稼働すれば、新しいサービスの追加は数分で完了します。ネイティブでOAuth2をサポートしているアプリケーションは、OIDC Providerへ直接接続できます。それ以外のレガシーなWebインターフェースについても、Nginx Proxy ManagerやTraefikと合わせてAuthentik Outpost(Forward Proxy)をデプロイすることで、一元化された2FA保護下に置くことが可能です。

アクティブセッションの監査、グループベースの権限割り当て、万が一の際の認証情報の一括無効化を、単一のダッシュボードから手軽に管理できるようになります。

Share: