15.4 Configuration Packages and Forking
Key Takeaways
- Kali forks a Debian package when it needs changes Debian will not take; Kali-specific versions append a kaliN suffix to the Debian revision (e.g. 2.9.4-1kali1)
- dch --local adds a changelog entry with the local suffix, and dpkg-buildpackage -us -uc -b rebuilds the forked .deb
- A configuration package overrides another package's files by registering diversions with dpkg-divert, so the original is safely renamed aside and restored on removal
- dpkg-divert survives package upgrades, unlike editing files in place, which the owning package will silently overwrite
- Kali's own kali-defaults package is the reference example; combining config packages + a custom repository + Salt gives fleet-wide, versioned, self-healing Kali policy
Two problems remain after you can image and configure machines at scale. Sometimes Kali itself must change a package it imports from Debian — that is forking. And sometimes your organization must override files owned by packages you do not control — that is the configuration package pattern. Both are exam topics, and both end the same way: your changes live in versioned packages on your internal repository.
Forking a Kali Package
Kali is rebuilt on Debian (Testing), and most packages flow in unmodified. But when Kali needs a change Debian will not accept — a patched feature, different defaults, a security tweak — Kali forks the package: it maintains its own build with a Kali-specific version. The convention you must recognize is the version suffix. A Debian version like 2.9.4-1 becomes 2.9.4-1kali1 in Kali; the kali1 marks the first Kali revision of that Debian version, bumped to kali2 for the next Kali change (real archive examples: autopsy 2.24-6kali1, amap 5.4-4kali6). When the Debian source is native-format — an upstream version with no -N revision to append to — Kali appends +kaliN instead: apt 3.2.0+kali1, tasksel 3.88+kali2. Packages Kali ships that Debian never had take a 0 revision plus the suffix: crlfuzz 1.4.1-0kali1 (the book's older cherrytree 0.38.8-0kali1 example has since moved into Debian proper). You will also see ~kali1 in some ecosystems. A bare or + suffix sorts after the base version while ~ sorts before, so the suffix both brands the package and controls upgrade ordering.
The workflow for maintaining a fork:
apt source somepackage # fetch source (needs deb-src lines) into ./somepackage-2.9.4/
cd somepackage-2.9.4
dch --local kali "Disable telnet fallback by default for policy compliance"
# ... make your source changes ...
dpkg-buildpackage -us -uc -b # build unsigned binary .deb
dch (from devscripts) edits debian/changelog: --local kali appends the suffix to the current version, turning 2.9.4-1 into 2.9.4-1kali1 and opens a new entry with your name, date, and message. The changelog is not bureaucracy — APT's entire upgrade logic keys off the version it defines. -us -uc skips GPG signing for a local build; the repository's SignWith key handles trust later. The finished .deb goes into your reprepro repository with includedeb, and from there to the fleet.
- Exam trap: a fork creates an ongoing maintenance duty — every time Debian or Kali updates the original, someone must merge the changes and rebuild. Fork only what you must.
Before forking, exhaust the cheaper options: many "changes" are really configuration (handle those with a configuration package instead), and genuinely useful fixes should be proposed upstream — Kali maintains its packages and their packaging sources publicly on GitLab (gitlab.com/kalilinux), and the Kali bug tracker (bugs.kali.org) is the right place to request changes. You can also inspect exactly how Kali diverged from Debian there, which doubles as the best study aid for this section: pick any package with a kali1 version, read its changelog, and you will see the dch-generated entries describing each Kali-specific change. When the change is truly local to your organization — an internal CA bundle, a patched agent — the fork workflow above is the right tool, and your reprepro repository is where the result lives.
Configuration Packages with dpkg-divert
Kali Linux Revealed builds its configuration package the plain Debian way: create an offsec-defaults-1.0/ directory holding the files you want shipped, run dh_make --native (package type indep, since it is architecture-independent text), edit debian/control, list what goes where in debian/<package>.install, then build with dpkg-buildpackage -us -uc. Its example payload is exactly the enterprise bundle from this chapter: an /etc/apt/sources.list.d/ entry for the internal repository, that repository's key, a Salt minion configuration under /etc/salt/minion.d/, a corporate wallpaper, and a gsettings override. The far more common need is not changing code but changing configuration — and doing it in a way that survives apt upgrade. Editing /etc/ssh/sshd_config or a desktop default by hand works until the owning package ships an update and clobbers or conflicts with your edit. The robust pattern, used by Kali's own kali-defaults package, is a configuration package that overrides files via dpkg-divert.
dpkg-divert is dpkg's official mechanism for saying "the file at this path should actually live somewhere else." When your configuration package installs, its postinst maintainer script runs:
dpkg-divert --package acme-kali-config --rename --add /etc/ssh/sshd_config
cp /usr/share/acme/sshd_config /etc/ssh/sshd_config
--add registers the diversion; --rename moves the distributor's original to /etc/ssh/sshd_config.distrib; --package names the one package exempt from the diversion — every other package's copy of that path gets diverted, while your own package's file still lands at the real path. Your package then installs its own version at the original path. The key properties, all exam-worthy:
- Upgrades are safe: when
openssh-serverupdates, dpkg writes its new file to the diverted path (.distrib), not over yours. - Removal restores the original: your package's
prermrunsdpkg-divert --package acme-kali-config --rename --remove /etc/ssh/sshd_config, and the distributor's file returns. - Everything is tracked:
dpkg-divert --listshows every active diversion, and the override appears indpkg -Sand package listings — no mystery edits.
The configuration package's control file typically Depends: on the packages it configures (so installing it pulls in openssh-server itself) and can conflict with packages that would break your policy. Kali uses this exact technique — kali-defaults and friends are why a stock Kali box has its distinctive look, its shell defaults, and its tweaked tool configurations, all delivered as ordinary packages.
Prefer drop-in directories (e.g. /etc/ssh/sshd_config.d/*.conf) when the software supports them — they need no diversion at all — but for the many files without include support, dpkg-divert is the canonical answer.
Fleet-Wide Policy: Config Packages + Custom Repo + Salt
Now assemble the full enterprise stack from this chapter:
- Package the policy: your
acme-kali-configpackage carries hardened configs, diverted safely;acme-kali-tools(a metapackage) defines the toolset; any forks carrykali1versions. - Distribute it: reprepro hosts everything; clients have the repo in
sources.list.dand your GPG key in their keyring. - Enforce it: a Salt state pins the whole thing in place:
acme-repo:
pkgrepo.managed:
- name: deb http://repo.acme.internal/ kali-rolling main
- file: /etc/apt/sources.list.d/acme.list
acme-kali-config:
pkg.installed:
- require:
- pkgrepo: acme-repo
acme-kali-tools:
pkg.installed:
- require:
- pkgrepo: acme-repo
The payoff is compounding: PXE + preseed builds the machine, its late_command installs the Salt minion, the first highstate adds the repo and installs your config and tool packages, and every subsequent highstate reconverges any drift — an admin who hand-edits sshd_config gets corrected on the next run. That closed loop, from bare metal to enforced policy with no manual steps, is what "Kali Linux in the enterprise" means in practice, and it is the mental model the KLCP exam is checking for.
You see the package version 2.9.4-1kali1 installed on a system. What does the kali1 suffix tell you?
Why does a configuration package use dpkg-divert instead of simply overwriting /etc/ssh/sshd_config during installation?