Looked at deb-pkg-tools for Python. Not a lot of obvious benefit. File name is name-stable_vers-dvers_arch.deb Prefix internally with "!" and newline. (Default for ar!) ar -rcSD my.deb files .deb is just an 'ar' archive with: ar -tv microsoft-edge-stable_147.0.3912.60-1_amd64.deb rw-r--r-- 0/0 4 Apr 9 16:23 2026 debian-binary rw-r--r-- 0/0 11380 Dec 31 19:00 1969 control.tar.xz rw-r--r-- 0/0 182242916 Dec 31 19:00 1969 data.tar.xz rw-r--r-- 0/0 481 Apr 10 02:42 2026 _gpgorigin The _gpgorigin thing is nonstandard and can be added later. debian-binary is just "2.0" as a single text line. data.tar.xz is root-relative install files, Xtar, root/root owner. drwxr-x--- root/root 0 2026-04-09 16:23 ./ drwxr-xr-x root/root 0 2026-04-09 16:23 ./etc/ drwxr-xr-x root/root 0 2026-04-09 16:23 ./etc/cron.daily/ drwxr-xr-x root/root 0 2026-04-09 16:23 ./opt/ drwxr-xr-x root/root 0 2026-04-09 16:23 ./opt/microsoft/ drwxr-xr-x root/root 0 2026-04-09 16:23 ./opt/microsoft/msedge/ drwxr-xr-x root/root 0 2026-04-09 16:23 ./opt/microsoft/msedge/MEIPreload/ cd $AB_HOME Xtar Jcf outdir/data.tar.xz --owner=root --group=root -T filelist control.tar.xz is files like this: drwxr-xr-x root/root 0 2026-04-09 16:23 ./ -rw-r--r-- root/root 1148 2026-04-09 16:23 ./control -rwxr-xr-x root/root 20193 2026-04-09 16:23 ./postinst -rwxr-xr-x root/root 15523 2026-04-09 16:23 ./postrm -rwxr-xr-x root/root 1241 2026-04-09 16:23 ./prerm Control file has: Package: microsoft-edge-stable Version: 147.0.3912.60-1 Architecture: amd64 Maintainer: Microsoft Edge for Linux Team Installed-Size: 641140 Pre-Depends: dpkg (>= 1.14.0) Depends: ca-certificates, fonts-liberation, libasound2 (>= 1.0.17), libatk-bridge2.0-0 (>= 2.5.3), libatk1.0-0 (>= 2.11.90), libatspi2.0-0 (>= 2.9.90), libc6 (>= 2.17), libcairo2 (>= 1.6.0), libcups2 (>= 1.6.0), libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3, libdbus-1-3 (>= 1.9.14), libexpat1 (>= 2.1~beta3), libgbm1 (>= 17.1.0~rc2), libglib2.0-0 (>= 2.39.4), libgtk-3-0 (>= 3.9.10) | libgtk-4-1, libnspr4 (>= 2:4.9-2~), libnss3 (>= 2:3.35), libpango-1.0-0 (>= 1.14.0), libudev1 (>= 183), libuuid1 (>= 2.16), libvulkan1, libx11-6 (>= 2:1.4.99.1), libxcb1 (>= 1.9.2), libxcomposite1 (>= 1:0.4.4-1), libxdamage1 (>= 1:1.1), libxext6, libxfixes3, libxkbcommon0 (>= 0.5.0), libxrandr2, wget, xdg-utils (>= 1.0.2) Provides: www-browser Section: web Priority: optional Description: The web browser from Microsoft Microsoft Edge is a browser that combines a minimal design with sophisticated technology to make the web faster, safer, and easier. Section should be misc. Version always needs a "-1" for Debian package version. postinst: #!/bin/sh [...] update-alternatives --install /usr/bin/microsoft-edge microsoft-edge \ /usr/bin/microsoft-edge-stable $PRIORITY postrm: ... nothing? prerm: #!/bin/sh action="$1" if [ "$2" = "in-favour" ]; then # Treat conflict remove as an upgrade. action="upgrade" fi # Don't clean-up just for an upgrade.` if [ "$action" = "upgrade" ] ; then exit 0 fi update-alternatives --remove microsoft-edge /usr/bin/microsoft-edge-stable cd controldir Xtar Jcf ../outdir/control.tar.xz cd outdir echo "2.0" > debian-binary ar -cf ../ab-package_1.1-1_amd64.deb * --- Debian repo format: mkdir dists/stable/non-free mkdir dists/stable/contrib In stable: InRelease Release InRelease file: Origin: Debian Label: Debian Suite: stable Version: 13.5 Codename: trixie Changelogs: https://metadata.ftp-master.debian.org/changelogs/@CHANGEPATH@_changelog Date: Sat, 16 May 2026 09:42:04 UTC Acquire-By-Hash: yes No-Support-for-Architecture-all: Packages Architectures: all amd64 arm64 armel armhf i386 ppc64el riscv64 s390x Components: contrib non-free Description: Debian 13.5 Released 16 May 2026 MD5Sum: 3f9227b1aa510c20408dc34132c2df9e 1959586 contrib/Contents-all d39ffb553416d926059c3b52ff3b5061 134039 contrib/Contents-all.gz 41c164dc66d4f58d89987ab26cc51392 3059725 contrib/Contents-amd64 b46abcf1291b763dd208ebfab90a601f 187747 contrib/Contents-amd64.gz [...] SHA256: ae508754e2ebad9d1d1090248c80258c0c41b1344697bfa12cff3d0bf56e78a4 1959586 contrib/Contents-all bf0da030de5025ba94c48c76e352b3639f9948e876c4d6f8b7105b49873173a2 134039 contrib/Contents-all.gz 5890b46f6a7b4194334657801608705c251fa592f50f68d16c007eb5581ee20b 3059725 contrib/Contents-amd64 630d65a9d659333641ab82ddc1623eff607e7ba8e8f1bcbbb8c63906bc58f7c7 187747 contrib/Contents-amd64.gz a907d98592312a27cede5c179674df920f0fb6f21df83e012f5ef9a509680c3c 1641886 contrib/Contents-arm64 7ed7175acc7ecb0cc871281153763d822dc3cebd08f005627d287b47f8ade709 114902 contrib/Contents-arm64.gz In contrib and non-free: Contents-amd64.gz binary-amd64/ Contents file has: boot/2nd_gen_i5_i7_SINIT_51.BIN non-free/admin/intel-acm boot/3rd_gen_i5_i7_SINIT_67.BIN non-free/admin/intel-acm boot/4th_gen_i5_i7_SINIT_75.BIN non-free/admin/intel-acm boot/5th_gen_i5_i7_SINIT_79.BIN non-free/admin/intel-acm boot/6th_7th_gen_i5_i7-SINIT_79.bin non-free/admin/intel-acm boot/7th_8th_gen_i5_i7-SINIT_81.bin non-free/admin/intel-acm boot/GM45_GS45_PM45_SINIT_51.BIN non-free/admin/intel-acm boot/Q35_SINIT_51.BIN non-free/admin/intel-acm boot/Q45_Q43_SINIT_51.BIN non-free/admin/intel-acm boot/Xeon-5600-3500-SINIT-v1.1.bin non-free/admin/intel-acm boot/Xeon-E7-8800-4800-2800-SINIT-v1.1.bin non-free/admin/intel-acm boot/i5_i7_DUAL_SINIT_51.BIN non-free/admin/intel-acm Use "misc" instead of "admin." Reference example of repo: https://ftp.debian.org/debian/