2026年5月20日

2026年5月20日

WordPressステージング環境の設定|ログイン・BASIC認証・noindex・メール停止

ステージング環境は、本番サイトを複製して更新やデザイン変更を試す場所です。本番と同じデータが入っているため、そのまま公開すると、検索結果に重複したページが出る、テスト中の操作で本物の顧客にメールが届く、といった問題が起きます。

この記事では、ステージング環境で行う設定を順に説明します。内容は 2026年11月時点の WordPress 6.9 と WP-CLI 2.12 で確認しています。

1. wp-config.php で環境の種類を指定する

WordPress 5.5 から、WP_ENVIRONMENT_TYPE という定数で環境の種類を指定できます。値は local・development・staging・production のいずれかで、指定しなければ production として扱われます。

<?php
// wp-config.php(「編集が必要なのはここまでです」の行より上に書く)
define( 'WP_ENVIRONMENT_TYPE', 'staging' );

テーマやプラグインのコードでは、wp_get_environment_type() で現在の値を取得できます。後で出てくるメール停止のコードも、この値で本番かどうかを判定します。

デバッグ表示が必要なら、WP_DEBUG と WP_DEBUG_LOG も合わせて設定します。なお、WP_DEBUG を書かなかった場合に自動で有効になるのは development のときだけで、staging では有効になりません。

2. BASIC 認証でサイト全体を保護する

ステージング環境は、関係者以外が開けないようにしておきます。いちばん手軽なのは、サーバーの BASIC 認証です。レンタルサーバーの多くは管理画面から設定できますが、ここでは設定ファイルで行う方法を示します。

Apache(2.4)の場合

パスワードファイルを作ります(公開ディレクトリの外に置きます)。

htpasswd -c /home/username/.htpasswd staginguser

ステージングのサイトの .htaccess に次を追加します。

AuthType Basic
AuthName "Staging"
AuthUserFile /home/username/.htpasswd
Require valid-user

社内のネットワークからは認証なしで開けるようにしたい場合は、Require を RequireAny でまとめます。

AuthType Basic
AuthName "Staging"
AuthUserFile /home/username/.htpasswd
<RequireAny>
    Require ip 203.0.113.10
    Require valid-user
</RequireAny>

Order・Allow from・Satisfy は Apache 2.2 の書き方です。2.4 では上の Require を使います。

Nginx の場合

server ブロックの中(location の外)に書きます。location / { … } の中だけに書くと、.php を処理する別の location には認証がかからず、wp-login.php などを認証なしで開けてしまいます。

server {
    # …既存の設定…
    auth_basic           "Staging";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

設定を変えたら nginx -t で確認してから systemctl reload nginx で読み込みます。

BASIC 認証を通ったブラウザーは、同じサイトの admin-ajax.php などへのリクエストにも認証情報を付けて送ります。そのため、管理画面を使うために admin-ajax.php を認証から外す必要はありません。

BASIC 認証で起きること

WordPress がサーバー内から自分自身にリクエストを送る処理には、BASIC 認証の情報が付きません。そのため、次のことが起きます。

  • 「ツール → サイトヘルス」で、ループバックリクエストの失敗が表示される
  • アクセスをきっかけに予約投稿などを実行する WP-Cron が動かないことがある

ステージングで予約処理を確かめたい場合は、wp-config.php に define( 'DISABLE_WP_CRON', true ); を書き、サーバーの cron から WP-CLI で実行します。

# 5分ごとに実行する crontab の例
*/5 * * * * cd /home/username/staging && wp cron event run --due-now --quiet

3. 検索エンジンにインデックスさせない

管理画面の「設定 → 表示設定」にある「検索エンジンでの表示」で、「検索エンジンがサイトをインデックスしないようにする」にチェックを入れます。WP-CLI なら次のコマンドです。

wp option update blog_public 0

この設定にすると、WordPress は各ページに <meta name='robots' content='noindex, nofollow' /> を出力します。同じタグを出すコードを functions.php に追加する必要はありません。

この値はデータベースに保存されているので、本番のデータベースをステージングに複製し直すと、本番の値(インデックスを許可)に戻ります。複製のたびに設定し直してください。また、noindex は検索エンジンへのお願いであり、アクセス制限ではありません。BASIC 認証と組み合わせて使います。

4. メールを送らないようにする

ステージングで注文や問い合わせのテストをすると、本番から複製したユーザーにメールが届くおそれがあります。WordPress 5.7 からある pre_wp_mail フィルターを使うと、wp_mail() による送信を止められます。

<?php
// wp-content/mu-plugins/stop-mail-on-staging.php
add_filter( 'pre_wp_mail', function ( $return, $atts ) {
    if ( 'production' === wp_get_environment_type() ) {
        return $return; // 本番では何もしない
    }
    $to = is_array( $atts['to'] ) ? implode( ',', $atts['to'] ) : $atts['to'];
    error_log( '[staging] mail suppressed: ' . $to . ' / ' . $atts['subject'] );
    return true; // 送信したことにして、実際には送らない
}, 10, 2 );

null 以外を返すと、wp_mail() は実際の送信をせずに、その値を返します。宛先と件名は debug.log(WP_DEBUG_LOG を有効にした場合)に記録されます。mu-plugins に置くと、テーマやプラグインの切り替えに関係なく読み込まれます。

送信内容を確認したい場合は、宛先を開発者に差し替える方法もあります。

<?php
add_filter( 'wp_mail', function ( $args ) {
    if ( 'production' === wp_get_environment_type() ) {
        return $args;
    }
    $original      = is_array( $args['to'] ) ? implode( ',', $args['to'] ) : $args['to'];
    $args['to']      = 'dev@example.com';
    $args['subject'] = '[STAGING to ' . $original . '] ' . $args['subject'];
    return $args;
} );

どちらの方法も、wp_mail() を通らずに送信するプラグインや外部サービスのメールは止められません。メール配信サービスの API で送るプラグインを使っている場合は、ステージングではそのプラグインを無効にするか、API キーを外します。

5. 本番のデータを複製した後に URL を置き換える

本番のデータベースを複製しただけでは、siteurl や home が本番の URL のままです。この状態でステージングの管理画面を開くと、本番のログイン画面に移動してしまいます。WP-CLI で URL を置き換えます。

# まず何件置き換わるかを確認する
wp search-replace 'https://example.com' 'https://staging.example.com' --skip-columns=guid --dry-run

# 問題がなければ実行する
wp search-replace 'https://example.com' 'https://staging.example.com' --skip-columns=guid

wp option get siteurl
wp option get home

wp search-replace は、シリアライズされたデータの文字数も合わせて書き換えます。SQL の REPLACE で直接置き換えると、プラグインやウィジェットの設定が壊れることがあるので使いません。

本番のユーザーのメールアドレスを、届かないアドレスに置き換えておくこともできます。--skip-email を付けないと、変更のたびに元のアドレスへ通知メールが送られます。

for id in $(wp user list --field=ID); do
    wp user update "$id" --user_email="user${id}@example.com" --skip-email
done
wp option update admin_email 'dev@example.com'

example.com は例示用に予約されたドメインで、実在の人には届きません。user+staging@gmail.com のような「+」を付ける書き換えは、元の受信箱に届くサービスがあるので避けます。

6. ステージングにログインする

本番から複製したステージングには、本番と同じユーザー名とパスワードが入っています。ログインできないときは、次の点を確認します。

  • siteurl と home がステージングの URL になっているか(上の手順 5)
  • 本番でログイン URL を変更するセキュリティプラグインや、2段階認証のプラグインを使っていないか。使っている場合は、本番と同じ URL・同じ方法でログインする必要があります
  • ブラウザーには本番のログイン状態の Cookie があっても、ドメインが違うステージングでは使えません。ステージングで改めてログインします

テスト用のユーザーは WP-CLI で作れます。--user_pass を指定しなければパスワードが自動で作られ、画面に表示されます。

wp user create staging_admin dev@example.com --role=administrator
wp user create staging_editor editor@example.com --role=editor

既存のユーザーのパスワードを変える場合は、通知メールを送らないように --skip-email を付けます。

wp user update admin --user_pass='新しいパスワード' --skip-email

注意点

  • ステージングには本番の顧客情報がそのまま入っています。作業が終わったら削除するか、アクセス制限を外さずに保管してください。
  • 本番に戻すときに、ステージングの WP_ENVIRONMENT_TYPE やメール停止のコードまで一緒に移さないように、wp-config.php と mu-plugins は環境ごとに分けて管理します。

関連記事

お気軽にご相談ください

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