SSH 다계정 인증과 ~/.ssh/config alias

로컬·VM·CI/CD 환경에서의 SSH 키 전략과 멀티 계정 관리

SSH 키가 왜 필요한지, 어느 주체(로컬/VM/CI-CD)에서 생성해야 하는지 원칙을 정리하고, ~/.ssh/config Host alias 패턴으로 멀티 GitHub 계정을 충돌 없이 관리하는 방법을 다룬다. Poetry, git, GitHub Actions 등 실무 환경에서의 적용 사례도 함께 정리한다.

Engineering
DevOps
Python
Poetry
Security
SSH
저자

Kwangmin Kim

공개

2025년 03월 09일

1 개요

SSH 키 관리의 핵심은 “접속을 시작하는 주체” 에 개인키가 있어야 한다는 원칙이다. 로컬 PC, VM 서버, CI/CD 파이프라인이 각각 다른 대상에 접속할 때 필요한 키가 달라진다. 이 원칙을 이해하면 멀티 계정 SSH 충돌 문제도 자연스럽게 해결된다.

  • 개발 환경에서 로컬 PC, Azure VM, GitHub Actions가 각각 서로 다른 대상에 SSH로 접속한다.
  • 각 접속 주체에 적합한 키를 준비하고, ~/.ssh/config의 Host alias로 멀티 계정을 명확히 구분한다.

2 SSH 키의 핵심 원칙

SSH에서 접속을 시작하는 쪽(클라이언트) 에 개인키(private key)가 있어야 하고, 접속을 받는 쪽(서버) 에 공개키(public key)가 등록되어 있어야 한다.

클라이언트 (개인키 보유)  →  SSH 접속  →  서버 (공개키 등록됨)

따라서 어떤 머신이 능동적으로 다른 곳에 접속하면, 그 머신에 개인키가 있어야 한다.

2.1 개인키 파일 형식: .pem vs id_ed25519

id_rsa, id_ed25519 같은 파일만 개인키라고 생각하기 쉽지만, .pem도 형식만 다를 뿐 동일한 개인키다.

파일 형식 발급 주체
id_ed25519 OpenSSH 형식 사용자가 ssh-keygen으로 직접 생성
test-agent_key.pem PEM 형식 Azure/AWS가 VM 생성 시 발급

두 형식 모두 ~/.ssh/configIdentityFile에 지정해서 동일하게 사용한다.

2.2 Azure VM 키 페어의 생성 위치

.pem 파일은 VM에서 생성된 것이 아니라, Azure가 생성해서 로컬로 내려준 개인키다.

Azure Portal에서 VM 생성
        ↓
Azure가 키 페어를 생성
        ↓
개인키(.pem) → 로컬로 다운로드  ← test-agent_key.pem 이것
공개키        → VM의 ~/.ssh/authorized_keys에 자동 등록

VM 내부에는 공개키만 등록되어 있고 개인키는 없다. 그래서 로컬에서 .pem으로 VM에 접속할 수 있는 것이다. 만약 VM 안에 개인키가 있다면 그건 보안 문제다.

노트

현재 로컬 ~/.ssh/id_ed25519 계열 파일이 없더라도, .pem 파일이 있다면 VM 접속용 개인키는 이미 존재하는 것이다. “개인키가 없다”는 표현은 GitHub SSH용 키가 없다는 의미일 뿐이다.

3 환경별 SSH 키 전략

3.1 키 주체별 정리

로컬 PC, VM, GitHub Actions 각각이 어디에 접속하는지에 따라 필요한 키가 결정된다.

접속 주체 접속 대상 키 종류 위치
로컬 PC Azure VM .pem 키 파일 로컬 ~/.ssh/
로컬 PC GitHub id_ed25519_* 로컬 ~/.ssh/
Azure VM GitHub id_ed25519 VM의 ~/.ssh/
GitHub Actions Azure VM .pem 내용 GitHub Secrets

3.2 로컬 PC → Azure VM

Remote-SSH로 VM에 접속할 때 “나는 azureuser다”를 증명하는 키다. 이게 없으면 VM 접속 자체가 불가능하다. Azure에서 VM을 생성할 때 발급받은 .pem 파일이 이 역할을 한다.

3.3 로컬 PC → GitHub

로컬에서 git push, git pull을 SSH로 할 때 필요하다. HTTPS 방식으로 GitHub를 쓰고 있다면 당장은 없어도 되지만, 멀티 계정 설정을 하려면 반드시 필요하다. HTTPS는 URL만으로 계정을 구분할 수 없어서 멀티 계정이 불가능하다.

3.4 Azure VM → GitHub

VM이 GitHub에서 코드를 git pull할 때 필요하다. 배포 스크립트가 아래와 같은 형태라면, VM 자신이 GitHub에 인증해야 한다.

git pull origin main   # VM이 GitHub에 능동적으로 접속
docker compose up -d

VM에 키가 없으면 이 단계에서 인증이 막힌다.

3.5 GitHub Actions → Azure VM

GitHub Actions가 코드를 빌드한 후 VM에 자동 배포할 때, Actions 서버가 VM에 SSH로 접속해야 한다. .pem 파일의 내용을 GitHub Secrets에 등록해두면 Actions가 그 키로 VM에 접속한다.

# .github/workflows/deploy.yml
- name: Deploy to VM
  uses: appleboy/ssh-action@v1
  with:
    host: ${{ secrets.VM_HOST }}
    username: azureuser
    key: ${{ secrets.VM_SSH_KEY }}   # .pem 파일 전체 내용
    script: |
      docker pull ghcr.io/username/myapp
      docker compose up -d
중요

CI/CD에서는 개인이 쓰는 범용 키를 그대로 쓰지 않고, 배포 전용 키를 별도로 생성해서 Secrets에 등록하는 것이 보안상 올바르다.

3.6 VM에서 SSH 키를 생성해야 하는 경우 요약

VM 자신이 능동적으로 외부에 접속하는 시나리오에서만 VM에 키가 필요하다.

시나리오 VM에 키 필요 여부
VM → GitHub (코드 pull/push) 필요
VM → 다른 VM (내부 통신) 필요
VM → Docker Registry 필요
CI/CD Runner가 VM에서 실행 필요
내가 로컬에서 VM에 접속만 할 때 불필요

4 GitHub SSH 멀티 계정이 필요한 경우

GitHub 계정이 1개라면 멀티 계정 설정은 불필요하다. SSH 키도 1개만 만들면 된다.

# GitHub용 SSH 키 하나만 생성 (단일 계정)
ssh-keygen -t ed25519 -C "your@email.com" -f ~/.ssh/id_ed25519_github
# config에 추가
Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_github

개인 프로젝트와 회사 프로젝트를 같은 GitHub 계정으로 관리하고 있다면 이 키 하나로 모두 커버된다.

멀티 계정 SSH 설정이 필요해지는 시점은 회사가 별도 GitHub 조직 계정(또는 GitHub Enterprise)을 만들고 전용 계정을 요구할 때다.

상황 멀티 계정 필요 여부
개인 계정 1개로 개인/회사 프로젝트 모두 관리 불필요 — 키 1개로 충분
개인 계정 + 회사 전용 계정 분리 필요
개인 계정 + 여러 조직 계정 필요
개인 계정 + 봇/서비스 계정 필요

멀티 계정이 필요한 경우 HTTPS보다 SSH가 훨씬 편하다. git credential manager는 계정을 하나만 캐싱해서 다른 계정 repo에 push할 때마다 로그인을 다시 해야 하는 반면, SSH alias는 URL만으로 계정을 구분해 비밀번호 입력 없이 자동 인증된다.

5 문제 상황: 멀티 계정 SSH 충돌

5.1 기본 SSH 접속 시도

GitHub은 기본적으로 ~/.ssh/id_rsa 또는 ~/.ssh/id_ed25519 키를 시도한다. SSH 키가 여러 개 있을 때 어떤 키를 써야 할지 특정할 수 없어서 인증이 실패한다.

$ ssh -T git@github.com
git@github.com: Permission denied (publickey).

조직/팀별로 별도 키를 쓸 경우 ~/.ssh/config로 alias를 지정해야 인증 충돌을 방지할 수 있다.

5.2 VM 서버의 SSH 키 현황 예시

$ ls ~/.ssh/*.pub
/home/azureuser/.ssh/agent_repo.pub   # 개인 repo용 키
/home/azureuser/.ssh/sg_org.pub       # 조직(Seegene) repo용 키

두 개의 키가 각각 다른 GitHub 계정/조직에 등록되어 있는 상태에서, 기본 접속으로는 어떤 키를 써야 할지 알 수 없다.

6 ~/.ssh/config 구조

SSH config 파일은 여러 계정/조직별로 Host alias를 지정해, 각 alias마다 사용할 키와 접속 정보를 분리 관리한다. 실무에서는 개인/조직/CI용 키를 모두 별도 alias로 관리하는 것이 안전하다.

Host agent_repo
    HostName github.com
    User git
    IdentityFile ~/.ssh/agent_repo

Host seegene_org
    HostName github.com
    User git
    IdentityFile ~/.ssh/seegene_org

6.1 설정 항목 설명

항목 설명
Host SSH 접속 시 사용할 alias (임의 이름)
HostName 실제 접속할 호스트 (github.com)
User GitHub SSH 접속 유저 (항상 git)
IdentityFile 이 alias 사용 시 적용할 SSH private key 경로

7 alias를 사용한 접속 테스트

SSH alias로 접속하면 원하는 키로 인증이 명확히 이뤄진다. 실무에서는 인증 테스트를 통해 키/alias 설정이 올바른지 반드시 확인한다.

$ ssh -T git@seegene_org
Hi kmkim-seegene! You've successfully authenticated,
but GitHub does not provide shell access.

git@seegene_org는 실제로 git@github.com으로 접속하되 ~/.ssh/seegene_org 키를 사용한다.

노트

“does not provide shell access” 는 정상이다. GitHub SSH는 shell이 아닌 git 명령만 허용하므로 인증 성공 메시지다.

8 git clone/remote URL에서 alias 사용

git clone, remote 등 모든 git 명령에서 github.com 대신 SSH alias를 쓰면, ~/.ssh/config에 지정한 키로 자동 인증된다. 여러 계정/조직을 병행 관리할 때 필수적인 패턴이다.

8.1 일반 GitHub URL vs alias URL

# 기본 URL (어떤 키를 쓸지 모름)
git clone git@github.com:SeegeneDevelopmentPlatform/repo.git

# alias URL (seegene_org 키 사용 명시)
git clone git@seegene_org:SeegeneDevelopmentPlatform/repo.git

github.com 대신 alias 이름(seegene_org)을 사용하면 ~/.ssh/config에 따라 올바른 키로 자동 인증된다.

9 Poetry git dependency에서 alias 사용

Poetry, pip 등 Python 패키지 관리 도구에서도 SSH alias를 그대로 활용할 수 있다. pyproject.toml에 기록되는 URL에도 alias를 쓰면, 팀 전체가 동일한 인증 구조를 공유할 수 있다. 단, 팀원 모두 동일한 alias 설정이 필요하다.

SSH alias는 poetry add 명령과 pyproject.toml URL에도 동일하게 적용된다.

# 기본 github.com — 어떤 키를 쓸지 불명확, 인증 실패 가능
poetry add "git+ssh://git@github.com/SeegeneDevelopmentPlatform/repo.git@main"

# alias 사용 — seegene_org 키로 명확하게 인증
poetry add "git+ssh://git@seegene_org/SeegeneDevelopmentPlatform/repo.git@main"

pyproject.toml에 기록되는 형태:

[project]
dependencies = [
    "sg-data-standardization @ git+ssh://git@seegene_org/SeegeneDevelopmentPlatform/data_standardization.git@main"
]
중요

pyproject.toml을 다른 팀원이 사용하려면 해당 팀원의 ~/.ssh/config에도 동일한 seegene_org alias가 설정되어 있어야 한다.

10 특정 키를 일회성으로 지정 — GIT_SSH_COMMAND

SSH config를 수정하지 않고 임시로 특정 키만 지정해 git 명령을 실행할 수도 있다. GIT_SSH_COMMAND 환경변수는 일회성 인증, 임시 테스트, CI/CD 등에서 유용하다.

config를 수정하지 않고 임시로 특정 키를 사용하는 방법:

GIT_SSH_COMMAND='ssh -i ~/.ssh/seegene_org -o IdentitiesOnly=yes' \
  git clone git@github.com:org/repo.git
옵션 설명
-i ~/.ssh/seegene_org 사용할 private key 경로
-o IdentitiesOnly=yes 지정한 키만 사용 (ssh-agent 키 무시)

11 최종 ~/.ssh/config 구성 예시

로컬 PC 기준으로 VM 접속과 멀티 GitHub 계정을 모두 포함한 완성된 config 형태다.

# Azure VM 접속
Host ai_agent_dev_vm
    HostName 20.196.196.16
    User azureuser
    Port 22
    IdentityFile ~/.ssh/vm_key.pem

# GitHub 개인 계정
Host github-personal
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_personal

# GitHub 조직/회사 계정
Host github-work
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_work

이 구성에서 각 접속 방식은 아래와 같다:

# VM 접속
ssh ai_agent_dev_vm

# 개인 계정 repo 클론
git clone git@github-personal:username/repo.git

# 조직 계정 repo 클론
git clone git@github-work:org/repo.git

12 SSH 키 생성 및 GitHub 등록 전체 흐름

SSH 키 생성, 공개키 등록, config alias 추가, 인증 테스트까지의 전체 흐름은 실무에서 반복적으로 사용되는 기본 패턴이다.

12.1 Step 1: 키 생성

ed25519 알고리즘을 권장한다. 기존 rsa 방식보다 짧고 보안성이 높다.

ssh-keygen -t ed25519 -C "your@email.com" -f ~/.ssh/id_ed25519_work
옵션 설명
-t ed25519 키 알고리즘 (ed25519 권장)
-C "your@email.com" 키에 붙이는 주석 (GitHub 이메일 사용)
-f 경로 키 파일 저장 경로 (생략 시 기본값 ~/.ssh/id_ed25519)

명령 실행 후 passphrase 입력을 요구한다. 빈칸으로 두면 패스프레이즈 없이 사용할 수 있다 (편의성↑, 보안↓). 실무에서는 설정을 권장한다.

생성 결과:

~/.ssh/id_ed25519_work      ← 개인키 (절대 유출 금지)
~/.ssh/id_ed25519_work.pub  ← 공개키 (GitHub에 등록할 것)
경고

개인키(id_ed25519_work)는 절대 외부에 공유하거나 git에 커밋하지 않는다. 공개키(.pub)만 외부에 등록한다.

키 생성 시 터미널에 아래와 같이 출력된다:

Your identification has been saved in ~/.ssh/id_ed25519_work
Your public key has been saved in ~/.ssh/id_ed25519_work.pub
The key fingerprint is:
SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx your@email.com
The key's randomart image is:
+--[ED25519 256]--+
|        .o+.     |
...
+----[SHA256]-----+

fingerprintrandomart는 따로 저장할 필요 없다. 언제든 재확인할 수 있다:

ssh-keygen -lf ~/.ssh/id_ed25519_work        # fingerprint 재확인
ssh-keygen -lv -f ~/.ssh/id_ed25519_work     # randomart 재확인

12.2 Step 2: GitHub에 공개키 등록

공개키를 클립보드로 복사한다.

Linux/macOS:

cat ~/.ssh/id_ed25519_work.pub
# 출력 내용을 복사

Windows(PowerShell):

cat C:/Users/username/.ssh/id_ed25519_work.pub | clip

GitHub 등록 절차:

  1. GitHub 로그인 → 우측 상단 프로필 아이콘 → Settings
  2. 좌측 메뉴 → SSH and GPG keys
  3. New SSH key 클릭
  4. Title: 키를 구분할 이름 입력 (예: work-laptop-2026)
  5. Key type: Authentication Key (기본값)
  6. Key: 클립보드 붙여넣기
  7. Add SSH key 클릭

12.3 Step 3: ~/.ssh/config에 alias 추가

cat >> ~/.ssh/config << 'EOF'

Host github-work
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_work
EOF

멀티 계정이 아닌 단일 계정이라면 Host github.com으로 그대로 사용하면 된다.

12.4 Step 4: 인증 테스트

ssh -T git@github-work

처음 접속 시 known_hosts 추가 여부를 묻는다. yes를 입력한다:

The authenticity of host 'github.com (140.82.121.4)' can't be established.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes

인증 성공 시 출력:

Hi kmink3225! You've successfully authenticated,
but GitHub does not provide shell access.
노트

but GitHub does not provide shell access.는 오류가 아니라 정상이다. GitHub SSH는 shell 접속이 아닌 git 명령만 허용하기 때문이다.

12.5 최종 ~/.ssh/ 디렉토리 상태

~/.ssh/
├── config                    ← Host alias 설정 파일
├── id_ed25519_work           ← 조직 계정 개인키
├── id_ed25519_work.pub       ← 조직 계정 공개키
├── id_ed25519_personal       ← 개인 계정 개인키 (멀티 계정 시)
├── id_ed25519_personal.pub   ← 개인 계정 공개키 (멀티 계정 시)
├── known_hosts               ← 신뢰한 서버 목록 (자동 생성)
└── vm_key.pem                ← Azure VM 접속용 개인키 (있는 경우)

13 요약

항목 내용
SSH 키 핵심 원칙 접속을 시작하는 주체에 개인키가 있어야 한다
기본 git@github.com 실패 원인 여러 키 중 어떤 키를 써야 할지 특정 불가
해결 방법 ~/.ssh/config에 Host alias 정의
alias 형식 (git) git@alias_name:org/repo.git
alias 형식 (Poetry) git+ssh://git@alias_name/org/repo.git@branch
VM에 키가 필요한 경우 VM이 GitHub, 다른 VM 등 외부에 능동적으로 접속할 때
CI/CD 배포 키 범용 개인키 대신 전용 배포 키를 별도 생성해 Secrets에 등록
팀 공유 시 주의 모든 팀원이 동일한 alias 설정 필요

다음 블로그에서는 pyproject.toml이 없는 repo를 패키지화하기 위해 setuptools 설정 파일을 작성하고 PR로 반영하는 과정을 다룬다.

Subscribe

Enjoy this blog? Get notified of new posts by email: