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
- Packaging for Debian
- Packaging for Apache
- Building
- Packaging for PEAR/Composer
- Hosting Debian Packages
- References
- Comments
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:
-
Source and Package — these are the source and compiled packages, respectively. The latter is the one that will be installed. Apache packages are expected to be in the form
libapache2-mod-*. -
Section — we are building for Apache so
httpdis the appropriate value. -
Standards-Version — there may be a newer version,
4.6.2is the known version at time of writing. -
Build-Depends — this is where you list other Debian packages that your build depends on. Listed are the minimum dependencies to build against Apache. Please note that the Apache dependences are required whether you are building a compiled module or not. Also note that the
debhelper-compatmay have a newer version,13is the known version at time of writing. -
Architecture — this can be
allfor PHP packages, but may be specific to your target audience if you are making a compiled package (such asamd64). This can take multiple values. -
Depends — this is where you list other Debian packages that the installation of your package depends on.
${misc:Depends}is the minimum (this pulls in packages from theBuild-Dependsthat are for both); andphpis required for running PHP packages. - Suggests — this is optional (not included above) for other Debian packages that work well with yours, but is not required for yours to function.
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-phpcomposerDepends: ${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
- https://www.debian.org/doc/manuals/debmake-doc/index.en.html
- https://www.debian.org/doc/manuals/maint-guide/
- https://www.debian.org/doc/debian-policy/ch-scope.html
- https://wiki.debian.org/Packaging/Intro
- https://wiki.debian.org/Packaging
- https://wiki.debian.org/HowToPackageForDebian
- https://wiki.debian.org/BuildingTutorial
- https://serverfault.com/questions/380454/creating-custom-deb-packages-of-common-programs
- https://stackoverflow.com/questions/7176065/how-do-i-create-a-native-debian-package-for-static-files/7176656#7176656
- https://www.makeuseof.com/create-deb-packages-debian-ubuntu/
- https://mentors.debian.net/
- https://stackoverflow.com/questions/71196872/how-do-i-build-a-deb-without-zstd-compression-in-ubuntu-21-10/72359798#72359798
- https://github.com/yktoo/indicator-sound-switcher/issues/113#issuecomment-997810115
- https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
- https://manpages.debian.org/testing/devscripts/dch.1.en.html
- https://www.debian.org/releases/stable/amd64/apcs02.en.html
- https://stackoverflow.com/questions/7176065/how-do-i-create-a-native-debian-package-for-static-files
- https://wiki.debian.org/PackagingWithGit
- https://www.debian.org/doc/manuals/debian-faq/pkg-basics.en.html
Lintian
- https://lintian.debian.org/manual/index.html
- https://manpages.debian.org/testing/debhelper/dh_lintian.1.en.html
- https://manpages.debian.org/testing/lintian/lintian.1.en.html
- https://wiki.debian.org/EnsuringPackageIsLintianCleanBeforePushingUpstream
- https://lists.debian.org/debian-mentors/2011/11/msg00566.html
- https://lintian.debian.org/tags/privacy-breach-generic.html
- https://httpd.apache.org/
- https://httpd.apache.org/docs/2.4/developer/modguide.html
- https://wiki.debian.org/Apache/PackagingFor24
- https://wiki.debian.org/Apache/PackagingModules
- https://manpages.debian.org/unstable/apache2-dev/dh_apache2.1.en.html
- https://manpages.ubuntu.com/manpages/questing/en/man1/dh_apache2.1.html
- https://askubuntu.com/questions/260978/add-custom-steps-to-source-packages-debian-package-postinst
- https://stackoverflow.com/questions/35971583/debian-package-creation-postinst-as-non-root
- https://stackoverflow.com/questions/21974320/dpkg-postinst-how-to-run-it-as-a-normal-user
- https://getcomposer.org/
- https://udd.debian.org/lintian-tag/composer-prerequisite
- https://wiki.debian.org/Teams/DebianPHPGroup/Composer
- https://askubuntu.com/questions/403327/install-pecl-packages-on-ubuntu
- https://softwareengineering.stackexchange.com/questions/195633/good-approaches-for-packaging-php-web-applications-for-debian
- https://gist.github.com/awesomebytes/ce0643c1ddead589ab06e2a1e4c5861b
- https://www.joshmcguigan.com/blog/host-debian-repo/
- https://earthly.dev/blog/creating-and-hosting-your-own-deb-packages-and-apt-repo/
- https://wiki.debian.org/DebianRepository/Setup
- https://wiki.debian.org/DebianRepository/SetupWithReprepro
- https://superuser.com/questions/124174/how-can-i-specify-the-repository-from-which-a-package-will-be-installed-emacs/124200#124200
- https://wiki.debian.org/SourcesList
- https://wiki.debian.org/DebianRepository/Format
- https://askubuntu.com/questions/49196/how-do-i-create-a-self-signed-ssl-certificate/49197#49197
- https://serverfault.com/questions/1093511/apt-get-update-failing-because-of-certificate-validation/1133024#1133024
- https://serverfault.com/questions/340887/using-a-self-signed-ssl-cert-for-an-https-based-internal-apt-repository/561100#561100
My Project Examples