Lesstep
GitHub Actions · Ubuntu runners · Checked November 5, 2026

apt-get stuck for minutes on GitHub-hosted Ubuntu runners: a slow azure.archive.ubuntu.com, and why apt does not move to the next mirror

On GitHub-hosted Ubuntu runners, apt asks azure.archive.ubuntu.com first. When that mirror sends archives slowly, at tens of kB/s, apt keeps downloading from it: the runner image's timeout fires only when nothing arrives at all, so an install that usually takes a minute runs until timeout-minutes cancels the job. The image maintainers track it in runner-images #14823, open since September 30, 2026. It is the mirror, not the image: ubuntu-24.04 and ubuntu-26.04 runners see the same.

What it looks like

The package lists come down at full speed, and the archives do not (RustCrypto/crypto-bigint, ubuntu-26.04, October 25, 2026):

Fetched 3043 kB in 0s (10.8 MB/s)
...
Need to get 21.3 MB of archives.
Get:2 http://azure.archive.ubuntu.com/ubuntu resolute-updates/main amd64v3 libc6-dev-i386 amd64 2.43-2ubuntu2.4 [1605 kB]
...
Fetched 21.3 MB in 8min 11s (43.3 kB/s)

Why apt does not move on

Why replacing the host name does nothing

A step that runs sed -i 's|azure\.archive\.ubuntu\.com|archive.ubuntu.com|g' over /etc/apt/sources.list and sources.list.d changes nothing on these runners: the sources do not name the host, they name the mirror list (snapotter-hq/SnapOtter #1808). Edit /etc/apt/apt-mirrors.txt instead.

A step that moves on

The maintainers' answer in #15142, with your own package list:

- name: Install system packages
  timeout-minutes: 6
  run: |
    pkgs="ffmpeg imagemagick"
    sudo apt-get update
    if ! timeout 90 sudo apt-get install --yes --download-only $pkgs; then
      sudo sed -i '/azure\.archive\.ubuntu\.com/d' /etc/apt/apt-mirrors.txt
      sudo apt-get install --yes --download-only $pkgs
    fi
    sudo apt-get install --yes $pkgs

The first download gets 90 seconds. If it does not finish, the Azure line comes out of the mirror list and the download is tried again from archive.ubuntu.com; the last line installs what was downloaded. timeout-minutes is the backstop for the whole step. Set the 90 from your own packages: a healthy mirror serves tens of MB/s, so most installs need far less.

For an apt-get update that stops, give each try a limit and try again:

    for i in 1 2 3; do
      timeout 120 sudo apt-get update && break
      [ "$i" = 3 ] && exit 1
    done

Or keep away from the Azure mirror

Telling it apart

The same on Azure Pipelines

Microsoft-hosted agents for Azure Pipelines are built from the same repository, actions/runner-images. If an Ubuntu job's log shows Get:1 file:/etc/apt/apt-mirrors.txt Mirrorlist, the same step works there, with timeoutInMinutes on the step instead of timeout-minutes.

See failed jobs from IntelliJ IDEA

Pipeline Inbox for GitHub Actions Workflows, a plugin by Lesstep for JetBrains IDEs 2024.1 or later, lists the runs of all your repositories in an IDE tool window, with their jobs and steps, so the jobs that were cancelled in an apt step stand out, and your current branch's runs are in the status bar. Reading is free; re-running failed jobs, cancelling, running workflows and reviewing deployments are Pro (US$1.50 a month, with a 30-day trial).

Get it on JetBrains Marketplace

GitHub and GitHub Actions are trademarks of GitHub, Inc.; Ubuntu is a trademark of Canonical Ltd.; Azure and Azure Pipelines are trademarks of Microsoft Corporation; IntelliJ IDEA is a trademark of JetBrains s.r.o. This page is not affiliated with, sponsored or endorsed by GitHub, Inc., Canonical, Microsoft or JetBrains.

More: apt on Ubuntu 26.04: renamed and removed packages · "The job has exceeded the maximum execution time" · "The ubuntu-latest label will migrate to Ubuntu 26" · 日本語