skip to content

An Alpine Linux system's `/etc/apk/repositories` points at `v3.20/main` and `v3.20/community`, and a colleague wants to add an `edge` line to get a newer version of one package. What are Alpine's branches and repositories, and what are you agreeing to if you mix edge into a stable system?

level: middleimportance: nice to knowfreq 34%

answer

  1. two axes: which branch, which repository
  2. numbered branches freeze, edge never does
  3. main, community, and testing on edge only
  4. one flat search space for dependency resolution
  5. tagging narrows it, it does not isolate it

basics

~20 s

Alpine ships stable branches (v3.20 and friends) and one rolling branch called edge, each split into repositories: main, community, and testing which exists only on edge. Mixing edge into a stable system drags dependencies along and effectively converts it to a rolling system.

solid answer

~50 s

Alpine publishes a numbered stable branch roughly twice a year plus `edge`, the permanently rolling development branch. Within a branch, `main` holds the core packages the project commits to supporting for that release's lifetime, `community` holds packages maintained by contributors, and `testing` exists only under edge. `/etc/apk/repositories` is just a list of the branch/repository URLs `apk` will consult, and it is a flat namespace — a package's dependencies are resolved across every listed line. So adding an edge line to a stable host does not fetch one newer package in isolation: edge builds are compiled against edge's musl and toolchain, so `apk` will happily pull edge versions of shared libraries too, and you have drifted onto a rolling system without deciding to. If you truly need one package from edge, tag that repository line and request the package explicitly against the tag, and treat it as a known deviation.

code

bash · 6 lines
bash
cat /etc/apk/repositories
# https://dl-cdn.alpinelinux.org/alpine/v3.20/main
# https://dl-cdn.alpinelinux.org/alpine/v3.20/community
# @edge https://dl-cdn.alpinelinux.org/alpine/edge/community

apk add nodejs@edge   # only this package is taken from the tagged repository

go deeper

for a junior

Know that /etc/apk/repositories lists where apk fetches packages from, that numbered branches are the stable ones, and that edge is the rolling development branch you should not add casually.

for a middle

Explain the branch/repository split — main, community, testing only on edge — and why apk resolves dependencies across every listed line, so an edge entry pulls newer shared libraries along with the package you wanted.

for a senior

Demonstrate the operational consequence: an untagged edge line converts a supported host into an unsupported rolling one over successive upgrades, and you should be able to spot that as the cause of an unreproducible build or a post-upgrade failure.

for a principal

Own the currency-versus-stability policy. Decide whether the organisation runs pinned stable branches with a scheduled upgrade cadence or accepts edge somewhere, and make branch end-of-life dates a tracked obligation rather than a discovery.

## The two axes: branch and repository Alpine's package universe is addressed on two axes, and conflating them is the usual confusion. The first axis is the **branch**, which is a point in Alpine's release timeline. Numbered branches such as `v3.20` are stable: once released they receive bug and security fixes rather than new upstream versions, and a new one appears roughly every six months. `edge` is the single rolling branch where development happens; it has no version number and never freezes. The second axis is the **repository** within a branch. `main` contains the core set the project commits to supporting for the branch's lifetime. `community` contains packages maintained by contributors that have graduated out of testing. `testing` exists only under `edge` — there is no `v3.20/testing`, which is why people reach for edge in the first place when the package they want has not graduated yet. A URL is therefore a branch plus a repository, and `/etc/apk/repositories` is nothing more than the list of those URLs, one per line, that `apk` consults. ``` cat /etc/apk/repositories # https://dl-cdn.alpinelinux.org/alpine/v3.20/main # https://dl-cdn.alpinelinux.org/alpine/v3.20/community ``` ## Why a stable branch pins versions When you install from `v3.20`, you get whatever upstream version Alpine froze at that branch's release, with fixes backported. That is the entire point of a stable branch: the same repository line a year later still resolves to the same major versions, so a rebuild is reproducible in the ways that matter and an upgrade is a decision you make rather than an event that happens to you. Each stable branch gets fixes for a bounded window — on the order of two years, with the precise end-of-life dates published per release — after which its URLs still exist but stop receiving security updates. Running a branch past that date is one of the quieter ways to accumulate unpatched CVEs. ## What mixing edge actually does The repository list is a flat search space. `apk` does not treat 'my stable lines' and 'my edge line' as separate worlds it keeps apart; it resolves the whole dependency graph across everything listed. The package you wanted from edge was built against edge's musl, edge's toolchain and edge's versions of every shared library it links. Satisfying it therefore drags those newer libraries in, and once core libraries come from edge, subsequent installs and upgrades resolve against them too. Two `apk upgrade` runs later the machine is functionally an edge system that nobody chose, on a branch with no support commitment and no stability promise, where a package can change major version overnight. The damage is worst on long-lived systems and worst of all when it is invisible: the change is one line in a config file, and the consequence arrives weeks later as an unreproducible build or a service that will not start after a routine upgrade. ## The narrower tool: repository tags When you genuinely need one package that only exists in edge, `apk` supports tagging a repository line with a leading `@name` marker and then requesting a package explicitly against that tag, so the tagged repository is consulted only for packages you ask for by tag rather than for everything. ``` # /etc/apk/repositories # https://dl-cdn.alpinelinux.org/alpine/v3.20/main # https://dl-cdn.alpinelinux.org/alpine/v3.20/community # @edge https://dl-cdn.alpinelinux.org/alpine/edge/community apk add nodejs@edge ``` This is narrower than an untagged edge line, but it is not free: the tagged package's own dependencies still have to be satisfied, and if it needs a newer library than your stable branch carries, that library comes from edge too. Treat it as a documented deviation with an owner, not as a general-purpose newer-packages switch. ## What good practice looks like Pin the branch you actually intend to run, including in whatever provisions your systems, so a rebuild months later does not silently move. Prefer waiting for a package to graduate into a stable branch's community repository over pointing at edge. If you need edge for real, run edge deliberately and everywhere it applies rather than as a graft onto a stable host. And know your branch's end-of-life date, because a stable branch stops being stable and starts being unmaintained on a specific day. ## A related apk trait worth knowing `apk` keeps a downloaded index and, optionally, cached packages. The `--no-cache` option tells it to fetch a fresh index for this operation and keep nothing afterwards, which is why it appears so often in automated builds: no stale index, no cache directory left behind. It is a cache-behaviour switch, not a repository or branch selector, and it does not change which versions you get.

  • Why does `testing` not exist under a numbered Alpine branch?
    Because testing is where new and unvetted packages land while they are being shaken out, which is incompatible with the promise a stable branch makes. Packages graduate from edge/testing into edge/community, and only then appear in the next numbered release's community repository. If the package you want is still in testing, there is no stable path to it — that is information about its maturity, not just an inconvenience.
  • What does `apk add --no-cache` change?
    It makes apk fetch a fresh package index for that operation and keep no cache afterwards, so you neither rely on a stale index nor leave a cache directory behind. It is purely about apk's caching behaviour: it does not alter which repositories are consulted or which versions resolve, and it is not a substitute for pinning the branch you intend to run.
  • How would you keep a rebuilt system from silently drifting to newer packages months later?
    Pin the branch explicitly in whatever writes /etc/apk/repositories, and treat moving from v3.20 to v3.21 as a deliberate, tested change. Track the branch's end-of-life date so the pin does not quietly become an unpatched system, and if reproducibility matters more than that, record the exact package versions you validated rather than trusting the branch alone.

saying these in an interview costs you the question

  • Thinks edge is Alpine's long-term support branch
  • Believes an edge line affects only the package requested
  • Says main and community differ by license, not maintenance
  • Assumes a stable branch is supported indefinitely
  • Confuses --no-cache with a version or branch selector

context