東方同人音楽流通 2026/09/30 + α 配信一覧

2026/08/15 追加配信

サークル アルバム名
TUMENECO 星降る夜のユートピア【Disc1】 (劇場版秘封倶楽部)
TUMENECO 星降る夜のユートピア【Disc2】 (劇場版秘封倶楽部)

2026/09/09 追加配信

サークル アルバム名
愛歌-manaka- Awake
愛歌-manaka- My Crimson
愛歌-manaka- The Light
愛歌-manaka- アンビバレンス・イマージュ
愛歌-manaka- 幻想-Phantasia-

2026/09/30 追加配信

サークル アルバム名
DiGiTAL WiNG EURO BEAT BEST OF DiGiTAL WiNG(Disc1)
DiGiTAL WiNG EURO BEAT BEST OF DiGiTAL WiNG(Disc2)
DiGiTAL WiNG LEGEND WiNG 2026
DiGiTAL WiNG RAVER'S NEST 17 TOHO RAVE PARTY
Fragmented Rhodession Encyclophantasy
Fragmented Rhodession Faux RACERS: Scarlet
K2E†Cradle TOHO EURO TRIGGER VOL.31
K2E†Cradle TOHO EURO TRIGGER VOL.32
LAYIA COLOR Eternal Wish,Fleeting Heart
LAYIA COLOR 世界をきみに委ねて
Moonlight Magic Swing in Taboos
Rolling Contact Chilled Chapters
Rolling Contact Dubliminal Effect
Studio-Stardustglass StibNight
XL Project 東方小曲集 ~唯我独尊~
ZYTOKINE ZYPANG
ノーストリリア Ctrl + BackSpace
ノーストリリア Do you have transient dreams?
ノーストリリア Epilogue
ノーストリリア Here to Hear(t)
ノーストリリア Low-Signal,High-Gain
ノーストリリア Triad:Errant Seasons
ノーストリリア 乖
凋叶棕 牟
少女フラクタル 必然のカタストロフィ/Magical-マジカル-
岸田教団&THE明星ロケッツ 超々キューカンバー
幽閉サテライト 零れ桜/黄昏模様の感情論
染色硝子ノ欠片 神楽の祀り
玲瓏のHydrangea 解錨宣言
茜音色タウン 硝子の蝶 - Single
魂音泉 Elysion II:TOHO Geek Rebuild

東方編曲録の見た目を保ったままフロントエンドを刷新しました

Bootstrap 3・jQuery・Select2からTailwind CSS v4・Propshaft・importmap・Tom Selectへ

こんばんは、迷い家の白猫のシロです。

今回は、東方アレンジ楽曲のデータベースサイト「東方編曲録」の見た目を保ったまま、フロントエンドの構成を刷新した内容について書きます。

新しいデザインに作り変えることが目的ではありません。今までと同じように使えることを優先しながら、内部の仕組みを新しくしました。

まず結論

移行前と移行後の主な違いは次のとおりです。

項目 移行前 移行後
CSS Bootstrap 3 + Sass + Sprockets Tailwind CSS v4 + Propshaft
JavaScript jQuery、jquery-ujs、ページ別の古い読み込み ブラウザ標準のES Modules + importmap
候補入力 Select2 Tom Select
画面遷移 ページ全体を読み直す 必要な部分だけを更新
ページ別処理 共通の大きなJavaScriptを読み込む 必要な画面のモジュールだけを読み込む
アイコン Glyphicons、Ioniconsなど Font Awesome、IcoMoon

CSS、JavaScript、候補入力、画面遷移をまとめて見直したのが今回の変更です。

なぜフロントエンドを刷新したのか

Ruby 4.0 / Rails 8.1へのアップデートと、デプロイ方法をKamal 2へ切り替えられたことがきっかけです。

Dockerでイメージをビルドしてレジストリへpushし、Kamalでデプロイする流れになりました。本番前に確認できる事前確認用の環境も用意できたため、変更を試して確認するサイクルを回しやすくなっています。

そこで、フロントエンドも古い構成を残さず、現在のRailsに合うモダンな構成へ整理することにしました。

以前は、Bootstrap 3とjQueryを含む共通アセットを多くの画面で読み込んでいました。使っていない機能まで読み込まれたり、Bootstrap 3を上書きするCSSが増えたりしていたためです。

フロントエンドの刷新前と刷新後

刷新前は、共通の大きなCSSとJavaScriptを読み込む構成でした。

刷新後は、共通部分と画面固有の処理を分けています。

CSS

共通スタイルはTailwind CSS v4で管理し、Propshaftで配信しています。ページ固有のCSSも分けられるため、スタイルの場所を追いやすくなりました。

JavaScript

jQuery中心の処理をブラウザ標準のES Modulesへ変更し、importmapで依存関係を管理しています。画面の種類に応じて、必要なページモジュールだけを読み込みます。

候補入力

Select2をTom Selectへ変更しました。候補順を保ち、自由入力、日本語入力、候補表示のオン・オフ、選択条件の削除にも対応しています。

見た目を変えないために

今回の目的はデザイン変更ではないため、刷新前の画面を基準に次の部分を確認しました。

  • 文字の太さ、サイズ、行の高さ
  • 入力欄やカードの余白
  • 枠線、角丸、背景色
  • デスクトップからモバイルまでのレイアウト
  • ボタン、タブ、一覧、詳細画面の操作感

Tailwind CSSの標準値に合わせるのではなく、これまでの見た目に値を合わせています。

アイコンは、旧画面のGlyphiconsやIoniconsと新しいFont Awesomeで字形が異なります。この点だけは許容し、それ以外の文字やレイアウトはできるだけ差が出ないようにしました。

容量を比較してみる

刷新前のdevelopブランチと刷新後の現在のブランチを、同じデータベースで比較しました。

計測条件は次のとおりです。

  • 画面幅は375px
  • Docker上で同じデータを使用
  • 各画面の初回アクセスを計測
  • HTMLはHTMLレスポンス、CSSとJavaScriptは/assets/のサイズ
  • フォント、画像、外部ウィジェット、開発用ツールは除外
  • サイズは1 KiB = 1024 bytesで換算

表の数値はすべて「移行前 → 移行後」です。

公開画面ごとのHTML・CSS・JavaScript

画面 HTML (KiB) CSS (KiB) JS (KiB) 合計 (KiB) 合計削減率
ホーム 15.4 → 17.5 982.0 → 234.3 14.8 → 39.1 1012.3 → 290.9 71.3%
検索結果 103.6 → 105.9 982.2 → 234.3 32.7 → 66.6 1118.5 → 406.8 63.6%
詳細検索 19.4 → 22.0 1016.5 → 250.0 301.7 → 250.5 1337.6 → 522.5 60.9%
原曲一覧 95.1 → 95.9 982.0 → 234.3 14.8 → 39.1 1092.0 → 369.3 66.2%
イベント一覧 83.4 → 84.6 982.0 → 234.3 14.8 → 39.1 1080.3 → 358.0 66.9%
イベント日付一覧 19.9 → 22.1 982.0 → 234.3 14.8 → 39.1 1016.8 → 295.5 70.9%
イベント(シリーズ) 42.9 → 45.3 982.0 → 234.3 14.8 → 39.1 1039.8 → 318.7 69.3%
イベント(日付・年別) 17.5 → 19.8 982.0 → 234.3 14.8 → 39.1 1014.3 → 293.2 71.1%
サークル一覧 35.0 → 37.2 676.1 → 242.0 21.2 → 51.8 732.3 → 331.0 54.8%
ボーカリスト一覧 38.9 → 41.1 676.1 → 242.0 21.2 → 51.8 736.2 → 334.9 54.5%
編曲者一覧 39.2 → 41.4 676.1 → 242.0 21.2 → 51.8 736.5 → 335.2 54.5%
作詞者一覧 38.3 → 40.5 676.1 → 242.0 21.2 → 51.8 735.6 → 334.4 54.5%
統計 12.9 → 15.3 982.0 → 234.3 185.4 → 115.8 1180.3 → 365.5 69.0%
統計(原曲) 22.8 → 25.1 982.0 → 234.3 185.4 → 115.8 1190.2 → 375.3 68.5%
統計(原曲・楽曲) 36.8 → 39.0 982.0 → 234.3 185.4 → 115.8 1204.2 → 389.2 67.7%
About 13.4 → 15.7 982.0 → 234.3 14.8 → 39.1 1010.2 → 289.1 71.4%
原曲詳細 68.0 → 70.1 982.0 → 234.3 35.2 → 60.1 1085.2 → 364.5 66.4%
サークル詳細 12.9 → 15.3 982.0 → 234.3 14.8 → 39.1 1009.8 → 288.7 71.4%
イベント詳細 105.5 → 39.8 982.0 → 234.3 0.0 → 39.1 1087.6 → 313.2 71.2%

結果

代表的な10画面の合計サイズの中央値は、次のようになりました。

移行前  1,108.7 KiB
移行後    369.9 KiB

約66.6%の削減です。

多くの画面で共通して読み込んでいたCSSは、982.0 KiB → 234.3 KiBとなり、約76.1%削減できました。

JavaScriptはすべての画面で小さくなったわけではありません。単純な画面では、移行後に共通のapplication.jsなどが加わったため、JavaScriptだけを見ると増えています。一方、詳細検索は301.7 KiB → 250.5 KiB、統計は185.4 KiB → 115.8 KiBになりました。

この表は各画面を独立した初回アクセスとして計測しています。実際の利用ではブラウザキャッシュが効くため、共通ファイルを毎回このサイズ分読み込むわけではありません。

アクセス速度も比較してみる

同じ環境から各URLへ5回アクセスし、HTMLレスポンスの合計時間の中央値を比較しました。画像やフォントを含む画面全体の表示時間ではなく、サーバーからHTMLが返るまでの時間です。

画面 HTML応答時間(ms) 変化
ホーム 76.1 → 56.9 25.2%短縮
検索結果 546.2 → 574.2 5.1%増加
詳細検索 34.5 → 18.0 47.8%短縮
原曲一覧 98.4 → 77.2 21.5%短縮
イベント一覧 58.7 → 35.6 39.4%短縮
イベント日付一覧 35.7 → 20.2 43.4%短縮
サークル一覧 67.0 → 57.9 13.6%短縮
統計 84.3 → 39.3 53.4%短縮
About 32.7 → 12.8 60.9%短縮
原曲詳細 177.7 → 173.0 2.6%短縮
10画面の中央値 71.6 → 48.1 32.8%短縮

検索結果だけは少し遅くなりました。検索条件やデータベースのクエリに左右されるため、今回の計測だけでフロントエンドの刷新が原因とは断定していません。

今回の主な効果は、サーバーの検索処理を速くしたことではありません。CSSとJavaScriptのサイズを減らし、操作のたびにページ全体を読み直さないようにしたことです。

フロントエンド刷新でできた改善

部分更新

検索結果、詳細検索、左メニュー、タブ、ページネーション、一覧から詳細への遷移を、本文の部分更新に対応しました。

URLとブラウザの戻る・進むは維持しながら、必要な部分だけを入れ替えます。失敗した場合は通常の画面遷移へ戻るため、操作不能にならないようにしています。

ページネーションと追加読み込み

ページネーション後は、モバイルでも一覧の「アレンジ曲」付近が見える位置へ移動します。固定ヘッダーに見出しが隠れないよう、余白も確保しました。

一覧は1ページ50件ですが、最後まで表示してからではなく、下端が近づいた段階で次のページを読み込みます。スクロールを止めたときに待たされにくくするためです。

候補入力と画面幅

Tom Selectでは、サーバー側の候補順、自由入力、日本語入力、候補表示の切り替え、選択条件の削除を扱えるようにしました。

デスクトップ、タブレット、モバイルで、ヘッダーとの重なり、一覧表の幅、候補リストの位置、SNSボタンの間隔、タブの枠線なども確認しています。

変わったもの、変えていないもの

内部の構成は大きく変えましたが、画面の配置、文字の見え方、検索や一覧の操作、公開データはできるだけ変えないようにしました。

まとめ

東方編曲録では、見た目と操作感を保ったまま、フロントエンドを次の構成へ刷新しました。

Bootstrap 3 + jQuery + Select2
              ↓
Tailwind CSS v4 + Propshaft + importmap + Tom Select

代表的な10画面では、HTML・CSS・JavaScriptの合計サイズを約66.6%削減できました。今回の計測条件では、HTML応答時間の中央値も約32.8%短くなっています。

さらに、検索やページ遷移の部分更新、追加読み込みの先行処理、候補入力の改善もできました。

見た目を保ったまま内部だけを刷新することで、利用者にはいつも通り使ってもらいながら、今後の改善を進めやすい構成にできました。

東方編曲録を新VPSへ移行し、Ruby/Railsを最新バージョンへ更新しました

Docker・Multipass・CentOS 7・Capistranoを経て、新VPSとKamal 2へ

こんにちは、迷い家の白猫のシロです。

今回は、東方アレンジ楽曲のデータベースサイト「東方編曲録」の大きな更新について書きます。

主な内容は次のとおりです。

  • Ruby 3.0.0からRuby 4.0.6へ更新
  • Rails 6.1.7.10からRails 8.1.3.1へ更新
  • 古いVPS上の本番環境を直接更新せず、新しいVPSを用意
  • Capistrano中心のデプロイから、新VPSではKamal 2へ移行
  • 新VPSの事前検証環境、Basic認証、ヘルスチェック、メンテナンス、rollbackを準備
  • 直近で行った公開画面・管理画面のUI改善

この記事で扱う変更は、プライベートリポジトリで行った一連の変更をもとにしています。リポジトリは非公開のため、この記事ではコードそのものではなく、公開できる範囲の設計と運用の流れを紹介します。

先に大事なことを書くと、変更をマージした時点では、本番DNSを切り替える前の新VPSの事前検証までが完了し、本番DNSの切り替えとproduction向けKamalデプロイはまだ実施していません。本番切り替えの手順も含めて、どこまで準備できたかを記録します。

まず結論

以前は、RubyとRailsの更新を何週間もかけて少しずつ行う計画でした。実際には、更新対象を細かいコミットに分け、Dockerで実行環境を固定し、新しいVPSを並行して用意することで、最初の更新コミットから一連の変更のマージまでを1日以内に終えられました。

Gitの履歴では、最初のRuby/Rails更新コミットから一連の変更のマージまでを、約半日で終えています。

この速度を実現できた最大の要因は、開発パートナーとしてCodexを使えたことです。既存コードの調査、依存関係の更新、互換性問題の切り分け、Kamal移行の設計、UI回帰の確認を、調査・実装・テストのサイクルとして短く回せました。

ただし、これは「古い本番サーバーへその場で更新を適用した」という意味ではありません。旧本番を触らずに、新環境を作って検証し、最後にDNSを切り替えられる状態まで持っていった、という速さです。

更新前と更新後

バージョンの比較

項目 更新前 更新途中 更新後・新環境
Ruby 3.0.0 3.3.12 → 3.4.10 4.0.6
Rails 6.1.7.10 7.0 → 7.1 → 7.2 → 8.0 8.1.3.1
Puma 4.3.12 互換対応 7.2.1
Rails実行環境 ruby:3.0.0 Dockerイメージを更新 ruby:4.0.6-bookworm
デプロイ Capistrano 3 + rbenv + Nginx 旧環境を維持 Kamal 2.12 + Docker + kamal-proxy
DB 既存のMySQL構成 変更しない MySQL Accessory

Railsは一気に8.1へ書き換えるのではなく、7.0、7.1、7.2、8.0、8.1の順番に通しました。Rubyも3.3.12、3.4.10を経由しています。

この順番にしたことで、どのバージョンで互換性問題が出たのかをコミット単位で追跡できます。Rails 8向けのenumや管理画面パラメータ、Rails 8.1向けのPaperTrailなど、変更理由も分けて記録できました。

CentOS 7 + rbenv上でRuby 4.0.6を試す

現行本番は、さくらのVPS上でCapistrano、Nginx、Pumaを動かしています。ホストOSはCentOS 7で、Rubyはrbenvで管理していました。

CentOS 7はすでにEOLを迎えています。それでも、まずは既存環境のままRuby 4.0.6を入れられないか試しました。

rbenvでRuby 4.0.6をインストールするために、コンパイラ、OpenSSL、ビルド依存、RubyGems、既存Gemとの互換性などを一つずつ確認し、かなり頑張ってインストールを進めました。インストールコマンドが通るところまでは進めても、それだけで本番アプリケーションが安定して動くとは限りません。

アプリケーションのbundle、Puma、Capistrano、画像処理、アセット、既存のRailsコードまでを、Ruby 3.0.0から4.0.6へ安定して移行する必要があります。CentOS 7自体がEOLのため、ここで問題が起きた場合にOS側の更新で解決できないことも不安要素でした。

旧コンテナ側でも、Ruby 3.0.0のベースイメージはDebian Busterを前提にしており、パッケージ取得にはすでにarchive.debian.orgを使う対応が必要になっていました。

Ruby 4.0、Rails 8.1、Puma 7を古いOS・古いライブラリ環境へ直接載せ替えると、次の問題を同時に抱えることになります。

  • OS、glibc、OpenSSL、Node.js、native extensionの互換性をまとめて確認する必要がある
  • 失敗したときに、アプリの問題かホストOSの問題か切り分けにくい
  • 本番でRubyを入れ替えるため、切り戻しの手順も複雑になる
  • 作業中に旧環境まで壊すと、比較対象と復旧先を失う

Ruby 4.0.6をインストールすることと、CentOS 7上でRuby 3.0.0から4.0.6へ安定移行することは別問題です。検証を進めた結果、後者を旧VPSの上で続けるのは難しいと判断しました。

そこで、「新VPSを借りて、旧VPSと並行して準備する」方針に切り替えました。OSの更新、Ruby/Railsの更新、デプロイ方式の変更を、新しい環境でまとめて検証できるようにしたわけです。

移行方法の判断マトリクス

選択肢 初期作業 旧本番への影響 切り戻し 今回の判断
旧VPS上で直接Ruby/Railsを更新 少ない 大きい 難しい 不採用
旧VPS上でDockerだけ更新 中程度 OS側の制約が残る 中程度 不採用
新VPSを用意して並行検証 新VPSのセットアップが必要 旧本番を変更しない 旧VPSを残せる 採用
DBまで同時にPostgreSQLへ移行 非常に大きい データ移行リスクが大きい 難しい 今回は見送り

今回の移行では、Ruby/Railsとデプロイ基盤に集中するため、DBエンジンの変更は見送りました。MySQLからPostgreSQLへの移行は、検索SQL、照合順序、インデックス、データ型などを確認する別プロジェクトに分けています。

そもそも、普段の開発環境から大変だった

今回の更新が難しかった理由は、単にRailsのメジャーバージョンを上げるだけではありませんでした。Ruby 3.0.0を使っていたため、私の通常のmacOS環境ではRuby自体をビルドできず、実質的にDockerで動かすしかない状態でした。

macOSではRuby 3.0.0を動かせない

普段使っているMacでRuby 3.0.0を直接ビルドしようとしても、現在のmacOS、Apple Silicon、古いRuby、OpenSSL、native extensionの組み合わせでビルドできない状態でした。

Rubyだけを入れれば終わりではなく、Gemのビルド、Node.js、MySQLクライアント、アセットのビルドまでそろえる必要があります。

そのため、アプリケーションの開発・RSpec・アセットの確認はDockerで行っていました。

Mac
  ↓
Docker Compose
  ├─ Ruby 3.0.0
  ├─ Rails 6.1
  ├─ MySQL
  └─ Node.js / assets

Dockerに閉じ込めることで、少なくともアプリケーションの実行環境は固定できます。一方で、Capistranoのデプロイは別の問題として残りました。

Capistranoを動かすためにMultipassを使う

旧本番へのデプロイにはCapistranoを使っていました。しかし、Capistranoを実行するためのRuby環境も、古いアプリケーションに合わせる必要があります。

そこで、Mac上にMultipassでUbuntu環境を用意し、Capistranoを実行していました。

Mac
  ├─ Docker       : アプリ開発・RSpec・ビルド
  └─ Multipass    : Ubuntu上でCapistranoを実行
                         ↓
                    旧VPSへデプロイ

デプロイのたびにMultipassのUbuntu環境へ入り、そこからCapistranoを実行する必要がありました。アプリケーションをDockerで動かす環境と、旧本番へデプロイする環境が分かれていたことも、日常の負担になっていました。

つまり、日常的に次の4つの環境を意識していました。

環境 用途 Rubyの扱い
Mac本体 エディタ、Git、ブラウザ Ruby 3.0.0は直接動かさない
Docker アプリ開発、テスト、アセットビルド Ruby 3.0.0をコンテナで実行
Multipass Ubuntu Capistranoのデプロイ 旧環境用のRubyとGemを実行
旧VPS 本番 CentOS 7 + rbenv + Ruby 3.0.0

この構成は動いてはいましたが、Ruby/Railsを更新する前から、開発とデプロイの経路が複数に分かれていました。

1日で進めた時系列

時刻(JST) 内容 変更の意味
8/22 13:05 Rails 7.0、Ruby 3.3.12へ更新 古い実行環境から最初の段階へ進む
8/22 14:34頃 Rails 7.1、秘密情報の環境変数化 Railsの非推奨箇所とsecrets.ymlを整理
8/22 15:03〜15:29 Rails 7.2、8.0、8.1へ更新 enum、管理画面、PaperTrailなどを順に互換対応
8/22 16:30 Ruby 4.0.6、Puma 7系へ更新 Docker・CI・Capistranoの実行環境をそろえる
8/22 20:41 Kamal 2の依存とVPSデプロイ設定を追加 新VPS用のデプロイ経路を作る
8/22 夜 GHCR、MySQL Accessory、DB dump/restore、事前検証環境を確認 本番に近い環境で検証する
8/23 00:07 事前検証環境にBasic認証を追加 公開前の画面を保護する
8/23 00:43 現行本番のNginxメンテナンスを準備 DNS切り替え時に旧VPSを安全に止める
8/23 01:31 一連の変更をマージ 実装と切り替え準備が完了

Ruby/Rails更新で行ったこと

Railsをメジャーバージョンごとに通す

更新の順番は、次のようになっています。

Rails 6.1
  ↓
Rails 7.0
  ↓
Rails 7.1
  ↓
Rails 7.2
  ↓
Rails 8.0
  ↓
Rails 8.1.3.1

主な互換性対応は次のとおりです。

  • Rails 7.1以降の管理画面パラメータ検証に対応
  • Rails 8系のenum構文へ更新
  • Rails 8の管理画面ステータス名へ対応
  • Rails 8.1とPaperTrail 17の組み合わせへ更新
  • Ransack、Devise、Pumaなどを互換バージョンへ更新
  • Ruby 3.4以降で標準ライブラリから分離されたcsv、nkf、observer、mutex_mなどを明示
  • Ruby 4.0でCapistrano関連の依存を整理
  • Node.jsをDockerとCIへ入れ、ExecJSの実行環境を統一
  • Active Storageの画像処理に備えてimage_processingとlibvipsを追加

実行環境をDockerイメージに閉じ込める

旧環境では、Capistranoがrbenv上のRuby 3.0.0を使う構成でした。新環境では、Ruby、Rails、Gem、Node.js、画像処理ライブラリ、アセットをDockerイメージに含めます。

新環境では、Ruby 4.0.6を含むDockerイメージを作成します。

本番イメージのビルド時にアセットのコンパイルまで実行するため、デプロイ先でアセットを再生成する必要がありません。新しいコンテナが起動してヘルスチェックを通過した後に、Kamal Proxyが通信先を切り替えます。

config/secrets.ymlを削除する

Railsのconfig/secrets.ymlは削除し、秘密情報を環境変数から渡す形へ変更しました。

秘密情報はリポジトリへ実値を置かず、1PasswordのSecret Referenceをデプロイ時に環境変数として解決します。

1Password
  ↓ op run
環境変数
  ↓
Kamal / Dockerコンテナ

これにより、Gitへ秘密情報をコミットせず、開発PCからKamalを実行する場合とCIから実行する場合で同じ仕組みを使えます。

CapistranoからKamal 2へ

今回の変更は、Capistranoを一度に削除したわけではありません。旧VPSの本番運用を維持したまま、新VPS用のデプロイ経路としてKamal 2を追加しました。

デプロイ方式の比較

項目 旧本番 新VPS
デプロイツール Capistrano 3 Kamal 2.12
Rubyの管理 ホストのrbenv Dockerイメージ
Web Nginx → Puma Unix socket kamal-proxy → Puma TCP
イメージ管理 サーバー上でbundle・アセット生成 GHCRへGit SHAタグでpush
HTTPS 既存Nginxの設定 kamal-proxy + Let's Encrypt
メンテナンス Nginxの静的ページとフラグファイル Kamal Proxyのメンテナンスモード
ヘルスチェック 既存監視 /up、/healthz
rollback Capistranoのrelease切り戻し Kamalで直前SHAのイメージへ切り戻し
DB 既存MySQL MySQL Accessory

旧本番をCapistranoで動かし続けるのは、切り替えまでの安全網を残すためです。新VPSへのデプロイが失敗しても旧VPSは変更されていないため、DNSを戻す判断ができます。

事前検証環境と本番環境を分ける

Kamalの宛先を省略すると本番へ接続してしまう事故を防ぐため、stagingまたはproductionの指定を必須にしました。

宛先 公開範囲 役割
staging 非公開の検証用ホスト 新VPSの事前検証
production touhou.arrangement-chronicle.com DNS切り替え後の本番

事前検証環境では通常ページだけBasic認証を有効にしています。/upと/healthzは、Kamal Proxyと外部監視が利用するため認証対象外です。

実環境では次の結果を確認しました。

確認 結果
認証なしで事前検証環境の通常ページ 認証が必要になることを確認
正しいBasic認証で通常ページ 正常に表示できることを確認
間違ったパスワード アクセスが拒否されることを確認
/up ヘルスチェックが応答することを確認
/healthz ヘルスチェックが応答することを確認

stagingのイメージをproductionへ昇格する

stagingとproductionで別々にイメージをビルドすると、「事前検証環境で確認したものと本番で動くものが違う」という事故が起きます。

そこでstagingで検証したGit SHAをそのままproductionへ昇格させます。stagingで動作確認したイメージを識別し、本番では同じイメージを再ビルドせずに利用する仕組みにしました。

新VPSのセットアップと事前検証

新VPSには、XServer VPSのUbuntu Server 26.04 LTS、4GB RAM、vCPU 4コア、NVMe SSD 150GBの構成を用意しました。

Kamalを実行する前に、次のホスト設定を行います。

  • Ubuntuのセキュリティ更新
  • デプロイ用ユーザーと接続設定
  • 不要な管理者ログインとパスワード認証の無効化
  • UFWで公開ポートを必要最小限に制限
  • AppArmor、時刻同期、unattended-upgradesの確認
  • Docker EngineとCompose pluginの導入
  • XServerのコンソール接続による復旧経路の確認

その後、Kamalのstaging設定を確認し、新VPS上でアプリケーションと関連サービスをセットアップして、事前検証用のデプロイを行います。

MySQLはアプリケーションコンテナとは別のAccessoryとして起動し、3306番ポートは外部へ公開しません。現行本番から取得したdumpを新VPSへrestoreし、検索インデックス、データベースビュー、主要画面を確認しました。

今回、事前検証環境と将来の本番環境は同じDBを使います。ただし、事前検証環境での確認は読み取り中心に限定し、db:seed_fuやカウンター再計算のようなデータ変更タスクを動作確認目的では実行しない方針にしました。

メンテナンス画面を用意する

DNSの切り替え中に、旧VPSへアクセスする利用者と新VPSへアクセスする利用者が混在する可能性があります。そのため、旧VPS側にもメンテナンス画面を用意しました。

旧VPS側はNginxの静的ページ

旧VPSはCapistrano管理のNginxなので、新VPS用のKamalから直接操作できません。旧VPSへは、Nginxのフラグファイルでメンテナンスを切り替えます。

メンテナンスページは、Railsや通常のassets配信に依存しない自己完結したHTMLにしています。Nginx設定をroot権限で反映するときは、appユーザーが書き換えられる場所のスクリプトを直接sudo実行せず、root管理下の/usr/local/sbinへ配置してから実行します。

設定反映後は、Nginxの構文チェックに成功した場合だけreloadします。失敗時はバックアップから復元するようにしました。

新VPS側はKamal Proxyのメンテナンス

新VPSのKamal側では、Proxyがメンテナンス応答を返すモードを使います。アプリコンテナが起動していない状態でも応答できるのが利点です。

事前検証環境では、次の状態を確認済みです。

状態 通常ページ /up
メンテナンス中 エラー応答 ヘルスチェックは継続
メンテナンス解除後 正常表示 正常応答

ヘルスチェックはメンテナンス中も応答するため、Kamal Proxyがアプリの状態を確認できます。

DNS切り替えと本番切り替え

ここは、今回用意した本番切り替え手順です。変更をマージした時点では、まだこのproductionデプロイとDNS変更は実行していません。

切り替え前

  1. stagingで検証したGit SHAとDocker image digestを固定する
  2. 旧VPSでデプロイと書き込みを止める
  3. 旧VPSのNginxメンテナンスをONにする
  4. 新VPSのMySQL、Rails、Kamal Proxy、ログローテーションを確認する
  5. /up、/healthz、トップページ、検索、一覧、詳細、画像、管理画面を確認する
  6. production向けの設定を最終確認する

今回の前提では、新VPSのDBは現行本番の最新状態へ復元済みで、切り替え前の追加更新もありません。そのため、切り替え時の最終dump/restoreは行わない方針です。切り替え前にデータ更新が発生した場合は、この前提を見直します。

DNSを切り替える

新VPSにはグローバルIPv6がないため、Aレコードを新VPSへ変更すると同時に、旧VPSを向いているAAAAレコードを削除します。リンクローカルIPv6をAAAAレコードへ登録しないことも確認します。

DNSのAレコードとAAAAレコードが新VPSを向いていることを確認します。反映には時間差があるので、旧VPSはすぐに停止せず、rollback判断期間はメンテナンス状態で残します。

productionへ同じイメージを昇格する

DNS切り替え後、stagingで確認したSHAをproductionへ昇格します。その後、ヘルスチェック、トップページ、検索、一覧、詳細、画像、管理画面を順番に確認します。

productionで確認するのは、デプロイが成功したかだけではありません。検索結果、一覧のページング、詳細画面、画像表示、管理画面のログイン、Rails/Puma/Kamal Proxy/MySQLのログ、エラー応答の有無まで確認します。

rollbackの考え方

新VPSで書き込みが発生した後に旧VPSへDNSを戻すと、旧VPSのDBには新VPS側の書き込みが存在しない可能性があります。そのため、rollbackは状況ごとに分けます。

状況 取るべき対応
DNS切り替え前 旧VPSのメンテナンスを解除する
DNS切り替え直後・書き込みなし DNSを旧VPSへ戻して正常性を確認する
新VPSで書き込み発生後 まず新VPS上でRailsイメージを直前SHAへ戻す
DB障害 新VPSをメンテナンスにし、restoreまたは切り戻しを判断する

アプリのrollbackとDBのrollbackは別物です。Kamalでイメージを戻せても、DB migrationを自動的に戻してよいとは限りません。スキーマ変更はexpand/contract方式で、古いコードと新しいコードが一時的に混在しても動くようにします。

直近で行ったUI変更

インフラ更新だけでなく、8月中旬から公開画面と管理画面のUIも大きく変更しました。

UI改善の一覧

主な変更 利用者にとっての変化 技術面
共通UIシェル、レスポンシブ、検索、一覧、詳細画面を刷新 PC・タブレット・スマホで探しやすくなった CSS/JavaScript分離、ページング、キャッシュ、N+1削減
原曲・アルバム詳細の前後ナビゲーション 一覧順に沿って次の情報へ移動できる 共通サービス・ヘルパーを追加、CoffeeScriptをJavaScriptへ移行
テーブル内無限スクロール、固定ヘッダー、モバイル操作改善 長い曲一覧でも表の中だけをスクロールできる 読み込み中・失敗・再試行・完了状態を追加
詳細検索のスペース入力、表セルのフォーカス枠を修正 検索とキーボード操作の違和感を減らした Rails 8互換修正と合わせて回帰テストを追加

特に変わったところ

詳細画面の前後ナビゲーション

原曲詳細画面やサークルのアルバム詳細画面で、一覧順に基づく前後リンクを表示するようにしました。

「検索結果へ戻る」「一覧を探し直す」を繰り返さず、前後の原曲・アルバムを順番に見られます。

長い曲一覧をテーブル内で追加読み込み

以前の追加読み込みはページ全体が伸びる方式でした。現在は、テーブルにスクロール領域を設け、その中で追加読み込みを行います。

  • ヘッダーをスクロール領域の上端に固定
  • 読み込み中、失敗、再試行、全件完了を表示
  • モバイル・タブレットの表示切り替えをフローティング化
  • サイドバーの開閉操作を追加
  • 件数カードの列数を画面幅と件数に合わせて調整

データが多いサービスでは、単に「ページを速く表示する」だけでなく、読み終わるまでの操作を止めないことも重要です。

CoffeeScriptからJavaScriptへ

Railsのバージョンアップに合わせて、残っていたCoffeeScriptをJavaScriptへ移行し、CoffeeScript依存を削除しました。UI変更と実行環境更新を別々にせず、アセットパイプラインを整理しながら進めています。

テストと確認

今回の更新では、互換性修正だけでなくテスト基盤も強化しました。

確認項目 結果
RSpec 互換性修正後のテストを通過
RuboCop 対象ファイルを確認
Brakeman セキュリティチェックを完了
SimpleCov branch coverage計測を追加
事前検証環境のBasic認証 認証なし・正しい認証・誤った認証の挙動を確認
ヘルスチェック /up、/healthzの応答を確認
Kamalメンテナンス メンテナンス中・解除後の表示とヘルスチェックを確認
rollback 既知のSHAへ切り戻し、再度復元して確認

UI側では、デスクトップ・タブレット・モバイル幅の表示、テーブル内スクロール、固定ヘッダー、追加読み込みの成功・失敗・再試行を実ブラウザで確認しています。

1日で終えられた理由

1. 本番を直接更新しなかった

旧本番を保持したまま新VPSを作ったので、作業の途中で本番を壊すリスクを抑えられました。新VPS側で失敗しても、旧環境を比較対象として残せます。

2. Ruby/Railsを段階的に更新した

Rails 6.1から8.1へ直接ジャンプせず、各メジャーバージョンを順番に通しました。コミットもバージョン更新、互換修正、テスト、デプロイ基盤に分けています。

3. 実行環境をDockerに固定した

ホストOSへRubyを入れ直すのではなく、Ruby、Rails、Node.js、Gem、アセットをイメージにまとめました。新VPSのホストOSとアプリケーションの依存関係を分離できます。

4. stagingとproductionで同じイメージを使う設計にした

stagingで確認したGit SHAをproductionへ昇格するため、検証済みのものを本番で再ビルドしません。

5. DBの大規模変更を同時に行わなかった

既存のMySQL構成を維持し、PostgreSQL化や文字コードの変更は別課題に分離しました。今回の目的をRuby/Railsと実行基盤の更新に絞れたことが大きいです。

6. Codexと対話しながら進めた

今回の約1日という短さは、Codexの影響が非常に大きいです。Ruby/Railsの更新では、変更箇所を探し、互換性の問題を見つけ、修正し、テスト結果を確認する作業を何度も繰り返します。Codexを使うことで、この調査と修正の往復を止めずに進められました。

デプロイ基盤の移行でも、Capistranoを残す範囲、新VPSへKamal 2を導入する順番、事前検証と本番切り替えの境界を整理しながら実装できました。UI変更についても、検索・一覧・詳細画面の利用者目線と、Rails更新による回帰の両方を同時に確認できました。

正直に言えば、Codexがなければ、この範囲の変更を約1日で形にすることはできなかったと思います。ただし、提案をそのまま採用したわけではなく、変更の妥当性、テスト結果、デプロイ手順、本番切り替えの判断は自分で確認しています。

まとめ

今回のポイントは、古いVPS上でRubyとRailsを無理に更新しなかったことです。

旧環境をCapistranoで残し、新VPSをKamal 2で構築することで、アプリケーションのバージョン更新とサーバー移行を同時に進めながら、切り戻し先も確保できました。

また、直近のUI改善では、検索・一覧・詳細画面を「情報を見つける」「次へ進む」「大量データを読み続ける」という利用者の操作に合わせて整理しました。UIの回帰テストとRailsの互換性テストを同じ更新の中で強化できたのもよかったです。これらを短期間で進められた背景には、Codexと対話しながら調査・実装・検証を進められたことがあります。

変更をマージした時点では本番DNS切り替え前ですが、事前検証環境、DB restore、Basic認証、ヘルスチェック、メンテナンス、rollbackまでを準備できました。本番切り替え後は、DNSの反映時間と新VPSでの書き込みを確認しながら、旧VPSを一定期間維持する予定です。

東方同人音楽流通 2026/06/30 + α 配信一覧

2026/05/15 追加配信

サークル  アルバム
DiGiTAL WiNG  デジウィ LOVELESS
DiGiTAL WiNG  HIGH SPEED BEST OF RAVER'S NEST Vol.5

2026/05/23 追加配信

サークル  アルバム
ShibayanRecords TOHO BOSSA NOVA 15

2026/06/17 追加配信

サークル  アルバム
DiGiTAL WiNG I'll be back

2026/06/30 追加配信

サークル  アルバム
ACCORD ON CODES Live (2025)
Atainchi Records tsuki kaze
COOL&CREATE インターネットサバイバー
Crest Hole In The Wall
Crest Re:RISE
Crest Saikai (止揚-)
EastNewSound EastNewSound 夕月椿 Best
Emoism Records The Memory of Touhou vol.2
fractrick Harmonia del (Piano Version)
fractrick Adamantos Historia 2016-2018
Fragmented Rhodession Hyperphantasia
Fragmented Rhodession Fragmented Aesthetics
Fragmented Rhodession 🩵𝓔𝔂𝓮 𝓒𝓵𝓸𝓼𝓲𝓷𝓰💙
IbEthics Epilogue
IbEthics Truth
IbEthics #EAF4FC
IbEthics Rebirth
INTX Rec. Abundant Reflections
KALANCHOE RECORDS Fantastic Drift!
MN-logic24 ツナグハル
Moonlight Magic ArcanaMaze
Phoenix Project ReiGen-黎幻-
Phoenix Project ReiGen-黎幻2-
Phoenix Project Side by Side
POLTANEST 夜が降りてくる ~ Night in Void
Rolling Contact EAST BREEZE AVENUE
Rolling Contact シュラインサイドで夢を見る
Silver Forest Clutch Shooter #01
Silver Forest Clutch Shooter #02
Silver Forest Clutch Shooter #03
Silver Forest Clutch Shooter #04
SOUND HOLIC THE BEST - 20TH ANNIVERSARY
sound sepher sepher.jp 東方アレンジコレクション1
sound sepher sepher.jp 東方アレンジコレクション2
sound sepher sepher.jp 東方アレンジコレクション3
sound sepher sepher.jp 東方アレンジコレクション4
sound sepher sepher.jp 東方アレンジコレクション5
sound sepher 東方幻奏祀典11 Libretto
XL Project Afterlife
XL Project 流界回音
ZYTOKINE Out Of Order
アベニュールーム 一問一闘
イノライ ALIVE SCARLET
イノライ INORAI Touhou Music 1
イノライ こいフラ Silent Night
イノライ ALIVE SCARLET
オーライフジャパン 神秘披歴譚
かなまいのサークル ダンマクヒロイズム
ジェリコの法則 Madness Manipulation
ジェリコの法則 New Immersion
ゼッケン屋 Zekken No.8 New Old Stock
ちょこふぁん おまけSelection2
マッコ屋 離れてく。
マッコ屋 近づいてく。
茜音色タウン MY TWO HISTORIES
茜音色タウン 失楽園
外柿山 オーケストラ拾遺集
甘夏 -アマナツ- 東方ずんだかーにばる
甘夏 -アマナツ- Elektro Fox
甘夏 -アマナツ- 写し夢
甘夏 -アマナツ- Spring Ensemble
甘夏 -アマナツ- ナナイロポップ
給食頭蛮 Aero Utopia
暁Records LIMITED SINGLES season5
荒御霊 穢土純来
魂音泉 Reign
少女フラクタル 彷徨いの冥~天~&境界線上のランデブー
少女理論観測所 壊れた人形のマーチ変奏曲集
針の音楽 針の縫い目
針の音楽 幻宴Project ~ オーケストラとスクリーンで甦る幻想郷の歴史絵巻
幽閉サテライト 星に寄せる想い/色は匂へど散りぬるを
粒々アンサンブル SWINGIN N SPRINGIN3
玲瓏のHydrangea 星が降る前に
玲瓏のHydrangea Exclusive Tracks Collection Vol.2

2026/07/27 追加配信

サークル  アルバム
CrazyBeats GENSOU DANCE FESTIVAL 03
森羅万象 シンクロ6
東方LostWord sine nomine
東方LostWord ギラギラGood day
東方LostWord 一輪花

東方同人音楽流通 2026/05/04 配信一覧

サークル アルバム
A-One Nobody's Pussycat
DiGiTAL WiNG デジウィBEST (2025)
DiGiTAL WiNG RAVER'S NEST 16 TOHO RAVE PARTY
DiGiTAL WiNG Chasing Rain

東方同人音楽流通 2026/03/31 配信一覧

サークル アルバム
A-One Nobody's Pussycat
Amateras Records 恋トラ -KOIIRO MASTER TRANCE 04-
Amateras Records Endless Journey
EastNewSound Illegal Door
Emoism Records The Memory of Touhou
K2E†Cradle TOHO EURO TRIGGER VOL.28
K2E†Cradle TOHO EURO TRIGGER VOL.29 Non-Stop BEST
K2E†Cradle TOHO EURO TRIGGER VOL.30
Lapis lanta Rose Icy memoria
magic red kids the answer is…
Moonlight Magic Coldblood
OTAKU JAZZ COLONY BLUE CLIENT
POLTANEST リジッドパラダイス ~ Reanimate
Rolling Contact HARDCORE BARRAGE X-5
Rolling Contact ELECTRO CUTE 8
Rolling Contact Twisted Bouncers 8
Silver Forest Super Forest Beat VOL.17
SOUND HOLIC NANA HOLIC VII
TUMENECO 星夢セカイ
TUMENECO エンドレス・リピート
TUMENECO 黄昏ボーダーライン
TUMENECO 空を待つ魔法
イノライ 綺麗事だけの歌が嫌いだった
イノライ INORAI Live OST 妖々夢
イノライ Valentine Mode♡
マッカチン企画 DIVE INTO STARSHIP
マッカチン企画 FAR EAST JOURNEYS
マッカチン企画 MCK THE BEST HIT TOHO
マッカチン企画 MONSTER POPULATION
マッカチン企画 Re:makes MCK!
マッカチン企画 空想ネクストリップ
マッカチン企画 モノノケ・ナイトフィーバー
マッカチン企画 永夜リフレイン
マッカチン企画 REPOP MEMORIES
マッカチン企画 黄昏ブラインド
マッカチン企画 月面ストレンジャー
マッカチン企画 東方幻想ジェネレーション
茜音色タウン DOWNTOWN-12 Hollow
茜音色タウン 桜咲ク未来ヘ -廻桜- (Rebuild)
音召缶 -OTOMEKAN- Eternal Tanz (OMK Instrumental Trax Collection)
音召缶 -OTOMEKAN- Gensou Hard Dancing
音召缶 -OTOMEKAN- Gensou Hard Dancing2
机上の空想理論 ちぇあ’s 東方アレンジ せれくしょん。
暁Records オマケベストなのか~その④
群雨アンブレイラ Swap!! -MurasameUB Exchanged Remix Collect.-
群雨アンブレイラ Reminiscence Worlds
群雨アンブレイラ Gevurah
荒御霊 Blameless
魂音泉 カワシロラボ B1
魂音泉 THE SELECTED WORKS OF TAMAONSEN 7
少女フラクタル 輪廻転生のバタフライvol.2
少女フラクタル 無限大ドリーマー
凋叶棕 縁 (配信版)
幽閉サテライト 君と不揃いなカンタータをvol.2
幽閉サテライト 始まりの雨
幽閉サテライト 漢の幽閉サテライト 参
玲瓏のHydrangea 想い乱れて 咲く日まで

東方同人音楽流通 2025/10-2025/12 配信一覧

サークル アルバム
A-One EYE LOVE YOU, YOU LOVE ME?
A-One The Night of the Chupacabra
ちょこふぁん ちょこふぁん BEST 2025
ちょこふぁん ちょこふぁんアソート
ちょこふぁん 四等分のフランドール
ちょこふぁん STONE SOUNDS
森羅万象 東方歌ってみた 配信Ver
森羅万象 ノンフィク陰謀論