これまでパブリッククラウドはGCP一筋で、ブログ用WordPressもGCEのVMインスタンスで運用していました。ほぼ最小構成なら月2,400円程度。ロリポップのような共有レンタルサーバーの月300円ほどのプランと比較すると、「おや?もしかしなくても、リッチすぎかな?」と思うお値段です。
しかし、「Apacheを自由に触る」という高尚な要件があったので、GCPは優秀だし、「ま、こんなもんだろ」と自己暗示をかけていました(移設は面倒だし忙しいし)。
ところが最近、クライアントのAWS/Lightsailを触る機会があり、その際に料金プランも見てみると最安5米ドルから。料金はGCPの1/3ほどじゃないですか。しかも、Apacheも自由にカスタムできる「仮想専用サーバー型」だと。
「それならば他にも安いサービスがあるかも?」と貧乏根性丸出しで探偵ごっこを始めた結果、国内勢のさくらインターネットが最安プランなら月々600円ほどで、さらに安い。ということで、WordPressをさくらのVPSに移行しました。
さくらVPSはパブリッククラウドのなかでは数少ない国内勢で、以前から気にはなっていたのですが、コスパもよく、コンソールもシンプルで、小規模アプリならさくらVPSもアリかなと思いました。
ここでは備忘録として、その移設作業の顛末と、無駄に凝った構成につき私が毎回のように踏み抜く地雷、そしてその解決策を記録しておきます。誰かの何かの役に立つかは知りませんが、少なくとも私はもう同じ過ちを繰り返さないでしょう。多分。
↓音声で聞く(Geminiで作成)
GCPから国内さくらVPSへ。月2,400円が600円に!コストカットの裏にあった、サブディレクトリ移設の地雷と格闘した全記録。
今回の移設がただの引っ越しで終わらなかった理由。それは、WordPressがドメインのルートではなく `/about/` という「離れ」で暮らしていたからです。この構成が、数々の面白い(そして面倒な)問題を引き起こします。
WordPressを `/about/` で動かすには、すべての関連ファイルが物理的にその中に収まっている必要があります。
/var/www/html/
└── about/
├── index.php
├── wp-admin/
├── wp-content/
├── wp-config.php <-- ココ!
└── .htaccess <-- ココ!
設定ファイルが親ディレクトリに散らばっていると、ApacheはWordPressを見つけられず、404エラーの深淵へ…。
/var/www/html/
├── wp-config.php <-- アレ?
├── .htaccess <-- こっちにも?
└── about/
└── index.php
└── ...
現在のクラウド構成。WordPressは「奥ゆかしい」サブディレクトリ暮らし
さて、我がWordPressの構成は、少々ひねくれています。なぜか?ドメインのルート (https://domain.com/) は「本家」であるWebアプリケーションが居座っており、WordPressはその「分家」のように、サブディレクトリ (https://domain.com/about/) でひっそりとホスティングされていました。奥ゆかしい。
ちなみに、単一のドメインからパスに応じて複数のサーバーにトラフィックを分散させたい場合、「サブドメインにすべきか? あるいはサブディレクトリにすべきか?」という、誰もが一度は悩むがたいてい正解がないという永遠の命題がありますよね。
実際にやってみて管理の手間を考えるなら、サブドメインの方が圧倒的に楽だと思いました。サブディレクトリは「ちょっと凝ったことしたい欲」を満たしてくれますが、その分、設定の沼が深くなることもあります。SEO的にはサブディレクトリの方がよいかもですが……。
既存環境
- 環境:Google Cloud Platform(GCP)上のVMインスタンス(GCE)
- Webアプリのパス:https://domain.com/(GCP上)
- WordPressのパス:https://domain.com/about/(GCP上)
- WordPressの場所:/var/www/html/about/(GCP上)
- アクセス方法:GCPのロードバランサー(LB)を経由して /about/ トラフィックを割り当て
変更点
- WordPressの場所:/var/www/html/about/(さくらVPS)
- アクセス方法:GCPのLBから /about/ へのアクセスをさくらVPSに振り向ける
さくらVPSへの移行フロー。7つのステップで迷宮を突破
この苦行は、大きく7つのステップに分けることができます。
- ステップ1:旧WordPressのバックアップ作成
- ステップ2:さくらVPSのサーバー構築
- ステップ3:WordPressとApacheの内部設定およびリダイレクトルールの調整
- ステップ4:さくらVPS側でのSSL証明書設定
- ステップ5:GCPロードバランサーの設定
- ステップ6:さくらVPSへWordPressでバックアップの読み込み
- ステップ7:最終確認とトラブルシューティング
ステップ1:旧WordPressのバックアップ作成
GCPで動いているWordPressのバックアップを作成します。「All-in-One WP Migration」プラグインを使えば簡単。バックアップしたスナップショットは、最後の命綱としてローカルに大切に保存しておきます。
ステップ2:さくらVPSのサーバー構築
さくらVPSで新しいインスタンスを立ち上げたら、まずSSHで接続し、WordPressを動かすための基本的な環境を構築します。
といっても、さくらVPSならWordPressがあらかじめ組み込まれたインスタンスイメージが用意されており、サーバーを立ち上げると自動でWordPressがインストールされ、以下のように管理画面からログインすることができます。
http://[外部IP]/wp-admin
サーバー側の設定をいじるなら、インスタンスに直接接続するコンソールを使う手もあります。さくらVPSのVNCコンソールは、GCPやAWSのSSH画面と同じようにブラウザベースですが、使い勝手が異なりました。例えばキー入力や貼り付けがしにくく、慣れるのが大変なので断念。代わりに、いつもの慣れたローカルのターミナルからSSH接続しました。これならスムーズ。
ssh [ユーザー名]@[外部IP]
rocky などのユーザー名とパスワードを入力すればOKです。あとはいつものコンソール画面でインスタンスを自由に触ることができます。
ステップ3:WordPressとApacheの内部設定およびリダイレクトルールの調整
ここからが本番です。WordPressが /about/ ディレクトリで正しく動作するように、Apacheにお願いをします。つまり、WordPressは /about/ に引っ越しをするわけなので、ルーティングを依頼するのです。
これは、WordPressを「辺境の地」サブディレクトリでホスティングする際、私という先人が膝から崩れ落ち、そのまま再起不能になったポイントの一つです。大切なのは、WordPressファイルの「物理的な場所」と、Apacheの「マッピング」を一致させることです。
- WordPressアプリケーションのファイル一式を適切な物理パスに配置する
- wp-config.php でWordPressのベースURLを明確に伝える
3-1.WordPressファイル一式を適切な物理パスに配置する
WordPressを特殊なディレクトリでホスティングする際、最も重要でありながら(私が)見落としがちなのが、「WordPressのファイル一式が物理的にどこに置かれているか?」問題です。
通常、肝心のWordPressの脳みそ(index.php)や心臓部(wp-config.php)は旧居(ルートディレクトリ)に置かれています。
/var/www/html/
├── index.php <-- WordPress本体はここにある!
├── wp-admin/
├── wp-content/
├── *その他ファイル一式
└── about/ <-- ここが空っぽ!
この場合、ユーザーが https://example.com/about/ にアクセスすると、サーバーは「WordPressはここじゃないよ」と冷たくあしらい、結果的に「404 Not Found」という、ネットの深淵にユーザーを突き落とします。
解決策はシンプルです。WordPressのファイル一式を、ホスティングしたいサブディレクトリに確実に移動させること。
正しいディレクトリ構造は以下のようになります。
/var/www/html/ <-- ここは空でOK
└── about/
├── index.php <-- WordPress本体
├── wp-admin/
├── wp-content/
├── wp-config.php <-- WordPressのコア設定ファイルはここ!
└── .htaccess <-- Apacheのリライトルールもここ!
もし、wp-config.php や .htaccess が /var/www/html/ のような親ディレクトリに散らばっている場合は、以下のコマンドで /var/www/html/about/ へ移動させましょう。
# wp-config.php を /var/www/html/about/ に移動
sudo mv /var/www/html/wp-config.php /var/www/html/about/wp-config.php
# .htaccess も /var/www/html/about/ に移動
sudo mv /var/www/html/.htaccess /var/www/html/about/.htaccess
これでWordPressは、ようやく自分の「本当の居場所」を理解し始めます。
3-2.「.htaccess」の調整
WordPressが無事に「離れ」に引っ越せたら、今度は大家さん(Apache)に「あのー、すいません、ウチのWordPressは今度から/about/にいますんで、来た郵便物(アクセス)は全部そっちに転送してくださいね!」と、丁寧にお願いする手続きです。これがないと、また「404 Not Found」でユーザーは深淵にダイブします。
具体的には.htaccess ファイルを調整します。このファイルは、特定のディレクトリ単位でサーバーの挙動を制御するという、地味ながらも強力な権限を持っています。サーバー(Apache)とアプリ(WordPress)の力関係の違いを垣間見た気がします。
# /var/www/html/about/.htaccess
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /about/ ; ここが重要!
RewriteRule ^index\\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /about/index.php [L] ; ここも重要!
</IfModule>
# END WordPress
最後に、Apacheがこの .htaccess ファイルを読み込むことを許可しているか確認します。Apacheの設定ファイル(通常は /etc/httpd/conf/httpd.conf や /etc/httpd/conf.d/ssl.conf など)で、WordPressを設置したディレクトリに対して AllowOverride All が設定されていることを確認します。
<Directory "/var/www/html/about"> # WordPressのルートディレクトリのパス
AllowOverride All # 👈 .htaccess を有効にする
Require all granted
</Directory>
AllowOverride が許可されていないと、せっかくリダイレクトルールを書いても Apache さんが読んでくれないので、やはり「404 Not Found」の深淵へとダイブすることになります。
3-3. wp-config.phpのURLを /about に調整
WordPressは起動時、まず wp-config.php を読み込み、自身の「家」がどこにあるかを判断します。ここで「私の家は /about/ というサブディレクトリですよ」と明確に教えてあげなければ、WordPressは迷子になってしまいます。
そこで、wp-config.php ファイルでURLを設定します。ルートでホスティングするならURLを ‘https://example.com/’ にしますが、今回は /about/ をWordPressのルートとしたいので、以下のように設定します。
define( 'WP_SITEURL', 'https://example.com/about' );
define( 'WP_HOME', 'https://example.com/about' );
これがズレていると、「画像やフォントが表示されない」「管理画面がリダイレクトループになる」といった開発者の睡眠時間を奪う問題が発生します。
変更したら、Apacheを再起動して設定を反映させます。
sudo systemctl restart httpd
ステップ4:さくらVPS側でのSSL証明書設定
「HTTPS? え、なんか面倒そうだし、HTTPでよくね?」
楽をしたい気持ちと、安全を確保したい気持ちのせめぎ合いですが、セキュリティや信頼性の観点からはHTTPS一択です。検索エンジンからも「やる気あんの?」とばかりに蹴り落とされるので、SEO的にも必須。
Apache/WordPressでHTTPS接続する手順
いつもHTTPS設定したらそれっきりで忘れがちなので、これを機におさらい。HTTPS接続をするためには以下2つのステップが必要ですね。
- 認証局(CA)からSSL証明書を取得する
- 証明書や秘密鍵などのファイルをApache側で扱えるようにする
HTTPS通信を行うには、まず認証局(CA)からSSL証明書を発行してもらう必要があります。この証明書にはサーバーのドメイン名や、公開鍵、発行元の署名、有効期限等が含まれています。いわば実在証明書です。サーバーが「ドメインは一応、私が所有しています」とアピールするための材料になります。
HTTPS通信をApacheが粛々と行ってくれるようにするためには、このSSL証明書や秘密鍵などの物理的なファイルを正しいディレクトリに配置して、それをApacheが認識・処理可能なように設定する必要があります。
- サーバー証明書(.crt または .pem)
- 秘密鍵(.key)
- 中間証明書(CAバンドル)
Let’s Encrypt/Certbotを使って簡単に設定
こういった手続きをするのは、申請書書いて、ファイル置いて、設定ファイルいじって……と開発者泣かせですが、ありがたいことに、無料の救世主、Let’s Encryptを使えば簡単に証明書を取得できます。
そして、それを簡単に扱えるツールが Certbot です。
私の場合は Rocky Linux で Apache を使っていたのですが、以下のコマンドをターミナルで実行するだけで(他の環境でも似たようなもの)、この不毛な作業から解放されます。
# CertbotとApache用プラグインのインストール
sudo dnf install certbot python3-certbot-apache -y
# 証明書の取得とApacheへの自動設定
sudo certbot --apache -d sakura.example.com
# 指示に従ってメールアドレス入力、利用規約同意などを進めます。
# ドメイン名は実際に使いたいものに置き換える
# 自動更新の設定(通常は自動で設定されます)
sudo systemctl enable certbot-renew.timer
Apache設定ファイルへのSSLディレクティブ追加や自動更新設定(systemdタイマー)などの複雑な作業も自動化してくれるという、至れり尽くせりなツールです。
これがあれば、以下のようなコマンド一発でHTTPS化が完了します
sudo certbot --apache -d sakura.example.com # 間違えると、誰にも証明できない証明書になります
そして、Apacheの設定ファイル(例:/etc/httpd/conf.d/ssl.conf)には自動で以下のような記述が挿入されます:
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/sakura.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/sakura.example.com/pr
しかも、SSL証明書は3ヶ月で期限切れになりますが、Certbotが自動で更新してくれます。期限切れでサイトが胡散臭い状態になる、なんていう惨劇は避けられます。
手作業でやっていた苦労が嘘のようですね。
ステップ5:GCPロードバランサーの設定
WordPressを、GCPから見ればまさに「遠い親戚の家」であるさくらVPSに引っ越しさせました。HTTPS接続もできるようになり、WordPressも /about/ ディレクトリで起動できる状態です。
しかし、まだドメインとさくらVPSのインスタンスは紐付いておらず、ドメイン経由ではその家にはたどり着けません。そこで、GCPのロードバランサーを使って、特定のパス(/about)へのアクセスをさくらVPSにルーティングさせる必要があります。家の門番に、以下のような指示を出すイメージです。
「もし『/about』と尋ねてくる奴がいたら、そいつは遠い離れ(さくらVPS)の裏口に案内してやってくれ」
GCPで仮想バックエンド「NEG」を作成
GCPの「インターネット ネットワーク エンドポイント グループ(NEG)」という、外部インスタンスに接続できる仮想的なバックエンドを作り、それをロードバランサーでマッピングするだけです。
NEGの作成方法は以下の通り。
- タイプ: 「NEG」です。他を選ぶと、Googleのさんは「社内向けですか?じゃあ社内ルールで処理しますね!」と、意図をガン無視
- 範囲: 「グローバル」一択。この指示は世界中に共有
- デフォルトポート:443(HTTPS)推奨でしたね
- ポートタイプ: 「単一」でOK。たくさん種類があっても困ります
- ネットワーク エンドポイント: さくらVPSの「番地(グローバルIPアドレス)」と「部屋番号(ポート)」を登録
ロードバランサーのトラフィック設定
既存のロードバランサーの「URL マップ」を開き、「パスルール」セクションへ。
- ホスト: * 「このサイト宛ての問い合わせは全部聞いてくれ」という指示
- パス: /about/* (「/about/」以下の全てのリクエスト)。これが重要。「『/about/』って聞いてくる奴だけ、裏口(さくらVPS)に回せ」という特定の指示
- バックエンドサービス: 先ほど作成した「インターネット NEG」を選択。これで「裏口への案内係」が割り当てされる
優先度を忘れずに。まるで、VIP専用レーンのように、より具体的なパスルール(/about/*)が、より一般的なルール(/*、例えば通常のWordPressサイトへのルーティング)よりも優先されるように設定します。でないと、「/about/って言ってるのに、トップページに飛ばされる……」と困惑する訪問者が出てきます。
ステップ6:さくらVPSへWordPressでバックアップの読み込み
さてここで「https://example.com/about/」は表示され、「https://example.com/about/wp-admin」で管理画面にログインできるようになったでしょうか? なりましたよね(迫真)。
さくらVPSのWordPressに「All-in-One WP Migration」プラグインを導入して、ローカルに保存したスナップショットをインポートします。
ここで注意点。クラウドプロバイダーやインスタンスイメージによっては、アップロードできるファイルのデータサイズが4MBなどの小さめに制限されていることがあります。なぜ小心者な設定になっているのか分かりませんが、スナップショットのデータサイズによってはインポートができません。
この場合はApache側のサーバー設定を変更する必要があります。「アップロードできるデータサイズの制限が、どこに記述されているか?」はケースバイケースで、要は迷宮探しになる可能性もあります。とはいえ特に以下のいずれかのファイルに記述されていることが多いです。
* `/var/www/html/.htaccess`
* `/var/www/html/wp-config.php`
* `/etc/php.ini`
該当のファイルを見つけたら、以下のように書き換えます。
```ini
upload_max_filesize = 500M
post_max_size = 500M ; これも忘れずに!
これで無事にスナップショットをアップロードできるようになりました。
ステップ7:最終確認とトラブルシューティング
すべての設定が完了したら、実際にサイトにアクセスしてみて問題がないか確認します。
WordPressサイトの表示確認
ブラウザで https://example.com/about/ にアクセス。サイトが表示されるか?
HTTPでアクセスした場合、自動的にHTTPSに飛ばされるか。飛ばされないならCertbotがサボったか、Apacheの設定ミスを疑います。
管理画面へのログイン確認
https://example.com/wp-admin へ。ログインできるか。前述のステップでできているはずですが、もし入れなければ、地獄の始まりです。
画像の表示確認、フォントの読み込み確認
サイト内の画像やアイコン、フォントが全て表示されているか。ここが肝心。 もし表示されないなら、サイトの内部リンクがまだHTTPのままだったり、WordPressのサイトアドレス設定が間違っている可能性が高いです。
ルートディレクトリへの影響
ルートである https://example.com/ にアクセスして、本来のアプリが表示されるかも確認しておきます。万が一WordPressが表示されたら、ロードバランサーのルーティング設定が間違っている可能性大です。
まとめ
ここまで苦労自慢をしてきたわけですが、実は記事に書いた内容以外にもさまざまな地雷を踏んでいます。以下がGCPのコストカット成功の証であり、慰めです。
奥ゆかしい構成の特殊なケースであり、一体誰に伝わるのか甚だ疑問という執筆感だけが残っています。22世紀に生きるシステム開発歴史学者が見つけてくれたら上出来かなと思い、筆を置きます。

