GitHub Actions 통합
Alpacon의 전용 GitHub Actions로 배포와 서버 관리를 자동화하세요.
사용 가능한 액션
Alpacon은 CI/CD 워크플로를 위한 4가지 GitHub Actions를 제공합니다:
| 액션 | 용도 | 사용 사례 |
|---|---|---|
| alpacon-setup-action | Alpacon CLI 설치 | 항상 먼저 실행 |
| alpacon-websh-action | 원격 명령 실행 | 앱 배포, 서비스 재시작 |
| alpacon-cp-action | 파일 전송 | 빌드 업로드, 로그 다운로드 |
| alpacon-common-action | 모든 Alpacon 명령 실행 | 서버 목록 조회, 상태 확인 |
전체 입력값 정보는 Actions 레퍼런스를 참고하세요.
빠른 시작
1. 서비스 토큰 생성
CI와 자동화는 서비스 토큰으로 동작합니다. 서비스 토큰은 사람이 아니라 Application에 속하기 때문에 담당자가 바뀌어도 그대로 유지되며, 파이프라인이 무엇까지 할 수 있는지는 ACL이 정확히 정합니다.
토큰 발급 전에 애플리케이션에 서버 계정과 필요한 scope를 허용하는 전역 역할을 부여하세요. 예시의 ci-deploy는 애플리케이션이 소유한 계정으로 바꿔 사용합니다. 이 계정이 배포 디렉터리와 Docker에 접근할 수 있도록 권한을 설정하세요. 서비스 토큰은 root로 실행하거나 대화형 Websh 세션을 열 수 없습니다.
Alpacon Cloud에서는 서비스 토큰의 sudo 위험도가 심각(Critical)보다 낮거나 평가되지 않았으면 허용하고, 심각이면 거부합니다. 단, Advisory 워크스페이스에서는 위험도를 이유로 거부하지 않고 판단을 기록합니다. Advisory가 아니면 워크스페이스의 token_exec 규칙으로 위험도 기준을 더 엄격하게 정할 수 있습니다. 워크스페이스의 sudo 설정도 켜져 있어야 하며, 꺼져 있으면 workspace_sudo_with_mfa_disabled로 거부됩니다. 기본 설정의 자체 호스팅에서는 모든 서비스 토큰 sudo가 거부됩니다. 명령어 규칙은 sudo를 포함한 제출 문자열 전체와 일치해야 합니다. 서비스 토큰을 참고하세요.
- IAM → 애플리케이션에서 이 파이프라인이 속한 Application을 열거나 새로 생성
- 토큰 탭에서 새로 만들기 클릭
- 토큰 이름과 만료 시점 지정, 액세스 템플릿이나 직접 선택으로 권한 지정, 서버·명령어·경로 준비, 검토 단계에서 필요한 사유 작성
- 표시된 키 복사 또는 다운로드(
alpst-로 시작하며 한 번만 표시)
명령어와 파일 전송 scope는 항상 웹 콘솔에서 승인을 기다립니다. ACL을 추가하거나 파이프라인을 시작하기 전에 슈퍼유저나 해당 요청의 승인자에게 승인을 받으세요.
2. ACL 규칙 추가
새 서비스 토큰은 ACL 규칙을 추가하기 전까지 아무 곳에도 닿지 못합니다. 서버, 명령, 파일 경로가 각각 기본 거부이므로 규칙이 하나도 없는 토큰은 어디서든 거부됩니다.
승인 후 토큰의 접근 규칙 탭에서 준비한 규칙을 적용하거나 서버와 파일 규칙을 추가하세요. Alpacon Cloud에서는 명령 ACL 관리자에 등록된 관리자가 같은 탭의 사전 승인된 명령에 명령어를 추가합니다. 이 권한은 워크스페이스 역할과 별개입니다. 자체 호스팅에서는 명령어 ACL을 사용합니다. 다음 접근 범위를 설정하세요.
| 규칙 | 제한 대상 |
|---|---|
| Server ACL | 파이프라인이 접근할 수 있는 서버 |
| 명령어 접근 | 워크플로가 제출하는 명령어 전체. 예: cd /opt/myapp && git pull && npm install && pm2 restart app |
| File 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'
username: 'ci-deploy'
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: ap1ALPACON_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 exec ci-deploy@prod-server "cd /opt/myapp && git pull && npm install && pm2 restart app"
- name: Upload build artifacts
run: |
alpacon cp -r ./dist/ ci-deploy@prod-server:/var/www/app/이 방식은 최소한의 설정으로 CLI에 직접 접근할 수 있으며, 여러 CLI 명령이 필요한 복잡한 워크플로에 유용합니다.
사용 예제
아래 모든 예제는 이전 단계에서
alpacon-setup-action이 이미 실행되었다고 가정합니다. 전체 워크플로는 빠른 시작 섹션을 참고하세요.
sudo로 서비스 재시작
애플리케이션 계정으로 실행하세요. Cloud에서는 워크스페이스에 더 엄격한 규칙이 없으면 심각 미만의 sudo를 허용하며, Advisory에서는 위험도를 이유로 거부하지 않고 판단을 기록합니다. 워크스페이스 sudo 설정이 켜져 있어야 합니다. 기본 설정의 자체 호스팅에서는 거부됩니다. 명령어 규칙은 sudo systemctl restart nginx 전체 문자열과 일치해야 합니다.
- 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: 'ci-deploy'
script: sudo systemctl restart nginx애플리케이션 계정으로 실행
- name: Deploy as the application account
uses: alpacax/alpacon-websh-action@v1
with:
workspace-url: ${{ secrets.ALPACON_WORKSPACE_URL }}
api-token: ${{ secrets.ALPACON_SERVICE_TOKEN }}
target: 'web-server'
username: 'ci-deploy'
script: |
cd /home/ci-deploy/app && git pull && npm install서비스 토큰은 항상 해당 계정의 전용 그룹을 사용합니다.
환경 변수 전달
이 계정으로 시스템 서비스를 재시작하려면 sudo가 필요합니다. 워크스페이스 설정과 명령어 규칙은 sudo로 서비스 재시작을 참고하세요.
- 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'
username: 'ci-deploy'
env: |
APP_ENV=production
DB_HOST=localhost
script: |
echo "Deploying to $APP_ENV"
sudo 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'
username: 'ci-deploy'
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'
username: 'ci-deploy'
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'
username: 'ci-deploy'
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 }}
username: 'ci-deploy'
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
env:
APP_SECRETS: ${{ secrets.APP_SECRETS }}
run: |
echo "APP_ENV=${{ inputs.env }}" > /tmp/.env
echo "APP_PORT=${{ env.APP_PORT }}" >> /tmp/.env
printf '%s' "$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
env:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
with:
workspace-url: ${{ secrets.ALPACON_WORKSPACE_URL }}
api-token: ${{ secrets.ALPACON_SERVICE_TOKEN }}
target: ${{ env.TARGET_SERVER }}
username: 'ci-deploy'
env: |
DOCKER_USERNAME
DOCKER_PASSWORD
script: |
printf '%s\n' "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
- 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 }}
username: 'ci-deploy'
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 }}
username: 'ci-deploy'
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 }}
username: 'ci-deploy'
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 전용 서비스 토큰을 최소 권한으로 발급
- 토큰이 실행할 수 있는 명령어는 Cloud의 사전 승인 명령어나 자체 호스팅의 명령어 ACL로 제한
- 토큰은 시크릿으로 저장하고 리포지토리에는 커밋 금지
- 워크스페이스에서 토큰을 정기적으로 교체한 뒤 GitHub 시크릿 갱신
- 여러 리포지토리가 공유하는 토큰에는 조직 시크릿 사용
- 모든 명령은 워크스페이스 감사 로그에 기록되며 민감한 값은 자동 마스킹
리소스
- Actions 레퍼런스
- Alpacon CLI 문서
- 서비스 토큰
- GitHub Marketplace - Setup Action
- GitHub Marketplace - Websh Action
- GitHub Marketplace - CP Action
- GitHub Marketplace - Common Action