GitLab CI/CD를 위한 SSH Key 생성 및 배포 환경 구성

GitLab CI/CD를 위한 SSH Key 생성 및 배포 환경 구성

주요 내용

GitLab CI/CD를 위한 SSH Key 생성 및 배포 환경 구성

진행중인 프로젝트에서 어플리케이션 아키택터 요청으로 CI/CD 를 위한 배포 환경 구성을 위해 SSH Key 를 통한 배포 환경을 구성해 보았습니다. 현대적인 DevOps 환경에서 수동 배포는 더 이상 선택지가 아닙니다. 특히 보안이 강조되는 배포 프로세스에서 비밀번호 없는 인증(Passwordless Authentication)은 필수적인 요소입니다.

오늘 포스팅에서는 GitLab Runner(도커 기반)를 활용하여 개발(Dev), QA, 운영(Prod) 서버에 안전하게 접속하고 코드를 배포하기 위한 SSH Key 관리 및 환경 구성 전략을 상세히 알아보겠습니다.

GitLab CI/CD를 위한 SSH Key 생성 및 배포 환경 구성
GitLab CI/CD를 위한 SSH Key 생성 및 배포 환경 구성

왜 SSH Key 방식의 배포인가?

일반적으로 서버 접속 시 비밀번호를 사용하면 무차별 대입 공격(Brute-force)에 노출될 위험이 큽니다. 반면, SSH 키 쌍(Public/Private Key)을 이용하면 다음과 같은 이점이 있습니다.

  • 보안성 강화: 물리적인 키 파일 없이는 서버 접속이 불가능합니다.
  • 자동화 용이: CI/CD 파이프라인 실행 시 사용자 개입 없이 안전하게 인증할 수 있습니다.
  • 중앙 관리: GitLab의 CI/CD Variables 기능을 활용해 서버에 키 파일을 직접 저장하지 않고도 배포 경로를 제어할 수 있습니다.

배포용 SSH 키 쌍 생성하기

먼저 GitLab Runner가 사용할 SSH 키를 생성해야 합니다. 보안을 위해 Ed25519 알고리즘 사용을 권장합니다.

Bash

# 특정 환경을 위한 키 생성 (예: gitlab-deploy)
ssh-keygen -t ed25519 -C "gitlab-ci-deployment" -f ~/.ssh/id_ed25519_gitlab
  • Private Key: GitLab의 CI/CD 변수에 저장합니다. (절대 외부에 노출 금지)
  • Public Key: 배포 대상 서버(Dev, QA, Prod)의 ~/.ssh/authorized_keys에 등록합니다.

환경별 배포 전략 (Dev, QA, Prod 분리)

보안과 안정성을 위해 각 환경은 물리적 또는 논리적으로 분리되어야 합니다. GitLab의 Environments 기능을 활용하면 효율적입니다.

3.1 서버측 설정 (Public Key 등록)

배포 대상 서버에 접속하여 생성한 공개키를 등록합니다.

Bash

echo "ssh-ed25519 AAAAC3Nza..." >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

3.2 GitLab CI/CD Variables 설정

GitLab 프로젝트의 Settings > CI/CD > Variables 메뉴에서 다음 변수들을 등록합니다.

변수명설명보안 설정
SSH_PRIVATE_KEY생성한 Private Key 내용 전체Masked & Protected
SERVER_IP_DEV개발 서버 IP 주소
SERVER_IP_PROD운영 서버 IP 주소

.gitlab-ci.yml 구성 예시

도커 기반의 GitLab Runner에서 SSH 에이전트를 실행하고 키를 주입하는 과정입니다.

YAML

before_script:
  - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
  - eval $(ssh-agent -s)
  - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
  - mkdir -p ~/.ssh
  - chmod 700 ~/.ssh
  - ssh-keyscan $SERVER_IP >> ~/.ssh/known_hosts

deploy_prod:
  stage: deploy
  script:
    - ssh root@$SERVER_IP_PROD "cd /var/www/app && git pull origin main && docker-compose up -d"
  only:
    - main
  environment:
    name: production

GitLab CI/CD 배포 아키텍처 가이드: 안전한 자동화 흐름 구축하기

효율적인 소프트웨어 개발 생태계에서 배포 자동화는 필수적입니다. 하지만 단순히 코드를 서버에 옮기는 것을 넘어, 어떤 구조로 데이터가 흐르고 보안을 어떻게 유지할 것인지에 대한 설계가 선행되어야 합니다. 이번 포스팅에서는 GitLab CI/CD를 활용한 표준 배포 아키텍처와 논리적 흐름을 상세히 살펴보겠습니다.

배포 아키텍처의 핵심 구성 요소

안정적인 배포 환경을 구축하기 위해서는 역할을 명확히 분리해야 합니다. 본 가이드에서 제안하는 아키텍처는 크게 세 가지 계층으로 나뉩니다.

1.1 GitLab Server: 관리 및 보안의 중심

GitLab 서버는 단순히 소스 코드를 저장하는 곳이 아닙니다. 배포 프로세스의 두뇌 역할을 하며 다음과 같은 핵심 데이터를 관리합니다.

  • 소스 코드 관리: 모든 버전의 코드를 안전하게 보관합니다.
  • CI/CD 변수 보관: 서버 접속에 필요한 SSH 개인키(Private Key)와 같은 민감 정보를 GitLab 내부의 보안 변수(Variables) 기능을 통해 암호화하여 저장합니다.

1.2 GitLab Runner (Docker 기반): 독립된 실행기

실질적인 배포 명령을 수행하는 주체입니다. 도커 컨테이너 환경에서 동작하는 Runner를 사용하면 다음과 같은 장점이 있습니다.

  • 일관성 유지: 매 배포마다 깨끗한 환경에서 작업이 시작됩니다.
  • 보안성: 배포가 시작되는 시점에만 GitLab 서버로부터 개인키를 메모리에 로드하며, 배포 작업이 종료되면 해당 컨테이너와 함께 메모리 데이터도 소멸됩니다. 이는 물리 서버에 키 파일을 상시 저장하는 것보다 훨씬 안전합니다.

1.3 Target Servers (Web/WAS): 최종 배포 대상

코드가 실행될 실제 서버입니다. 보안 강화를 위해 root 계정이 아닌 webadmin과 같은 일반 계정을 사용하여 배포를 수행하는 것을 권장합니다. 이는 배포 프로세스에서 발생할 수 있는 실수나 해킹 공격으로부터 시스템 핵심 영역을 보호하는 최소 권한 원칙(Principle of Least Privilege)을 준수하기 위함입니다.

데이터와 배포의 논리적 흐름

배포가 시작되면 코드는 다음과 같은 흐름을 거쳐 사용자에게 전달됩니다.

  1. 코드 푸시 및 파이프라인 트리거: 개발자가 main 또는 배포 브랜치에 코드를 푸시하면 GitLab CI/CD 파이프라인이 자동으로 실행됩니다.
  2. 환경 변수 주입: GitLab 서버는 설정된 배포 대상(Dev, QA, Prod)에 맞는 SSH 개인키와 IP 정보를 GitLab Runner 컨테이너에 전달합니다.
  3. 인증 및 접속: Runner는 전달받은 개인키를 메모리에 올리고, 배포 대상 서버의 webadmin 계정으로 SSH 접속을 시도합니다. 이때 서버의 authorized_keys에 등록된 공개키를 통해 인증이 완료됩니다.
  4. 명령 수행: 인증이 완료되면 Runner는 서버에서 코드 풀(Pull), 빌드, 서비스 재시작(예: Docker Compose Up) 등의 명령을 원격으로 실행합니다.
  5. 배포 완료 및 흔적 제거: 배포 성공 후 Runner 컨테이너가 종료되며 메모리에 있던 모든 임시 보안 데이터는 자동으로 삭제됩니다.

보안 강화를 위한 체크리스트

성공적인 아키텍처 구성을 위해 다음 사항을 반드시 점검하세요.

  • Masked Variables 설정: GitLab 변수 설정 시 로그에 키 값이 노출되지 않도록 Mask 기능을 활성화해야 합니다.
  • 계정 권한 제한: 배포 계정인 webadmin은 서비스 구동에 필요한 디렉토리에만 쓰기 권한을 가져야 합니다.
  • 방화벽 설정: 배포 대상 서버의 SSH 포트(22번 등)는 GitLab Runner의 IP 주소에 대해서만 접근을 허용하는 것이 좋습니다.
문제 해결 방법
문제 해결 방법

GitLab CI/CD SSH 접속 시 패스워드를 계속 물어본다면? 트러블슈팅 가이드

GitLab CI/CD를 활용해 자동화 배포 환경을 구축하다 보면, 분명히 SSH 키를 등록했음에도 불구하고 파이프라인 로그에서 패스워드를 요구하며 멈춰버리는 현상을 마주할 때가 있습니다. 자동화 배포에서 사용자 개입이 필요한 패스워드 입력 요구는 곧 배포 실패를 의미합니다.

오늘은 SSH 키 인증 대신 패스워드 입력을 요구하는 대표적인 원인 3가지와 그 해결 방법을 상세히 알아보겠습니다.

1. 서버 디렉토리 및 파일 권한 불량 점검

SSH 인증 시스템은 보안을 최우선으로 하기 때문에, 키 파일이나 관련 디렉토리의 권한이 지나치게 개방되어 있으면 보안 위협으로 간주하고 해당 키를 무시해 버립니다. 이 경우 시스템은 차선책으로 패스워드 인증을 시도하게 됩니다.

가장 먼저 배포 대상 서버에 접속하여 다음 권한들을 확인하십시오.

유저 홈 디렉토리 권한

webadmin 계정의 홈 디렉토리는 그룹이나 타인에게 쓰기 권한이 있어서는 안 됩니다.

  • 권한 확인: ls -ld /home/webadmin
  • 권한 설정: chmod 755 /home/webadmin (또는 700)

.ssh 디렉토리 및 인증키 권한

실제 키가 저장된 디렉토리와 파일 권한은 더욱 엄격해야 합니다.

  • .ssh 디렉토리: 700 (drwx——)이어야 합니다.
  • authorized_keys 파일: 600 (-rw——-)이어야 합니다.

만약 권한이 틀리다면 아래 명령어로 수정하세요.

Bash

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

2. 키 쌍(Key Pair) 일치 여부 및 경로 확인

두 번째로 점검할 항목은 현재 사용 중인 개인키와 서버에 등록된 공개키가 실제로 한 쌍인지 확인하는 것입니다.

키 쌍 불일치 문제

로컬 환경이나 GitLab CI/CD Variables에 저장된 개인키가 서버의 authorized_keys에 등록된 공개키와 매칭되지 않으면 인증은 실패합니다. 키를 생성할 때 여러 개를 생성했다면 혼동이 생기지 않았는지 다시 확인해야 합니다.

정확한 키 경로 지정

여러 개의 SSH 키를 관리하는 경우, SSH 클라이언트가 엉뚱한 키를 사용하고 있을 수 있습니다. 배포 스크립트에서 명시적으로 -i 옵션을 사용하여 개인키 경로를 지정했는지 확인하십시오.

  • 예시 명령어: ssh -i ~/id_ed25519_prod webadmin@server_ip

GitLab CI/CD 환경이라면 변수에 저장된 키가 파일로 정상적으로 생성되어 해당 경로를 가리키고 있는지 로그를 통해 검토해야 합니다.

3. SSH 서버 설정(sshd_config) 검토

디렉토리 권한과 키 쌍에 문제가 없다면, 배포 대상 서버 자체의 SSH 설정에서 키 인증이 비활성화되어 있을 가능성이 있습니다.

PubkeyAuthentication 옵션 확인

서버의 SSH 설정 파일인 /etc/ssh/sshd_config를 열어 다음 항목이 주석 처리되어 있거나 no로 되어 있는지 확인하십시오.

  • 설정 확인: PubkeyAuthentication yes

SSH 서비스 재시작

설정을 변경했다면 반드시 SSH 서비스를 재시작해야 변경 사항이 적용됩니다.

Bash

sudo systemctl restart sshd

워드프레스 블로그 운영과 구글 검색 최적화(SEO)를 고려하여, 결론 및 권장사항을 중심으로 한 전문적인 기술 포스팅을 작성해 드립니다. 요청하신 대로 강조 기호()는 모두 제거했습니다.

GitLab CI/CD 배포 보안의 완성: 결론 및 핵심 권장사항 가이드

성공적인 GitLab CI/CD 파이프라인 구축은 단순히 코드를 자동으로 배포하는 것에 그치지 않습니다. 진정한 자동화의 가치는 보안이 전제될 때 발휘됩니다. 지금까지 살펴본 SSH 키 설정과 환경 구성을 바탕으로, 실제 운영 환경에서 반드시 지켜야 할 보안 원칙과 관리 권장사항을 정리해 보겠습니다.

1. 최소 권한 원칙: 일반 계정 사용의 필수성

많은 개발자가 배포 설정의 편의성을 위해 root 계정을 직접 사용하려는 유혹에 빠지곤 합니다. 하지만 이는 보안 측면에서 매우 위험한 선택입니다.

배포는 반드시 root가 아닌 webadmin이나 deployer 같은 별도의 일반 계정을 생성하여 수행해야 합니다.

일반 계정 사용이 중요한 이유

첫째, 시스템 보호입니다. 만약 배포 스크립트의 실수나 파이프라인 취약점으로 인해 공격자가 침입하더라도, 일반 계정은 시스템 전체를 제어할 수 있는 권한이 없으므로 피해 범위를 최소화할 수 있습니다. 둘째, 책임 소재의 명확화입니다. 서비스 구동에 필요한 파일에만 접근 권한을 부여함으로써 데이터베이스나 시스템 설정 파일이 의도치 않게 수정되는 것을 방지할 수 있습니다.

2. 흔적 제거: 개인키 파일 즉시 폐기

SSH 키 쌍을 생성한 후 가장 간과하기 쉬운 부분이 바로 로컬 PC나 임시 서버에 남은 개인키 파일 관리입니다.

키 유출 차단을 위한 조치

GitLab CI/CD 변수(Variables)에 개인키 등록이 완료되었다면, 해당 키를 생성했던 Runner 서버나 로컬 PC의 .ssh 디렉토리에 있는 개인키 파일은 즉시 삭제해야 합니다.

이미 GitLab의 보안 변수 시스템에 안전하게 저장되었기 때문에 더 이상 로컬에 파일을 남겨둘 이유가 없습니다. 물리적인 파일이 존재하지 않는 것만으로도 잠재적인 키 유출 경로를 원천 차단하는 가장 확실한 방법이 됩니다.

3. 지속적인 보안: SSH 키 정기 갱신 및 관리

보안은 한 번의 설정으로 끝나지 않습니다. 시간이 지남에 따라 관리자의 부주의나 알려지지 않은 취약점으로 인해 키가 노출될 가능성은 항상 존재합니다.

정기 갱신 권장 주기

우리는 최소 1년 단위로 SSH 키를 재생성하여 교체하는 것을 강력히 권장합니다.

  • 갱신 프로세스: 새로운 키 쌍 생성 -> GitLab 변수 업데이트 -> 서버 authorized_keys 교체 순으로 진행합니다.
  • 알고리즘 업데이트: 갱신 시점에 가장 안전하다고 평가받는 알고리즘(현재 기준 Ed25519 등)을 선택하여 최신 보안 표준을 유지하십시오.

정기적인 갱신은 혹시 모를 키 복제 사고로부터 시스템을 보호하는 최후의 방어선이 됩니다.

결론: 안전한 자동화가 비즈니스의 신뢰를 만듭니다

GitLab CI/CD를 통한 배포 자동화는 개발 생산성을 비약적으로 향상시킵니다. 하지만 그 기반이 되는 SSH 인증 체계가 무너진다면 기업의 소중한 자산인 코드가 위협받을 수 있습니다.

오늘 강조한 세 가지 원칙, 즉 일반 계정 사용, 개인키 파일 폐기, 정기적인 키 갱신만 철저히 지켜도 훨씬 견고한 DevOps 환경을 운영할 수 있습니다. 지금 여러분의 배포 파이프라인 설정을 다시 한번 점검해 보시기 바랍니다.

전문가의 인사이트 : 함께 읽어 보세요.

[RHEL 9.6: Nginx – Tomcat 리버스 프록시 구성]

참조 및 출처 URL:

https://docs.gitlab.com/ci/jobs/ssh_keys