Debian Directory

Now that we have Debian tools ready, it's time to define the package. In this guide however, we won't be showing steps by steps as an independent guide but rather complements from the existing document.

Binary or Source Package

Debian system allows you to compile either the binary form or the source form. They are both different in terms of deployment and maintainability. From Debian Buster onward, the official guide requires us to build the source package. Let's stick to the source package.

The primary difference between them are:

  • Binary package requires you to create an UPCASE Debian directory: $ mkdir DEBIAN
  • Source package requires you to create a lowercase Debian directory: $ mkdir debian


Once you created the Debian directory inside your project, it's time to pack the necessary files in it. In this guide, we'll be strictly building the source package.

$ mkdir debian

Creating debian/control

debian/control file is the most critical file of all. It carries the instruction and the metadata for your package. This file follows a very strict rules and template, like the one specified in the guide. We'll go through each of them accordingly.

Template Format

 1 Source: <software name>
 2 Section: <software type>
 3 Priority: optional
 4 Maintainer: Josip Rodin <joy-mg@debian.org>
 5 Build-Depends: debhelper (>=10)
 6 Standards-Version: 4.0.0
 7 Homepage: <insert the upstream URL, if relevant>
 8
 9 Package: gentoo
10 Architecture: any
11 Depends: ${shlibs:Depends}, ${misc:Depends}
12 Description: <insert up to 60 chars description>
13  <insert long description, indented with spaces>


Line 1: Source

Source is the software name or the package. This name should be like a 1 word or 2 words with/without connected with hyphen(-).

Avoid using long name. If it happens to you, you should greatly consider the level of details in the name and place them in the descriptions instead.

Example: gentoo, bashell, nuko, shellcheck, coreutils


Line 2: Section

Section is the software distribution your software should goes into. It is a controlled value listed in the Debian Policy Manual. Generally, we use these sections but you can browse the policy to search for more:

  • main - the free software
  • non-free - the not free software
  • contrib - the free software that depends on non-free software.
  • devel - the programmer tools
  • doc - the documentation
  • libs - the libraries
  • mail - the email and its associated daemons
  • net - the network applications and daemons


Line 3: Priority

Denotes the priority to install your package to user. It is a controlled value listed in Debian Policy Manual. In summary, the values are as follow:

  • required - for software critical enough that it can break dpkg packaging software, brick the operating system and make the system totally broken.
  • important - for bare minimum software that is common across all Linux system, such as coreutils, grub, etc.
  • standard - for bare minimum of your software. The core system. You should only have one standard package with many optional packages.
  • optional - commonly used for majority of the archive.

If you don't know what to do, use optional.


Line 4: Maintainer

The contact email when something happens to your package. Please ensure you provide a proper send-able email address. This email follows the format:

FULL NAME <email address>

Example:

Josip Rodin <joy-mg@debian.org>


Line 5: Build-Depends

Specify the dependent tools/software for building your software package. Based on the guide, since most implementation is now using dh command, you should append debhelper (>=10) into Build-Depends. A good example would be:

Build-Depends: debhelper (>=9), bash (>=4.3)


Line 6: Standards-Version

The version number for the standards you're planning to use. Do not confused this field as your software version. It is strictly referring to the Standards-Version list. Keep in mind that not all versions are available in every operating system or distribution branches. You should use the appropriate version that is compatible to your build machine.


Line 7: Homepage

The web URL for your software. Keep it short and simple.


Line 8: Empty Line

This empty line is mandatory. It splits the source section and binary section of the control file. Leave it a clean blank line.


Line 9: Package

Name for the binary package. It is usually the same as Line 1 Source name.


Line 10: Architecture

Specify the package is architecture dependent or otherwise as per Debian Policy Manual. You can check the architecture list using the command dpkg-architecture -L. Some common values are:

armhf
armel
mipsn32
mipsn32el
mipsn32r6
mipsn32r6el
mips64
mips64el
mips64r6
mips64r6el
powerpcspe
x32
arm64ilp32
i386
ia64
amd64
armeb
arm
arm64
avr32

Debian also supplies 2 common value for architecture independent software like scripts, images, and docs; and "compile at install" software. These are:

  • any - for "compile at install" software
  • all - for architecture independent software


Line 11: Depends

Specify the dependencies for the binary package. This is the list where user will get software lists to be installed when installing your software using dpkg. By default, you must include ${shlibs:Depends}, ${misc:Depends}. These 2 flags are for packager to include the dependencies identified via automation .

There are a lot more keywords aside "Depends". You can refer to the guide: https://www.debian.org/doc/manuals/maint-guide/dreq.en.html.


Line 12: Short Description

The short description, should be around 60 characters, written in the following styles:

Style 1: This package <name> <do what in a nutshell>
Style 2: collection of <something> from <where>
Style 3: <what's inside in a nutshell>
Style 4: <do what in a nutshell> with <name>

Some guidelines:

  1. Never starts the description with the package name. This is an error.
  2. Never go beyond 80 characters, or only a word. Follow the 60 characters guideline. They are known errors for too long and too short.
  3. Capitalize accordingly. Lintian will notify you if it detects such phenomenon.
  4. Never starts the description with article (a, an, the). This is a known warning. Use "This" or other styles.
  5. Never state a package name as the short description. This is an error.
  6. Clean up your leading space. This is a warning.
  7. Don't end the sentence with a period (.). Lintian will notify you if it detects such phenomenon.


This short description is meant pitching your software package during package shopping. User may use certain keywords in his/her search. Therefore, just like Search Engine Optimization, you should always do a good research with the keywords and let user find your software easily! Here are some examples when a user search for coreutils:

$ sudo apt search coreutils
bsdmainutils/stable,now 9.0.12+nmu1 amd64 [installed]
  collection of more utilities from FreeBSD

coreutils/stable,now 8.26-3 amd64 [installed]
  GNU core utilities

gotail/stable 1.0.0+git20160415.b294095-3+b2 amd64
  Go implementation of tail

libsemanage1/stable,now 2.6-2 amd64 [installed]
  SELinux policy management library

mktemp/stable 8.26-3 all
  coreutils mktemp transitional package

policycoreutils/stable 2.6-3 amd64
  SELinux core policy utilities

policycoreutils-dev/stable 2.6-3 amd64
  SELinux core policy utilities (development utilities)

policycoreutils-gui/stable 2.6-3 all
  SELinux core policy utilities (graphical utilities)

policycoreutils-python-utils/stable 2.6-3 amd64
  SELinux core policy utilities (Python utilities)

policycoreutils-sandbox/stable 2.6-3 amd64
  SELinux core policy utilities (graphical sandboxes)

progress/stable 0.13.1-1 amd64
  Coreutils Progress Viewer (formerly known as 'cv')

python3-sepolgen/stable 2.6-3 all
  Python3 module used in SELinux policy generation

realpath/stable 8.26-3 all
  coreutils realpath transitional package


Line 13 and Beyond: Long Description

This section holds the long description for your software. There isn't any limit to the long description but please keep it concise and straight to the point. A sensible length is usually 2-4 paragraphs at 6 maximum lines each.

User views this long description using apt show <package> command. Here's an example:

$ sudo apt show zoo
Package: zoo
Version: 2.10-28
Priority: optional
Section: utils
Maintainer: Debian QA Group <packages@qa.debian.org>
Installed-Size: 140 kB
Depends: libc6 (>= 2.14)
Homepage: http://www.ibiblio.org/pub/packages/ccic/software/unix/utils/
Tag: implemented-in::c, interface::commandline, role::program,
 scope::utility, use::compressing, use::storing, works-with::archive
Download-Size: 64.3 kB
APT-Sources: http://ftp.us.debian.org/debian stretch/main amd64 Packages
Description: manipulate zoo archives
 Zoo is used to create and maintain collections of files in compressed
 form.  It uses a Lempel-Ziv compression algorithm that gives space
 savings in the range of 20% to 80% depending on the type of file data.
 Zoo can store and selectively extract multiple generations of the same
 file.
 .
 This package exists for its historical value. If you are looking for
 a compression tool for serious use, check tar and gzip.


There are a few things to take note of:

  1. You must leave a space( ) for each line.
  2. For newline, add a period (.) instead of leaving it empty.
  3. Don't add URL in it. That belongs to Homepage.
  4. Don't describes anything that is already known in other field.
  5. Be very sensitive with Capitalization. The Lintian is great at detecting such error.
  6. Don't duplicate your short description into your description. This is a known error.

Here's an example for a debian/control file or see the one in the official guide:

Source: fennec
Section: devel
Priority: optional
Maintainer: ZORALab Enterprise <tech@zoralab.com>
Build-Depends: debhelper (>=9), bash (>=4.3)
Standards-Version: 3.9.8
Homepage: https://gitlab.com/ZORALab/fennec

Package: fennec
Architecture: all
Depends: ${misc:Depends}, ${shlibs:Depends}, bash (>= 4.3)
Description: This package fennec provides a way to handle CI script
 fennec is a software management tool to handle web supported git repository.
 It structures the repository for a semi-automatic continuous integration
 alongside with web platform supports, such as GitLab.

Creating debian/copyright

This defines the software license for using the your software package. It is a UTF-8 encoded only file and strictly machine parse-able document. The entire detailed information is documented in the Debian Policy Manual - Copyright File section. While it takes time to create one, you can follow the main guide. Here's one example:

 1 Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
 2 Upstream-Name: <package name>
 3 Upstream-Contact: Emil Brink <emil@obsession.se>
 4 Source: <url to source>
 5
 6 Files: *
 7 Copyright: 1998-2010 Emil Brink <emil@obsession.se>
 8 License: GPL-2+
 9
10 Files: icons/*
11 Copyright: 1998 Johan Hanson <johan@tiq.com>
12 License: GPL-2+
13
14 Files: firmware/*
15 Copyright: 1998-2010 Josip Rodin <joy-mg@debian.org>
16            2008, John Doe <jdoe@example.com>
17            2007, Jane Smith <jsmith@example.org>
18            2007, Joe Average <joe@example.org>
19            2007, J. Random User <jr@users.example.com>
20 License: Proprietary
21
22 License: GPL-2+
23  This program is free software; you can redistribute it and/or modify
24  it under the terms of the GNU General Public License as published by
25  the Free Software Foundation; either version 2 of the License, or
26  (at your option) any later version. 
27  .
28  This program is distributed in the hope that it will be useful,
29  but WITHOUT ANY WARRANTY; without even the implied warranty of
30  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31  GNU General Public License for more details.
32  .
33  You should have received a copy of the GNU General Public License along
34  with this program; if not, write to the Free Software Foundation, Inc.,
35  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
36  .
37  On Debian systems, the full text of the GNU General Public
38  License version 2 can be found in the file
39  '/usr/share/common-licenses/GPL-2'.
40
41 License: Proprietary
42  PROPRIETARY AND CONFIDENTIAL
43  Unauthorized copying of any files and any codes within this project, via any
44  medium is strictly prohibited.
45  .
46  Any line of code and file in this repository CANNOT be copied and/or
47  distributed in any means, any forms, any medium and any channels, without the
48  express written permission of the owner mentioned above.

Line 1: Format

Declares the copyright format version for the package. It tells how this copyright document to parse. Currently there is only version 1.0, in which you can read it here:

TIP: read the document itself to populate the necessary information in this file.


Line 2: Upstream-Name

The package name. This should be the same as "Source" and "Package" fields in debian/control.


Line 3: Upstream-Contact

The maintainer contact. This should be the same as "Maintainer" field in debian/control.


Line 4: Source

The URL to your source repository / website. This can be the same as "Homepage" field in debian/control.


Line 5: Necessary Line Split

This is an empty line to split the file header, which is Line 1 to Line 4.


Line 6 - Line 9: License Bind

The license binding for a file/set of files. In a bind, you need to specify the filename with its relative path, copyright owner and the corresponding license tag. Keep in mind that the license tag is a recognized short-code, in which you'll define the license later. We'll go through each line one by one here.


Line 6: Files

The list of files you plan to bind to. Use asterisk (*) to indicate all files within a directory. If you use a single asterisk alone like in Line 6, it means the entire package is bind to that license.


Line 7: Copyright Owner

State the copyright owner for the specified files. When applicable, this can be the same as "Maintainer" field in debian/control. If you have multiple owners, you can list them out in the following line with aligned indentation. Here's an example:

Copyright: 1998-2010 Josip Rodin <joy-mg@debian.org>
           2008, John Doe <jdoe@example.com>
           2007, Jane Smith <jsmith@example.org>
           2007, Joe Average <joe@example.org>
           2007, J. Random User <jr@users.example.com>

This field also supports multi-year copyright. See line 15 in the example above.


Line 8: The License Tag

The license tag you wish to bind with. Keep in mind that this is a tag. You'll need to declare the license's body in later section. It is a controlled value specified inside the specification format that you use. Example, for version 1.0, see License Specification section. These license tags are also available at SPDX License List alongside with their respective license body.

If you are using dual or multiple licensing, you can use them with "and" or "or" words for additional bindings. Here's an example:

License: GPL-1+ or Artistic
License: GPL-2+ and BSD-3-clause

Here's how it works, as per version 1.0 format:

A or B( A or B).

A and BA and B.

A or B and CA or (B and C).

A or B, and C(A or B) and C.

You are, however, not allowed to mislead known keywords to a foreign license body. Example: your tag is "GPL-2.0-only" but your license body declares the tag has "NRL License".

Exception

If you really need to use private tag, such as "proprietary" or "fair-use", make sure they are not declared in the known list. As long as the license body is declared in later section that matches the keyword, you're good.


Line 9: Necessary Line Split

When a license bind is completed, this line indicates that binding statements are completed. You should leave an empty new line.


Line 10-12: Demonstrate Licenses Binding Across Multiple Files

This is a different tag to demonstrate how to bind the same license across different files. Notice the similarity.


Line 14-20: Demonstrate License Binding Across Multiple Licenses

This is a different tag to demonstrate how to bind a different license, with multiple copyright owners alongside their copyright years. Notice the similarity.


Line 22: License Declaration

Specify the license body for a particular tag. This line specify GPL2+ tag as deployed in Line 6 and Line 12 license binding. You should append the short text / license header in the following line.


Line 23-39: License Body

The written license body. There is a machine formatting for this section:

  1. Use 1 space ( ) to indicate it's a long text.
  2. If you need an empty line for your text, use a period (.). See line 27, 32, and 36.


Line 40: Necessary Line Split

When a license body is done writing, this line indicates that the declaration is completed. You should leave an empty new line.


Line 41-48: Demonstrate A Multiple Licenses Declaration

This is a different declaration for multiple licenses. Notice the similarity.

Creating debian/changelog

Indicate the software changes in the package. This changelog serves a series of vital information for your package:

  1. software package name
  2. software version, its epoch indicator, and revision
  3. types of package
  4. urgency for installation
  5. contents of the changes
  6. developer/maintainer signed-off

We'll go through one by one later.

Template

1  <name> (<version><-revision>) <distribution>; urgency=<level>
2
3    * <changes 1>
4    * <changes 2>
5
6   -- Josip Rodin <joy-mg@debian.org>  Mon, 22 Mar 2010 00:37:31 +0100
7

The changelog follows a very strict format, especially with the spacing and parenthesis shown above. As per Debian Policy Manual:

  1. <name> - the package name. It is the same as "Source" and "Package" in debian/control.
    • No leading space.
    • A space after the name.
  2. <version><-revision>- the version of the software.
    • Place within a pair of parentheses "()".
    • No space after opening parenthesis "(", and before closing parenthesis ")".
    • A space after the closing parenthesis ")".
  3. <distribution> - The distribution for this package to deliver to.
    • follows up with a semi-colon (;) after completion.
    • A space after the semi-colon.
  4. <level> - urgency level to notify user's system to update this package. It is a controlled value.
    • no space before (after equal)
    • no space after (tailing space)
  5. Necessary Empty Line - Splitting release header
    • Empty new line.
  6. <changes N> - your changelog items. Each item:
    • Starts with a double space ( )
    • Then an asterisk (*)
    • Then a space ( )
    • Then the summary of a change.
    • The whole line should be kept at maximum 80 columns line.
  7. Necessary Empty Line - Splitting changelog items
    • Empty new line.
  8. Signature and Email - The package maintainer / developer signature and email.
    • Starts off with a space ( )
    • A double hyphen (--) follows up.
    • A space after double hyphen.
    • Full name (Capitalized).
    • A space after.
    • Email opening parenthesis (<)
    • Send-able email address
    • Email closing parenthesis (>)
  9. Signed-off Date and Time
    • Double spacing after the email parenthesis
    • Date and time.
  10. Necessary Empty Line - Splitting release entries
    • Empty new line.
  11. Keep Line 1 consistent for each release entries.

Here's an example for Debian unstable branch:

bashell (1.2.0) unstable; urgency=low                                                                                                                                                                    
                                                                                                                                                                                                                   
  *README.md: updated snap installation to have --classic flag                                                                                                                                                     
  *bashell.sh: implement strict test workspace cleaning                                                                                                                                                            
  *bashell.sh: added local cache download and install                                                                                                                                                              
  *test/scripts/bashell/create_bash: fix improper filepath for diff                                                                                                                                                
  *bashell.sh: fix incorrect checking for $TERM                                                                                                                                                                    
  *bashell.sh: fix run test exit always return 0 even in failed cases                                                                                                                                              
                                                                                                                                                                                                                   
 -- ZORALab Enterprise <tech@zoralab.com>  Fri, 25 May 2018 10:41:26 +0800                                                                                                                                         
                                                                                                                                                                                                                   
bashell (1.1.1) unstable; urgency=low                                                                                                                                                                    
                                                                                                                                                                                                                   
  *README.md: added Fedora installation guidelines using snaps                                                                                                                                                     
  *rpmbuild: added rpmbuild build system into repository                                                                                                                                                           
                                                                                                                                                                                                                   
 -- ZORALab Enterprise <tech@zoralab.com>  Mon, 14 May 2018 07:53:42 +0800                                                                                                                                         
                                                                                                                                                                                                                   
bashell (1.1.0) unstable; urgency=low                                                                                                                                                                    
                                                                                                                                                                                                                   
  *SNAP: added ubuntu snaps packaging automation                                                                                                                                                                   
  *bashell.sh: change bash template to use VERSION instead of version                                                                                                                                              
  *README.md: updated documentation to relfect the bash creation feature                                                                                                                                           
  *bashell.sh: added create bashell friendly linux bash script feature                                                                                                                                             
  *bashell.sh: consolidate printouts under single echo                                                                                                                                                             
                                                                                                                                                                                                                   
 -- ZORALab Enterprise <tech@zoralab.com>  Wed, 02 May 2018 22:10:44 +0800 


Name

This is to indicate the changes belongs to this package. It is also meant to identify the origin of the changelog. At minimum, this field must shares the same value as "source" in debian/control.


Version[-Revision]

The common version number. Debian follows [epoch:]upstream_version[-debian_revision]. However, it allows Major.Minor.MajorPatch.MinorPatch format and the commonly use Major.Minor.Patch format as well.

Keep in mind that it does follows the Debian Package Manual definition of version number, such as the specific use of hyphen (-) delimiter: the specific [-Revision] indicator. This delimiter is only meant for indicating upstream build/revision; which makes the upstream testing process easier. With this delimiter, we can also identify the package origin: either it was from an upstream compiled package or an independent native compiled package.

Alternatively, to compensate that hyphen delimiter, the manual encourages us to use the period (.) delimiter, plus (+) delimiter, colon (:) delimiter, and tilde (~) delimiter for conventional version numbering control across different distributions. Here are some good examples:

  • Native Packages
    1. 1.15.35
    2. 1.15
    3. 0.5.0+0ubuntu1~xenialppa1
    4. 1.15~unstable1
    5. 1.15~unstable2
  • Upstream Packages
    1. 1.15-1
    2. 2:1.15-1 (with epoch version 2)

You should not use epoch at all except under the instruction of the distributor's maintainer. Epoch is mainly used for facilitating scheme changes in the upstream system and it is not meant for user consumption.


Distribution

The distribution channel for your package. This varies from different Debian-based operating system such as Debian and Ubuntu. You should follows the upstream guide of the targeted operating system. Example:


Changes Entry

Multi-line entries describing the list of changes per release. This changelog uses asterisk line indicator instead. You should keep each line as short as a terminal 80 column lines. Anything additional should enter a separate files inside your software repository like Release Note document.


Signed Off Signature

The signed-off for the release. It follows a strict pattern:

 -- [FULL NAME] <[EMAIL ADDRESS]>  [RFC-2822 DATE AND TIME]

This signed-off is highly recommended to be done by the package maintainer. The date is RFC-2822 format, in which the following command produces:

$ date -R

If you're creating one manually, ensure it complies to the following format, as specified in the manual:

day-of-week, dd month yyyy hh:mm:ss +zzzz

Example:

Sat, 22 Sep 2018 13:16:54 +0800

Creating debian/rules

This is a Makefile dedicated for building your package. To date (2018), the ecosystem does supply the debhelper to simplify things up. We'll be using this method for building the package.

As per the Debian guide, you're allowed to customize this rules Makefile. However, this guide will focus on copy and paste software as our highest priority is to get things work. If you're looking for customization guide, it will be in a separate topic.

Keeping it simple, we only need this (NOTE: the "TAB" spacing here is TAB, not space):

#!/usr/bin/make -f

# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1

%:
        dh $@

Creating debian/compat

Declare compatibility for the debhelper. As per guide, you can create this file with the number version in it, like "10". A quick way to create this file is:

$ echo 10 > debian/compat

You should build your compatibility version to 10 to avoid outdated disruption.

Creating debian/manpage.N

Creating manual page for your package. You must follow the guide, especially the numbering extension. The manpage format follows the standard man-page format. The number level however, indicates the particular manual page at certain operating system level:

  • 1 - User Commands
  • 2 - System Calls
  • 3 - Library Calls
  • 4 - Special Files
  • 5 - File Formats
  • 6 - Games
  • 7 - Macro Packages
  • 8 - System Administration
  • 9 - Kernel Routine

Use the correct numbering to indicate the content. You can save the documents anywhere inside the debian directory. A good way would be grouping them inside a debian/doc directory.

Creating debian/package.manpages

Create the list of manpages for your package. This file serves as an index for all your manuals. You just need to list your manpages path relative to debian directory in this file. Here's an example of what's inside the file:

doc/package.1
doc/package.2
doc/package.3
doc/package.4
doc/package.5
doc/package.6
doc/package.7
doc/package.8
doc/package.9

The system is smart enough to identify the manpage's level through the file numbering.

Creating debian/source/format

This is to tell the build system to use the source format. There are a series of versions available. The commonly used are:

  • 3.0 (quilt)
  • 3.0 (native)
  • 3.0 (git)
  • 1.0

You just need to create a directory called source and then a file containing the value in it. Quilt is a version control for the package and is compulsory to use it if you're building an upstream package.

Otherwise, stick to the native version 3 by default.

Keep in mind that git version 3 is still experimental and it may not work properly in the upstream version. Use with caution.

Creating debian/install

Tells the package manager to install files at the correct location. In this file, we declare what files to be placed at which location. As per guide, you should declare the path in a pure relative manner. Example:

<relative path from current source to file> <relative to root directory>

Here are some examples:

bin/executable usr/bin/program
src/bar usr/bin/bar

fennec usr/bin                                                                                                                                                                                                     
lib/fennec usr/share/fennec

Now you can't simply copy your files anywhere in the Linux root system. All the corresponding files should comply to the Debian File Hierarchy Standards.

For our power-on objective, let's keep things simple by copying 1 file to a known location of your desire.

Once you're done, you should have your Debian directory ready. A quick look over the package should produce something as follows (an example):

debian
├── changelog
├── compat
├── control
├── copyright
├── fennec.1
├── fennec.manpages
├── install
├── rules
└── source
    └── format

There are more files specified by the policy manual and the guide. However, these are the minimum requirements for the package builder to build a successful deb package.