# Operating System Package Cache

import { Tabs, TabItem } from '@astrojs/starlight/components';

Operating system package caching uses the independent
`cache.os-packages.enabled` repository setting. It is on by default. Avrea exports
`AVREA_OS_PACKAGES_URL=https://cache.avrea.com:8443/os` in the runner environment.
These URLs are reachable inside Avrea runners.

Turn it off for an organization or a single repository under **Settings** in the
[Avrea console](https://console.avrea.com), or with
`avr settings set cache.os-packages.enabled false`. A repository inherits the
organization value unless it sets its own. See
[Managing Cache](/cache/managing/).

## Ubuntu runners

Ubuntu 22.04, 24.04 and 26.04 LTS runners are configured automatically. Apt
tries the cache first and retains each original repository as a fallback.
Turning the setting off restores configuration owned by Avrea while preserving
subsequent user edits.

Apt keeps its normal HTTPS timeout and retry settings. An unresponsive cache
can delay fallback for more than two minutes. Apt continues to verify repository
signatures and package hashes.

## Container helpers

Containers need explicit opt-in through small setup helpers. Commit the helpers
to your own repository instead of downloading them in every job. A job that
downloads a helper at run time fails when docs.avrea.com is unreachable, and it
runs whatever the site serves at that moment. Download the helpers you need
once, review them, and commit them. Update them deliberately in the same way.

```sh
curl --fail --fail-early --silent --show-error --create-dirs \
  --output-dir ci/avrea --remote-name-all \
  https://docs.avrea.com/scripts/os-package-cache-alpine.sh \
  https://docs.avrea.com/scripts/os-package-cache-fedora.sh \
  https://docs.avrea.com/scripts/os-package-cache-debian.sources
```

The examples below mount `ci/avrea` read-only at `/avrea` for container runs,
and copy it to `/avrea` for image builds. Docker and Podman accept the same
`-e`, `-v` and `--build-arg` options. Host environment variables are not
automatically available inside a container or image build, so every example
forwards `AVREA_OS_PACKAGES_URL` explicitly.

Turning the setting off removes `AVREA_OS_PACKAGES_URL` from the runner
environment. The helpers then leave the repositories unchanged and exit
successfully, and the Debian example falls back to the stock sources, so
committed opt-ins keep working with the cache off. The Debian example also uses
the stock sources when the URL differs from the one in its committed template.

## Alpine containers

Install the bootstrap tools from the original repositories, then run the setup
helper:

<Tabs syncKey="container-engine">
  <TabItem label="Docker">

```sh
docker run --rm -e AVREA_OS_PACKAGES_URL -v "$PWD/ci/avrea:/avrea:ro" \
  alpine:3.22 sh -ec '
  apk add --no-cache ca-certificates curl
  sh /avrea/os-package-cache-alpine.sh setup
  apk add --no-cache jq
  sh /avrea/os-package-cache-alpine.sh restore
'
```

  </TabItem>
  <TabItem label="Podman">

```sh
podman run --rm -e AVREA_OS_PACKAGES_URL -v "$PWD/ci/avrea:/avrea:ro" \
  docker.io/library/alpine:3.22 sh -ec '
  apk add --no-cache ca-certificates curl
  sh /avrea/os-package-cache-alpine.sh setup
  apk add --no-cache jq
  sh /avrea/os-package-cache-alpine.sh restore
'
```

  </TabItem>
</Tabs>

Use a pinned image digest for reproducible builds; the examples here use a tag
only so they stay readable. The helper preserves the image's release, repository
names, tags, and comments. It rewrites recognized
HTTPS `dl-cdn.alpinelinux.org/alpine` entries and leaves other origins unchanged.
It does not replace your repository list with a hard-coded Alpine release.

The helper saves `/etc/apk/repositories.avrea-original` and records the installed
configuration's checksum. Repeated setup is idempotent. Restoration refuses to
overwrite user edits; reconcile those edits before restoring. Failed preflight
leaves the original repository configuration active.

Setup and restore serialize on `/etc/apk/repositories.avrea-lock`, and never
break that lock automatically: no userspace liveness check is free of a window
in which two invocations both rewrite the repository file. A process killed
outright leaves the lock behind, and later runs then report that the lock is
held. Confirm no setup or restore is running and remove it with
`rmdir /etc/apk/repositories.avrea-lock`.

If setup reports an incomplete ownership state, run restore first. Restore
clears a half-written state; setup deliberately refuses to write over one.

### Image builds

Declare the build argument and copy the committed helpers into the build:

```dockerfile
FROM alpine:3.22
ARG AVREA_OS_PACKAGES_URL
COPY ci/avrea/ /avrea/
RUN apk add --no-cache ca-certificates curl \
    && sh /avrea/os-package-cache-alpine.sh setup \
    && apk add --no-cache jq \
    && sh /avrea/os-package-cache-alpine.sh restore \
    && rm -r /avrea
```

Forward the runner's value when building:

<Tabs syncKey="container-engine">
  <TabItem label="Docker">

```sh
docker build --build-arg AVREA_OS_PACKAGES_URL="$AVREA_OS_PACKAGES_URL" .
```

  </TabItem>
  <TabItem label="Podman">

```sh
podman build --build-arg AVREA_OS_PACKAGES_URL="$AVREA_OS_PACKAGES_URL" .
```

  </TabItem>
</Tabs>

Restore before distributing an image so its repositories remain usable outside
Avrea. Bootstrap packages still come from the original repositories.

### Cache outage recovery

Alpine does not gain apt's automatic mirror fallback. If an apk operation fails
after opting in, restore the original repositories and retry explicitly. If the
command stalls, interrupt it first, then run restoration and retry as separate
commands:

```sh
sh /avrea/os-package-cache-alpine.sh restore
apk add --no-cache jq
```

Keep apk's signing keys and signature verification enabled. Do not use
`--allow-untrusted` or disable HTTPS certificate validation.

## Fedora DNF5 containers

Fedora 44 containers support explicit opt-in with DNF5. The official Fedora 44
image includes the bootstrap tools the helper uses; custom images need DNF5,
curl, CA certificates, and coreutils installed from their original repositories
first.

<Tabs syncKey="container-engine">
  <TabItem label="Docker">

```sh
docker run --rm -e AVREA_OS_PACKAGES_URL -v "$PWD/ci/avrea:/avrea:ro" \
  fedora:44 sh -ec '
  sh /avrea/os-package-cache-fedora.sh setup
  dnf5 install -y jq
  sh /avrea/os-package-cache-fedora.sh restore
'
```

  </TabItem>
  <TabItem label="Podman">

```sh
podman run --rm -e AVREA_OS_PACKAGES_URL -v "$PWD/ci/avrea:/avrea:ro" \
  docker.io/library/fedora:44 sh -ec '
  sh /avrea/os-package-cache-fedora.sh setup
  dnf5 install -y jq
  sh /avrea/os-package-cache-fedora.sh restore
'
```

  </TabItem>
</Tabs>

The helper builds an override pointing the base and updates repositories at
the cache, checks that the cache serves both, and atomically installs
`/etc/dnf/repos.override.d/99-avrea.repo`. It verifies the effective DNF5
configuration and rolls back its override if verification fails. Stock repo
files remain in place: signing keys, enabled state, and other settings stay
inherited. Source, debug, and third-party repositories keep their original
configuration. Package signature checks remain enabled. DNF4 is unsupported.

Repeated setup is idempotent. The helper records its override's checksum and
refuses to replace an existing unowned file or remove a user-edited override.
Restore before changing cache URLs or distributing an image outside Avrea.

For image builds, declare `ARG AVREA_OS_PACKAGES_URL`, copy the helpers with
`COPY ci/avrea/ /avrea/`, and forward the value with `--build-arg`, as in the
Alpine example. Run setup, install packages, and restore in the same `RUN`
step before completing the image.

Two modes combine those steps. `try-setup` runs setup and, if setup fails,
prints a warning and leaves the original repositories in use instead of
failing. If an override remains after the failed setup, such as an unowned one
that was already present, `try-setup` fails instead. `run` performs `try-setup`, runs the given command, restores, and
exits with the command's status:

```dockerfile
RUN sh /avrea/os-package-cache-fedora.sh run dnf5 install -y jq
```

Both modes run the helper again by its path, so invoke it from a file rather
than piping it into `sh`. When `AVREA_OS_PACKAGES_URL` is unset, the helper
reads it from the secret file `/run/secrets/avrea_os_packages_url`. Passing
the URL with `--secret id=avrea_os_packages_url,env=AVREA_OS_PACKAGES_URL`
and `RUN --mount=type=secret,id=avrea_os_packages_url` keeps it out of the
layer cache keys, unlike a build argument.

### Cache outage recovery

Server-side Fedora mirror selection handles upstream mirror failures. An
unreachable cache still requires explicit recovery inside the container. If
DNF5 fails or stalls, interrupt it, remove the owned override, and retry:

```sh
sh /avrea/os-package-cache-fedora.sh restore
dnf5 install -y jq
```

Do not disable package signature checks or HTTPS certificate validation.

## Debian 13 containers

Debian reuses the apt cache with an explicit source template for the official
Debian 13 (`trixie`) image. It includes main, updates and security, and retains
the stock Debian archive key. It does not configure Ubuntu guests or custom
Debian source lists. Bootstrap tools still come from the original repositories.

Select the committed template for each cached apt command:

<Tabs syncKey="container-engine">
  <TabItem label="Docker">

```sh
docker run --rm -e AVREA_OS_PACKAGES_URL -v "$PWD/ci/avrea:/avrea:ro" \
  debian:trixie-slim sh -ec '
  apt-get update
  apt-get install -y --no-install-recommends ca-certificates
  if [ "${AVREA_OS_PACKAGES_URL:-}" = https://cache.avrea.com:8443/os ]; then
    cached_apt() {
      apt-get -o Dir::Etc::sourcelist=/avrea/os-package-cache-debian.sources \
        -o Dir::Etc::sourceparts=- "$@"
    }
  else
    cached_apt() { apt-get "$@"; }
  fi
  cached_apt update
  cached_apt install -y hello
'
```

  </TabItem>
  <TabItem label="Podman">

```sh
podman run --rm -e AVREA_OS_PACKAGES_URL -v "$PWD/ci/avrea:/avrea:ro" \
  docker.io/library/debian:trixie-slim sh -ec '
  apt-get update
  apt-get install -y --no-install-recommends ca-certificates
  if [ "${AVREA_OS_PACKAGES_URL:-}" = https://cache.avrea.com:8443/os ]; then
    cached_apt() {
      apt-get -o Dir::Etc::sourcelist=/avrea/os-package-cache-debian.sources \
        -o Dir::Etc::sourceparts=- "$@"
    }
  else
    cached_apt() { apt-get "$@"; }
  fi
  cached_apt update
  cached_apt install -y hello
'
```

  </TabItem>
</Tabs>

Pin the image digest for reproducible builds. The same commands work in an
image build with `ARG AVREA_OS_PACKAGES_URL` and `COPY ci/avrea/ /avrea/`;
forward the value with `--build-arg`. Remove `/avrea` before distributing the
image.

These command-specific options leave stock source files intact and deliberately
select only the template's Debian repositories. Use your normal apt invocation
for third-party repositories. Normal HTTPS timeouts and retries remain in force.
If a cached command fails or stalls, interrupt it and run `apt-get update` followed
by the original install command without the two source options. This template
uses explicit recovery, not automatic mirror fallback. Keep signature and hash
verification enabled.