31. 03. 2025 Davide Sbetti Development, DevOps, NetEye

Reducing the NetEye ISO Size: How to Carefully Choose the Right Packages!

If you’re a NetEye regular, you may have downloaded the NetEye ISO at least once in your life.

And if you did, you probably discovered that you had a bit of free time before the download was completed and the ISO was ready to be used. Why’s that? Because until a couple of weeks ago, the NetEye ISO was running about 15 GB – not the lightest ever!

Okay, to understand how we managed to improve this aspect and reduce the size of the ISO by just a bit, we first need to take a look at how the NetEye ISO is built.

A NetEye ISO Story

To build a NetEye ISO we need two ingredients: a Red Hat Enterprise Linux 8 official ISO and… a NetEye container!

That’s because our pipelines have always built the NetEye ISO starting from a NetEye container, which is based on a UBI 8 container, on top of which the NetEye packages are installed from our repos, using the associated DNF groups.

We use containers internally to perform most of our development work, and the NetEye ISO is no exception. In particular, the ISO project would create the NetEye ISO as follows:

  • Start from the official RHEL 8 ISO. Note that this contains two repos: BaseOS and AppStream
  • Spawn a NetEye container and add all NetEye packages to the ISO
  • Adapt the ISO kickstart and repo information, adding to the NetEye one
  • Repackage the ISO and voilá:

So, where does that 15 GB come from?

Well, making a summary of what the NetEye ISO contains, we can see the content divided among the following three repos:

  • Base OS
  • App Stream
  • NetEye

Now, the Base OS is clearly something that’s needed, at least if we would like to have a NetEye that works 😅

The same holds for the NetEye one, since otherwise our packages will be missing… so guess which repo is the one holding unnecessary packages?

You’re right! App Stream!

Why is that? Because the App Stream repo contains all possible Application Streams that can be installed on a RHEL 8 system, together with their dependencies.

And, as you can imagine, not all those streams are needed when NetEye is first installed from the ISO, since we require just some specific streams and versions.

Time to Clean Up!

Great, so we managed to identify the repo that’s holding some extra packages that we don’t need during the first installation. But how can we identify, in an automatic way, the specific packages that we can remove?

Well, we need to remember that we are starting from a container, which already contains (it is a container, right? 🤣) the packages that we really need. So, once more, we can use it as a basis for our ISO!

Of course, there’s a little exception: there are some packages that are not in the container (and that we cannot really install there, to avoid some nasty conflicts) but that we would like to preserve in the ISO, together with their dependencies.

In that case, what we can do is to simulate the installation of those packages in the container and get the installed packages as a list of packages to preserve from the App Stream repo, to ensure we do not delete them by mistake.

The procedure to extract the list of packages that we want to preserve from the App Stream repo was performed like this, using Ansible:

- name: Prepare Environment | gather the packages list
  ansible.builtin.package_facts:

# We start by creating the list of packages 
# that are installed in the container
- name: Create list of packages installed in the container
  ansible.builtin.set_fact:
    packages_array: "{{ ansible_facts.packages | dict2items 
                | map(attribute='value') | list | flatten}}"

# We keep only the names and version, 
# the other information are not required.
- name: Extract the packages names and versions
  ansible.builtin.set_fact:
    container_packages:"{{ packages_array | map(attribute='name') 
           | zip(packages_array | map(attribute='version')) 
           | map('join', '-') | zip(packages_array 
           | map(attribute='release')) 
           | map('join', '-') | list  }}"

- name: Simulate package installation to catch missing packages
  ansible.builtin.dnf:
    name: "{{ extra_packages_needed_in_the_iso | join(',') }}"
    state: latest
    # Necessary since in the containers we may have some packages 
    # that conflicts with something we want to install through
    # the ISO such as coreutils-single
    allowerasing: true
  # Hey, it is just a simulation!
  check_mode: true
  register: packages_with_dependencies

- name: Extract the packages names
  ansible.builtin.set_fact:
    extra_packages: "{{ packages_with_dependencies.results 
        | select('match','^Installed.*') 
        | map('regex_replace', '^Installed.*: ', '') | list }}"
  when: packages_with_dependencies.changed

- name: Create list of packages to preserve in the AppStream Repo
  ansible.builtin.set_fact:
    packages_to_preserve: "{{ container_packages  
          + (extra_packages | default([])) }}"

And with this we were able to remove all the packages present in the App Stream Repo that were not part of the packages_to_preserve list.

After that, to really make the ISO work, we need to update the metadata of the App Stream repo, as follows:

createrepo --update {{ rhel8_unpackaged_iso_path }}/AppStream

The Final Countdown ISO Size

By applying the aforementioned procedure in our ISO building pipeline, we managed to reduce it from the initial 15 GB to just 5 GB!

This improvement allowed us to speed up some internal pipelines while also improving the installation process, providing a more compact and manageable ISO for NetEye 🚀

These Solutions are Engineered by Humans

Did you find this article interesting? Does it match your skill set? Programming is at the heart of how we develop customized solutions. In fact, we’re currently hiring for roles just like this and others here at Würth Phoenix.

Davide Sbetti

Davide Sbetti

Hi! I'm Davide and I'm a Software Developer with the R&D Team in the "IT System & Service Management Solutions" group here at Würth Phoenix. IT has been a passion for me ever since I was a child, and so the direction of my studies was...never in any doubt! Lately, my interests have focused in particular on data science techniques and the training of machine learning models.

Author

Davide Sbetti

Hi! I'm Davide and I'm a Software Developer with the R&D Team in the "IT System & Service Management Solutions" group here at Würth Phoenix. IT has been a passion for me ever since I was a child, and so the direction of my studies was...never in any doubt! Lately, my interests have focused in particular on data science techniques and the training of machine learning models.

Leave a Reply

Your email address will not be published. Required fields are marked *

Archive