Skip to content

Linux Native Packages (.deb / apt & .rpm / dnf-yum)

One-liner: Ship the bundle as distro-native .deb and .rpm packages served from a GPG-signed apt/yum repository, so users install and update with their system package manager.

Category OS-native package manager (first-class)
Platforms Debian/Ubuntu & derivatives (apt/dpkg); Fedora/RHEL/CentOS/Rocky/Alma & openSUSE (dnf/yum/zypper)
Prerequisites A GPG signing key; a hosted repo (HTTP/S); build tooling (dpkg-deb/debhelper, rpmbuild); control/spec metadata
Handles acquire ✓ / verify ✓ (GPG repo+pkg signing) / place ✓ / configure ✓ (maintainer scripts) / start ✓ (systemd units) / update ✓ / uninstall ✓
Maturity fit Growth → Mature (the standard for Linux server distribution)
Trust model Repo and packages signed with your GPG key; users import your public key once, then the package manager verifies every download.

How it works

A native package is an archive plus metadata. For Debian the metadata is a control file (name, version, Depends:, architecture) and optional maintainer scripts (preinst/postinst/prerm/postrm) that run at install/remove time — ideal for creating users, installing systemd units, or pulling a container image. dpkg-deb --build produces the .deb. For RPM the equivalent is a .spec file with Requires:, %install, and scriptlets (%post, %preun); rpmbuild -bb produces the .rpm.

Single files are not enough for smooth updates — you publish a repository. An apt repo is a directory tree with a Packages index and a top-level Release file that is GPG-signed (InRelease/Release.gpg); tools like aptly or reprepro build it. A yum/dnf repo has repodata/ generated by createrepo_c, a .repo descriptor, and packages signed with rpm --addsign. Users add your repo descriptor, import your public key, and from then on apt/dnf verify signatures on every install and upgrade.

For the bundle: the Python+Rust json-tables CLI compiles to a native binary and drops in perfectly. The pip-based MCP server is the awkward part — you either vendor its wheels and dependencies into the package (recommended; avoids polluting system Python and PEP 668 "externally managed" errors) or declare python3/pip deps. The Exasol Personal/Nano database is containerized: the package realistically installs a launcher, a systemd unit, and a postinst step that docker pulls a digest-pinned image and wires up config. docker/podman is declared as a dependency but the engine remains a runtime requirement the package cannot itself provide as a daemon.

Example

# ---------- Debian/Ubuntu (.deb) ----------
# 1) Package layout
#   exa-bundle/DEBIAN/control      (Package, Version, Depends: docker.io, ...)
#   exa-bundle/DEBIAN/postinst     (docker pull <image@sha256:...>; systemctl enable exa-bundle)
#   exa-bundle/usr/bin/json-tables, /usr/bin/exa-bundle, /lib/systemd/system/exa-bundle.service
dpkg-deb --root-owner-group --build exa-bundle exa-bundle_1.2.0_amd64.deb

# 2) Sign & publish a repo (aptly example)
gpg --full-generate-key                       # one-time signing key
aptly repo create -distribution=stable exa
aptly repo add exa exa-bundle_1.2.0_amd64.deb
aptly publish repo -gpg-key="<KEYID>" exa     # signs InRelease/Release.gpg

# 3) Consumer side
curl -fsSL https://repo.example.com/key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/exa.gpg
echo "deb [signed-by=/usr/share/keyrings/exa.gpg] https://repo.example.com stable main" \
  | sudo tee /etc/apt/sources.list.d/exa.list
sudo apt update && sudo apt install exa-bundle

# ---------- Fedora/RHEL (.rpm) ----------
# 1) exa-bundle.spec  -> Requires: podman ; %post: podman pull <image@sha256:...>
rpmbuild -bb exa-bundle.spec                  # -> ~/rpmbuild/RPMS/x86_64/exa-bundle-1.2.0.rpm

# 2) Sign packages + build a signed repo
rpm --define "_gpg_name <KEYID>" --addsign exa-bundle-1.2.0-1.x86_64.rpm
createrepo_c /var/www/repo/                    # generates repodata/
gpg --detach-sign --armor /var/www/repo/repodata/repomd.xml   # sign repo metadata

# 3) Consumer side
sudo rpm --import https://repo.example.com/key.gpg
sudo tee /etc/yum.repos.d/exa.repo <<'EOF'
[exa]
name=Exasol Bundle
baseurl=https://repo.example.com/rpm/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://repo.example.com/key.gpg
EOF
sudo dnf install exa-bundle        # or: sudo yum install exa-bundle

Pros

  • Uses the OS-native, default manager — no extra tool to install; familiar to every sysadmin.
  • Strong, layered integrity: both the repo metadata and individual packages are GPG-signed and verified automatically.
  • First-class lifecycle: declared Depends/Requires, maintainer scripts for config/users, systemd units for start/stop, clean remove/purge.
  • Seamless apt upgrade / dnf update rolls forward with the rest of the system.
  • The compiled json-tables binary fits the model perfectly.

Cons

  • Two separate toolchains and package formats to build, test, and host (deb and rpm), often per-architecture and per-distro-version.
  • You must run and maintain a signed repository (key management, index generation, hosting/CDN).
  • Bundling pip dependencies cleanly is fiddly (PEP 668 externally-managed environments; vendoring vs. system Python).
  • The multi-container DB is not "installed" by the package — it still needs Docker/Podman running underneath; the package only orchestrates a pull + unit.
  • Repo and key compromise is high-impact: a leaked signing key undermines every consumer.

Security considerations

GPG signing is the trust backbone: sign both the repository metadata (InRelease/repomd.xml) and the packages themselves, and enable gpgcheck=1/repo_gpgcheck=1. Distribute the public key over HTTPS and document its fingerprint out-of-band. Protect the private signing key (HSM or an offline/CI-scoped signer). In maintainer scripts, avoid unbounded network actions; if you docker pull, pin the image by digest (@sha256:...), not a mutable tag, and validate inputs in postinst. See Security.

Approval & maintenance burden

  • Your own repo: no third-party approval, but high upkeep — build deb+rpm per arch/distro, regenerate signed indexes, run hosting, rotate keys.
  • Official distro repos (Debian main, Fedora, EPEL): a real review/sponsorship process (packaging guidelines, license review, no bundled libs) and ongoing maintainer duties; slow but yields maximum trust and reach.

Best for / Avoid when

Best for: Linux servers and headless deployments; teams that need systemd integration, dependency resolution, and signed updates; anything destined for fleet/config-management. Avoid when: your audience is macOS/Windows; you can't commit to maintaining signed repos across distros; or the product is purely a container stack where a plain Compose/Docker approach is simpler than wrapping it in packages.

Real-world examples

  • Docker, HashiCorp, Microsoft, Google Chrome, and NodeSource all ship signed apt/yum repos with a "add key + add repo + install" flow.
  • Grafana, InfluxData, and PostgreSQL (PGDG) publish parallel .deb and .rpm repositories with the exact pattern above.

See also