Home / Alt manpages / dpkg-scanpackages(1)

  • dpkg-scanpackages(1)
  • User command
  • linux

Build a Debian Packages Index with dpkg-scanpackages

You will finish with a Packages index that describes the Debian binary packages in a local archive directory, plus a compressed copy suitable for most APT clients. The examples use dpkg-scanpackages 1.22.6 from dpkg-dev 1.22.6ubuntu6.6, as installed on the machine used for this guide.

Allow about fifteen minutes. You need a shell, dpkg-dev, a directory containing valid .deb files, and write access to the directory where the index will be saved. The scan itself does not need root. Writing into a system-owned repository or installing packages are separate operations and may need elevated privileges.

1. Check the installed command

Start with read-only checks. They confirm that you are using the expected executable and show the syntax provided by this installation:

$ command -v dpkg-scanpackages
/usr/bin/dpkg-scanpackages
$ dpkg-scanpackages --version
Debian dpkg-scanpackages version 1.22.6.
$ dpkg-query -W -f='${Package} ${Version}\n' dpkg-dev
dpkg-dev 1.22.6ubuntu6.6

The command takes a binary package tree, an optional override file, and an optional path prefix. Its normal output is sent to standard output, so the usual pattern is a shell redirection into a file:

$ dpkg-scanpackages BINARY_PATH > Packages

Checkpoint: do not continue until command -v finds the command and its version output is plausible for the host you are maintaining.

2. Put packages under a stable archive root

Choose a directory layout before scanning. For a small local archive, this is enough:

$ mkdir -p "$HOME/local-debian/pool"
$ cp /path/to/your-package.deb "$HOME/local-debian/pool/"
$ find "$HOME/local-debian" -type f -name '*.deb' -print
/home/you/local-debian/pool/your-package.deb

Replace both placeholders with real paths. The command searches the binary path as a tree, so the directory can contain subdirectories. It normally scans files ending in .deb. A package file must be a valid Debian binary package; a renamed archive is not enough.

Run the scanner from the archive root and pass the package directory as a relative path:

$ cd "$HOME/local-debian"
$ dpkg-scanpackages pool > Packages

This relative path affects the Filename fields in the generated index. Scanning an absolute directory can produce absolute-looking filenames, which are a poor fit for a repository whose files are served or copied from a separate root. Read the result before wiring it into APT:

$ sed -n '1,24p' Packages
Package: your-package
Version: 1.0
Architecture: all
Filename: pool/your-package_1.0_all.deb
Size: 1234
MD5sum: ...
SHA1: ...
SHA256: ...

The exact fields and values depend on the package. The filename should point from the archive root to the package, and the size and hashes should describe the file that is actually present.

3. Choose the generated hashes deliberately

By default, the installed command generates all currently supported hashes. You can restrict that list with -h or --hash. For a compact modern index, this example requests only SHA-256:

$ dpkg-scanpackages --hash sha256 pool > Packages
$ awk '/^(MD5sum|SHA1|SHA256):/ {print}' Packages
SHA256: ...

The supported values in this version are md5, sha1, and sha256. Pass a comma-separated list when a consumer needs more than one:

$ dpkg-scanpackages --hash sha1,sha256 pool > Packages

Do not confuse a hash selection with repository signing. These fields help a client verify the downloaded package contents; they do not authenticate who controls the repository. A repository exposed to machines you do not fully control needs an appropriate APT signing and key-distribution design as well.

4. Understand duplicate versions

If the tree contains more than one version of a package, the default output includes only the newest version. If matching versions differ only by architecture, the first one found is used. That default is often useful for a simple repository, but it can hide an old package that you expected to see.

Inspect the package names and versions before scanning when the directory is assembled automatically:

$ dpkg-deb -f pool/*.deb Package Version Architecture
Package: your-package
Version: 1.0
Architecture: all

Use --multiversion when the index must contain every found version:

$ dpkg-scanpackages --multiversion pool > Packages
$ awk '/^(Package|Version):/ {print}' Packages

Checkpoint: verify that the number and versions of entries match your policy. Do not add --multiversion just because it sounds safer. Multiple versions can make repository selection less obvious for clients and operators.

5. Add an override file only when you need one

The optional override file supplies distribution metadata such as a package's section and priority. Its format is defined by deb-override(5); it is not the same as a Debian control file. Use it when the repository's classification needs to differ from the package metadata:

$ dpkg-scanpackages pool path/to/override-file > Packages

The override file may be compressed on supported dpkg versions, including this one. If you do not have a deliberate override policy, leave this argument out. The scanner warns about packages missing from an override file and about maintainer substitutions that do not take effect, so read warnings rather than treating the final file as proof that every metadata rule was applied.

The --extra-override FILE option reads supplementary overrides in the format documented by deb-extra-override(5). It is another metadata input, not a replacement for the ordinary override-file position.

6. Check warnings and refresh the index safely

Capture diagnostics separately while writing the new index to a temporary file in the same repository directory:

$ tmp_packages="$(mktemp Packages.XXXXXX)"
$ if dpkg-scanpackages --hash sha256 pool > "$tmp_packages"; then
>     mv "$tmp_packages" Packages
> else
>     status=$?
>     rm -f "$tmp_packages"
>     exit "$status"
> fi
dpkg-scanpackages: info: Wrote 1 entries to output Packages file.

The informational line is normally written to standard error, while the index is written to standard output. The entry count is useful, but it is not a substitute for checking the paths and package versions. If the scan fails, the temporary file is removed and the previous Packages file remains in place. The mv replaces the old index only after a successful scan, so this workflow has a simple recovery path: rerun the scan, or restore the previous file from your repository backup if a successful scan used the wrong package tree.

Warnings can identify wrong subdirectories, duplicate packages, an existing Filename control field, missing override entries, or ineffective maintainer substitutions. Fix the package layout or metadata source and regenerate. Do not silence warnings by redirecting all diagnostics away during a release build.

7. Compress the index for APT

APT generally ignores an uncompressed Packages file for remote repositories. The manpage permits uncompressed access for local file:// sources, but a compressed index is the safer default for a served repository:

$ gzip -c Packages > Packages.gz
$ xz -c Packages > Packages.xz
$ ls -l Packages Packages.gz Packages.xz

Keep the uncompressed file while checking the result, and publish the compressed file or files alongside it according to the clients you support. These commands overwrite the named compressed outputs, so make sure the current directory is the intended repository directory before running them. If you generated a bad compressed file, rerun the command from the known-good Packages; no package installation is involved.

Done means

  • dpkg-scanpackages --version and the dpkg-dev package version were recorded.
  • The scan used a binary path relative to the archive root, producing usable Filename values.
  • The entry count, package versions, architectures and warnings were checked.
  • Hash selection matches the clients and repository policy.
  • The new index replaced the old one only after a successful scan.
  • A compressed index is available when clients use a non-local APT source.