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 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 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).
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
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.
We shall follow the plan outlined above.
Actions on the host
Setting up the webserver and packages
The following will install the Apache 2 webserver and other prerequisites.
$ sudo apt install apache2 dpkg-dev dpkg-sig
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
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 <list of packages here>
Setting up your key pair and signing packages
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.
Once the key is created, run:
$ gpg --list-keys
Note the line starting with
publike 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.
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
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 <pkg1>
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
Run the following command to add the local repository:
$ sudo su $ cat <<EOF >> /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.
Add the laptop host repository's key:
$ wget -O http://laptop-host-ip/pkgs/keyFile | sudo apt-key add -
Now run the following:
$ sudo apt update
Once this step passes, you can run:
$ sudo apt install <package-name>