GitHub CLI 업데이트가 EXPKEYSIG로 막힐 때: APT 서명키 갱신하기

개발 PC에서는 gh 업데이트가 되는데, 같은 머신의 Docker 빌드는 여전히 EXPKEYSIG에서 멈춘다. 호스트의 키를 바꿨는데 이미지 안에서는 무엇이 아직 옛날 그대로일까?

GitHub CLI 업데이트가 EXPKEYSIG로 막힐 때: APT 서명키 갱신하기
세 줄 요약
  • GitHub CLI 공식 Linux 저장소의 옛 서명키는 2026년 9월 5일 만료됐다.
  • Ubuntu·Debian에서는 저장소 항목이 참조하는 키링에 새 공개키가 있는지 확인한다.
  • 새 키를 다른 경로에 받아 두거나 호스트만 고쳐서는 오래된 Docker 이미지까지 바뀌지 않는다.

cli.github.com의 서명 오류라면 저장소 키부터 본다

apt update에 EXPKEYSIG가 뜨고 대상이 https://cli.github.com/packages라면, GitHub 로그인 토큰보다 APT 저장소의 서명키를 먼저 확인해야 한다. GitHub의 9월 공지에 따르면 옛 키는 9월 5일 만료됐고, 그 뒤 첫 릴리스부터 저장소 메타데이터 서명에 새 키가 쓰인다.

두 키를 담은 키링은 4월 8일 배포됐다. 그 전에 공식 저장소를 설정한 뒤 갱신하지 않은 시스템이 점검 대상이다. 설치 날짜를 모르거나 커스텀 이미지를 쓴다면 실제 키를 보면 된다.

이 교체는 공식 APT·RPM 저장소 경로에 해당한다. Homebrew·Conda·배포판 커뮤니티 패키지나 GitHub Releases의 직접 다운로드는 같은 조치 대상이 아니다. 아래 명령은 Ubuntu·Debian의 공식 APT 저장소를 전제로 한다.

새 키를 저장할 경로도 APT 설정과 맞아야 한다

먼저 공식 설치 방식의 저장소 항목을 연다.

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

signed-by= 뒤의 경로가 APT가 읽을 키링이다. GitHub의 교체 안내는 현재 권장 경로인 /etc/apt/keyrings/와 과거의 /usr/share/keyrings/를 구분한다. 파일이 어느 폴더에 있는지만 보고 고르지 말고 저장소 항목의 값을 따른다.

설정을 직접 바꿔 .sources 형식을 쓰는 경우도 있다. APT 매뉴얼에 따르면 /etc/apt/sources.list.d/는 .list와 .sources를 모두 지원한다. 해당 저장소의 Signed-By: 값을 확인하면 된다.

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

위 명령의 경로도 실제 값으로 바꾼다. 공식 설치 문서와 대조할 지문은 다음과 같다.

키전체 지문
만료된 기존 키2C6106201985B60E6C7AC87323F3D4EA75716059
교체 키7F38BBB59D064DBCB3D84D725612B36462313325

현재 공식 키링에는 두 키가 함께 들어 있다. 따라서 기존 키에 expired 표시가 남아 있다는 사실만으로 갱신 실패라고 볼 수는 없다. 새 키의 존재와 APT가 참조하는 파일의 일치 여부가 중요하다.

공식 파일을 받은 뒤 확인한 경로에 설치한다

다음은 공식 다운로드 주소에서 임시 파일로 받아 지문을 확인하는 순서다. gh_keyring_path에는 앞에서 읽은 실제 경로를 넣는다. curl과 gpg가 설치된 셸에서 두 코드 블록을 이어 실행하는 예시다.

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"

다운로드가 성공하고 지문이 위 표와 일치하면 같은 셸에서 해당 파일을 설치한다. 0644는 관리자 외에도 키링을 읽을 수 있게 한다. APT는 패키지 조회용 사용자도 키 파일을 읽을 수 있어야 한다.

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

그 뒤에도 같은 저장소의 서명 오류가 남으면 signed-by 경로와 파일 읽기 권한을 다시 대조한다. 이 과정은 패키지 출처를 검증하는 공개키를 갱신하는 작업이므로 gh auth login을 다시 하는 것으로 대체할 수 없다.

호스트를 고쳐도 이미지 안의 오래된 키는 남는다

GitHub의 Docker 안내는 키링을 추가한 레이어를 다시 빌드하거나, 실패하는 apt update보다 앞선 레이어에서 새 키링을 받도록 설명한다. 개발 PC에서 갱신이 성공했어도 이미지가 옛 파일을 품고 있으면 빌드 단계는 계속 실패할 수 있다.

검색에서 2024년 만료 이슈가 먼저 나오는 경우도 있다. 그때는 기존 키의 만료일을 연장했지만 2026년에는 새 키로 교체했다. 현재 문제를 끝내는 기준은 “과거의 해결 명령을 실행했다”가 아니라, 실제 저장소 설정이 새 지문을 가진 키링을 읽고 있느냐다.