Xserverとの連携 — FTPと.htaccessと、たまに落ちるデプロイ
シリーズ3本目。サーバーはXserverを使っています。理由は「すでに契約していたから」で、それ以上でも以下でもありません。ただ、GitHubから自動で反映させようとすると、いくつか知っておくべきことがありました。
構成
mainブランチにマージされると、GitHub ActionsがHTMLを圧縮し、FTPでXserverに送り、送った先のバージョンが一致するか確認します。私がやることは「マージGO」と言うことだけです。
送り先は、ゲーム本体・プレビュー環境・ポータルサイトの3系統。ゲーム本体とそのプレビューは同じFTPアカウントでフォルダだけを分け、ポータルは別ドメインなので別アカウントにしています。
ハマったこと、順不同
FTPが、たまに接続できない
これが一番多い。デプロイの数回に1回くらい、FTP接続がタイムアウトして失敗します。原因は突き止められていませんが、失敗したジョブだけ再実行すると、ほぼ確実に通ります。最初は毎回原因を探していましたが、いまは「一過性」と割り切って、失敗したらAIに「失敗したジョブだけ再実行」を指示する運用にしています(ワークフロー自体に自動リトライは入れていません)。3回続けて失敗したら本当に何かが壊れている、という基準です。
サブドメインは「フォルダ」である
Xserverでサブドメインを作ると、親ドメインの公開フォルダの中にサブドメイン名のフォルダが切られ、そこが公開領域になります。つまり game.example.com/ と www.example.com/game/ が同じ場所を指す。これを知らずに「2つのURLで同じゲームが見える」と混乱しました。
FTPアカウントはこのフォルダ単位で作れるので、ゲーム用・ポータル用で分けておくと、片方の作業でもう片方を壊す心配がなくなります。
プレビュー環境は必須
AIが作った変更をいきなり本番に出すのは怖い。なので、PRを作ると自動でプレビュー用のURLに反映され、そこを確認してからマージする流れにしました。プレビューには検索避け(noindex)を入れて、間違って検索に出ないようにしています。
ここで一度やらかしたのが、AIがポータルサイトの更新をプレビューを飛ばして本番に出したこと。AIは「ポータルにはプレビュー環境が無い」と思い込んで作業を進め、実はプレビュー用のワークフローがちゃんと用意されていました。リポジトリを見れば分かったことです。私も「アップしてみて」と言ってしまい、止められなかった。確認より思い込みが先に立つと、こうなります。AIも、人間も。
.htaccessは階層で優先される
ポータルのルートに「wwwなしをwww付きに転送」というルールを置いたのに、ゲームのフォルダには効きませんでした。フォルダごとに.htaccessがあると、深い階層のものが優先されるからです。ゲーム側にも同じルールを足す必要がありました。
圧縮後のファイルは、文字列で検証できない
本番に出るHTMLは圧縮されているので、「この変数名があるか」で確認しようとすると失敗します。関数名や構造で確認する、あるいはバージョン番号を専用の場所に埋めて、そこだけを見る。検証の方法を、圧縮を前提に設計しておく必要がありました。
いまの運用まとめ
| やること | 担当 |
|---|---|
| コード修正・PR作成 | AI |
| プレビュー確認 | 私 |
| マージ指示 | 私 |
| マージ・本番デプロイ | AI(私のGO後) |
| デプロイ失敗時の再実行 | AI |
| FTPアカウント・DNS・ドメイン設定 | 私(サーバーパネル) |
最初から知っていたら
- FTPの失敗は一過性が多い。「失敗ジョブだけ再実行」を運用に組み込む
- サブドメインの実体はフォルダ。FTPアカウントもフォルダ単位で分ける
- プレビュー環境を最初に作る。本番直行はしない
- 圧縮後でも検証できる目印(バージョン番号)を埋めておく
シリーズ「最初から知っていたらこうした」
- 何はともあれGitHub連携
- GitHub連携で最初につまずいた話
- AIのメモリーは当てにしない。全部GitHubに残す
- Xserverとの連携 — FTPと.htaccessと、たまに落ちるデプロイ(この記事)
- 必ず事実から確認する — ルールを作って、随時直す
- マジで苦労したところ → こう対応した
- AdSenseの審査が通らない
- Issueに @claude と書くだけで、Claude Codeが動き出す
- AI丸投げでゲームはできるの?
- さよなら、ChatGPT
- Claudeさんに絵を描いてもらう方法