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 docker.io, 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 
    

No comments: