From Source Code to .deb Package: A Tutorial for Linux Package Management

From Source Code to .deb Package: A Tutorial for Linux Package Management

Β·

6 min read

πŸ“” Introduction

  • Disclaimer: This is not necessarily the optimal or best way to build a .deb package. It may be messy, but it's the workaround I've found and will be demonstrating here.

  • A .deb file in Linux is a package format developed for the Debian distribution, which has served as the foundation for many popular distributions such as Ubuntu, Linux Mint, and Kali Linux. When building a .deb package, it can typically run on these and other Debian-based distributions, ensuring compatibility across a wide range of systems

  • In this example we are going to do the following things:

    • Create a simple cli-app

    • Build the .deb file

    • Upload it to GitHub

    • Publish a release

🧰 Prerequisites

  • We need a list of packages or utilities for this

    • GitHub account (GITHUB)

    • git (GIT)

    • dpkg-dev package

πŸ“ Creating the Debian Package Directory Structure

  • We can read about what to use inside our DEBIAN folder -> Debian-package

  • As for my example, I'm only using postinst and postrm .

  • Little fact: control, postinst, postrm have no file extension.

πŸ“¦debian-package-base
 ┣ πŸ“‚DEBIAN
 ┃ ┣ πŸ“œcontrol
 ┃ ┣ πŸ“œpostinst
 ┃ β”— πŸ“œpostrm
 ┣ πŸ“‚usr
 ┃ ┣ πŸ“‚bin
 ┃ β”— ## OUR APP RESIDES INSIDE THE BIN FOLDER
 ┣ πŸ“œ.gitignore
  • First of all, we have our DEBIAN folder which contains the necessary information to build our package

  • Remember to give execution permissions to these files

chmod +x ./DEBIAN/postinst
chmod +x ./DEBIAN/postrm

πŸ›‚ The control file - * REQUIRED

Package: debian-template
Version: 0.0.1
Section: utils
Priority: optional
Architecture: all
Depends: bash
Maintainer: Jonathan Dyallo <contacto@jonathan.com.ar>
Description: A demo application

This one contains information about our package itself

  • package-name: the package name itself, this is how we are going to launch our app once is finished

  • version: version of the package

  • section: utils, system, security, can be a variety of things

  • priority: is necessary to the system?

  • architecture: processor architecture, like intelx32, amdx64, etc

  • dependencies: if we have to install something to run our package, like the module requests for making api-calls on a python script

To read more about the control file you can visit debian-docs

πŸ“§ The postinst file

This section contains information about what we do during the installation process once the package is running. It is important to note that we cannot install something with our package manager while the app is running. For instance, if we run dpkg -i our_app.deb, and our postinst script contains a command like dpkg -i another_app, it will result in an error message stating that the package manager is in use.

  • Here is where the monkey inside of me started to use a 1% of his power.

  • To execute the app as any other instead of going to the folder and run the main script etc, we create a symbolik link and clone the repo to that particular place.

  • So the instalattion itself is a big lie and we are just creating a workaround to execute it from the main file itself.

#!/bin/bash

# Create symbolic link
sudo ln -s /usr/share/debian-package-base/usr/bin/main.sh /usr/bin/debian-package-base

# Get the project in a more monkey-friendly way
cd /usr/share
git clone https://github.com/jd-apprentice/debian-package-base.git

# Give permissions to the application and source the files
chmod -R 777 /usr/share/debian-package-base

# Successfully installed the application, give message to the user
echo "debian-package-base has been installed successfully!"
echo "You can run it by typing 'debian-package-base' in the terminal."

❌ The postrm file

The postrm file is an optional script that runs after the package is removed from the system. It can be used to perform cleanup tasks such as deleting configuration files or stopping running services that were associated with the package.

#!/bin/bash

# We remove everything we can from the user's home directory
sudo rm -rf /usr/bin/debian-package-base
sudo rm -rf /usr/share/debian-package-base

πŸ“« Building the Package

  • For this particular task I've created a util/script to automate the building process of the package itself or new versions

  •     #!/bin/bash
    
        # App name for multiples uses
        app_name="debian-package-base"
    
        # Starting message
        echo "Building latest version of ${app_name}"
    
        # Find version of the package and save it in a variable
        file=$(find . -name 'control')
        string="Version"
    
        while read -r line; do
            if [[ $line =~ $string ]]; then
                version=${line:(-3):3}
            fi
        done <$file
    
        # We locate where the folder is located and move to it
        folder=$(find $HOME -type d -name "${app_name}" -print | tail -n 1)
        cd "$folder"
    
        # We create a folder for the build and copy the entire file one level above
        cd ..
        mkdir -p -- "${version}-${app_name}"
        copy=$(find $HOME -type d -name "${version}-${app_name}")
        cp -r $folder/* "$copy"
    
        # Move to the copy directory
        cd "$copy"
    
        # We remove git since we don't want it in the final build
        # Also here remove anything not useful to the final build example images for the readme, markdown files, etc
        rm -rf .git
        rm *.md
    
        # Move out of the copy directory
        cd ..
    
        # Build latest version of the package
        dpkg --build "${version}-${app_name}"
    
  • To run this script (you can create it inside the root of your app or a utils folder)

# Remember to be at the same level of the app
chmod +x ./utils/<script_name>.sh
./utils/<script_name>.sh
  • With this we should have a .deb file ready to be installed!

  • But before going to the install we proceed to uploading everything to github

β›… Uploading to Github

  • We can use my template with the button Use this template

  • Repository

    • Select a new name and with that we have our new repo, just like we see it above

    • Upload everything to the repository

πŸ“¦ Installing the Package

  • Now if everything is uploaded to the repository and we have the .deb file

  • To install the package we are going to use dpkg

  • Run the following command inside your terminal

sudo dpkg -i ./<version>-<package-name>.deb

🧟 It's Alive!

  • Here is an example of building, installing and running the app at the same time

  • Once we know is working we just have to create a release on github or share it with others!

  • In the future i'm going to expand this example with better practices and how to upload it to PPA and users can download it with just a simple apt-get install <my-package>

πŸ‘‹ Ending

  • Let me know if something is messed up and I'll update the guide and also if you have any trouble or have better ideas / suggestions, I'm open to hear.

  • Contact me at any of my Socials

Β