Chienomi

全ドメインをVPSに統合, ConoHa WING解約

Live With Linux::server

これは少し長い話になってきたものだ。 まず、2022年10月にConoHaでの情報漏洩疑惑があり、それをきっかけにメインサーバーをConoHaからさくらへと移した。

これに伴ってChienomiとHarukamy’s ChatshowをWINGから新しいVPSへと移設した。 これにはなかなか大変な移植作業が発生していた。

そして2023年3月にConoHa VPSでAkkomaサーバーを立て、続いてVultrでMisskeyサーバーを立て、この流れでConoHa VPSのAkkomaをVultrのMisskeyサーバーに統合し、メインサーバーをさくらからVultrへ移した。

このVultrメインサーバーはCloudFlareとの組み合わせになっており、これを機としてProject Radio Harukamy, Harukamy’s Memoranda, はるかのおはなしのおはなしの3つのサイトをWINGからVPSに移設した。

さらにその後、同月にもう1台(新しいドメインで)Vultrのサーバーを増やしている。

まとめるとこの時点でサーバーは次のようになっている。

  • ConoHa WING (Mimir Yokohama, Pieces)
  • Vultr VPS 1 (Akkoma, Misskey)
  • Vultr VPS 2 (Chieomi, and more 6 domains)
  • Vultr VPS 3 (New domain, HarukaSound)

時系列で(Akkoma, Misskeyの話を除外して)並べるとこうなる

  1. 漏洩疑惑事件が起きる
  2. さくらのVPSを契約してVPS移設, ConoHa VPSを解約 (2つのVPSから1つのVPSに統合)
  3. ChienomiのアプリケーションをVPS用に再開発
  4. ChienomiとHarukamy’s ChatshowをVPSへ移設, ConoHa WINGから削除
  5. Vultr2を契約, さくらのVPSからVultr2へ引っ越し
  6. CloudFlareを契約, ネームサーバーをConoHaからCloudFlareへ変更
  7. 2つのウェブサイトをWINGからVultr2へ移設・移植
  8. Vultr2にLighttpdとHiawathaを導入, CGI実行環境を用意する
  9. Vultr3を契約
  10. 新しいメールフィルターを開発, Vultr3へ導入
  11. 1つのウェブサイトとメール運用をVultr3へ移設・移植
  12. 従来VPSからのメールの転送先をWINGからVultr3へ変更, WINGのメール機能の利用を(Mimirを除き)停止
  13. 1つのウェブサイトをWINGからVultr2へ移設・移植
  14. メールフィルターをVultr2に導入, Vultr3への転送をやめる
  15. MimirとPiecesのウェブサイトおよびメールをVultr2へ統合・移植
  16. ConoHa WINGを解約

これまでの経緯の俯瞰

2022年10月からConoHa脱出を進めてきた。 この時点ではあまり現実的なものではなかった。さくらのサービスが、ConoHaを代替することができるようなものではなかったためだ。 「メインサーバーをConoHaに置いておかない」というレベルの話だったのだ。

しかしVultr+CloudFlareに強く可能性を感じ、いよいよ脱出が見えてきた。 ConoHaでやっていたことが完全に実現可能だし、WINGと比べると手間は増えるが、色々とサーバーを増やしたためにWINGのコストを払うのも辛い。それに、信頼できないConoHaに頼っていることもできない。

従来、ウェブサイトは完全にWING向けにチューニングされていた。 要は、レンタルサーバーであるWING上にRuby環境を構築して、そこにGemも入れて、Rack/CGIで動作させるという形だったし、ホームディレクトリ以下に縛られ、なおかつウェブアプリケーションはユーザーの権限で動作することを想定していたのだ。

ChienomiはこれをRack/Thinのアプリケーションサーバーに書き直した。 そもそも、全体でひとつのアプリケーションになるように書き換え、さらに複数のサイトにある「検索機能」「コメント機能」はそれぞれ独立したCGIスクリプトであり、仕様が少しずつ違ったが、これを共通仕様に作り変えた。

だが、全部に対してこれをやるとまた複雑なことになるし、Webhookを書きたい場合などCGIが使えると便利なケースは多い。

また、以前使っていたメールフィルターはメモリ不足でサーバーを落としたことがあるため、メールフィルターなしでWINGに転送し、WINGのメールフィルターに頼る仕組みになっていたが、相当な数のスパムメールを受け取っているため、メールフィルターなしでの運用はできない。

このことから、WINGからの移設で障壁となるのは

  • ウェブアプリケーション
  • メールフィルター

の2点だった。

Vultrに移してWING廃止が見えてきたことで、まずNginxのうしろにLighttpdを置く形でCGIを実行可能にした。 Nginxは直接CGIを実行できず、WINGではNginxのうしろにApacheがいる形になっている。静的ファイルのサーブもNginxはしない。

私はVPSでそのApacheの代わりにLighttpdを置いたわけだ。 Apacheよりも構成変更がしやすく、速く、軽く、設定が楽だ。 第二の選択肢としてHiawathaも用意している。

ただし、WINGのCGIスクリプトはWINGに合わせて書かれているため、VPSでそのまま動くわけではない。 このため、Harukamy’s Memorandaのコメント機能(ビルド時に組み込まれるという、結構複雑な機能である)は廃止にした。 正直スパムと荒らししかこないようなものだったので、あまり困らない。

メールのほうはもっと厄介だ。 メールフィルターを用意するというのも必要だが、大手メールプロバイダーが弱小VPSのメールを受け取らないという問題もある。 このことから、メールフィルターを開発し、まず全く新しいドメインでの運用を試した。

一見問題なさそうに見えたが、SpamAssassinがReceivedヘッダーを直近のものしか見ないため、SPF FAILしてしまうという問題があった。リソース的な意味でやや重いメールの処理はVPSから分離しておきたかったのだが、結局メールを転送するやり方自体を廃止にした。

そして、しばらく運用して、メールフィルターがちゃんと機能すること、新しいサーバーからのメールをGMailが問題なく受け取ってくれることを確認した上で、Mimir Yokohamaの統合に着手したわけだ。

なお、この話とは無関係だが、ChienomiをVPSに移した際に証明書がおかしいという問題が発生しており、これはCertbotの設定がおかしなことになっていたため(多分ドメインを除外するタイミングで壊したのだろう)、すべての証明書を作り直すということもあった。

Mimir YokohamaとPiecesを統合

Piecesが後回しにされた理由は正直よくわからない。 どちらかというとMemorandaのほうが厄介なスクリプトを持っていたはずだが。

Mimir Yokohamaのほうは明確だ。 Mimir Yokohamaには以下のアプリケーションがある

  • コメント
  • いいね
  • 検索
  • お問い合わせ送信

共通のアプリケーションとして「いいね」と「検索」があり、これはChienomiなどと同じように統合できるのだが、Mimir Yokohamaのコメント機能はほかと違い公開されず、単に感想を送るようなものになっている。 また、お問い合わせ送信機能はMimirにしかない。

(実際はさらに、チャットボット機能があったりするのだが、現在は公開していないので今回の作業には入っていない。)

ここでLighttpdバックエンドの登場だ。 だが改めてみると移植はしんどい、というか、魔改造されたCGIスクリプトを普通の環境で動かすために、また魔改造するというようなものになるため、手を入れることにした。

だが考えてみれば……感想を送るのと、問い合わせを送るのは同じようなものではないか?

従来、感想はファイルに書き、問い合わせはメールにするために分かれていたのだが、もともとコピーして改変されたもので、両者の処理は似ている。 そこで両者をひとつのファイルにまとめ、ついでに無駄に分かれているライブラリも取り込んだ。 Rack handlerはもう使えないので、Rackup Handlerへの変更も行った。

それ以外はここまで入念に準備してきたので、それほど苦労はなかった。

Postfix/Dovecot カスタムフィルタとバーチャルドメイン

カスタムフィルタを組み込む方法はSMTPDのパイプ, Milterなどの方法があるが、組み合わせに少し困ったりすることもある。 そこで私はlocal(8)を使用することを前提としてエイリアスコマンドを適用した。

エイリアスコマンドはエイリアスファイル(一般的には/etc/postfix/aliasesあるいは/etc/aliases)で

foo: "|foocommand arg1 arg2"

のように書くことでメールをコマンドに渡すことができる。

ここで重要なこととして、MDAコマンドは絶対に失敗してはいけない。 0以外のステータスコードが返ると、(特別な意味をもつステータスコードもあるが)エラー内容もろだしのバウンスメールが返ってしまう。なので、なにがなんでも(たとえエラーになっても)ステータスコード0で終了するように例外をすべて拾うこと。

それでもメールが失われる可能性はなくはないので、私は

foo: "|foocommand arg1 arg2", allbox

のようにしてすべてのメールが特定のメールボックスに(も)入るようにしている。 このメールボックスは普段は見ないし、定期的に掃除している。スパムも入ってしまうが、普段見ないためあまり困らない。

local(8)はこのエイリアスを何度でも検証するため、ボックスをまとめたりするのに使える。 というより、私の運用だとエイリアスはかなり巨大になる。

そこでちょっとしたコツなのだが、$mydestinationlocalhostだけにしたほうが良い。 というのも、メールのルーティングのためにエイリアスにかなりの数のユーザー名を書くことになるが、そうすると$mydestinationに含まれるドメイン宛のメールでそれらのユーザー名で配送することができる状態になってしまい、スパムが届きやすくなる。それを回避しようとするとユーザー名が長くなって管理しづらい。

localhostだけにすることでそうした問題を回避することができる。 この場合、$mydestinationは外からのメールで直接取り扱わないので、なんなら存在しない特殊なドメインにしてもいい。 Postfixのドメイン名はSSL証明書のCNと絡んでくるが、そこに$mydestinationは関係しない。

その上で$virtual_mailbox_domainsに全部のドメインを書くことですべてvirtual(8)に回すことができる。

だが、ここで重要なこととして、virtual(8)はlocal(8)と違い、エイリアスコマンドがない。つまり、virtual(5)にはコマンドが書けないようになっている。

このルーティングは、aliases(5)に

foo: "|foocommand arg1 arg2", allbox

のように書いておいて、virtual(5)には

foo@example.com: foo

のように書けば解決できる。

なお、私のメインサーバーは時すでに遅しなaliases(5), vmailbox(5)になっているので、もっと複雑にルーティングされている。

さて、これでコマンドに渡すところまではできるようになった。コマンドがメールフィルタの機能を果たせば目的は達成できる。

だが、local(8)が起動するコマンドはプライベートマウント名前空間を持つnobody:nobodyなのでコマンドがかなり大変なことになる。

そして開発されたのがMailDeliverだ。 より汎用性のあるフィルタとして作り直されたv4である。

MailDeliverは最終的にはdovecot-ldaを用いて配送する。 だが、dovecot-ldaで配送できるようにするのは、かなり大変だ。かなり試行錯誤したため手順が残っていないが、重要なのはmatrics.conf

service stats {
  unix_listener stats-writer {
    mode = 0666
  }
}

master.conf

  unix_listener auth-userdb {
    mode = 0600
    user = mda
    group = mda
  }

(mdaは私固有の環境のユーザー, ) lda.conf

lda_mailbox_autocreate = yes

といったところだと思う。 私の環境ではサーバーである maildeliver.rbmdaユーザーで動作している。

Postfixのコマンドから渡るようにmaildeliver.rbはTCPサーバーとして動作するようになっており、maildevlier-q.rbコマンド経由でメールが渡され、フィルタしたのち最終的にはdovecot-ldaによってメールボックスへ配送される。 すべてのメールをこのフィルタ経由で保存する場合、Postfixが直接メールを保存することはないため、local(8)はただのルーターとして機能し、virtual(8)はlocal(8)に渡すだけの役割となる。 vmailbox(8)は空である可能性がある。

おまけ1: 大変だった作業

1番大変だったのは、Chienomiのアプリ移植作業だと思う。 非常に数多くのトラブルに引っかかったので、時間もかかったし苦労した。

メール関連は最近のいつものことだけど、非常に複雑かつ難解で、作業手順としても面倒で抜けも発生しやすい。 維持管理が相当大変なものになっていると感じる。

メールフィルターはPostfixのエイリアスコマンドがnobody:nobodyで動作し、なおかつ/tmp/varがプライベートマウントされている(マウント名前空間が分離されている)ということ。 このためMailDeliver4はUnixソケットからTCP/IPに変更されており、そもそも余計にコンポーネントを分離する必要も生じさせた。 MailDliver v4の開発はかなり困難を極めた。

あと、Vultrがデフォルトでメール通さないのが割と大変でもあった。

おまけ: ConoHaと私

私が活動再開してちょっとした頃に縁を持ったのが、当時サービスインして間もないConoHaだった。 どういうきっかけだったかはもう覚えてもいないが、「てっくおやじ」というイベントにお呼ばれして、これが活動再開後最初の登壇となった。

これは私の活動の幅を広げる大きな契機になったし、当時の三雲このはさんはかなり技術に詳しい方がやっていて、技術的な問い合わせをこのはさん経由でやれてかなり良かった。 営業の方や技術の方とも仲良くなり、コミュニティ支援をいただいてMimir Yokohamaの初期活動の大きな助けになった。

その後記念イベントに参加したり、2018-2022の5年間、ConoHa Advent Calendarに寄稿したりしていたが、2019年から三雲このはさんをしている方は技術の全く分からない方で、三雲このはをVTuberとして技術やサービスとは全く関係ない方向で展開していたり、アフィリエイターにすり寄ったりと、近年はおかしな方向に進んでいた。 同時に技術的に深い人たちに対しては冷たい態度を取るようになっていき、私に限らずConoHaを離れる人が増えていた。 むしろ、私はよく残ったほうだ。

決定的な軋轢を生んだのはLiteSpeedの件で、ConoHa脱出を決めたのもサポートの回答が決め手であったから、ConoHaのサポートの品質は存在価値がないほどに低い。 だが、それがConoHaというサービスの今の提供姿勢なのだろう。

ConoHa WINGで使われているソフトウェアが重大な脆弱性のあるバージョンなので更新してくれ、ということも散々言い続けたのだが、聞き入れられることはなかった。

私がConoHaと仲が良かったのは2014年から、2016、もしくは2017年あたりまでであり割と短いのだが、割とConoHaに対して影響力を持っていた――私の記事をきっかけとしてConoHaを使い始める人が結構いたという意味だ。 ConoHaのイベントに定期的に参加し、コンテンツとして発信することから、割とConoHaの宣伝になっていたのではないだろうか。

2019年にはその姿勢を疑問視してはいたが、それでもまだConoHaを推すつもりではいた。 数多くの問題を持っていたが、便利だったからだ。

私にとっては、私のひとつの時代の象徴するもののひとつだったと言っていい。 とても寂しい気持ちだし、残念だ。