Build a Debian Sources Index with dpkg-scansources
You will turn a directory containing Debian source description files into a Sources index that an archive or local package repository can publish. The examples use dpkg-scansources from dpkg-dev 1.22.6ubuntu6.6, which reports dpkg version 1.22.6. Allow about fifteen minutes if your .dsc files and override data are ready.
The route
Jump straight to the step you need, or tick off Done means at the end.
The command reads .dsc files and writes the index to standard output. It does not need root, and it does not modify the scanned directory. You need a shell, readable source-package files, and enough space for the generated index and any compressed copy.
1. Confirm the installed command
Check the package and executable before building an index. This is a read-only checkpoint:
$ dpkg-query -W -f='${Package} ${Version}\n' dpkg-dev
dpkg-dev 1.22.6ubuntu6.6
$ command -v dpkg-scansources
/usr/bin/dpkg-scansources
$ dpkg-scansources --version
Debian dpkg-scansources version 1.22.6.
The synopsis is dpkg-scansources [options] binary-dir [override-file [path-prefix]] > Sources. The name binary-dir is easy to misread: this is the directory tree in which the scanner searches for source .dsc files. It does not consume .deb files.
2. Scan a source directory into Sources
Change to the root of the archive you intend to publish, then set a relative path to its source tree. Use a path that is readable by your normal account:
$ cd /srv/debian-archive
$ SOURCE_TREE='pool'
$ dpkg-scansources "$SOURCE_TREE" > Sources
The output is a set of control-style stanzas. Each stanza describes a source package and includes its .dsc file, checksums, and the other files listed by that .dsc. The command normally sorts stanzas by source package name. Inspect the result before publishing it:
$ sed -n '1,80p' Sources
Format: 3.0 (quilt)
Package: example
Binary: example
Architecture: all
Version: 1.0-1
...
$ test -s Sources && echo 'Sources is non-empty'
Sources is non-empty
If the file is empty, first check that the tree really contains readable files whose names end in .dsc. A successful command with no matching source files is still not a useful repository index.
3. Add the archive path prefix
The optional path-prefix is prepended literally to each generated Directory: field. Use a trailing slash when you want it separated from the existing path. For example, pass an override file positionally and add an archive-level prefix:
$ dpkg-scansources "$SOURCE_TREE" /dev/null 'archive/' > Sources
$ awk '/^Directory:/{print}' Sources | head
Directory: archive/pool/main/e/example
/dev/null is an empty override file for this example. Be deliberate about the prefix: it becomes part of the paths APT uses to find source files, so a filesystem staging directory such as /tmp/build/pool should not accidentally appear in a public index. A relative scan path also makes the result easier to reason about than an absolute temporary path.
Checkpoint: compare one Directory: value with the path that will actually be served by your web server or local repository. If they do not join to the real location of the files, fix the prefix and regenerate Sources.
4. Apply a binary override file when needed
An override file can add archive policy fields such as priority and section, and can replace maintainer information. Its ordinary format is whitespace-separated fields: package, priority, section, and optional maintainer information. For a small example, create this file in your repository's configuration area:
$ cat repository-override
example optional admin
$ dpkg-scansources "$SOURCE_TREE" repository-override 'archive/' > Sources
In the generated stanza, the matching binary package can contribute Priority: optional and Section: admin. The override is indexed by binary package, not directly by source package. When one .dsc produces several binaries, this dpkg implementation uses the highest priority it finds for the source stanza, and uses the first listed binary for the maintainer override. Treat that rule as an implementation detail, especially if your source package produces multiple binaries.
Override files may be compressed. Read the deb-override(5) manual when you need maintainer substitution syntax or the exact format rather than guessing. Do not put credentials or private contact data into an index that will be publicly served.
5. Separate source section overrides
The -s or --source-override option selects a two-field source override file. The first field is the source package name and the second is its section:
$ cat source-override
example admin
$ dpkg-scansources --source-override source-override "$SOURCE_TREE" repository-override 'archive/' > Sources
Blank lines and comments are ignored. If a source package appears in both the binary override and this file, the source override wins for the section. If you provide a normal override file and omit --source-override, dpkg-scansources looks for that file with .src appended as the default source override name. Make this explicit in scripts when reproducibility matters.
6. Choose sorting and supplementary overrides
Keep the default sorting unless another tool requires input order. --no-sort leaves stanzas unsorted, which can make output track directory traversal rather than package name:
$ dpkg-scansources --no-sort "$SOURCE_TREE" > Sources.unsorted
$ cmp -s Sources Sources.unsorted || echo 'ordering or content differs'
The -e or --extra-override option reads supplementary overrides in the format documented by deb-extra-override(5). Use it only when your archive policy requires that additional input. Keep all override files under review, because they change metadata without changing the source package's own .dsc.
7. Prepare the index for APT
Keep the uncompressed file while checking it, then create the compressed index next to it:
$ gzip -c Sources > Sources.gz
$ gzip -t Sources.gz
$ ls -l Sources Sources.gz
APT generally expects Sources.gz for a served repository and ignores an uncompressed Sources except for local file:// access. The compression step is separate from dpkg-scansources, so a successful scan alone does not prove that an APT client can fetch the index.
Do not overwrite a known-good index in place during a live repository update. Generate into a temporary name, validate it, and then use your repository's normal atomic deployment procedure. If you only need to undo this guide's example, remove the newly generated Sources, Sources.gz, or test output after confirming that those files are not shared by another repository process. The source tree and its .dsc files remain unchanged.
Common failure checks
- No packages appear: use
find "$SOURCE_TREE" -type f -name '*.dsc' -printto verify the search tree and permissions. The command is looking for source descriptions, not package binaries. - APT cannot fetch a source file: inspect
Directory:and each filename inSources. A wrongpath-prefixusually points the client at a path that is valid on the build host but not at the archive root. - Metadata is unexpected: rerun without overrides, then add the ordinary, extra, and source override files one at a time. This isolates policy input from the contents of the
.dsc. - The output changes between runs: check whether a script is using
--no-sort, changing the scanned directory, or modifying an input.dsc. The default sorted output is easier to review. - A command fails with permission denied: fix ownership or read permissions on the repository tree through your normal administration process. Do not run the scanner as root merely to hide a repository permission problem.
Done means
dpkg-scansources --versionidentified the installed dpkg-dev tool.Sourcescontains stanzas for the intended readable.dscfiles.- Every
Directory:field points into the archive layout that will actually be served. - Override files are reviewed, explicit, and kept separate from source-package data.
Sources.gzpassesgzip -tbefore it is published for APT.