Introduction: Raspberry Pi Cloud IP Camera With POE

About: I'm an electronic and computer engineer. Web development and electronics design is what I mostly do, but I do enjoy working on personal projects that involve electronics but also 3D printing. And if it happens…

I was inspired by scavix's work with the instructable Raspberry Pi as low-cost HD surveillance camera so I decided to make my own Raspberry PI based IP camera that also features POE and supports integration with the Google Drive.

The video streaming can be simply viewed from a web browser. Most desktop browsers should work, I have also tested with Firefox for Android and it seems to work fine. It is also possible to view the video stream from multiple cameras the same time by making a simple HTML file, but more about that later.

The camera footage is saved in the form of JPEG images instead of video files in order to make the uploading to the Google Drive easier for Internet connections with low upload speeds. To prevent Google Drive from running out of space, every one hour the system checks for any images that are older from a specific threshold (e.g. 2 days) and automatically deletes them. After that it syncs the local footage directory with the Google Drive.

All the partitions on the microSD are read-only to prevent corruption from power failures. An external USB drive is also used to keep the /var and /home partitions which they both need to be read-write. That way the system is unlikely to become unbootable from a power failure since the microSD is 100% read-only.

I built two of those IP cameras a while ago and they have been tested on production environment (a small retail store) for more than a year and they have shown absolutely no issues. Since the day they have been installed both cameras have 100% uptime. So I'm pretty confident that they can be used as low cost alternative to commercial IP cameras in a small business.

Step 1: Tools and Parts

To build the camera you will need the following parts:

  • A Raspberry Pi Model B+[30€] - It will also work with a Model B but it won't fit in the housing I used. I haven't tested it with a Raspberry Pi 2 but I think it should work.
  • A Raspberry Pi Camera Module[30€] - Plus at least two screws that fit its mounting holes.
  • An 8GB Class10 MicroSD[5€] - I used a Kingston SDC10. A larger capacity MicroSD can also be used but it won't make a big difference.
  • A TP-LINK TL-POE10RPOE Splitter[16€] - You can use any POE Splitter that supports the 802.3af POE standard but this particular one fits perfectly inside the housing I used.
  • A POE Injector (or a POE Switch) - This is not part of the camera itself but you will need it to power the camera. I used a TP-LINK TL-SF1008P POE Switch [40€] since I have more that one IP camera (it supports up to four), but for just one camera I recommend the TP-LINK TL-POE150S POE Injector [25€]. If you can't find either of those, any injector or switch that supports the 802.3af POE standard should work.
  • 1 x Dummy IP Camera for the housing [9€] - I highly recommend getting the same with me because all the hardware fits perfectly inside. You can find it fairly easily if you search on ebay for “dummy ip ir camera” (you can find it in either silver or black color).
  • 2 x RJ45 jacks plus a small piece of UTP cable (Cat5e or Cat6) [less than 1€]
  • 2 x Female to Female Jumper Wires [less than 1€]
  • 1 x Hot Glue Stick
  • Solder Wire and Solder Wick

And the following tools:

  • A Soldering Iron
  • A Hot Glue Gun
  • A Desoldering Pump - Optional if you have solder wick.
  • A Dremel with a disk that can cut plastic plus drill bits
  • An RJ45 Crimping Tool

The total cost of the camera parts (excluding the POE Injector/Switch and the tools) is around 100€. The prices can vary depending where you live and from where you bought them.

Step 2: Preparing the MicroSD

Burning the Installer Image to the microSD:

As base for the system I decided to use a bare minimum Raspbian install and on top of it install only the required packages. That way the system is going to be more secure, more stable and there will be no waste of resources for things that are not required.

To get started first download the Raspbian NetInstall image from Githuband burn it to your microSD.

If you are using Linux just download the latest raspbian-ua-netinst-<latest-version-number>.img.xz file and use the following command:

xzcat /path/to/raspbian-ua-netinst-<latest-version-number>.img.xz > /dev/sdX

Where X is the letter of the device that corresponds to your microSD e.g. c. Before running the command make sure that there are no mounted partitions that belong to the microSD. In case there are use the following command to unmount each one of them:

umount /dev/sdXY

In case you got a permission denied error try the following command:

xzcat /path/to/raspbian-ua-netinst-<latest-version-number>.img.xz | sudo tee /dev/sdX > /dev/null

But be extremely carefully here, using the wrong letter in place of X may do irreversible damage to your system and ruin your day. Before running the command double check that the letter you typed in place of X is really the one that corresponds to the microSD.

If you are using Windows download the raspbian-ua-netinst-<latest-version-number>.zip file instead. Format then your microSD as FAT32 and extract the installer files in it.

Installing the System:

When the installer is finally written to the microSD it's time to install the system. The installation process is completely automated and non-interactive, the only thing you need to do is to insert the microSD to your Raspberry Pi, plug it in to your router using an Ethernet cable, connect the camera module, plug the power cable and it will automatically start to download and install the packages. The installation process takes around 45 to 60 minutes depending on the speed of your Internet connection. If you have an HDMI cable and a monitor you can keep an eye to the installation process. If you don't have a display attached you can monitor the Ethernet controller LEDs to guess activity.

Step 3: Establishing an SSH Connection

When the installation is finally complete the Raspberry Pi will automatically reboot and then you will be able to connect to it through SSH. On the first boot the Pi is going to get dynamically an IP address from the DHCP server of your router, so at first you will need to discover its IP address. On Linux this is fairly easy, you can just run the following nmap command as root:

nmap -sn x.x.x.x/y

Where x.x.x.x is the IP address of your private network e.g. 192.168.1.0 and the y is the number of ones (in binary) of the network mask e.g. for the network mask 255.255.255.0 the number of ones is 24. So, for that particular network you would run:

nmap -sn 192.168.1.0/24

An example output for this command is the following:

Starting Nmap 6.47 (  http://nmap.org  ) at 2015-09-08 17:29 EEST
Nmap scan report for 192.168.1.1 Host is up (0.00059s latency). MAC Address: 12:95:B9:47:25:4B (Intracom S.A.) Nmap scan report for 192.168.1.2 Host is up (0.0075s latency). MAC Address: 1D:B8:77:A2:58:1F (HTC) Nmap scan report for 192.168.1.4 Host is up (0.00053s latency). MAC Address: 88:27:F9:43:11:EF (Raspberry Pi Foundation) Nmap scan report for 192.168.1.180 Host is up. Nmap done: 256 IP addresses (4 hosts up) scanned in 2.13 seconds

As you can see in my case the Pi has the IP address 192.168.1.4.

Another way to obtain the IP address of your Pi is to check the logs of the DHCP server of your router. Every router is different so I'm not going to describe that process. There is also a version of nmap for Windows that you can try.

When you obtain the IP address of your Pi you can SSH to it using the following command on Linux:

ssh root@<ip-address-of-raspberry-pi>

Or by using PuTTY on Windows.

The default root password is raspbian.

Step 4: Configuring the System

On the first boot the system is almost completely unconfigured so there are some tasks you will need to do first.

The very first thing you need to do is to change the default root password by running:

passwd

Then, you will have to configure the locales. You can do this by running the following command:

dpkg-reconfigure locales

Go ahead and select all the en_US locales by using the space bar plus any other locales you want. When you are done hit Enter. Lastly, select the en_US.UTF-8 as the default locale and hit Enter.

Next you will need to configure the timezone. To do this run the following command:

dpkg-reconfigure tzdata

At this point it's a good idea to do some updates:

apt-get update
apt-get upgrade
apt-get dist-upgrade

Next thing you need to do, is to install a text editor in order to be able to edit configuration files. One of the easiest to use terminal text editors is nano:

apt-get install nano

When you are done editing a file using nano hit Ctrl-X to exit, type y and finally hit Enter to save the changes.

Next you need to create a normal user to use instead of root to make the system more secure and also reduce the risk of human error:

useradd raspcam
passwd raspcam
mkdir /home/raspcam
chown raspcam:raspcam /home/raspcam

And to change the default shell to bash run:

nano /etc/passwd

And replace /bin/sh with /bin/bash on the line that starts with raspcam.

Now you need to give that user the ability to do things that require root access so you need to install sudo:

apt-get install sudo

Then to give your user the ability to use sudo run:

visudo

And right after the line:

root    ALL=(ALL:ALL) ALL

put the following line:

raspcam    ALL=(ALL:ALL) ALL

Finally, run:

su - raspcam

From now on you will use that user for anything you want to do and when you need root access you will use sudo.

Next to make the system a little more secure it's a good idea to prevent root login through SSH. So, run:

sudo nano /etc/ssh/sshd_config

And on the line:

PermitRootLogin yes

Change the yes to no.

Next, install the raspi-copies-and-fills package for improved memory management performance:

sudo apt-get install raspi-copies-and-fills

Now it's a good time to give your Pi a static IP so you won't have to search what IP address it has all the time. To do so you need to edit the /etc/network/interfaces configuration file:

sudo nano /etc/network/interfaces

Your /etc/network/interfaces needs to have the following format:

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
    address x.x.x.x
    netmask y.y.y.y
    gateway z.z.z.z

In order for the Raspberry Pi to be able to communicate with the rest of the network (including your own computer) you need to make sure that the netmask, and the gateway fields are exactly the same with your own computer. The address can be any valid IP address as long as it belongs to the same network with your own computer and does not conflict with another one, that has been already allocated from the DHCP server of your router to another device.

To figure out what to use for the address, the netmask, and the gateway, you need to check the network configuration of your own computer.

If you are using Linux run the following command as root:

ifconfig 

And you will get an output similar to the following:

eth0      Link encap:Ethernet  HWaddr 11:22:33:aa:bb:cc  
          inet addr:192.168.1.4  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::2a10:7bff:fec5:6bc4/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1917143 errors:0 dropped:1 overruns:0 frame:0
          TX packets:2092796 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:642211523 (612.4 MiB)  TX bytes:1122273820 (1.0 GiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:72892 errors:0 dropped:0 overruns:0 frame:0
          TX packets:72892 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:11713024 (11.1 MiB)  TX bytes:11713024 (11.1 MiB)

As you can see in this example this particular machine has the IP address 192.168.1.4, the broadcast address of the current network is 192.168.1.255 and the network mask is 255.255.255.0. From that information you already know what to use for the netmask field.

Now to find out the gateway IP address (which is the IP address of your router) you can run the following command as root:

route -n

This will give you an output similar to the following:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG    1024   0        0 eth0
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0

The gateway is the IP address that has as its destination the IP address 0.0.0.0. In this example the gateway IP is 192.168.1.1.

Lastly, for the address field you can use any IP address between 192.168.1.1 and 192.168.1.254 as long as it's not the gateway address and it does not conflict with the IP of another device on the network. I suggest using an IP address like for example 192.168.1.100 so the risk of conflict will be very small. Furthermore, an IP address like this will be easier to remember.

If you want to be extra sure that the IP of the Pi will never conflict with the IP address of another device, you will need to configure the DHCP server of your router to exclude that IP from its address pool. Unfortunately, I cannot describe how to do that since every router is different.

If you are using Windows you can find out what address, netmask, and gateway to use in the same way by running the following command on the command line:

ipconfig /all

So, for our example the /etc/network/interfaces would look like the following:

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
    address 192.168.1.100
    netmask 255.255.255.0
    gateway 192.168.1.1

Next you need to set the nameservers. To do that run:

sudo nano /etc/resolv.conf

Typically, the primary nameserver will be your router, for the secondary nameserver you can use the Google Public DNS which is 8.8.8.8. To add the Google Public DNS as the secondary nameserver, at the end of the config file add the following line:

nameserver 8.8.8.8

Finally, for the changes to take effect you need to restart the networking service:

sudo /etc/init.d/networking restart

After restarting the networking service the SSH session is going to hang, because the IP of the Raspberry Pi has now changed so you will have to reconnect, but this time using the new user you created instead of root.

After reconnecting to your Pi you need to enable the camera module. To do so first you need to install raspi-config:

sudo apt-get install raspi-config

And run it as root:

sudo raspi-config

Select the Enable Camera option and then select Enable. Finally, answer yes to the question if you want to restart the Raspberry Pi now. After the reboot reconnect to it through SSH.

Step 5: Installing Motion

At this point you are finished with the basic system configuration, now it's time to setup the video steaming. To do that you are going to use motion:

sudo apt-get install motion

After installing motion you will also need to install some more libraries:

sudo apt-get install -y libjpeg62 libjpeg62-dev libavformat53 libavformat-dev libavcodec53 libavcodec-dev libavutil51 libavutil-dev libc6-dev zlib1g-dev libmysqlclient18 libmysqlclient-dev libpq5 libpq-dev

There is a known issue with motion and the Raspberry Pi Camera Module which can be fixed by replacing the original binary of motion with the one from this fork. To do that just run the following commands:

wget https://www.dropbox.com/s/jw5r1wss32tdibb/motion-mmal-opt.tar.gz
tar -xvf motion-mmal-opt.tar.gz
sudo cp motion-mmal/motion /usr/bin/motion
rm -rf motion-mmal motion-mmal-opt.tar.gz

Now you need to configure motion. First make a directory to keep the camera footage and a second one for the log files:

mkdir ~/logs/
mkdir -p ~/data/cloud
chmod -R 775 ~/data
sudo chgrp -R motion ~/data

Next, you need to create a log file in /var/log directory and give motion write access to it:

sudo touch /var/log/motion.log
sudo chown motion:motion /var/log/motion.log

Enable the motion daemon by running:

sudo nano /etc/default/motion

And changing the no to yes.

Now download the attached motion.conf file and put it in the /etc directory:

sudo wget https://www.instructables.com/files/orig/FCB/2PVD/IE7J5E20/FCB2PVDIE7J5E20.conf
sudo mv FCB2PVDIE7J5E20.conf /etc/motion.conf

There are a couple of things you may need to edit in the configuration file:

sudo nano /etc/motion.conf

First, go on the line:

stream_authentication username:password

And change the username and password to what you want. You are going to use that username / password pair to access the video stream later from your web browser.

By default motion is going to take a snapshot image every 6 seconds and save it in the /home/raspcam/data/cloud directory. You can change that interval if you want by editing the following line.

snapshot_interval 6

Bare in mind though that the smaller the snapshot interval is the larger the USB drive and the available space on Google Drive need to be.

The settings I provide you are what I found it works best for me after a lot of adjusting and tweaking but that does not mean you have to keep it as is, there are many other options you may want to play around with. So, feel free to play around with the settings and if you mesh up something you can always redownload the configuration file.

Now that everything is configured you need to start the motion daemon by running:

sudo /etc/init.d/motion start

If everything went as expected you should see the LED from the camera module to turn on. At this point you should be able to see the live streaming from the camera module if you go to the URL http://<ip-of-second-raspberry-pi>:8081 from your web browser.

If you made more than one cameras and you want to view the video stream from both the same time you can use the attached HTML file. The only thing you need to do is to replace the:

<ip-of-first-raspberry-pi>

And:

<ip-of-second-raspberry-pi>

With the actual IP addresses of your cameras.

Step 6: Adding Google Drive Support

Now that the live streaming is working, it's time to add Google Drive support. To do so you need to install the drive utility. To install it, run the following commands:

wget https://github.com/odeke-em/drive/releases/download/v0.2.8-arm-binary/drive-armv6l-sha256.bf9ad9cda93af2f05162eb48d92896f7bd5633c9676e805db8ed7070e50cb539
sudo mv drive-armv6l-sha256.bf9ad9cda93af2f05162eb48d92896f7bd5633c9676e805db8ed7070e50cb539 /usr/local/bin/drive
chmod +x /usr/local/bin/drive
sudo chown root:root /usr/local/bin/drive

Now if you run:

drive version

You should see an output like the following:

drive version: 0.2.8
Commit Hash: '906eb82d1bc7662f3c503ca9213980f7523e5199'
Go Version: go1.3.1
OS: linux/arm
BuildTime: 2015-08-28 02:42:01.299545786 +0000 UTC

After installing drive you need to pair it with a Google account so it can access Google Drive. I strongly recommend creating a new Google account for each IP camera because the snapshot images are going to occupy a lot of space.

To pair it with a Google account first login to it from your browser and then run the following command:

drive init ~/data/cloud/

Copy and paste the generated authorization link to your browser, copy and paste back to the terminal the authorization code and hit Enter.

Now run:

cd ~/data/cloud/ && drive about

If you see an output like the following, it means everything went as expected:

Account type:    LIMITED
Bytes Used:    0                    (0.00B)
Bytes Free:    16106127360          (15.00GB)
Bytes InTrash:    0                    (0.00B)
Total Bytes:    16106127360          (15.00GB)

* Space used by Google Services *
Service                              Bytes                               
DRIVE                                0.00B                               
GMAIL                                0.00B                               
PHOTOS                               0.00B                               
Space used by all Google Apps        0.00B                               

* Maximum upload sizes per file type *
FileType                                           Size                
application/vnd.google-apps.document               10.00MB             
application/vnd.google-apps.spreadsheet            100.00MB            
application/vnd.google-apps.presentation           100.00MB            
application/vnd.google-apps.drawing                2.00MB              
application/pdf                                    4.77TB              
*                                                  4.77TB              

Feature                        Request limit (queries/second)
ocr                            0.000000                      
translation                    2.000000

Now you need to make a cronjob that will delete the snapshot images that are older from a specific threshold e.g. 2 days and then it will sync the ~/data/cloud directory to Google Drive. So, run:

crontab -e

And insert the following lines:

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin/go/bin:/home/raspcam/go/bin
50 * * * * yes | find /home/raspcam/data/cloud/ -name *.jpg -type f -mtime +2 -exec rm {} \; > /home/raspcam/logs/cleanold.log 2>&1
0 * * * * yes | drive push /home/raspcam/data/cloud/ > /home/raspcam/logs/cloudsync.log 2>&1 && cd /home/raspcam/data/cloud/ && yes | drive emptytrash

Yes, you need to empty the trash every time after you push the new images to the Google Drive because even if the old images are trashed they still occupy space on Google Drive. And that is the second reason why you should create a new Google account for the IP camera instead of using your own, you don't want the automatic emptying of the trash to also delete personal files that you manually deleted.

If you want to keep images older than 2 days you can replace the +2 with the number of days you want, but be careful the total images not to exceed the total size of your Google Drive or the size of your USB drive minus 1.5GB for the /var partition.

Step 7: Configuring the Firewall

Now it's time to configure the firewall, to do it the easy way you can use UFW which is a front-end for iptables:

sudo apt-get install ufw

And to configure it run the following commands:

sudo ufw allow 22/tcp
sudo ufw allow 8081/tcp
sudo ufw default deny
sudo ufw enable

The only ports that you need to be accessible are the port 22 so you will be able to SSH to your camera when you need to and 8081 so you can access the video steam of the camera, the rest of the ports are blocked.

Step 8: Boosting the Performance

There are a couple of things you can do to enhance the performance of your IP camera. The first is to disable the motion's motion detection if you don't need it. This is done through a web interface accessible on port 8080 but for security reasons this port has been blocked from the firewall. But, you can still access it locally so you can disable the motion detection using a simple curl command:

sudo apt-get install curl
curl http://admin:admin@127.0.0.1:8080/0/detection/pause

But you don't want to run this command by hand every time the Pi reboots. So you can simply add it in your rc.local by running:

sudo nano /etc/rc.local

And just before the line:

exit 0

Put the line:

curl http://admin:admin@127.0.0.1:8080/0/detection/pause 1>&2 > /home/raspcam/logs/disable_motion_detection.log

A second thing you can do is to overclock the Raspberry Pi. To do this run:

sudo raspi-config

From the menu select the Overclock option and then the Modest setting. Finally, select Finish to save the changes and answer yes to the questing if you want to reboot now. After the reboot reconnect to your Pi again through SSH.

Step 9: Making the File System Read-Only

Now it's time to move the /var and /home partitions to an external USB drive and make the rest of the system read-only.

First thing you need to do is to temporally stop the motion, cron, ufw and rsyslog daemons so you will be able to move /home and /var partitions without having issues:

sudo /etc/init.d/motion stop
sudo /etc/init.d/ufw stop
sudo /etc/init.d/cron stop
sudo /etc/init.d/rsyslog stop

Next insert the USB drive to your Pi and create two ext4 partitions in it. One with 1.5GB size for the /var and a second one with the rest of the capacity for the /home. First you need to find the device name of the USB drive, so run:

sudo fdisk -l

You will get an output like the following:

Disk /dev/mmcblk0: 7860 MB, 7860125696 bytes
4 heads, 16 sectors/track, 239872 cylinders, total 15351808 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1              16      250047      125016    b  W95 FAT32
/dev/mmcblk0p2          250048    15351807     7550880   83  Linux

Disk /dev/sda: 8004 MB, 8004304896 bytes
35 heads, 21 sectors/track, 21269 cylinders, total 15633408 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1              32    15633407     7816688    b  W95 FAT32

In my case the USB drive is the /dev/sda.

Next run fdsik to manage the partitions of the USB drive:

sudo fdisk /dev/sdX

Where X is the letter that corresponds to the USB drive device e.g. a.

Then delete any existing partitions by running:

d /dev/sdXY

e.g.

d /dev/sda1

Now you need to create a new partition. To do that type:

n

And hit Enter. Then:

p

And hit Enter. Type:

1

And hit Enter again. Hit Enter once again to accept the default sector, which is the first free sector on the disk.

Type:

+1536M

And hit Enter. Now the partition for /var is ready. Likewise for the partition for /home:

n <Enter>
p <Enter>
2 <Enter>
<Enter>
<Enter>

And a second partition with the remaining space is going to get created. If you now type p and hit Enter you should see an output similar to the following:

Disk /dev/sda: 8004 MB, 8004304896 bytes
35 heads, 21 sectors/track, 21269 cylinders, total 15633408 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1            2048     3147775     1572864   83  Linux
/dev/sda2         3147776    15633407     6242816   83  Linux

If everything seems OK save the changes and exit fdisk by typing:

w <Enter>

Now that the partitions have been created you need to format them as ext4. To do that run the following commands:

sudo mkfs.ext4 /dev/sdX1
sudo mkfs.ext4 /dev/sdX2

Now you need to update fstab to point the mounting points of /var and /home to the new partitions. But before doing that you need first to know the UUIDs of the two partitions you just created. To list all the UUIDs run:

sudo blkid

You will get an output like the following:

/dev/mmcblk0p1: SEC_TYPE="msdos" UUID="63E4-85SE" TYPE="vfat" 
/dev/mmcblk0p2: UUID="eefa3c42-1n08-4107-a6b7-84f3d6ec1bed" TYPE="ext4" 
/dev/sda1: UUID="07794ca2-2091-4de2-c7fb-6871af55nd3c" TYPE="ext4" 
/dev/sda2: UUID="db6p8bcc-66e6-4cb8-88e0-70d4b38bc628" TYPE="ext4"

To edit the fstab run:

sudo nano /etc/fstab

And replace its contents with the following:

# microSD
/dev/mmcblk0p1 /boot vfat defaults,ro 0 2
/dev/mmcblk0p2 / ext4 ro,errors=remount-ro,noatime 0 1

# USB Drive
UUID=<the-UUID-of-/dev/sdX2> /home ext4 defaults 0 2
UUID=<the-UUID-of-/dev/sdX1> /var ext4 defaults,noatime 0 2

Make sure to put the appropriate UUIDs where needed.

Next, you need to move all the files from /var to the /dev/sdX1 partition and all the files from /hometo the /dev/sdX2 partition. First mount temporarily /dev/sdX1 to /mnt.

sudo mount /dev/sdX1 /mnt

And then:

sudo cp -rp /var/* /mnt/
sudo rm -rf /var/*
sudo umount /mnt

After that do the same for /home:

sudo mount /dev/sdX2 /mnt
sudo cp -rp /home/* /mnt/
sudo rm -rf /home/*
sudo umount /mnt

Now reboot you Raspberry and after the reboot reconnect again to it through SSH:

sudo reboot

After you have connected to your Pi once again, run:

df -h

You should get an output like the following:

Filesystem      Size  Used Avail Use% Mounted on
rootfs          7.0G  406M  6.2G   7% /
udev             10M     0   10M   0% /dev
tmpfs            38M  116K   38M   1% /run
/dev/mmcblk0p2  7.0G  406M  6.2G   7% /
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs            75M     0   75M   0% /run/shm
/dev/mmcblk0p1  122M   40M   82M  33% /boot
/dev/sda2       5.8G   51M  5.4G   1% /home
/dev/sda1       1.5G  185M  1.2G  14% /var
tmpfs            75M     0   75M   0% /tmp

Now all the partitions in the microSD are read-only and only the partitions on the USB drive are read-write. But, there is one last thing that would be useful to do. Since Raspberry Pi is actually a fully functional computer that runs an actual operating system, you may want from time to time to install new software using apt-get or do updates. But since the file system is now read-only you will have to remount it as read-write every time and when you are done remount is as read-only again. This might be a little annoying so to get rid of this problem you can create a simple script that will run every time you use apt and do all the job for you.

At fist, temporarily make the root file system read-write so you can create the script:

sudo mount -o remount,rw /

Then run:

sudo nano /etc/apt/apt.conf

And paste inside the following lines:

DPkg {
    // Auto re-mounting of a readonly /
    Pre-Invoke { "mount -o remount,rw /"; };
    Post-Invoke { "test ${NO_APT_REMOUNT:-no} = yes || mount -o remount,ro / || true"; };
};

Finally, remount as read-only the root partition again:

sudo mount -o remount,ro /

Now you will be able to use apt-get to run updates and install or remove new software without having to worry about making the root partition read-write first. But be careful, this script will make read-write temporarily only the root partition but not the /boot, that means if you want to update the kernel the apt-get is going to fail. In that case before running apt-get you will have to make the /boot manually read-write by running:

sudo mount -o remount,rw /boot

And when you are done you can run the following command to make the /boot partition again read-only

sudo mount -o remount,ro /boot

Updating the kernel on an embedded system that you may not have physical access is somewhat risky, so this will prevent accidental updating of the kernel unless you are sure you want to do it.

And you are finally done! At this point I highly recommend backing up your microSD card so you will be able to easily restore the system if you mesh something up in the future or clone it to another microSD if you want to make a second camera. Make sure to do a raw backup of your microSD that will also include the partition table and not just the files. If you don't now how to do a raw image backup of your microSD you may want to give this article a read. In the same way also make a raw backup of the USB drive.

Step 10: Assembling the Camera

Now that you are done with the software part is time to assemble the camera.

Preparing the POE Splitter:

First thing you need to do it to take the POE splitter and crack it open to remove its PCB. You are interested only in the PCB so you can throw the plastics away.

Next you need to modify the PCB a little, start by desoldering the barrel power jack and the slide switch. Then, take the two female to female jumper wires and cut them in half. In place of the power jack solder two of the half jumper wires on the negative side and the two other on the positive side. The reason for using two jumper wires on each side instead of just one is to increase the maximum current they can deliver.

Finally, take a small piece of solid core wire and solder it between the first and the third contact of the slide switch you just desoldered (see the second attached photo). That way the POE splitter will be set to supply constantly 5V.

Preparing the Housing:

Next you need to prepare the housing for the camera. Start by completely disassembling the dummy camera you are going to use for the housing.

When you are done, take the piece of the housing that has the AA battery holder on it and using your dremel cut around the edges to remove it. You have to remove the battery holder because it occupies a lot of space inside the housing and with it in the way you can't fit both PCBs inside.

After that, you need to make a square hole for the input Ethernet connector of the POE splitter on the back piece of the housing. So take the POE splitter PCB, place it on top of the back piece so see where exactly you need to make the hole (is going to be on the upper right corner, see photo) and using your dremel again cut the square hole. Finally, check that the connector fits in the hole.

Connecting the Raspberry Pi with the POE Splitter:

To connect your Pi with the POE splitter first you need a very small Ethernet cable. The cable must be around 9cm including the RJ45 plugs. I'm not going to describe how to crimp a UTP cable because this not the subject of this instructable, but there are already many tutorials on the web that demonstrate the process. Because the length of the cable is critical take your time, if you don't succeed on the first try don't worry just try again.

After you have crimped and tested the cable connect the one end to your Pi and the other end to the output of your POE splitter, then fold them in order to form a U shape. Now put the two PCBs on top of the back piece of the housing and verify that they fit. Finally, disconnected the Ethernet cable from the POE splitter and your Pi, get the POE splitter, secure it in place with hot glue and let it cool.

After the hot glue has cooled before doing anything else plug in the microSD to your Pi if you haven't already. Ir order to earn some extra space the Raspberry Pi is going to get powered through the GPIO header instead of the micro USB connector. To power your Pi though the GPIO header connect the two positive jumper wires to the pins 2 and 4 of the GPIO header, and the two ground jumper wires to the pins 6 and 9.

Next, connect the two PCBs together with the small Ethernet cable you made. Finaly, plug the USB drive to the Pi if you haven't already.

Attaching the Camera Module:

Next step is to attach the camera module to the housing. First take the plastic piece with the fake LEDs and put the camera module in the hole to mark were you need to open the holes. Drill the holes and using screws secure into place the camera module.

Now, take all the front pieces of the housing and reassemble them. Lastly, connect the camera module to the Raspberry Pi using the ribbon cable.

Next, get the top and bottom piece of the housing, attach them to the back piece of the housing and screw them in place. On the other side screw in place the front side of the housing. Assemble the remaining parts of housing the base and you are done!

Step 11: So What's Next?

Don't forget that this IP camera is not just any IP camera but a fully functional Linux computer. You can do with it anything you can with a normal computer that runs Linux, the only limit is your imagination.

Some ideas about extending the project are the following:

  • Stream and/or record audio - You can very easily add a microphone to the camera and apart from streaming video also stream sound. You can also record audio files and upload them to Google Drive together with the snapshots that motion takes.
  • Talk to people - Another idea is to add a small speaker to your camera so you can talk to people remotely. This would be useful if you own for example a small business and you want to easily interact with your employees when you are not there. e.g. In case you notice something wrong while watching the video stream you can directly talk to your employees without having to call them.
  • Add motors! - A third idea is to add motors to your camera and control them remotely through a simple web interface. The only problem is that I don't see an easy way to mount motors on the housing I used, but you can search for another housing or even make your own if you have access to a 3D printer.
  • Add any sensor you want - You can add any sensor you can image to your camera (e.g. a temperature sensor) and make it take periodically measurements. Then you can make the measurements accessible through a web interface or even upload them to Google Drive.

You've got an idea about extending the project? Leave it in the comments!

Raspberry Pi Contest

Second Prize in the
Raspberry Pi Contest

Remix 2.0 Contest

Participated in the
Remix 2.0 Contest