To connect via RTSP:




If you are filtering outgoing connections, allow this outgoing ports to camera:

554 TCP

6970-6990 UDP

You can test RTSP stream with VLC media player.

Possible bug: When you connect to the camera with your phone, disconnect from it and then try to open rtsp stream in VLC media player, it will only load the first frame and stuck there. You need to reboot the camera, connect to rtsp with VLC media player without accessing it via mobile device.

Extra note: It’s advisable to block outgoing traffic from camera into internet. My camera is connecting to some IP with weird ports.

Quick whois showed me this IP belongs to I did not sniff the traffic, so I’m not sure if the nature of it is spyware. It’s probably their cloud service or some other service.

For the extra paranoid, physically disconnect the microphone on the camera:


Xerox phaser 3020 black ink percentage remaining – SNMP cacti data and graph template at the bottom of this post.


With some tweaks this method should also works for other brand printers.

With the help of this article: I could set up a cacti template for my Xerox 3020 printer. Some printers return ink level value in percents but in my case I got only the raw value.

1. Get SNMP toner max capacity value, OID for that is

root@cacti: snmpget -v2c -c public
SNMPv2-SMI::mib- = INTEGER: 700

700 is the raw value for 100% toner capacity.

2. Get SNMP toner current levels value, OID for that is

root@cacti: snmpget -v2c -c public
SNMPv2-SMI::mib- = INTEGER: 686

686 is the current raw value of my toner levels. To calculate toner ink percentage remaining we need to divide current raw value (686) with max raw value (700) and multiply it by 100. 686 / 700 * 100 = 98 (percentage of ink remaining). Since the max raw value is a nice number (700), we can just divide current raw value with 7, 686/7 = 98. We can use this formula for our CDEF definitions in cacti later. Remember, this is only for Xerox 3020, other brand printers can output different raw values and you need to correct this formula accordingly.

Xerox 3020 ink remaining percentage formula: raw_current_ink_level / 7

3. Login to cacti and go to Console -> Presets -> CDEFs

Click plus sign and create new CDEF and name it Xerox toner percentage

Click plus at CDEF Items.

CDEF Item Type: Special Data Source

CDEF Item Value: Current Graph Item Data Source

Click Save

Click plus at CDEF Items.

CDEF Item Type: Custom String

CDEF Item Value: 7 (this is the value cacti will use to divide raw data)

Click Save

Click plus at CDEF Items.

CDEF Item Type: Operator

CDEF Item Value: / (this will tell cacti to use a divide operation with the custom string we defined in a previous step).

Click Save

4. Go to Console -> Templates -> Data Source

Click plus to create new data source template and name it Printer – black toner current

Name: |host_description| – black toner current

Data Input Method: Get SNMP Data

Data Source Active: tick the right box

Internal Data Source Name: toner_current

Click Create

New Custom Data field will appear.


Click Save

5.1 Go to Console -> Templates -> Graph

Click plus sign

Name: Printer – black toner levels

Title: Printer – black toner levels

Vertical Label: percent

Tick Rigid Boundaries Mode

Upper Limit: 100

Click Create

5.2 Now click plus sign at Graph Template Items

Graph Item Type: AREA

Data Source: Printer – black toner current

Color: select what you like

Consolidation Function: AVERAGE

CDEF Function: Xerox toner percentage

Text Format: Available

Click save

Add another Graph template item

Graph Item Type: GPRINT

Data Source: Printer – black toner current

Consolidation Function: LAST

CDEF Function: Xerox toner percentage

GPRINT Type: Percent(Round down to the nearest decimal)

Text format: Current:

Click Save

Add another Graph template item

Graph Item Type: LINE1

Data Source: Printer – black toner current

Consolidation function: AVERAGE

CDEF function: Xeror toner percentage


Your graph is now ready to device assignment.

Final result:

Download data and graph templates for xerox phaser 3020:

xerox_3020_cacti_toner_level_template [Dropbox mirror]




  1. SSH login to QNAP
  2. Identify virtual switch you want to put into monitoring mode, in my case qvs1
  3. Set ageing to 0
brctl show
brctl setageing qvs1 0

My example:

I’ve created a virtual machine  (SecurityOnion) on my QNAP virtualization station to monitor my home network traffic. I have setup a port mirroring on my switch to send all traffic to the QNAP ethernet adapter number 2. (My QNAP has 4 ethernet adapters). Sniffing OS usually needs two ethernet adapters, one for management and one dedicated for monitoring (sniffing). I’ve created a new virtual switch in QNAP with adapter number 2 and set it to external mode (no IP address), then I assigned this virtual switch to monitoring interface in SecurityOnion. I should’ve been able to see all the traffic now, but that wasn’t the case. There were no packets flowing to my monitoring ethernet adapter. After some investigating I found out a reddit user had the same problem. This is the solution:

SSH into your QNAP with your admin username and credentials. Check your virtual switches with a command “brctl show“, this will list all virtual switches you created. Now you need to select the virtual switch you assigned to your sniffing ethernet adapter in my case, that was adapter number 2 and run the following command: “brctl setageing qvs1 0″, where qvs1 is the number of your selected virtual switch (one that will do the sniffing, in my case adapter 2, identified as qvs1). That’s it, you should see all packets on the sniffing interface now. Thanks go to the reddit user I don’t want to name due privacy concerns.

SecuritOnion is now receiving packets on the monitoring interface:

Side note: Sniffing and analyzing traffic is heavy on CPU, HDD and RAM resources. Qnap is not a suitable candidate for that. My Qnap tests showed a CPU bottleneck (quad core celeron N3160) averaging around 70% cpu usage with low network traffic and less than 20 devices on the network.

I wanted to limit upload speed of my torrent clients (utorrent, qbittorent) with port forwarding enabled. This can be done on the client itself but I prefer the method via firewall.

For this example I forwarded port 17123 to my qbittorent client and limited upload speed to 1mbit/s. There are probably other more “proper” methods to achieve this on Pfsense, but this is working for me:

Set up a port in a client:

Go to Pfsense, Firewall, traffic shaper, limiters:

Click New limiter

Tick Enable limiter and its children

Name it upload1mbit

Set Bandwidth to 1 Mbit/s

Set Mask to Source addresses and set Description to something you like and save.

For limiters to work you also need to make a download limiter. Click new limiter and name it download1000mbit

Set bandwidth to 1000 Mbit/s

Set mask to Destination addresses

Set description and click save.

Now go to firewall, NAT and add a new rule:

Interface: WAN

Protocol: Depends on your needs, usually TCP, UDP or both

Destination: WAN address

Destination port range: 17123 to 17123

Redirect target IP: LAN IP of the machine torrent client is running on, example

Redirect target port: 17123

Description: Torrents

Click Save


Now go to firewall, rules, WAN and find the associated rule we created in the previous step, click edit.

Scroll down to the bottom and click Display Advanced, scroll down again to find In / Out pipe.

For In select download1000mbit, and for out select upload1mbit, save and apply changes. This is the opposite of what you do when you want to limit LAN IP bandwidth, because this rule is applied to WAN interface not LAN. Click save and the limiter should work. You should always reset the states when applying new settings to filters. You can do that on Diagnostics, states, reset states.

I will add more images later, this is only a quick draft. It should be sufficient to set up a rule though.


# Rtsp to youtube streaming with ffmpeg

VBR="1000k" # Bitrate of the output video, bandwidth 1000k = 1Mbit/s
QUAL="ultrafast" # Encoding speed
YOUTUBE_URL="rtmp://" # RTMP youtube URL
THREADS="0" # Number of cores, insert 0 for ffmpeg to autoselect, more threads = more FPS

VIDEOCHANNEL="videoSub" # videoMain and VideoSub for Foscam cameras

KEY="xxx-xxxx-xxxx-xxxx" # Youtube account key

# To download fonts
# wget -O /usr/local/share/fonts/ "";unzip

# Text allingment

# Other
box="1" # enable box
boxcolor="black@0.5" # box background color with transparency factor
reloadtext="1" # Reload textfile after each frame, usefull for overlaying changing data 
# like weather info. To update the textfile while streaming, you need to use mv command or a crash
# is going to happen when you update the textfile.
# Example:
# wget -q -O - | grep somevalue > ffmpegraw.txt; mv ffmpegraw.txt ffmpeg.txt

# Ffmpeg with drawtext, 
    ffmpeg -loglevel panic \
    -f lavfi -i anullsrc \
    -rtsp_transport tcp \
    -i "$SOURCE" \
    -vcodec libx264 -pix_fmt yuv420p -preset $QUAL -g 20 -b:v $VBR \
    -vf "drawtext="fontfile=${FONT}":textfile=${textfile}:x=${x}:y=${y}:reload=${reloadtext}: \
    fontcolor=white:fontsize=${FONTSIZE}:box=${box}:boxborderw=${boxborderwidth}:boxcolor=${boxcolor}" \
    -threads $THREADS -bufsize 512k \
    -f flv "$YOUTUBE_URL/$KEY"

# Copy stream only, don't encode
#ffmpeg \
#    -f lavfi -i anullsrc \
#    -rtsp_transport tcp \
#    -i "$SOURCE" \
#    -vcodec libx264 -pix_fmt yuv420p -preset $QUAL -g 20 -c:v copy -b:v $VBR \
#    -f flv "$YOUTUBE_URL/$KEY"

Overlayed data over webcam stream example:

To run the script in background you need to add nohup otherwise ffmpeg will hang.

nohup bash &

Ffmpeg likes to crash from time to time. Create a script to check for ffmpeg process and restart it if there is no process running.

# Description: Checks for existing ffmpeg process and starts one if needed

if ! pgrep -x "ffmpeg" > /dev/null
    /bin/bash $script > /dev/null 2>&1 &

Save script as

chmod +x

Run the script with crontab every minute.

crontab -e
* * * * * sudo bash /path_to_script/

1. Make sure .well-known and acme-challenge directories are set permissions to 755

2. Create random file test.txt in .well-known/acme-challenge/ and try to view it with browser

If all of this is good, your certificate should renew. The problem I had on my server is that even when step 1. and 2. were ok and working, I still  got permission denied message. The problem was I setup my Varnish engine to force SSL on non SSL request. When bot requested it was automatically redirected to So,

3. Make sure you disable force SSL during renewal.

Error message example:

Failed authorization procedure. (http-01): urn:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from "<!DOCTYPE html>
<title>403 Forbidden</title>
<h1>Error 403 Forbidden</h1>

EDIT: I have experienced some lag with webm streaming, scroll down for swf configuration.

Live stream camera (Foscam in my case) over the internet cheat sheet:

apt-get install software-properties-common
add-apt-repository ppa:mc3man/trusty-media
apt-get update
apt-get install ffmpeg

Create ffserver.conf file

nano /etc/ffserver.conf
HTTPPort 8090 # Port to bind the server to
MaxHTTPConnections 2000
MaxClients 15
MaxBandwidth 50000 # Maximum bandwidth per client
 # set this high enough to exceed stream bitrate
CustomLog -

<Feed feed1.ffm>
 File /tmp/feed1.ffm
 FileMaxSize 1g
 ACL allow localhost
 ACL allow

<Stream live.webm>
 Format webm
 Feed feed1.ffm

 VideoCodec libvpx
 VideoSize 640x480
 VideoFrameRate 30
 VideoBitRate 512
 VideoBufferSize 512
 AVOptionVideo flags +global_header


<Stream status.html> # Server status URL
 Format status
 # Only allow local people to get the status
 ACL allow localhost
 ACL allow

<Redirect index.html> # Just an URL redirect for index
 # Redirect index.html to the appropriate site
 URL live.webm/

Save, exit and start the services

ffserver > /dev/null 2>&1 &
ffmpeg -loglevel error -r 30 -i rtsp://user:pass@camera_IP:port/url http://LAN_IP_WHERE_FFSERVER_IS_RUNNING:8090/feed1.ffm /dev/null 2>/var/log/ffmpeg.log &

Visit http://LAN_IP_WHERE_FFSERVER_IS_RUNNING:8090/live.webm
For status go to http://LAN_IP_WHERE_FFSERVER_IS_RUNNING:8090/status.html

I have experienced some lag with the above configuration, here is the config for a swf streaming:

HTTPPort 8090 # Port to bind the server to
MaxHTTPConnections 2000
MaxClients 15
MaxBandwidth 50000 # Maximum bandwidth per client
 # set this high enough to exceed stream bitrate
CustomLog -

<Feed feed1.ffm>
 File /tmp/feed1.ffm
 FileMaxSize 1g
 ACL allow localhost
 ACL allow

<Stream live.ffm>
 Feed feed1.ffm

Format swf
VideoCodec flv
VideoFrameRate 30
VideoBufferSize 80000
VideoBitRate 100
# quality ranges - 1-31 (1 = best, 31 = worst)
VideoQMin 1
VideoQMax 5
VideoSize 1024x786
PreRoll 0


<Stream status.html> # Server status URL
 Format status
 # Only allow local people to get the status
 ACL allow localhost
 ACL allow

<Redirect index.html> # Just an URL redirect for index
 # Redirect index.html to the appropriate site
 URL live.ffm/

Save and restart ffserver and ffmpeg.

Edit your index.html file to play swf file in the browser:

<meta charset="UTF-8">
<link rel="icon" href="favicon.ico" type="image/x-icon" />
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
<title>Site title</title>
<script type="text/javascript" src="swfobject.js"></script>
 <script type="text/javascript">
 swfobject.registerObject("myFlashContent", "9.0.0", "expressInstall.swf");
 <script type="text/javascript">
 swfobject.embedSWF("http://FF_SERVER_IP:8090/live.ffm", "myContent", "1024", "786", "9.0.0");
<p align="top">Some optional text.</p>
 <div id="myContent">
 <p>Live stream</p>


The rpisystat script will report the following system parameters to your LCD:

  • Internal IP
  • External IP
  • CPU temperature
  • GPU temperature
  • CPU usage
  • Memory usage
  • Free disk space
  • Incoming and outgoing network traffic

You need:

1. Breadboard with T-Cobbler (or connect the wires directly)
2. 16×2 LCD board
3. Adjustable resistor (potentiometer) for adjusting LCD contrast

1. Wiring (source:×2-lcd-directly-with-a-raspberry-pi/wiring):

Pin #1 of the LCD goes to ground (black wire)
Pin #2 of the LCD goes to +5V (red wire)
Pin #3 (Vo) connects to the middle of the potentiometer (orange wire)
Pin #4 (RS) connects to the Cobbler #25 (yellow wire)
Pin #5 (RW) goes to ground (black wire)
Pin #6 (EN) connects to Cobbler #24 (green wire)
Skip LCD Pins #7, #8, #9 and #10
Pin #11 (D4) connects to cobbler #23 (blue wire)
Pin #12 (D5) connects to Cobbler #17 (violet wire)
Pin #13 (D6) connects to Cobber #21 (gray wire)
Pin #14 (D7) connects to Cobber #22 (white wire)
Pin #15 (LED +) goes to +5V (red wire)
Pin #16 (LED -) goes to ground (black wire)


This schematics is for RaspberryPi 1 version, but you can connect to the same pins on RaspberryPi 2 (picture bellow).


2. Software

Download required packages:

sudo apt-get update
sudo apt-get install python-dev python-setuptools python-pip git
sudo easy_install -U distribute
sudo pip install rpi.gpio

Download my scripts:

sudo git clone git://
cd 16-2-LCD-rpisystat
sudo ./

Make sure you edit to match your GPIO pins (default is for the wiring above). Also edit and to match your network adapter.

Check the display in action:





  • RasberryPi 2
  • AM2302 humidity/temperature sensor
  • Some wires from old PCs to connect sensor with RaspberryPi


  • Raspbian OS
  • Nginx
  • Munin
  • WiringPi
  • Lol_dht22

1. Solder wires to the sensor like on the picture above, and connect them to the correct pins:

Pin 1 on the AM2302 to pin 1 (+3.3V) on the GPIO connector (labeled P1 on the raspi)
Pin 2 on the AM2302 to pin 7 (GPIO 4) on the GPIO connector
Pin 4 on the AM2302 to pin 9 (Ground) on the GPIO connector

For detailed instructions, check this blog up to step 4:

All shell commands will be run as root, so I will not use sudo.

2. Install Nginx (web server)

apt-get update
apt-get install nginx php5-fpm

3. Install Munin

Muning is a monitoring tool for sysadmins. It creates graphs to monitor various parameters. We will configure munin to display AM2302 sensor in graphs.

apt-get install munin munin-node munin-plugins-extra

Edit munin configuration file:

pico /etc/munin/munin.conf
 use_node_name yes

4. Configure Nginx virtual host. Dynazoom will work with this config.

pico /etc/nginx/sites-enabled/default or pico /etc/nginx/sites-enabled/
server {
        listen 443 ssl;
        ssl_certificate /etc/nginx/ssl/;
        ssl_certificate_key /etc/nginx/ssl/;
        root "/var/cache/munin/www/";
        auth_basic            "Private access";
        auth_basic_user_file  /etc/munin/munin_htpasswd;

        location ^~ /munin-cgi/munin-cgi-graph/ {
                fastcgi_split_path_info ^(/munin-cgi/munin-cgi-graph)(.*);
                fastcgi_param PATH_INFO $fastcgi_path_info;
                fastcgi_pass unix:/var/run/munin/spawn-fcgi-munin-graph.sock;
                include fastcgi_params;

        location /static/ {
                alias /etc/munin/static/;

5. Generate SSL cert

mkdir /etc/nginx/ssl
openssl req -subj '/' -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/ -out /etc/nginx/ssl/

6. Generate website password

apt-get install apache2-utils
htpasswd -c /etc/munin/munin_htpasswd admin

You will be promted to enter a new password.

7. Add common modules to munin

cd /usr/share/munin/plugins
wget -O pisense_
chmod a+x pisense_
ln -s /usr/share/munin/plugins/pisense_ /etc/munin/plugins/pisense_temp
ln -s /usr/share/munin/plugins/pisense_ /etc/munin/plugins/pisense_clock
pico /etc/munin/plugin-conf.d/munin-node
user root

8. Configure AM2302 prerequisites

apt-get install git-core
cd /opt/
git clone git://
cd wiringPi
cd /opt/
git clone
cd lol_dht22

9. Create plugins for munin

pico /etc/munin/plugins/DHT22-humidity

case $1 in
 cat <<'EOM'
graph_title Relative humidity
graph_vlabel Percent
graph_category AM2302
humidity.label RH
humidity.draw AREASTACK
humidity.colour 3E9BFB
 exit 0;;

printf "humidity.value "
/opt/lol_dht22/loldht 7 | grep -i "humidity" | cut -d ' ' -f3
chmod +x /etc/munin/plugins/DHT22-humidity
pico /etc/munin/plugins/DHT22-temperature

case $1 in
 cat <<'EOM'
graph_title Temperature
graph_vlabel Celsius
graph_category AM2302
temperature.label Celsius
temperature.label Temperature
temperature.draw AREASTACK
temperature.colour 00FF00
 exit 0;;

printf "temperature.value "
/opt/lol_dht22/loldht 7 | grep -i "temperature" | cut -d ' ' -f7
chmod +x /etc/munin/plugins/DHT22-temperature
pico /etc/munin/plugin-conf.d/munin-node

Add this to the end of the file:

user root

10. Enable Dynazoom for graphs

apt-get install spawn-fcgi libcgi-fast-perl
pico /etc/init.d/munin-fastcgi
#! /bin/sh

# Provides: spawn-fcgi-munin-graph
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: starts FastCGI for Munin-Graph
# --------------------------------------------------------------
# Munin-CGI-Graph Spawn-FCGI Startscript by Julien Schmidt
# eMail: munin-trac at
# www:
# --------------------------------------------------------------
# Install: 
# 1. Copy this file to /etc/init.d
# 2. Edit the variables below
# 3. run "update-rc.d spawn-fcgi-munin-graph defaults"
# --------------------------------------------------------------
# Special thanks for their help to:
# Frantisek Princ
# Jérôme Warnier
# --------------------------------------------------------------
# Last Update: 14. February 2013
# Please change the following variables:

DAEMON_OPTS="-s $SOCK_FILE -F $FCGI_WORKERS -U $SOCK_USER -u $FCGI_USER -g $FCGI_GROUP -P $PID_FILE -- /usr/lib/munin/cgi/munin-cgi-graph"

# --------------------------------------------------------------
# No edits necessary beyond this line
# --------------------------------------------------------------

if [ ! -x $DAEMON ]; then
 echo "File not found or is not executable: $DAEMON!"
 exit 0

status() {
 if [ ! -r $PID_FILE ]; then
 return 1
 for FCGI_PID in `cat $PID_FILE`; do 
 if [ -z "${FCGI_PID}" ]; then
 return 1
 FCGI_RUNNING=`ps -p ${FCGI_PID} | grep ${FCGI_PID}`
 if [ -z "${FCGI_RUNNING}" ]; then
 return 1
 return 0
start() {
 if status; then
 echo "FCGI is already running!"
 exit 1

stop () { 
 if ! status; then
 echo "No PID-file at $PID_FILE found or PID not valid. Maybe not running"
 exit 1
 # Kill processes
 for PID_RUNNING in `cat $PID_FILE`; do
 kill -9 $PID_RUNNING
 # Remove PID-file
 rm -f $PID_FILE
 # Remove Sock-File
 rm -f $SOCK_FILE

case "$1" in
 echo "Starting $NAME: "
 echo "... DONE"

 echo "Stopping $NAME: "
 echo "... DONE"

 echo "Stopping $NAME: "
 echo "Starting $NAME: "
 echo "... DONE"
 if status; then
 echo "FCGI is RUNNING"
 echo "Usage: $0 {start|stop|force-reload|restart|status}"
 exit 1

exit 0
chmod 755 /etc/init.d/munin-fastcgi
update-rc.d munin-fastcgi defaults
/etc/init.d/munin-fastcgi start

11. Restart daemons and visit your munin site


/etc/init.d/nginx restart

/etc/init.d/munin-node restart

Go to


Check how to add dewpoint graph on my next post.