Creating a Software Bill of Materials (SBOM)

A Software Bill of Materials (SBOM) in the context of Ubuntu is a list of software components, applications, libraries, and modules that are installed by the operating system. Ubuntu consists of several packages that depend on other packages such as shared libraries. These are shipped on different forms such as debs and snaps. The following sections show how to get the list for each type of packages to assist you in keeping your systems up-to-date.

List of deb packages

To see the package dependencies in Ubuntu use:

$ dpkg -l

The output is a list of packages similarly to the following.

| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                                             Version                               Architecture Description
ii  apparmor                                         3.0.3-0ubuntu1                        amd64        user-space parser utility for AppArmor
rc  apparmor-utils                                   3.0.0-0ubuntu7.1                      amd64        utilities for controlling AppArmor
ii  apt                                              2.3.9                                 amd64        commandline package manager

List of snap packages

$ snap list

This outputs a list such as the one below.

Name                     Version                      Rev    Tracking         Publisher          Notes
bare                     1.0                          5      latest/stable    canonical✓         base
canonical-livepatch      10.1.2                       126    latest/stable    canonical✓         -
1 Like

This is great, but not usable in real practice.

This is why I have created simple python script named Save/Restore Software List Script for Ubuntu and Debian at

I’ll cite my below:


Save/Restore Software List Script for Ubuntu and Debian

This is Python 3 script for my personal needs. Currently it was tested on Ubuntu MATE 18.04 and 20.04 LTS.

Usage scenario is the following: user has two computers. The first computer is old, but has all needed software installed. The second computer is new, user wants to install all the software from first computer on it.

Currently the script supports almost all possible installation sources - Snap, Flatpak, Ubuntu Make and APT. Software lists are saved to JSON file and then maybe be restored/loaded from it.

To enable all the features user needs to install the dependencies using command below:

# minimal for APT
sudo apt-get install python3 python3-gi python3-apt software-properties-common python3-jsonpickle

# additional for Snap, Flatpak
sudo apt-get install snapd flatpak gir1.2-snapd-1 gir1.2-flatpak-1.0

# additional for Ubuntu Make
sudo apt-get install ubuntu-make

After this one can use the following syntax to call ./ with one argument:

  • ‘snap_save’/‘snap_load’ (for Snap),
  • ‘flatpak_save’/‘flatpak_load’ (for FlatPak),
  • ‘umake_save’/‘umake_load’ (for Ubuntu Make),
  • ‘apt_save’/‘apt_load’ (for APT),
  • ‘all_save’/‘all_load’ (for Snap, Flatpak, Ubuntu Make and APT in one shot).

Please note that JSON files have the following names:

  • snaps.json for Snap,
  • flatpaks.json for FlatPak,
  • umake.json for Ubuntu Make,
  • debs.json for APT.

‘Load’ operation for Snap, Flatpak and Ubuntu Make are almost automatic. They require user to enter password only on package installation.

‘Load’ operation for APT is interactive. The Python script generates Bash script named User should manually review this script and then run it by sudo bash ./ and keep an eye on it. Some issues may occur here because of dependencies of something similar. It is recommended to run the ‘load’ operation on fully upgraded system without PPAs and third-party repositories added. Current version of script support the following repositories: Launchpad PPAs, OpenSuSe Build Service, Oracle VirtualBox, Google Chrome, UbuntuZilla on SourceForge and Yandex Disk.

Quick start:

  1. clone this repository on the first machine, install the dependencies, run the script using ./ all_save, copy JSON files and ./ script to removable media;
  2. install the dependencies on the second machine with the same OS version, launch the script with ./ all_load from removable media, follow the instructions on screen.

In real practice I have cloned about 10 machines with it to have the same debs, PPAs, Flatpaks, Snaps and UbuntuMakes installed on them.

You’ve got a point here, software is too complex to track and inventory. Things may come from the OS or from 3rd parties, things found from github or pip, conda, etc. To keep things simple the focus of the article above is limited on what gets installed by the OS.

Thank you @Norbert for providing this solution. We should definitely keep this note around for others to use.

We’re currently reviewing all server docs feedback to incorporate back into the official docs. In this case I’m not sure we can do that as we don’t think the official docs should have a reliance on third party software sources. We’d expect such software to be made “official” by being incorporated into Ubuntu itself first.

I just wanted to note why we’ve decided not to incorporate this into the official docs. But it’s great that it’s documented here, and we’ll keep your notes here for others to find. Thank you for helping others with this use case!