ZoneMinder is a free, open source, Linux based security DVR solution. I've found it to be quite handy, but the installation process can be a bit overwhelming at first. In this post, I've documented how I got ZoneMinder running on CentOS 5.6.
In my professional career, I've been tasked with managing a corporate DVR deployment for the better part of the last 10 years. I've seen the gradual move from analog cameras to almost pure IP camera environments, and the evolution of security-centric DVR software. The software I use at work, while adequate, is quite expensive, and Windows-based. So, when I decided to install some (IP) cameras at home for security, I decided to do some research and see what else was on the market. There were, as you can imagine, quite a few Windows based DVR solutions, but most of them were either costly, or clunky. Enter ZoneMinder - a free, Linux based DVR solution. Paired with the most excellent eyeZm iPhone/iPad app, I've found ZoneMinder to meet or exceed the quality and reliability of many commercial offerings. When you first look at the ZoneMinder website, the installation process may seem a bit overwhelming. The purpose of this article is to document my installation experience. What worked, what didn't, and the end result. Disclaimer - in the interest of full disclosure, I am no Linux expert. What follows is what worked for *me* and may not necessarily represent best practices for either Linux or ZoneMinder configuration. YMMV. Use at your own risk. You've been warned. At the end of this article, you should have a working ZoneMinder installation, with FFmpeg support, and basic eyeZm support. I personally only use IP cameras, so any details related to hardware capture cards have been omitted. I'll be writing a follow-up post to detail how to enable H264 support for eyeZm.
ZoneMinder runs on Linux. While most any Linux distribution should work fine, I'm a fan of CentOS, and that's what the rest of this article will focus on. If you're using another distribution, then this article probably isn't for you.
First, I'll go over my CentOS installation. If you already have a working install of CentOS, then you can likely skip ahead.
1 - You'll need a working install of CentOS 5.6 (RHEL 5.x should also work, but I've not tested this) before you can install ZoneMinder. The good folks over at Easynews.com have a blazing fast mirror of CentOS set up here.
2 - I'm going to assume that you've got some Linux background and are familiar with installing CentOS. I'm only going to document where I deviated from the default/standard install. The following changes are in order, but I've not gone to great lengths to document exactly where in the installation process they were made. It should be pretty self-explanatory if using the graphical installer.
3- Since I'm using this box as a dedicated CentOS box, I changed the partition layout to "Remove all partitions on selected drives and create default layout". You can partition to meet your needs.
4 - Assign a static IP address and disable IPv6 (unless you use IPv6). Set a hostname, gateway, and primary DNS. Note - DHCP will work (provided you have a DHCP server on your network), but I'm assuming you'll probably want to do some port forwarding / static NAT so you can access your ZM installation remotely - so a static IP just makes sense.
5 - Uncheck "Desktop - Gnome" and any other software sets that are checked. Check the button that says "Customize Now", then next. With the exception of "Base" under the Server category, uncheck everything else. We'll install what we need later. Removing these other packages during installation also does away with the need for any installation CD other than CD 1.
6 - Upon your first boot of CentOS, you should be see the System Setup utility pop up. Under Firewall Configuration, I've disabled SELinux (ZoneMinder should work with SELinux enabled - with some tweaking, but since this server is running at home behind my firewall, I'd rather not have the added complexity). In the Firewall Configuration->Customize, I've allowed inbound SSH (TCP/22), WWW (TCP/80), Secure WWW (TCP/443), and under "Other Ports", I've added "10000:tcp" for Webmin (more to come on that later).
7 - There are likely a number of System Services that can be disabled (i.e., Bluetooth), but I'll leave that to your discretion, as it largely depends on your environment.
1 - First, let's download and install any updates we're missing:
[root@zm1 ~]# yum update
2 - Since there was likely a kernel update that was installed as part of the previous yum update, let's go ahead and reboot:
[root@zm1 ~]# reboot
3 - I want to exclude kernel updates from being applied automatically in the future when yum update is run, so I'm going to modify /etc/yum.conf. Note: I'll be using emacs for the remainder of this article. Use whatever editor you're comfortable with.
First, let's install kernel-headers. We'll need these later, and won't be able to install them once we modify yum.conf
[root@zm1 ~] yum install kernel-headers
Now that we've done that, let's go ahead and modify yum.conf:
[root@zm1 ~]# emacs /etc/yum.conf
We want to add the line exclude=kernel* to the [main] section. You should end up with something like this:
[main] cachedir=/var/cache/yum keepcache=0 debuglevel=2 logfile=/var/log/yum.log distroverpkg=redhat-release tolerant=1 exactarch=1 obsoletes=1 gpgcheck=1 plugins=1 exclude=kernel* bugtracker_url=http://bugs.centos.org/set_project.php?project_id=16&ref=http://bugs.centos.org/bug_report_page.php?category=yum
4 - Next, I want to be able to set up NTP for time sync, so I'll install NTP. Since we'll be using this server for security / DVR purposes, having an accurate time source is paramount.
[root@zm1 ~]# yum install ntp
5 - I'm lazy, and don't know every Linux command there is,so I'm going to install Webmin to help me manage this server from a web browser. I'm installing from the tar.gz file, you can install Webmin however you'd like (or, optionally, skip it. It's in no way required for ZM to run).
[root@zm1 ~]# wget http://prdownloads.sourceforge.net/webadmin/webmin-1.550.tar.gz [root@zm1 ~]# tar zxvf webmin-1.550.tar.gz [root@zm1 ~]# cd webmin-1.550 [root@zm1 webmin-1.550]# ./setup.sh
And from here, just step your way though the setup wizard as appropriate for your environment.
6 - Go ahead and open Webmin in your web browser: http://ip-of-your-zm-server:10000. Once logged in, go to Hardware->System Time, Time Server Sync. Enter an NTP server (I like pool.ntp.org). Change "Synchronize on schedule?" to Yes, then modify your sync schedule to suite you, then click "Sync and Apply".
7 - Back in our SSH session, let's go ahead and install some of ZoneMinder's prerequisites. First, Apache and PHP:
[root@zm1 ~]# yum install httpd httpd-devel php53 php53-cli php53-common php53-devel php53-gd php53-mbstring php53-mysql php53-snmp php53-soap php53-xml php53-xmlrpc
[root@zm1 ~]# yum install mysql mysql-devel mysql-server
Let's go ahead and start MySQL server real quick:
[root@zm1 ~]# service mysqld start
Then, we'll run the MySQL secure installation script to set a root password and remove some unused DBs and users:
[root@zm1 ~]# /usr/bin/mysql_secure_installation
Next, we'll install the Perl-compatible regular expression library:
[root@zm1 ~]# yum install pcre pcre-devel
[root@zm1 ~]# yum install netpbm*
[root@zm1 ~]# yum install libjpeg libjpeg-devel
8 - We're ready to install ffmpeg now, but before we can do that, we need to enable the RPMforge repository for CentOS. This can be done by following these simple instructions. Once done, let's install ffmpeg:
[root@zm1 ~]# yum install ffmpeg ffmpeg-devel ffmpeg-libpostproc
9 - We'll need gcc-c++ (C++ support for GCC) to compile ZoneMinder, so let's install that next:
[root@zm1 ~]# yum install gcc-c++
10 - ZoneMinder needs OpenSSL, along with some associated packages (some of these are probably already installed):
[root@zm1 ~]# yum install openssl openssl-devel gnutls gnutls-devel perl-Crypt-OpenSSL-* perl-Net-SSLeay
11 - ZoneMinder also needs some bzip2 libraries. Let's install them:
[root@zm1 ~]# yum install bzip2 bzip2-devel
12 - ZoneMinder needs some Perl modules. Quite a few, in fact. Let's go ahead and install them now:
[root@zm1 ~]# yum install perl-Date-Manip perl-LWP-UserAgent-Determined perl-Sys-Mmap perl-Device-SerialPort perl-Archive-Tar perl-MIME-Lite perl-MIME-tools perl-Net-SMTP-* perl-Net-FTP-AutoReconnect perl-Archive-Zip perl-Module-Load
[root@zm1 ~]# wget http://www.zoneminder.com/downloads/ZoneMinder-1.24.4.tar.gz [root@zm1 ~]# tar zxvf ZoneMinder-1.24.4.tar.gz [root@zm1 ~]# cd ZoneMinder-1.24.4 [root@zm1 ZoneMinder-1.24.4]#
15 - We're now ready to run the configure script (where "YOUR_ZM_MYSQL_PASSWORD" is the password you'd like to use for the "zmuser" MySQL user:
[root@zm1 ZoneMinder-1.24.4]# ./configure --with-webdir=/var/www/html/ --with-cgidir=/var/www/cgi-bin/ ZM_DB_PASS=YOUR_ZM_MYSQL_PASSWORD CPPFLAGS=-D__STDC_CONSTANT_MACROS
Assuming you installed all the packages listed above, the configure script should run without a hitch, and you'll end up with "Writing Makefile for ZoneMinder". One note - "CPPFLAGS=-D__STDC_CONSTANT_MACROS" is necessary, at least in my case, in order for ffmpeg to properly compile. See this FAQ from the official ZM Wiki for more.
2011-07-28 - User BARKY81 pointed out the following in the comments (thanks again for the feedback). Relevant for x64 users:
One other minor clarification for x86_64 users.... I got this "if you get the configure "error zm requires libmysqlclient.a" with 64 bit CentOS add the following to the end of your configure statement...found the answer in the zone minder wiki at http://www.zoneminder.com/wiki/index.php/CentOS. EVERYTHING WORKS!
Next, we can go ahead and and run "make":
[root@zm1 ZoneMinder-1.24.4]# make
This may take a little bit, despending on the speed of your computer. Assuming nothing bombs out, we can move on to the next step.
16 - At this point, we need to create the default ZoneMinder database, and then import the default data into the newly created DB. Please note, MySQL will prompt you for your root password that you established back at step 7.
[root@zm1 ZoneMinder-1.24.4]# mysql -uroot -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 10 Server version: 5.0.77 Source distribution Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> create database zm; Query OK, 1 row affected (0.00 sec) mysql> exit; Bye [root@zm1 ZoneMinder-1.24.4]# mysql -uroot -p zm < ./db/zm_create.sql Enter password: [root@zm1 ZoneMinder-1.24.4]#
And now, we just need to grant our ZoneMinder user rights to the newly created database (Where "YOUR_ZM_MYSQL_PASSWORD" is identical to the password you specified in the previous step):
[root@zm1 ZoneMinder-1.24.4]# mysql -uroot -p zm Enter password: Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 13 Server version: 5.0.77 Source distribution Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> grant select,insert,update,delete on zm.* to 'zmuser'@localhost identified by 'YOUR_ZM_MYSQL_PASSWORD'; Query OK, 0 rows affected (0.00 sec) mysql> quit; Bye [root@zm1 ZoneMinder-1.24.4]# mysqladmin -uroot -p reload Enter password: [root@zm1 ZoneMinder-1.24.4]#
17 - Almost there! Now, we just need to "make install" to get all the files where they belong:
[root@zm1 ZoneMinder-1.24.4]# make install
18 - Now, just for a little house keeping. First, we need to modify our php.ini file:
[root@zm1 ~]# emacs /etc/php.ini
We're looking for the "short_open_tag" directive. This needs to be "On", or you'll get a lovely error 500 when attempting to browse to ZoneMinder. Change this, save, and close out of php.ini.
short_open_tag = On
19 - You'll probably want to have ZoneMinder start with your system. Luckily, ZoneMinder includes a script for this purpose. We just need to copy it to /etc/init.d, and apply the appropriate permissions:
[root@zm1 ZoneMinder-1.24.4]# cp ./scripts/zm /etc/init.d/ [root@zm1 init.d]# chmod 755 /etc/init.d/zm
Now, for whatever reason (and perhaps I'm doing something wrong), I have trouble at this point. If you try to run the /etc/init.d/zm script, it bombs out. Running dos2unix sorts it out though. If anyone knows why this is necessary, please feel free to comment.
[root@zm1 init.d]# dos2unix /etc/init.d/zm dos2unix: converting file /etc/init.d/zm to UNIX format ...
Just one more command to actually get ZoneMinder to start on boot:
[root@zm1 ~]# chkconfig --add zm
20 - Almost done, I promise. Log back into Webmin. Go to System->Startup and Shutdown. Check httpd, mysqld, and zm (which should already be enabled), and click "Start on Boot". ZoneMinder requires Apache (httpd) and MySQL Server (mysqld), and obviously ZoneMinder (zm) to run. You can do this from the command line, if you prefer, but I didn't install Webmin for nothing!
21 - While not strictly required, I'd suggest rebooting your server at this point:
[root@zm1 ~]# reboot
22 - Now just open up your web browser, and browse to http://ip-of-your-zm-server. If all went well, you should be greeted with "ZoneMinder Console - Running - v1.24.4". Go ahead and set up your first monitor and make sure everything is in working order.
Congratulations! You now have a working ZoneMinder installation, and are ready to set up all your cameras, define your zones, and customize the installation to meet your needs. If you're going to be using the eyeZm iOS app for remote monitoring and management, then you should have basic support working now (mjpeg based streaming). To enable H264 support for eyeZm for lower bandwidth, higher quality streaming, please see this follow up article.