With a local package repository, I'm able to provide my APT instances with a set of software packages and configurations from a server which I control, allowing any client to install this software using just the normal apt install command (providing the repository is added to their /etc/apt/sources.list{,.d/}).

For my attempt at creating a local package repository, I followed this tutorial on bipmedia.com, which roughly consists of:

  1. Generate the .deb
  2. Store the .deb on an Apache2 web server
  3. Generate a Package.gz file

My Attempt

Generating the binary package file

To generate the .deb, the software files are required, a DEBIAN folder with metadata is generated and the following command compiles the code and assembles the package:

dpkg-deb --build [source code tree with DEBIAN directory]

Serve repository files with Apache2 server

I'm skipping this part as it's unrelated to the problem I'm seeking to solve with this question.

Generating a Packages.gz file (repository metadata)

With the an open shell instance whose working directory is the Apache server root folder containing the .deb file from above, I called:

dpkg-scanpackages debian /dev/null | gzip -9c >debian/Packages.gz


Calling apt update on the client machine, it complains with:

W: The repository 'http://example.com packages/ Release' does not have a Release file.

This necessary file is missing in my local repository. It seems to be a register of package checksums, but after searching on the Internet, my very limited understanding of the topic kept me from being able to find out how to generate it.

Note: My /etc/apt/sources.list file does have the following line:

deb http://example.com packages/


How do I generate the Release file for a local APT package repository?


2 Answers 2


There are a number of ways of going about this; I use apt-ftparchive.

  1. Create an aptftp.conf file in the root of your repository:

    APT::FTPArchive::Release {
      Origin "Your origin";
      Label "Your label";
      Suite "unstable";
      Codename "sid";
      Architectures "amd64 i386 source";
      Components "main";
      Description "Your description";

    with the appropriate values (change “Origin”, “Label”, “Description” at least, and adjust “Architectures” to match the binaries you host).

  2. Create a matching aptgenerate.conf file alongside:

    Dir::ArchiveDir ".";
    Dir::CacheDir ".";
    TreeDefault::Directory "pool/";
    TreeDefault::SrcDirectory "pool/";
    Default::Packages::Extensions ".deb";
    Default::Packages::Compress ". gzip bzip2";
    Default::Sources::Compress ". gzip bzip2";
    Default::Contents::Compress "gzip bzip2";
    BinDirectory "dists/unstable/main/binary-amd64" {
      Packages "dists/unstable/main/binary-amd64/Packages";
      Contents "dists/unstable/Contents-amd64";
      SrcPackages "dists/unstable/main/source/Sources";
    BinDirectory "dists/unstable/main/binary-i386" {
      Packages "dists/unstable/main/binary-i386/Packages";
      Contents "dists/unstable/Contents-i386";
      SrcPackages "dists/unstable/main/source/Sources";
    Tree "dists/unstable" {
      Sections "main"; # contrib non-free";
      Architectures "amd64 i386 source";

    (removing i386 if you don’t need that).

  3. In your repository, clear the database:

    rm -f packages-i386.db packages-amd64.db
  4. Generate the package catalogs:

    apt-ftparchive generate -c=aptftp.conf aptgenerate.conf
  5. Generate the Release file:

    apt-ftparchive release -c=aptftp.conf dists/unstable >dists/unstable/Release
  6. Sign it:

    gpg -u yourkeyid -bao dists/unstable/Release.gpg dists/unstable/Release
    gpg -u yourkeyid --clear-sign --output dists/unstable/InRelease dists/unstable/Release

    (with the appropriate id instead of yourkeyid).

Whenever you make a change to the repository, you need to run steps 3 to 6 again.

  • Can you use something like ` dpkg-scanpackages` rather than apt-ftparchive?
    – Toby
    Commented Jul 16, 2019 at 16:41
  • @Toby you can use dpkg-scanpackages to generate the package catalogs, but it won’t handle Release for you. The simple option nowadays is probably aptly; I should re-write this answer using that. Commented Jul 16, 2019 at 17:00
  • Awesome! Thanks. I should have said earlier, I was looking for a cross platform tool which apt-ftparchive seems like it's not. So aptly sounds good for me and I'll read up on creating the packages. I'm assuming the signing is separate anyway.
    – Toby
    Commented Jul 17, 2019 at 10:42
  • I have done exactly this, with focal instead of unstable everywhere, and amd64 only, and my custom deb file is in dists/focal/main/binary-amd64, but when I run step 4, may Packages file in dists/focal/main/binary-amd64 is empty, zero size. And if I try to install the binary on another computer, it does not find the package... Commented Aug 7, 2020 at 21:34
  • Valuable info, but this makes me glad the equivalent FreeBSD cmd is pkg repo. :) Minus the signing, but HTTPS kinda makes up for some of that.
    – Jim L.
    Commented Jul 2 at 8:13

I found this wonderful splendig tutorial on the internet: https://earthly.dev/blog/creating-and-hosting-your-own-deb-packages-and-apt-repo/

There this script is included which does the job:

echo '#!/bin/sh
set -e

do_hash() {
    echo "${HASH_NAME}:"
    for f in $(find -type f); do
        f=$(echo $f | cut -c3-) # remove ./ prefix
        if [ "$f" = "Release" ]; then
        echo " $(${HASH_CMD} ${f}  | cut -d" " -f1) $(wc -c $f)"

cat << EOF
Origin: Example Repository
Label: Example
Suite: stable
Codename: stable
Version: 1.0
Architectures: amd64 arm64 arm7
Components: main
Description: An example software repository
Date: $(date -Ru)
do_hash "MD5Sum" "md5sum"
do_hash "SHA1" "sha1sum"
do_hash "SHA256" "sha256sum"
' > ~/example/generate-release.sh && chmod +x ~/example/generate-release.sh

Adjust to your needs.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .