GitHub CLI EXPKEYSIG on Ubuntu: Update the Keyring APT Actually Uses

The GitHub CLI key on your Ubuntu host is updated, yet the Docker build still stops at EXPKEYSIG. Which keyring is APT actually reading?

GitHub CLI EXPKEYSIG on Ubuntu: Update the Keyring APT Actually Uses
TLDR
  • The old signing key for GitHub CLI's official Linux repositories expired September 5, 2026.
  • On Ubuntu and Debian, check the keyring referenced by the APT source entry.
  • Updating another file—or only the Docker host—leaves the stale configuration in place.

Check the repository named in the error

If apt update reports EXPKEYSIG for https://cli.github.com/packages, inspect the repository signing key before changing GitHub login credentials. The September announcement says the old key expired September 5, with repository metadata using the replacement from the first subsequent release.

GitHub published a keyring containing both keys on April 8. An older repository setup that has never been refreshed needs attention. When the installation date is uncertain, inspect the actual keys.

This rotation concerns the official APT and RPM repositories. Homebrew, Conda, community packages, and direct GitHub Releases downloads do not require this repair. The commands below target the official APT setup on Ubuntu or Debian.

Follow signed-by to the file that matters

For the standard GitHub CLI repository setup, read:

cat /etc/apt/sources.list.d/github-cli.list

The signed-by= value selects the keyring. GitHub's rotation instructions distinguish the recommended /etc/apt/keyrings/ location from the older /usr/share/keyrings/ path. Follow the source entry instead of choosing whichever file exists first.

If the machine uses deb822 configuration, inspect the corresponding Signed-By: field. APT supports both .list and .sources files under /etc/apt/sources.list.d/, as documented in its manual.

gpg --show-keys /etc/apt/keyrings/githubcli-archive-keyring.gpg

Substitute the actual path. Match the fingerprints against the official installation document:

KeyFull fingerprint
Expired key2C6106201985B60E6C7AC87323F3D4EA75716059
Replacement7F38BBB59D064DBCB3D84D725612B36462313325

The official keyring contains both. An expired label on the old entry alone does not mean replacement failed; check that the new key is present in the file APT actually references.

Download, inspect, then install at that path

This sequence stages the official keyring in a temporary file. Set gh_keyring_path to the path you identified. It assumes curl and gpg are available; run both blocks in the same shell.

gh_keyring_path=/etc/apt/keyrings/githubcli-archive-keyring.gpg
gh_keyring_download=$(mktemp)
curl -fsSL -o "$gh_keyring_download" \
  https://cli.github.com/packages/githubcli-archive-keyring.gpg &&
gpg --show-keys "$gh_keyring_download"

After a successful download and fingerprint match, install it. Mode 0644 keeps it readable by APT's package-fetching user, as required by the Signed-By rules.

sudo install -m 0644 "$gh_keyring_download" "$gh_keyring_path" &&
rm -f "$gh_keyring_download" &&
sudo apt update &&
sudo apt install gh

If the repository still fails verification, recheck the referenced path and read permissions. This repairs package-source verification; running gh auth login cannot substitute for it.

Docker needs the updated file inside the image

GitHub's Docker guidance calls for rebuilding the layer that fetched the keyring, or fetching the current file in a layer before the failing apt update. Repairing the host does not replace a stale file baked into an image.

Search results may also lead to the 2024 expiration issue. That incident extended an existing key's expiry; the 2026 change introduces a replacement key. The useful completion check is whether the current source entry reads a keyring containing the new fingerprint.