GitHub Actions 통합

Alpacon의 전용 GitHub Actions로 배포와 서버 관리를 자동화하세요.

사용 가능한 액션

Alpacon은 CI/CD 워크플로를 위한 4가지 GitHub Actions를 제공합니다:

액션용도사용 사례
alpacon-setup-actionAlpacon CLI 설치항상 먼저 실행
alpacon-websh-action원격 명령 실행앱 배포, 서비스 재시작
alpacon-cp-action파일 전송빌드 업로드, 로그 다운로드
alpacon-common-action모든 Alpacon 명령 실행서버 목록 조회, 상태 확인

전체 입력값 정보는 Actions 레퍼런스를 참고하세요.

빠른 시작

1. 서비스 토큰 생성

CI와 자동화는 서비스 토큰으로 동작합니다. 서비스 토큰은 사람이 아니라 Application에 속하기 때문에 담당자가 바뀌어도 그대로 유지되며, 파이프라인이 무엇까지 할 수 있는지는 ACL이 정확히 정합니다.

  1. IAM → Applications에서 이 파이프라인이 속한 Application을 열거나 새로 생성
  2. 자격 증명 탭에서 추가 클릭
  3. 토큰 이름과 접근 범위 지정, 필요한 사유 작성
  4. 표시된 키 복사(alpst-로 시작하며 한 번만 표시)

CI 범위로 만든 토큰은 검토를 거쳐야 동작합니다. 요청은 대기중(pending) 상태로 생성되고 승인 권한이 있는 사람이 활성화하기 전까지는 어디에도 인증되지 않습니다. 파이프라인 도중에 발견하지 않도록 이 단계를 미리 감안하세요.

2. ACL 규칙 추가

새 서비스 토큰은 ACL 규칙을 추가하기 전까지 아무 곳에도 닿지 못합니다. 서버, 명령, 파일 경로가 각각 기본 거부이므로 규칙이 하나도 없는 토큰은 어디서든 거부됩니다.

토큰을 열고 ACL 탭에서 다음을 추가하세요.

규칙제한 대상
Server ACL파이프라인이 접근할 수 있는 서버
Command ACL실행할 수 있는 명령. 예: git pull, npm install, pm2 restart app
File ACL업로드하거나 내려받을 수 있는 경로

파일 전송은 서버 규칙을 먼저 확인한 다음 파일 규칙을 확인합니다. ACL 탭을 건너뛰면 워크플로는 첫 명령에서 실패합니다.

3. GitHub에 시크릿 추가

리포지토리에 다음 시크릿을 추가하세요 (Settings → Secrets → Actions):

ALPACON_WORKSPACE_URL: https://your-workspace.ap1.alpacon.io
ALPACON_SERVICE_TOKEN: alpst-your-token-here

액션 입력값 이름은 api-token이며 서비스 토큰을 그대로 받습니다. 이미 배포된 워크플로와의 호환을 위해 이름은 그대로 둡니다.

4. 워크플로에서 사용

name: Deploy with Alpacon
on:
  push:
    branches: [main]
 
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
 
      - name: Setup Alpacon CLI
        uses: alpacax/alpacon-setup-action@v1
 
      - name: Deploy to production
        uses: alpacax/alpacon-websh-action@v1
        with:
          workspace-url: ${{ secrets.ALPACON_WORKSPACE_URL }}
          api-token: ${{ secrets.ALPACON_SERVICE_TOKEN }}
          target: 'prod-server'
          script: |
            cd /opt/myapp
            git pull
            npm install
            pm2 restart app

대안: Alpacon CLI 컨테이너 사용

사전 제작된 액션 대신 Alpacon CLI를 직접 사용하려면 공식 Docker 컨테이너를 사용할 수 있습니다.

이 방식에서는 CLI가 URL이 아니라 워크스페이스 이름과 리전으로 Alpacon Cloud에 로그인하므로 시크릿 두 개를 더 추가합니다:

ALPACON_WORKSPACE: your-workspace
ALPACON_REGION: ap1

ALPACON_WORKSPACE_URL은 네 가지 액션의 workspace-url 입력값으로 그대로 쓰이므로 남겨 두고, ALPACON_SERVICE_TOKEN은 두 방식이 함께 사용합니다.

name: Deploy with Alpacon CLI
on:
  push:
    branches: [main]
 
jobs:
  deploy:
    runs-on: ubuntu-latest
    container:
      image: alpacax/alpacon-cli:latest
 
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
 
      - name: Login to Alpacon
        run: alpacon login --workspace ${{ secrets.ALPACON_WORKSPACE }} --region ${{ secrets.ALPACON_REGION }} -t ${{ secrets.ALPACON_SERVICE_TOKEN }}
 
      - name: Deploy to production
        run: |
          alpacon websh prod-server "cd /opt/myapp && git pull && npm install && pm2 restart app"
 
      - name: Upload build artifacts
        run: |
          alpacon cp -r ./dist/ prod-server:/var/www/app/

이 방식은 최소한의 설정으로 CLI에 직접 접근할 수 있으며, 여러 CLI 명령이 필요한 복잡한 워크플로에 유용합니다.

사용 예제

아래 모든 예제는 이전 단계에서 alpacon-setup-action이 이미 실행되었다고 가정합니다. 전체 워크플로는 빠른 시작 섹션을 참고하세요.

root 권한으로 명령 실행

- name: Restart nginx
  uses: alpacax/alpacon-websh-action@v1
  with:
    workspace-url: ${{ secrets.ALPACON_WORKSPACE_URL }}
    api-token: ${{ secrets.ALPACON_SERVICE_TOKEN }}
    target: 'web-server'
    username: 'root'
    script: systemctl restart nginx

특정 사용자로 명령 실행

- name: Deploy as ubuntu user
  uses: alpacax/alpacon-websh-action@v1
  with:
    workspace-url: ${{ secrets.ALPACON_WORKSPACE_URL }}
    api-token: ${{ secrets.ALPACON_SERVICE_TOKEN }}
    target: 'web-server'
    username: 'ubuntu'
    script: |
      cd /home/ubuntu/app
      git pull
      npm install

특정 사용자와 그룹으로 명령 실행

- name: Deploy with www-data group
  uses: alpacax/alpacon-websh-action@v1
  with:
    workspace-url: ${{ secrets.ALPACON_WORKSPACE_URL }}
    api-token: ${{ secrets.ALPACON_SERVICE_TOKEN }}
    target: 'web-server'
    username: 'ubuntu'
    groupname: 'www-data'
    script: cp -r /tmp/build/* /var/www/html/

환경 변수 전달

- name: Deploy with environment variables
  uses: alpacax/alpacon-websh-action@v1
  with:
    workspace-url: ${{ secrets.ALPACON_WORKSPACE_URL }}
    api-token: ${{ secrets.ALPACON_SERVICE_TOKEN }}
    target: 'prod-server'
    env: |
      APP_ENV=production
      DB_HOST=localhost
    script: |
      echo "Deploying to $APP_ENV"
      systemctl restart myapp

빌드 산출물 업로드

- name: Build application
  run: npm run build
 
- name: Upload build to server
  uses: alpacax/alpacon-cp-action@v1
  with:
    workspace-url: ${{ secrets.ALPACON_WORKSPACE_URL }}
    api-token: ${{ secrets.ALPACON_SERVICE_TOKEN }}
    source: './dist/'
    target-server: 'prod-server'
    target-path: '/var/www/app/'
    recursive: true

다중 파일 업로드

- name: Upload config files
  uses: alpacax/alpacon-cp-action@v1
  with:
    workspace-url: ${{ secrets.ALPACON_WORKSPACE_URL }}
    api-token: ${{ secrets.ALPACON_SERVICE_TOKEN }}
    source: |
      ./docker-compose.yml
      ./nginx.conf
      ./.env.production
    target-server: 'prod-server'
    target-path: '/opt/myapp/'

로그 다운로드

- name: Download error logs
  uses: alpacax/alpacon-cp-action@v1
  with:
    workspace-url: ${{ secrets.ALPACON_WORKSPACE_URL }}
    api-token: ${{ secrets.ALPACON_SERVICE_TOKEN }}
    source: '/var/log/app/error.log'
    target-server: 'prod-server'
    target-path: './logs/'
    mode: download
 
- name: Upload logs as artifact
  uses: actions/upload-artifact@v4
  with:
    name: error-logs
    path: ./logs/

다중 서버 배포

jobs:
  deploy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        server: [web1, web2, web3]
    steps:
      - uses: actions/checkout@v4
 
      - name: Setup Alpacon CLI
        uses: alpacax/alpacon-setup-action@v1
 
      - name: Deploy to ${{ matrix.server }}
        uses: alpacax/alpacon-websh-action@v1
        with:
          workspace-url: ${{ secrets.ALPACON_WORKSPACE_URL }}
          api-token: ${{ secrets.ALPACON_SERVICE_TOKEN }}
          target: ${{ matrix.server }}
          script: |
            cd /opt/myapp
            git pull
            npm install
            pm2 restart app

모든 Alpacon 명령 실행

- name: List all servers
  uses: alpacax/alpacon-common-action@v1
  with:
    workspace-url: ${{ secrets.ALPACON_WORKSPACE_URL }}
    api-token: ${{ secrets.ALPACON_SERVICE_TOKEN }}
    command: "server ls"

환경별 Docker 배포

동적 서버 선택을 통해 다양한 환경에 컨테이너화된 애플리케이션을 배포합니다:

name: Deploy Application
 
on:
  workflow_dispatch:
    inputs:
      env:
        description: "Deployment environment"
        required: true
        type: choice
        options:
          - dev
          - prod
 
jobs:
  deploy:
    runs-on: ubuntu-latest
 
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
 
      - name: Select target server
        run: |
          if [ "${{ inputs.env }}" = "prod" ]; then
            echo "TARGET_SERVER=prod-server" >> $GITHUB_ENV
            echo "APP_PORT=8080" >> $GITHUB_ENV
          else
            echo "TARGET_SERVER=dev-server" >> $GITHUB_ENV
            echo "APP_PORT=8081" >> $GITHUB_ENV
          fi
 
      - name: Prepare environment file
        run: |
          echo "APP_ENV=${{ inputs.env }}" > /tmp/.env
          echo "APP_PORT=${{ env.APP_PORT }}" >> /tmp/.env
          echo '${{ secrets.APP_SECRETS }}' >> /tmp/.env
 
      - name: Setup Alpacon CLI
        uses: alpacax/alpacon-setup-action@v1
 
      - name: Docker login on target server
        uses: alpacax/alpacon-websh-action@v1
        with:
          workspace-url: ${{ secrets.ALPACON_WORKSPACE_URL }}
          api-token: ${{ secrets.ALPACON_SERVICE_TOKEN }}
          target: ${{ env.TARGET_SERVER }}
          script: docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
 
      - name: Copy docker-compose.yml
        uses: alpacax/alpacon-cp-action@v1
        with:
          workspace-url: ${{ secrets.ALPACON_WORKSPACE_URL }}
          api-token: ${{ secrets.ALPACON_SERVICE_TOKEN }}
          source: ./docker-compose.yml
          target-server: ${{ env.TARGET_SERVER }}
          target-path: /opt/myapp/docker-compose.yml
 
      - name: Copy environment file
        uses: alpacax/alpacon-cp-action@v1
        with:
          workspace-url: ${{ secrets.ALPACON_WORKSPACE_URL }}
          api-token: ${{ secrets.ALPACON_SERVICE_TOKEN }}
          source: /tmp/.env
          target-server: ${{ env.TARGET_SERVER }}
          target-path: /opt/myapp/.env
 
      - name: Deploy application
        uses: alpacax/alpacon-websh-action@v1
        with:
          workspace-url: ${{ secrets.ALPACON_WORKSPACE_URL }}
          api-token: ${{ secrets.ALPACON_SERVICE_TOKEN }}
          target: ${{ env.TARGET_SERVER }}
          script: |
            docker compose -f /opt/myapp/docker-compose.yml pull
            docker compose -f /opt/myapp/docker-compose.yml --env-file /opt/myapp/.env up -d
            docker compose -f /opt/myapp/docker-compose.yml ps

모범 사례

  • CI/CD 전용 서비스 토큰을 최소 권한으로 발급
  • 토큰이 실행할 수 있는 명령은 Command ACL로 제한
  • 토큰은 시크릿으로 저장하고 리포지토리에는 커밋 금지
  • 워크스페이스에서 토큰을 정기적으로 교체한 뒤 GitHub 시크릿 갱신
  • 여러 리포지토리가 공유하는 토큰에는 조직 시크릿 사용
  • 모든 명령은 워크스페이스 감사 로그에 기록되며 민감한 값은 자동 마스킹

리소스

다음 단계

최종 수정: