fear the mighty Golembot!

April 15, 2018

Lately I have been playing with a great gizmo:

Pimoroni scrollbot project



It’s a fun project with raspberry pi zero w plus a led pHAT and some 3d printed case.

I did interface that to my Golembot, a python Telegram bot that is used to control what messages are scrolled on the led screen.

let me detail what I did to do that.

First of all I suggest to use a gpi hammer header kit to avoid soldering.

Follow pi moroni videos for the setup and it’s quite easy to assemble the kit

Raspbian Setup

Besides the KIT shipped by Pimoroni guys you need an SD card to install the OS on the pi zero.

I bought a 16 gb microsd and used Raspbian as OS. I suggest that because: it’s quite easy, flexible , complete and diffused plus we’re not NOOBS , right?

After installing the image on sd card with rufus , I suggest mounting the /boot partition (it’s FAT so you can do that in windows too)

to fix wifi, probably you will have to add to config.txt


and in cmdline.txt


after rootwait

Also I had to install on my windows 10 drivers mod-duo-rndis.zip  to see ethernet over USB.

This will show up you pi connectd by usb as


You need then the bonjour service on windows to be able to connect to the name  raspberrypi.local

when you can ssh into that  ( user pi password raspberry is the default)

you can then setup wifi and maybe add a static dhcp reservation on your router for your pi wifi address.


Then you can have fun creating the telegram bot

just ask botfather for a key, then

I chose echobot

as the starting example.

You will need to

 pip install telegram
 pip install scrollphathd

and any other needed module.

My first script was  dimmi.py a simple script to scroll stuff on the phat taken from the examples

# dimmi.py
# scrolls what is passed as argument to the script on the led strip

import time
import scrollphathd as sphd
import sys


#sphd.write_string('Shiver me timbers!')
sphd.write_string(' ' + stringa + ' ')

while True:

this is my golembot.py



#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Simple Bot to reply to Telegram messages.

This program is dedicated to the public domain under the CC0 license.

This Bot uses the Updater class to handle the bot.

First, a few handler functions are defined. Then, those functions are passed to
the Dispatcher and registered at their respective places.
Then, the bot is started and runs until we press Ctrl-C on the command line.

Basic Echobot example, repeats messages.
Press Ctrl-C on the command line or send a signal to the process to stop the

from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
import logging
import os

# Enable logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
# level=logging.DEBUG)

logger = logging.getLogger(__name__)

# secret telegram bot token
token ="xxxxxxxxxx"

# Define a few command handlers. These usually take the two arguments bot and
# update. Error handlers also receive the raised TelegramError object in error.
def start(bot, update):
 """Send a message when the command /start is issued."""

def quotes(bot, update):
 """print quotes BTC ETH"""
 update.message.reply_text("attivo quotes coinbase " + update.message.text)
 os.system("pkill -9 dimmi.py;/home/pi/quotes/gimmecoinbase.py &")

def noquotes(bot, update):
 """stop quotes BTC ETH"""
 update.message.reply_text("fermo quotes coinbase ")
 os.system("ps -ef | grep -v grep | grep coinbase |awk '{ print $2'} | xargs kill -9")

def help(bot, update):
 """Send a message when the command /help is issued."""
 update.message.reply_text('I will echo your msg, /quotes prints coinbase quotes /noquotes stops them')

def echo(bot, update):
 """Echo the user message."""
 update.message.reply_text("you said " + update.message.text)
 os.system("pkill -9 dimmi.py;/home/pi/dimmi.py \"" + update.message.text +" \" &")

def error(bot, update, error):
 """Log Errors caused by Updates."""
 logger.warning('Update "%s" caused error "%s"', update, error)

def main():
 """Start the bot."""
 # Create the EventHandler and pass it your bot's token.
 updater = Updater(token)

# Get the dispatcher to register handlers
 dp = updater.dispatcher

# on different commands - answer in Telegram
 dp.add_handler(CommandHandler("start", start))
 dp.add_handler(CommandHandler("help", help))
 dp.add_handler(CommandHandler("quotes", quotes))
 dp.add_handler(CommandHandler("noquotes", noquotes))

# on noncommand i.e message - echo the message on Telegram
 dp.add_handler(MessageHandler(txtreceived, echo))

# log all errors

# Start the Bot

# Run the bot until you press Ctrl-C or the process receives SIGINT,
 # SIGTERM or SIGABRT. This should be used most of the time, since
 # start_polling() is non-blocking and will stop the bot gracefully.

if __name__ == '__main__':


as a bonus I added /quotes command that prints coinbase quotes for BTC and eth

using coinbase libary and the gimmecoinbase.py script


#!/usr/bin/env python
# -*- coding: utf-8 -*-

# cfr https://github.com/coinbase/coinbase-python
# also #https://api.coinbase.com./v2/prices/ETH-EUR/buy

import coinbase
import json
import sys
import time
import scrollphathd as sphd
from scrollphathd.fonts import font5x7

# fix unicode

# client coinbase
from coinbase.wallet.client import Client
# mia api key
client = Client("coinbasekey", "coinbasesecret")

# pulisci scroller
# routa scroller
# mostra
# luminosita scroller
#sphd.write_string('Shiver me timbers!')

# funzione per recuperare ticker da coinbase, ritorna stringa ticker
def myticker():

JBTCEUR=client.get_sell_price(currency_pair = 'BTC-EUR')
 "amount": "396.40",
 "base": "ETH",
 "currency": "EUR"


JETHEUR=client.get_sell_price(currency_pair = 'ETH-EUR')

ticker = "BTC " + BTCEUR + u"\u20AC" + " ETH " + ETHEUR + u"\u20AC" + " "

return ticker


sphd.write_string(' ' + ticker + ' ',font=font5x7)
print ticker

start_time = time.time()

while True:
 elapsed_time = time.time() - start_time
 if elapsed_time > 120:
 print "refresh dopo 120 secondi"
 start_time = time.time()
 print ticker
 sphd.write_string(' ' + ticker + ' ',font=font5x7)


sorry bout some italian comments, will translate them asap

this is my systemd unit script

root@raspberrypi:/lib/systemd/system# more golembot.service
Description=GolemBot Service

ExecStart=/usr/bin/python /home/pi/golembot.py > /home/pi/golembot.log 2>&1



then you can

systemctl enable golembot

systemctl start golembot


What do you think?








Installing nagios with nginx in amazon EC2 or CentOS6

November 10, 2013

Nagios is a great monitoring system which is also distributed as rpm package in some repositories.

All  rpms , as far as I know , are preconfigured to be used with apache as a webserver.

I recently been using nginx  on some linux servers in Amazon VPC  because it’s very efficient and uses resources quite lightly, allowing more users for the same server.

I’d like to share my configuration to use amazon stock nginx, php-fpm and nagios rpm packages from amazon repositories, this should be also very easyly portable on CentOS/ RHEL 6 with epel and maybe rpmforge repos.

The tricky part in the installation is that the latest nagios uses both php and CGIs , they are usually handled by nginx as FastCGI applications.

There are a lot of possible implementations, I choose php-fpm (with php 5.4) for php pages and a perl fastcgi-wrapper.pl script I found mentioned here, here you can download the script.

First of all I  yum installed  nginx, php54-fpm , all php54* packages I needed, nagios, nagios-plugins-all , perl-FCGI

I configured php-fpm to use a unix socket in  /etc/php-fpm.d/www.conf   with :

listen = /tmp/phpfpm.sock

while my fastcgi wrapper in /usr/local/sbin/fastcgi-wrapper.pl  contains an IP socket:

        $socket = FCGI::OpenSocket( "", 10 ); #use IP sockets

You can start php-fpm as a service with service php-fpm start

While you can control the fastcgi-wrapper.pl script with upstart by placing the file   /etc/init/fastcgi-wrapper.conf  with this content

start on runlevel [2345]
stop on runlevel [016]

exec /usr/bin/perl /usr/local/sbin/fastcgi-wrapper.pl

and issueing initctl start fastcgi-wrapper .

This is the nginx virtualhost in /etc/nginx/conf.d/mynagios.mydomain.conf

server {

        server_name mynagios.mydomain.com;
        root /usr/share/nagios/html; 

        error_log  /var/log/nginx/nagios.error.log ;
        access_log  /var/log/nginx/nagios.access.log  main;

        expires 31d;
        index index.php index.html;

  auth_basic            "Restricted";
  auth_basic_user_file  /etc/nginx/htpasswd;

        location /nagios/stylesheets {
                alias /usr/share/nagios/html/stylesheets;

        location /nagios/js {
                alias /usr/share/nagios/html/js;

        location /nagios/images {
                alias /usr/share/nagios/html/images;         

 location ~ \.cgi$ {
        root /usr/lib64/nagios/cgi-bin;

        rewrite ^/cgi-bin/(.*)$ /$1;
        include /etc/nginx/fastcgi_params;
        fastcgi_param AUTH_USER $remote_user;
        fastcgi_param REMOTE_USER $remote_user;
        fastcgi_param SCRIPT_FILENAME /usr/lib64/$fastcgi_script_name;

        location ~ \.php$ {
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_intercept_errors on;
                fastcgi_pass unix:/tmp/phpfpm.sock;


As you can see the whole virtualhost is behind basic authentication.

Please let me know what you think of this, is there any better way to achieve the same?


Nagios Escalations using http and cgi

December 26, 2009

Nagios escalations are used to submit check results to remote systems.
The ufficial way to escalate betewen 2 nagios installations is using NSCA . NSCA is a deamon running on the remote nagios server, it listens on a TCP port and receives check results submitted from the local nagios (“escalated”) using send_nsca command to a passive check on the remote one.

Sometimes you do not wish to have and extra daemon on your remote server or , maybe due to firewall policies, you can only use http protocol to escalate a check result.

We have a “remote” nagios installation which is used by all sysadmins and a “local” installation only used by network people.

On both servers we use Centos 5 as OS and nagios from RPMForge as nagios versions.

What I needed was a quick and dirty way to escalate some “local” mayor network problems to a single remote passive check on the “remote” nagios to let everyone know about the problem.

“Local” Nagios setup

On the “local” nagios I created a new notification command with the following bash script:

# notify nagios event using http
# /usr/lib/nagios/plugins/eventhandlers/notify-http 

# this script uses 5 params:

# exit if not in HARD state ( occurs after 2 SOFT states )
if [ "$servicestatetype" != "HARD" ]
exit 0

#returncode must be numeric
case $servicestate in
 "OK" )
 returncode=0 ;;
 returncode=1 ;;
 returncode=2 ;;
 returncode=3 ;;

#new output is servicedesc + old output + state
output="$servicestate $servicedesc $output"
# new service desc is remotepassivecheckname
servicedesc="remotepassivecheckname $hostname"

#hostname is remote nagios

#urlencode output
output=$(echo -n "$output" | \
/usr/bin/perl -pe's/([^-_.~A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg');

/usr/bin/wget -q \
"http://remoteserver/cgi-bin/passv.pl?hostname=$hostname&servicedesc=$servicedesc&returncode=$returncode&output=$output" \
-O /dev/null 2>&1

The script uses some nagios standard macros as GET parameters to a remote perl cgi.

It escaltes to the remote installation only when the check gets into HARD state

It is registered in /etc/nagios/objects/commands.cfg with the following lines:

define command{
 command_name    http-notify
 command_line    /usr/lib/nagios/plugins/eventhandlers/notify-http "$HOSTNAME$" "$SERVICEDESC$" "$SERVICESTATE$" "$SERVICEOUT

Every check tha thas to be escalated just needs the line

event_handler           http-notify

into its service definition.

“Remote” nagios setup

On the remote instance I just created a properly named passive check linked to the remote nagios host.

The passive check is notified by the following cgi which uses the submit_check_result command.

# /var/www/cgi-bin/passv.pl
# submits a remote check to a local passive check
# using submit_check_result

use CGI;
$query = new CGI;
if ($esitochk =~ /CRITICAL/) {$esitochk=2;}
$myoutput=`/usr/lib/nagios/plugins/eventhandlers/submit_check_result $hostname $servicedesc $returncode $output`;
print "Content-type: text/html\n\n\n";
print "myoutput $myoutput";

I hope these suggestions will be useful to anyone , please let me know what you think about it.

porting phpfreechat from Mysql to Oracle

October 3, 2009

I’ve been recently playing with the porting to Oracle of a really nice ajax php chat application :  phpfreechat or PfC for short.
This application makes very easy to integrate new types of persistance containers because it abstracts them in class implementations that provide just 3 methods that have to be adapted to the new type of container, and you just need a single table in the database.

I used pear DB classes to get access to the database.

Of course, php has to be compiled with oci extensions that require at least an instant client installation.

I used oracle express edition as DB server on my development server, it is free (as in beer) for development use, and very light on resources.

I had to convert datatypes from Mysql to Oracle and I confess I used phpbb3 oracle sql schema as an inspiration.

Oracle has no autoincrement types so you have to use sequence (+ triggers).

As far as I know, there is no timestamp type (seconds from the epoch)  as well  so I had to improvise some PL/SQL.

Another issue that I had to struggle with is timezones : UTC vs your local time, be careful to calculate time always in the same way.

Now we have a prototype, that is currently in trunk.
It certainly needs some testing and some advice from skilled oracle users, please try it out and let me know any issue, suggestion, idea, insults….

The quickest way to test it is : download the latest stable pfc, get oracle.class.php , drop it in the containers dir , create database and parameters as explained in php file.

useful apache modules for your reverse proxy

September 19, 2009

There are a couple of reasons why you might need to reverse proxy a web site:  security, high availability, etc.

My favorite software to implement a reverse proxy is ( of course ) apache.

Some modules that allow this possibility are mod_proxy and mod_rewrite, usually you can use both of them for the more flexible results.

Mod_proxy lets you to publish internal http,ftp and AJP (= tomcat webapps) sites while mod_rewrite can be a godsend in rewriting urls , for example in SEO friendly urls or to redirect users from moved applications.
Mod_rewrite has also proxying capabilities but the latest mod_proxy has better features like caching and load balancing.

All this modules cannot change the content of the proxyed pages while sometimes this could be needed, you might have a proxied application that contains hardcoded absolute URLs which are different from you reverse proxy.

The most used module to change some strings in the output of your reverse proxy is mod_proxy_html.
This module allows you to intercept and substitute or add strings in the html produced by the proxyed application, it can be used together with mod_proxy to provide a more functional reverse proxy.

Sometimes mod_proxy_html power is still insufficient, that might happen because it fails to understand the html markup or scripting produced by the proxyed application.
In these cases I found another module that will be part of the next apache release and is currently in trunk: mod_sed.

Beware that mod_sed is still in its infancy (I would not recommend it in a big web site of a major italian financial institution) but I found it very handy when other solutions couldn’t globally replace some patterns.

One final suggestion is mod_security .
This great piece of software in an application level firewall: it (tries to) filter any malicious request before fowarding the request to the proxyed application.
Sometimes you just do not feel very comfortable about the security of some major php application or you do not trust blindly the latest microsoft technology du jour, this little friend could be some extra layer of security you were looking for…

That’s it for now, please let me know what do you think or your revproxying experiences

PS : ` Despite the tons of examples and docs, mod_rewrite is voodoo. Damned cool voodoo, but still voodoo. ”

— Brian Moore
bem@news.cmc.net (quoted from mod_rewrite docs)

php + owa 2003 calendar fun

September 13, 2009

I’ve been recently playing with WEBDAV integration between OWA 2003 ( Microsoft Exchange Outlook Web Access) and php.
Looks like Troy Wolf has made an excellent work creating some classes to provide WEBDAV methods , xml parsing and also Exchange 2003 integration examples.

I had specific needs in calendar integration and I found some good extra work provided by Ryan Hadley.

Looks like he made an excellent implementation of exchange calendar to ics format conversion.
The small bit I still needed was the creation of appointments using WEBDAV, like it is explained here.
After applying all my google-fu I still could not find any php examples  so I had to adapt visual basic and other dialects to php….

this is a working example:


// Modify the path to this class file as needed.

// Change these values for your Exchange Server.
$exchange_server = "http://exchange";
$admin_username = "exchadministrator";
$admin_password = "password";
// We use Troy's http class object to send the XML-formatted WebDAV request
// to the Exchange Server and to receive the response from the Exchange Server.
// The response is also XML-formatted.
$h = new http();
$h->headers["Content-Type"] = 'text/xml; charset="UTF-8"';
$h->headers["Depth"] = "0";
$h->headers["Translate"] = "f";

// Build the XML request.
// This section must be against the left margin.

$golemreq= <<<END
<?xml version="1.0"?>
<g:propertyupdate xmlns:g="DAV:"
xmlns:mapit="http://schemas.microsoft.com/mapi/proptag/" xmlns:x="xml:"
xmlns:header="urn:schemas:mailheader:" xmlns:mail="urn:schemas:httpmail:">


$strMailInfo = "<mail:subject>Test Appointment Subject</mail:subject>\n";
$strMailInfo .= "<mail:htmldescription>Lets meet here</mail:htmldescription>\n";

$strCalInfo = "<cal:location>meetappt Location</cal:location>\n";
$strCalInfo .="<cal:dtstart dt:dt=\"dateTime.tz\">2009-11-18T23:00:00.000Z</cal:dtstart>\n";
$strCalInfo .="<cal:dtend dt:dt=\"dateTime.tz\">2009-11-18T23:30:00.000Z</cal:dtend>\n";
$strCalInfo .="<cal:instancetype dt:dt=\"int\">0</cal:instancetype>\n";
$strCalInfo .="<cal:busystatus>BUSY</cal:busystatus>\n";
$strCalInfo .="<cal:meetingstatus>CONFIRMED</cal:meetingstatus>\n";
$strCalInfo .="<cal:alldayevent dt:dt=\"boolean\">0</cal:alldayevent>\n";
$strCalInfo .="<cal:responserequested dt:dt=\"boolean\">1</cal:responserequested>\n";
$strCalInfo .="<cal:reminderoffset dt:dt=\"int\">900</cal:reminderoffset>\n";

$strHeaderInfo = "<header:to>".$partecipants."</header:to>\n";

$golemreq .= $strMailInfo . $strCalInfo . $strHeaderInfo ;
$golemreq .= "<mapi:finvited dt:dt=\"boolean\">1</mapi:finvited>\n";
$golemreq .= "</g:prop>\n</g:set>\n";
$golemreq .= "</g:propertyupdate>";

$h->xmlrequest = $golemreq;

// The http object's 'fetch' method does the work of sending and receiving the
// request. We use the WebDAV PROPPATCH method to create or update Exchange items.
//$url = $exchange_server."/public/Company%20Contacts/john%20doe.EML";
$url = $exchange_server."/exchange/$exchange_username/Calendar/testapp.eml";
if (!$h->fetch($url, 0, null, $admin_username, $admin_password, "PROPPATCH")) {
 echo "<h2>There is a problem with the http request!</h2>";
 echo $h->log;

// You can print out the response to help troubleshoot.
echo "debug \n";
echo "<pre>".$h->header."</pre><hr />\n";
echo "<pre>".$h->body."</pre><hr />\n";


It took a while to get the proper xml namespaces so I hope that might be of some use to someone else…
Btw the administrator account needs explicit permission to write into the user calendar, beware also that the calendar is created at the first time the user writes something into it and the name is dependant on the language used by the calendar ( “Calendar” is just for english users).

I am afraid all this will not work on recent ( exchange 2007 and over) versions because there is a new (and  maybe saner) web services interface to exchange.
Please let me know what you think….

Remotely Install VNC on windows server from linux box

September 12, 2009

Have you ever needed to remotely access a windows box with a borked terminal server and that you would not/could not rather reboot?

That’s exactly what happened me a couple of days ago….

My idea was to remotely install and start a vnc server.

After some googling I managed to fish out this and this

Which is a good start,  the problem is  the windows  server was reachable through ssh on a centos box ( port forwarding terminal server port tcp 3389 inside the ssh connection).
So I had to get the ” Complete set of executables, no installer” version from tightvnc

Unpack it, and get the files (WinVNC.exe, VNCHooks.dll) on the centos box.
Then I copied the files to win server on the ADMIN$ share using:

smbclient //$ -U administrator

I managed then to get a remote prompt using

winexe -U WINDOWSDOMAIN/Administrator%password' // "cmd.exe"

BTW winexe is great , watch out that on centos/RHEL linux the static compiled version is not compatible with the OS libc…

I had to compile it , untarring sources and with a :

make proto bin/winexe

then, on the windows prompt  you need to install the service with

winvnc.exe -service 

please note that the service won’t allow logins until you set a password, what I did is exporting a vnc config from another windows machine and merge it into the registry:

this one for example sets the password to   secret

Windows Registry Editor Version 5.00


The idea was to copy it on the windows box in a vnc.reg file and then use:

regedit /s vnc.reg

finally you can remotely start the service in the windows prompt using:

net start winvnc

If you forward your local port 5900 inside the ssh connection on the remote windows machine and connect with a vnc client to localhost you will magically reach the remote server.


I noticed that on windows, the remote forwarding trick for terminal server connections using localhost is not possible anymore with the new mstsc.exe client , remember to keep an old version around.

I have 5.0.2195.6674 version which still works, 6.0.6001.18000 from windows xp sp3 it is not, or please check out this

Wow that was my first post, geeky enough isn’t it?