Creating your own Signed APT-Repository

Everytime I have a lot of install-steps for things, I create a debian package. I love it just to say apt-get install or apt-get remove and all necessary steps are done. Also the update functions of apt-get or aptitude are pretty nice. However, some months ago, I thought about the posibility to release some packages publicly. I decided that it was high time to organise the repository and sign all my packages plus the repository itself. Everybody who has tried this will recognize that there is a large amount of conflicting information out there as to how exactly this can be achieved. I just had some letters with notes on it, but now I think its time to write it down in my blog.


First we need to generate a GPG key to sign our repository and all of our packages with. Maybe you’ve already done this, so you can skip the next section.

Create a GPG Key

  1. run gpg --gen-key
  2. select option (1)to generate an RSA Key
  3. Choose your keysize. The default value of 2048 should be a good size.
  4. If you doesn’t matter about the key, you can choose option 0. So your key does not expire. I choose 4 years.
  5. Enter your name and email address when prompted
  6. Enter a passphrase if you want.

We now have a GPG key which we use to sign everything. Next we have to produce a ASCII formatted public key file which we can distribute to people so they are able to tell apt to trust my repository.

ASCII Formatted Public Key File

By default, the gpg export function produces a binary formatted output of our public key. This is not very handy if you’re planning to distribute your key via web. So we use the option --armor to produce an ASCII formatted version.

We also insert the email address of the key we want to export and a output filename. You can/have to substitute the email address and filename in the following command.

gpg --armor --export --output

Save the keyfile somewhere, we make it available over the web for people to add to their apt keychains later.

Signing deb-packages

I assume that you already know how to create deb-packages. If not, you can have a look at the debian wiki.

A pretty cool feature is that if you’ve already generated a GPG key (see above), your packages will be automatically signed as long as the name and email address in your package’s changelog file and of the GPG key you created are the same. So, a simple run of dpkg-buildpackage will now give you signed packages.

If you want to resign an existing debian package and you already have a GPG key set up, you can use a tool called dpkg-sig.

Install it:

apt-get install dpkg-sig

and run the following command to sign the package:

dpkg-sig --sign builder myPackage_1.0.1_amd64.deb

The “builder” name is a debian convention, indicating that the builder of the package signed it.

Create a signed APT-Repository

We’ve got now a bunch of signed packages and need some way to make them available to the world. Preferably one which doesn’t throw up authentication warnings every time they try to install from your repository. Therefore you need a signed repository.

First step is to create a base directory where the packages can live in. I decided to locate it at /var/www/debianPool. Inside that directory you have to create a folder called conf.
Inside this folder, create a text file called distributions and insert something like the following text:

    Label: apt repository
    Codename: squeezy
    Architectures: amd64 source
    Components: main
    Description: Oberberger debian package repo
    SignWith: yes
    Pull: squeeze

The main things are self-explaining, for example if you are not packaging for debian squeezy, you have to replace all occurrences of squeezy with wheezy.
I’m only creating 64-bit packages. If you’re packaging for i386 or other architectures, you have to add/replace them.

The really important line is SignWith: yes. This line states that we want to sign the repository with our GPG key.

Now the descriptions file is ready and we now want to add our packages to the repository. The easiest way ist to use the tool reprepro. You can install it with the following command:

apt-get install reprepro

This tool will create all the structure it needs inside the repository automatically, so you don’t have to worry about it. You can run the following command to add a package to your repository:

reprepro --ask-passphrase -Vb . includedeb squeezy /path/to/myPackage_1.0.1_amd64.deb

The --ask-passphrase tells the command to prompt you for your GPG Key passphrase. -Vb . includedeb squeezy tells the command to be verbose and set the base directory for the command as the current directory. The includedeb-part tells that we are passing a deb file and add it to the squeezy repository. The last part is the absolute path to the deb-file.

Make the Repository available to the World

The first step here is to make your repository available over the web. Therefore you have to create a apache2-vhost file.
I use a file called pool and insert something like the following text:


        DocumentRoot /var/www/debianPool
            AllowOverride None
            Options ExecCGI -MultiViews
            Order allow,deny
            allow from all


After you created this file in /etc/apache2/sites-available/ you have to enable the site: sudo a2ensite pool

The second part is making your public GPG key available so the world can mark the repository as trusted. Therefore you copy the public GPG key we created above in the root of your repository (cp /var/www/debianPool). ATTENTION: Make sure you only store the public part of your key (The gpg --armor --export command).

The command for people to download your public key and import it into their apt-keychain in one step is the following:

wget -O - | sudo apt-key add -

If your users/the worlds people have run the above command, they can add your repo to their /etc/apt/sources.list by adding the following line:

deb squeeze main

After that they just run apt-get update and they are ready to use your repository without any authentication warning.


You have to change all URLs and distributions above as appropriated.

The sources (pool and distribution-file) are available at Github

comments powered by Disqus