Debian Package for Apache Tutorial

Published by Matthew Turner on .

There are many good resources for building your own Debian package. However, the resources for doing so specifically for Apache HTTPd are quite lacking.

Table of Contents

Introduction

There are many good resources for building your own Debian package. However, the resources for doing so specifically for Apache HTTPd are quite lacking. If you are looking to build a non-Apache package, then this tutorial is not for you. Please look at the references for resources.

For comprehensiveness, there is a section on self-hosting Debian packages. This is useful for development as well as for use until the mentors accept it. They are a good resource for your packaging journey.

Packaging for Debian

Dependencies for building packages:

sudo apt install make build-essential fakeroot devscripts

 

The first thing that you need to know is that there are two kinds of Debian packages: native and quilt. The latter, quilt, is the preferred approach and is better documented. Specifically, quilt is meant when the source and the package live in separate repositories, and the source is potentially used for multiple platforms. On the other hand, while less preferred, native is meant for source and package joined together in the same repository and exclusively developed for Debian. While I will henceforth assume that you are developing a native package, most of the tutorial is still applicable. Please refer to documentation and other resources if you are developing a quilt package.

 

You MUST have the following file:

your/repo/debian/source/format

3.0 (native)

 

You MUST have a copyright file following Debian's standard:

/your/repo/debian/copyright

Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: https://github.com/user/libapache2-mod-package-name
Upstream-Name: libapache2-mod-package-name
Upstream-Contact: Name <email@host.com>
Files:
 *
Copyright: YYYY Name
License: short-name
    .
    license text

 

You MUST have a changelog that can be generated with dch and formatted properly:

/your/repo/debian/changelog

libapache2-mod-package-name (0.0.0) unstable; urgency=medium
  * Initial release.
 -- Name <email@host.com>  Sun, 8 Oct 2025 13:46:32 -0700

 

You MUST have a control file:

/your/repo/debian/control

Source: libapache2-mod-package-name
Maintainer: Name <email@host.com>
Uploaders: Name <email@host.com>
Section: httpd
Priority: optional
Standards-Version: 4.6.2
Build-Depends: debhelper-compat (= 13),
    apache2-api-20120211,
    apache2-dev,
    dh-apache2
Homepage: https://github.com/user/libapache2-mod-package-name
Vcs-Browser: https://github.com/user/libapache2-mod-package-name
Vcs-Git: https://github.com/user/libapache2-mod-package-name
Package: libapache2-mod-package-name
Architecture: all
Depends: ${misc:Depends}, php
Homepage: https://github.com/user/libapache2-mod-package-name
Description: This is an Apache module in PHP.
 .
 More description.

Important fields:

 

You MAY have

/your/repo/debian/docs

README.md

This is the path to additional documentation files, one per line, relative to the repository root (/your/repo/). Note that some may be included in README.Debain, see Packaging for Apache for more details.

 

You MAY have

/your/repo/debian/libapache2-mod-package-name.examples

example.php

This is the path to additional example files, one per line, relative to the repository root (/your/repo/). As examples, they are purely for reference purposes.

 

You MAY have

/your/repo/debian/install

app.php /usr/src/libapache2-mod-package-name/

This is the path to additional installation files, one per line, that do not belong in another file. Typically these are source and binary files. The first entry on a line is relative to the repository root (/your/repo/) and the second entry is the final absolute path it will be installed under. Typical paths are /usr/src/ and /usr/bin/ to adhere to the Filesystem Hierarcy Standard.

 

You MAY have

/your/repo/debian/libapache2-mod-package-name.lintian-overrides

This file has, one per line, an exact copy of an error or warning that lintian outputs. CAUTION, it is generally discouraged to ignore these, and it is provided for situations where the behaviour is known, expected, and intentional.

 

For quilt you MAY also have

/your/repo/debian/watch

Packaging for Apache

Dependencies for building Apache-specific packages:

sudo apt install apache2-dev

For compiled modules, this will instead be

sudo apt install apxs apache2-dev

 

You are RECOMMENDED to have

/your/repo/debian/libapache2-mod-package-name.apache2

mod mod_package_name.so
mod package_name.load
conf other1.conf
conf other2.conf

The first two lines, starting with mod, are exclusively for a compiled module (these MUST have the same name as the package, and you MUST have both lines); if you are not compiled, such as with PHP, then do not include these. The .so and .load will be auto-generated as a part of the build process for compiled modules. You may have any number of conf lines, and these will be installed as additional Apache configuration. While this file is not strictly required, without it there will need to be manual configuration after installation to utilize any installed files. Thus, you will almost ALWAYS want this file.

 

You MUST have

/your/repo/debian/rules

#!/usr/bin/make -f
override_dh_auto_build:
	#apxs2 -c -Wc,-fno-strict-aliasing -Wc,-ffile-prefix-map=$(CURDIR)=. mod_package_name.c
override_dh_auto_install:
	# handled by dh_install
override_dh_builddeb:
	dh_builddeb -- -Zxz
%:
	dh $@ --with apache2

The most important part to pay attention to is the --with apache2. This is what lets the build system know that it is an Apache module that you are building so it will enable the .apache2 configuration to be processed. Non-compiled modules need this as well.

For compiled modules, they will need the commented line with apxs2 so that it can be run as a part of the build (more information about apxs2 and compiled modules in the official guide).

Please also note that dh_builddeb -- -Zxz SHOULD be unnecessary. However, I included this line after issues occurred when I tried to upload or host the package. It needs some kind of compression and the default was not giving any on my system. Warning, this will cause a lintian warning to be issued during the build.

 

You MAY have

/your/repo/debian/libapache2-mod-package-name.postinst

#!/bin/sh
set -e
#DEBHELPER#
# commands
exit 0

This will include any additional scripting to run for completing the installation. Take particular note of #DEBHELPER# because this will be replaced with the auto-generated Apache-specific scripting.

Building

Finally, to build your package you can run

debuild -us -uc -Zxz

Please note that the -Zxz option SHOULD be unnecessary. However, I included this line after issues occurred when I tried to upload or host the package. It needs some kind of compression and the default was not giving any on my system. This MUST match the compression in the rules file.

 

Due to debuild outputting to the directory above your repository, I also recommend running

mkdir package || true
mv ../libapache2-mod-package-name_* package/

 

For security purposes, you may want to consider adding a digital signature by running

cd package && debsign libapache2-mod-package-name_0.0.0_amd64.changes

Packaging for PEAR/Composer

If you would like to use PEAR packages for PHP, then some additional steps MUST be performed. However, it is important to note that the preferred approach assumes that the PEAR packages have a corresponding Debian package (with a specific naming convention) available to you. Since this MAY NOT be the case, you will either need a separate package to fulfill this requirement (by repackaging the PEAR for Debian) OR to follow the provided short-cut. WARNING, PLEASE ABIDE BY THE LICENSING OF THE PEAR PACKAGE, IN REGARD TO DISTRIBUTION RIGHTS, WHICH EITHER APPROACH MAY VIOLATE.

Preferred Approach

Dependencies

sudo apt install php-dev composer php-pear pkg-php-tools dh-php dh-sequence-phpcomposer

 

Update

/your/repo/debian/control

Build-Depends: debhelper-compat (= 13),
    apache2-api-20120211,
    apache2-dev,
    dh-apache2,
    php-dev,
    pkg-php-tools,
    dh-php,
    dh-sequence-phpcomposer
Depends: ${misc:Depends}, ${phpcomposer:Debian-require}, php

This will manage the PEAR-to-Debian conversion for your dependencies.

 

Update

/your/repo/debian/rules

%:
	dh $@ --with apache2 --with php

This will allow PEAR/Composer to run during debuild.

 

Run composer

composer require pear-package

This will create composer.json.

Short-cut

WARNING, PLEASE ABIDE BY THE LICENSING OF THE PEAR PACKAGE, IN REGARD TO DISTRIBUTION RIGHTS, WHICH EITHER APPROACH MAY VIOLATE.

 

Dependencies

sudo apt install php-dev composer php-pear

 

Run composer

composer require pear-package

This will create composer.json.

 

Update

/your/repo/debian/rules

override_dh_auto_build:
	composer install

This will create composer.lock and vendor/ during debuild so that you do not forget.

 

Update

/your/repo/debian/install

vendor /usr/src/libapache2-mod-package-name/
composer.* /usr/src/libapache2-mod-package-name/

This will distribute the PEAR package inside your Debian package. WARNING, PLEASE ABIDE BY THE LICENSING OF THE PEAR PACKAGE, IN REGARD TO DISTRIBUTION RIGHTS, WHICH EITHER APPROACH MAY VIOLATE.

Hosting Debian Packages

# Credit:
# - https://earthly.dev/blog/creating-and-hosting-your-own-deb-packages-and-apt-repo/
# - https://gist.github.com/awesomebytes/ce0643c1ddead589ab06e2a1e4c5861b
# - https://wiki.debian.org/DebianRepository/SetupWithReprepro
# - https://rpmdeb.com/devops-articles/how-to-create-local-debian-repository/

 

First, you need a suite directory to hold the packages. This suite directory is RECOMMENDED to have a codename of a release or an alias; and it MUST have a particular directory structure underneath.

mkdir unstable || true
mkdir debian/libapache2-mod-package-name || true
cp /your/repo/package/libapache2-mod-package-name* unstable/libapache2-mod-package-name/

 

Next, you MUST have a package manifest for the suite. This manifest is RECOMMENDED to have a compressed copy as well.

dpkg-scanpackages --multiversion unstable > unstable/Packages
cat unstable/Packages | gzip -9 > unstable/Packages.gz

Note that --multiversion allows you to broadcast multiple versions of the package. Without this, other packages can be present, but apt (or another package manager) will not be aware of them.

 

Then you MUST have a release manifest for the suite. The following commands have two supporting scripts below.

./release_meta.bash > debian/Release
./release_hash.bash debian/ "MD5Sum" "md5sum" >> unstable/Release
./release_hash.bash debian/ "SHA1" "sha1sum" >> unstable/Release
./release_hash.bash debian/ "SHA256" "sha256sum" >> unstable/Release

 

./release_meta.bash

#!/bin/bash
cat << EOF
Origin: example.com
Label: Example
Suite: unstable
Codename: unstable
Version: 1.0
Architectures: amd64
Components: main
Description: Hosted packages
Date: $(date -Ru)
EOF

 

./release_hash.bash

#!/bin/sh
set -e
# Credit: https://earthly.dev/blog/creating-and-hosting-your-own-deb-packages-and-apt-repo/
HASH_DIR=$1
HASH_NAME=$2
HASH_CMD=$3
cd "${HASH_DIR}"
echo "${HASH_NAME}:"
for f in $(find -type f); do
    f=$(echo $f | cut -c3-) # remove ./ prefix
    if [ "$f" = "Release" ]; then
        continue
    fi
    echo " $(${HASH_CMD} ${f}  | cut -d" " -f1) $(wc -c $f)"
done

 

At this point, you need to host the suite directory through some webserver.

 

Finally, you need your destination to become aware of the hosted package repository.

/etc/apt/sources.list.d/example.list

deb [trusted=yes] https://example.com/your/package/repo/ unstable/

 

If you have set up SSL/TLS on your webserver with a self-signed certificate, then you will also need to download it and configure it at your destination.

/etc/apt/apt.conf.d/80-vendor-example

Acquire::https::example.com {
	Verify-Peer "true";
	Verify-Host "true";
	CaInfo "/your/ssl/certs/ssl-cert-self-signed.pem";
}

References

Packaging for Debian

Lintian

Packaging for Apache

Packaging for PEAR/Composer

Hosting Packages

My Project Examples

Webmentions Received

Comments