Setting up a debian package archive with aptly

This article describes how to set up a debian archive with aptly on a debian 9 “stretch” computer, served by an nginx web server.

Initial setup

  1. Add a DNS alias for your virtual nginx web site (outside of the scope of this blog post). The examples below assume that is the DNS alias
  2. Install the required software, logged in as root, give the following command
    apt-get install gnupg pinentry-curses nginx aptly
  3. Logged in as your regular user, do the following:
    1. Create a gpg keyNote! It is a good idea to do the key generation when logged into a debian desktop and move the mouse about during generation, to get good random values for the key generation.Giving the following command at the command line
      gpg --full-generate-key
      1. At the prompt for key type, just press ENTER to select the default (RSA and RSA)
      2. At the prompt for key size, type “4096” (without the quotes) and press ENTER
      3. At the prompt for how long the key should be valid, type “0” without the quotes and press ENTER
      4. At the prompt for “Real name”, type your real name and press ENTER
      5. At the prompt for “Email address”, type your email address and press ENTER
      6. At the prompt for “Comment”, type the host name of your archive web server, e.g. “” and press ENTER
      7. At the prompt “Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?”, type “O” (without the quotes) and press ENTER
      8. At the prompt for a passphrase, give a passphrase you will remember. You will be asked for this passphrase every time every time the repository is published
    2. Export the public key of the gpg key pair in a form that the web server can use
      1. First list the keys to find the id of the key
        steinar@lorenzo:~$ gpg --list-keys
        pub   rsa4096 2017-12-27 [SC]
        uid           [ultimate] Steinar Bang ( <>
        sub   rsa4096 2017-12-27 [E]
      2. Then use the id of the key to export the public key of the gpg key pair in a form that the web server can return
        gpg --output apt_pub.gpg --armor --export 6B7638490707CCE365DF5415D2BA778731DC1EAC
      3. Publish the key with the default GPG keyserver
        gpg --send-keys 6B7638490707CCE365DF5415D2BA778731DC1EAC
    3. Create a local repository “stable”
      aptly repo create -distribution="stable" stable
    4. Configure an architecture in the archive: open the ~/.aptly.conf file in a text editor, and change the line
      "architectures": [],


      "architectures": ["amd64"],

      Note! Without a concrete architecture in place, aptly refuses to publish. So add an architecture here, even you are going to publish packages with architecture “all” (e.g. java, python, shell script). In the example I’m using “amd64” which, despite its name, is appropriate for modern 64 bit intel chips (i5 or i7 of various generations).

    5. Import a package into “stable” (the example uses the package built in Installing apache karaf on debian stretch)
      aptly repo add stable git/karaf-deb-packaging/karaf_4.1.4-1_all.deb
    6. Publish the archive (switch the gpg-key with the id of your actual repository key):
      aptly publish repo --gpg-key="6B7638490707CCE365DF5415D2BA778731DC1EAC" stable

      Note! If you get a time out error instead of a prompt for the GPG key passphrase, and you’re logged in remotely to the server, the reason could be that gpg tries to open a GUI pinentry tool. Switch to explictly using a curses-based pinentry and try the “aptly publish” command again. Do the command:

      update-alternatives --config pinentry

      and select “pinentry-curses” in “Manual mode”

  4. Log in as root and do the following
    1. Create a root directory for a new web server and copy in the public key used to sign the published achive
      mkdir -p /var/www-apt
      cp /home/steinar/apt_pub.gpg /var/www-apt/
    2. In a text editor, create the file /etc/nginx/sites-available/apt with the following content
      server {
      	listen 80;
      	listen [::]:80;
      	root /var/www-apt;
      	allow all;
      	autoindex on;
      	# Full access for everybody for the stable debian repo
      	location /public {
      		root /home/steinar/.aptly;
      		allow all;
      	# Allow access to the top level to be able to download the GPG key
      	location / {
      		allow all;

      Note! I actually started out with also serving HTTPS and signing with letsencrypt, but as it turns out APT doesn’t support HTTPS out of the box, so there was no point in including it in this HOWTO

    3. Enable the site by creating a symlink and restarting nginx
      cd /etc/nginx/sites-enabled
      ln -s /etc/nginx/sites-available/apt .
      systemctl restart nginx

Your APT artchive is now up and running.

Use the new APT archive

To start using the APT archive, do the following on a debian computer:

  1. Log in as root
  2. Add the archive key
    wget -O - | apt-key add -
  3. Add the archive by adding the following lines to /etc/apt/sources.list
    # My own apt archive
    deb stable main
  4. Update APT to get the information from the new archive
    apt-get update
  5. Install a package from the archive
    apt-get install karaf

Future additions and updates of existing packages can be done as your regular user, with no need to log in as root during the process.

Publish a new version of a package

To update an existing package:

  1. Build a new version of the package
  2. Add the new version of package to the package archive
    aptly repo add stable git/karaf-deb-packaging/karaf_4.1.5-1_all.deb
  3. Update the publish the package archive (i.e. the package archive served by nginx)
    aptly publish update --gpg-key="6B7638490707CCE365DF5415D2BA778731DC1EAC" stable
  4. Do “apt-get update” on the computers using the archive
  5. Do “apt-get dist-upgrade” on the computers using the archive, and the package should be upgraded

Remove old versions of a package

To delete old versions of a package:

  1. Do a query to verify that the expression matches only the packages you want to delete
    aptly repo search stable 'karaf (<=4.1.4-4)'
  2. Remove all packages matching the query
    aptly repo remove stable 'karaf (<=4.1.4-4)'
  3. Remove old versions of the database (this is where the disk usage of the repository is reduced)
    aptly db cleanup


2 thoughts on “Setting up a debian package archive with aptly”

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s