Skip to content

Instantly share code, notes, and snippets.

@ju2wheels
Last active August 3, 2023 17:49
Show Gist options
  • Save ju2wheels/b40cd89a8735f39a12b3547a45a45342 to your computer and use it in GitHub Desktop.
Save ju2wheels/b40cd89a8735f39a12b3547a45a45342 to your computer and use it in GitHub Desktop.
Creating a Ubuntu package backport

Dev deb build environment setup

References:

  1. Install build tools:

    sudo apt install apt-file gnupg pbuilder qemu-user-static ubuntu-dev-tools 
    
  2. Create gpg key:

    gpg --full-gen-key
    
    • Select RSA/RSA
    • Set expiration to 0
    • Set 4096 bit
    • Fill in your name and email address
  3. Export gpg key to save it:

    gpg --export-secret-keys --armor <gpg_key_id> > <name>_<email>_gpg_priv.asc
    gpg --export --armor <gpg_key_id> > <name>_<email>_gpg_pub.asc
    
  4. Publish gpg public key to GPG key server:

    gpg --send-keys --keyserver keyserver.ubuntu.com <gpg_key_id>
    
  5. Create SSH key:

    ssh-keygen -t rsa -b 4096 [-f ~/.ssh/mykey]
    
  6. Create pbuilder environments for 18.04, 20.04, and 22.04:

    pbuilder-dist bionic amd64 create
    pbuilder-dist bionic arm64 create
    pbuilder-dist focal amd64 create
    pbuilder-dist focal arm64 create
    pbuilder-dist jammy amd64 create
    pbuilder-dist jammy arm64 create
    
  7. Create Launchpad account

  8. Add GPG key and SSH key to Launchpad account

  9. Add Debian packaging tools user id details to ~/.bashrc:

    export DEBFULLNAME="Full Name"
    export DEBEMAIL="[email protected]"
    

Getting the source, creating a backport, editing, and building a backport deb

Note: If you intend to release the backports for non internal use, be sure to sign the packages. All steps here are for an unsigned deb package build.

Use the latest distribution you are backporting from as the development base from which to build your backports. Ensure your deb build environment is setup as described above (the Launchpad setup is optional).

  1. Download and extract the source deb for latest version of the package for each the old end of life (EOL) distributions you are backporting to (this is more for having a reference point):

    pull-pkg --arch <architecture> --distro <distribution name> --pull source <package name> <distribution release name|package version>
    

    Example:

    pull-pkg --arch amd64 --distro ubuntu --pull source ca-certificates bionic
    pull-pkg --arch arm64 --distro ubuntu --pull source ca-certificates bionic
    pull-pkg --arch amd64 --distro ubuntu --pull source ca-certificates focal
    pull-pkg --arch arm64 --distro ubuntu --pull source ca-certificates focal
    
  2. Take the source deb for the latest version of the package from the current supported distribution release and repackage it as a backport package for each of the older EOL distribution releases without making any modifications to the code in the package at all other than making an initial backport source package that you can then modify (this helps to setup the changelog and package files with the proper backports naming convention):

    backportpackage --destination <destination distribution release> --dont-sign [--mirror <ubuntu mirror url>] --source <source distribution release> --workdir ./ <package name>
    

    Example:

    backportpackage --destination bionic --destination focal --dont-sign --source jammy --workdir ./ ca-certificates
    
  3. Extract the debian source package for each backport created in the last step:

    dpkg-source --no-check --extract <backport dsc path>
    

    Example:

    dpkg-source --no-check --extract ca-certificates_20230311ubuntu0.22.04.1~bpo20.04.1.dsc
    
  4. Use dirdiff to compare the changes in the old EOL distribution package version to the newly created backport package for that distribution:

    dirdiff <old distribution package path> <backport package path>
    

    Example:

    dirdiff ca-certificates-20230311ubuntu0.18.04.1/ ca-certificates-20230311ubuntu0.22.04.1~bpo18.04.1/
    
  5. Modify the contents of the extract backport package source as necessary (such as adding/removing files, updating the debian control file, etc).

  6. Update the package source archives with the changes from the extracted directory and build the deb package from the update backport sources:

    cd <backport package path>
    debuild -S -d -us -uc
    pbuilder-dist <pbuilder release environment> <pbuilder release environment architecture> build <backport dsc path>
    

    Example:

    cd ca-certificates-20230311ubuntu0.22.04.1~bpo18.04.1/
    debuild -S -d -us -uc
    pbuilder-dist bionic amd64 build ../ca-certificates-20230311ubuntu0.22.04.1~bpo18.04.1.dsc
    
  7. Find build result in ~/pbuilder/<pbuilder release environment>[-<pbuilder release environment architecture>]_result/ and upload deb to APT repository of your choice like Nexus.

Example backport of ca-certifates from 22.04 to 18.04

Note: If you intend to release the backports for non internal use, be sure to sign the packages. All steps here are for an unsigned deb package build.

  1. Download the original 18.04 last release of ca-certificates and create a backport using 22.04:
    mkdir -p ~/Downloads/ca-certificates-build
    cd ~/Downloads/ca-certificates-build
    
    pull-pkg --arch amd64 --distro ubuntu --pull source ca-certificates bionic
    backportpackage --destination bionic --destination focal --dont-sign --source jammy --workdir ./ ca-certificates
    
  2. Use dirdiff on the two folders to compare last 18.04 package version to the 22.04 package version being backported. In this example, I am making the following modifications to the backport (however be aware that you need to evaluate what can be backported and cant be on a backport by backport basis even for the same version of a package across different distribution releases):
    1. Copy debian/compat from the 18.04 package version into the 22.04 package version being backported.
    2. Revert debian/control settings in the 22.04 package version being backported to their values in the 18.04 package version (except for maintainers info) and remove any newly added settings in the backpoprt.
    3. Revert mozilla/Makefile line for executing certdata2pem.py to use python instead of python3 in the 22.04 package version being backported since we dont want to force 18.04 to depend on Python 3 since the last release did not either.
    4. Copy mozilla/certdata2pem.py from the 18.04 package version into the 22.04 package version being backported since the we dont want to include the code that requires a newer cryptography via python3-cryptography.
  3. Build the backport deb:
    cd ~/ca-certificates-build/ca-certificates-20230311ubuntu0.22.04.1~bpo18.04.1/
    debuild -S -d -us -uc
    pbuilder-dist bionic amd64 build ../ca-certificates-20230311ubuntu0.22.04.1~bpo18.04.1.dsc
    
  4. Get the resulting deb packages from ~/pbuilder/bionic_result.

Cross architecture package building

Most of the above commands assume that you are building a deb package for the same architecture as the host you are currently using to build the deb. If you want to do cross architecture builds, the qemu-user-static dependency listed above is required for pbuilder to use qemu to emulate another architecture. If any of the commands support passing the architecture as a parameter, most of them will automatically do the right thing. In the case of the backportpackage command which only seems to support providing the package version, its unclear if you can include the architecture in the version string (if it doesnt support this then your only option here would be to run this command on the same architecture that you are trying to build the package for). Besides this command, the other ones seem to work ok for cross-architecture use.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment