Tech Chorus

How To Determine Your Public IP Address Programmatically

written by Sudheer Satyanarayana on 2019-03-30

Short answer: use ipify

ipify provides a simple public address API.

Using the tool, you can determine your public IP address programmatically. If you are using shell:

curl ''

Using it in a shell script:

my_ip=$(curl '' -s)
echo $my_ip

Using the Ansible ipify module:

- hosts: localhost
    - name: Get my public IP
        timeout: 20
      delegate_to: localhost
      register: public_ip
    - name: output
      debug: msg="{{ ipify_public_ip }}"

Sample output of Ansible playbook execution:

ansible-playbook ipify.yml 
 [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] **************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Get my public IP] *******************************************************************************************************************************************************************************************
ok: [localhost -> localhost]

TASK [output] *****************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": ""

PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0

Gavika Ansible Roles

written by Sudheer Satyanarayana on 2019-03-27

Yesterday, we announced the launch of Ansible role to install and configure AWS CloudWatch Agent.

You might have seen my other open source Ansible roles on Ansible Galaxy and Github.

In the same spirit, the company, Gavika Information Technologies Pvt. Ltd. Bangalore, has started publishing open source projects on Github. Ansible role to install and configure AWS CloudWatch Agent is the first project. Expect more projects in future.

These are some of the guidelines for the Ansible role projects that Gavika follows.

Installing AWS CloudWatchAgent On EC2 Instance Via Ansible

written by Sudheer Satyanarayana on 2019-03-26

Install the Ansible role gavika.aws_cloudwatchagent via Galaxy.

ansible-galaxy install gavika.aws_cloudwatchagent

Create The Playbook File - cw-play.yml :

- hosts: all
  become: true
    - role: gavika.aws_cloudwatchagent

Prepare the AWS CloudWatch Agent configuration - aws-cw-config.json:

    "metrics": {
        "namespace": "gavika",
        "metrics_collected": {
            "cpu": {
                "measurement": [
                "metrics_collection_interval": 360,
                "resources": [
                "totalcpu": false
            "disk": {
                "measurement": [
                "metrics_collection_interval": 360,
                "resources": [
            "diskio": {
                "measurement": [
                "metrics_collection_interval": 360,
                "resources": [
            "mem": {
                "measurement": [
                "metrics_collection_interval": 360
            "swap": {
                "measurement": [
                "metrics_collection_interval": 360

In this example, I am using the namespace, gavika. Feel free to change it. We collect the cpu, disk, diskio, mem and swap metrics. The agent will send these metrics once in 360 seconds.

Run The Playbook (CentOS):

ansible-playbook -i, cw-play.yml

The target machine is a CentOS server. Hence you see centos username. I am passing the server name inline. In a production system, you might have a well-defined inventory file. Change the command to suit your needs.

Run The Playbook (Ubuntu)

ansible-playbook -i, cw-play.yml -e ansible_python_interpreter=/usr/bin/python3 -vvv

The Ubuntu server has Python3 by default and Ansible expects Python2 by default. Therefore, I pass the ansible_python_interpreter extra variable from the command line.

After the playbook executes successfully, you should see the metrics in AWS CloudWatch under the namespace specified.

Fedora 29 And Overheating Lenovo W540 Laptop

written by Sudheer Satyanarayana on 2019-03-06

I installed Fedora 29 on a Lenono W540 laptop. The laptop started overheating within a few minutes of booting up.

The output of lspci:

0:00.0 Host bridge: Intel Corporation Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller (rev 06)
00:01.0 PCI bridge: Intel Corporation Xeon E3-1200 v3/4th Gen Core Processor PCI Express x16 Controller (rev 06)
00:02.0 VGA compatible controller: Intel Corporation 4th Gen Core Processor Integrated Graphics Controller (rev 06)
00:03.0 Audio device: Intel Corporation Xeon E3-1200 v3/4th Gen Core Processor HD Audio Controller (rev 06)
00:14.0 USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB xHCI (rev 04)
00:16.0 Communication controller: Intel Corporation 8 Series/C220 Series Chipset Family MEI Controller #1 (rev 04)
00:16.3 Serial controller: Intel Corporation 8 Series/C220 Series Chipset Family KT Controller (rev 04)
00:19.0 Ethernet controller: Intel Corporation Ethernet Connection I217-LM (rev 04)
00:1a.0 USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB EHCI #2 (rev 04)
00:1b.0 Audio device: Intel Corporation 8 Series/C220 Series Chipset High Definition Audio Controller (rev 04)
00:1c.0 PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express Root Port #1 (rev d4)
00:1c.1 PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express Root Port #2 (rev d4)
00:1c.2 PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express Root Port #3 (rev d4)
00:1c.4 PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express Root Port #5 (rev d4)
00:1d.0 USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB EHCI #1 (rev 04)
00:1f.0 ISA bridge: Intel Corporation QM87 Express LPC Controller (rev 04)
00:1f.2 SATA controller: Intel Corporation 8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] (rev 04)
00:1f.3 SMBus: Intel Corporation 8 Series/C220 Series Chipset Family SMBus Controller (rev 04)
01:00.0 VGA compatible controller: NVIDIA Corporation GK106GLM [Quadro K2100M] (rev a1)
02:00.0 SD Host controller: O2 Micro, Inc. SD/MMC Card Reader Controller (rev 01)
03:00.0 Network controller: Intel Corporation Wireless 7260 (rev 83)

The laptop has an NVIDIA Quadro K2100M graphics card.

The solution was to install the NVIDIA proprietary driver via RPMFusion.

First, enable RPMFusion.

sudo dnf install$(rpm -E %fedora).noarch.rpm$(rpm -E %fedora).noarch.rpm

Then, install the NVIDIA drivers.

dnf install xorg-x11-drv-nvidia akmod-nvidia
dnf install xorg-x11-drv-nvidia-cuda 
dnf update -y

Reboot and wait for five minutes till the kernel module is built.

Simple Password Vault With Ansible

written by Sudheer Satyanarayana on 2019-02-17

Ansible comes with a vault feature. It is meant to be used in the context of configuration management. But you can also use it as a standalone simple password vault for your personal or organization's use.

Initial setup of password vault:

At this point, your password vault is setup and pushed to your central Git repository. The next time you want to use it on another or same device, here's the flow you could use:

Keep in mind that Git will treat your password vault as a binary file.

Installing Specific Version Of Ruby On CentOS

written by Sudheer S on 2019-01-08

How do you install a specific version of Ruby on CentOS 7?

The answer: via SCL.

The Ansible role bngsudheer.ruby makes it even more easier.

Create the file ruby_playbook.yml and insert the following contents:

- hosts: my_ruby_servers
    ruby_version: 2.3
     - bngsudheer.ruby

Once done, run the Ansible playbook:

ansible-playbook ruby_playbook.yml

What if I want to install Ruby 2.4 on CentOS?

Just set ruby_version to 2.4. Similarly, if you want to install Ruby 2.5, set ruby_version to 2.5.

It is also possible to enable particular version of Ruby on a per-user basis. For example, to enable Ruby 2.5 for the user myproject user, set ruby_enable_users to ['myproject'].

Systemd Unit File Just To Create A Directory Under /run

written by Sudheer Satyanarayana on 2018-01-19

On recent versions of Fedora, CentOS and RHEL, /var/run and /var/lock are mounted as /tmpfs. Also, /var/run is a symlink to /run. Because of this, if you create a directory under /run it won't stay there after a reboot.

If you are starting to migrate your service to systemd or just want to create a directory under /run using systemd, use this simple unit file. The contents of:

Description=My Service

# We just want to create the myservice run directory

Replace my.service with an appropriate name for your service. Replace the description, User and Group values to your needs.

Start the unit:

systemctl start my.service

Enable the unit so that it starts when the system boots:

systemctl enable my.service

What is wrong in using ExecStartPre=-/bin/mkdir /var/run/myservice?

Systemd can handle directory creation and setting up its attributes for you. You just specifiy the name of the directory in the RuntimeDirectory= directory. When the unit starts, systemd creates the directory and sets its owner and group to the values you specify in User= and Group= directives. So, the counter question is, when systemd can do it for you using a simple directive, why do you want to do it yourself? Also, note that the - prefix just ignores the error when the directory already exists and another attempt is made to create it. Although the error is ignored, it still shows up in red when you check the status of the service.

What is Type=oneshot?

Type=oneshot means the process is expected to exit before systemd starts follow-up units. Along with this, we also specify RemainAfterExit=yes. We tell systemd that my.service shall be considered active even when all its processes exited. When you query the status of the service, you will see that the unit is active because of this directive.

What is ExecStart=/bin/true?

Typically, you would put the path to your service executable in ExecStart= directive. In our example, we're not doing that yet. We're simply using the sytemd unit file to create the /run/myservice directory. So, we use the placeholder command /bin/true. /bin/true simply returns 0 indicating that the command was executed successfully.


journalctl Cheatsheet

written by Sudheer Satyanarayana on 2017-10-26

Between date ranges

journalctl --since "2017-10-20" --until "2017-10-21"

Between date and time ranges

journalctl --since "2017-10-20 10:00:00" --until "2017-10-21 11:00:00"

Friendlier unit values of since and until

journalctl --since "2017-10-20 10:00:00" --until "1 hour ago"
journalctl  --since "1 hour ago"
journalctl  --since "2 hour ago"  --until "1 hour ago"

View particular unit

journalctl -u alertmanager

where alertnamaner is the systemd unit name.

Kernel messages

journalctl -k

By priority

journalctl -p crit

Continuously watch like tail -f

journalctl -fu prometheus

Catalogue and jumping to end in the pager

journalctl -xe

This is particularly useful when your last command results in an error and you want to the most recent errors. The -x flag adds useful descriptive messages to errors when they are available.

Installing Latest Version Of Texlive On Fedora

written by Sudheer Satyanarayana on 2017-05-19

The version of textlive shipped with Fedora 25 was too old for my needs.

$ dnf info texlive
Last metadata expiration check: 22 days, 8:44:09 ago on Wed Apr 26 22:34:24 2017.
Available Packages
Name        : texlive
Arch        : x86_64
Epoch       : 6
Version     : 2016
Release     : 33.20160520.fc25
Size        : 33 k
Repo        : updates
Summary     : TeX formatting system
URL         :
License     : Artistic 2.0 and GPLv2 and GPLv2+ and LGPLv2+ and LPPL and MIT and Public Domain and UCD and Utopia
Description : The TeX Live software distribution offers a complete TeX system for a
            : variety of Unix, Macintosh, Windows and other platforms. It
            : encompasses programs for editing, typesetting, previewing and printing
            : of TeX documents in many different languages, and a large collection
            : of TeX macros and font libraries.
            : The distribution includes extensive general documentation about TeX,
            : as well as the documentation for the included software packages.

Specifically, I wanted the updated version of tex4ebook package. The version shipped by Fedora didn't cut it. So, I had to install newer version of textlive only for certain tasks. So, I downloaded and installed texlive on a separate user account.

adduser somenewuser
su - somenewuser

Go to and get the link to the latest tarball.

wget ''

Unpack the archive.

tar -zxvf install-tl-unx.tar.gz
Execute the installer. Your directory name may vary depending on the build number.
cd install-tl-20170413/

In the installation wizard, set the TEXDIR using the D option. I set mine to ~/texlive/2016/.

The installation takes some time. Enjoy the new version of tex4ebook using the path


This way, you can use the Fedora provided version of texlive on your regular user accounts and custom textlive on special user.


written by Sudheer Satyanarayana on 2017-05-14

VIM Plugins And Notes

The plugins I use for Vim. Recently, I have started using Atom for web development. For rest my editing needs, I use Vim.

For General Editing

For Python Development

For JavaScript

Some Cool VIM Resources