Installing Debian .deb Packages on Arch Linux (Without the AUR)

Linux Arch Linux Audio ajboni ・ 10/2/2026

A lot of pro audio software ships exclusively as .deb for Debian/Ubuntu. Tracktion is a perfect example: their Download Manager and Waveform 14 are distributed as Debian packages, with no official Arch package in sight.

Here is how I got both running on Arch: per-user, sandbox-friendly, and with zero third-party PKGBUILDs.

The problem

On Arch you have three obvious options, and each has a catch:

  1. The AUR. There was an tracktion-download-manager package at the exact version I needed, but it had zero votes, zero popularity, a single maintainer, and had never been revised since submission. Every AUR PKGBUILD is user-submitted and unvetted, AUR artifacts aren't signed, and recent supply-chain incidents have targeted exactly this profile: low-attention packages and "sleeper" accounts. Not a great trade for a closed-source binary.
  2. debtap. Converts a .deb into an Arch package. It uses your file, which is better, but you're still trusting a third-party AUR tool to do the conversion.
  3. Manual extraction. The .deb is just an ar archive containing two tarballs. Extract it, check the dependencies, run it. For a self-contained binary this is the least-trust path: the runtime comes only from the vendor, and the libraries come only from the official repos.

This post is option 3, done carefully, with an integrity check, a dependency audit, a no-root trial run, and finally a per-user install that shows up in your application menu.

What's actually inside a .deb

A .deb is an ar archive with three members:

$ ar t tracktion_download_manager_v1.5.3.deb
debian-binary
control.tar.xz     # metadata, deps, checksums
data.tar.xz        # the actual files
  • control.tar.* holds the control file (declared dependencies) and md5sums.
  • data.tar.* holds the payload, rooted at the filesystem level (usr/bin/..., usr/share/...).

The compression varies: the download manager used xz, while Waveform 14 used gz. That detail matters: tar -xJf (xz) fails on a gzip payload. Check first with file, or use the right flag.

Step 1: Inspect before you extract

file waveform14_14.0.50_amd64.deb
ar t waveform14_14.0.50_amd64.deb

# declared dependencies
ar p waveform14_14.0.50_amd64.deb control.tar.gz | tar -xOzf - ./control

# payload listing
ar p waveform14_14.0.50_amd64.deb data.tar.gz | tar -tzf -

Waveform's control reveals the usual GTK stack:

Depends: lame, ffmpeg, libcurl4t64 | ..., libasound2t64 (>= 1.2.10),
 libatomic1 (>= 4.8), libc6 (>= 2.38), libfontconfig1, libfreetype6,
 libgcc-s1, libgl1, libglib2.0-0t64, libgtk-3-0t64,
 libjavascriptcoregtk-4.1-0, libsoup-3.0-0, libusb-1.0-0,
 libwebkit2gtk-4.1-0 (>= 2.39.90)

Every one of those maps to a current Arch package (gtk3, webkit2gtk-4.1, libsoup3, libusb, fontconfig, lame, ffmpeg, …). Good sign. But declared dependencies on Debian aren't the same as the binary's actual dynamic dependencies, so let's verify those directly.

Step 2: Read the ELF's real DT_NEEDED entries

The linker tells the truth. This tiny Python snippet parses the ELF .dynamic section straight from a pipe, with no temp files:

ar p waveform14_14.0.50_amd64.deb data.tar.gz \
  | tar -xOzf - ./usr/bin/Waveform14 \
  | python3 -c 'import sys,struct
b=sys.stdin.buffer.read()
e_shoff,=struct.unpack_from("<Q",b,0x28)
e_shentsize,e_shnum,_=struct.unpack_from("<HHH",b,0x3a)
secs=[struct.unpack_from("<IIQQQQIIQQ",b,e_shoff+i*e_shentsize) for i in range(e_shnum)]
for name,typ,off,size,link,info,align,ent in secs:
 if typ==6:
  doff=secs[link][2]
  for j in range(size//(ent or 16)):
   tag,val=struct.unpack_from("<qQ",b,off+j*16)
   if tag==1:
    print(b[doff+val:b.index(b"\x00",doff+val)].decode())'

For Waveform that yields libwebkit2gtk-4.1.so.0, libgtk-3.so.0, libGL.so.1, and friends. Cross-check each against your system:

for lib in libwebkit2gtk-4.1.so.0 libgtk-3.so.0 libGL.so.1; do
  ldconfig -p | grep -m1 "^[[:space:]]*${lib} "
done

The trap I dodged. The other Tracktion app, Download Manager, hard-references libwebkit2gtk-4.0.so, and Arch only ships WebKitGTK 4.1 (a different SONAME, not ABI-compatible). That's an embedded-web-view risk, not a startup failure. Waveform 14 is built against 4.1, so it's clean. Always check the specific SONAME, not just the library name.

Step 3: Extract to /tmp and verify checksums

Never install before you've validated the payload against the package's own manifest:

rm -rf /tmp/wf-test && mkdir -p /tmp/wf-test && cd /tmp/wf-test
ar x /home/baj/Downloads/waveform14_14.0.50_amd64.deb
tar -xzf data.tar.gz

# verify every file against the deb's md5sums
ar p /home/baj/Downloads/waveform14_14.0.50_amd64.deb control.tar.gz \
  | tar -xOzf - ./md5sums | (cd /tmp/wf-test && md5sum -c)

chmod +x /tmp/wf-test/usr/bin/Waveform14

md5sum -c should report OK for all files. If it doesn't, stop.

Step 4: Trial run with no root

Because the binary resolves its libraries from the normal ld cache, you can run it straight out of /tmp:

setsid --fork nohup /tmp/wf-test/usr/bin/Waveform14 \
  >/tmp/wf-run.log 2>&1 </dev/null & disown

setsid --fork plus disown fully detaches it so your shell isn't held open, which matters if you're scripting this.

If you're on Hyprland, confirm it actually opened a window:

hyprctl clients | grep -iE 'class:|title:' | grep -i waveform

Expect noise in the log: LV2 plugin scan notices (lilv_world_add_plugin), ALSA startup underruns, and an xprop lookup line. None of it is fatal. What you're watching for are missing-library or RUNPATH errors.

If you want an even tighter trial for a closed-source binary, bubblewrap is available on Arch: read-only system, writable scratch $HOME, with /dev/snd and the Wayland socket passed through. Great for a "run it once and see" test.

Step 5: Per-user install (still no root)

Why touch /usr at all? Put everything under ~/.local: nothing is system-wide, nothing needs sudo, and your launcher still finds it.

mkdir -p ~/.local/bin \
         ~/.local/share/applications \
         ~/.local/share/icons/hicolor/512x512/apps \
         ~/.local/share/mime/packages

install -m755 /tmp/wf-test/usr/bin/Waveform14 ~/.local/bin/Waveform14
install -m644 /tmp/wf-test/usr/share/pixmaps/waveform14.png \
              ~/.local/share/icons/hicolor/512x512/apps/waveform14.png
install -m644 /tmp/wf-test/usr/share/mime/packages/waveform14.xml \
              ~/.local/share/mime/packages/waveform14.xml

~/.local/bin is already on PATH on most Arch setups. The icon goes into the hicolor theme so Icon=waveform14 resolves.

Rewrite the launcher

Vendor .desktop files point at /usr/bin/... with an absolute Exec, so they break under ~/.local. Copy and retarget:

[Desktop Entry]
Type=Application
Name=Waveform14
GenericName=Waveform
Comment=Audio and MIDI workstation
Exec=/home/baj/.local/bin/Waveform14 %u
Icon=waveform14
Terminal=false
Categories=AudioVideo;Audio;AudioVideoEditing;Sequencer;Recorder;Music;
MimeType=application/x-waveform14-project;application/x-waveform14-archive;
StartupWMClass=Waveform
Version=1.0

Then refresh the caches and validate:

update-desktop-database ~/.local/share/applications
update-mime-database ~/.local/share/mime
desktop-file-validate ~/.local/share/applications/waveform14.desktop

Vendor .desktop files are often not spec-compliant. Download Manager's shipped with Version=1.5.3 (invalid: Version is the spec version, always 1.0) and an unregistered Categories value (AudioEditing). Some launchers silently ignore such entries. desktop-file-validate caught both; I fixed them.

The whole thing, condensed

# inspect
ar t app.deb
ar p app.deb control.tar.* | tar -xOzf - ./control   # use the right -J/-z flag!

# extract + integrity check
mkdir -p /tmp/app && cd /tmp/app && ar x ~/Downloads/app.deb && tar -xzf data.tar.gz
ar p ~/Downloads/app.deb control.tar.gz | tar -xOzf - ./md5sums | md5sum -c

# trial run
setsid --fork nohup /tmp/app/usr/bin/App >/tmp/app.log 2>&1 </dev/null & disown

# per-user install
install -Dm755 /tmp/app/usr/bin/App ~/.local/bin/App
install -Dm644 /tmp/app/usr/share/pixmaps/app.png \
  ~/.local/share/icons/hicolor/512x512/apps/app.png
# …write ~/.local/share/applications/app.desktop with an absolute Exec…
update-desktop-database ~/.local/share/applications

# clean up
rm -rf /tmp/app /tmp/app.log

Uninstall is symmetric:

rm -f ~/.local/bin/App \
      ~/.local/share/applications/app.desktop \
      ~/.local/share/icons/hicolor/512x512/apps/app.png
update-desktop-database ~/.local/share/applications

Takeaways

  • A .deb is just ar + two tarballs. You don't need a converter, and you don't need the AUR. Extraction is the lowest-trust path for vendor binaries.
  • Verify before installing. The package ships its own md5sums; use it.
  • Read the real DT_NEEDED list, not just Debian's Depends. Distro library naming diverges (WebKitGTK 4.0 vs 4.1 is the classic landmine) and this also clears false positives.
  • Trial in /tmp first. A no-root, no-commitment run catches missing libs and dead RUNPATHs before anything touches your home.
  • ~/.local is enough. No sudo, clean uninstall, and it integrates with your launcher.
  • Watch for non-compliant vendor .desktop files. Validate them.
  • The AUR isn't the answer by default. For low-popularity, single-maintainer packages, hand-rolling the install is often both safer and simpler.

Maintainers: repackaging your .deb into a proper source-built Arch package would be appreciated. Until then, this is a solid workaround.