This tutorial is originally meant to be a guide to go along with a talk for PyLadies (but also for anyone else who finds it useful) on how to create a simple Twilio SMS application that sends you a notification for an event.

Here is what you will need:

  • An editor
  • Python 2.7 or 3.5
  • Python twilio module: pip install twilio or easy_install twilio
  • A Twilio account, sign up here Don’t worry, go ahead, I’ll wait until you’re back. Make sure you verify your existing phone number, this is very important! Otherwise you won’t be able to send anything. It doesn’t make too much of a difference what you select for your possible projects to be, so choose whatever matches your interests the best.
  • A Twilio phone number that has capabilities for sending a SMS. Once you have registered, navigate to, and click on the “Get started” button:
  • SMS dashboard

    To get a number:
    and it will offer you a number. If you don’t like this one, you can click on “Search for a different number”. In any way, make sure it has SMS listed in the capabilities (should be the case pretty much anywhere in the world). You should be greeted with a message similar to this:

    Congratulations, you how have a programmable number that has infinite use cases from notifying you when your train is late, telling you when there was movement detected by a camera, or sending your grandmother preset signs of affection that get sent out automatically at specific times so that she doesn’t feel lonely! Or make your dog send selfies to send them over MMS, your choice:

    You will also need the ACCOUNT_SID and AUTH_TOKEN to send a SMS. Keep in mind that the AUTH_TOKEN is equivalent to a password, so keep it secure accordingly. In order to get it, click on the “Show API credentials link”:
    or simply navigate to and click on the eye to see your token:
    The account sid always starts with AC and it’s an equivalent to a user name. Write both of these down, you will need it later.

    Ok, now we get to the fun part, coding. Sending a SMS is as simple as filling in the ACCOUNT_SID and AUTH_TOKEN variables with correct values and adjusting the message. Leave the quotes, replace just the text between these. Save it to a file, let’s say

    from import TwilioRestClient
    # put your own credentials here
    ACCOUNT_SID = 'replace with your account sid'
    AUTH_TOKEN = 'replace with your account token'
    client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN)
        to = 'replace with the number you want to send a sms to',
        from_ = 'replace with your Twilio number you just created',
        body = 'replace with the message',

    Let's try it out! Execute python from a shell and make sure that you either are in the directory where the file is or give it a full path. If it was successful, it has no output, you just get a new prompt line and you should receive a message with the contents you entered, padded with a free trial account message, like this:

    Congratulations, you have created your first Twilio SMS app! Now you can reuse this for any other application to send a notification for any sort of an event. Your imagination what to integrate it with is your playground. You could also execute the Python script from crontab periodically to check for any condition (let's say a Twitter post for a specific user or a hashtag, stock price change and so on), and if it's met, it will let you know by SMS.

    Note that you are not limited to SMS, you could also send MMS, make a call or use any of the other products available. and are good places to explore next with great tutorials.

    Let’s say you want to automatically and nightly update all packages from the security repository. Beware that if you have updated any packages other ways than apt, it might not work for you. Run with superuser privileges:

    echo "0 4 * * * root test -x /usr/sbin/apt-security-updates && /usr/sbin/apt-security-updates" | tee --append /etc/cron.d/apt-security-updates

    Copy all security related lines to a separate apt file
    cat /etc/apt/sources.list |grep security > /etc/apt/sources.list.d/security.list

    And remove from the original file
    sed -i '/security/d' /etc/apt/sources.list

    Run apt-get update manually to check it works fine and there are no errors.

    Create the script that runs the update and set the permissions:
    echo 'date
    apt-get update
    apt-get upgrade -y -o Dir::Etc::sourcelist="sources.list.d/security.list" -o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0" -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold"' | tee --append /usr/sbin/apt-security-updates
    chmod +x /usr/sbin/apt-security-updates

    The logs will be at /var/log/apt/history.log as for any other apt upgrade.

    In order to extract just one file from a deb package, you can do it like this:
    dpkg --fsys-tarfile package.deb| tar xOf - ./file/location/inside/deb > /path/to/destination
    For example:
    dpkg --fsys-tarfile libpng12-0_1.2.44-1+squeeze6_i386.deb| tar xOf - ./lib/ > ~/skype/usr/lib/
    Note that you do need to know the exact path and filename inside the package though. To list the contents:
    dpkg --contents package.deb

    While I needed to install Skype on Linux and even the multiarch package came up with
    dpkg: error processing archive skype-debian_4.3.0.37-1_i386 (1).deb (--install):
    package architecture (i386) does not match system (amd64)
    Errors were encountered while processing:
    I thought I’d share my solution with others. This is written as of October 2016 with Skype 4.3.0. I am running Parrot Security OS, but since it’s a Debian derivative just as Ubuntu is for example, it’s likely going to work on other Debian derivatives just as well.

    I found this instructions page:
    But.. these instructions are out of date as Squeeze repositories have been discontinued. However, this is how I got it working:
    So here goes:

  • Download a multiarch version from here:” target=”_blank”>
  • mkdir -p ~/skype/usr/lib; dpkg -x ~/Downloads/skype-debian_4.3.0.37-1_i386.deb ~/skype/
    sudo dpkg --add-architecture i386; sudo apt-get update
    Install the dependencies:
    sudo apt-get install lib32asound2 ia32-libs ia32-libs-gtk libqt4-network:i386 libxi6:i386 libsqlite3-0:i386 libqt4-xmlpatterns:i386 libxv1:i386 libxss1:i386 libqtwebkit4:i386

    And check that everything is needed to make your Skype happy (there shouldn’t be any => not found):
    ldd ~/skype/usr/bin/skype (0xf77a6000) => /usr/lib/i386-linux-gnu/ (0xf54ee000) => /usr/lib/i386-linux-gnu/ (0xf54eb000) => /lib/i386-linux-gnu/ (0xf54e2000) => /lib/i386-linux-gnu/ (0xf54dd000) => /usr/lib/i386-linux-gnu/ (0xf538b000) => /usr/lib/i386-linux-gnu/ (0xf5376000) => /usr/lib/i386-linux-gnu/ (0xf52e9000) => /usr/lib/i386-linux-gnu/ (0xf2f3d000) => /usr/lib/i386-linux-gnu/ (0xf2ef4000) => /usr/lib/i386-linux-gnu/ (0xf238d000) => /usr/lib/i386-linux-gnu/ (0xf2227000) => /usr/lib/i386-linux-gnu/ (0xf1f0e000) => /lib/i386-linux-gnu/ (0xf1ef1000) => /usr/lib/i386-linux-gnu/ (0xf1d78000) => /lib/i386-linux-gnu/ (0xf1d23000) => /lib/i386-linux-gnu/ (0xf1d06000) => /lib/i386-linux-gnu/ (0xf1b4f000)
    /lib/ (0x56555000) => /usr/lib/i386-linux-gnu/ (0xf1b23000) => /lib/i386-linux-gnu/ (0xf1ac7000) => /lib/i386-linux-gnu/ (0xf1aa8000) => /usr/lib/i386-linux-gnu/ (0xf1a9c000) => /usr/lib/i386-linux-gnu/ (0xf1a2b000) => /usr/lib/i386-linux-gnu/ (0xf19f1000) => /usr/lib/i386-linux-gnu/ (0xf19e1000) => /usr/lib/i386-linux-gnu/ (0xf19a9000) => /usr/lib/i386-linux-gnu/ (0xf191a000) => /usr/lib/i386-linux-gnu/ (0xf18b0000) => /usr/lib/i386-linux-gnu/ (0xf1839000) => /usr/lib/i386-linux-gnu/ (0xf16f0000) => /usr/lib/i386-linux-gnu/ (0xf1692000) => /lib/i386-linux-gnu/ (0xf1565000) => /usr/lib/i386-linux-gnu/ (0xf1450000) => /usr/lib/i386-linux-gnu/ (0xf140d000) => /usr/lib/i386-linux-gnu/ (0xf0faf000) => /usr/lib/i386-linux-gnu/ (0xf0ea4000) => /usr/lib/i386-linux-gnu/ (0xf0e32000) => /usr/lib/i386-linux-gnu/ (0xf0e15000) => /usr/lib/i386-linux-gnu/ (0xf0d61000) => /usr/lib/i386-linux-gnu/ (0xf0d57000) => /usr/lib/i386-linux-gnu/ (0xf0d3a000) => /usr/lib/i386-linux-gnu/ (0xf0d34000) => /usr/lib/i386-linux-gnu/ (0xf0d2d000) => /lib/i386-linux-gnu/ (0xf0c9c000) => /usr/lib/i386-linux-gnu/ (0xf0c5d000) => /usr/lib/i386-linux-gnu/ (0xf0bcb000) => /usr/lib/i386-linux-gnu/ (0xf0bc6000) => /usr/lib/i386-linux-gnu/ (0xf0bbd000) => /lib/i386-linux-gnu/ (0xf0b44000) => /lib/i386-linux-gnu/ (0xf0b1a000) => /usr/lib/i386-linux-gnu/ (0xf0b16000) => /usr/lib/i386-linux-gnu/ (0xf0b10000) => /usr/lib/i386-linux-gnu/ (0xf0afe000) => /usr/lib/i386-linux-gnu/ (0xf0af5000) => /usr/lib/i386-linux-gnu/ (0xf0ae6000) => /usr/lib/i386-linux-gnu/ (0xf0ae1000) => /usr/lib/i386-linux-gnu/ (0xf0ad9000) => /usr/lib/i386-linux-gnu/ (0xf0ad6000) => /usr/lib/i386-linux-gnu/ (0xf0aba000) => /usr/lib/i386-linux-gnu/ (0xf0ab6000) => /usr/lib/i386-linux-gnu/ (0xf0aaf000) => /usr/lib/i386-linux-gnu/ (0xf0aac000) => /usr/lib/i386-linux-gnu/ (0xf0a8d000) => /usr/lib/i386-linux-gnu/ (0xf0a87000) => /usr/lib/i386-linux-gnu/ (0xf0a80000) => /usr/lib/i386-linux-gnu/ (0xf0a6e000) => /usr/lib/i386-linux-gnu/ (0xf0a07000) => /lib/i386-linux-gnu/ (0xf0a01000) => /lib/i386-linux-gnu/ (0xf09d6000) => /lib/i386-linux-gnu/ (0xf09ad000) => /lib/i386-linux-gnu/ (0xf08df000) => /lib/i386-linux-gnu/ (0xf08c7000)

    And finally start the client:
    ~/skype/usr/bin/skype &

  • If you find a need to get a specific file from a Linux live image, but don’t want to reboot, then there’s an easier way how to get your hands on the filesystem.

    For that mount the iso an a virtual filesystem as follows:
    sudo mkdir /media/cdrom
    sudo mount -o loop path/to/file.iso /media/cdrom
    sudo mount -o loop /media/cdrom/live/filesystem.squashfs /mnt

    Take note that the filesystem.squashfs location in the iso varies between distros, it’s easy to find the exact location with
    find /media/cdrom/ -name filesystem.squashfs

    In case you wanted to get debs for a specific package from the mounted iso:
    sudo apt-get install -s packagename | grep Inst | awk '{print $2}' > pkgreq to list required packages
    And finally run cat pkgreq | xargs sudo dpkg-repack --root=/mnt to get those deb(s).

    If you need to set a package “on hold” so it wouldn’t get automatically updated in Debian-based distributions, there are a couple of ways to do it.

    With dpkg:
    echo "packagename hold" | sudo dpkg --set-selections
    To unhold:
    echo "packagename install" | sudo dpkg --set-selections

    With apt:
    sudo apt-mark hold packagename
    To unhold:
    sudo apt-mark unhold packagename

    With aptitude:
    sudo aptitude hold packagename
    To unhold:
    sudo aptitude unhold packagename

    The following lets you determine your openssl key length and size:
    for keyfile in ~/.ssh/id_*; do ssh-keygen -l -f "${keyfile}"; done | uniq
    The output is similar to:
    8192 SHA256:eqKdP2VG3gd0pDApo4K2PyTVfY7ADoOKNE+/vLzDMz4 carry@dragon (RSA)
    Where in this case it’s a SHA-256 RSA-8192 key.

    If it happens that you committed a large file to git like I did (like an iso), in other words, made an oopsie. As you might know, just running git rm --cached bigfile would still keep it in .git history and retain the space on the disk, so we have to come up with something better that that.
    This is how to fix it:
    From the root of your repository, execute
    git filter-branch --prune-empty -d /dev/shm/scratch \
    --index-filter "git rm --cached -f --ignore-unmatch path/to/bigfile.iso" \
    --tag-name-filter cat -- --all

    where the –ignore-unmatch parameter is the file you wish to remove.
    It responds with something similar to this
    Rewrite 3f6277e3d7b938ee5191cdcc461af47ead97dcf2 (27/28) (2 seconds passed, remaining 0 predicted) rm 'Algorithms on Graphs/Week 2/Parrot-full-3.1.1_amd64.iso'
    Ref 'refs/heads/master' was rewritten
    WARNING: Ref 'refs/remotes/origin/master' is unchanged

    After that execute
    git update-ref -d refs/original/refs/heads/master
    git reflog expire --expire=now --all
    git gc --prune=now

    And all is good again.

    This is a rant that I dreamed up, and not a normal technical post. This is to give you a heard’s-up if you are not interested in that.

    Initially the idea came from people ranting and not being able to interrupt them. Have you ever had a moment when someone goes on and on about something and you just can’t get a word in? What if everybody had some sort of a LED light that could be color-coded and there was an universal protocol to the meanings of the colors that you could control either from a smartphone app or something more discrete (standalone buttons in your pocket etc)?

    Then I proceeded to expand the idea to the classroom – what if the teacher could instantly get color-coded feedback from students, for example:
    “I am bored, speed up”
    “You are going too fast”
    “Explain this more in depth”
    “I have a question”
    “This does not make sense”
    Based on this the teacher could immediately know if someone is not on the same page with the rest of the group, or if a lot of people light their LEDs up, there could be a camera in front of the classroom to do aggregations for the whole group. If the entire class is bored, then it means that the teacher can quickly adjust to give a better experience instead of finding out postmortem that something was wrong. The goal of teachers is always to give a good experience to the class, or they would not do it in the first place. This kind of technology could improve the quality of learning.

    The same concept could be extended to the virtual classroom – color codes work much faster than students typing comments and waiting for the lecturer to read them one by one. Also, these can be easily aggregated the same way to a virtual teacher.

    To get a perfect Qualys SSL Labs test score, this is the configuration I used:

     ssl on;
     ssl_certificate /etc/nginx/ssl/meshed.pem;
     ssl_certificate_key /etc/nginx/ssl/meshed.key;
     ssl_session_timeout 5m;
     ssl_session_cache shared:SSL:10m;
     ssl_session_tickets off; # Requires nginx >= 1.5.9 
     # OCSP Stapling ---
     # fetch OCSP records from URL in ssl_certificate and cache them
     ssl_stapling on; # Requires nginx >= 1.3.7, 
     ssl_stapling_verify on; # Requires nginx => 1.3.7
     resolver valid=300s;
     resolver_timeout 5s;
     ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
     ssl_prefer_server_ciphers on;
     # Diffie-Hellman parameter for DHE ciphersuites, recommended >= 2048 bits
     ssl_dhparam /etc/nginx/ssl/dhparam.pem;
     # HSTS
     add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
     add_header X-Frame-Options DENY;
     add_header X-Content-Type-Options nosniff;

    In order to use a stronger DH prime size, create a DH prime that is at least 2048 bits.

    openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096

    For getting a free third-party signed SSL certificate, I recommend usingĀ
    To generate a certificate signing request with openssl, first create a key:

    openssl genrsa -out meshed.key 4096

    and then create a certificate signing request:

    openssl req -new -sha256 -key meshed.key -out meshed.csr

    Restart Nginx and verify results at