Wednesday, November 29, 2017

Java alphabet soup

Java alphabet soup

Trying a Java refresher, more specifically a Spring refresher, has so far been a source of mixed emotions. Having written a lot of Core Java in the past and used a smattering of Spring, the utility of either wasn't in question in my head. But then having developed tons of Ruby on Rails apps, and seen both its magic and seamy sides, my perspective perhaps has more dimensions to it today.

I found the Java / Spring way of developing web applications a little too archaic by today's standards. All the annotations have still not exorcised much of the esoteric XML that you still cannot avoid. But Eclipse provides significant relief to the extent that you can get away without writing perhaps a single line of XML, using its Maven and Spring (Spring Tools Suite / Web Tools Platform) plugins instead to add most of the XML content.

You still need to manually configure Tomcat, manually configure data sources and JNDI for accessing your data sources in server specific ways. You still have to manually configure your web.xml. Those are hard, and you have to know at least what to search for in google, and then what to search for in the documentation that google lists. It is frustrating if you don't have a very good, precise tutorial or howto. It all shows the struggles of an old and evolving framework in trying to remain usable even as it remains solidly relevant. I suspect Spring Boot, something I am yet to explore, would bear signs of some true-north evolution. In the meantime, one hopes Java comes up with more modern web frameworks. Spring is mature, stable, mildly usable and very useful. But it feels a decade behind. Spring addressed usability problems of Java EE. But today, something else needs to do that for Spring. Spring Boot may be an evolutionary step in that direction, but more needs to be done.

Read more!

Saturday, November 11, 2017

Setting up local repos for Ubuntu packages

Setting up repos of .deb packages for Ubuntu may not be something people need to do often on their own laptops. But I was recently doing something where it made sense. I was setting up a kubernetes cluster using VirtualBox on my Linux laptop and wanted to automate the whole process using vagrant and ansible. This meant that each time a VM would be spun up, I would add apt repositories to it and then install, kubeadm, kubectl, kubelet, and kubernetes-cni packages. All of these VMs were to be on my laptop, and each time they'd reach out to google's or docker's repos to pull these packages in. A sum total of around 70 MB isn't big but I could be spinning up tens of VMs over the course of my experiments and a fresh download off the web every time is a terribly inefficient use of bandwidth (certainly here in India). So I wanted to setup an apt repository locally on the host laptop which runs Ubuntu 16.04 (xenial).

The plan

On the host: What we need to do is to run a web server (Apache2 works fine) that serves a directory with the packages that I want to host. To make this secure, we need to generate a key pair using GnuPG, and sign the packages I want to expose. I should also expose the public key. The packages are .deb files (the analogues of .rpm on RedHat / Centos, etc.) and in case you've already installed them on your host laptop, they might be available under the directory /var/cache/apt/archives. If not you can download the packages without installing using a command-line switch for apt install.

On the guests: On each guest, we'll need to edit the /etc/apt/sources.list file to include the repository from the host laptop. We'll also need to accept the public key from this repository.

The action

We shall follow the plan outlined above.

Actions on the host

Setting up the webserver and packages

  1. The following will install the Apache 2 webserver and other prerequisites.

    $ sudo apt install apache2 dpkg-dev dpkg-sig
  2. The root virtual directory for Apache is by default /var/www/html. You should create the following directory tree under it: /var/www/html/pkgs/dists/$(lsb_release -s -c)/main/binary-amd64. To do that, run the command:

    $ mkdir -p /var/www/html/pkgs/dists/$(lsb_release -s -c)/main/binary-amd64
  3. Download the required packages in the directory you just created:
    $ cd /var/www/html/pkgs/dists/$(lsb_release -s -c)/main/binary-amd64
    $ apt download 

Setting up your key pair and signing packages

  1. If you haven't already, you should generate a key pair using GnuPG.
    $ gpg --gen-key

    In the prompts that follow, select the key type to be RSA (sign only), key size to be 4096 bits, key does not expire, and specify a unique name. Specify a reasonable password. Wait for the keys to be generated.

  2. Once the key is created, run:
    $ gpg --list-keys

    Note the line starting with pub like this one:
    pub   4096R/B1B197AF 2017-11-11

    Note the number appearing after the size specifier (4096R/). Here it is B1B197AF. This would be your key identifier and would be used in the next step.

  3. Generate your public key file so that it is accessible through your web server:
    $ cd /var/www/html/pkgs
    $ sudo gpg --output keyFile --armor --export B1B197AF
  4. Finally, sign each of your packages thus:
    $ cd /var/www/html/pkgs/dists/$(lsb_release -s -c)/main/binary-amd64
    $ sudo dpkg-sig --sign builder 

    Also, generate a Packages.gz and a Release + InRelease files.
    $ cd /var/www/html/pkgs/dists/$(lsb_release -s -c)/main/binary-amd64
    $ dpkg-scanpackages . | gzip -9c > Packages.gz
    $ apt-ftparchive release . > Release
    $ gpg --clearsign -o InRelease Release
    $ gpg -abs -o Release.gpg Release

Actions on the guest

  1. Run the following command to add the local repository:
    $ sudo su
    $ cat <> /etc/apt/sources.list
    > deb [ arch=amd64 ] http://laptop-host-ip/pkgs xenial main
    > EOF

    One point to understand here is that you would want your repository to be chosen preferentially over others if the packages are present in your repository. So unless the packages of interest not be present on other listed repositories, you should put this entry above any other repositories. The above command appends your repository at the end of the fail. To move it up in the file, you may need to edit it manually.

  2. Add the laptop host repository's key:
    $ wget -O http://laptop-host-ip/pkgs/keyFile | sudo apt-key add -
  3. Now run the following:
    $ sudo apt update

    Once this step passes, you can run:
    $ sudo apt install 

Read more!