APK internals

From Adélie Linux

This page describes the internal odds and ends of the APK packaging system as used by Adélie Linux, Alpine Linux, and other distributions.


APK is the package manager used by Adélie Linux, developed originally by Alpine Linux who remain its primary maintainers. This document was created to document the internal workings of APK for development of apkkit and other projects, but may be useful to other development activities or for debugging issues. Note that this information could become inaccurate very quickly as it relies on implementation details that are not documented publicly. This document was written on 29 May 2017, against the current git version of APK (2.7.1+9325eb72).

Secrets of the build system

APK's Makefile supports a number of undocumented options.

Option Values
LUAAPK Empty: not build Lua module
Any value: Build Lua module
SHARED_LIBAPK Empty: Do not build libapk.so
Any value: libapk.so
TEST y: Build test applet
Any other value: Do not build test applet

APK files

An APK file contains an internal signature, a manifest that describes the package, optional executables to run after certain package operations, an optional trigger to run when files are modified in specified directories, and then the package's contents.

Nominally, the APK is created in two parts: control.tar, which contains all of the package's metadata; and data.tar, which contains the package's data. The data.tar file is signed using SHA1 with abuild-tar.

The APK file is compressed using gzip. Alpine's abuild uses GNU gzip; Adélie's apkkit uses Python's gzip module which internally uses zlib.

Package metadata

Inside control.tar, a .PKGINFO file is required. This is a text file that contains the package's metadata.

A signature file may also be present. If signed, the signature file must be the first file in the archive, and it must match the naming format .SIGN.$TYPE.$KEYNAME. $TYPE specifies the signature algorithm, and must be either DSA or RSA [sic, meaning SHA]. $KEYNAME specifies the name of the public key that signed control.tar; to verify the signature, an identical public key file must be present at $APKROOT/etc/apk/keys/$KEYNAME.

Certain package operations will execute named executable files if they are present in the control file (unless --no-scripts is passed):

  • .pre-install, if present, will be executed before the package is first installed if the package passes verification. If the package has not been signed, or failed verification but the user passed --allow-untrusted, this script will not be run. If the package is being upgraded, .pre-upgrade will be run instead; the package must still pass verification.
  • .post-install, if present, will be executed after the package is first installed. If the package is being upgraded, .post-upgrade will be run instead.
  • .pre-deinstall, if present, will be executed before the package is uninstalled.
  • .post-deinstall, if present, will be executed after the package is uninstalled.


The .PKGINFO file contains most of the package's metadata. It is a text file in key/value pair format, similar to INI configuration files but with a required space on each side of the equal sign. Full-line comments, starting with a "#" symbol, are ignored; a # symbol at any other position in a line will be treated as a literal.

Presently, the following keys are recognised by APK:

Key Type Index char Meaning
n/a String C Checksum (SHA-1?) of the control part of the package, excluding signatures.
pkgname String P The name of the package.
pkgver Version V The version of the package.
pkgdesc String T The user-readable description of the package.
url String U The URL of the package, typically the developer's Web site.
size Integer I The installed size of the package in whole bytes.
license String L The software license of the package.
arch String A The architecture for which the package was built.
depend Atom D A package name, virtual, or library on which the package depends. There can be more than one depend line.
install_if Atom i If all package, virtual, or libraries specified in install_if are installed, this package will be installed automatically. There can be more than one install_if line.
provides Atom p A package name, virtual, or library that this package provides. There can be more than one provides line.
replaces Atom r A package name that this package replaces. There can be more than one replaces line. The previous package will be removed and the files owned by it will become owned by this package.
replaces_priority Integer q The priority of the replacement. The highest number in the index wins.
triggers String n/a A space-delimited list of directories. See below section for more information.
maintainer String m The name of the maintainer of this package.
builddate Integer t The date this package was built. This field is a 64-bit POSIX timestamp specified in whole seconds.
commit String c A commit ID for this package.
origin String o The name of the origin package for this package. If this package is a subpackage (ex: foo-doc), this is the name of the base package (ex: foo). Otherwise, this is almost always the name of the package.

Strings are internally referred to as "blob"s. Integers are always 64-bit. A version can contain numbers, ASCII alphabetical characters, and the symbols "-_=~<>". Atoms are packages, and may be only a name, or a name followed by a dash (-) followed by a Version. A virtual can be specified with a "v:" prefix; a library can be specified with a "so:" prefix.

Only pkgname and pkgver are required. Size will default to 0 bytes if not specified. Arch will default to the current architecture (as specified at $APKROOT/etc/apk/arch), or the default architecture compiled in to the binary.


The .trigger executable, if present in package A's control.tar, will be executed when any package B installs a file into a directory matching the triggers key in a package A's .PKGINFO. Each directory in the space-delimited list will be passed to fnmatch with the FNM_PATHNAME flag. This allows you to use shell-like globbing for subdirectories.


The signature format for the data.tar needs to be documented here eventually. Rev-eng abuild-tar.

Index files (APKINDEX, APKINDEX.tar.gz)

The APKINDEX.tar.gz file is created by apk from a directory of *.apk files using the index applet. The index APK applet takes a few parameters:

Parameter Type Meaning
--quiet (none) Don't print any output.
--output String The filename to which to write the index.
--description String The description to use for the index. There is no default; it can be set to anything. abuild uses $git describe in the repository base as a default.
--rewrite-arch String Causes all packages to appear to be built for the specified arch. This is used by abuild because otherwise 'noarch' packages would not be chosen by apk (because they would appear to be for a different CPU).

apk will read every *.apk file in the directory and output the APKINDEX.tar.gz file to the path specified by --output, or APKINDEX.tar.gz in the current working directory if --output is not specified.

Once the file is created it must be signed similarly to control.tar.gz for the APK file itself.


There are typically three files in the APKINDEX.tar.gz file:

  • .SIGN.RSA.publickeyid
This is the signature.
This is a plain-text file that contains the string passed to --description. If no --description was specified, this file will not exist.
The actual index, containing each record.


The index is a series of records which are separated by a blank link (\n).