[🛠] Operations Automation #3: レガシー年休自動化のNAS移行と外部HTTPS接続
✨ GPT-5.6 Solの要約
既存の年休取得促進機能とデータを新しいNAS環境へ移し、外部HTTPS接続後に実機のモバイル端末で見つかったUI不具合まで直した記録。
レガシー年休自動化の機能とデータを新しいNAS環境へ持ってきて、外部HTTPSリクエストがNAS内部のアプリケーションまで届く経路をつないだ。単にcontainerを起動したのではなく、既存の業務フローを新しい運用環境へ移す作業だった。
しかし、新しい画面が開くだけでは移行完了とは言えなかった。従業員と年休のデータが表示され、取得促進の対象とメッセージ文面が既存と同じでなければならない。一日130件を超えたメッセージは翌日へ繰り越され、送信queueと履歴も引き継がれる必要があった。一つでも抜ければ、名前だけが同じ別のサービスになってしまう。
先に営業自動化と従業員管理を再び分けたとき、既存の年休取得促進機能はまず再現してから移すことにしていた。実際に始めてみると、その順序はさらに重要だった。NASへのdeployはしばらく後回しにした。
ローカル機能の再現とデータ復元
FastAPI、Next.js、MariaDBを、隔離したローカルCompose環境で先に動かした。既存サービスと衝突しないよう、port、network、volume、credentialも別にした。管理者としてログインして従業員・年休データを開き、取得促進対象、生成された文面、130件制限を超えた予約、queue、履歴を既存フローと照合した。
運用DBを直接触りたくはなかった。既存のSQL backupを別のMariaDBへ復元し、schemaと主要tableの件数を比較した。backendを再起動した後もデータが残っているか確認した。ここまでできて初めて、ローカル動作の基準ができた。その後NASで問題が起きても、コードの違いなのか、imageやnetworkの誤りなのかを切り分けられるようになった。
backupが復元されたからといって、運用移行が終わったわけではない。管理者アカウントも、業務用端末も、実際のSMSも、まだ新しい経路を通っていなかった。
実際のSMS送信経路に設けた二重制限
次に詰まったのは実際のSMSだった。メッセージを送らなければ、Android業務用端末まで続く経路を最後まで確認できない。かといって、production送信を開いたまま試験するわけにもいかなかった。
そこでserverの送信modeを三つに分けた。
NO_SEND
ALLOWLIST_SEND
PRODUCTION
普段はNO_SENDだ。試験するときだけ、許可した受信者一人をALLOWLIST_SENDに入れた。電話番号の平文ではなくSHA-256 hashで対象を照合し、serverが取得できる件数を1件に制限した。Androidアプリの中にも別の1件budgetを入れた。serverかアプリのどちらかを誤操作しても、二通目は送られないようにしたかった。
この状態はコードを見るだけでは済ませなかった。Computer Useで実際の管理画面を開き、NO_SEND、現在claim可能な件数、queue、履歴を確認した。同じ画面でCodexの作業結果と実装コードも照合した。

運用アプリをそのまま触らないよう、テストpackageも別に作った。USB接続したAndroid端末にはadb reverseでローカルendpointをつないだ。こうして実際のSMS一通がSUCCESSで終わり、受信端末でも届いたメッセージを確認した。
曖昧な結果も一つ出た。利用者はメッセージを受け取ったが、Androidのdelivery callbackは取得できなかった。SUCCESSは通信事業者が送信リクエストを受け付けたという意味であり、delivery callbackまで完了したという意味ではない。実際の受信とcallback状態を同じ成功としてまとめると、後でUNKNOWNをどう扱うかがさらに分かりにくくなると思った。
一通を確認した後は、すぐNO_SENDへ戻した。Android readinessは0、server claimは204 No Contentになった。もう一度テスト操作が行われても次のSMSはない状態で終えた。
linux/amd64 Docker imageのNAS移行
NASには自動化platform全体ではなく、年休自動化サービスだけを個別に載せた。NASでsourceをbuildし直さず、Macでlinux/amd64 imageを作り、hashを確認して移した。Compose projectも既存stackとは分けた。backend一つを入れ替えたときに、MariaDBとFrontendまで一緒に作り直されないようにする構成だった。
外部HTTPSとReverse Proxyの接続
新しいアドレスでログイン画面が開き、既存の従業員・年休データも表示された。だが、外部ブラウザからMariaDBまでリクエストがどう入るのかは、文章だけでは一目で分かりにくかった。特に3101がInternetへ開いているportなのか、NAS内だけで使うportなのかを説明するとき、境界が何度も混ざった。リクエスト経路を図にした。
図にしてみると、外部に必要なのはHTTPS 443一つだけだった。Routerが443をNASへ転送し、NASのreverse proxyがhostnameを見て127.0.0.1:3101のFrontendへ送る。Backend 8000とMariaDB 3306はDocker network内だけで接続される。3101もNAS loopbackだけにbindされているため、Internetから直接アクセスできない。
Cloudflareを標準経路に入れなかったのも同じ理由だった。すでに利用しているauthoritative DNSと固定グローバルIPがあり、Routerも直接制御できた。サービス用A recordだけを追加し、NASで証明書を管理すれば、中間構成要素を一つ減らせた。その代わり、証明書更新とport forwardingは自分で管理しなければならない。証明書の発行・更新に使う80を除けば、実際のサービスリクエストは443だけで受ける。
実機モバイル端末での検証とレスポンシブUI修正
外部HTTPSアドレスが開いたからといって、移行が終わったわけではなかった。USBで接続した実際のAndroid端末からモバイル回線で新しいアドレスにアクセスし、ログインからdashboard、従業員一覧、SMS履歴、年休管理まで直接確認した。画面は開いたが、そのまま使える状態ではなかった。
PCブラウザの幅を狭めただけでは見逃していた問題が、実機では一気に現れた。dashboardではデスクトップ用sidebarが画面の大半を占め、cardと文字が縦に押しつぶされていた。
以下の比較画像はすべて、左が修正前、右が修正後だ。

従業員一覧では、見出しとbuttonが一文字ずつ折れ、横長のtableが狭い幅へ無理に押し込まれていた。見出しと操作領域は横の流れを保つようにし、tableは内容を押しつぶす代わりに必要な分だけ横へscrollできるようにした。

SMS履歴と年休管理のfilterも同じ問題だった。複数の入力欄と日付範囲が一行へ押し込まれていた。小さい画面では二列を中心に配置し、日付範囲は別の行へ下げ、各項目を読んで押せるようにした。


修正後は新しいDocker imageを再deployし、同じ端末でもう一度ログインした。メニューを開き、画面をscrollし、各filterとtableを直接見ながら、最初に見つけた不具合が消えたかを確認した。外部networkがNASのcontainerまで届くかだけを見るはずだった検証が、実際に使う画面まで直す作業へつながった。
段階別の移行状況と管理者UI/E2E検証
NAS移行、外部接続、内部SMS一通までつないで全体roadmapをもう一度広げると、1〜3段階は越えていた。現在地は、改善した管理者UIを新しいimageとしてdeployし、ADBと実機ですべてのpageをもう一度確認する第4段階だった。

この図を添えると、今回の作業の次の境界もはっきりした。外部接続自体はすでに通過したが、管理者画面の実機再検証が終わるまでは本社でのdogfoodingへ進めない。だから次の段階は新機能を増やすことではなく、修正したUIがデスクトップとモバイルの両方で同じ業務フローを保つか最後まで確認することにした。
運用移行前の安全状態とrollback
現在、新しいstackは意図的に何も自動実行しない設定にしている。
ENABLE_SCHEDULER=False
SMS_SEND_MODE=NO_SEND
SMS_ALLOWLIST_MAX_CLAIMS=0
管理者credentialはComposeやimageには書かなかった。NASでは権限0600のsecret fileから渡し、MacではKeychainに保管した。
新しいアドレスでログインしてデータを読めるようになり、制限した条件ではSMS一通も届いた。外部モバイル回線でも、ログインからデータ参照、画面操作まで確認した。それでも既存の年休SMSサービスを削除するには、delivery callbackがない送信の復旧方法と、実際の送信条件への承認が残っている。
そこで既存のcontainerとvolumeは停止するだけにして、そのまま残した。次に必要なのは構成を増やすことではない。callbackがない送信をどう復旧するか決め、承認された条件で限られた件数から実際の送信を開くことだ。
技術移行とは別に、AIに実際の端末とRouter・NASの管理画面まで一緒に見せたことで自分が感じた変化は、AIを積極的に活用できれば、できることが無限に広がって感じられるに分けて書いた。
コメントする