Creating an offline ubuntu package repository with only the packages you need.

I don’t know why this took me so long to figure out … It was simple enough. I wanted a offline ubuntu package repository with only the packages needed to update my templates, which only have specific packages installed.

Well, here’s how you do it!

Start by creating your repository by downloading a list of packages that you need. What I like to do is from my main template, I’ll run this command to download all packages that are needed to update my other images. They are all the same, so if this works for the main image, it will work for all other vms that have been created with it. Granted, you don’t have extra packages that were installed after the fact.

apt update && apt upgrade --download-only

You can see all the packages have been downloaded

cd /var/cache/apt/archives

You can no copy all the packages to a directory and configure a webserver that will be able to access these files. I used NGINX.

apt install nginx

Now copy all the packages over to the default root folder to be served by nginx. I will to create a folder called ubuntu and served the files from there.

mkdir /var/www/html/ubuntu
cp /var/cache/apt/archives/*.deb /var/www/html/ubuntu

Now, let’s create a Packages.gz file for your repository.

apt install dpkg-dev
cd /var/www/html/ubuntu
dpkg-scanpackages . /dev/null | gzip -9c > Packages.gz

Now let’s configure NGINX. I’m keeping this simple and just using the default file from the NGINX installation.

vim /etc/nginx/sites-available/default

Make sure these values are changed

root /var/www/html;
autoindex on;

Now let’s start/restart NGINX

systemctl restart nginx

You can test this out by going to your webserver by loading up the ip of your box with /ubuntu. Replace the ip with your own ip, of course 🙂

http://192.168.X.X/ubuntu

You can now use this small repository to update your templates with ansible. So let’s create a playbook to do so. The entries in BOLD

---
- block:
  - name: "Change sources.list file to remote repo."
    copy:
      content: "deb [trusted=yes] http://192.168.X.X/ubuntu ./"
      dest: /etc/apt/sources.list

  - name: "Updating the operating system."
    apt:
      name: "*"
      state: latest     # noqa package-latest
      force_apt_get: true
      update_cache: true

  - name: "Installing additional packages."
    apt:
      name: "{{ additional_packages[ansible_os_family] }}"
      state: latest     # noqa package-latest
  when: ansible_os_family == 'Debian'

This playbook will change the /etc/apt/sources.list file and replace it with the content above “deb [trusted=yes] http://192.68.X.X/ubuntu ./”

The playbook will now run an apt update and apt upgrade and fully upgrade all the packages for the machine.