티스토리 뷰

반응형

Laravel/ PHP 사이트 기준 예시를 중심으로 하지만, 다른 스택에도 같은 흐름으로 적용하면 됩니다.

아래는 전체 흐름(요약) → 서버 준비 → GitHub(Secrets) 준비 → 실제 GitHub Actions 워크플로우(예제) → 보안/운영 팁 → 문제 해결 체크리스트 순서입니다.

1) 전체 흐름 요약

  1. 서버에 deploy 전용 사용자와 SSH 공개키 설정
  2. 로컬(또는 CI용)에서 SSH 개인키를 GitHub Actions Secrets에 등록
  3. .github/workflows/deploy.yml 파일을 만들어 main 브랜치에 푸시되면 실행되도록 설정
  4. Actions가 SSH로 서버에 접속 → 코드 동기화(rsync 또는 scp) → 원격에서 의존성 설치/마이그레이션/캐시/서비스 재시작 수행

2) 서버(우분투 계정) 준비 (권장)

아래 명령은 루트 권한으로 실행합니다(또는 sudo 앞에 붙이세요).

 
# 1) deploy 전용 사용자 생성 (비밀번호 로그인 비활성 권장) sudo adduser --disabled-password --gecos "" deploy # 2) 필요한 패키지 설치 sudo apt update sudo apt install -y openssh-server rsync git unzip # 3) 앱 디렉터리 만들기 및 소유권 설정 (예: /var/www/myapp) sudo mkdir -p /var/www/myapp sudo chown -R deploy:deploy /var/www/myapp

SSH 접속 보안

  • 서버에 공개키를 추가할 때 deploy 사용자의 ~/.ssh/authorized_keys에 public key를 넣습니다.
  • /etc/ssh/sshd_config 에서 PasswordAuthentication no 로 변경(단, 키로 로그인 가능한지 확인 후 재시작).
  • 포트(22) 변경, 방화벽 설정(UFW 또는 cloud security group) 권장.

(선택) deploy에게 서비스 재시작 권한만 부여
sudoers로 제한된 명령만 허용하면 안전합니다:

 
# 예: /etc/sudoers.d/deploy deploy ALL=(ALL) NOPASSWD: /bin/systemctl restart nginx, /bin/systemctl reload nginx, /bin/systemctl restart php*-fpm

3) SSH 키 생성 및 GitHub Secrets 등록

SSH 키 생성 (로컬 또는 CI 환경에서)

 
# 로컬에서 (파일명은 예시) ssh-keygen -t ed25519 -C "github-actions@yourproject" -f ./gh_deploy_key # 생성하면 gh_deploy_key (private) / gh_deploy_key.pub (public) 생성
  • gh_deploy_key.pub의 내용을 서버 deploy 계정의 ~/.ssh/authorized_keys 에 추가.
  •  
    # 서버에서 (deploy 계정으로) mkdir -p ~/.ssh && chmod 700 ~/.ssh echo "<PUBLIC_KEY_CONTENT>" >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys chown -R deploy:deploy ~/.ssh
  • gh_deploy_key(비밀키) 파일 내용을 GitHub 리포지토리 → Settings > Secrets and variables > Actions 에 새 Secret으로 등록
    • 이름 예시: SSH_PRIVATE_KEY
    • 추가로 아래도 Secrets로 등록:
      • SERVER_HOST (예: 1.2.3.4 또는 example.com)
      • SERVER_USER (예: deploy)
      • SERVER_PORT (옵션, 기본 22)
      • TARGET_DIR (예: /var/www/myapp)
      • (필요 시) BRANCH (예: main)

4) GitHub Actions 워크플로우 예제

아래 파일을 ./github/workflows/deploy.yml 로 저장하세요. (Laravel 예시 — 필요 시 명령을 본인 스택에 맞게 수정)

 
name: CI/CD Deploy to Server on: push: branches: - main # main 브랜치로 merge/push 될 때 배포 jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Install rsync (ensure available) run: sudo apt-get update && sudo apt-get install -y rsync # SSH 키를 에이전트에 올리기 - name: Start ssh-agent and add key uses: webfactory/ssh-agent@v0.5.4 with: ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} - name: Add server to known_hosts run: | mkdir -p ~/.ssh ssh-keyscan -p ${{ secrets.SERVER_PORT || 22 }} ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts # (옵션) 빌드/테스트 단계 수행 (ex. npm build, phpunit 등) - name: Build (optional) run: | # 예: npm install && npm run build echo "빌드가 필요하면 여기에 추가하세요" # 파일 동기화 (rsync) - name: Sync files to server run: | rsync -avz --delete \ --exclude='.git' \ --exclude='node_modules' \ --exclude='vendor' \ --exclude='storage' \ ./ ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:${{ secrets.TARGET_DIR }} # 원격에서 의존성 설치, 마이그레이션, 캐시 등 실행 - name: Run remote deployment commands run: | ssh -p ${{ secrets.SERVER_PORT || 22 }} ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }} << 'EOF' set -e cd ${{ secrets.TARGET_DIR }} # 권한 설정 (옵션) chown -R deploy:www-data . # composer 설치(앱이 PHP/Laravel일 경우) if [ -f composer.json ]; then composer install --no-dev --optimize-autoloader --no-interaction fi # Laravel specific (필요하면) if [ -f artisan ]; then php artisan migrate --force php artisan config:cache php artisan route:cache php artisan view:cache fi # 서비스 재시작 (sudoers에서 허용된 명령만) sudo systemctl reload nginx || true sudo systemctl restart php8.1-fpm || true EOF

주의:

  • rsync 명령의 --exclude 를 환경에 맞게 조정하세요. vendor를 제외했으므로 서버에서 composer install을 돌리도록 했습니다(더 안전).
  • sudo 명령 사용 시 deploy 사용자에게 관련 시스템 서비스 재시작 명령을 NOPASSWD로 허용해야 합니다(앞서 설명).
  • webfactory/ssh-agent는 private key를 ssh-agent에 등록해 SSH 연결을 가능하게 합니다.

5) 대체 방법 (짧게)

  • Bare repository + post-receive hook (서버에서 Git으로 직접 pull 트리거): GitHub에서 webhook을 서버로 보내면 서버 hook에서 git --work-tree=/var/www/myapp --git-dir=/home/git/repo.git checkout -f 등으로 배포. (작업은 서버 측에서 모든 처리)
  • Self-hosted runner: 서버에 GitHub Actions runner를 설치하면 액션을 서버에서 직접 실행(보안/네트워크 요구사항 고려). 장점: 네트워크 제한 내부망 배포에 유리.
  • Container / Docker 방식: Actions에서 이미지를 빌드하고 레지스트리에 push → 서버에서 docker pull & restart로 배포(Blue/Green 또는 컨테이너 오케스트레이션 필요 시).

6) 보안 권장사항

  • 배포용 SSH 키는 오직 배포용 계정에만 사용 (개인 계정 키와 분리).
  • GitHub Secrets는 repo 권한이 있는 사람만 접근 가능. 정기적으로 키 회전.
  • deploy 사용자는 가능한 최소 권한만 부여(특정 systemctl 명령만 허용).
  • 서버에서 패스워드 인증 비활성화(키 기반만 허용).
  • 방화벽(포트 제한), Fail2ban 등 적용.

7) 트러블슈팅 체크리스트

  • Permission denied (publickey) → GitHub secret의 private key가 올바른지, 서버에 public key가 붙어있는지 확인.
  • Host key verification failed → ssh-keyscan으로 known_hosts 추가 or 수동으로 등록.
  • 파일 소유권 문제 → chown -R www-data:www-data 등으로 권한 조정.
  • composer 가 없거나 메모리 부족 → 서버에 composer 설치 / swap 추가.
  • rsync 동기화 실패 → 경로 권한, 포트 확인, 방화벽 확인.
반응형

'laravel' 카테고리의 다른 글

추천 알리고리즘  (0) 2025.10.13
Laravel Accessor 호출 방식  (0) 2025.10.10
Git 연결 세팅  (0) 2025.10.10
laravel 프로젝트 생성시 Base table or view not found  (0) 2025.10.08
Storage 심볼릭 링크 설정  (0) 2025.10.08
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2026/05   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함
반응형