GitHub Actions에서 Permission denied (publickey)가 나오면 먼저 실패한 접속의 목적지와 사용자를 확인하세요. 러너가 배포 서버에 들어가지 못한 경우와, 서버에 들어간 다음 git fetch가 GitHub에서 거부된 경우는 공개키 등록 위치가 다릅니다. 한 키를 여러 위치에 다시 붙여 넣는 방식보다 연결을 두 단계로 나누는 것이 먼저입니다.
이 글은 OpenSSH 기반 Linux 배포 서버와 SSH GitHub 인증을 사용하는 흐름을 다룹니다. 서드파티 배포 Action마다 입력값 형식이 다르므로 해당 Action의 고정 버전 문서도 함께 확인해야 합니다. 문서 확인 기준일은 2026-10-10입니다. 실제 러너·서버에 접속하거나 개인키를 읽지 않았으며 명령은 진단 예시입니다.
원인: 서로 다른 두 SSH 연결을 하나의 키 문제로 봅니다
| 실패 구간 | 개인키를 사용하는 쪽 | 공개키를 확인할 곳 |
| 러너 → 배포 서버 | 러너의 승인된 배포 키 | 배포 사용자 authorized_keys 또는 조직의 인증 방식 |
| 서버 → GitHub 저장소 | 서버의 저장소 접근 키 | GitHub 계정 SSH 키 또는 해당 저장소 deploy key |
| 러너 → GitHub 직접 접근 | 러너가 사용하는 저장소 인증 | GitHub에서 해당 주체의 저장소 권한 |
서버에 로그인했다고 그 서버가 GitHub 저장소도 읽을 수 있는 것은 아닙니다. 반대로 GitHub에 deploy key를 등록했다고 임의의 Linux 배포 서버가 그 키를 허용하는 것도 아닙니다. 실패 로그의 호스트·사용자와 명령 실행 위치를 적으세요. git@github.com에서 거부된 로그는 서버 사용자의 authorized_keys만 고쳐서는 해결되지 않을 수 있습니다.
해결 절차 1: 러너에서 서버로 가는 사용자·키를 확인
SSH 사용자 이름이 실제 공개키를 등록한 배포 계정과 같은지 확인합니다. root·ubuntu·deploy를 임의로 바꿔 시도하지 않습니다. Secrets 이름, Repository/Organization/Environment 범위와 실행 권한·승인 조건을 대조하세요. GitHub 공식 문서는 없는 Secret 참조가 빈 문자열을 반환한다고 설명하므로 키를 새로 만들기 전에 실행에서 값이 제공되는지 확인해야 합니다. 키 원문이나 전체 환경 변수를 로그에 출력하지 마세요. 공식 Secrets 사용 문서를 기준으로 전달 범위를 확인합니다.
# 승인된 키 파일이 이미 준비된 러너에서 확인
# 호스트 키는 검증된 known_hosts에 사전 등록
ssh -o BatchMode=yes \
-o IdentitiesOnly=yes \
-i /path/to/deploy_key \
deploy@deploy.example.com true
deploy.example.com과 파일 경로는 자리표시자입니다. 이 명령은 실제로 원격 접속을 시도하고 true를 실행하므로 승인된 시험 대상에서만 사용합니다. 암호화된 개인키를 쓰면 안전하게 준비된 에이전트나 선택한 도구의 암호 지원 방식이 필요합니다. IdentitiesOnly=yes는 에이전트의 다른 키가 섞이는 상황에서 의도한 인증 파일을 선택하는 데 도움을 주지만 잘못된 키를 올바르게 만드는 옵션은 아닙니다. OpenSSH 설정 설명에서 실제 적용 설정을 확인하세요.
해결 절차 2: 배포 서버의 공개키 등록과 파일 권한 확인
# 해당 배포 사용자의 콘솔에서 경로·소유자 확인
ls -ld ~ ~/.ssh
ls -l ~/.ssh/authorized_keys
기본 경로를 쓰는 서버라면 해당 사용자의 authorized_keys에 대응 공개키가 있는지, 소유자가 맞는지 확인합니다. 실제 서버는 AuthorizedKeysFile, 인증서 또는 별도 키 조회를 사용할 수도 있으므로 기본 파일이 없다는 이유만으로 새 파일을 만들어 해결했다고 판단하지 않습니다. 파일·홈 디렉터리에 다른 사용자의 쓰기 권한이 있으면 StrictModes에 의해 거부될 수 있습니다. OpenSSH 서버 인증 파일 설명을 확인하고 보안 검사를 끄는 대신 잘못된 소유자·권한의 원인을 바로잡으세요.
수정이 필요하면 현재 키 파일과 권한을 승인된 안전한 위치에 보존하고 기존 정상 관리자 세션을 유지한 채 새 세션에서 시험합니다. 키를 교체하는 동안 기존 키를 즉시 제거하면 원격 접근을 잃을 수 있습니다. 조직의 키 등록·폐기 절차와 최소 권한 배포 계정을 사용하세요.
해결 절차 3: 서버에서 GitHub로 가는 연결을 따로 확인
# 배포 서버의 실제 git 실행 사용자 환경에서 확인
ssh -T git@github.com
이 명령은 GitHub SSH 인증을 실제로 시도합니다. 올바른 사용자 환경과 승인된 네트워크에서 시험하고 기대한 GitHub 주체로 인증되는지 확인하세요. GitHub는 셸 접근을 제공하지 않으므로 일반 서버 로그인 명령의 종료 코드만으로 판단하지 말고 공식 문서의 응답을 함께 읽습니다. 인증 성공 후에도 저장소 접근 권한, remote URL, deploy key 적용 저장소가 맞는지는 별도로 확인해야 합니다. GitHub 공개키 오류 공식 점검을 참고하세요.
확인 방법: 어디까지 성공했는지 단계별로 남깁니다
| 확인 지점 | 완료 판단 |
| Secrets 제공 | 필요한 범위의 승인된 실행에서 키 제공 여부 확인, 원문 비공개 |
| 러너 → 서버 | 예상 배포 사용자로 승인된 진단 명령 성공 |
| 서버 → GitHub | 예상 GitHub 주체 인증과 대상 저장소 읽기 권한 확인 |
| 실제 배포 | 인증 이후 별도 빌드·배포·서비스 검증 결과 확인 |
필요할 때만 제한된 진단 실행에서 SSH 상세 로그를 확인합니다. 공유 전 호스트·사용자·경로·식별 정보를 가리고, Secret 마스킹이 모든 형태의 민감한 출력을 보호한다고 믿지 마세요. 재시도는 원인 수정 후 한 번씩 수행하며 같은 설정에서 반복 접속해 성공을 기다리는 방식은 피합니다. 인증 성공은 배포 성공과 구분합니다.
주의사항: 호스트 키 경고는 공개키 인증 오류와 다릅니다
Host key verification failed는 목적지 서버 신원 검증 문제이며 이 글의 사용자 공개키 인증 거부와 별개입니다. StrictHostKeyChecking=no로 통과시키지 말고 신뢰된 경로로 호스트 키를 확인하세요. chmod 777, StrictModes 비활성화, 개인키 저장소 커밋, root 허용 확대는 일반 해결책으로 사용하지 않습니다. 제3자 Action은 검증된 고정 버전과 필요한 권한만 사용합니다.
FAQ
개인키와 공개키 중 무엇을 서버에 등록하나요? 일반적인 공개키 인증은 클라이언트가 개인키를 보유하고 서버가 대응 공개키를 허용합니다. 개인키를 authorized_keys에 넣지 않습니다.
Secret 이름을 바꿔도 오류가 계속되면요? 실제 참조 이름·범위·실행 조건과 대상 사용자부터 확인합니다. 로그에 키 내용을 출력해서 존재 여부를 시험하지 않습니다.
서버 접속은 성공하고 git fetch만 실패하면요? 서버에서 GitHub로 가는 두 번째 연결의 실행 사용자·키·저장소 권한을 별도로 점검하세요.
공식 출처와 관련 글
공식 자료 확인 기준일: 2026-10-10. 문서 확인 내용과 설계 예시이며 실제 계정·명령 실행 결과가 아닙니다.
함께 읽기: GitHub Actions와 GitLab CI 러너 운영 선택
직접 제작한 개념 이미지. 두 SSH 연결의 키 등록 위치를 구분하며 실제 키·로그·실행 화면은 아닙니다.

'소프트웨어개발' 카테고리의 다른 글
| Docker port is already allocated 해결: Compose 호스트 포트 충돌 점검 (0) | 2026.10.12 |
|---|---|
| AWS Backup과 EBS DLM 비교: 스냅샷 보존·복구 운영 선택 기준 (0) | 2026.10.11 |
| Tailscale와 Cloudflare Tunnel·Access 비교: 내부 관리자 접속 방식 선택 기준 (0) | 2026.10.11 |