Linux構築チームへ渡す私が Mac 使いのまま、新規団体のサーバを Ubuntu にした話
新規団体のサーバは Linux の実機にする。ただし私は Linux が苦手で、vi に至ってはお手上げである。だから組むのはパートナー企業にお願いすることにした。渡すのは Windows で動く構築ナビ一式。仮想環境の中で通してみたら、十を超える不具合と、送る直前にもう一つが出てきた。
10年後も、どこかの役場で動いていてほしい
先に、私の立場を書いておく。
私は Mac 使いである。 Windows も使えるが、好きではない。好き嫌いの問題ではなく、やりたいことに使えるか使えないかで判断すると、圧倒的に Mac のほうでやりたいことができる、という理由が大きい。
そして Linux は、なお苦手である。 知識が乏しく、覚えているコマンドも少ない。vi に至っては全くお手上げだ。開いてしまって出られなくなる、あの状態である。
こんな人間が Linux サーバの構築をうまくやれるとは、自分でも思えない。
だから、NGW のパートナー企業にお願いすることにした。
理由ははっきりしている。10年後も、NGW がどこかの自治体で動いていてほしいからである。私一人が抱えている限り、その未来は私の寿命と体力の話になってしまう。私が触れない領域は、触れる人に渡すほうがいい。
その第一歩が、新規団体向けのサーバ構築である。
既存団体は Mac の中の Ubuntu へ、新規団体は Linux 実機へ
いまの NGW は、Mac mini の上に MAMP で構築した環境で動いている。Apache と PHP と MySQL を Mac の上に一式入れて、その上で動かしている形である。
これを UTM の仮想マシンに載せた Ubuntu へ移す。既存の団体は、この道をたどる。機体はそのまま活かして、中身を Linux に置き換える。
そして新しく入る団体は、Linux の実機で立てる。
どちらもソースは同じである。動くプログラムは一つで、載る台が三種類(MAMP・仮想マシンの Ubuntu・実機の Ubuntu)あるだけだ。ここが分かれていたら、そもそもこんな移し方はできない。
そうすると、組む人が別のネットワークに居ることになる。しかもその人たちの環境は Windows である。こちらの Mac から手を伸ばして設定してあげる、という形が使えない。
つまり、zip で送れる渡し物が要る。
「渡せるかどうか」でアプリを分けた
NGW には構築を案内するアプリが既にある。NGW構築ナビという。工程を順番に並べて、いま何をすればいいか、それはどのアプリのどのボタンかを出してくれるやつだ(前に書いた)。
これをそのまま渡せばいい、とはならなかった。
理由は二つある。
一つ。作り方が根本から違う。 Mac+仮想マシンのペアは、出来上がったイメージを複製して二台目を作る。だから「複製元を壊さない」「複製に付いてくる重複した識別子を潰す」という工程が要る。ところが実機のペアは、二台を同じ手順で一台ずつ組む。複製元が無いので重複も起きない。代わりに「載せる前の下ごしらえ」が効いてくる。
工程表を一本に混ぜると、どちらの読み手にも自分には関係の無い工程が並ぶことになる。関係の無い工程が並ぶ表は、読み飛ばす癖を作る。この表は読み飛ばされたら意味が無いので、混ぜてはいけない。
二つ。既存の構築ナビは、こちらの本番環境へ手が届く。 macOS のキーチェーン、ssh-keygen、osascript。そして開発環境の機体のアドレス。外部へ出す入れ物に、こちらの本番へ届く手段を同梱してはいけない。
そこで別のアプリにした。NGWLinux構築ナビという。Windows の exe を作る。中は純粋な Go の SSH だけで、os/exec すら使わない。相手へ届く手段は SSH 一本きりで、こちらの機体のアドレスは一つも持たない。
これはテストで縛ってある。os/exec を import したら落ちる。開発環境のアドレスを書いたら落ちる。方針を文章で書いても、半年後の自分は読まない。
母船は、仮想環境の中に居る
さて、作ったものを試さなければならない。相手と同じ形、つまり Windows の PC + Ubuntu の実機二台で通す必要がある。
そんな環境は手元に無い。
そこで全部を仮想環境の中に建てた。
- 母船(構築ナビを動かす Windows)… Mac の上の仮想マシン
- リハ機(組まれる側の Ubuntu 二台)… 同じく Mac の上の仮想マシン
面白いもので、Linux が苦手だから Linux を渡すという話をしているのに、その練習台は自分の Mac の中にある。仮想環境というのはこういうときに効く。壊しても、消してもう一度入れ直せばいい。実機だったら、私は一日目で心が折れていたと思う。
ここで最初のつまずきが出た。Ubuntu のインストーラは、ディスクの割り当てを既定のまま進めると、ルートにボリュームグループの半分しか渡さない。残り半分は未使用のまま眠っている。気づかずに進めて、後から添付ファイルが育ってきたときに詰まる。手順書に「120GiB 以上」と書いてあっても、インストーラの画面がそれより小さい数字を出してくるのだから、書いてあるだけでは足りない。
通してみたら、七つ出てきた
母船の Windows で構築ナビを立ち上げた。
真っ白な画面が出た。
見出しと脚注だけがあって、中身が何も無い。原因は共通の CSS だった。.panel というクラスは、この製品では「タブの中身」— つまり .active が付くまで隠されるもので、私はそれを画面の枠に使っていた。Mac で開発していたときは別のアプリの画面しか見ていなかったので、気づけなかった。
名前を .card に変え、共通CSSが隠すクラス名を枠に使ったら落ちるテストを足した。
次。画面は出るようになったが、何を押しても効かない。案件も、点検も、終了ボタンも。/api/* は起動ごとのトークンを要求するのに、画面がそれを送っていなかった。
タチが悪いのは、画面は普通に出ることである。ボタンを押しても静かに何も起きないだけなので、「まだ実装していないのかな」と自分で自分を納得させてしまう。ここも、トークンを送らない fetch があったら落ちるテストを足した。
そのあと、実データで五つ出た。中でも一番効いたのはこれである。
mysql -sは、値の中のタブを\tという二文字に書き換える。
私は複数の設定値を CONCAT で一行に詰めて読んでいた。区切りのタブが二文字の文字列に化けるので、行が分解できない。このアプリの要である「MySQL の二つの設定」の判定が、そこで壊れていた。
要の判定が壊れていることに、実データを通すまで気づかなかった。
点検自身が「繋がっているつもり」だった
一番きまりが悪かったのは、この一件である。
NGW は二台一組で、データベースはレプリケーションが運ぶ。だが添付ファイル・PDF・共有文書は運ばれない。これらは ngw-sync.sh というスクリプトが五分ごとに別送する。
構築ナビには「メインからクローンへ鍵で入れるか」を確かめる点検がある。緑になっていた。
なのに、同期だけが落ちていた。
理由はこうだった。点検は StrictHostKeyChecking=no を付けて試していた。相手のホスト鍵を知らなくても通る書き方である。ところが本物の ngw-sync.sh は root として、administrator の鍵で ssh する。 root の known_hosts には相手のホスト鍵が無い。だから Host key verification failed で落ちる。
点検は ✔、実際の動作は ✖。
このアプリは何のために作ったのか。「繋がっているつもり」で終わらせないためである。その当のアプリが、自分で「繋がっているつもり」をやっていた。
同じ条件で試すように直した。ついでに、工程9で root と administrator の両方に相手のホスト鍵を控えるようにした。
歯止めが、空振りしていた
もう一つ、性質の悪いものが出た。
NGW の二台は、メインが倒れたらクローンが昇格する。昇格の前に 「メインは本当に死んでいるか」を確かめる仕組みが入っている。生きている相手を残したまま昇格すると、二台が同時に書き込む状態になるからだ。
訓練で通してみたら、確認は「応答なし」と出て、すんなり昇格した。
すんなり過ぎた。
設定ファイルを見たら、確認しに行く先が雛形の既定アドレスのままだった。組んだときの設定ファイルは雛形をコピーして作る。そこに書いてある 192.168.0.10 を、誰も書き換えていなかった。
つまり存在しないアドレスに問い合わせて、「応答なし」と判定していた。メインが生きていようが死んでいようが、答えは同じである。二重書込を防ぐ歯止めが、まるごと空振りしていた。
点検の側も直した。それまでは「伏せ字が残っていないか」しか見ていなかったのを、「案件の二台以外のアドレスが設定に混ざっていないか」で見るようにした。こうすると、役割を入れ替えた後に古いアドレスが残る形も同じ網で捕まる。
同じ穴が Mac 版の構築ナビにも空いていた。そちらはもっと悪くて、複製元のアドレスが残っていると、昇格したときに既存の本番が持っているアドレスを奪いに行く形だった。こちらも同じ一般則で塞いだ。
送る直前に、団体のデータが一件見つかった
そして今日、渡す zip を固めた。
中身は、Windows の exe 三本(構築ナビ・保守コンソール・団体DB構築ツール)と、手順書と、構築パックである。パックは「NGW が動く Ubuntu を作る材料」で、プログラム一式と雛形のデータベースと運用のスクリプトが入っている。360MB ある。
このパックには、団体のデータを一件も含めてはいけない。
外部のネットワークへ送る入れ物だからだ。住民の文書も、他団体のロゴも、職員の写真も入れない。そのために、収集は「入れないものを除外する」ではなく「入れるものを列挙する」方式にしてある。除外を一つ書き忘れた瞬間に漏洩になる作りを避けたかった。
固め終わった zip を、念のため開いて中を数えた。
web/ngw/jitt/jittUploadTemp/JITIKAICHO/files/jittupdate.xlsx
ある団体の自治会マスタだった。305件。列に「自治会長名」「自宅電話番号」「携帯電話番号」がある。
原因はこうだった。添付を置く場所は、アプリの中に二十箇所ほどある。決め打ちの一覧を持つと新しい置き場が増えたときに取りこぼすので、TEMP というディレクトリの親を添付の受け口とみなすという規則で探していた。実測して決めた規則である。
ところが、取り込み画面の受け口のうち一つだけ、TEMP を持っていなかった。空だったので消えたのか、最初から無かったのかは分からない。とにかく、そこは受け口と判定されず、下にあったファイルがそのまま運ばれた。
しかも番号ディレクトリの検査でも捕まらなかった。団体ごとの保存先は数字で切られるので「数字のディレクトリの下にファイルがあったら止める」検査を入れてあったのだが、この受け口は JITIKAICHO という英字で切られていた。
直した。受け口だと分かる名前そのものを根拠にすることにした。TEMP が在るかどうかは団体の使い方しだいで変わる — つまり根拠として弱い。名前は変わらない。あわせて、梱包する前に「受け口の中身が残っていないか」を数える検査を足し、テストで固定した。
パックからはその一件だけを抜いて詰め直した。ここでもう一つ踏んだ。
macOS の tar で詰め直したら、日本語のファイル名が別の表現に書き換わった。「プ」が「フ」+濁点の二文字になる、あれである。見た目は同じで、バイト列が違う。受け取った Linux では別の名前になる。気づかずに送っていたら、原因の分からない不具合を相手に押しつけていた。名前をそのまま運ぶ方法で詰め直し、元と新しいもので中身の一覧を突き合わせて、差が一行だけであることを確かめた。
手順書は、二冊になった
最後に手順書の話をしたい。
もともと用意していたのは、工程を一行ずつのコマンドで書いたものだった。47ページある。中身は正確だ。実測して書いてある。
だが読み返して思った。これは Linux が分かる人が「中で何が起きているか」を確かめるための本であって、「どのボタンを押すか」の本ではない。渡す相手は Linux が分かる人たちだが、NGW は分からない。知らないアプリを前にして最初に要るのは、コマンドではなくどの機器で・どのツールの・どのボタンを押すかである。
そこでもう一冊書いた。24ページ。全編この形で通してある。
| どこで | 母船 |
|---|---|
| 使うもの | NGWLinux構築ナビ |
| ナビからできること | 全部 |
「どこで操作するか」を背骨にした。三台のうちどこに座るかで、できることが変わるからだ。十二工程のうち九工程は母船で片付く。実機の前に立つのは、OSを入れるときと、切り替えの訓練のときだけ。これが分かっていることが、そのまま速さになる。
コマンド版は捨てずに「詳細版(辞書)」として同梱した。画面でつまずいたときに引く。片方だけだと、操作が分からないか、原因が追えないかのどちらかになる。
AIとの協働作業での学び
今回いちばん効いたのは、「できあがったものを、開いて数える」を面倒がらなかったことである。
zip は固まった。テストは通っていた。パックは「団体データを含まない」方式で作ってある。それでも開いて数えた。そうしたら出てきた。
正直なところ、私一人だったら開かなかったと思う。360MB の tar を展開して68,419件のファイル名を眺めるのは、やる気の問題ではなく気力の問題だ。「テストが通っているのだから大丈夫だろう」と自分に言う理由なら、いくらでも見つかる。
そしてもう一つ。規則の根拠が弱いところは、遅かれ早かれ破れる。
TEMP の親を受け口とみなす規則は、実測して決めたものだった。二十箇所を数えて、確かにそうなっていた。それでも破れた。破れたのは規則が間違っていたからではなく、根拠にしたものが動くからである。ディレクトリは消える。空なら消える。名前は消えない。
似た話が今日は三つあった。点検が StrictHostKeyChecking=no で試していたこと。生存確認が雛形のアドレスを見ていたこと。受け口を TEMP の有無で探していたこと。どれも「本物と少し違う条件で確かめていた」という同じ形をしている。
少し違う条件で確かめると、緑になる。そして緑は、人を安心させる。
さて、月曜には先方の手に渡る。Linux が分かる人たちが、私の書いた手順書を読んで、どこで詰まるのか。それを聞くのが、いまは少し楽しみでもある。
私は、10年後も相変わらず vi から出られないままだが、それはそれで構わないと思っている。出られる人に渡したのだから。