Raspberry Pi And Docker

Two of the most powerful tools for modern computing in their own realm – Raspberry Pi and Docker. If you have not heard about them, google search on them would fetch plenty of amazing content on them. In brief, just to set the context for this blog, here it is:

Raspberry Pi –  a credit card sized computer with wired, wireless interfaces, powerful in it’s own way, lots of interfacing options through it’s GPIO pins, very good Linux distributions to complement the hardware. Based on the ARM architecture. To learn more visit: Raspberry

Docker – A modern software “tool”, multi platform, a platform of it’s own ( if you can call that?), built on the concept of containers. To learn more visit: Docker

Now, when you bring these two tools together, it is one heck of a combination – a pocket dynamite. It opens up a lot of things. 

Here in this blog, I will be demonstrating how to setup the docker environment on the Pi, build a small container from scratch, run the container. The container launches, queries a website for a PHP page which returns the IP address of the node from which the query was made.

Setting Up Docker on Raspberry Pi

Docker now provides a script to install on any platform. The script automatically detects the platform on which it is being installed. 

curl -sSL https://get.docker.com | sh

Wait for the installation to complete and make sure it gets installed without any errors or exceptions.

Configure Docker

Enable as system service and auto start: sudo systemctl enable docker
Starts docker as a service             : sudo systemctl start docker
Make sure you add docker as user       : sudo usermod -aG docker pi

Check if docker is running

docker --version

Build An Docker Image

Create a directory of your choice in the location of your choice:

mkdir docker_example
cd docker_example

Create the Dockerfile with the below contents:


FROM resin/rpi-raspbian:latest
ENTRYPOINT []

RUN apt-get update && \
apt-get -qy install curl ca-certificates

CMD ["curl", "http://pradeepclicks.com/myData/test.php"]

FROM – Docker standard statement telling docker to pick up the base system to start with and build on it. Here is it  resin/rpi-raspbian:latest
ENTRYPOINT [] – to take control of what the entry point is going be and override the default for the Resin image.
RUN – Docker standard to run commands. 
             Here the system is being prepared with tools to query a PHP page from command line. curl and  ca-certificates, SSL certificates are being installed on raspbian.
CMD – Start up command for this container, docker run invokes the lines followed by CMD. Here it is querying a PHP page on a website and printing it’s content on screen.

Build the Docker Image

sudo docker build -t my_docker
You will see an output like the below:
│Sending build context to Docker daemon 2.048kB
~ │Step 1/4 : FROM resin/rpi-raspbian:latest
~ │ ---> e60721112344
~ │Step 2/4 : ENTRYPOINT []
~ │ ---> Running in 488417056adf
~ │Removing intermediate container 488417056adf
~ │ ---> 31b00564ef03
~ │Step 3/4 : RUN apt-get update && apt-get -qy install curl ca-certificates
~ │ ---> Running in 334ef363e4f3
.
.
.
.
 │Fetched 13.7 MB in 1min 52s (122 kB/s)
~ │Reading package lists...
~ │Reading package lists...
~ │Building dependency tree...
~ │ca-certificates is already the newest version.
~ │curl is already the newest version.
~ │0 upgraded, 0 newly installed, 0 to remove and 11 not upgraded.
~ │Removing intermediate container 334ef363e4f3
~ │ ---> bce998306b8c
~ │Step 4/4 : CMD ["curl", "http://pradeepclicks.com/myData/test.php"]
~ │ ---> Running in b064a0f8b845
~ │Removing intermediate container b064a0f8b845
~ │ ---> 97c25308ed2b
~ │Successfully built 97c25308ed2b
~ │Successfully tagged my_docker:latest

Run the Docker image

sudo docker run my_docker

 ~ │You have visited from....[ 49.207.49.116 ]

 This completes the exercise. To summarize, we
1. Setup the docker environment of Raspberry Pi.
2. Configured docker on Raspberry Pi.
3. Created a Dockerfile with contents to query a webpage using curl, installing curl in the process.
4. Build the docker container.
5. Run the docker container.

You could try more by:
1. Creating docker hub account.
2. Experimenting with official containers.
3. Exploring more docker cli options.

Please leave your comments about the post and/or if you need any more information.

TAMIYA 6 Speed Gearbox – Assembly

I recently got hold of the TAMIYA 6 Speed Gearbox for one of my hobby projects. Today, in this post, we will be seeing how to assemble the same for a gear ratio of 1300.9:1. The gearbox can be configured in various other gear ratios, but for my application, I need the maximum torque and as little RPM as possible. The specification for the above mentioned gear ratio is as below. Highlighted column is of interest.


  Gear Ratio 11.6:1 29.8:1 76.5:1 196.7:1 505.9:1 1300.9:1
RPM r/min 870 338 132 51.3 19.9 7.8
Torque mN-m 15.8 40.7 101.2 235.4 226.1 226.1

 

The gear ratio of 1300.9:1 offers a torque of 226.1 mN-m which is a good amount of torque coming from this compact package. The assembly instructions given is very informative and easily understood.

Below are some of the pictures during and post assembly.

Tamiya 6 Speed Gearbox

Tamiya 6 Speed Gearbox

Tamiya 6 Speed Gearbox

Tamiya 6 Speed Gearbox                                                 

Tamiya 6 Speed Gearbox

Tamiya 6 Speed Gearbox

Tamiya 6 Speed Gearbox

Tamiya 6 Speed Gearbox

 

 

 

 

 

 

 

 

Post this, I am hunting for a suitable chassis to mount this on. The chassis should be able to handle this gearbox, a Raspberry Pi 3 ,a Power bank, a LM298N motor driver circuit board and some 1-2kg of payload for it to be useful.

I shall update once I have identified the chassis and after the complete build…

TMUX – A True “Save-Complete-State” Genius For Terminal And Command Line.

Many of us who work with [*]nix environments and command line will be aware of two of the most invaluable tools – screen and tmux ; Available in many flavors and with tons of custom configuration ability, these tools help save the states of the command line, keep the command line active even when abruptly disconnected or you gracefully end the terminal at the end of the day’s work. Whatever might be the reason these tools are there to help you.

Personally having used both screen and tmux ; screen is good for beginners and to get a taste of “what’s going on” initially . But I would pick tmux as the tool to settle for. And with the plethora of plugin available tmux gets transformed into TREX of the two 🙂

Here in this post, I just jot down how I have configured tmux to suit my taste. This post is a note-to-self for myself to refer to later  or it could help someone to get started with tmux.

A similar post on screen will soon be posted at some point soon. Keep a watch.

As with any good  [*]nix  tools, applications, tmux has the capability to accept tons of custom configuration through the use of .conf file. For tmux it is usually .tmux.conf  located in the home directory of the user.

Location:  $HOME/.tmux.conf 

I have attached, in this post below, the .tmux.conf file which I have customized to my liking. Feel free to download and modify according to your taste.

Here is what it looks like:

My Tmux

My Tmux

When you execute or launch tmux, it by default looks for the above file and uses it for configuration. But for some reason, you have a different .tmux.conf file – let’say .tmux.conf.me, you can source the same using the below command.

tmux source-file /path/to/configuration/file/.tmux.conf.me

Once you do this, the configurations present in this file will be used and reflected when you launch the tmux session. 

Some basic very useful commands to start with.

tmux                        - New tmux session.
tmux ls                     - List tmux sessions.
tmux new -s <name>          - Create a new session with name.
tmux a -t <name>            - Attach to the named session.
tmux kill-session -t <name> - Kill the named session.

For more options and commands supported under tmux, Please feel free to google, as there are tons and tons of information available on the same.

Now, my custom tmux setup includes the following plugins:

https://github.com/tmux-plugins/tmux-resurrect - Persists tmux environment across system restarts.
https://github.com/tmux-plugins/tmux-continuum - Continuous saving of tmux environment. Automatic restore. Automatic tmux start when computer is turned on.
https://github.com/tmux-plugins/tmux-logging   - Easy logging and screen capturing for Tmux.

You can refer to the below git pages on – how-to-install, how-to-use etc.

My .tmux.conf.me file looks like this:


# https://github.com/seebi/tmux-colors-solarized/blob/master/tmuxcolors-256.conf
set-option -g status-bg colour235 #base02
set-option -g status-fg colour136 #yellow
set-option -g status-attr default

# set window split
bind-key | split-window -h
bind-key - split-window

# default window title colors
set-window-option -g window-status-fg colour244 #base0
set-window-option -g window-status-bg default
#set-window-option -g window-status-attr dim

# active window title colors
set-window-option -g window-status-current-fg colour166 #orange
set-window-option -g window-status-current-bg default
#set-window-option -g window-status-current-attr bright

# pane border
set-option -g pane-border-fg colour235 #base02
set-option -g pane-active-border-fg colour240 #base01

# message text
set-option -g message-bg colour235 #base02
set-option -g message-fg colour166 #orange

# pane number display
set-option -g display-panes-active-colour colour33 #blue
set-option -g display-panes-colour colour166 #orange
# clock
set-window-option -g clock-mode-colour green #green

set -g status-interval 1
set -g status-justify centre # center align window list
set -g status-left-length 20
set -g status-right-length 140
set -g status-left '#[fg=green]#H #[fg=black]• #[fg=green,bright]#(uname -r | cut -c 1-6)#[default]'
set -g status-right '#[fg=green,bg=default,bright]#(tmux-mem-cpu-load) #[fg=red,dim,bg=default]#(uptime | cut -f 4-5 -d " " | cut -f 1 -d ",") #[fg=white,bg=default]%a%l:%M:%S %p#[default] #[fg=blue]%$
-%m-%d'

# C-b is not acceptable -- Vim uses it
set-option -g prefix C-a
bind-key C-a last-window

# Start numbering at 0
set -g base-index 0

# Allows for faster key repetition
set -s escape-time 0

# Rather than constraining window size to the maximum size of any client
# connected to the *session*, constrain window size to the maximum size of any
# client connected to *that window*. Much more reasonable.
setw -g aggressive-resize on

# Allows us to use C-a a  to send commands to a TMUX session inside
# another TMUX session
bind-key a send-prefix

# Activity monitoring
setw -g monitor-activity on
set -g visual-activity on

# hjkl pane traversal
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

# set to main-horizontal, 66% height for main pane
bind m run-shell "~/.tmux/scripts/resize-adaptable.sh -l main-horizontal -p 66"
# Same thing for verical layouts
bind M run-shell "~/.tmux/scripts/resize-adaptable.sh -l main-vertical -p 50"

bind-key C command-prompt -p "Name of new window: " "new-window -n '%%'"

# reload config
bind r source-file ~/.tmux.conf \; display-message "Config reloaded..."

# auto window rename
set-window-option -g automatic-rename

# color
set -g default-terminal "screen-256color"

# https://github.com/edkolev/dots/blob/master/tmux.conf
# Updates for tmux 1.9's current pane splitting paths.

# from powerline
run-shell "tmux set-environment -g TMUX_VERSION_MAJOR $(tmux -V | cut -d' ' -f2 | cut -d'.' -f1 | sed 's/[^0-9]*//g')"
run-shell "tmux set-environment -g TMUX_VERSION_MINOR $(tmux -V | cut -d' ' -f2 | cut -d'.' -f2 | sed 's/[^0-9]*//g')"

# Vi copypaste mode
set-window-option -g mode-keys vi
if-shell "test '\( #{$TMUX_VERSION_MAJOR} -eq 2 -a #{$TMUX_VERSION_MINOR} -ge 4 \)'" 'bind-key -Tcopy-mode-vi v send -X begin-selection; bind-key -Tcopy-mode-vi y send -X copy-selection-and-cancel'
if-shell '\( #{$TMUX_VERSION_MAJOR} -eq 2 -a #{$TMUX_VERSION_MINOR} -lt 4\) -o #{$TMUX_VERSION_MAJOR} -le 1' 'bind-key -t vi-copy v begin-selection; bind-key -t vi-copy y copy-selection'

# status bar
if-shell '\( #{$TMUX_VERSION_MAJOR} -eq 2 -a #{$TMUX_VERSION_MINOR} -lt 2\) -o #{$TMUX_VERSION_MAJOR} -le 1' 'set-option -g status-utf8 on'

# rm mouse mode fail
if-shell '\( #{$TMUX_VERSION_MAJOR} -eq 2 -a #{$TMUX_VERSION_MINOR} -ge 1\)' 'set -g mouse off'
if-shell '\( #{$TMUX_VERSION_MAJOR} -eq 2 -a #{$TMUX_VERSION_MINOR} -lt 1\) -o #{$TMUX_VERSION_MAJOR} -le 1' 'set -g mode-mouse off'

# fix pane_current_path on new window and splits
if-shell "test '#{$TMUX_VERSION_MAJOR} -gt 1 -o \( #{$TMUX_VERSION_MAJOR} -eq 1 -a #{$TMUX_VERSION_MINOR} -ge 8 \)'" 'unbind c; bind c new-window -c "#{pane_current_path}"'
if-shell "test '#{$TMUX_VERSION_MAJOR} -gt 1 -o \( #{$TMUX_VERSION_MAJOR} -eq 1 -a #{$TMUX_VERSION_MINOR} -ge 8 \)'" "unbind '\"'; bind '\"' split-window -v -c '#{pane_current_path}'"
if-shell "test '#{$TMUX_VERSION_MAJOR} -gt 1 -o \( #{$TMUX_VERSION_MAJOR} -eq 1 -a #{$TMUX_VERSION_MINOR} -ge 8 \)'" 'unbind v; bind v split-window -h -c "#{pane_current_path}"'
if-shell "test '#{$TMUX_VERSION_MAJOR} -gt 1 -o \( #{$TMUX_VERSION_MAJOR} -eq 1 -a #{$TMUX_VERSION_MINOR} -ge 8 \)'" 'unbind %; bind % split-window -h -c "#{pane_current_path}"'

run-shell $HOME/software/tmux-resurrect/resurrect.tmux
run-shell $HOME/software/tmux-continuum/continuum.tmux
run-shell $HOME/software/tmux-logging/logging.tmux

 

You can also download the complete file from here:

[   .tmux.conf.me  ]

Access Your Home Computer From Anywhere In The World

NGROK – Setting up And Configurations

NGROK – A tool that helps to setup secure tunnels which allows you to access your home server from anywhere in the world from the internet. Here in this blog, we will see an example configuration to setup a ssh tunnel from a computer, here it is a Raspberry Pi running the latest flavor of Raspbian – Stretch. But this method is equally applicable on all Linux, and some Unix systems where the ngrok is available. Please refer to ngrok.com for more information on CPU Architecture and OS support.

Requirements:

  • Raspberry Pi (referred to as Rpi from now on) ;  Or an equivalent linux system.
  • Rpi on the network and accessible.
  • SSH server enabled and you can ssh into your Rpi from local network.
  • Ngrok binary ( Location:  Ngrok Downloads )
  • Ngrok account with auth token generated. Visit ngrok.com for more details.

Steps:

  • setup ngrok – unzip /path/to/ngrok.zip  ; 
  • Add /path/to/ngrok to the environment variable: export PATH=$PATH:/path/to/ngrok
  • Setup ngrok.yml configuration file: Located at $HOME/.ngrok2/ngrok.yml

Sample configuration for ssh tunnel:

authtoken: <your_auth_token_from_ngrok.com>
tunnels:
 ssh:
 proto: tcp
 addr: 22

console_ui: false

log_level: error
log_format: logfmt
log: /path/to/ngrok/ngrok.log

Then you could start ngrok as below:

ngrok start ssh

Now you will get an output as below, ssh to the url given and you can reach your home server from anywhere in the world via internet.

Sample Output:

ngrok by @inconshreveable                 (Ctrl+C to quit)
Session Status          online
Account                 Pradeep Prakash (Plan: Free)
Version                 2.2.8
Region                  United States (us)
Web Interface           http://127.0.0.1:4040
Forwarding              tcp://0.tcp.ngrok.io:12859 -> localhost:22
Connections             ttl   opn   rt1   rt5   p50   p90
                        0     0     0.00  0.00  0.00  0.00

 

Use the address in bold to ssh into your local machine from anywhere in the world now.

Example command line to ssh into your local machine .

ssh -p 12859 0.tcp.ngrok.io -u username

Now, if it is not a high availability server and a regular home server prone to frequent reboots due to power issues or any other issues. Then you will lose the connectivity. But not to worry as long as it’s a Linux system and the best of the scripting tools available for us,
we can achieve some kind of mechanism.
To automate the spawning of the ngrok upon reboot or if ngrok loses the tunnel for some reason, a script can be written to spawn ngrok and email the port number that it has come up with for the new tunnel.

If you want one such simple scripting mechanism, visit my GitHub Repository below and follow the instructions in the README.md and you should be on your way.

Download the Git Repo using standard git tools and follow the README. Hope it helps.

https://github.com/pradeepprakash/ngrok_scripts

A Memoir – Year 2017 For Us And Suryansh

It was a memorable year 2017 for us. Some of the highlights that I can think of

  • Suryansh’s first big trip to the Himalayas!
  • Moving into the new Home – Aashman!
  • Bhutan Motorcycle Trip!
  • Numerous Motorcycle Rides in the Western Ghats with Jyothi!

I have a couple of video doing the talking rather than a big written blog or a audio narrative, which I am planning to do ( a first to me). Audio narrative hoping to help Suryansh later when he grows up – to listen to!

But for now, enough said. Here it is!

 

 

Pushkar Mela – Vibrant, Colorful, Cheerful!

I got a chance to travel to Pushkar this time – it is usually held in mid-November every year. It is a week long extravaganza – camel trade, traditional folk dance, music, circus, concerts – rock, fusion, classical etc. The vibrance and colors are simply breathtaking. Here, I have tried to capture the beauty of it all  from my perspective to the best of my ability. Here are some of the moments from the trip.

Rebooting The Modem

BSNL Broadband is a very unreliable one most of the times because of the ADSL signal on a copper line and weather (yes, believe me it is!) – it is always bouncing and the DSL protocol renegotiated. This invariably means I can’t access my Synology DS214Play NAS server from anywhere outside my home. This is because my public IP address changes. I haven’t paid for a static IP as it costs a bomb and it is not reliable either because of the reason mentioned in the opening line of this post.

The synology has a built-in mechanism of refreshing the NAS’s public IP address and usually it is pretty reliable. All the above assumes that the TP-link modem (shown in picture for illustration only) is quite a robust one when it comes to ADSL protocol negotiation and frequent re-establishment of the PPPoE connection and getting a public IP address. Many a times, I have seen that the TPLink Modem hangs and not able to either establish a DSL link or obtain and renew a public IP. In such situations, I am left with no access to my NAS as mentioned before.

TPLINK - 8817 ADSL Modem

TPLINK – 8817 ADSL Modem

After pouring over the web and analyzing many options available – from replacing the modem with a better one  to rebooting the modem every now and then. Those solutions were impractical – changing the modem – because of costs. rebooting the modem regularly – 5mins, 1hr or 1day??

I came up with the below solution.

Rebooting/Resetting the Modem whenever

– there is a connectivity loss to an external device/node and sending email if reboot triggered.

– whenever an internal connectivity loss to one of the LAN nodes and sending email when reboot triggered.

– if we are redirected to a different page from the ISP and asking us to reboot the modem. Yes, this is done by BSNL after you reach the FUP limit.

I have observed that while the Modem is in the hung state, it’s CLI is still accessible via telnet and I am able to run administrative commands.

Scripts running on the NAS:

1. logip_reboot.sh  – A Shell script having the logic to determine the IP and reboot modem in case of failure. This is run every five minutes as a cron job.

#!/bin/bash
export MYIP=`cat /volume2/Aashman/Dropbox/aashman/logs/ip.me`
### curl ifconfig.me > /home/aashman/ip.me
### export NEW_IP=`cat ip.me`
### export NEW_IP=`curl ifconfig.me`
export NEW_IP=`curl http://myip.xname.org`

#Strings present in the BSNL redirect page.
export REDIR_MSG_1="Please wait while you are redirected"
export REDIR_MSG_2="ssssportal.war"

#To flag redirect page or not.
export IS_REDIR_MSG=0

#---------------------------------------------------------------
### export NEW_IP="<html>
### <head>
### <meta http-equiv=\"Refresh\" content=\"1; URL=http://172.30.3.136:8080/ssssportal.war/fup_4m-8g-512k.jsp\">
### <meta http-equiv=\"pragma\" content=\"no-cache\">
### </head>
### <body>
### Please wait while you are redirected ...
### </body>
### </html>"
#---------------------------------------------------------------

if [ -z "$NEW_IP" ]
then
 echo "NULL Returned from curl"
 echo "IP:NULL | `date`" >> /volume2/Aashman/Dropbox/aashman/logs/ipAdd.log
 exit
fi


#Debug , enable to debug.
### echo "$NEW_IP"
### echo " "
### echo "IS_REDIR_MSG:$IS_REDIR_MSG"

#Check if it is the redirect message.
case "$NEW_IP" in
 *$REDIR_MSG_1*)
 printf "\nSet for Reboot now, Found: \"$REDIR_MSG_1\"\n";
 export IS_REDIR_MSG=1;
 ;;
esac
case "$NEW_IP" in
 *$REDIR_MSG_2*)
 printf "\nSet for Reboot now, Found: \"$REDIR_MSG_2\"\n";
 export IS_REDIR_MSG=1;
 ;;
esac

if [ "$IS_REDIR_MSG" == 1 ]
then
 printf "\nRebooting Now, IS_REDIR_MSG: TRUE\n\n";
 sh /volume2/Aashman/Dropbox/aashman/scripts/syno/rebootModem.sh
 printf "\n\n_____________________________________________________________________\n"
 printf "\n"
 printf "|*******************************************************************|\n"
 printf "|*** Done Rebooting ADSL Modem - Try connecting after sometime   ***|\n"
 printf "|*******************************************************************|\n"
 printf "_____________________________________________________________________\n\n"
 # Send email here and log.
 echo "ADSL Modem Rebooted | `date` " >> /volume2/Aashman/Dropbox/aashman/logs/adslModemReboot.log
 echo -e "Subject:ADSL Modem Rebooted\n\n" "ADSL Modem Rebooted @ `date`" | sendmail -F "Aashman" -f home.aashman@gmail.com pradeepprakash@gmail.com
 exit
else
 printf "\nChecking if IP Address has changed and Logging, IS_REDIR_MSG: FALSE\n\n";
 echo $NEW_IP > /volume2/Aashman/Dropbox/aashman/logs/ip.me
 if [ "$MYIP" == "$NEW_IP" ]
 then
 echo "IP Has not changed"
 #echo "IP:$MYIP | `date`" >> /volume2/Aashman/Dropbox/aashman/logs/ipAdd.log
 #cat /volume2/Aashman/Dropbox/aashman/logs/ip.me | mail -s "Public IP Address Changed" pradeepprakash@gmail.com
 #echo -e "Subject:IP Address Not Changed\n\n" `cat /volume2/Aashman/Dropbox/aashman/logs/ip.me` | sendmail -F "Aashman" -f home.aashman@gmail.com pradeepprakash@gmail.com
 else
 echo "New IP is $NEW_IP"
 #cat /home/aashman/Dropbox/aashman/logs/ip.me | mutt -s "Public IP Address Changed" pradeepprakash@gmail.com
 #cat /volume2/Aashman/Dropbox/aashman/logs/ip.me | mail -s "Public IP Address Changed" pradeepprakash@gmail.com
 echo "IP:$NEW_IP | `date` **" >> /volume2/Aashman/Dropbox/aashman/logs/ipAdd.log
 echo -e "Subject:Public IP Address Changed\n\n" `cat /volume2/Aashman/Dropbox/aashman/logs/ip.me` | sendmail -F "Aashman" -f home.aashman@gmail.com pradeepprakash@gmail.com
 fi
fi

2. rebootModem.py – A Python script to reboot the modem. This is called by the above script.

import getpass
import sys
import telnetlib

HOST = "192.168.1.1"
#user = raw_input("Enter your remote account: ")
#password = getpass.getpass()
password = "aashmanf2$"

tn = telnetlib.Telnet(HOST)

#tn.read_until("login: ")
#tn.write(user + "\n")
if password:
 tn.read_until("Password: ")
 tn.write(password + "\n")

print "rebootModem.py - All set for rebooting\n Done!!"
tn.write("set reboot\n")
tn.write("exit\n")

print tn.read_all()

3. Crontab entries:

#minute hour mday month wday who command
*/5 * * * * root sh /volume2/Aashman/Dropbox/aashman/scripts/syno/logip_reboot.sh