ラズパイをオンプレサーバにする MongoDBと社内wiki (DevHub)

# 共有メモがほしい

ブラウザで使えるちょっとした共有やメモに使える社内Wikiとチャットが欲しい。

今は色々なサービスがあるけど調べるのも面倒なので、余っているラズパイを使って、昔使っていて気に入ってた[DevHub](https://github.com/volpe28v/DevHub)を使うことにします。
全体的に前時代的な取り組みになります◎

https://github.com/volpe28v/DevHub

最終的にこんなページ
![2023-01-20_20h57_32.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488658/d1eee74e-bde9-9fd9-c3e2-526d7e409d7c.jpeg)

* 軽量なwebサーバ
* すぐ編集できて履歴も残る共有Markdownメモ
* 通知のあるチャット
* 他のツールからAPIでもチャットに書ける
* 画像やファイルのドロップでのアップロード
* やろうと思えば自分で改造できる

古いOSSですが、10人くらいまでのゆるめの開発チームにはピッタリなのです。
あんまり大規模になると不向きですがぁ。

使う端末は`Raspberry Pi 4 Model B`です。
なにやら最近は品薄で価格高騰しているようで...
売っぱらちゃいたい気持ちを抑えつつ、会社備品なので有効活用します。

## どんなふうに作るか構想

* オンプレミス
* サーバにするラズパイは社内の壁にでもくっつける
  * 基本的に付けっぱなしで、再起動したら勝手にサーバ起動するように
  * MongoDB
  * DevHub
* クライアントは社内の数名がブラウザから
* バックアップは毎日深夜に社内のNASへ

# 構築手順

OS → MongoDB → Nodejs → DevHub → バックアップの機構
という流れ

## 入れるもの

OS含めて次の４つのインストール

* Raspberry Pi OS Lite
  * リリース: 2022-09-26 09:37
  * Debian GNU/Linux 11 (bullseye)
* MongoDB 4.4
* Nodejs (Latest)
* DevHub 2.4 (Latest) (npm "mongodb" ^3.3.2 を含む)

MongoDBのバージョンが最新ではないのは、DevHubが使用するnpmのMongoDB Driverのバージョンが古いからです。
DevHub`package.json`によれば、どうやらDriverは3.X.X

```json:package.json
 "dependencies": {
    ~~~
    "mongodb": "^3.3.2",
```

MongoDBのDriverとDBの対応表を見るに、MongoDB本体は4.4が良さそうです。
今はMongoDB 6.1まであるみたいなので、最新のものを入れないように注意。
対応表: <https://www.mongodb.com/docs/drivers/node/current/compatibility/>

ちなみに`MongoDB 4.4`の依存が、64bitかつ、`OpenSSL 1.1.1`です。
OSによってはこの`OpenSSL 1.1.1`がパッケージ提供されないことに注意です。
調べるとRpiOS LITEのLatestは、デフォルトで`OpenSSL 1.1.1`なので問題なしです。
<https://lindevs.com/get-list-of-default-packages-on-raspberry-pi-os>

## Raspberry Pi OS Lite 64bit (リリース: 2022-09-26 09:37)

OS を Raspberry Pi Imager を使ってインストール

https://www.raspberrypi.com/software/

> Raspberry Pi Imager を使うとインストールするときにGUIでwifiもSSHも設定できます
> ラズパイには電源以外触る必要がなくて楽ちん

こんなふうに設定しました。

![2023-01-18_19h57_22.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488658/20d9d29d-3340-e4c4-4ce3-2d7fe1d9af7f.jpeg)

Bonjourを使ったホスト名割り当てで、勝手に`.local`が付く。
ともかく次のコマンドで接続

```bash
ssh pi@devpi.local
# -> pi@devpi:~$
```

## MongoDB 4.4

MongoDBをインストール
このチュートリアルからの抜粋

<https://www.mongodb.com/developer/products/mongodb/mongodb-on-raspberry-pi/>

```bash
sudo apt update
sudo apt upgrade
# Install the MongoDB 4.4 GPG key:
wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -
# Add the source location for the MongoDB packages:
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list
# Download the package details for the MongoDB packages:
sudo apt-get update
# Install MongoDB:
sudo apt-get install -y mongodb-org
```

`mongod`: MongoDBのデーモンを、`systemctl`でサービスに設定

```bash
sudo systemctl daemon-reload
sudo systemctl enable mongod
```

ラズパイを再起動して、mongodが起動していることが確認できればOK

```bash
sudo systemctl status mongod
```

> ちなみに、認証をしないデフォルトで起動したMongoDB URIは`127.0.0.1:27017/?`
> 今回はURIは知らなくてもいい

## Nodejs

```bash
sudo apt update
sudo apt install -y nodejs npm
```

## DevHub

### インストール

```bash
wget https://github.com/volpe28v/DevHub/archive/refs/heads/master.zip
unzip master.zip
rm master.zip
cd DevHub-master
npm install
```

次のコマンドで起動

```bash
node app.js -d devhub_db -t "Deep Insight"
```

<http://devpi:3000>
アクセスして動いていることを確認
書き込み/写真のアップロードなどできればOK

### デーモン化

mongodのようにデーモン化するため、`forever`を使う

```bash
npm install forever
# デーモン化するコマンド
forever start app.js -d devhub_db -t DeepInsight
# 確認
forever list
```

ラズパイ起動時に立ち上がるように`crontab`に追記（フルパスで書く）

```:crontab -e
@reboot /usr/local/bin/forever start /home/pi/DevHub-master/app.js -d devhub_db -t DeepInsight
```

ラズパイを再起動後、<http://devpi:3000>にアクセス出来ればOK

## バックアップ機構

今回は社内にSAMBAのNASがあり、これにバックアップする

### NASをマウント

NAS:`//STRAGE.local/share/DevPi/backupdir`を、`~/backupdir_mount`をマウントする
sudoはしたくないので、工夫が必要

「起動時には`root`でマウントしていて、バックアップのときは`pi`で明示的にマウント」という形にする

```bash:ツールとマウントポイント
sudo apt install -y cifs-utils
mkdir backupdir_mount
```

まず`/etc/fstab`にマウント設定記述

```bash:/etc/fstab
# 追記
//STRAGE.local/share/DevPi/backupdir /home/pi/backupdir_mount cifs username=<USER>,password=<PASS>,users,vers=1.0 0 0
```

* `users`: 全てのユーザにマウント/アンマウントを許可
* `vers=1.0`はNASのcifsバージョンに従う

https://askubuntu.com/questions/1100114/mount-share-cifs-folder-without-sudo

https://qiita.com/devzooiiooz/items/2a0f8d748709b18a0901


これで、任意のユーザ、任意のタイミングで `mount backupdir_mount/umount backupdir_mount`できる。
次のように確認できればOK

* ラズパイ再起動時には、所有者`root`でマウントされていること

  ```shell-session
  pi@devpi:~ $ ls -l
  total 4
  drwxr-xr-x  2 root root    0 Jan 19 23:33 backupdir_mount
  drwxr-xr-x 10 pi   pi   4096 Jan 19 19:20 DevHub-master
  ```

* ユーザ`pi`でもマウントできること

  ```shell-session
  pi@devpi:~ $ mount backupdir_mount/
  pi@devpi:~ $ ls -l
  total 4
  drwxr-xr-x  2 pi pi    0 Jan 19 23:33 backupdir_mount
  drwxr-xr-x 10 pi pi 4096 Jan 19 19:20 DevHub-master
  ```

* マウントした後、[unmount](https://unix.stackexchange.com/questions/9832/why-is-umount-not-spelled-unmount)すると、所有者が`root`にもどること

  ```shell-session
  pi@devpi:~ $ ls -l
  total 4
  drwxr-xr-x  2 root root    0 Jan 19 23:33 backupdir_mount
  drwxr-xr-x 10 pi   pi   4096 Jan 19 19:20 DevHub-master
  ```

バックアップのときはユーザ`pi`で明示的にmountすることにする。

### MongoDB バックアップの仕方

`mongodump`コマンド

```bash
mongodump --db devhub_db
# devhub_db/ が生成される
```

### DevHubの画像/アップロードファイル バックアップの仕方

ユーザのアイコンや画像、アップロードされたファイルは、`DevHub-master/static/uploads`に保存される
これをディレクトリごと圧縮

```bash
# 圧縮
tar acvf uploads.tar.gz -C ~/DevHub-master/static uploads
# uploads.tar.gz が生成される
```

### バックアップを世代管理

毎朝4時にバックアップして、7日分取っておきたい。
一回分のバックアップは、`20230119`のような日付名ディレクトリを作って保存していく。
保存先は、マウントしたディレクトリ。

スクリプトを作り

```bash:run-backup.sh
#!/bin/bash
cd /home/pi

# NASをユーザでマウント
mount backupdir_mount
pushd backupdir_mount

# 今回のバックアップディレクトリの名前
TODAY=`/bin/date '+%Y%m%d'`

# バックアップ
mongodump --db devhub_db --out ${TODAY}
tar acvf ${TODAY}/uploads.tar.gz -C ../DevHub-master/static uploads

# 古いバックアップを削除
NOKOSU_NUM=7
IFS=$'\n'
for dir in $(ls -t1 | tail -n +$(($NOKOSU_NUM+1))); do
    rm -fr ${dir}
done

# アンマウント
popd
umount backupdir_mount
```

実行権限を与え、これを`crontab`に設定（フルパスで書く）

```:crontab -e
0 4 * * * /home/pi/run-backup.sh
```

# 完成

かんたんグループウェアを設置できました◎

# 復旧手順

仮にある日ラズパイが壊れてしまったときの復旧方法

## 1. 環境再構築

新しいラズパイでこのドキュメントに従って再構築

## 2. MongoDBリストア

チャットとwikiはDBなので、Mongoのダンプファイルを使って`mongorestore`コマンド

```bash
# DB`devhub_d`に何か入っていれば、先にdropしておく必要がある
mongorestore --db devhub_db <dumpしたdevhub_db>
```

## 3. アップロードデータ

DevHubにドロップでアップロードされたファイルは、普通に元あった場所に展開

```bash
# 展開
tar axvf <バックアップしたuploads.tar.gz> -C ~/DevHub-master/static
```