OWASP ZAPのコンテナを日本語対応させる

Webアプリケーションの脆弱性検査をするOWASP ZAPというツールを日本語環境で使用するためのメモです。

GitHub Container Registryから入手できるOWASP ZAPのコンテナイメージは日本語フォントが含まれていないため、WebSwingのGUIで言語設定を日本語にすると文字化け(豆腐)してしまいます。

毎回コンテナに入って日本語フォントを追加するのが面倒になったので、Dockerfileでカスタムイメージを作りdocker composeで設定の永続化の指定を行うようにしてみました。

コンテナイメージ作成と起動

Notoフォントを追加インストールする例です。

パッケージマネージャに収録されている別のフォントや、自前でフォントを組み込むこともできます。

Dockerfile

FROM ghcr.io/zaproxy/zaproxy:stable
USER root
RUN  apt-get update && \
     apt-get -y install fonts-noto-cjk
USER zap

docker-compose.yml

version: "3.7"
services:
  zaproxy:
    image: zaproxy-ja
    build:
      context: .
    environment:
      TZ: Asia/Tokyo
    command: zap-webswing.sh
    ports:
      - 8080:8080
      - 8090:8090
    volumes:
      - ./wrk:/zap/wrk
      - ./home:/home/zap

同じディレクトリ内にDockerfiledocker-compose.ymlを置いて、下記コマンドでビルドするとzaproxy-jaというコンテナイメージが作られます。

docker compose build --pull

--pullオプションを付けておくことで、最新のイメージが存在する場合はpullしてからビルドが実行されます。

今回の例ではdocker-compose.ymlを置いたディレクトリ内でボリューム永続化をしているため、あらかじめコンテナ内のzapユーザー(UID=1000)が読み書きできる権限でディレクトリを作成しておきます。

mkdir wrk home
chown 1000:1000 wrk home

準備が完了したので、コンテナを起動します。

docker compose up

この方法で起動したときはCtrl+Cでコンテナを終了できます。

初回の設定

Webブラウザからhttp://localhost:8080/zapにアクセスすることでGUIが起動します。

初回は英語設定になっているので、言語の設定をします。

設定目的でセッションの保存は必要ないので、No. I do not want to persist this session at this moment in timeを選択してStartします。

起動直後

ToolsメニューからOptions...を開きます。

オプション画面を開く

Languageの項目を開き、Languageプルダウンから日本語を選択します。

言語設定

一旦OWASP ZAPを終了し、再度GUIを起動し直すと言語設定が反映されます。

日本語表示で起動

WSLでネットワーク不調時に試すこと

WSLで起動したディストリビューションからネットワーク接続ができなくなることが偶に発生します。

/ # apk update
fetch https://dl-cdn.alpinelinux.org/alpine/v3.19/main/x86_64/APKINDEX.tar.gz
WARNING: updating and opening https://dl-cdn.alpinelinux.org/alpine/v3.19/main: temporary error (try again later)
fetch https://dl-cdn.alpinelinux.org/alpine/v3.19/community/x86_64/APKINDEX.tar.gz
WARNING: updating and opening https://dl-cdn.alpinelinux.org/alpine/v3.19/community: temporary error (try again later)
4 unavailable, 0 stale; 15 distinct packages available

このような場合、ホストマシンのネットワークアダプターを一旦無効化し、再度有効化すると解決する場合があります。後述するresolv.confの書き換えの前にまず試してみると良いでしょう。

ホストマシンのネットワーク接続が問題なく行えていて、IPアドレス直打ちであればWSLから外のネットワークに接続できる場合、原因はおよそWSL内からDNSの名前解決ができないことによるようです。

解決策としてwsl.confにてresolv.confの自動生成を抑制するよう設定し、/etc/resolv.confnameserver指定をパブリックDNSサーバーに決め打ちで指定するという方法がよく見つかります。

しかし、この方法では自宅内ではLAN内で稼働する機器向けのDNSサーバーを参照し、他のネットワーク接続時はデフォルトのDNSサーバーを参照するという使い方がとても面倒になります。できれば本来の動作のまま使えることを期待したいのです。

今回の解決方法となるネットワークアダプターの操作は、Windows 10ではネットワーク接続画面から行います。

ホストマシンのネットワークアダプターを無効化すると、付随してvEthernet(イーサネット)vEthernet(WSL)の2つのアダプターが削除されます。この2つのアダプターはホストマシンのネットワークアダプターを有効化すると再作成されます。

ネットワーク接続

vEthernet系のアダプターの再作成により、DNS問い合わせエラーによるWSLのネットワーク不調は解決すると思います。

この方法で解決できなかった場合は、resolv.confの書き換えなどの手段を検討してください。

警告
初稿時点ではWindows 11でWSLのネットワーク不調に遭遇していないため、Windows 11で同様に問題が解決するかは確認できていません。
情報

Windows 11では設定アプリのネットワークとインターネットネットワークの詳細設定ハードウェアと接続のプロパティからvEthernet (WSL (Hyper-V firewall))という名前のネットワークアダプターが確認できますが、ネットワークの詳細設定画面からのネットワークアダプター無効化→有効化操作ではvEthernetアダプターが再作成されたようには見えませんでした。

なお、Windows 11のネットワーク接続画面では、vEthernetアダプターが表示されないようになっていました。

情報

2024/4/3追記

WSL 2.2.1からDNSトンネリング機能がデフォルトで有効になり、DNS問い合わせエラーによるネットワーク接続の不調が解消されるようです。

Microsoft、WSL 2.2.1でDNSトンネリングをデフォルトで有効に

2024/4/3時点ではMicrosoft Storeから取得可能なバージョンはWSL 2.1.5ですが、WSL 2.2.1が利用可能になればまず試すことは「wsl --updateを実行すること」になりそうです。

WSL2のAlpine LinuxでDockerを使う

以前WSL2にAlpine Linuxをインストールする手順を紹介しましたが、この環境にDockerを導入してみます。

WSL2でDockerを使用する方法については既に幾つものWebサイトで解説されていますので、後述の自動起動に関する手順など参考にさせていただきました。

情報
2023年7月頃にOpenRCによるdockerdの自動起動に失敗するようになってしまったため、本記事では暫定対応を含めた手順を紹介します。

dockerと関連パッケージ導入

docker-ceとdocker composeの他に、自動起動するためのOpenRCを導入します。

apk add openrc docker docker-cli-compose
openrc sysinit
touch /run/openrc/softlevel
rc-update add docker

一般ユーザー用設定

一般ユーザー権限でdockerを使用できるようにするためには、対象ユーザーをdockerグループに所属させる必要があります。

警告
一般ユーザーがdockerを使用できることは、コンテナを介してホストに対してroot権限を使用できてしまうことを意味します。 基本的には安易に設定しないようにしてください。
addgroup <ユーザー名> docker

自動起動失敗回避

2023年7月頃のdocker-openrcパッケージ更新によりOpenRC経由でのdockerdの起動が失敗してしまうようになりました。

これはAlpine Linuxのissueによるとdockerが生成したネットワークがnetworkingサービスの再起動時に壊れてしまうことに対応するため、dockerとnetworkingに依存関係を設定したことに起因するようです。

WSL2にAlpine Linuxのminirootfsをインポートした環境ではnetworkingサービスは使用されず、設定ファイルが存在しないためnetworkingの起動に失敗します。そのため、dockerの起動前提を満たせないことになりdockerサービスの起動に失敗してしまいます。

暫定対応として、dockerサービスの起動定義ファイル(/etc/init.d/docker)を、依存関係が追加されたときのコミットを参照して以前の状態に手動で戻します。

/etc/init.d/dockerdepend内のnetを削除します。

 depend() {
-	need sysfs cgroups net
+	need sysfs cgroups
 	after firewall
 }

これで、OpenRCからdockerが起動できるようになります。

自動起動設定

Windowsから以下のコマンドを実行することでOpenRCが起動し、OpenRCによってdockerサービスが起動します。

wsl -d Alpine -u root --exec /sbin/openrc sysinit

この方法では、タスクスケジューラーなどでWindowsログイン時に上記コマンドを実行してあげる運用が考えられます。

また、Microsoft Store版WSLではディストリビューション起動時にコマンドを自動実行する機能が追加されています。

情報
コマンド自動実行機能はWindows 11のinbox版WSLで追加された機能ですが、Store版WSL正式リリースによりWindows 10にバックポートされた形になります。

今更ながら WSL2 の Alpine で Docker 環境構築という記事に/etc/wsl.conf[boot]セクションに起動コマンドを設定する方法について書かれていました。通常はこちらの手順で自動起動するのが使い勝手が良いと思います。

HugoのRender Hooksを利用してブロックの表現を拡張する

当ブログはHugoで構築していて、Markdownを使って記述しています。テーマを簡単に作れるので、自作テーマで好みに合わせてカスタマイズできるのが気に入っています。

しかしHugoが解釈できるMarkdownで表現可能な書式には限界があります。 そのためか、Markdownの一部表記からHTMLへの変換内容を自分で定義できるRender Hooksという機能が用意されています。

Hugo v0.93.0からはcodeblockのhookが追加され、以下の4種類のhooksを定義できるようになりました。

  • image
  • link
  • heading
  • codeblock

今回はnoteという名前でcodeblockのhookを作成し、注釈を記載するためのブロックを表現できるようにします。

記述例

```note
このように左に注釈の種類を示すアイコンを、右に注釈文を表示するようにします。
```

表示例

情報
このように左に注釈の種類を示すアイコンを、右に注釈文を表示するようにします。

Render Hooksの作成

HugoのMarkdown Render Hooksマニュアルによると、layouts/_default/markup/フォルダに規則に従った名前のファイルを作れば良いようです。

自作のテーマに追加するので、テーマ側のフォルダにrender-codeblock-note.htmlを作成してみました。

アイコンはMaterial Design IconsからSVG形式のアイコンを使用させていただきました。

render-codeblock-note.html

<div class="note-block">
  {{- $type := default "info" .Attributes.type -}}
  <div class="icon">
    {{- if eq $type "info" }}
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="icon-info">
      <title>情報</title>
      <path d="M13,9H11V7H13M13,17H11V11H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" />
    </svg>
    {{- else if eq $type "warning" }}
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="icon-warning">
      <title>警告</title>
      <path d="M13 14H11V9H13M13 18H11V16H13M1 21H23L12 2L1 21Z" />
    </svg>
    {{- else if eq $type "errata" }}
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="icon-errata">
      <title>訂正</title>
      <path d="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12H20A8,8 0 0,1 12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4V2M18.78,3C18.61,3 18.43,3.07 18.3,3.2L17.08,4.41L19.58,6.91L20.8,5.7C21.06,5.44 21.06,5 20.8,4.75L19.25,3.2C19.12,3.07 18.95,3 18.78,3M16.37,5.12L9,12.5V15H11.5L18.87,7.62L16.37,5.12Z" />
    </svg>
    {{ end -}}
  </div>
  <div class="note">{{- .Inner | markdownify }}</div>
</div>

css抜粋

.note-block {
  display: table;
  margin: 0 5px;;
}

.note-block .icon {
  display: table-cell;
  vertical-align: middle;
  border-right: 1px solid gray;
  margin: 0 16px 0 0;
}

.note-block .icon svg {
  padding: 8px;
  width: 48px;
  height: 48px;
}

.note-block .icon .icon-info {
  fill: steelblue;
}

.note-block .icon .icon-warning {
  fill: goldenrod;
}

.note-block .icon .icon-errata {
  fill: dimgray;
}

.note-block .note {
  display: table-cell;
  vertical-align: middle;
  padding: 0 0 0 16px;
}

.note-block .note p {
  margin: 8px 0;
}

アイコンの使い分け

ブロックにattributeを渡すことができるので、アイコンの使い分けはtypeという名前のattribute経由で指定できるようにしてみました。

type指定を省略するとinfoとして扱うようにします。

attribute指定例

```note {type=info}
```

{type=info}表示例

情報
情報です。

{type=warning}表示例

警告
警告文です。

{type=errata}表示例

訂正
訂正文です。

作ってみての所感

ブロックの使い方として正しいのかは置いておいて、markdown側の表記が比較的シンプルに済んだので習作の割に使い勝手良い物になりました。

hook側の定義が泥臭いように感じていて、もっと良い書き方がありそうに思うのですが、まずはこのまま使ってみて良い方法を見つけたら改良したいですね。

他にも、CLIのコマンドと出力結果をもっと見やすくできないかと常々考えていたので、Render Hooksを上手く利用して理想通りの表示ができるようにしたいです。

FessでWEB+DB PRESSのPDF検索システムを構築する

オープンソース全文検索サーバー Fessが強力なので、DockerコンテナでWEB+DB PRESS総集編のPDFを検索できる環境を構築してみました。お手軽な反面、だいぶはまったので設定した内容をメモしてみます。

起動前の準備

LinuxにDocker導入済みなので、基本的な導入手順は公式ページのインストール手順の「設定」の項目以降に沿って行いました。必要なのはLinuxに対するvm.max_map_countの設定と、compose.yamlcompose-opensearch2.yamlの入手です。

Fessのバージョン14.7ではすんなり起動できましたが、後に14.8にバージョンが上がっていたので試してみたらうまくいかず。そのため14.7でしばらく運用するつもりです。

情報
composeコマンド実行する度に2つのyamlファイルを指定するのは面倒なので、compose-opensearch2.yamlからcompose.override.yamlにシンボリックリンクを張っておくとファイル名指定が省略できて楽です。

設定ファイルの取得

Fessのデフォルト設定では、10MBまでのファイルをインデックス作成対象にしています。

今回、検索対象にするPDFのファイルサイズが大きい(50〜60MB)ため、Fessでインデックスを作成できるように設定する必要があります。設定ファイルの所在が複数のディレクトリに分散しているので、コンテナイメージから変更するファイルを取得して、編集したファイルをマウントして上書きします。

また、サムネイル作成用のシェルスクリプトに不備があったため、ついでに直しておきます。

書き換えが必要な設定ファイルは次のとおりです。

  • /etc/fess/fess_config.properties
  • /usr/share/fess/app/WEB-INF/classes/crawler/contentlength.xml
  • /usr/share/fess/bin/generate-thumbnail
情報
Fess 14.11.0のコンテナイメージではgenerate-thumbnailのシェルスクリプトの不備が修正されていました。
修正済みのコンテナイメージを使用する場合はgenerate-thumbnailに関する手順は不要になりますので読み飛ばしてください。(2023/11/11)

設定ファイルを置くためのディレクトリを作成しておきます。

mkdir fsetc fscrawler fspatch

コンテナを単純に起動して、必要なファイルを取り出します。

docker run -d -it --rm --name fess ghcr.io/codelibs/fess:14.7.0
docker cp fess:/etc/fess/fess_config.properties ./fsetc/
docker cp fess:/usr/share/fess/app/WEB-INF/classes/crawler/contentlength.xml ./fscrawler/
docker cp fess:/usr/share/fess/bin/generate-thumbnail ./fspatch/
docker stop fess

fess_config.propertiesの編集

クローラーが使用するメモリの上限を増やします。今回はホストマシンの搭載メモリがが32GBあるので4GBを最大値として設定しました。

jvm.crawler.options-Xmxを編集します。

-Xmx4096m

contentlength.xmlの編集

デフォルトではクロール対象のファイルサイズは10MBまでとなっていました。また、HTML用に2.5MBの定義があるので、これをコピーしてPDF用の定義を作成します。今回は250MBまでのPDFをクロール対象に含めるようにします。

                <postConstruct name="addMaxLength">
                        <arg>"application/pdf"</arg>
                        <arg>262144000</arg><!-- 250M -->
                </postConstruct>
訂正
当初80MBまでで想定していましたが、200MB超えのPDFが含まれていたためクロール対象の設定を250MBまでに変更しました。(2023/5/17)

generate-thumbnailの編集

このファイルは設定ファイルではありません。検索結果に表示されるサムネイルを作成するスクリプトなのですが、内部で使用しているコマンドが生成するファイル名とスクリプトが想定しているファイル名が一致せず処理が失敗してしまいます。

問題の特定と解決をされていたfessでthumbnail画像が生成されない問題というページがありましたので、こちらを参照させていただき該当箇所を修正してサムネイルが作られるようにします。

pdftoppmコマンドのオプションに-l 1を指定している箇所を-singlefileに変更します。

pdftoppm -png -singlefile "${target_file}" ${tmp_png_prefix}

compose.ymlの編集

変更を加えたファイルをコンテナにマウントするための定義を追加します。

    volumes:
      - ./fsetc/fess_config.properties:/etc/fess/fess_config.properties
      - ./fscrawler/contentlength.xml:/usr/share/fess/app/WEB-INF/classes/crawler/contentlength.xml
      - ./fspatch/generate-thumbnail:/usr/share/fess/bin/generate-thumbnail
      - /srv/docs/webdbpress/:/srv/docs/webdbpress:ro

検索対象にしたいWEB+DB PRESSのDVDの内容は/srv/docs/webdbpressに格納しておいて、コンテナ内の同パスに読み取り専用でマウントすることにします。

Fess起動とクロール設定

下準備を済ませているので、以下のコマンドで起動できます。

docker compose up -d

起動には少し時間がかかります。

起動後は管理者パスワードを設定し、管理画面のメニューからクローラーファイルシステムを選択します。

新規作成からファイルクロールの設定を開いて、最低限必要な項目を設定します。

項目名
名前webdbpress
パスfile:/srv/docs/webdbpress/webdb_pdf

クロール設定後、管理画面上部のクローラー実行からDefault Crawlerのジョブ画面を開き、今すぐ開始ボタンを押せばインデックス作成が始まります。

Alpine Linuxのパッケージ管理とシステム更新

Alpine Linuxのパッケージ管理についてまとめます。

パッケージリストの更新

apk update

更新可能なパッケージの確認

apk upgrade -s

upgradeサブコマンドの-sオプション(冗長表記は--simulate)を指定することで更新可能なパッケージのインストール済みバージョンと更新後のバージョンを確認できます。

オプション名通りシミュレートなので、実際にはパッケージ更新は実行されません。

更新可能なパッケージの更新

apk upgrade

稼働中のデーモンが更新された場合は、rc-service <デーモン名> restartで再起動して更新を反映させましょう。

LinuxカーネルやmuslなどのOSの根幹になるパッケージが更新された場合は、rebootでシステム全体を再起動しましょう。

パッケージの追加

apk add <パッケージ名>

パッケージ名は複数指定可能です。

パッケージの削除

apk del <パッケージ名>

パッケージ名は複数指定可能です。

パッケージの検索

apk search <パッケージ名>

パッケージ名は複数指定可能です。

一般ユーザー権限でも実行可能です。

インストール済みパッケージの表示

apk list -I

一般ユーザー権限でも実行可能です。

Alpine Linux 3.17頃までは順不同で出力されていたような。apk list -I | sortでソートすると見やすくなります。

ディストリビューションのバージョンアップ対応

公式の手順はこちら Upgrading Alpine

パッケージリストの取得元URLは/etc/apk/repositoriesに以下のように設定されています。

https://dl-cdn.alpinelinux.org/alpine/v3.18/main
https://dl-cdn.alpinelinux.org/alpine/v3.18/community

URLにディストリビューションのバージョン番号が含まれているため、該当個所を書き換えれば新バージョンに移行できます。

また、バージョン番号の代わりにlatest-stableを指定することで常に最新のディストリビューションのパッケージを取得できるようになります。その他、edgeを指定すると開発版パッケージを取得できます。

/etc/apk/repositories書き換え後は以下のコマンドで更新、再起動を実施します。

apk update
apk upgrade --available
sync
reboot

WSL2にAlpine Linuxをインストールする

WSL2にAlpine Linuxをインストールして、一般ユーザーでログインできるように設定します。

WSL2の有効化

2022/11にMicrosoft StoreのWSLが正式版になったので、Windowsインボックス版ではなくStore版を使います。Store版ではWindows 10でもWindows 11のインボックス版以降に追加された機能が使用可能になります。

インストールは、管理者権限のコマンドプロンプトから下記コマンドで行えます。(参考: WSL を使用して Windows に Linux をインストールする)

wsl --install

Microsoftのサイトに書かれていますが、上記コマンドを実行すると既定のディストリビューションとしてUbuntuがインストールされます。Alpine Linuxだけ使えれば充分という場合はMicrosoft Storeから直接Windows Subsystem for Linuxをインストールするのが良いかもしれません。

Alpine Linuxのインストール

この手順では、Alpine LinuxのDownloadsページより入手可能なMini root filesystemのアーカイブファイルを使用します。各種CPUアーキテクチャ用のファイルが用意されていますが、WSL2での使用を目的とするならまず間違いなくx86_64を選択することになるでしょう。自分の環境に合ったアーカイブファイルをダウンロードしてください。

ダウンロードしたMini root filesystemのアーカイブファイルを次のコマンドでインポートします。

wsl --import Alpine C:\wsl\alpine alpine-minirootfs-3.18.0-x86_64.tar.gz --version 2

このコマンド例では次のような指定をしています。

  • WSLでのディストリビューション名 Alpine
  • インポート先ディレクトリ C:\wsl\alpine
  • Mini root filesystemのアーカイブファイル alpine-minirootfs-3.18.0-x86_64.tar.gz
  • 使用するWSLのバージョン 2

Alpine Linux起動

Windowsターミナルを使用している場合は、プロファイルが自動的に作成されます。

コマンドプロンプトでは次のコマンドで起動できます。

wsl -d Alpine

Alpine Linuxが起動し、画面がashに切り替わります。

既存パッケージの更新

apk update
apk upgrade

apk updateでパッケージリストを更新し、apk upgradeで更新されたパッケージをインストールします。

通常使用でも、定期的に実行するのが望ましいです。

suを使用可能にする

passwd
apk add busybox-suid

一般ユーザからrootにスイッチする場合、rootにパスワードが設定されて入る必要があります。デフォルトではrootのパスワードは設定されていないので、ここで設定しておきます。

suコマンド自体は最初からbusyboxのシンボリックリンクとして用意されていますが、busyboxにはsuidの設定がないため、一般ユーザが呼び出しても権限不足となりsuコマンドが失敗します。busybox-suidはsuidが必要になるコマンドをbusyboxに代わって提供します。

一般ユーザー作成

adduser <ユーザー名>

デフォルトユーザー設定

/etc/wsl.confを作成して、以下の内容を書き込みます。

[user]
default = <ユーザー名>

次回Alpine Linux起動時から反映されます。

サーバーソフトウェア更新 3

自宅サーバーでは、当ブログ以外にもプライベートで使用するソフトウェアをいくつか稼働させていました。それぞれの移行手段について纏めてみました。

Wordpress

当ブログ公開用に運用。ただし全然使いこなせていないしコードを載せるには標準のエディタは使いにくく、以前からMarkdownあたりで書ける別のソフトウェアに乗り換えようと考えていました。

たまたま知ったHugoが良さそうだったので、デザインをちょっと寄せたテーマを自作してWordpressから移行してみました。内容は直接移行する手段がないため、WordpressでエクスポートしたXMLを個別のファイルに分割するスクリプトを書き、手作業で調整しました。1

内容やテーマは後述のGitLabで管理することにしたので、更新もGitLab CI/CD機能を利用することにしました。

GitLab

GitLabは、かつてGitHubがフリープランでプライベートリポジトリを作成できなかった時代に個人用のリポジトリを管理するために使い始めました。 そのままGitHubとは使い分けながら使い続けています。

今まではOmnibus版をインストールしていましたが、幸い開発元によるDockerイメージが公開されている2ので、活用することにします。

データの移行については、公式ドキュメントのBack up and restore GitLabに沿って今までのサーバーでバックアップを作成、コンテナにバックアップデータを入れたディレクトリをマウントしてリストア実施でできました。

GitLabそのものの制約としてリストア先のGitLabのバージョンはバックアップ取得時点のものと一致していなければなりません。DockerHubに各バージョンがタグ付きで公開されていますので、リストアを実施するときはきちんとタグを指定してコンテナを起動するのが間違いないでしょう。

リストア完了後、タグ指定を新しいバージョンに変更するかlatestにしてしまえば、コンテナ起動時にデータのマイグレーションが実行されます。

FreshRSS

かつてはGoogle Readerを使っていて、Feedlyに流れ着くもWeb UIが合わずセルフホスティングの安心感に惹かれたのも相まってFreshRSSに落ち着きました。

私が重視しているのはデスクトップとスマートフォンで既読フラグとブックマークが共有できること、そしてスマートフォンで使用しているReederが連携できることでした。FreshRSSを知ったきっかけもReederのバージョンアップで新たな対応サービスとして追加されたことです。

こちらも開発元によるDockerイメージが公開されているので、今まで直接インストールしていた環境からデータを移行させました。と言っても設定ファイル以外の実データはデータベースの中なので実質データベースのダンプとリストアに終始することになりました。

ownCloud

Web UIでファイル管理できるし、簡単な世代バックアップも付いているしそれ以上の込み入ったことはしないのでとNextCloudがフォークされた後もそのまま使い続けていたのですが流石に限界3だったので、この機会にNextCloudに移行することにしました。

NextCloudはDockerによる公式イメージを使用しました。ownCloudからの移行も公式ページにMigration guideがあり、この文書に沿って作業すれば良いです。

ただし、私が作業した時(2023/3頃)にはマイグレーションスクリプトのownCloudバージョン判定が正しく機能せず、使用中のownCloud 10.10に対応した移行先のNextCloudバージョン選定に失敗していたため一筋縄ではいきませんでした。 現在(2023/5/5)はドキュメントが整備され、Migrating from ownCloudにownCloud 10.11.xからの移行について書かれているので、私が作業した時から状況が改善されたようです。

Mattermost

2022年9月からSlackのフリープランの内容が変更されたことから、セルフホスティングのMattermostに移行していました。

時期的には既に今回のコンテナ化を見据えていたので、最初からコンテナで稼働させています。ですのでデータの移行もコンテナにマウントしているディレクトリをコピーするだけでした。

なお、Slackからの移行についてはMattermost側でmmetlというツールが用意されているのですが、一部のデータが変換されず欠落してしまったので移行ツールを自作しました。

移行ツールはGitHubにてmmconverterという名称で公開しています。


  1. 良くも悪くも、元々の投稿数が少なくコード以外の書式設定が少なかったからできたことです。 ↩︎

  2. どうやらOmnibus版をそのままコンテナに押し込めたようで、GitLab本体とデータベースが同一のコンテナで稼働するなかなか強引な作りですが、更新頻度が高いのは安心材料です。 ↩︎

  3. 移行後に知ったのですが、ownCloud自体もownCloud Infinite Scaleとして作り直されていました。 ↩︎

サーバーソフトウェア更新 2

VMで稼働させていたサービスをコンテナに置き換えることに決定したので、次は新環境のソフトウェア選定です。

コンテナの稼働に特化したOSとなればFedora CoreOSやProxmox Virtual Environmentなどが存在しますが、今回は私が扱いに慣れているAlpine Linuxを使うことにしました。

コンテナ技術絡みでは、Alpine Linuxはコンテナイメージを軽量に作成できるベースイメージとして広まったように思います。この軽量という特徴はコンテナを動かす基盤として使用するにも都合が良いと考えられます。

なお、Alpine Linuxは軽量にするために他のディストリビューションとは標準Cライブラリや標準コマンドの非互換があり、稼働させるソフトウェアによっては相性が悪い場合があります。これはコンテナイメージのベースとして使用する際は場合によって無視できない要因ですが、コンテナを動かすだけであれば問題になることはないでしょう。

パッケージリポジトリに登録されているパッケージは充分な種類があり、パッケージのバージョンについても随時更新されているようです。何はともあれ必要になるDocker CEが(communityリポジトリではありますが)収録されているのは便利です。

もう一つOS選定に関わる要素がデバイスのサポートです。今回のソフトウェア更新は、使用中のRAIDカードがESXiの最新版でサポートされなくなってしまったことがきっかけの一つでした。問題のRAIDカードはLinuxカーネルに含まれているドライバが対応していたため特に手を加えることもなく動作しました。この件についてはLinuxベースであるCoreOSやProxmox VEでも同様に対応しているものと思います。1

また、コンテナを使いますがハードウェアは1台のみ、オーケストレーションもしないと割り切っているので、通常のLinux上で直接コンテナを実行する形態で充分と判断しています。流石に落ちたらそのまま放置という訳にもいきませんので、docker composeで死活監視を含め管理する想定です。


  1. カーネルのバージョンやビルドオプションに依存するでしょうし、各OSについて検証してはいないので正確にはわかりません。 ↩︎

サーバーソフトウェア更新 1

2月から3月にかけて自宅サーバーのソフトウェアを入れ替え、最新化しました。

もともとこの自宅サーバーは2017年4月にハードウェアを新調していました。(参考: 2017年以前のサーバー構成)

主にストレージを入れ替えながら、現在の構成はこのようなものになっています。

  • CPU:
    • Xeon E3-1240L v5
  • Memory:
    • DDR4-2666 32GB ECC
  • Boot Strage:
    • NVMe SSD 512GB
  • Data Storage:
    • RAID Controller: Adaptec RAID 6405E
    • HDD: WD Red Plus 10TB x 2 (RAID 1)

2017年にハードウェアを新調した時点では、前サーバーと同じくVMware ESXiをインストールしていました。 そのままv6.5 Update3まで更新しつつ運用していたところ2022年10月にサポートが終了し、v7.0以降にアップデートする必要が出たのですが…

使用しているRAIDカードがESXi v7.0以降に対応していない1ためアップデートを断念しました。

他にも複数の理由により、サーバーのソフトウェアを見直す時期が来たと判断しました。

  • VMを10台ほど起動していたためメモリの余裕がなく、ここ最近はやりくりに苦労していた
    • 解決のためVMからコンテナへ移行してのメモリ効率向上を計画していた
  • CentOS 7のサポート終了が近づいてきたためそろそろマイグレーションの準備をしなければならない
  • Windows Server 2012 R2のサポート終了が迫っているので、Linuxで代替する準備を始めなければならない

以前より部分的にコンテナ技術を導入・検討していたこともあり、今回はハードウェア構成はそのままに、VM上で稼働しているサービスを全てコンテナに置き換えることにしました。


  1. VMwareが公開している互換性リスト、及びRAIDカードのドライバの対応OSを確認した結果。望み薄そうだったのでダメ元でアップデートを試すことはしませんでした。 ↩︎