Contents
1. Traefik のミドルウェア概念とリクエストフロー
Traefik は EntryPoints → Routers → Middlewares → Services の順にリクエストを処理します。
この章では、各コンポーネントの役割と、ミドルウェアがどのタイミングで介在するかを整理し、認証やヘッダー操作をサービス側コードから切り離すメリットを示します。
1.1 コンポーネント概要
- EntryPoints
-
外部から入ってくるトラフィックの受け口。
web(HTTP)とwebsecure(HTTPS)が典型的です。 -
Routers
-
Host、Path、Headersなどでリクエストをマッチングし、対象となる Service と Middleware を紐付けます。 -
Middlewares
-
認証・ヘッダー付与・リトライ・IP 制限などの処理を実行する単位です。複数をチェーンでき、Router が選択された直後に適用されます。
-
Services
- 実際にリクエストを転送するバックエンド(Docker コンテナ、Kubernetes Service、外部 API 等)です。
ポイント:ミドルウェアは「ルーティング結果」→「サービス呼び出し」の間で実行されるため、認証失敗時にサービスまでリクエストが届くことはありません。
2. Basic 認証ミドルウェア(Traefik v3 系)の正しい記述
Traefik v3 系では Basic 認証 を表すキー名が basicAuth に統一されました。
以下では必須項目・オプションを具体例とともに示し、よくある間違い(ラベル名や TLS 設定)を防止します。
2.1 基本構文
|
1 2 3 4 5 6 7 8 |
http: middlewares: basic-auth: basicAuth: usersFile: /etc/traefik/auth/users.txt # bcrypt ハッシュが 1 行ずつ格納されたファイル realm: "Protected Area" # ブラウザに表示される認証領域名(任意) headerField: Authorization # デフォルトは Authorization |
basicAuthがミドルウェア種別を示す正しいキーです。usersFileかusersのいずれか 必須 で、平文パスワードは絶対に記述しません。
2.2 users と usersFile の使い分け
| 方法 | 設定例 | 適したシーン | ||
|---|---|---|---|---|
インライン (users) |
|
ユーザー数が非常に少なく、リポジトリ管理が容易な開発環境 | ||
外部ファイル (usersFile) |
|
本番環境で機密情報を Secret や ConfigMap に分離したい場合 |
- ハッシュ生成例(bcrypt)
bash
htpasswd -nbB alice $(openssl rand -base64 12) | cut -d: -f2 > users.txt
users.txtは 1 行 1 ユーザー の形式で保存し、Traefik が読み込めるようにボリュームまたは Secret としてマウントします。
2.3 認証失敗時のエラーページは別ミドルウェアで実装
basicAuth 自体には errorPage フィールドは存在しません。認証エラー時にカスタムページを返したい場合は、Error Page Middleware を別途作成し、Basic 認証ミドルウェアの後ろにチェーンします。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
http: middlewares: custom-error-page: errors: status: - "401" - "403" service: name: error-page-service port: 80 basic-auth: basicAuth: usersFile: /etc/traefik/auth/users.txt |
Router の middlewares に basic-auth@docker,custom-error-page@docker と列挙すれば、認証失敗時に指定したサービスが応答します。
2.4 TLS 設定の注意点
- エントリーポイントでの TLS 有効化は不要です。TLS は Router レベルで
tls: true(またはtls.certResolver)を設定するだけで有効になります。 entryPoints.websecure.tls=trueのようなオプションは 存在しません。誤って記述すると起動エラーの原因となります。
3. 実装例 ― Docker Compose と Kubernetes
この章では、上記で説明した正しい構文をもとに、Docker Compose と Kubernetes の両環境で Basic 認証ミドルウェアをデプロイする手順を示します。セキュリティは外部ファイル/Secret にハッシュを保存し、平文がコードに残らないこと を前提としています。
3.1 Docker Compose(ラベル方式)
Docker Provider ではコンテナの labels にミドルウェア定義を書き込む必要があります。以下は Traefik v3.x (RC) が動作するイメージ を想定した例です。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
version: "3.8" services: traefik: image: traefik:v3.0 # RC/preview タグを使用してください command: - "--providers.docker=true" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" - "--certificatesresolvers.myresolver.acme.tlschallenge=true" - "--certificatesresolvers.myresolver.acme.email=admin@example.com" - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" ports: - "80:80" - "443:443" volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" - "./auth/users.txt:/etc/traefik/auth/users.txt:ro" # bcrypt ハッシュファイル - "./letsencrypt:/letsencrypt" whoami: image: traefik/whoami labels: # Router の定義 - "traefik.http.routers.whoami.entrypoints=websecure" - "traefik.http.routers.whoami.tls=true" - "traefik.http.routers.whoami.tls.certresolver=myresolver" - "traefik.http.routers.whoami.middlewares=basic-auth@docker,custom-error-page@docker" # Basic 認証ミドルウェア(キー名は basicAuth) - "traefik.http.middlewares.basic-auth.basicAuth.usersFile=/etc/traefik/auth/users.txt" - "traefik.http.middlewares.basic-auth.basicAuth.realm=Protected Area" # カスタムエラーページ用ミドルウェア - "traefik.http.middlewares.custom-error-page.errors.status=401,403" - "traefik.http.middlewares.custom-error-page.errors.service=error-page@docker" |
ポイント解説
basic-auth.basicAuth.*が正しいキー名です。以前のbasicauthではロードに失敗します。- Router の
middlewaresはカンマ区切りで複数指定できます。認証 → エラーページ の順序が重要です。 usersFileのパスはコンテナ内部から見た絶対パス(ここでは/etc/traefik/auth/users.txt)を記述します。
3.2 Kubernetes(CRD + Secret)
Kubernetes 環境では Traefik が提供する Custom Resource Definitions (CRD) を使ってミドルウェアを定義し、認証情報は Secret に格納します。
3.2.1 Secret の作成
|
1 2 3 4 5 6 7 8 9 10 |
apiVersion: v1 kind: Secret metadata: name: basic-auth-secret type: Opaque stringData: users.txt: | alice:$2y$12$e0NRVv6XbK4RZ3JzqY1hOeFjHcGQw7Ue3f5B9kLxT9pW8sD3aZC bob:$2y$12$K7dPpXQkE4vG0M6tVnJYbA8rN1hSgHjLzqR5cUeO2fV9iT6xW4y |
stringDataに bcrypt ハッシュを プレーンテキスト で記載し、Kubernetes が自動的に base64 エンコードします。
3.2.2 Middleware CRD
|
1 2 3 4 5 6 7 8 9 |
apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: basic-auth spec: basicAuth: usersFile: /etc/traefik/auth/users.txt # Secret がマウントされるパス realm: "Protected Area" |
3.2.3 Error Page Middleware(認証失敗時用)
|
1 2 3 4 5 6 7 8 9 10 11 12 |
apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: custom-error-page spec: errors: status: - "401-403" service: name: error-page-service port: 80 |
3.2.4 IngressRoute と Volume マウント設定
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
--- apiVersion: v1 kind: ConfigMap metadata: name: traefik-auth-config data: # 空ファイルを用意し、Secret が上書きできるようにするだけのプレースホルダー users.txt: "" --- apiVersion: apps/v1 kind: Deployment metadata: name: whoami spec: replicas: 1 selector: matchLabels: app: whoami template: metadata: labels: app: whoami spec: containers: - name: whoami image: traefik/whoami ports: - containerPort: 80 volumeMounts: - name: auth-volume mountPath: /etc/traefik/auth volumes: - name: auth-volume projected: sources: - configMap: name: traefik-auth-config - secret: name: basic-auth-secret |
3.2.5 IngressRoute 本体
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: whoami-ingress spec: entryPoints: - websecure routes: - match: Host(`whoami.example.com`) kind: Rule services: - name: whoami port: 80 middlewares: - name: basic-auth - name: custom-error-page tls: certResolver: myresolver # Let's Encrypt による自動取得 |
ポイント解説
- Secret と ConfigMap の
projectedボリュームで、users.txtをファイルとしてマウント。Traefik はこのパスをusersFileで参照します。 - エラーページは別ミドルウェア (
custom-error-page) としてチェーンし、認証失敗時に独自の HTML を返せます。 - TLS 設定は IngressRoute の
tls.certResolverにより自動取得され、Router でtls: trueが暗黙的に有効化されます。
4. セキュリティベストプラクティス
Basic 認証は 平文の資格情報が HTTP ヘッダーに乗る ため、TLS が必須です。ここでは、Traefik のミドルウェアだけで実装できる追加防御策をまとめます。
4.1 HTTPS と HSTS の組み合わせ
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# traefik.yml(静的設定例) entryPoints: websecure: address: ":443" http: middlewares: - hsts@file # グローバルに適用する場合は entrypoint に直接指定 http: middlewares: hsts: headers: stsSeconds: 31536000 stsIncludeSubdomains: true forceSTSHeader: true |
HSTSヘッダーを付与すると、ブラウザが 以降の HTTP 接続を自動的に HTTPS に切り替える ため、TLS ダウングレード攻撃を防げます。
4.2 IP 制限(社内限定アクセス)
|
1 2 3 4 5 6 7 8 |
http: middlewares: ip-whitelist: ipWhiteList: sourceRange: - "203.0.113.0/24" # 社内ネットワーク - "2001:db8::/32" |
ipWhiteListミドルウェアを Basic 認証の前にチェーンすれば、許可 IP 以外からは認証さえ試みられません。
4.3 ログレベルとデバッグ情報
- 本番環境では
--log.level=INFOが推奨ですが、トラブル時には 一時的に
bash
--log.level=DEBUG
を有効化し、traefik.http.middlewares.basic-auth.basicAuth.debug=true(v3 のみ)でハッシュ比較の詳細を取得できます。
4.4 パスワード管理上の注意点
| 項目 | 推奨事項 |
|---|---|
| ハッシュアルゴリズム | bcrypt (-B) を必ず使用し、SHA1/MD5 は避ける |
| 平文保存 | ソースコード・Docker イメージ内に絶対に残さない |
| ローテーション | Secret/ConfigMap の差し替えだけで即時反映できるよう設計する |
| アクセス権限 | users.txt は 0644、コンテナ内のマウント先は読み取り専用 (ro) に設定 |
5. テスト・検証とトラブルシューティング
実装後は 認証が期待通りに動作するか を必ず確認しましょう。ここではコマンド例、ダッシュボードの見方、典型的な障害パターンと対処法をまとめます。
5.1 curl と Postman による基本チェック
|
1 2 3 4 5 6 |
# 正常な認証(ユーザー alice が正しいパスワードでアクセスできるケース) curl -I -u alice:correct_password https://whoami.example.com # 誤った資格情報 curl -I -u alice:wrong_password https://whoami.example.com |
200 OK→ 認証成功401 Unauthorized→ 認証失敗(エラーページが設定されていればカスタム HTML が返ります)
Postman では Authorization → Basic Auth を選択し、同様に結果を確認できます。
5.2 Traefik ダッシュボードの活用
- URL:
http://<traefik-host>:8080/dashboard/(api.insecure=trueが有効な場合) - Middlewares タブで
basic-authのステータスがEnabled: trueか確認。 - Routers タブで対象 Router に紐付くミドルウェア一覧をチェックし、順序(認証 → エラーページ)が正しいか確認します。
5.3 主なトラブルと対処法
| 症状 | 原因例 | 確認ポイント / 対策 |
|---|---|---|
常に 401 が返る |
usersFile のパスが誤っている、ファイル権限不足 |
コンテナ内で cat /etc/traefik/auth/users.txt が読めるか確認。chmod 644 と ro マウントを再チェック |
| 認証ヘッダーが届かない | 前段の CDN(例:Cloudflare)が Authorization ヘッダーを除去 |
CDN の "Hide Origin Header" 設定を無効化、または headerField: X-My-Auth に変更し、CDN 側で転送許可 |
| bcrypt ハッシュが認証に失敗する | htpasswd -B ではなくデフォルトの crypt が生成された |
再度 htpasswd -nbB user password でハッシュを作成し、ファイルを書き換える |
| ログにミドルウェアロードエラーが出る | ラベル名が basicauth になっている(v3 の仕様と不一致) |
traefik.http.middlewares.<name>.basicAuth.* に修正し、Traefik を再起動 |
| TLS が機能せず HTTP になる | Router の tls: true が抜けている |
traefik.http.routers.<router>.tls=true(Docker)または IngressRoute の tls: 設定を確認 |
6. まとめ
- ミドルウェア は Traefik のリクエストフローに柔軟に介在でき、認証やヘッダー操作をサービスコードから切り離す中心的役割を担います。
- Traefik v3 系 では Basic 認証のキーが
basicAuthに統一され、ラベル・CRD の記述はこの名前に合わせる必要があります(旧basicauthはエラーになります)。 - TLS 必須 であり、
entryPoints.websecure.tls=trueといった無効なオプションは削除し、Router のtls:またはcertResolverに委ねます。 - 認証失敗時のカスタムエラーページは 別ミドルウェア(Error Page)で実装し、チェーン順序に注意してください。
- Docker Compose でも Kubernetes でも Secret / ConfigMap を利用してハッシュファイルを外部化し、平文がコードに残らない設計を徹底します。
- HTTPS+HSTS、IP 制限、適切なログレベル設定で 平文パスワードの漏洩リスク を最小化できます。
これらのベストプラクティスと正しい構文を守ることで、Traefik v3 系においても安全かつ運用性の高い Basic 認証ミドルウェアを実装できるようになります。ぜひ本稿を手元に置きながら、実際の環境で試してみてください。