2026年7月6日

2026年7月6日

htpasswd コマンドの使い方|.htpasswd の生成・追加・削除・確認と Apache Basic 認証(wp-admin の保護)

htpasswd は、Apache の Basic 認証で使うパスワードファイル(ユーザー名とパスワードのハッシュを1行ずつ並べたファイル)を作成・更新するコマンドです。この記事では、htpasswd でユーザーを追加・削除・確認する方法と、Apache 2.4 で Basic 認証をかける設定を説明します。

パスやパッケージ名は2026年10月時点の Ubuntu 24.04 / Debian 12(Apache 2.4 系)を例にし、RHEL 系(AlmaLinux・Rocky Linux)の違いは都度書いています。

htpasswdをインストールする

htpasswd は Apache 本体とは別のパッケージに入っています。

OS パッケージ インストール
Ubuntu / Debian apache2-utils sudo apt install apache2-utils
AlmaLinux / Rocky Linux / RHEL httpd-tools sudo dnf install httpd-tools

インストールされたかは which htpasswd で確かめます。htpasswd -v はバージョン表示ではなく「パスワードが合っているかの確認」なので、インストール確認には使えません。Apache 自体のバージョンは次で確認します。

# Ubuntu / Debian
apache2 -v
# RHEL 系
httpd -v

パスワードファイルを作る・ユーザーを追加する

パスワードファイルは、Web から見えない場所(DocumentRoot の外)に置きます。ここでは /etc/apache2/.htpasswd を使います(RHEL 系なら /etc/httpd/.htpasswd など)。

# 新規作成して最初のユーザーを登録(-c はファイルを作り直す)
sudo htpasswd -c -B /etc/apache2/.htpasswd alice

# 2人目以降は -c を付けない
sudo htpasswd -B /etc/apache2/.htpasswd bob

-c は既存のファイルがあっても作り直すため、2人目以降に付けると先に登録したユーザーが消えます。

主なオプションは次のとおりです(Apache 2.4 の公式マニュアルより)。

オプション 意味
-c ファイルを新規作成する(既存のファイルは上書きされる)
-B bcrypt でハッシュ化する。何も指定しないときの既定は Apache 独自の MD5($apr1$)
-C 数値 bcrypt のコスト(4〜17、既定5)。-B と一緒に使う
-b パスワードをコマンドラインで渡す。シェルの履歴やプロセス一覧に残る
-i パスワードを標準入力から読む(スクリプト向け)
-n ファイルを更新せず、結果を画面に出す
-D 指定したユーザーを削除する
-v 入力したパスワードが登録済みのものと一致するか確認する(2.4.5 以降)

新しく作るなら -B(bcrypt)を使うのがよいでしょう。スクリプトで登録する場合は、履歴に残る -b より -i を使います。

# 変数 PASS に入れたパスワードを標準入力で渡す
printf '%s\n' "$PASS" | sudo htpasswd -i -B /etc/apache2/.htpasswd carol

パスワードの変更・削除・確認

# パスワードの変更(既存ユーザーに対して追加と同じコマンドを実行)
sudo htpasswd -B /etc/apache2/.htpasswd bob

# ユーザーの削除
sudo htpasswd -D /etc/apache2/.htpasswd alice

# パスワードが合っているか確認(入力を求められる)
sudo htpasswd -v /etc/apache2/.htpasswd bob

# 登録されているユーザー名の一覧
sudo cut -d: -f1 /etc/apache2/.htpasswd

ファイルの中身は ユーザー名:ハッシュ の行です。bcrypt なら $2y$、MD5 なら $apr1$ で始まります。

ファイルの権限は、Apache の実行ユーザーが読めて、他のユーザーからは読めないようにします。

# Ubuntu / Debian(Apache は www-data で動く)
sudo chown root:www-data /etc/apache2/.htpasswd
sudo chmod 640 /etc/apache2/.htpasswd

# RHEL 系(Apache は apache で動く)
# sudo chown root:apache /etc/httpd/.htpasswd
# sudo chmod 640 /etc/httpd/.htpasswd

ApacheでBasic認証をかける

設定ファイルに書く場合

サーバーの設定を編集できるなら、バーチャルホストの設定に書くのが分かりやすく、.htaccess を毎回読む処理も省けます。

<Directory /var/www/html/admin>
    AuthType Basic
    AuthName "Restricted Area"
    AuthUserFile /etc/apache2/.htpasswd
    Require valid-user
</Directory>

特定のユーザーだけ許可するときは Require user alice bob と書きます。

.htaccessに書く場合

共用サーバーなどで .htaccess を使う場合は、保護したいディレクトリの .htaccess に同じ4行を書きます。AuthUserFile は / から始まるフルパスで指定します(相対パスは ServerRoot からの位置と解釈されます)。

AuthType Basic
AuthName "Restricted Area"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user

認証の設定を .htaccess で使うには、そのディレクトリに AllowOverride AuthConfig(または All)が許可されている必要があります。許可されていないと、.htaccess の認証設定は使えません(AllowOverride None なら読まれず、許可されていない種類の指示を書くと 500 エラーになります)。

IPアドレスとの組み合わせ(Apache 2.4の書き方)

社内のネットワークからは認証なし、それ以外からはパスワードを求める、という条件は <RequireAny> で書きます。

AuthType Basic
AuthName "Restricted Area"
AuthUserFile /etc/apache2/.htpasswd
<RequireAny>
    Require ip 192.0.2.0/24
    Require valid-user
</RequireAny>

Apache 2.2 の Order / Allow / Satisfy Any は、Apache 2.4 では互換用の mod_access_compat が有効なときしか動かず、新しい Require と混ぜると意図どおりに動かないことがあります。2.4 では Require だけで書きます。

設定を反映する

# 構文チェック
sudo apache2ctl configtest
# 反映
sudo systemctl reload apache2

RHEL 系では sudo apachectl configtest と sudo systemctl reload httpd です。.htaccess の変更は再読み込みなしで反映されます。

Basic 認証のモジュール(mod_auth_basic・mod_authn_file・mod_authz_user)は Ubuntu の標準構成で有効です。無効にしている場合は sudo apache2ctl -M | grep auth で確認し、sudo a2enmod auth_basic などで有効にします。

動作を確認する

# 認証なしでアクセス → 401 になること
curl -sI https://example.com/admin/

# 認証付きでアクセス(パスワードは入力を求められる)
curl -sI -u alice https://example.com/admin/

認証なしでは 401 Unauthorized と WWW-Authenticate: Basic realm="Restricted Area" が返り、正しいユーザーとパスワードなら本来のステータス(200 など)が返ります。

うまくいかないときは、Apache のエラーログ(Ubuntu は /var/log/apache2/error.log、RHEL 系は /var/log/httpd/error_log)を見ます。

ログのメッセージ(抜粋) 意味
AH01617: user alice: authentication failure for "/admin/": Password Mismatch パスワードが違う
AH01618: user alice not found: /admin/ そのユーザーがファイルに無い(別のファイルを見ている可能性も)
AH01620: Could not open password file: /etc/apache2/.htpasswd ファイルが無い、またはパスや権限が違う
AH01615: need AuthName: /admin/ AuthName が書かれていない

WordPressのwp-adminをBasic認証で守る

WordPress の管理画面に Basic 認証を重ねると、ログイン画面への総当たり攻撃を手前で止められます。ただし wp-admin/admin-ajax.php はサイトの表側(テーマやプラグインの非同期処理)からも呼ばれるため、ここまで認証をかけると訪問者の画面で機能が動かなくなります。admin-ajax.php だけは認証の対象から外します。

# /etc/apache2/sites-available/example.conf のバーチャルホスト内
<Directory /var/www/html/wp-admin>
    AuthType Basic
    AuthName "WordPress Admin"
    AuthUserFile /etc/apache2/.htpasswd
    Require valid-user

    # admin-ajax.php は認証なしで通す(Apache 2.4 の書き方)
    <Files "admin-ajax.php">
        Require all granted
    </Files>
</Directory>

# ログイン画面(ドキュメントルート直下)も保護する
<Files "wp-login.php">
    AuthType Basic
    AuthName "WordPress Admin"
    AuthUserFile /etc/apache2/.htpasswd
    Require valid-user
</Files>

<Files> の設定は <Directory> より後に適用され、既定では後から適用された Require が前のものを置き換えます。このため admin-ajax.php だけが認証なしになります。.htaccess で行う場合は、wp-admin/.htaccess に <Directory> の中身(<Files "admin-ajax.php"> を含む)を書き、ログイン画面の <Files "wp-login.php"> はドキュメントルートの .htaccess に書きます。

確認は次のように行います。

# 認証なしで 401 になること
curl -sI https://example.com/wp-login.php
# admin-ajax.php は 401 にならないこと(WordPress の応答として 400 などが返る)
curl -sI https://example.com/wp-admin/admin-ajax.php

注意点

  • Basic 認証は、ユーザー名とパスワードを Base64 で符号化して送るだけで、暗号化はしません。HTTPS のサイトでだけ使います。
  • パスワードファイルを DocumentRoot の下に置くと、設定によってはダウンロードされるおそれがあります。外に置くのが安全です。
  • Basic 認証をかけたディレクトリは、外部の監視サービスや決済サービスからの通知(Webhook)も通らなくなります。そうした URL があるディレクトリにはかけないか、上の admin-ajax.php と同じ方法で除外します。

関連記事

お気軽にご相談ください

お見積りへ お問い合わせへ
▲