Crypto Price Ticker on the System Tray


Like many other people I love customizing my Linux machine’s system tray. I am using the i3 Window Manager and the conky system monitor in order to show various interesting stats on the system tray. From the CPU temperature and current time, to the amount of I/O the system is performing at any given time.

This is a short post to showcase how this can be achieved and specifically to show how we can also add price tickers for your favorite crypto coins on the system tray.


I will assume that the reader is using i3 and is familiar with its setup process. If you are not using i3 that is also fine since conky can send and display information either in pure text form (which we will use from i3) or using simple progress bars and graph widgets, with different fonts and colours. Check the conky user configuration wiki for more information, examples and screenshots.

i3 and Conky Setup

In order to use conky on the i3 bar, install its package and make sure to have the following inside your i3 config file (~/.i3/config):

# Start i3bar to display conky status
bar {
    font pango:DejaVu Sans Mono 9
    status_command ~/.local/bin/

Essentially this sets the font to be used inside the i3-bar and also specifies a script to run that populates the contents of the bar.


# Send the header so that i3bar knows we want to use JSON:
echo '{"version":1}'

# Begin the endless array.
echo '['

# We send an empty first array of blocks to make the loop simpler:
echo '[],'

# Now send blocks with information forever:
exec conky -c ~/.conkyrc

Above we can see the contents of ~/.local/bin/ It’s a very simple script that notifies the i3-bar that we will be using JSON and then starts an endless JSON array by executing conky with the conkyrc config file.

out_to_x no
own_window no
out_to_console yes
background no
max_text_width 0

# Update interval in seconds
update_interval 2.0

# This is the number of times Conky will update before quitting.
# Set to zero to run forever.
total_run_times 0

# Shortens units to a single character (kiB->k, GiB->G, etc.). Default is off.
short_units yes

# How strict should if_up be when testing an interface for being up?
# The value is one of up, link or address, to check for the interface
# being solely up, being up and having link or being up, having link
# and an assigned IP address. 
if_up_strictness address

# Add spaces to keep things from moving about?  This only affects certain objects.
# use_spacer should have an argument of left, right, or none
use_spacer left

# Force UTF8? note that UTF8 support required XFT
override_utf8_locale no

# number of cpu samples to average
# set to 1 to disable averaging
cpu_avg_samples 2

# Stuff after 'TEXT' will be formatted on screen

# JSON for i3bar

{"full_text": " ❤ $acpitemp°C [$cpu%] ","color": 
              ${if_match ${acpitemp}<50}"\#007000"${else}"\#E60000"${endif}},
{"full_text": " I/O: $diskio", "color":"\#D683FF"},
{"full_text": " GPU: ${execi 60 nvidia-smi -q -d TEMPERATURE | grep Gpu | cut -c39-40}°C",
              "color": "\#3E63D1"},
{"full_text": " ≣ [$memeasyfree] ", "color":"\#B58900"},
{"full_text": " ⛁ / [${fs_free /}] ", "color": "\#99CC33"},
{"full_text": " ⛁ /home [${fs_free /home}] ", "color": "\#99CC33"},
{"full_text": " ≈ ${wireless_essid wlan0} [${wireless_link_qual_perc wlan0}%] ","color":"\#33CC99"},
{"full_text": " ☍ eno1 [${addr eno1}] ","color":"\#33CC99"},
{"full_text": " up [${uptime}] ", "color": "\#3399CC"},
{"full_text": " ${time %Y-%m-%d %H:%M:%S} "}

Pasted above you can see the contents of the conkyrc file I am using. The important part to customize is the JSON for the i3-bar section.

Essentially conky displays the contents of the map we are showing above. The key is always "full_text" and what matters is the value. In the snippet above you should keep entries only if you are interested in them.

You should replace eno1 and wlan0 with the name of your LAN and wireless interface respectively. Additionally if you do not have an nvidia card and/or don’t have the nvidia-utils package you can safely remove the nvidia entry.

All of the above will be updated every 2 seconds, except for the entries which have execi in front. Those allow the user to set the amount of seconds to be used as an interval between executions for that specific conky entry.

Adding a Crypto Price Ticker to conkyrc

In order to add a crypto price ticker to conkyrc, first we have to get the data from somewhere. For this example we will be using the well known cryptocurrency-exchange site kraken and its API.

Kraken uses a very simple REST API which allows you to make simple HTTP queries and get results in JSON format.

For example by going to you will get a JSON dictionary containing the query’s response. Below you can see an example:


To learn what all the different values mean you can consult the API page linked above and you will see this explanatory table:

<pair_name> = pair name
    a = ask array(<price>, <whole lot volume>, <lot volume>),
    b = bid array(<price>, <whole lot volume>, <lot volume>),
    c = last trade closed array(<price>, <lot volume>),
    v = volume array(<today>, <last 24 hours>),
    p = volume weighted average price array(<today>, <last 24 hours>),
    t = number of trades array(<today>, <last 24 hours>),
    l = low array(<today>, <last 24 hours>),
    h = high array(<today>, <last 24 hours>),
    o = today's opening price

In order to add a price ticker we probably want the last closed trade. From the above example we need to extract "10.91835" from the json data. And due to the way conkyrc expects its entries, this operation should be an one-liner.

Using some awesome console magic we can avoid requiring any extra packages. We can achieve this by simply using curl and grep.

echo `curl -s`
| grep -Po '"c":.*?[^\\]",'
| grep  -Po '[0-9.]+'

So in the end the JSON part of the conkyrc becomes:

# JSON for i3bar

{"full_text": " €/Ξ: ${execi 60 echo `curl -s` | grep -Po '"c":.*?[^\\]",' | grep  -Po '[0-9.]+'}", "color":"\#D683FF"},
{"full_text": " €/Ƀ: ${execi 60 echo `curl -s` | grep -Po '"c":.*?[^\\]",' | grep  -Po '[0-9.]+'}", "color":"\#D683FF"},
{"full_text": " ❤ $acpitemp°C [$cpu%] ","color": 
              ${if_match ${acpitemp}<50}"\#007000"${else}"\#E60000"${endif}},
{"full_text": " I/O: $diskio", "color":"\#D683FF"},
{"full_text": " GPU: ${execi 60 nvidia-smi -q -d TEMPERATURE | grep Gpu | cut -c39-40}°C",
              "color": "\#3E63D1"},
{"full_text": " ≣ [$memeasyfree] ", "color":"\#B58900"},
{"full_text": " ⛁ / [${fs_free /}] ", "color": "\#99CC33"},
{"full_text": " ⛁ /home [${fs_free /home}] ", "color": "\#99CC33"},
{"full_text": " ≈ ${wireless_essid wlan0} [${wireless_link_qual_perc wlan0}%] ","color":"\#33CC99"},
{"full_text": " ☍ eno1 [${addr eno1}] ","color":"\#33CC99"},
{"full_text": " up [${uptime}] ", "color": "\#3399CC"},
{"full_text": " ${time %Y-%m-%d %H:%M:%S} "}

One more thing to note is that we used execi 60 in order to not spam Kraken’s server and have our system’s IP blacklisted. The end result is a very nicely looking price ticker on the system monitor as we can see in the picture below.


The example above used Ether and Bitcoin. Note that conky also accepts unicode and as such we are using the unicode symbols for both cryptocurrencies and Euro. Now while working you can be distracted by the price changes of your favorite crypto coins displayed on the system tray 🙂


We explored how to customize the system tray of a Linux machine using conky and giving a concrete example with the i3-bar. We also saw how to add a crypto price ticker by calling into an external server, querying for price data, processing it and populating conky’s endless JSON data that end up being displayed on the i3-bar.

How do you use the system tray in your setup? Do you also use conky? Got any cool scripts or screenshots to show? Got any feedback for the method outlined in this post? If so please don’t hesitate to post in the comments about it.

About the Author


Lefteris Karapetsas is a passionate developer/tinkerer currently located in Berlin.

After graduating from the University of Tokyo, Lefteris has been developing backend software for various companies including Oracle and Acmepacket. He is an all-around tinkerer who loves to takes things apart and put them back together learning how they work in the process.

His interests include language/compiler design, Artifical Intelligence, Robotics, Intelligent Systems and Systems programming. He feels at home with C code and GDB.

More recently he has gained a lot of blockchain expertise since he has been part of Ethereum as a C++ core developer since November 2014, having worked on Solidity, the ethash algorithm, the core client and the CI system. Additionally he is the tech lead of where he took part in connecting Blockchain and IoT with the Ethereum computer and the creation of the DAO.


Twitter: @lefterisjp


System encryption with passphrase protected usb key


The past month a lot of security issues have popped up in my work and personal life most prominent of which was the DAO hack. All these have lead me to think a lot about security and prompted me to learn and utilize new methods I had never used before. All in all I can say that the events of the past few months have made me quite a bit paranoid.

As a result of that I started reading about full system encryption of the root file system and wanted to apply it in a newly installed ArchLinux system. The Archwiki has a very extensive guide on system encryption which can function as a reference to anyone wanting to do the same. One scenario not covered by that guide is how you can encrypt the system with a password protected keyfile located on a USB stick. This is the scenario we are going to cover in this guide.

Encrypting an entire system

We will be using the Device Mapper crypt module in order to encrypt block devices using the Linux Kernel’s crypto API. We assume a very simple setup with 2 partitions. The first partition will be the boot parition and the other is going to be the root partition which we will encrypt.


We will use the Logical Volume Manager (LVM) in order to have a flexible root parition logical volume on top of a LUKS encrypted partition. We will essentially be using the LVM on Luks methodology of the Archwiki but with a big change that will allow us to have a passphrase protected keyfile in a USB stick. I will assume you are attempting to install an ArchLinux machine following the wiki and explain the different/additional steps that need to be taken in order to achieve the encryption.

Preparing the disk

For extra safety you can securely wipe the entire disk using Luks as can be seen here. After that is done and depending on whether you have an UEFI motherboard or not create an UEFI or an MBR boot partition. Also create a root partition. To do so you can use parted. Once you have created the partitions you will need to format them. In the examples below we will assume an UEFI partition and that your drive is /dev/sda. Adjust the commands depending on your drive name.

Create the 2 partitions.

(parted) mkpart ESP fat32 1MiB 513MiB
(parted) set 1 boot on
(parted) mkpart primary ext4 513MiB 100%

Format them accordingly. Here we are creating an UEFI boot partition and an ext4 root partition.

mkfs.fat -F32 /dev/sda1
mkfs.ext4 /dev/sda2

Now we can use cryptsetup in order to create the encrypted container on top of the root partition. You can choose a lot of different options for the encryption like the hash algorithm used for key derivation, or the number of iterations to be used for passphrase processing.

cryptsetup luksFormat /dev/sda2

After that you will have to open the container.

cryptsetup open --type luks /dev/sda2 lvm

The decrypted container is now available at /dev/mapper/lvm.

Preparing the logical volumes

Now we are going to create a physical volume on top of the opened LUKS container.

pvcreate /dev/mapper/lvm

Subsequently create a volume group and create the root logical volume for it. You should change VolName with the name you would like your volume group to have.

vgcreate VolName /dev/mapper/lvm
lvcreate -l 100%FREE VolName -n root

Finally you should format the logical volume and mount it.

mkfs.ext4 /dev/mapper/VolName-root
mount /dev/mapper/VolName-root /mnt

Preparing and configuring the boot partition

For our example we have an UEFI boot partition on /dev/sda1. You can always adjust this guide to any other type of boot partition your system may have. Mount the boot partition and continue with the installation procedure up to the point where you deal with initramfs.

mkdir -p /mnt/boot
mount /dev/sda1 /mnt/boot

The bootloader loads the kernel and the initramfs scripts from the boot partition. The new iteration of initramfs is called mkinitcpio and is essentially a very small early userspace environment which loads various kernel modules and sets up all necessary things before handing control over to init.

We can use the already existing encrypt and lvm2 hooks of mkinitcpio. To enable them edit /etc/mkinitcpio.conf and add them in the HOOKS line. They should be added before the filesystems hook. so in essence it should look like this:

HOOKS="... encrypt lvm2 ... filesystems ..."

Run the following in order to create the updated initcpio scripts.

mkinitcpio -p linux

Now you should figure out the UUID of your physical device. You can do so by running:

blkid /dev/sda2

/dev/sda2: UUID="8197c881-160c-465c-a15c-96b59as26157" TYPE="crypto_LUKS" PARTUUID="fe8d1a97-d10b-43c9-a748-972b0af8a09b"

Replace /dev/sda2 with the partition of your root filesystem. Once that is done then you can edit your bootloader to add the following kernel arguments, which will be picked up by the encrypt initcpio module and decrypt your device at boot. If for example you are using systemd-boot then you should edit /boot/loader/entries/entry.conf like so:

title Arch Linux
linux /vmlinuz-linux
initrd /intel-ucode.img
initrd /initramfs-linux.img

options cryptdevice=UUID=8197c881-160c-465c-a15c-96b59as26157:VolName root=/dev/mapper/VolName-root quiet rw

Remember to change VolName to the name of the volume group you created.

Finally make sure to properly populate /etc/fstab so that after decryption the logical root partition is properly mounted at boot:

# /etc/fstab: static file system information
# <file system> <dir>   <type>  <options>       <dump>  <pass>
# /dev/mapper/VolName-root
UUID=8197c881-160c-465c-a15c-96b59as26157       /               ext4            rw,relatime,data=ordered        0 1

# /dev/sda1
UUID=0C02-13D4          /boot           vfat            rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro    0 2
/dev/mapper/VolName-root /mnt ext4 defaults,errors=remount-ro 0 2

Once that is done then you can simply reboot and you will be prompted for the passphrase to unlock your encrypted root partition at boot. Congratulations you have now encrypted your root partition!

Using an encrypted USB stick

Having an encrypted partition that decrypts simply by typing a password is nice but if a malicious actor learns of your password then he can without any trouble decrypt your root partition and gain access to your data. A method by which you can make this more difficult is to use a 2-factor authentication by having a USB stick with an encrypted passphrase which will act as a key to decrypt the root partition. As such a malicious actor would need physical access to both your USB stick containing the keyfile and to the password that unlocks it.


Create the keyfile

The simplest way to achieve the 2fa effect is to again use LUKS in order to create an encrypted keyfile inside the USB stick. Let’s assume now that the usb stick is located at /dev/sdc1 and that it uuid is 1193c881-267f-134f-123a-12b34as56357.

We now have to mount the usb stick, create a random keyfile in it and encrypt it with Luks. You can change OurKey with whatever name you would like the decrypted Luks volume of the key to have. Also you should replace /dev/sdb2 with the root partition you want to encrypt with that key.

mkdir -p /mnt/stick
mount /dev/sdc1/ /mnt/stick
dd if=/dev/zero of=/mnt/stick/key.luks count=2057 
cryptsetup --align-payload=1 luksFormat /mnt/stick/key.luks 
cryptsetup luksOpen /mnt/stick/key.luks OurKey
dd if=/dev/urandom of=/dev/mapper/OurKey
cryptsetup luksAddKey /dev/sdb2 /dev/mapper/OurKey

Create an initcpio hook

We will create an initcpio hook so that the bootloader can prompt us for the passphrase and decrypt the encrypted partition during the boot process. The beauty of initcpio is that it’s all simply shell scripts and as such they are quite easy to understand.

First of all you should decide on a name for your hook. I called mine lefcrypt but you can use whichever name you want. To create a hook you need to create 2 files under 2 different directories.

Create /usr/lib/initcpio/install/lefcrypt:


build() {
    # Copied from the encrypt hook install script
    local mod

    add_module loop
    add_module dm-crypt
    if [[ $CRYPTO_MODULES ]]; then
        for mod in $CRYPTO_MODULES; do
            add_module "$mod"
        add_all_modules '/crypto/'

    add_binary "cryptsetup"
    add_binary "dmsetup"
    add_file "/usr/lib/udev/rules.d/10-dm.rules"
    add_file "/usr/lib/udev/rules.d/13-dm-disk.rules"
    add_file "/usr/lib/udev/rules.d/95-dm-notify.rules"
    add_file "/usr/lib/initcpio/udev/11-dm-initramfs.rules" "/usr/lib/udev/rules.d/11-dm-initramfs.rules"


help() {
    cat <<HELPEOF
This is our custom hook for decrypting a keyfile from a USB stick.

The above essentially prepares the script, states the required modules for the script to run and also provides a help docstring which will appear if you typed mkinitcpio -H lefcrypt.

Also create /usr/lib/initcpio/hooks/lefcrypt:


run_hook() {
    modprobe -a -q dm-crypt >/dev/null 2>&1
    modprobe loop
    [ "${quiet}" = "y" ] && CSQUIET=">/dev/null"

cat << "EOF"

                                       .-'. . . . . . .`-.
                                     .'  ` . . . . . .  ' `.
                                   .' ` ` . . . . . . '  '  `.
 .----------------------..--.     / `` ` ` ` _.---._ ' ' ' '  \
|  ,                 `--||--.\   / ` ` ` `.-'_.---._`-.' ' ' ' \
|  `                 ,--||--'/  [\ ` ` `.'.-' ..| ..`-.`.' ' '' \
`-----------------------`'--'  _[/ ` ``/.' \ .. |..  / `.\' ' '  \
   |       |                  / / ` ` // `` \  .| . /' ' \\' ' _  \
   |        \__.---------.___/|\ - ` // `. ` \.---./'' .' \\ - _ - |
   |    _.--' ` `` ` ` ` `  /-| \ -  ` = -`. / ___ \ .'- = ||- = - |
   || .'   `` ``  ``` `` `.' -|||::= `---.__/_/   \ \  _.-'||= _ = |
   \ /  ` ``  ` ` ` `.---' [] | |::  ||[_]    ___  \|-'- = ||- _ - |
   |(O]================-------| |    ||[_]   (O__) ||------||- - - |
   / \ ' ''    ''    `---. [] | |::  ||[_]____     /|-._ = ||- _ - |
   || `._ ' ''  ' ''    ' `. -|||::= ,---'  \ \___/ / - `-.||= _ = |
   |     `--.__ ' ' '''' '__\-| / -  , = -.' \     / `. =  ||- = - |
   |        /  `---------'   \|/ _ ' \\ .''' /`---'\`  `. // - _ - |
   |       |                  \_\ ' ' \\ '  /. .|.. \``  // ` `   /
 .--------------------..--.     [\'' ' \`.'/ .. | .. \ .'/ `  ` `/
|  ,               `--||--.\    [/' ' ' `.`-._ .|. _.-'.' `  ` `/
|  `               ,--||--'/     \ ' ' '  `-._`---'_.-' ` ` ` `/
 `--------------------`'--'       \' ' ' '   .`---'.   ` `  ` /
                                   `.'' '' '. . . . `` `  ` .'
                                     `.'' '. . . . . . ` `.'
                                       `-.___ . . . ___.-'

Provide the captain's command authorization code for the USB stick:

    #obtain the key
    mkdir -p /mnt/usbstick
    resolved=$(resolve_device  /dev/disk/by-uuid/1193c881-267f-134f-123a-12b34as56357)
    mount -t ext4 "$resolved" /mnt/usbstick
    cryptsetup -T 5 luksOpen /mnt/usbstick/key.luks OurKey

    #unlock the root partition
    cryptsetup --key-file /dev/mapper/OurKey luksOpen /dev/disk/by-uuid/8197c881-160c-465c-a15c-96b59as26157 lvm

    #clean up the key
    cryptsetup luksClose OurKey

The above is a really simple script which uses the UUID of the usb stick in order to find the key and prompt the user to decrypt it. I could not resist putting a Star Trek reference at the prompt. Apologies :). You should change the UUIDs with your drive’s actual UUIDs and also OurKey with the name you provided for your LUKS encrypted key partition.

In order to use this hook you have to include it in the /etc/mkinitcpio.conf and put it instead of encrypt like so:

HOOKS="... lefcrypt lvm2 ... filesystems ..."

Finally you should create the new initramfs image by issuing mkinitcpio:

mkinitcpio -p linux

==> Building image from preset: /etc/mkinitcpio.d/linux.preset: 'default'
  -> -k /boot/vmlinuz-linux -c /etc/mkinitcpio.conf -g /boot/initramfs-linux.img
==> Starting build: 4.6.3-1-ARCH
  -> Running build hook: [base]
  -> Running build hook: [udev]
  -> Running build hook: [autodetect]
  -> Running build hook: [modconf]
  -> Running build hook: [block]
  -> Running build hook: [lefcrypt]
  -> Running build hook: [lvm2]
  -> Running build hook: [filesystems]
  -> Running build hook: [keyboard]
  -> Running build hook: [fsck]
==> Generating module dependencies
==> Creating gzip-compressed initcpio image: /boot/initramfs-linux.img
==> Image generation successful
==> Building image from preset: /etc/mkinitcpio.d/linux.preset: 'fallback'
  -> -k /boot/vmlinuz-linux -c /etc/mkinitcpio.conf -g /boot/initramfs-linux-fallback.img -S autodetect
==> Starting build: 4.6.3-1-ARCH
  -> Running build hook: [base]
  -> Running build hook: [udev]
  -> Running build hook: [modconf]
  -> Running build hook: [block]
==> WARNING: Possibly missing firmware for module: wd719x
==> WARNING: Possibly missing firmware for module: aic94xx
  -> Running build hook: [lefcrypt]
  -> Running build hook: [lvm2]
  -> Running build hook: [filesystems]
  -> Running build hook: [keyboard]
  -> Running build hook: [fsck]
==> Generating module dependencies
==> Creating gzip-compressed initcpio image: /boot/initramfs-linux-fallback.img
==> Image generation successful

Now once you reboot you can simply input the USB stick and be prompted for the passphrase. Congratulations you now have 2fa in the encryption of your root partition!

Removing the simple passphrase decryption

If you followed this guide step by step then you will still have the option to decrypt the system using the simple passphrase key you created in the first section. If you have confirmed that the USB stick decryption works perfectly then you can safely remove the simple passphrase key.

First check how many keys are used by the encrypted root partition:

cryptsetup luksDump /dev/sda2 | grep BLED

Key Slot 0: ENABLED
Key Slot 1: ENABLED
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED

You should only see 2. Key slot 0 should be the very first simple passphrase key and Key slot 1 the one we just created on the USB stick. You can generally query a lot of information about the keys as can be seen in the related wiki.

If you have used different passphrases for the USB encrypted stick and for the normal passphrase key then it’s quite easy to remove the key without even specifying the slot.

cryptsetup luksRemoveKey /dev/sda2
Enter LUKS passphrase to be deleted:

If you have used the same password then you have to also specify the slot when removing the key.

cryptsetup luksRemoveKey /dev/sda2 0
Enter any remaining LUKS passphrase:

After this action is complete then the only way to decrypt your root filesystem and gain access to your machine would be by using the key located inside the USB stick.


We have presented a way to use a password protected encrypted key located in a usb stick to decrypt the root filesystem of your computer. This provides us with a lot of security and the ability to perform a 2-factor authentication when booting the system in order to protect our data if the computer ever falls into the hands of a malicious actor.

There are disadvantages to this approach. If a malicious actor ever gains access to both your key and your keyfile it is Game Over. At the same time the boot partition needs to be unencrypted to perform the bootloading process. This can introduce vulnerabilities which an attacker could take advantage of. There are some methods that can be followed in order to secure the unencrypted boot partition, such as having it located on an external drive etc.

The presented method is not perfect, but it provides superior security in comparison to a totally unencrypted system and provides a nice basis from which the curious reader can explore many other methods of disk encryption. I hope you enjoyed this post and please don’t hesitate to leave some comments explaining how you use encryption to protect your data and what kind of improvements you believe can be made in the method presented here.