ZoneMinderを導入した話(2022/11)

# 1.前置き
初Qiitaちゃんどぅえす
実家の治安がなかなかにヤバいということで中華IPカメラを打ちまくりました。
監視カメラの本体側で映像を記録させてるとドラレコみたいにいつの間にかSDカードが釈迦ってたりしそうだし、
再生も面倒なので、集約できる鯖を立てることを画策。
ZoneMinderなるものを見つけて導入することにしましたです。結構前からあるみたいですね

ZoneMinderの導入方法を備忘として記録
あんまり情報が出回ってなくいろいろ苦労しました…

有志の方が日本語パッチを公開されているようですが、今回の手順では英語のままいきます。

# 2.環境

## 2-1.ネットワーク構成
![hoeg.drawio (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985190/baa7d2f5-a58d-fb82-66d6-cf237096df2c.png)
雑な構成図ですがこんな感じ
既存のNWに加え、新たにIPカメラ用のネットワークを組みました
本当はサーバーにNICを追加してもよかったのですが、Linuxで後付けNICってあんまりいい話を聞かないので
VLANを切ってネットワークを重畳してます
ZoneMinderの公開は既存NWで行い、映像の収集はカメラ用のNWで行います
各カメラには図内のL3SWから**DHCPを降らせて固定割り当て**してます。
（この辺で色々やっかいなことになったのです）

## 2-2.サーバー
サーバースペックはこんな感じ
- CPU:Core i5-2500K
- MEM:16GB
- SSD:120GB
- HDD:4TB x2 RAID1
- OS:UbuntuServer 22.04 LTS
- ZoneMinder 1.36

約10年前に自作したマシンを引っ張り出してきました。
無駄にRAID1組んで記録用ディスクにしています。

## 2-3.カメラ
カメラは以下2機種を使用しました。

ieGeek IG20
![SnapCrab_NoName_2022-11-24_10-10-30_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985190/dd5cf3ee-9800-67e2-6635-63e28947c3d0.png)

https://www.amazon.co.jp/dp/B092VJF7NT

　
TP-Link Tapo C100
![SnapCrab_NoName_2022-11-24_10-10-53_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985190/bc5e9771-40bd-92d7-a40f-a5e784b0b5b2.png)

https://www.amazon.co.jp/dp/B085LFQ9BN

ONVIFに対応しているカメラであれば、別に機種にこだわる必要はないと思います。

IG20は屋外用に4台、C100は屋内用に3台用意しました。

IG20については専用ソフトで設定するように説明書に記載がありましたが、
IPアドレスをブラウザで叩くと設定画面が出てきたのでそこから初期設定を済ませました。

C100についてはスマホの専用アプリでないと無線LAN設定ができないようでしたので、おとなしくそれに従いました。
（こやつはどうも外部とずっと通信してるみたいでちょっと嫌な感じ）

# 3.サーバーの初期設定
OSのインストール手順については特にここでは書かないですが、普通にインストール。
SSHを有効にしてコピペできる環境から接続することをおススメします。
インストール後、最低限タイムゾーンの変更はやっておきました。
```shell-session
$ sudo timedatectl set-timezone Asia/Tokyo
```

VLANを組むのはここを参考にしました。(Netplan最高)

https://kapibara-sos.net/archives/830

RAIDを組むのはここを参考にしました。

https://www.server-world.info/query?os=Ubuntu_22.04&p=raid1

:::note warn
UFWはZoneMinderのカメラ追加が終わるまで無効にしておくことをおススメします。
ONVIFカメラの検出ができなくなる可能性があります。
:::

# 4.ZoneMinderのインストール
ここが本当に鬼門でした。有志の方の日本語で書かれているドキュメントをいろいろ見ながらやりましたが、どうもサービスが起動しない。
どの手順も、やれ関連パッケージを全部打ち込んで手動インストールだ（？）、やれSQLのユーザー変更だ、
いろいろ味付けが濃いめでどうも自分の環境には合わなかったでした。

で、最終的に以下のサイトを参考にインストールして動かすことができました。

https://www.how2shout.com/linux/how-to-install-zoneminder-on-ubuntu-22-04-20-04-lts/

ほぼ素の状態で入っていますので、「SQLの設定がそのままじゃないか！」等セキュリティを気にされる方はお気を付けください。
ネットのセキュリティも大事ですが今はご近所のセキュリティの方が相当ヤバいので、まずは動かすことを主眼に置きます。

## 4-1.いつものおまじない
```shell-session:いつもの
$ sudo apt update
$ sudo apt upgrade
```
Ubuntu 22.04でこれを叩くと"Which services should be restarted?"と聞かれることがありますが、普通にOKで良いです。
必要なデーモンは勝手に再起動してくれい…

## 4-2.LAMP環境のインストール(Apache,MySQL,PHP)
```shell-session:いんすこ
$ sudo apt install apache2 mysql-server php
```
```shell-session:サービス有効化
$ sudo systemctl enable --now apache2 mysql
```
```shell-session:サービス状態確認
$ sudo systemctl status apache2 mysql

# 私の環境だとこんな感じで出ました。ちゃんと走ってますネ
● apache2.service - The Apache HTTP Server
     Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2022-11-23 13:29:49 UTC; 33s ago
       Docs: https://httpd.apache.org/docs/2.4/
   Main PID: 22489 (apache2)
      Tasks: 6 (limit: 1029)
     Memory: 16.7M
        CPU: 43ms
     CGroup: /system.slice/apache2.service
             tq22489 /usr/sbin/apache2 -k start
             tq22492 /usr/sbin/apache2 -k start
             tq22493 /usr/sbin/apache2 -k start
             tq22494 /usr/sbin/apache2 -k start
             tq22495 /usr/sbin/apache2 -k start
             mq22496 /usr/sbin/apache2 -k start

Nov 23 13:29:49 hogehoge systemd[1]: Starting The Apache HTTP Server...
Nov 23 13:29:49 hogehoge apachectl[22488]: AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 1>
Nov 23 13:29:49 hogehoge systemd[1]: Started The Apache HTTP Server.

● mysql.service - MySQL Community Server
     Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2022-11-23 13:29:44 UTC; 38s ago
   Main PID: 21283 (mysqld)
     Status: "Server is operational"
      Tasks: 39 (limit: 1029)
     Memory: 356.0M
        CPU: 988ms
     CGroup: /system.slice/mysql.service
             mq21283 /usr/sbin/mysqld

Nov 23 13:29:44 hogehoge systemd[1]: Starting MySQL Community Server...
Nov 23 13:29:44 hogehoge systemd[1]: Started MySQL Community Server.
```

## 4-3.ZoneMinderのPPAの追加
Ubuntu公式のリポジトリにはZoneMinderが公開されていないので
最新版のZoneMinderのPPAを追加します。
```shell-session:リポジトリ追加
$ sudo add-apt-repository ppa:iconnor/zoneminder-1.36
```
2022/11現在の最新バージョンは1.36です。
最新バージョンが分からない場合は下記サイトで確認しましょう。

https://launchpad.net/~iconnor

リポジトリが追加出来たらもう一度おまじないを打っておきましょう。
```shell-session:いつもの
$ sudo apt update
$ sudo apt upgrade
```

## 4-4.真打インストール
ZoneMinderをインストールします。
```shell-session:ZoneMinderインストール
$ sudo apt install zoneminder
```
依存パッケージも含めると結構な数になります。コーヒーでも飲みながら待ちましょう。

## 4-5.SQL設定ファイルを編集
ZoneMinderをインストールできたら、SQL設定ファイルを上書きし、設定を加えます。
```shell-session:設定ファイル上書き
$ sudo rm /etc/mysql/my.cnf
$ sudo cp /etc/mysql/mysql.conf.d/mysqld.cnf /etc/mysql/my.cnf
```
上書きしたファイルを適当なエディタで開きます
```shell-session:ファイルを開く
$ sudo vim /etc/mysql/my.cnf
```
ファイルの最終行に以下を加えます
```
sql_mode = NO_ENGINE_SUBSTITUTION
```
エディタを使わないならこんなのもアリですね
```shell-session
$ echo "sql_mode = NO_ENGINE_SUBSTITUTION" | sudo tee -a /etc/mysql/my.cnf
```

## 4-6.Apache設定変更
Apacheに関連するファイルのパーミッション設定をします。
```shell-session:権限変更
$ sudo chmod 740 /etc/zm/zm.conf
$ sudo chown root:www-data /etc/zm/zm.conf
$ sudo chown -R www-data:www-data /usr/share/zoneminder/
```
Apacheのモジュールを有効化します。
```shell-session:モジュール有効化
$ sudo a2enmod cgi rewrite expires headers
```
ZoneMinderのコンフィグファイルを適用します。
```shell-session:コンフィグ適用
$ sudo a2enconf zoneminder
```
PHPの設定ファイルを開きタイムゾーンを変更します。
```shell-session:php設定ファイルを開く
$ sudo vim /etc/php/8.1/apahce2/php.ini
```
8.1の部分はバージョンになります。違う可能性もありますので現状に合わせて変更してください。(Tab補完がおススメ)

タイムゾーンの設定行、私の場合はほぼ真ん中、968行目にありました。
コメントアウトを解除しタイムゾーンをAsia/Tokyoに変更します。
（もちろん置換でやっても良きかと）
![SnapCrab_19216825544 - zm@hogehoge ~ VT_2022-11-23_22-54-13_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985190/62680dce-5cc3-f6ab-072f-e602c44f3fc3.png)

## 4-7.ZoneMinder起動
いよいよZoneMinderのサービスを立ち上げます
```shell-session:ZoneMinder起動
$ sudo systemctl enable zoneminder
$ sudo systemctl start zoneminder
```
```shell-session:ZoneMinder起動確認
$ sudo systemctl status zoneminder

# 私の環境だとこんな感じで出ました。ちゃんと走ってますネ
● zoneminder.service - ZoneMinder CCTV recording and surveillance system
     Loaded: loaded (/lib/systemd/system/zoneminder.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2022-11-23 13:55:09 UTC; 37s ago
    Process: 29811 ExecStart=/usr/bin/zmpkg.pl start (code=exited, status=0/SUCCESS)
   Main PID: 29826 (zmdc.pl)
      Tasks: 6 (limit: 1029)
     Memory: 120.9M
        CPU: 1.901s
     CGroup: /system.slice/zoneminder.service
             tq29826 /usr/bin/perl -wT /usr/bin/zmdc.pl startup
             tq29855 /usr/bin/perl -wT /usr/bin/zmfilter.pl --filter_id=1 --daemon
             tq29861 /usr/bin/perl -wT /usr/bin/zmfilter.pl --filter_id=2 --daemon
             tq29867 /usr/bin/perl -wT /usr/bin/zmwatch.pl
             tq29874 /usr/bin/perl -wT /usr/bin/zmupdate.pl -c
             mq29879 /usr/bin/perl -wT /usr/bin/zmstats.pl

Nov 23 13:55:09 hogehoge sudo[29863]:     root : PWD=/usr/share/zoneminder/www ; USER=www-data ; COMMAND=/usr/bin/zmdc.pl start zmwatch.pl
Nov 23 13:55:09 hogehoge sudo[29863]: pam_unix(sudo:session): session opened for user www-data(uid=33) by (uid=0)
Nov 23 13:55:09 hogehoge sudo[29863]: pam_unix(sudo:session): session closed for user www-data
Nov 23 13:55:09 hogehoge sudo[29870]:     root : PWD=/usr/share/zoneminder/www ; USER=www-data ; COMMAND=/usr/bin/zmdc.pl start zmupdate.pl -c
Nov 23 13:55:09 hogehoge sudo[29870]: pam_unix(sudo:session): session opened for user www-data(uid=33) by (uid=0)
Nov 23 13:55:09 hogehoge sudo[29870]: pam_unix(sudo:session): session closed for user www-data
Nov 23 13:55:09 hogehoge sudo[29876]:     root : PWD=/usr/share/zoneminder/www ; USER=www-data ; COMMAND=/usr/bin/zmdc.pl start zmstats.pl
Nov 23 13:55:09 hogehoge sudo[29876]: pam_unix(sudo:session): session opened for user www-data(uid=33) by (uid=0)
Nov 23 13:55:09 hogehoge sudo[29876]: pam_unix(sudo:session): session closed for user www-data
Nov 23 13:55:09 hogehoge systemd[1]: Started ZoneMinder CCTV recording and surveillance system.
```
ZoneMinderが起動できたら、Apacheをリロードします
```shell-session:apahceリロード
$ sudo systemctl reload apache2
```

## 4-8.ZoneMinderへアクセス
同じネットワークで起動している端末のブラウザから、サーバに向かってアクセスします。
```title:サーバーアドレスが192.168.1.10の場合
http://192.168.1.10/zm
```
初回アクセス時は規約の確認画面が出てきますが、下の方のAPPLYを押せばメイン画面にアクセスできます。
![SnapCrab_ZM - Privacy - Google Chrome_2022-11-23_23-5-25_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985190/74e5ce6c-0fe0-9790-d5e2-5ad669ab7222.png)
インストールは以上です。お疲れさまでした。

# 5.ONVIFカメラの追加
インストールができたら、コーヒーブレイクを挟みつつカメラを追加しましょう。
自分の場合はONVIF対応カメラを買っていたのでこれで追加できました。
ここは他のサイトでもやり方が紹介されているのでサラっと流します。

1.ADDをクリック
![SnapCrab_ZM - Console - Google Chrome_2022-11-23_23-6-16_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985190/c6fccb48-198a-9b97-cabc-63fa137451b3.png)
2.右上の３つ並んでるうちの真ん中(RSSフィード(死語)みたいなアイコン)をクリック
![SnapCrab_ZM - Monitor - Monitor-1 - Google Chrome_2022-11-23_23-6-25_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985190/ee789d1a-3d9c-2541-96ab-84415751a6a0.png)
3.Detected Camerasから接続するカメラを選択、カメラに設定したユーザー名とパスワードを入力しNEXT
![SnapCrab_ZM - Monitor Probe - Google Chrome_2022-11-24_0-57-17_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985190/32b391b8-47da-7556-ac5d-3769a1be3f08.png)![SnapCrab_ZM - Monitor Probe - Google Chrome_2022-11-24_0-58-18_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985190/a65a1529-909b-fd64-2288-d190eadb7b24.png)
4.Detected Profilesから適当なプロファイルを選んでSAVE
(いくつか表示されると思いますが基本的にmainStreamのどれかを選べば問題ないかと。うまく映らなければ別のものに変えてください。)
![SnapCrab_ZM - Monitor Probe - Google Chrome_2022-11-24_0-57-49_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985190/4929eb3e-d2c2-3a4a-f0a1-fb1bcfa849db.png)![SnapCrab_ZM - Monitor Probe - Google Chrome_2022-11-24_0-57-54_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985190/c112aa88-6c7c-1181-75f0-5c0cbd504eb4.png)
5.元の画面に戻るので、カメラの名前を適当に変更してSAVE
　名前以外は特にいじる必要はないかと
　（日本語化してないので英語でね）
![SnapCrab_ZM - Monitor - TP-IPC - Google Chrome_2022-11-24_0-58-38_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985190/4d928fcd-23d4-0ae2-ed9c-e0351ba38db1.png)
6.追加完了

ところが、これがうまくできなくなったのです…

# 6.ONVIF追加で沼った話
実は一番最初はカメラ用のネットワークを作らず、お試しということで既存NWだけでカメラにDHCPでアドレスを振って設定していました。
![hoeg.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985190/4a9ab872-09d0-6169-d29f-c60b4899945c.png)
この時にはちゃんとDetected Camerasにカメラが表示されていました。

ところが、カメラ用のNWを切ってIPアドレスを固定化したところ、Detected Camerasに一覧が表示されなくなってしまいました。

いろいろ調べまわって、自分の場合は以下3つのポイントを確認するとなんとかONVIFを使うことができました。


## 6-1.デフォルトゲートウェイの確認
こちらのフォーラムで糸口を見つけました。おそらく開発者であろう方が回答しているものです。

https://forums.zoneminder.com/viewtopic.php?t=29921

>You say they are on the same network, but ONVIF will only probe the network that has the default gateway. Does the non-working machine have a second network that is actually it's primary?
>
>in 1.35 I added code to tell it to probe a different network. You could give that a try.

ONVIFはデフォルトゲートウェイが設定されているネットワークに対してしか検出がされないと書いてあります。
バージョン1.35で修正されたようで、現に複数NWが選択できるような項目は存在していますが、
1.36でも正しく検出できているかどうかは怪しいかもしれません。

NICが1つしかない(1つのNWにしか接続していない)状況でしたらまず起きえない事ですが
例えば有線LANと無線LANが共存しているような環境だったりすると、設定次第ではこういったことが起こるかもしれません。
![hoeg.drawio (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985190/8e4c8efb-cb4a-f9ba-7705-5d8050bdb375.png)
私の場合もこれと同じような状況になっていて、デフォルトゲートウェイとカメラNWが別のネットワークになっていました。
状態を解消するためにサーバーの設定を変更し、デフォルトゲートウェイをカメラNWのL3SWに設定することで、一部のカメラは無事検出できるようになりました。

一部のカメラですので、残りのカメラはというと…


## 6-2.カメラへのアドレス割り当てはDHCPで
ゲートウェイ変更の後、DHCPで振らせていたカメラは検出できましたが、固定IPで設定していたカメラは検出されませんでした。
試しに固定IPをやめてDHCPで割り当てるようにしたところ、今度は無事に全カメラを認識できるようになりました。
長かった…


## 6-3.UFWは一時的に無効化する
これはこの記事の編集にあたり発覚したこと。
いざもう一度同じ手順でやってみようとしたらカメラが検出されない！
いろいろ試した結果、UFWを一時的に切ることで無事に一覧を取得できました…

# 7.ほかにやったこと
- 録画開始
録画先をRAIDディスクにしてfunctionをRecordモードに、常時録画を開始しました。
今のところカメラ7台をほぼ連続録画して1日約50GB弱くらいのペースで録画できてます。
JPEG保存設定はオフ、録画はエンコード処理は行わずにパススルーモードで
(エンコードモードにした途端、サーバーが暴走しました笑)
![SnapCrab_NoName_2022-11-24_2-36-15_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985190/17c02069-f9c2-cded-2eca-dec502405c21.png)
- ユーザー認証機能の有効化とユーザー追加
Options -> System -> OPT_USE_AUTHにチェックを入れるだけでユーザー認証を有効化できます。
このほか、家族が間違って設定をさわってしまわないよう、機能制限ユーザーを追加しました。
![SnapCrab_NoName_2022-11-24_2-56-41_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985190/7d124c4c-69e3-a7e2-fbca-c55b38bdc56a.png)
- Sambaインストール
録画データを引っこ抜きやすくするためにSambaを入れました
- pyzmでAPIごにょごにょ
ZoneMinder APIのPythonラッパーがあったので、これを使って定期実行プログラムを作りました。
詳細は別記事にまとめる予定です。

# 8.おわりに
だいぶ導入に苦戦しましたが、動き出したらとても素晴らしいソフトです。
このクオリティが無料で使えるとは…開発者の方々に頭が上がりません。

環境構築からまだ一週間と経っていませんが、今のところは安定して動いています。

PythonでZoneMinderのAPIをいじるモジュールも使ってみたので、それは別記事にまとめる予定です。

2022/11/25　追記
書きました

https://qiita.com/takasyu260/items/35a62f0d1e6647aa7a66