This is practically a place where I put things I that aren’t mine but would hate to go and search online for,again or just things that don’t belong to me that I aquired by fair means. A collection of things I know that aren’t mine if you will. My original thoughts or things I believe are my original thoughts go in my main blog

For those who do not know me, my name is Abraham Raji. I like to make things. I design and build solutions to problems that fascinate me. I consider myself a minimalist who believes in sensible and intuitive design that is beautiful both on the outside as well as under the hood.

A few phrases that could be used to semi-accurately describe me are:

  • Free/Libre Software Enthusiast.
  • Privacy Advocate.
  • Consumer of Art.
  • Open Design Advocate.
  • An advocate of “Be excellent to everyone you see”.
  • Hardware Enthusiast.
  • Debian Contributor.
  • Mozillian.
  • Vector Designer.

Reducers in react

Reducers can seem a bit intimidating at first. I was one of those folks who had written it off as too complicated until recently I got the opportunity to work on a project that extensively leverages the useReducer hook and it forced me to work with it. From my experience, I can say that the hook solves a very specific problem that is updating and managing complex states and yes it is by far the perfect tool for it. I’m not going to explain how the hook exactly works here because the official documentation is actually good. Also when you get to it, useReducer is simple enough that you can understand it by looking at a simple example. Given below is a small example of a counter that uses the useReducer hook to manage it’s state.

import { useReducer } from 'react'

function App() {
  const countReducer = (state, action) => {
    if (action.type === "add")
      return { ...state, count: state.count + state.step }
    else if (action.type === "subtract")
      return { ...state, count: state.count - state.step }
    else if (action.type === "reset")
      return { ...state, count: 0 }
    else if (action.type === "step")
      return { ...state, step: action.step }

  const [state, dispatch] = useReducer(countReducer, { count: 0, step: 1 });

  return (
        onChange={e => dispatch({ type: "step", step: Number( })} />
      <button onClick={() => dispatch({ type: "add" })}>Add</button>
      <button onClick={() => dispatch({ type: "subtract" })}>Subtract</button>
      <button onClick={() => dispatch({ type: "reset" })}>Reset</button>

export default App

One could and should try implementing the same logic with useState first to understand and appreciate how elegant and efficient useReducer makes the whole thing. With useState you’d need two different states to manage the data and the step and the logic to deal with all the actions won’t be as elegant either. Now mind you this is a simple example and in all honesty, could function just fine with useState. But if you are dealing with complex states where say one value is dependent on another or updating one value requires changing/updating multiple other values, useReducer will give you a much better experience than useState. This drastically helps you reduce the number of state transitions required, making your application more performant. It also shines in scenarios where the state is not a number or a string but is a collection or a hash. useReducer also enables us to put the business logic within the hook. This approach is much better than exporting and importing a bunch of functions all the time as one would do within a context.

All that being said, here are a few things you should look out for while using this hook:

  • A huge reducer function that everyone needs to constantly navigate through and refer to in comparison to a scenario where the component and logic or function and function call are close to each other.
  • Redundant actions in reducer due to poor maintenance, especially in large teams or in teams where the people are constantly joining and leaving.
  • Using useReducer where you should be using a context.
  • Not being conservative about adding actions to the reducer.

A bag of rails tips

At the time of me writing this I am a junior full stack developer who works with Rails and React. Rails is a wonderful framework that is more often than not, a joy to work with. Here are a few things I think every beginner working in rails should know, in no particular order. Before I begin, I’d like to make it clear that these are tips even though some of them may feel like hard rules or conventions that are to be followed in every use case and scenario, let me assure you they’re nothing of the sort. Use them at your own discretion.

  • Byebug and Pry, they’re your best friends. Get to know them from day one. Thank me later.
  • Really good methods are not more than a single line long and often don’t take any parameters.
  • If an object/method takes too long to read and understand, then a refactor is in order.
  • Replace temporary variables with queries. (What? and Why?)
  • Refactor early on, the more you wait to refactor the cost of it also increases. It is always a good idea to refactor code to make it more readable.
  • When your language’s/framework’s community has already figured a solution to a common problem, do not try and reinvent the wheel. (Unless you really think there’s something seriously wrong with the solution.). Rails has got you covered in many aspects of building a web app. Get to know your framework. Do it the rails way!
  • Even though it does not say so in the framework’s tag line, Rails is great choice for perfectionists. This is also my way of telling you to aim for perfection.
  • Put a lot of thought into the database design, then start building.
    • Make sure your schema doesn’t leave room for ambiguity.
    • Make sure data is never duplicated within the schema.
    • The schema should pretty much reflect the business logic. All implicit and explicit assertions in the business logic should be reflected in the schema as well.
  • When your models start to get big start assessing your code, a refactor is in order. Of course any web app that you make will have one or two big models. These models are usually what the app is about. If you’re making a blog app the models are usually going to be post and author/user models. These models are allowed to be a little big than the rest but even then be very careful. If a specific functionality is what is making the model bloat maybe you need to put it in a service or maybe you’re trying to squash together, what should be two models into one.
  • On the other had if one model is constantly asking questions about another model to perform it’s functionalities, asses your design again. (Read more)
  • Always use RESTful routes. Keep your controllers small. Methods related to functionality goes in the model or a service, not the controller.
  • Do not be afraid to make simple ruby objects. Remember we are doing OOP, data and functionality stays together.
  • Trust your instincts. If you feel something’s not right, do not be afraid to probe further into whatever’s making you uneasy.
  • Have a mentor, you can learn programming without one but having one just makes everything way more easier.

Setting up Sid Development Environment for Debian Packaging

Why a sid env?

Debian packages are developed for Debian through the Unstable distribution or Unstable Branch. Debian always has three distributions going for it at any point in time. There is a stable branch which is currently Bullseye which is what users put on their production machines and is recommended by Debian for it’s users as it’s officially supported by the community and receives regular updates that resolve bugs and provide security patches. Concurrently Debian also maintains two other Distributions: testing which currently is Bookworm and unstable which always will be Sid. The way this works is when a new release is made the Debian Developers discuss and decide what features they wish to implement in the next release. They work on these features in Sid, which is used to package new packages that are uploaded to the Sid archives and once they’ve proven their usability they’re moved to the testing archives where they’re further tested and worked upon. When all the features that were decided have been implemented and the distribution contains no release-critical bugs, a new version of Debian is released that is when the Testing becomes the new stable and the current stable becomes old-stable. The next stable version will be current testing which is Bookworm and Bullseye at that point will become old-stable. So in short to do packaging we need a Sid env set up somehow. You have many options here namely: use Dual Boot, use VMs, use container tech such as Docker or LXD, create a schroot.

Why schroot?

Schroot is lightweight and easy to set up and use, but the real feature that sells schroot for me is that it uses the same home folder that my base distro uses. So I can access the files that I worked from schroot without entering schroot and there’s a lot less duplication of config files.

Setting a Sid env with Schroot.

If you already have a Debian stable or Debian-based distribution (Arch also has schroot package, though if you have a different distro, you need to check if it has schroot package), this option is best for you. These instructions assume you are already running a Linux Distribution (preferably Debian Stable).

sudo apt install schroot debootstrap

Create root file system: The /srv contains data served by your system, it’s a relatively new folder in Unix, and not a lot of distributions use it. We will create a folder in the /srv directory to home the root files of our Debian Sid env.

mkdir -p /srv/chroot/debian-sid

Now we will use debootstrap to pull the Debian Sid files.

debootstrap sid /srv/chroot/debian-sid

Now create a text file /etc/schroot/chroot.d/debian-sid with your favorite text editor and add the following lines to it:

description=Debian Sid for building packages suitable for uploading to debian
users=<your username>

Where <your username> is an underprivileged user on your host system.

And there you go! We have successfully set up a Debian Sid env that you can now use to package Debian packages.

Using Schroot.

To enter schroot as a superuser, enter the following from a terminal.

sudo schroot -c debian-sid

W: Failed to change to directory '/ ... is a common warning and can be ignored for now.

Now that you’re in schroot play around a bit. Install your favorite applications:

apt-get update && apt-get install <some-package>

Once you’re done just type in exit and hit enter to exit the schroot.

To run schroot as a normal user, type in:

schroot -c debian-sid

You will notice that your home folder in your base system is still your home folder and all the files are accessible to you and your configs such as your .bashrc will work here too.

Setting up sudo

Maybe you don’t want to exit out of your normal user and re-enter schroot as the root user every time you want to install a dependency for a package and want sudo. You can set it up the same way you would in a regular distro.

First, enter the schroot as root with the command given above and install sudo with

apt install sudo

Once that is done add your user to the sudo group with this command:

usermod -aG sudo <your username>

Now you can exit from the root shell and re-enter schroot as a normal user and run sudo.

How to make sure you’ve set up everything correctly?

Run the command cat /etc/debian_version and it should give you an output as shown below.

❯ cat /etc/debian_version

Using GnuPG

GNU Privacy Guard (GnuPG or GPG) is a free (as in freedom) software replacement for Symantec’s PGP cryptographic software suite, and is compliant with RFC 4880, the IETF standards-track specification of OpenPGP.

Basically a piece of software that lets you generate public-private key pairs which can then be used for things like encrypting your mail, signing commits, storing passwords and more.

Modern versions of PGP are interoperable with GnuPG and other OpenPGP-compliant systems.

So technically it doesn’t matter what system you use as long as you make sure that they’re compliant with the OpenPGP standard but GnuPG is free software and so that is what I use.

Generating a GPG key pair

You can genrate a key pair with the following command:

gpg --full-gen-key

Upon which you’ll recieve the following menu:

gpg (GnuPG) 2.2.20; Copyright (C) 2020 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
  (14) Existing key from card
Your selection?

Here GPG is asking you to choose an encryption algorithm that your key will use. I would suggest you either go with DSA or RSA, simply because both have well defined specifications, are widely used and at the time of me writing this blog equally secure. However it’s always a good idea to do some research on your own.

Once you make your choice you’ll have to make another decision, Keysize.

RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072)

I usually go with 4096 because why not? It takes a few extra seconds to make but that’s an accaptable trade of for me.

Then we choose how long we want the key to be valid.

Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0)

For most cases you should be fine with the key does not expire option but if you’re not like me and can handle keeping track of the key’s expiration date and is okay with generating new one when the current one is expired go ahead and set a time period for automatic expiration of the key.

Is this correct? (y/N)

Put a y.

Now to add your information to the key.

GnuPG needs to construct a user ID to identify your key.

Real name: Name
Email address:
Comment: Comment
You selected this USER-ID:
    "Name (Comment) <>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?

Unless your version of GPG has some weird bug this step should be go smoothly. If everything looks good type in O and hit Enter.

At this point you’ll receive a message about how your key is being generated and GPG needs entropy to create random numbers and so on. Just keep using the system as you would and depending on your algorithm and keysize the process should take anywhere between a second to a couple of seconds.

What to call my key?

Now that you have a key what do you call it? GPG is the software here. PGP is the actual system. You could say ‘GPG Key’ and that is widely used too but that wouldn’t exactly be accurate. The most accurate term would be an ‘OpenPGP key’.

Backing Up keys

To export your GPG private key, run the following command on your terminal:

gpg --export-secret-keys --armor name > /path/to/secret-key-backup.asc

As an addition, you can also backup the GPG trust database.

gpg --export-ownertrust > /path/to/trustdb-backup.txt

Now to restore the GPG Key:

gpg —-import /path/to/secret-key-backup.asc

And to restore your GPG trust database, run the following command:

gpg --import-ownertrust < /path/to/trustdb-backup.txt

Signing commits

First we need to list all the keys first:

gpg --list-secret-keys --keyid-format LONG <your_email>

This will list all your GPG keys. Copy the GPG key ID that starts with ‘sec’ and add this as the key to sign commits in git using the following commit:

git config --global user.signingkey <GPG Key ID>

Optionally you can ask git to sign commits automatically using the following command:

git config --global commit.gpgsign true

Simple Packaging Tutorial: The Long Version

This page is intended to aid the attendees of the ഡെബിയന്‍ പാക്കേജിങ്ങ് ബാലപാഠങ്ങള്‍ പഠിയ്ക്കാം (Simple Packaging Tutorial with debmake) workshop held at the Malayalam MiniConf during DebConf 20 on 28th August 08:30 PM - 10:15 PM IST.

The workshop was taken by Pirate Praveen who is a Debian Developer and me. This page adheres to the structure of the workshop and provides additional information that is otherwise spread across multiple pages in the Debian Wiki.

You could refer Simple Packaging Tutorial (a shorter version of this) on the Debian Wiki.

Having a Debian Unstable System is a pre-requisite to this workshop. If you haven’t set one up yet, you can follow this tutorial to set up an unstable system on your machine using schroot.

Every command we execute in this tutorial will be done in the Unstable System.

Step 0: Getting Organized

First, let’s get organized, let’s create a folder in our home directory dedicated to packaging. You can do so from the terminal itself by running the following command:

mkdir <directory name>

Where <directory name> is pretty much anything you wish to name the folder where you’ll put all the files related to packaging. I’ve named mine Debian.

Keeping things organized will help you when working with complex packages in the future. It will avoid confusion and help you stay on top of things without getting overwhelmed. Now once we’ve created the said directory let’s switch to it using the cd command

cd <directory name>

Packaging is often a straightforward ordeal. The process of packaging remains more or less the same regardless of whether it’s a JS or a python or a language x package. For this tutorial, we will be packaging a node module called pretty-ms.

Step 1: Acquire the source code.

To begin we need to first collect the source code of the piece of software that we intend to package, which in our case is pretty-ms. So let’s go to npmjs for pretty-ms. There on the right side of the page, we can find the link to the repository and this is where we can find the source code. The source to pretty-ms is hosted here. What this package pretty, much does is convert time produced in milliseconds to more human-friendly formats such as hours, minutes, and seconds.

If we go through the files, we can find the following files:

  • package.json: contains the metadata of the node module
  • some basic information about the node nodule respectively.
  • index.js: The main file where the module actually lives.
  • test.js: contains tests for the module to test it’s functionality.
  • LICENSE: contains the copyright information which will be useful later on.

Now on Github, we have the ‘Releases’ page which contains various versions of the module. Other platforms might call this page something else but fear not, most developers tag their versions/releases in git so that is somewhere you can be sure to find versions/releases, if the platform that you encounter does not have a straightforward place to download releases from. Here the latest version of pretty-ms is 7.0.0. Let’s download the source code in tar.gz format. Apart from tar.gz, tar.bz2 and tar.xz are also used by developers. The difference between them is the algorithm used to compress the files. When you compare bz2 and gz you will find that bz2 has smaller file sizes but require more time to compress and decompress whereas gz has comparatively larger file sizes but is very fast in compressing and decompressing the files. It’s the developer of the package who decides which one to use.

Now, we can download it from the browser itself but what’s the fun in that? Let’s copy the link and use wget to download the tar file. So let’s first install wget in out schroot env and download the file using it. Do this from the directory we created earlier that is dedicated to packaging.

sudo apt install wget

Package Name

Debian has specifications and formats for everything associated with a Debian package and there’s a format for the source tarball’s name too. This format is <packagename>_<version>.orig.<tarball format>.

As far as the package names go, if the piece of software we are packaging is something the users will run themselves for example Firefox, Rollup, Rails, etc. we usually name the package the actual name of the software itself. If we take the above examples, their package names will remain firefox, rollup and rails. On the other hand, if it is a library that the users won’t necessarily run themselves, we use a different naming convention. The convention used is here is as follows: the system or programming language or framework the library was made for, followed by a hyphen and then the package name sometimes the system or programming language or framework comes after the name of the library (whether it comes before or after the name of the package is a convention set by the team that maintains the library.). If the module we intend to package is made for Node JS we add node before the package name and if the package is relevant for JS, in general, we add libjs before the package name. Again this is only applicable to libraries and not to be used for user-facing executable programs. Since pretty-ms is a module made for Node JS, the name will be node-pretty-ms. Another important thing to note is that we do not use underscores or uppercase characters in our package names, if your package contains an underscore convert those to hyphens and the upper case characters to lowercase characters when naming your package.

Now let’s complete the name of our tarball. So first comes the package name which is node-pretty-ms, next we add an underscore followed by the version of the package which is 7.0.0 and finally .orig.tar.gz. So at the end the whole thing looks like node-pretty-ms_7.0.0.orig.tar.gz .

Step 2: Debianization

Now let’s go ahead and extract the contents of our tarball with the following command:

tar -zxvf node-pretty-ms_7.0.0.orig.tar.gz

tar is one of those commands that may seem unusable at the beginning, with the -zxvf and everything but in the long run using the command line will save you a lot of time once you get used to it. If you folks have any doubts regarding any program in your distribution, just type in man <package name> into your terminal to see the options that package provides you.

Now let’s change the name of the directory according to the above mentioned naming convention except no underscore before the version number, instead of underscore for the directory we use a hyphen. The mv command can be used to do this.

mv pretty-ms-7.0.0 node-pretty-ms-7.0.0

Now let’s change into that directory using the cd command. The contents of the folder should look something like this:

drwxr-xr-x 3 avronr avronr  4096 Apr 27 11:42 .
drwxr-xr-x 3 avronr avronr  4096 Aug 28 10:00 ..
-rw-r--r-- 1 avronr avronr   175 Apr 27 11:42 .editorconfig
-rw-r--r-- 1 avronr avronr    19 Apr 27 11:42 .gitattributes
drwxr-xr-x 2 avronr avronr  4096 Apr 27 11:42 .github
-rw-r--r-- 1 avronr avronr    23 Apr 27 11:42 .gitignore
-rw-r--r-- 1 avronr avronr  2948 Apr 27 11:42 index.d.ts
-rw-r--r-- 1 avronr avronr  3697 Apr 27 11:42 index.js
-rw-r--r-- 1 avronr avronr   833 Apr 27 11:42 index.test-d.ts
-rw-r--r-- 1 avronr avronr  1109 Apr 27 11:42 license
-rw-r--r-- 1 avronr avronr    19 Apr 27 11:42 .npmrc
-rw-r--r-- 1 avronr avronr   855 Apr 27 11:42 package.json
-rw-r--r-- 1 avronr avronr  3333 Apr 27 11:42
-rw-r--r-- 1 avronr avronr 12608 Apr 27 11:42 test.js
-rw-r--r-- 1 avronr avronr    45 Apr 27 11:42 .travis.yml

If your file structure looks like this then you’re good. If not retrace your steps and find what went wrong.


In the next section, we are starting the debianization process and traditionally we do it using the package debmake. But if you try to run debmake, you probably will hit an error. This is a known issue with debmake and JavaScript packages. Don’t worry all hope is not lost, we have another tool called dh_make which we can install by running sudo apt install dh-make. Basically the only thing that’s changed in the tutorial from this point on is that instead of running debmake we run dh_make.

Next, we begin the actual Debianization which is done using a tool called Debmake that generates the debian/ directory. Let’s install debmake using sudo apt install debmake and run debmake.

If you ran dh_make you should get a prompt like so:

Type of package: (single, indep, library, python)

The answer to the prompt here is single, so press s which should give you the following output:

Type of package: (single, indep, library, python)
Maintainer Name     : Abraham Raji
Email-Address       :
Date                : Tue, 12 Sep 2023 19:18:34 +0530
Package Name        : node-pretty-ms
Version             : 8.0.0
License             : blank
Package Type        : single
Are the details correct? [Y/n/q]
Skipping creating ../node-pretty-ms_8.0.0.orig.tar.gz because it already exists
Currently there is not top level Makefile. This may require additional tuning
Done. Please edit the files in the debian/ subdirectory now.

After running debmake/dh_make, the file structure should look something like this:

 ├── debian
 │   ├──  changelog
 │   ├──  compat
 │   ├──  control
 │   ├──  copyright
 │   ├──  patches
 │   ├──  README.Debian
 │   ├──  rules
 │   ├──  source
 │   └──  watch
 ├──  .editorconfig
 ├──  .gitattributes
 ├──  .github
 |     └── funding.yml
 ├──  .gitignore
 ├──  index.d.ts
 ├──  index.js
 ├──  index.test-d.ts
 ├──  license
 ├──  .npmrc
 ├──  package.json
 ├──  test.js
 └── .travis.yml

Step 3: Creating a source package

Next, let’s create a source package using dpkg-source -b .. If you guys don’t have dpkg-source in your system you can get it by running sudo apt install build-essential. The output of which should look like this:

❯ dpkg-source -b .
dpkg-source: info: [[[using source format '3.0 (quilt)']]]
dpkg-source: info: [[[building node-pretty-ms using existing ./node-pretty-ms_7.0.0.orig.tar.gz]]]
dpkg-source: info: [[[building node-pretty-ms in node-pretty-ms_7.0.0-1.debian.tar.xz]]]
dpkg-source: info: [[[building node-pretty-ms in node-pretty-ms_7.0.0-1.dsc]]]
  1. If you look through this log you will see dpkg-source mentioning that it is using the quilt 3.0 source format.
  2. You will also notice that is using the .orig.tar.gz file that we created earlier
  3. It has built a tar of the debian directory too. But there is also something new here, the file is named node-pretty-ms_7.0.0-1.debian.tar.xz where you can see that there is a -1 after the version number. That number is called the Debian revision number. Say we packaged a piece of software and uploaded it to the Debian archives and then someone reported a bug and we made a fix. Now you see we have different ‘revisions’ of the same package (one with the fix and the other without) with the same version number that we wish to release in the archives. So to help keep a track of this change we have a Debian revision number which is just a count of the number of times that particular version package was released into the Debian archives. So if we have made a bug fix in node-pretty-ms and released it again to the archives it will be released as node-pretty-ms_7.0.0-2.
  4. Lastly we have the node-pretty-ms_7.0.0-1.dsc file. This file is a security measure. If you look into that file you file, you will find information regarding the package extracted from the files in our debian directory and the check-sums of files node-pretty-ms_7.0.0.orig.tar.gz and node-pretty-ms_7.0.0-1.debian.tar.xz. This is so that others can check the integrity of these files once they have downloaded them from the archives after a Debian Developer uploads them there. These three files together form the Debian Source Package.

The .dsc file

Let’s look at the contents of the .dsc file real quick.

Format: 3.0 (quilt)
Source: node-pretty-ms
Binary: node-pretty-ms
Architecture: any
Version: 7.0.0-1
Maintainer: Abraham Raji <>
Homepage: <insert the upstream URL, if relevant>
Standards-Version: 4.1.4
Build-Depends: debhelper (>= 11~)
 node-pretty-ms deb unknown optional arch=any
 28bb69ab4720c07dcdd73520b1305137ae354f90 6142 node-pretty-ms_7.0.0.orig.tar.gz
 329139a95e273617ecfdb41466325cede4fa983d 2004 node-pretty-ms_7.0.0-1.debian.tar.xz
 256871d7b49dc76e33d841e46c5d36008858aceea9081d9e62c7f5760e65ea33 6142 node-pretty-ms_7.0.0.orig.tar.gz
 3e28122e5bbcb1c771c7431b9af90bc74da45c0461be3a6bc8bcadd73e930707 2004 node-pretty-ms_7.0.0-1.debian.tar.xz
 ab6e9b3155d0cd73b54d4f0ba8dd0774 6142 node-pretty-ms_7.0.0.orig.tar.gz
 1d7cf58aef1718817cece400cb978ad9 2004 node-pretty-ms_7.0.0-1.debian.tar.xz

We can see a bunch of information here such as the format used, which as we saw before is quilt 3.0. The source field gives us the name of the Debian source repository from which the package was generated. The binary field gives the name of the binary package generated from the source repository. Next, we have Architecture which gives us the architectures you can install this package on, here since it’s a JS package it can be installed on all architectures and that field should actually say all, but debmake hasn’t learned to detect that yet so it put any there, for now, we’ll fix that later. Then we have the version followed by the information about the person working on the package (which debmake got from my .zshrc which is where I’ve put it and if you use bash you can put it in your .bashrc and Debmake will pick that up). Next, we have the Homepage field where we can put the link to the homepage of the package. Next is Standards-Version which tells us which Debian policy the package follows and set to the version number of the package debian-policy, this is also a bit outdated and we will fix it later. The next field is Build-Depends which specifies the packages needed to build executable files from the source. Next, we have the checksums we mentioned above in three formats, Sha1, Sha256 and MD5.

Step 4: Building, Making Fixes and Satisfying Lintian


Now that we have the source package we can build it. We need to be in the node-pretty-ms-7.0.0 folder to build it. Inside the folder, we will execute the dpkg-buildpackage command which will build the package for us. The output of that command will look something like this:

❯ dpkg-buildpackage
dpkg-buildpackage: info: source package node-pretty-ms
dpkg-buildpackage: info: source version 7.0.0-1
dpkg-buildpackage: info: source distribution UNRELEASED
dpkg-buildpackage: info: source changed by Abraham Raji <>
dpkg-buildpackage: info: host architecture amd64
 dpkg-source --before-build .
 fakeroot debian/rules clean
dh clean
 dpkg-source -b .
dpkg-source: info: using source format '3.0 (quilt)'
dpkg-source: info: building node-pretty-ms using existing ./node-pretty-ms_7.0.0.orig.tar.gz
dpkg-source: info: building node-pretty-ms in node-pretty-ms_7.0.0-1.debian.tar.xz
dpkg-source: info: building node-pretty-ms in node-pretty-ms_7.0.0-1.dsc
 debian/rules build
dh build
   create-stamp debian/debhelper-build-stamp
 fakeroot debian/rules binary
dh binary
dpkg-gencontrol: warning: Depends field of package node-pretty-ms: substitution variable ${shlibs:Depends} used, but is not defined
dpkg-deb: building package 'node-pretty-ms' in '../node-pretty-ms_7.0.0-1_amd64.deb'.
 dpkg-genchanges  >../node-pretty-ms_7.0.0-1_amd64.changes
dpkg-genchanges: info: including full source code in upload
 dpkg-source --after-build .
dpkg-buildpackage: info: full upload (original source is included)
dpkg-buildpackage: warning: not signing UNRELEASED build; use --force-sign to override

Since it is a simple package, it will build successfully. Also, if we look at the parent directory we have a few new files:

❯ ls ..
node-pretty-ms-7.0.0                    node-pretty-ms_7.0.0-1.debian.tar.xz
node-pretty-ms_7.0.0-1_amd64.buildinfo  node-pretty-ms_7.0.0-1.dsc
node-pretty-ms_7.0.0-1_amd64.changes    node-pretty-ms_7.0.0.orig.tar.gz

Most notable of the new files are the .buildinfo, the .changes and the .deb files.

  • .buildinfo gives us the info regarding the packages that were in our distribution at the time of building.
  • .changes gives us a lot of information that you could also find in the .dsc file but also contents of the debian/changelog file.
  • the .deb file is something we’re all familiar with and is what we use to install the package in our system.

Now if we install the generated .deb file and run the command dpkg -L node-pretty-ms (which essentially gives us all the files associated with that package in our system) you will see that the important files such as the index.js or package.json was not installed. So even though we have a source package that builds and installs properly we haven’t installed the package to our system yet. Let’s start fixing this.

Making fixes

First, let’s fix the architecture which can be fixed by editing our debian/control file. The control file has a section for Architecture which currently is set to any and we will set that to all. Let’s open a text editor of choice and make the necessary change. This is probably how it will look at first.

Source: node-pretty-ms
Section: unknown
Priority: optional
Maintainer: Abraham Raji <>
Build-Depends: debhelper (>=11~)
Standards-Version: 4.1.4
Homepage: <insert the upstream URL, if relevant>

Package: node-pretty-ms
Architecture: any
Multi-Arch: foreign
Depends: ${misc:Depends}, ${shlibs:Depends}
Description: auto-generated package by debmake
 This Debian binary package was auto-generated by the
 debmake(1) command provided by the debmake package.

There are a few things we can fix here, namely:

  • Section: this is a JS package. So set it to javascript.
  • Standards-Version: this is also using an old version, so set it to the new one, which is 4.5.0
  • We could also add the homepage link
  • The Architecture ofcourse.
  • Add a description too. You can find this from the package’s homepage or

Once you’ve made these changes, the file should look something like this:

 Source: node-pretty-ms
 Section: javascript
 Priority: optional
 Maintainer: Abraham Raji <>
 Build-Depends: debhelper (>=11~)
 Standards-Version: 4.5.0
 Package: node-pretty-ms
 Architecture: all
 Multi-Arch: foreign
 Depends: ${misc:Depends}, ${shlibs:Depends}
 Description: Convert milliseconds to a human readable string

Next, let’s tell Debian what files to install. We can do so in a file inside the debian directory called install. In this case, we want to install the index.js, index.d.ts, and the package.json file. In debian we install these files to /usr/share/nodejs/<module-name>/ (one thing to note here is that we don’t use the debian name here but the actual name of the package for the folder). So open the debian/install file with your favorite text editor and add the required files. Once you’ve done that the debian/install file should look something like this:

❯ cat debian/install
index.js usr/share/nodejs/pretty-ms
index.d.ts usr/share/nodejs/pretty-ms
package.json usr/share/nodejs/pretty-ms

Let’s build again using dpkg-buildpackage. If you installed the previous .deb file you should remove it before you install the new one we just generated. Now if we install the new .deb file and run the command dpkg -L node-pretty-ms, we can see that all the required files were installed properly.

Next, let’s fix the copyright file. We can find the missing information in that file from the upstream license file. Right now it will look something like this:

Upstream-Name: node-pretty-ms
Source: <url://>
# Please double check copyright with the licensecheck(1) command.

Files:     .editorconfig

Files:     license
Copyright: Sindre Sorhus <> (
License:   Expat
 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

# Files marked as NO_LICENSE_TEXT_FOUND may be covered by the following
# license/copyright files.

# License file: license
 MIT License
 Copyright (c) Sindre Sorhus <> (
 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Softw

Make sensible changes here. One thing to note here is that a single line should not have more than 80 characters. Once you’re done, it should look something like this.

 Upstream-Name: node-pretty-ms
 Files:     *
 Copyright: Sindre Sorhus <> (
 License:   Expat
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/ or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions: .
  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

Satisfying Lintian

Now run the dpkg-buildpackage again so that the changes we made take effect. As of now, we have resolved all the basic issues. Lintian will help us find the ones that we missed, lintian by default will give short messages but detailed descriptions will help us solve these issues. in order to do that let’s set an alias in our shell’s rc file (~/.bashr or ~/.zshrc). So pul the following lines in your .bashrc or .zshrc

alias lintian='lintian -iIEcv --pedantic --color auto'

Now run lintian and it will throw a bunch of complaints on your face. We need to pay attention to the lines that start with E: (error) or W: (warning). Let’s fix an E: which complains that changelog-is-dh_make-template. If you read through the description of the error you’ll see that the issue is in the debian/changelog file. Let’s take a look at the file:

node-pretty-ms (7.0.0-1) UNRELEASED; urgency=low

  * Initial release. Closes: #nnnn
    <nnnn is the bug number of your ITP>

 -- Abraham Raji <>  Fri, 28 Aug 2020 16:05:03 +0530

The issue is that when we wish to package a new package, we need to send an ‘Intend to Package’ mail that gets registered as an ITP Bug. This helps coordinate packaging work and prevent duplicate work. The bug has a unique identification number which we put in the changelog after the hashtag in * Initial release. Closes: #nnnn. So we need to check for existing bugs before we create a new ITP bug. We could search for existing bugs at Now we can solve this error by removing the line <nnnn is the bug number of your ITP> and adding the ITP bug number. For the sake of this workshop, we’re going to add a random number there. Once we do that the file should look something like this:

node-pretty-ms (7.0.0-1) UNRELEASED; urgency=low
   * Initial release. Closes: #982937
  -- Abraham Raji <>  Fri, 28 Aug 2020 16:05:03 +0530

We still have more complaints to solve but to keep the size of this page somewhat reasonable, I’m not going to include fixes to all the complaints in this page. That being said, here’s an example from a package I updated a while ago. It is sort of a jackpot, in the sense it has a bunch of fixes to common lintian complaints I’ve come across. Commit messages could be a little better and more creative though.

In this workshop we did a lot of things manually, like visit websites, rename files, collect tarballs, etc. but technically we didn’t really have to do all that manually. We actually have tools that do most of what we already did. For JavaScript and node packages the tool is called npm2deb and for ruby it’s gem2deb. You should be able to find others as well. The reason we went through all that in this tutorial is because it is important for you to know and understand what is happening under the hood.

Further Reading

  • Here’s a wiki page giving a tutorial on how to use npm2deb.
  • Here’s a wiki page I wrote regarding updating packages.

Updating a Debian Package

Every GNU/Linux distribution has its own package manager and package format. For Debian it’s apt and .deb. Debian packaging is quite interesting, there’s a fair bit of information that is included in a Debian source package. This page deals with updating a Debian package to a new upstream release.


When to update a package?

How frequently a package is updated varies from package to package. It’s usually as per the discretion of the maintainer of the package. Usually, there are software packages that are the main products that our users primarily interact with such as Firefox, Gitlab, Emacs, etc., and then there are other pieces of software and libraries that are required for the above-mentioned software packages to function. These packages are called dependencies. Dependencies are usually only updated to a newer version when their dependents (the main software products we mentioned above) require a newer version of the dependency.

The rationale for such a system comes from Debian’s core policy of preferring stability over shiny new features. It’s more important that every software package currently in Debian works well with other software packages in Debian.

What do you need to update a Debian package?

  1. A system running Debian. It’s possible to package for Debian using Ubuntu or Mint or any Debian-based distro but doing it from a Debian system in my experience, has given me the least headaches.

  2. A virtual Debian Unstable env. Debian has three to four distributions active at all times: Old-Stable (Currently Stretch), Stable (Currently Buster), Testing (Currently Bullseye) and Unstable (Always Sid). We do packaging on sid. Every package truly only enters Debian once it is in sid, the unstable distribution. It is here that critical bugs are found, reported and fixed. Once a package reaches a level of stability in sid, it’s moved to the current testing repo. At any point, sid has the latest version of any package in Debian. This helps people like me (and hopefully you) who package software for Debian. Sid BTW is the only Debian rolling release distribution. You could compare it to Archlinux. This page is quite long as it is so I’m not going to make it longer by adding instructions to set up a Debian Unstable env. Here’s a Debian Wiki Page that tells you how to do that. Might add a page for this too in the future but not now. On that page, I would suggest going with schroot because it’s very a simple option.

    Update: I’ve made a wiki page on how to set up a Debian Sid env here.

  3. Ability to work from a terminal. You don’t need to be a unix wizard. Just know your way around a terminal or this is going to be a lot harder.

  4. Steady internet connection.

  5. If you’re not a Debian developer you need a Debian Developer to sponsor your package (upload your package).

Getting Started

  1. Get the Unstable env up.
  2. Install the required packages:
    sudo apt install devscripts git git-buildpackage lintian
  3. Create an account on Salsa- Debian’s Gitlab instance.
  4. Add the following to you .bashrc or .zshrc:
    export DEBEMAIL=your@email.domain
    export DEBFULLNAME='Your Name'
    alias lintian='lintian -iIEcv --pedantic --color auto'
    alias git-import-dsc='git-import-dsc --author-is-committer --pristine-tar'
    alias clean='fakeroot debian/rules clean'

Steps to update

I’m going to use ruby-health-check, a package I recently worked on as an example. The general steps remain the same for almost all packages.

  1. First fork and clone the salsa repo using git-buildpackage i.e gbp:

    gbp clone --pristine-tar

    We use gbp for convenience purposes because it does a lot of things automatically. For example, most Debian source package has three branches: master, upstream, and pristine-tar. The Master branch is usually where we work and build the package, upstream just has untouched upstream files and pristine-tar has instructions to the pristine-tar tool to generate the same tarball from the upstream branch and tag. If we clone using git it will only clone the repo and the default branch but when we use gbp all three branches will be pulled from salsa.

    If we used git we would have had to:

    git clone
    git checkout upstream
    git checkout pristine-tar
    git checkout master

    So using gbp clone will save us some effort.

  2. Next cd into the directory and download the new upstream release tarball using the command:

    uscan --verbose

    Sometimes when using uscan, the download link would have deprecated and uscan won’t work, at that point your options are either to fix the download link which can be found at debian/watch or to manually download the tarball from the upstream releases page. I prefer to fix the link at debian/watch whenever possible and it is fixable in most cases. Here’s an example of me fixing the debian/watch file for another package. Here are the instructions to manually download upstream sources when necessary.

  3. If you used uscan to download the tarballs you should see a tarball named package-name_upstream-version.orig.tar.gz in the directory, you cloned the repo in. Import the orig.tar.gz using:

    gbp import-orig --pristine-tar ../ruby-health-check_3.0.0.orig.tar.gz
  4. We need to tell the operating system that we have imported a new version into the repo. We do that by adding an entry in the debian/changelog file. We do so by running the following command: gbp dch -a. What this will do is add an entry to debian/changelog file that looks something like this:

    ruby-health-check (3.0.0-1) UNRELEASED; urgency=medium
        * New upstream version 3.0.0
    -- Abraham Raji <>  Thu, 13 Aug 2020 16:17:14 +0000

    As I mentioned above Debian takes bugs seriously and the team works constantly on improving the quality of the software, so the package maintainers often update the packages with patches, missing tests etc., so a single version of the package can have multiple revisions that are uploaded to unstable. To keep track of this we add a Debian revision number to the end of the upstream version number. So how the version number looks at the end is upstream-version-debian-revision. Above, you can see the version is 3.0.0-1, which means the upstream version of the package right now is 3.0.0 and 1 signifies that this is the first revision of the said package in Debian. To learn more about versioning checkout:

    Sometimes gbp can mess up the version number if there is an UNRELEASED entry already. In this sense, it will add your entry as a new revision of the previous version. In that case, you can open the file in a text editor of your choice and manually change the version number.

  5. Now we build. Run:


    For minor updates, i.e. a.b.c-d => a.b.e-1 there shouldn’t be any problem. The build will complete successfully almost always. If it’s not a minor update, things may not `just work`. Sometimes you may have issues where you need a newer version of a dependency for this version of our package to work, so we may have to update that package first and come back to this one or there are patches in debian/patches made by package maintainers in case a change needs to be made and for some reason, the upstream maintainer can’t make that change in the upstream, these patched may no longer work when switching from one major version to another. So we need to fix these issues and successfully build the package. When do you know you’ve successfully built it? Ironically it is when you get a warning saying something along the lines of ‘failed to sign your .dsc file’. You don’t need to worry about that since the person uploading the package will be the one to sign it.

  6. Next, we look for policy violations using lintian. When you successfully build a package a file named package-name_version-number_debian-revision-architecture.changes is generated in the parent directory which if you pass it on as an argument to lintian will give you all the warnings and errors. Run

    lintian ../ruby-health-check_3.0.0-1_amd64.changes

    All complaints from lintian come with reasons and suggestions to fix them. If it doesn’t then you haven’t added the stuff you were supposed to add at the beginning of this page. Fix lintians complaints. Commit your changes using git and use clear commit messages. Commit everything except debian/changelog. Here’s an example from a package I updated a while ago. It is sort of a jackpot in the sense it has almost every lintian complaint I’ve come across. So you should find fixes to most lintian complaints there. Commit messages could be a little better and more creative though.

  7. Now remember gbp dch -a? once you’ve satisfied Lintian run it again. Now if you look at the changelog you’ll find that all of your commit messages are listed as entries in the changelog. Check if there are any duplicates and remove them. Now change the UNRELEASEDin the header to unstable. Now your changelog should look something like this:

    ruby-health-check (3.0.0-1) unstable; urgency=medium
        * Team Upload
        * New upstream version 3.0.0
        * Bumps debhelper-compat version to 13
        * Bumps standards version to 4.5.0
        * Added Rules-Requires-Root: no
    -- Abraham Raji <>  Thu, 13 Aug 2020 16:17:14 +0000

    At this point commit your debian/changelog with the commit message Upload to Unstable.

  8. Now try and build the package in a clean env. Here are the instructions to set up sbuild and build your package using sbuild.

  9. If the package was a major update you also need to run autopkgtests. An easy way to do this is through the meta scripts made by the Debian ruby team. Instructions to set up and use the scripts are mentioned in the file.

  10. If all goes well send an RFS to the mailing list of the Debian Team that maintains the packages. Node packages are maintained by the Debian JS team and ruby packages by the Debian Ruby Team. Join the mailing list from a separate mail account as there’s a lot of mail that comes to those lists every day. Then send a mail requesting sponsorship.

Zsh with Oh My Zsh

I don’t use zsh with ohmyzsh anymore. This is what I use now. More lean and custom.

Z shell or Zsh is a unix shell that was written by Paul Falstad in 1990. The name zsh derives from the name of Yale professor Zhong Shao (then a teaching assistant at Princeton University) — Paul Falstad regarded Shao’s login-id, “zsh”, as a good name for a shell. Zsh has features like interactive Tab completion, automated file searching, regex integration, advanced shorthand for defining command scope, and a rich theme engine. Combine it with a framework like oh-my-zsh, it really could help you be more productive.

Installing Zsh

  • Debian, Ubuntu and other Debian based disros:
$ sudo apt install zsh
  • Archlinux, Manjaro and other Arch-based distros:
$ sudo apt install zsh
  • Fedora, RHEL, and CentOS:
$ sudo dnf install zsh

Setting Zsh to your default shell

Now that you have installed zsh on your machine let’s set it as the default shell for your user. Execute the following command without sudo, upon which you’ll be prompted to enter the password for your user.

chsh -s $(which zsh)

Now if you log out and log back and open a terminal it should present you with the zsh shell instead of the bash shell.

Installing Oh My Zsh

  • Using Curl
$ sh -c "$(curl -fsSL"
  • Using Wget
$ sh -c "$(wget -O -)"

At this point you might as well install a favourite powerline font. if you’re on Debian or any of it’s forks sudo apt install powerline-fonts should work for most cases.


A lot of plugins come built in, for example plugins for distro specific commands are available in the name of the distro it’s written for, so you’ll find plugins such as debian and fedora. you can find all the plugins at ~/.oh-my-zsh/plugins. All the plugins are not enabled by default. In-order to enable a plugin you need to add the plugin nams to your plugins list in your .zshrc

One plugin that I find a lot of value in is the zsh-autosuggestions plugin. It commands based on your .zsh_history. But it is not a default plugin so we need to manually add it. We can do so by cloning the plugin repo to the ~/.oh-my-zsh/custom/plugins folder.

Here’s a list of all the plugins that I use:

  • colored-man-pages
  • debian
  • emacs
  • git
  • gnu-utils
  • lxd
  • zsh-autosuggestions
  • zsh-syntax-highlighting

Only two of the above plugins are custom, so we clone them to the custom plugins folder.

cd ~/.oh-my-zsh/custom/plugins
git clone
git clone

Then I add the names of the plugins to the list in my .zshrc

plugins=(colored-man-pages debian emacs git gnu-utils zsh-autosuggestions zsh-syntax-highlighting )


There are a wide variety of themes built-in to oh-my-zsh but my favourite is Powerlevel10k. You can install it by running the following command:

git clone --depth=1 ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k

This theme is pretty neat and if configured properly can give you a lot of information through the prompt itself. It uses a bunch of icons which you can get through the theme’s recomended font Meslo Nerd Font. You can get these fonts by downloading the TTF files given below to your ~/.fonts/ folder Download these four ttf files:

Then set ZSH_THEME="powerlevel10k/powerlevel10k" in ~/.zshrc. After this source your ~/.zshrc or open a new terminal to run the setup process for the theme.

And there you go this is my setup.

My Laptop

I assure you we do not have an unhealthy relationship. This is just my Baby. My first laptop. This machine has been through thick and thin. It has almost never let me down. I mean everyone messes up once or twice. This laptop is what a smartphone is to most people my age.

  • Name: Aspire F15
  • Model Number: F5-573G-7536
  • CPU: Intel i7-7500U (4) @ 3.500GHz
  • Dedicated GPU: NVIDIA GeForce 940MX
  • Integrated GPU: Intel HD Graphics 620 (Kaby Lake GT2)
  • Memory: 7846MiB
  • Storage: 1000GB
  • Screen Resolution: 1920x1080 [16:9]
  • WiFi Card: Qualcomm Atheros QCA9377 802.11ac Wireless Network Adapter
    This little bad boy needs a proprietary firmware to work
  • Ethernet Card: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller

Software I Use

This is a list of software that I use. The main purpose for the existence of this page is to keep a track of the software I use and to create a place I could refer to in case I mess my system up.


  • Primary: Firefox Specifically Firefox ESR
    • Why?:
    • Extensions:
      • Adnauseum:
        AdNauseam quietly clicks on every blocked ad, registering a visit on ad networks’ databases. As the collected data gathered shows an omnivorous click-stream, user tracking, targeting and surveillance become futile.
      • Bitwarden:
        My password manager of choice. If you don’t use one, you should because if you don’t, with the amount of software services we login to, you bet you’ll reuse password between services which is a terrible idea. The alternative is to memorize a different 16+ character string for all the services you use. Seriously, use a password manager. Bitwarden works great for my use, has many useful features and is Free Software.
      • Sharp Color Picker:
        Because I like good color combinations and I design stuff from time to time.
  • Secondary: Ungoogled Chromium: basically Chromium with all the Google bits removed.
    • Why?
      Because I develop websites and I need to make sure the websites I make properly render across various browsers.

Operating System

❯ cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux bullseye/sid"
NAME="Debian GNU/Linux"

Text Editor


I use emacs for most of my text editing needs and more. Sometime ago I started working on an emacs distribution named Armacs that helps people get started with Emacs. Up until recently I used to for pretty much anything. Recently I started experimenting with Doom Emacs and I’ve really started liking Evil Mode might actually adopt it to Armacs.

  • Why?
    • Free Software ♥
    • You can get a lot done from just Emacs- text editing, git. ssh, Document editor and more!

Instant Messaging

Terminal Emulator

  • St
  • Gnome Terminal


  • Zsh

Building neovim from source on Debian GNU/Linux

If you’re using Debian and want the latest version of neovim, at the moment your best bet is to use a flatpak. But if you want to use neovim, I’m going to assume that installing Neovim with Flatpak repulses you to your core. After a couple of frustrated google searches, I went through the wiki and found something that worked. I have put it here so that I know exactly where to look when I wish to build neovim again. So here we are. Obviously we should be scraping through the official wiki to figure this out but we have things to do. The instructions below can be used to build the master branch of Neovim on Debian release “Bookworm” (and possibly trixie).

  • Clone the repository
git clone
  • Install dependencies.
sudo apt install luajit libluajit-5.1-dev lua-mpack lua-lpeg libunibilium-dev libmsgpack-dev libtermkey-dev
  • Build deps
mkdir .deps && cd .deps
  • Build neovim
cd .. && mkdir build && cd build
cmake ..
sudo make install