In this post we will show you how to set up a standard USB webcam with a Raspberry Pi (RPI) and the Nabto platform for easy access and high security: There are already many good guides out there that demonstrate how to setup a webcam with the RPI – but they all leave the reader with a combination of firewall hassle and very poor security: You will have to setup port forwarding in the WAN router to access the RPI and there is no encryption or access control. So a lot of hassle and risk of strangers peeking through your webcam.

With a few additional, simple steps as compared to these existing guides, you can eliminate the firewall hassle, add strong encryption and a robust access control mechanism – Nabto to the rescue!

RPI + Logitech C270

Once you are done, you will be able to securely access your RPI Webcam from anywhere through the Nabto Video App – without any firewall fiddling or messing with DynDNS and self-signed certificates. As you will see below, the apps are freely available from the app stores – and the source code is available so you can tweak yourself. It is a hybrid app, so you can make many interesting changes and additions by just knowing basic HTML.

What you need

  1. A Raspberry Pi board with a Raspbian image installed. We have tested with 2nd and 3rd generation boards, 1st generation will most likely also work like a charm. raspberry-pi-3-hero-1-1571x1080
  2. A camera connected to the PI, this guide assumes a USB webcam but you can use anything that works with the Motion software package, including Raspberry Pi camera modules.
  3. An iOS or Android device.
  4. An Nabto Cloud Console account – create one for free on, no credit card necessary and you can add several devices completely free of charge for development, testing, home and educational use.


Step 1: Log on to the RPI

Log on to your RPI, either directly if you have it connected to a display with keyboard or through ssh from a computer on your network:

$ ssh [email protected]
[email protected]'s password:
Last login: Sat Sep 9 09:14:12 2017 from mclappe2.home
[email protected]:~ $

The default password for the pi user is raspberry.


Step 2: Install software

The following must be installed:

  • Motion – webcam software
  • CMake, Git and Ninja – to build the Nabto remote access software

Log on to the RPI as described above and perform the following steps:

$ sudo apt-get update
Fetched 9,707 kB in 22s (439 kB/s)
Reading package lists... Done
$ sudo apt-get install motion
$ sudo apt-get install git cmake ninja-build
Unpacking ninja-build (1.3.4-1.2) ...
Processing triggers for man-db (2.7.5-1~bpo8+1) ...
Setting up ninja-build (1.3.4-1.2) ...

If you already have a running webcam and just want to setup remote access, only lines 1 and 7 are necessary.

Step 3: Configure the webcam software

In this step we must edit two configuration files on the RPI. If you have a favorite editor and know your way around, just do the following:

  • set “daemon on” and “stream_localhost on” in /etc/motion/motion.conf
  • set “start_motion_daemon=yes” in /etc/default/motion

For a bit more detail:

Log on to the RPI as described above and start the nano editor in the console to enable the webcam software to run as a background service:

[email protected]:~ $ sudo nano /etc/motion/motion.conf

The nano editor on the RPI. It is highly recommended to learn another editor like vi or emacs if you are going to edit a lot of files - but nano seems a popular choice in tutorials.Change “daemon off” to “daemon on” (the line with the cursor above).

Next, as an extra security measure, you can disable insecure remote access to the camera. You can do this by setting “stream_localhost on” in the same file (when we install the secure remote access software in a moment, it will access the camera from localhost):

Screen Shot 2017-09-09 at 19.29.17.pngThe tricky part is to exit this nano editor … press “control-x” (to exit), press “y” (to save) and press enter (to use the default suggested filename).

Next, we must start the webcam software when the RPI boots:

[email protected]:~ $ sudo nano /etc/default/motion

Screen Shot 2017-09-09 at 19.22.02

Set “start_motion_daemon=yes” and exit as described above (control-x, “y”, enter).

Finally, start the webcam service:

[email protected]:~ $ sudo service motion start


Step 4: Build the remote access software

Perform the following steps on the RPI (ie, log on to the device or continue in the shell from above).

First, retrieve the remote access source code from the github repo

$ mkdir git
$ cd git
$ git clone
Cloning into 'unabto'...
remote: Counting objects: 5745, done.
remote: Total 5745 (delta 0), reused 0 (delta 0), pack-reused 5745
Receiving objects: 100% (5745/5745), 2.63 MiB | 1.55 MiB/s, done.
Resolving deltas: 100% (3388/3388), done.

Next,  run cmake to prepare the build of the uNabto tunnel service. The key step in line 4 below is quite long, so scroll a bit to see it all or look below where we have zoomed in on it:

$ cd unabto/apps/tunnel
$ mkdir build
$ cd build
$ cmake -DCMAKE_BUILD_TYPE=Release -DUNABTO_CRYPTO_MODULE=openssl_armv4 -DUNABTO_RANDOM_MODULE=openssl_armv4 -GNinja ..
-- The C compiler identification is GNU 4.9.2
-- The ASM compiler identification is GNU
-- Found assembler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc
-- Generating done
-- Build files have been written to: /home/pi/git/unabto/apps/tunnel/build

The cmake invocation in step 4 looks as follows:

cmake -DCMAKE_BUILD_TYPE=Release \
-DUNABTO_CRYPTO_MODULE=openssl_armv4 \
  -DUNABTO_RANDOM_MODULE=openssl_armv4 -GNinja ..

Just FYI – the Ninja tool used is an alternative to standard make tool; it builds much faster on the RPI than make, likely because Ninja has optimized filesystem access on the quite slow RPI.

Now you can build the tunnel:

[email protected]:.../build $ ninja
[77/77] Linking C executable unabto_tunnel

Check you can execute the unabto_tunnel binary (./unabto_tunnel) and copy the resulting binary into /usr/bin:

[email protected]:.../build $ sudo cp unabto_tunnel /usr/bin


Step 5: Create a Nabto device

For this step, you need an Nabto Cloud Console account – go to and sign up if you haven’t done so already.

Next, create a product – you don’t have to tick the “Free product” checkbox, you get a few regular licenses for free with your account (in this way you don’t have to see ads for the first devices you use).

Screen Shot 2017-09-09 at 20.29.24

Next, generate a license by clicking the “Generate license” button and enter 1 as quantity:

Screen Shot 2017-09-09 at 20.36.18

You now have everything you need to run the tunnel on the device – the device id and the key revealed when clicking “Show License Key” are used in the next step:

Screen Shot 2017-09-09 at 20.38.32

Step 6: Configure the tunnel

Log on to the RPI or continue your session above. Edit the file ./git/unabto/apps/tunnel/scripts/unabto_tunnel.conf:

[email protected]:~ $ cd git/unabto/apps/tunnel/scripts
[email protected]:.../scripts $ nano unabto_tunnel.conf

Replace the device id and key fields with what you retrieved from the Nabto Cloud Console in step 5:

Screen Shot 2017-09-09 at 22.01.07.png

The port number 8081 matches the default configuration of the Motion webcam service, change this if you use a different port number.

Install the startup script and config file from the scripts directory:

$ sudo cp unabto_tunnel.conf /etc
$ sudo cp unabto_tunnel_initd /etc/init.d/unabto_tunnel
$ sudo chmod +x /etc/init.d/unabto_tunnel
$ sudo update-rc.d unabto_tunnel defaults
$ sudo /etc/init.d/unabto_tunnel start

Now everything should be working like a charm! Before actually firing up the app and enjoying remote access to your webcam, let’s check everything looks ok:

$ ps auwwx | grep unabto_tunnel | grep -v grep
pi  16300 0.1 0.2 18428 1932 ? 21:00 0:00 /usr/bin/unabto_tunnel /usr/bin/unabto_tunnel -d -s -k

If nothing is seen as output of the ps command, go back to step 4 and make sure you can execute the binary after building it – and that you copied it into /usr/bin. If this does not help, write a comment below with your error message.

Also check the webcam service is running fine:

[email protected]:.../scripts $ ps auwwx | grep motion | grep -v grep
motion 15762 1.4 1.1 53716 10020 ?    Sl  20:31  1:13 /usr/bin/motion

If nothing is seen here, make sure everything was installed correctly in step 2. Also, check Motion’s FAQ.

Step 7: Access the webcam

Visit Apple’s App Store or Google Play to download the Nabto Video app. Start the app on the same network as the RPI to discover the device by tapping “Add new” and pair on the subsequent screens:

After pairing, you can see the actual webcam feed from anywhere – your communication with the camera is encrypted and only paired clients are allowed access. You can change settings for the device to control remote access:

On the security settings page, you should disable “Open for pairing” when you don’t want to allow further clients access to the camera. In the Access Control List you can see all the paired clients, ie who has access. You can delete the individual users with access by tapping the element.

Note that the “player” is extremely simple – it can only be used to show the default MJPG stream from the webcam. In a later blog post in this series we will add support for more advanced players for better video quality and also for adding sound.

You can download the source code for the player app from the ionic-starter-nabto-video github repo – it is a hybrid app you can edit by knowing just basic HTML. We will get back to this in a later post, demonstrating how to add new features to the webcam app.

Further Reading on Security

Some of you have asked for a bit of elaboration on how access control works in more detail and how we make sure only the intended users can access the device. It is a bit out of the scope to go into detail with in this post – but the Nabto Video app and the tunnel software installed on the RPI use the Nabto platform under the hood for communication.

The platform provides a few different ways to control access, in this project we use the “Paired Public Key Authentication” approach outlined in section 8.2 of TEN036 “Security in Nabto Solutions”. Basically this ensures that only clients that possess the private key of an RSA keypair where the public key has been installed on the RPI is allowed to access the camera. In addition to the introduction above, you can read more about it in the Fingerprint ACL module documentation in the uNabto SDK.

For a more general introduction to security in the Nabto platform, the remaining sections of TEN036 “Security in Nabto Solutions are a good read – and also, we have a short introduction in this blog post.


4 thoughts on “Secure App Access to Raspberry Pi Camera

  1. Rich says:

    Hey guys, awesome post!

    Was able to get everything working on a rasp 4.

    My only question is, how can I access the web interface to play with settings? I’m getting the video feed, but when I try to access the web interface from the local network, I get Err_connection_refused.

    And I apologize in advance, I’m a little new to raspberries! Thanks again

  2. Ulrik Gammelby says:

    Hi Rich,

    This app is very simple – the “player” is just an img tag that shows an MJPEG picture from the webcam. So to be able to show the web interface, you would need a more general tunnel.

    We have a general web view tunnel demo available here: (iOS) and here: (Android). And the source is available here: – perhaps you can combine the webview and “MJPEG player” apps into one. Or just use two different apps if it is a quick solution for a specific problem you have yourself.

    Note that whenever you are guided to use the AppMyProduct portal or console, use the modernized replacement at instead – you can retrieve the same device id and crypto key from there. As you can see, we still need to update some posts and documentation in this regard – sorry!


  3. Steve Ledonne says:

    What codec does motion use? Is there a way to view the camera stream via VLC instead of an app? What is the latency of the video? Is it video and audio or just video?

    What if I want to use PiCAM instead of motion?

Leave a Reply

Your email address will not be published. Required fields are marked *