個人メモ用にQNAP NASでWiki.jsとdockerを使ってオンラインメモページを作る。

# はじめに
システムエンジニアをやっている仕事柄、調べ物をする機会も多いため、気になったことや後で調べておきたいことなどはToDoリストに書き溜めたりしています。

しっかりとまとめたい場合は、最近は`Qiita`で記事化して投稿してしまっていますが、`Qiita`で書くほどでも無かったり、個人的なもので公開できないようなものだと、メモ帳で雑に書き連ねることが多かったです。

ただ、デフォルトのメモ帳だとあまりテンションが上がる見た目でもなく、適当なファイル名で雑多に置かれているのも精神衛生上よろしくないので、いろいろな端末から見られたり、いい感じに編集したりできるオンラインメモページを作ろうと思ったので、やった結果を紹介したいと思います。

# 今回の要件整理
メモとはいえ、ToDoリストのような１行、２行のメモというよりはもう少し内容をまとめたメモとして使いたいと思うので、その前提で要件まとめました。

- 外で作業することが多いのでどこからでもアクセスできるようにしたい
- オンラインメモページとはいえ個人メモだから全体公開するようなことはしたくない
- 個人のみで使用できるクラウドサービスなども色々あると思うが、今回は使いたくない
- メモとはいえ見栄えが良いほうがテンションが上がるので単純なメモ帳的なものは嫌
- 簡単に見栄えが良い感じになってQiitaで慣れている`Markdown`で編集できるのがいいな
- たまに図とかフローとか書くこともあるので`Draw.io`や`PlantUML`など使えると嬉しい

メモと言いつつまとめてみたら結構贅沢な要件になりました（笑）

ドキュメントページを作成する目的のアプリケーションで調べてみると、`Sphinx`や`MKDocs`が出てきましたが、いわゆる静的サイトジェネレータとなり、`GitHub Pages`でも使われる`Jekyll`と同様、サイト生成にビルドが必要だそうです。

メモを取るだけで、いちいちビルドするのも手間なので、できれば`Wiki`のようにサイト上から編集できればと思い、調べてみると`Wiki.js`が`Markdown`形式でサイト上から編集でき、`Draw.io`なども使えそうなので、`Wiki.js`を導入してみます。

# 構成
要件の通り、外部公開はしたくないので、常時稼働している自宅のNASを使います。

自宅のNASは、元々`WireGuard`を使った`VPN`も行っているため、外から安全にアクセスする環境は整っており、また、NAS上で`Docker`を動かすことができるので`Docker`で作ろうと思います。

`WireGuard`については以前まとめたので、気になる方は以下を見てください。

- [WireGuardでVPN接続する。](https://qiita.com/sakai00kou/items/61c9c467ee8906ffd477)

# Dockerの起動
`QNAP NAS`で`Docker`を起動するための事前準備と、`docker-compose.yml`など必要な設定ファイルを作成して`Docker`を動かしていきます。

- [Dockerネットワーク設定](#dockerネットワーク設定)
- [docker-compose.ymlの作成](#docker-composeymlの作成)
- [config.ymlの作成](#configymlの作成)
- [Dockerの起動](#dockerの起動)

## Dockerネットワーク設定
通常、あまり考えずにdockerのネットワーク設定を行う場合、ホスト側（今回の場合NAS側）からポートフォワードする方法になりますが、できれば`http://xxxxx.local`のように末尾にポート番号を付与しない形でアクセスしたいのと、ホスト側のアドレスからは分けたいという思いもあり、ホスト側のポートをブリッジする方式で設定を行います。

`QNAP NAS`の「**ネットワークと仮想スイッチ**」よりブリッジ用の仮想スイッチを作成して、後の手順で作成するコンテナを紐づけました。
※今回関係ないコンテナも表示されております。

![Monosnap_20240421_131341.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/34ff54d6-a551-9446-f16c-8508337e9edd.png)

ホスト側と同じネットワークに繋がる仮想スイッチを作成後、ホスト側で`docker network ls`を実行すると以下のように表示されます。

```bash:docker network ls結果
$ docker network ls
NETWORK ID     NAME                      DRIVER    SCOPE
b7fd8a7fd9a6   bridge                    bridge    local
172cc8f12d59   host                      host      local
3e1cc3fb4df2   none                      null      local
b62342c908aa   qnet-static-eth0-fab139   qnet      local
```

私の環境では`qnet-static-eth0-fab139`が外部と繋がるネットワークになるため、名前を控えておきます。

## docker-compose.ymlの作成
[Wiki.jsのドキュメント](https://docs.requarks.io/install/docker)に記載されている`Docker`定義を参考に作成した`docker-compose.yml`は以下となります。

ネットワークは先程控えた名前を指定して、外部の任意のアドレスを付与、DBは最新版でも動いたので、バージョンを`Wiki.js`のドキュメントに記載されているバージョンより少し上げています。

また、次手順で作成する`config.yml`は、あらかじめ作成しておき、ホスト（NAS）側の「`/share/Container/Docker/wikijs/`」に格納して起動時にホスト側から共有するようにします。

```yml:docker-compose.yml
version: "3"

services:
  wikijs:
    image: ghcr.io/requarks/wiki:2
    container_name: wikijs
    hostname: wikijs
    restart: unless-stopped
    depends_on:
      - wikijs-db
    environment:
      DB_TYPE: postgres
      DB_HOST: wikijs-db
      DB_PORT: 5432
      DB_USER: wikijs
      DB_PASS: wikijsrocks
      DB_NAME: wiki
    networks:
      qnet-static-eth0-fab139:
        ipv4_address: 192.168.0.101
    ports:
      - "80:80"
    cap_add:
      - NET_ADMIN
    volumes:
      - /share/Container/Docker/wikijs/config.yml:/wiki/config.yml
      - wiki-data:/wiki/data/content

  wikijs-db:
    image: postgres:16.2
    container_name: wikijs-db
    hostname: wikijs-db
    restart: unless-stopped
    environment:
      POSTGRES_DB: wiki
      POSTGRES_PASSWORD: wikijsrocks
      POSTGRES_USER: wikijs
    logging:
      driver: "none"
    networks:
      qnet-static-eth0-fab139:
        ipv4_address: 192.168.0.102
    cap_add:
      - NET_ADMIN
    volumes:
      - db-data:/var/lib/postgresql/data

networks:
  qnet-static-eth0-fab139:
    external: true
    ipam:
      config:
        - subnet: 192.168.0.0/24

volumes:
  db-data:
  wiki-data:
```

## config.ymlの作成
デフォルトだと`Wiki.js`は3000番ポートで待ち受ける設定となりますが、80番ポートで待ち受けたかったので以下のようにコンフィグファイルを作成しました。

```yml:config.yml
port: 80
bindIP: 0.0.0.0
db:
  type: $(DB_TYPE)
  host: '$(DB_HOST)'
  port: $(DB_PORT)
  user: '$(DB_USER)'
  pass: '$(DB_PASS)'
  db: $(DB_NAME)
  storage: $(DB_FILEPATH)
  ssl: $(DB_SSL)
ssl:
  enabled: $(SSL_ACTIVE)
  port: 3443
  provider: letsencrypt
  domain: $(LETSENCRYPT_DOMAIN)
  subscriberEmail: $(LETSENCRYPT_EMAIL)
logLevel: $(LOG_LEVEL:info)
logFormat: $(LOG_FORMAT:default)
ha: $(HA_ACTIVE)
```

## Dockerの起動
作成した`docker-compose.yml`を`QNAP NAS`の「**Container Station**」で起動します。

「**Container Station**」の「**アプリケーション**」から`docker-compose`形式のコンテナを起動できるので、「**作成**」ボタンから進め、適当なアプリケーション名を入力して、先程作成した`docker-compose.yml`の中身をコピペして、「**検証**」に成功したら「**作成**」で作成します。

![Monosnap_20240421_133940.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/85fb6b5c-6547-d1fd-a7f9-1be1b25da488.png)

# Wiki.jsへのアクセス
コンテナが正常に起動したら、先程`docker-compose.yml`に記載した`Wiki.js`のアドレスに`http`でアクセスします。

先程の設定と同じなら「`http://192.168.0.101`」でアクセスできるはずです。

アクセスすると、以下のように初回の管理者ユーザ作成画面となるため、メールアドレスやパスワードを登録。

![Monosnap_20240421_134753.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/7e239a87-434c-230d-263b-49c7c6e0d8b4.png)

インストール後、先程作成した管理者ユーザの情報を入力してログイン。

![Monosnap_20240421_134902.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/b51bbe60-ff88-834c-ad5b-c669b469c9d7.png)

ログインできれば以下のような画面が表示されるため、管理者以外のユーザを作成したり、日本語化等行いたい場合は「**ADMINISTRATION**」、ページを作成したい場合は「**CREATE HOME PAGE**」で作成します。

![Monosnap_20240421_135317.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/1e077070-52cb-6e67-71b4-644f96b8a5a9.png)

## Wiki.jsの日本語化
ページ作成する際にも影響するため、先に日本語化を行っておきます。

「**ADMINISTRATION**」の「**Locale**」の「**Download Locale**」から日本語を見つけてダウンロードボタンを選択。

ダウンロードすると、「**Locale Settings**」から日本語が選択できるようになるため、日本語を選択して、「**APPLY**」を選択すれば完了です。

![Monosnap_20240421_135932.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/247267bb-4379-1c14-0489-746f35aa4ebc.png)

# Wikiページの作成
先程のトップページに戻ると、日本語化したため、「**CREATE HOME PAGE**」が「**ホームページの作成**」に変わっていると思います。

「**ホームページの作成**」から進むと、ページ作成する際の方法がいくつか表示されますが、私は`Markdown`形式で作成したいため、「**Markdown**」を選択します。

最初にページのプロパティの設定を行う必要があるため、タイトル等の情報を入力します。

![Monosnap_20240421_142016.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/224a226e-c7c9-19b2-18c2-edd7cad84559.png)

各項目ごとの概要については以下となります。

|項目|説明|
|:--|:--|
|タイトル|Wiki.jsの左ペインに表示されるタイトル名|
|簡単な説明|記載するとコメントが表示される|
|言語|多言語対応したい場合に作成する言語を選択|
|パス|バックアップ等行った際のファイルパス|
|タグ|任意のタグを付与<br>`tag_test`のように入力してエンターを選択すると上記の画面のように登録されます|

ページ作成後の画面となりますが、各プロパティ部分は以下のように紐づけられます。

![Monosnap_20240421_142656.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/11b045b1-65c1-4bdc-4f28-c71809daa1af.png)

「**パス**」については「`/`」で区切って記載するだけでディレクトリを含んだパス表示となり、特にディレクトリを先に作っておいたりする必要はありません。

:::note info
実際にはDB上に記録されるだけなので、どこかにディレクトリが作成されるということはありませんが、Wiki.jsの画面上では、ディレクトリ構造でページが表示されるため、ディレクトリを分けたほうが管理しやすいと思います。
:::

また、バックアップする際には「**パス**」に記載したファイル・ディレクトリ形式で出力され、最後に拡張子が付与される書式となるため、例えば上記の例でバックアップした際には「`/directory/Markdownテストページ.md`」といったパスでバックアップされます。

# Wiki.jsのMarkdownで表示できる色々な機能
`Markdown`を扱うことができる`Visual Studio Code`や`GitHub`、また、`Qiita`で記事を書く際もそうですが、最近の`Markdown`エディタは単純に`Markdown`形式の文章を書くだけではなく、図を挿入したり`Mermaid`や`PlantUML`の形式でフローやシーケンス図を作成することができたりするものが増えています。

`Wiki.js`も、少なくとも私が欲しいと思っている機能は大体揃っており、書き慣れた`Visual Studio Code`や`Qiita`で`Markdown`を編集したときと同じく、プレビュー表示しながら記事を作成できるという点で、私には最適なメモ環境と感じています。

以下で`Wiki.js`の`Markdown`で表示できる色々な機能について紹介していこうと思います。

## Markdown作成画面
以下はこの記事の冒頭部分を`Wiki.js`の`Markdown`で表示させた場合の例となります。

![Monosnap_20240421_150733.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/48d50541-904b-a49e-9f23-48d49b487d2b.png)

最近の`Markdown`エディタだと当たり前となる、プレビューしながらの編集が可能で、編集している場所に自動スクロールする機能もあり、太文字にしたり取り消し線を付与したりする基本的な操作は上と左のバーにまとまっているため、`Markdown`の書式に不慣れな方でも直感的に操作ができるかと思います。

また、シンタックスハイライトにより`Markdown`の書式で表している部分が分かりやすくなっており、地味なところでは左の編集画面上でも見出しサイズが変わる点は私的に高評価です。

## 図の作成
`Wiki.js`では、既に手元にある図を挿入するだけではなく、編集画面上から`Draw.io`を開き、`Draw.io`で作成した図をそのまま貼り付けることができるようになっています。

左バーの以下ボタンを選択すると作図を行う`Draw.io`の画面が開きます。

![Monosnap_20240421_153115.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/b8117f53-755b-43b3-7e18-0709c1f3c4ff.png)

`Draw.io`で適当な図を作成し、「**保存して閉じる**」で閉じます。

![Monosnap_20240421_153704.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/e450551e-44c0-fd15-d2c3-3dc2dfc9e034.png)

保存して閉じると元の編集画面に戻り、以下のように先ほど`Draw.io`で作成した図がそのまま表示されます。

図は`base64`形式で`Markdown`にそのまま挿入される方式となりますが、編集画面上では以下のように隠されているので、長いコード部分をスクロールしなくて済むのはありがたいですね。

![Monosnap_20240421_153834.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/885a9574-d156-fcd4-e610-27e902baedac.png)

ちなみに生のコードを見たい場合は「**<->**」部分を選択して広げると見ることができます。

## Mermaid図の表示
`GitHub`でも`Mermaid`形式の図が表示できるようになって久しいですが、`Wiki.js`でも`Markdown`ファイル中で以下のように記載することで`Mermaid`形式の図を作成することができます。

~~~md:Mermaid形式の図の記載方法
```mermaid
※内容
```
~~~

`Mermaid`の公式ドキュメントに記載されているサンプルのシーケンス図を表示させた場合は以下のようになります。

![Monosnap_20240421_162924.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/2a072451-3e83-62ec-a4f0-4ac6276b90a3.png)

## PlantUML図の表示
`Mermaid`と同じくフロー等の作成ができる`PlantUML`も以下のように記載することで`PlantUML`形式の図を作成することができます。

~~~md:PlantUML形式の図の記載方法
```plantuml
※内容
```
~~~

こちらも`PlantUML`の公式ドキュメントに記載されているサンプルのシーケンス図を表示させた場合は以下のようになります。

![Monosnap_20240421_163510.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/418e75ba-beb0-ed59-8cd3-022bfbb78c40.png)

`PlantUML`については特に凝ったことをしなければこれで問題ないですが、以前以下の記事で紹介したような構成図を作ったりする場合は、`Wiki.js`に導入されている`PlantUML`のバージョンが古いからか、私の場合エラーとなってしまうことがありました。

- [PlantUMLでできるだけきれいなAWS構成図を描く方法](https://qiita.com/sakai00kou/items/18e389fc85a8af59d9e0)

そのため、私は`PlantUML`のサービスを別で作成し、描画する際には作成した`PlantUML`のサービスを見るようにすることで、上記のような凝った構成図を表示させるようにしております。

以下で`PlantUML`を別で導入する方法を紹介します。

### PlantUMLのサービスを別で用意する方法
`Wiki.js`のコードを追ってみると`PlantUML`の描画は、以下のサイトで生成・描画した結果を表示しているようです。

- https://plantuml.requarks.io

オンラインページで生成していることからパフォーマンスも出にくいという点と、おそらく上記ページで使われている`PlantUML`自体のエンジンバージョンも古いと思われるため、今回は`Wiki.js`と同じく`QNAP NAS`上に`Docker`で作成します。

先ほどと同様、以下のように`docker-compose.yml`を作成し、`QNAP NAS`の「**Container Station**」で起動しました。

```yml:docker-compose.yml
version: '3.3'

services:
  plantuml:
    image: plantuml/plantuml-server:jetty
    container_name: plantuml
    hostname: plantuml
    environment:
      BASE_URL: plantuml
    networks:
      qnet-static-eth0-fab139:
        ipv4_address: 192.168.0.103
    ports:
      - 8080:8080
    cap_add:
      - NET_ADMIN

networks:
  qnet-static-eth0-fab139:
    external: true
    ipam:
      config:
        - subnet: 192.168.0.0/24
```

作成後、`Wiki.js`の管理画面から「**レンダリング**」→「**markdown**」の「**PlantUML**」から「**PlantUML Server**」を、新たに構築した`PlantUML`のURL（上記`docker-compose.yml`で作成した場合、`http://192.168.0.103:8080/plantuml`）を指定して「**適用**」を選択します。

![Monosnap_20240421_171556.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569912/9930bdef-3f18-fd4f-7f1d-096218357c83.png)

# おわりに
今回は、最近使ってみて個人的にアウトプットが捗っている`Wiki.js`について、構築したやり方を含めて紹介しました。

私は複数PCからアクセスしたかったため`QNAP NAS`上に構築しましたが、`Docker`で簡単に作成できるので、私のように複数PCからアクセスするようなことがなければ、自分のPC上に`Docker`で動かしてメモ帳代わりに使うのも良いかなと思います。

また、その場合は自分のPC上やGit上にバックアップするように設定しておくと、`Markdown`ファイルそのままの形式で残しておけるので他に移行する場合でも便利です。

`Docker`で簡単に自分専用の高機能なメモ環境を作ることができるので、あちこちにメモが散らばっていて、あとから探すのに苦労している方や、図やフローもメモ帳に残しておきたいけど、デフォルトのメモ帳やエディタでは書けないから困っていた方は、使ってみるとアウトプットの効率が劇的に上がるかと思うので、一度試してみると離れられなくなるかもしれません。