Table of Contents
- Quick start
- Required prerequisite information
- Install necessary tools
- Create directory structure and config files
repreproto create the repository
- Notes on debian repository security
- Consistent Debian repositories (fix Hash sum mismatch)
- Secure Debian repository access
- Accessing the Debian repository
This blog post will explain the steps needed for creating a Debian APT repository using command line tools.
The fastest, easiest, and most secure way to create a Debian repository is to sign up at packagecloud.io. You will take advantage of numerous features like SSL and consistent APT repositories without needing to build any of these features yourself.
If you are determined to do it yourself with command line tools, follow the guide below. Note that, unfortuantely, you cannot generate consistent APT repositories with
Required prerequisite information
It’s important to understand that APT repositories as generated by
reprepro are essentially a carefully constructed series of directories. The exact directory path (and thus the URL) that is generated is determined largely by a few important parts: the codename, the component, and the architecture.
For example, if your repository is setup with the codename “trusty”, the component “main”, and the “amd64” architecture, a series of directories will be created with these names for storing your repository metadata.
We’ll see where these are configured shortly.
Install necessary tools
Start by installing the command line tool
reprepro which will be used to generate the repository metadata:
Create directory structure and config files
First, create a top level directory for your debian repository:
Next, create a directory called
conf and a file in that directory called
distributions file with your favorite editor. You’ll need the following configuration:
What do these
reprepro configuration options do? Check the man page (
man reprepro) for a detailed explanation. A short description of the minimum options provided above:
Origin: This field is copied directly into the generated metadata. This usually an identifier explaining where this repository came from. A URL is a good bet for this field. Folks using APT pinning may attempt to setup their pinning using a combination of this field and others, so choose wisely.
Label: This field is copied directly into the generated metadata, as well. Folks using APT pinning may attempt to setup their pinning using a combination of this field and others, so choose wisely.
Codename: This field is used to determine the directory structure of where the generated metadata will live. Usually, you’ll want to choose an Ubuntu or Debian codename for this, like: “trusty” or “xenial” or “jessie”. When a user configures a repository for installation on their system, they will need to specify their codename in their configuration. Technically, you can choose any value for this, if you like.
Architectures: The architectures to update. Most folks will want at least
sourceis useful if you plan on having source packages, but is not mandatory.
Components: The names of the components that packages can be imported into. You can think of components as a way of segementing packages in a repository. You can use any identifier you want for this. You’ll need to let the user know which component they should use so the user can correctly configure their apt client. In our example, we chose a commonly used component name:
Description: This field is optional, but useful for end users. This field will copied directly to the generated metadata.
SignWith: This field can be either “yes”, “default”, or have the GPG key ID of a GPG key that should be used to sign the repository metadata. If “yes” or “default” are specified,
repreprowill use the default GPG key available when signing repository metadata. You can get your GPG key id by running
SignWith is one important component of generating a secure APT repository. Please continue reading through the Notes on security section below to understand all of the important requirements for a secure debian repository.
reprepro to create the repository
Once you have the directories and configuration file setup, you can now import a package to generate the repository.
In this example, we’re going to import a package named
jake_1.0-7_amd64.deb to the repository for the
Done! The repository has been generated. You can now add more packages if needed and start using your repository. Before showing how to use the repository, let’s take a look at some important security notes.
Notes on debian repository security
Debian repositories are tricky to operate in a secure manner. There are two major points that should be mentioned here:
If you are distributing your repository over the internet, you must do so via SSL. Debian repositories (even those with GPG signatures) are vulnerable to replay attacks if not served over SSL. In addition, there is a remote code execution vulnerability when verifying GPG signatures over HTTP. Always use SSL when distributing APT repositories over the internet.
GPG signatures are a confusing part of creating and configuring Debian repositories. There are two types of GPG signatures: signatures on the Debian packages themselves and signatures on the repository metadata. Signatures on Debian packages are not used or verified by default on Ubuntu systems. This means that if you sign your package with
debsign, users installing your package will not be verifying the signatures. Signatures on the repository metadata, however, are verified automatically by clients. Using the
SignWithoption described above is the simplest way to generate GPG signatures for your repository metadata.
Read our detailed blog post about how to sign and verify debian packages and APT repositories if you’d like to learn more about GPG and APT.
Consistent Debian repositories (fix Hash sum mismatch)
Unfortunately, the APT metadata format is inherently racy. This means that if you run
reprepro to regenerate your repository while a user is running
apt-get update against your reopsitory, the user can get an error and end up with stale or inconsistent metadata.
This is the primary cause of the confusing Hash sum mismatch error many APT users run into in the wild.
At the time of this writing, the
reprepro commandline tool does not support generating APT metadata that allows clients to avoid this issue. The easiest way to avoid this issue is to create a free debian repository on packagecloud.
Secure Debian repository access
In order to get access to secure debian repositories distributed over SSL with GPG signed metadata, the end user will need to a few simple tasks:
sudo apt-get install apt-transport-https. This will install a helper program that
apt-getwill use to download repository metadata over SSL.
- Import the repository signing key. If you provide the GPG public key for your repository over the internet, the user can run
wget -qO - https://your-url-here.com/archive.key | sudo apt-key add -to add the public key to the APT keyring.
Accessing the Debian repository
Once the user has installed
apt-transport-https and imported the public GPG key, they will need to construct a simple repository configuration file in
/etc/apt/sources.list.d/. It is required that this filename ends in
In order to construct the file correctly, the user will need to know the component and codename of the repository to add:
The first line of the sample configuration above adds a binary repository. The second line starts with
deb-src because it adds the repository so that source packages can be downloaded. If you didn’t add “source” to the
Architectures option, clients do not need to specify a
Once the configuration file is setup, the client must run
apt-get update and then they can install packages from your repository!
You can use the
reprepro command line tool to create and update debian repositories. It’s a useful tool and has a wide range of options explained in the man page. It is only one piece of the software distribution puzzle. Users still need to deal with SSL, backups, access control. Clients can sometimes receive the dreaded “hash sum mismatch” error if the repository is updated on the server while the client is refreshing its metadata cache on the client side.