Ubuntu 22.04 - Install Zoneminder
Zoneminder is an open source web application that can be used for connecting
to cameras (in my case network "IP" cameras), and setting up various
security scenarios, such as automatic recording whenever motion is detected
in a specific zone at certain times etc.
This tutorial will show you how install and configure Zoneminder 1.36 on an
Ubuntu 22.04 server. Hopefully in the near future we will use Docker to make
this much simpler, as there are quite a few steps and configurations.
Requirements
CPU: The handling of multiple camera input streams and the corresponding
image processing for motion detection, can take quite a bit of CPU
horsepower. Luckily this works across multiple cores, so this is ideal for
something like a Ryzen 5/7 CPU with 6+ cores.
Networking: For the best performance and quality, you will want to use
Gigabit networking between your cameras and the computer running Zoneminder.
I used a Netgear POE switch to power the cameras over the gigabit connection
which made them easier to deploy around the outside of the house. If you are
just using one Wifi camera with a moderate to low resolution, you will
probably be fine with Wifi, especially if its a good 5Ghz signal.
Install MySQL Server
Zoneminder requires a MySQL or MariaDB server. For this tutorial, I am going
to install MariaDB 10 onto this server, from the Ubuntu repositories.
Alternatively, you could deploy or use an existing MySQL/MariaDB server on
another node and hook Zoneminder up to that later.
Installing MySQL server is as easy as....
Setting SQL Mode - No Engine Substitution
Unfortunately, Zoneminder requires the sql_mode to have
NO_ENGINE_SUBSTITUTION. Luckily for us, the stock installation of MariaDB 10
on Ubuntu 22 has this in the SQL mode, so if you followed the steps above,
there is nothing you need to do here. However, sometimes people may choose
to use a remote database they have already set up, so it is worth knowing
how to check, and how to configure this just in case.
Check SQL Mode
To check the SQL mode, log into the database and run:
select @@sql_mode;
This should output something like:
+----------------------------------------------------------------------+
| @@sql_mode |
+----------------------------------------------------------------------+
| STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER
,NO_ENGINE_SUBSTITUTION |
+----------------------------------------------------------------------+
1 row in set (0.000 sec)Configure SQL Mode
If you didn't see NO_ENGINE_SUBSTITUTION in the output, then you need to add
the following line to the /etc/mysql/mariadb.conf.d/50-server.cnf or
appropriate to your database (might be a different path if you installed
MySQL rather than MariaDB.
editor /etc/mysql/mariadb.conf.d/50-server.cnf
I like to add the following line (if there isn't already one for setting the
sql_mode, somewhere in the fine tuning section, but the important thing is
that it is underneath the [mysqld] and before the next [somethingHere] that
defines another section. (TOML format).
sql_mode = STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO
,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
For the change to take effect, you will need to restart the MySQL service
like so:
sudo service mysql restartInstall Zoneminder
For this tutorial, we are going to install Zoneminder from Isaac Conor's PPA.
sudo apt update \
&& sudo apt install software-properties-common software-properties-common -y \
&& sudo add-apt-repository ppa:iconnor/zoneminder-1.36 -y \
&& sudo apt update \
&& sudo apt install zoneminder -yConfigure Apache
After having installed Zoneminder, we need to get it configured to play with
Apache by enabling the zoneminder virtual host configuration and setting the
file permissions as required.
sudo chmod 740 /etc/zm/zm.conf \
&& sudo chown root:www-data /etc/zm/zm.conf \
&& sudo chown --recursive www-data:www-data /usr/share/zoneminder/ \
&& sudo a2enconf zoneminder
Then we need to enable CGI and rewrite mods in Apache before restarting the
service for the changes to take effect.
sudo a2enmod cgi \
&& sudo a2enmod rewrite \
&& sudo a2enmod expires \
&& sudo a2enmod headers \
&& sudo systemctl reload apache2Set TimezonesSet Host TImezone
Set the timezone on the host by running:
sudo dpkg-reconfigure tzdataSet Database Timezone
The database will default to UTC timezone, so to set it to something different
one needs to perform the following steps:
Import the timezone info into the database:
mysql_tzinfo_to_sql /usr/share/zoneinfo | sudo mysql -u root mysql
Now edit the /etc/mysql/mariadb.conf.d/50-server.cnf config file:
/etc/mysql/mariadb.conf.d/50-server.cnfsudo editor /etc/mysql/mariadb.conf.d/50-server.cnf
Find the [mysqld] section header and append the following underneath it:
default-time-zone = "America/Chicago"sudo service mysql restartNote:
These steps can also be found here.Set PHP Timezone
Finally, Zoneminder needs us to specify the timezone to use in the PHP.ini
configuration filein the PHP.ini
sudo editor /etc/php/8.1/apache2/php.ini
Find the commented-out line:
;date.timezone =
... and replace it with your timezone. I am going to use the Chicago Timezone
(here is a nice list of timezone labels to refer to):
date.timezone = "America/Chicago"Freshen Zoneminder Database Configuration
Run the following command/script to "freshen" Zoneminder configuration in the
database (reference). Without this, I found that I had undefined configuration
variable defines, and Zoneminder would fail silently, resulting in Apache
serving up a blank page with a 500 HTTP status code.
sudo /usr/bin/zmupdate.pl --freshenOptional Extra StepsChange Zoneminder Database Password
In older tutorials for setting up zoneminder, one had to manually initialize
the database. This is also useful to know, should you lose access to your
database and need to set it up again. Here is what you would need to do:
sudo mysql -e \
"grant select,insert,update,delete,create,alter,index,lock tables on zm.* to
'zmuser'@localhost identified by 'useRandomPasswordHere';"
Update the ZM_DB_PASS variable in the /etc/zm/zm.cnf file, to the database
password you just set.
Store Events On Separate Drive
If you're like me, you want to store all the captured video footage on cheap HDD
storage rather than your boot drive's SSD. This is easy enough to configure with
symlinks.
The default setup will have Zoneminder write events to
/var/cache/zoneminder/events. This means we can easily just change the pointer
to wherever our hard drive is mounted to. In my case, I am using an NFS at
/mnt/nfs so I will do:
NEW_LOCATION="/mnt/nfs/zoneminder/events"
sudo mkdir -p $NEW_LOCATION \
&& sudo rm -rf /var/cache/zoneminder/events \
&& sudo mkdir -p $NEW_LOCATION \
&& sudo chown --recursive www-data:www-data $NEW_LOCATION \
&& sudo ln -s $NEW_LOCATION /var/cache/zoneminder/events
It is important that www-data is the owner of this new folder, which gives it
the ability to create and manage the files in that location.
sudo chown www-data:www-data -R /mnt/nfs
You can also repeat the steps above for images and temp but these should not
require as much storage.
Start Zoneminder
Run the following commands to start zoneminder and configure it to automatically
start on boot:
sudo systemctl start zoneminder.service \
sudo systemctl enable zoneminder.serviceTesting
You should now be able to go to your node's hostname or IP address in your
browser and see the zoneminder web application. From this point on, you probably
want to add some cameras, and setup authentication.
Conclusion
The UI looks a bit dated and could really do with implementing bootstrap, but
it's pretty darn good functionally.
AppendixInitialize Database
In older tutorials for setting up zoneminder, one had to manually initialize the
database. This is also useful to know, should you lose access to your database
and need to set it up again. Here is what you would need to do:
mysql -uroot -p < /usr/share/zoneminder/db/zm_create.sql
sudo mysql -e \
"grant select,insert,update,delete,create,alter,index
,lock tables on zm.* to 'zmuser'@localhost identified by
'useRandomPasswordHere';"References