How I setup a CCTV camera with Raspberry Pi Zero W and MotionEyeOS image for home surveillance

When the Raspberry Pi Zero W was launched, I didn't think twice before ordering one. Compared to the Raspberry Pi Zero, the Raspberry Pi Zero W comes with WiFi. This meant that I can use my new Raspberry Pi Zero W to replace my Raspberry Pi 3 CCTV camera for home surveillance and use the more powerful Raspberry Pi 3 for other projects.

This post documents how I setup my Raspberry Pi Zero W as a CCTV camera using the MotionEyeOS image.

Hardware used for this CCTV camera setup

I utilized the following hardware component for this CCTV camera setup:

Note that I had utilized an earlier version of the Raspberry Pi Camera module. If you do not have a Raspberry Pi Camera module, you may want to get the Raspberry Pi Camera module V2 instead.

Preparing the MotionEyeOS image on my microSD card

The first task that I took to setup my Raspberry Pi Zero W as a CCTV camera is to prepare the MotionEyeOS image on my microSD card.

Choosing the right version of MotionEyeOS for my Raspberry Pi Zero W CCTV camera

As of this writing, there are three versions of MotionEyeOS images available for setting up CCTV cameras on Raspberry Pi boards:

Since I was setting up a CCTV camera with a Raspberry Pi Zero W board, I downloaded the first image option, motioneyeos-raspberrypi-20170329.img.gz, onto my MacBook Pro.

Installing the MotionEyeOS image on my microSD card

Although I used to install Raspberry Pi operating system with my Windows machine, I chose to install the operating system image with my Mac this time round.

To install the MotionEyeOS image on my microSD card, I first extracted .img file from motioneyeos-raspberrypi-20170329.img.gz.

I then inserted the microSD card via its adapter into my MacBook Pro.

Finally, I selected the .img file that I had extracted earlier and click on the "Flash!" button on Etcher. Once Etcher had completed installing the MotionEyeOS image on my microSD card, I then proceeded to prepare the WiFi configurations for my Raspberry Pi Zero W CCTV camera to connect to my home WiFi network.

Getting the Raspberry Pi Zero W CCTV camera connect to my home WiFi on first boot

The easiest way to configure my Raspberry Pi Zero W CCTV camera is to get it to connect to my home WiFi so that I can communicate with MotionEyeOS's web server through a web browser running on my MacBook Pro.

To get my Raspberry Pi Zero W CCTV camera to connect to my home WiFi on first boot, I first used nano to create the wpa_supplicant.conf file and saved it on my Desktop:

update_config=1
ctrl_interface=/var/run/wpa_supplicant

network={
        scan_ssid=1
        ssid="my-home-wifi-ssid"
        psk="my-home-wifi-password" 
}

After saving the file, I dragged wpa_supplicant.conf into the microSD card:
MotionEyeOS image with wpa_supplicant.conf on microSD card

Connecting the Raspberry Pi Camera Module to Raspberry Pi Zero W board and the Official Case

After preparing the microSD card, I inserted the microSD card into the microSD card slot on my Raspberry Pi Zero W board. With that, I could then connect the Raspberry Pi Camera Module to the Raspberry Pi Zero W board and the Raspberry Pi Zero Official Case. After assembling the parts, my Raspberry Pi Zero W CCTV camera looks like this:

Raspberry Pi Zero Official Case with Camera Module and Zero W board

Booting into MotionEyeOS on my Raspberry Pi Zero W CCTV camera

Once I had assembled the parts for Raspberry Pi Zero W CCTV camera, the next step that I did was to connect my Belkin micro USB cable to the power port on my Raspberry Pi Zero W CCTV camera. The other end of my Belkin micro USB cable was connected to my USB wall plug charger to draw power into my Raspberry Pi Zero W CCTV camera.

Since I did not have a micro HDMI cable with me, I logged into the status page of my DLink router to check whether my Raspberry Pi Zero W CCTV camera had completed the first boot operations.

When my Raspberry Pi Zero W CCTV camera had completed the first boot operations, it would have requested for a private IP address via DHCP. When the private IP address requisition was successful, my router's status page was updated with an entry in the table under the "LAN COMPUTERS" section.

To get the private IP address of my Raspberry Pi Zero W CCTV camera, I looked for the row with a name of the form "meye-xxxxxxxx". Indeed, there was such an entry and the corresponding IP address that my Raspberry Pi Zero W CCTV camera had been given was 192.168.0.116.

Accessing the camera video stream on my Raspberry Pi Zero W CCTV camera with my browser from within my home network

To access the camera video stream on my Raspberry Pi Zero W CCTV camera, I entered 192.168.0.116 into the location bar of my web browser on my MacBook Pro.

With that, I got the following screen:

First access to Raspberry Pi Zero W CCTV camera via Chrome

Making sure that my Raspberry Pi Zero W CCTV camera can only be accessed through my user account

By default, MotionEyeOS allows anybody with a browser to watch the camera video stream of my Raspberry Pi Zero W CCTV camera without any restriction. I am definitely not comfortable with this default setting. Hence, the first configuration that I made to my Raspberry Pi Zero W CCTV camera was to set some passwords to restrict access to the camera stream.

To apply access control to the MotionEyeOS running on my Raspberry Pi Zero W CCTV camera, I would need to login as the admin user.

To login with the admin user, I clicked on the person icon at the top left corner of the screen and was shown the following screen:

MotionEyeOS login prompt on Raspberry Pi Zero W CCTV

I then entered admin as the username, left the password field blank and clicked on Login.

With that, the camera video stream appeared on the browser window again. Next, I clicked on the hamburger icon on the top left corner of the screen to and was shown the configuration panel:

MotionEyeOS v20170329 with configuration panel shown

Setting a password for the admin user

In MotionEyeOS, only the admin user is allowed to configure MotionEyeOS and the username of the admin user cannot be changed.

To set a password for the admin user, I entered a password in the "Admin Username" text field.

Creating the surveillance user

The surveillance user is only granted view access to the video stream from my Raspberry Pi Zero W CCTV camera. Configuring a username and password for the surveillance user would ensure that the video stream from my Raspberry Pi Zero W CCTV camera only displays after either the surveillance user or admin user logs in successfully.

To create a surveillance user, I entered a username in the "Surveillance Username" field and a password in the "Surveillance Password" text field.

Saving the access control configurations

Once I was satisfied with the surveillance username and passwords that I had chosen for both the admin and surveillance users, I then clicked on the "Apply" button that appeared at the top. Doing so resulted in a prompt to reboot MotionEyeOS:

MotionEyeOS v20170329 with system reboot prompt after setting access control configurations

I clicked "Yes" to make MotionEyeOS reboot itself.

After my Raspberry Pi Zero W CCTV camera started up again, I was shown the login prompt.

I keyed in my admin user credentials to continue on with configuring my Raspberry Pi Zero W CCTV camera.

Turning on Advanced Settings

After setting the access control to my Raspberry Pi Zero W CCTV camera, I proceeded to turn on "Advanced Settings" so that I could configure MotionEyeOS further.

To turn on "Advanced Settings", I clicked on the toggle button next to "Advanced Settings" under the "General Settings" tab:

MotionEyeOS v20170329 with after turning on advanced settings

I then clicked the "Apply" button at the top.

Changing the default timezone

The default timezone for MotionEyeOS was set to UTC, which was not the timezone for the region where I resided in. This resulted in inaccurate timestamp on my camera video. Such inaccurate time display would create inconvenience when I wanted to verify whether the deliveryman from the postal service had really attempted to come to my house at the time that they had claimed in their failed delivery sms message.

To avoid having to calculate the timestamp for my region from the UTC timestamp, an easier way would be to change the default timezone on my Raspberry Pi Zero W CCTV camera. To change the default timezone to the one that my region follows, I selected "Asia/Singapore" from the Time Zone dropbox and clicked the "Apply" button at the top of the screen to save the changes. I clicked "Yes" when MotionEyeOS prompted to reboot itself.

After my Raspberry Pi Zero W CCTV camera started up again, I keyed in my admin user credentials to continue on with the other configurations.

Turning off the camera LED indicator

Since the Raspberry Pi Zero Official Case is opaque, it doesn't make much sense to turn on the camera LED indicator. Furthermore, turning off the camera LED indicator can also reduce the power consumption of my Raspberry Pi Zero W CCTV camera.

To turn off the camera LED indicator on my Raspberry Pi Zero W CCTV camera, I clicked on the "Expert Settings" tab and clicked on the toggle button beside "Enable CSI Camera Led":

MotionEyeOS v20170329 with CSI Camera Led disabled

I then clicked on the "Apply" button at the top and reboot my MotionEyeOS.

After my Raspberry Pi Zero W CCTV camera started up again, I keyed in my admin user credentials to continue on with the other configurations.

Changing video resolution

The default resolution setting of 320 X 200 for the Raspberry Pi Zero W CCTV camera made the videos look too blurry. With a 128 GB microSD card, I could afford a higher resolution for the videos that my Raspberry Pi Zero W CCTV camera is going to capture.

To change the video resolution, I clicked on the "Video Device" tab, select the "1024 X 768" option from the drop down box besides "Video Resolution" and clicked "Apply" at the top:

MotionEyeOS v20170329 video resolutions changed to 1024x768

Once the setting is applied, I got a better view of the area that my Raspberry Pi Zero W CCTV camera was pointing at.

Limiting the preservation of still images and movies

By default, MotionEyeOS keeps images and movies for as long as it can. In the event where the storage space on the microSD card got maxed out, it will stop recording movies. This is not an ideal behaviour for my use case. To ensure that there is always storage space for new videos, there is a need to limit the preservation of still images and movies.

To configure the preservation period of pictures and movies, I clicked on the hamburger icon to bring out the configuration panel. Inside the configuration panel, I clicked on the "Still Images" and "Movies" tabs to expand both sections. I then chose the "For One Month" option for both the "Preserve Pictures" and "Preserve Movies" drop down boxes.

Changes to both drop down boxes caused the following prompt to appear:

MotionEyeOS v20170329 warning prompt after changing picture preservation settings

I clicked the "Ok" button on both prompts and got the following configuration state:

MotionEyeOS v20170329 with configurations to preserve pictures and movies for one month

Once I was done with that, I clicked on the "Apply" button at the top to persist the configurations and rebooted my Raspberry Pi Zero W CCTV camera.

With that, I was satisfied with the configurations that I wanted for my Raspberry Pi Zero W CCTV camera.

Making my Raspberry Pi Zero W CCTV camera accessible from outside my home network through HTTPS

Without HTTPS, it would be insecure to access my Raspberry Pi Zero W CCTV camera from outside my home network. Protecting the HTTP traffic between a web browser and my Raspberry Pi Zero W CCTV camera would require a reverse proxy server, a domain name and a SSL certificate.

Through my experience in setting up a LEMP web server on Raspberry Pi 3 and setting up a free CA signed SSL certificate to secure a WordPress site hosted on it, I had the hardware and software resources to secure access to my Raspberry Pi Zero W CCTV camera with HTTPS.

Creating a sub domain from a domain that I already owned and point that sub domain to the public IP address of my home router

Since I own a couple of domain names, I could create a sub domain from one of the domain names. And since I am leveraging on DigitalOcean name servers to translate my domain names into IP addresses, I could create a sub domain via DigitalOcean's control panel.

To create a sub domain via DigitalOcean's control panel, I logged into my Digital Ocean account and go to the "Networking" page. I then proceeded to the "Domain" tab to select a domain which I wanted to create a sub domain from.

At the "Create new record" page, I entered the sub domain that I wanted for my Raspberry Pi Zero W CCTV camera and the public IP address of my home router:

Digital Ocean page to create a new Type A DNS record for CCTV camera

After clicking on the "Create Record" button, I was able to get the IP address of my home router by sending a ping to cctv.adomainname.com.

And being able to reach my home router will meant that I was able to reach the LEMP server running on my Raspberry Pi 3.

Configuring nginx to facilitate the Let's Encrypt client in acquiring the SSL certificate for my sub domain

Once I was sure that the nginx server running on my Raspberry Pi 3 could receive HTTP requests directed at my sub domain, I proceeded on with creating the nginx configurations to facilitate the Let's Encrypt client in acquiring the SSL certificate for my sub domain.

To do so, I connected to my Raspberry Pi 3 LEMP server via SSH:

ssh root@192.168.0.123

Once I got into my Raspberry Pi 3 LEMP server, I used nano to create a configuration file at /etc/nginx/sites-enabled/cctv.adomainname.com.conf:

sudo nano /etc/nginx/sites-enabled/cctv.adomainname.com.conf

Once inside my nano editor, I created the following nginx configuration:

server {
	listen 80;
	server_name  cctv.adomainname.com;

	root /var/www/cctv.adomainname.com;

	location ~ /.well-known {
		allow all;
	}
}

After creating the nginx configurations, I saved the file and restarted my nginx server:

sudo systemctl restart nginx.service

I also created the directory /www/var/cctv.adomainname.com for the Let's Encrypt client to use in the process of acquiring the SSL certificate for my sub domain:

sudo mkdir /www/var/cctv.adomainname.com
sudo chown www-data:www-data /www/var/cctv.adomainname.com

Running Let's Encrypt client to get a SSL certificate artefacts for the sub domain to my Raspberry Pi Zero W CCTV camera

Once I had the configurations necessary for the Let's Encrypt client to acquire the SSL certificate artefacts for my sub domain, I ran the following command to get the Let's Encrypt client running:

/opt/letsencrypt/letsencrypt-auto certonly -a webroot --webroot-path=/var/www/cctv.adomainname.com -d cctv.adomainname.com

Creating the nginx configurations for serving HTTPS on behalf of my Raspberry Pi Zero W CCTV camera

After my Let's Encrypt client had acquired the SSL certificate artefacts for my sub domain, my nginx was ready for the corresponding configurations to serve HTTPS on behalf of my Raspberry Pi Zero W CCTV camera. The following is the last set of configurations that I included in /etc/nginx/sites-enabled/cctv.adomainname.com.conf. These set of configurations allows me to access my Raspberry Pi Zero W CCTV camera over HTTPS via my sub domain:

# Redirect HTTP requests to HTTPS 
server {
	listen 80;
	server_name  cctv.adomainname.com;
	return 301 https://$host$request_uri;
}

# For ssl
server {
	ssl on;
	ssl_certificate /etc/letsencrypt/live/cctv.adomainname.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/cctv.adomainname.com/privkey.pem;
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	ssl_prefer_server_ciphers on;
	ssl_dhparam /etc/ssl/certs/dhparam.pem;
	ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
	ssl_session_timeout 1d;
	ssl_session_cache shared:SSL:50m;
	ssl_stapling on;
	ssl_stapling_verify on;
	add_header Strict-Transport-Security max-age=15768000;
	
	default_type  application/octet-stream;
	
	listen 443;
	server_name  cctv.adomainname.com;

	location ~ /.well-known {
		allow all;
	}

	location / {
		proxy_pass http://192.168.0.116;
	}
}

Buying your Raspberry Pi Zero W CCTV camera from Amazon

If you do not have the Raspberry Pi Zero W CCTV components mentioned in this post yet, you may want to purchase them from Amazon. Simply click on the button below to add the Raspberry Pi Zero W CCTV components to your cart. You may remove anything that you already have or replace some of the components with other components.


Advertisements

About Clivant

Clivant a.k.a Chai Heng enjoys composing software and building systems to serve people. He owns techcoil.com and hopes that whatever he had written and built so far had benefited people.

Advertisements
Advertisements