소스 : https://github.com/braverokmc79/nestjs-netflix
1. AWS Elastic Beanstalk 배포
.gihub/workflows/aws-deploy.yml
name: Deploy to AWS Elastic Beanstalk on: push: branches: - main jobs: build-and-deploy: runs-on: nextjs-latest services: postgres: image: postgres:16 env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 5432:5432 steps: - name: Checkout Code uses: actions/checkout@v3 - name: Set Up NodeJS uses: actions/setup-node@v3 with: node-version: '18' - name: Create Env File env: ENV: ${{secrets.ENV}} DB_TYPE: ${{secrets.DB_TYPE}} DB_HOST: ${{secrets.DB_HOST}} DB_PORT: ${{secrets.DB_PORT}} DB_USERNAME: ${{secrets.DB_USERNAME}} DB_PASSWORD: ${{secrets.DB_PASSWORD}} DB_DATABASE: ${{secrets.DB_DATABASE}} HASH_ROUNDS: ${{secrets.HASH_ROUNDS}} ACCESS_TOKEN_SECRET: ${{secrets.ACCESS_TOKEN_SECRET}} REFRESH_TOKEN_SECRET: ${{secrets.REFRESH_TOKEN_SECRET}} AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}} AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}} AWS_REGION: ${{secrets.AWS_REGION}} BUCKET_NAME: ${{secrets.BUCKET_NAME}} run: | touch test.env echo ENV="test" >> test.env echo DB_TYPE="$DB_TYPE" >> test.env echo DB_HOST="localhost" >> test.env echo DB_PORT="$DB_PORT" >> test.env echo DB_USERNAME="$DB_USERNAME" >> test.env echo DB_PASSWORD="$DB_PASSWORD" >> test.env echo DB_DATABASE="$DB_DATABASE" >> test.env echo HASH_ROUNDS="$HASH_ROUNDS" >> test.env echo ACCESS_TOKEN_SECRET="$ACCESS_TOKEN_SECRET" >> test.env echo REFRESH_TOKEN_SECRET="$REFRESH_TOKEN_SECRET" >> test.env echo AWS_ACCESS_KEY_ID="$AWS_ACCESS_KEY_ID" >> test.env echo AWS_SECRET_ACCESS_KEY="$AWS_SECRET_ACCESS_KEY" >> test.env echo AWS_REGION="$AWS_REGION" >> test.env echo BUCKET_NAME="$BUCKET_NAME" >> test.env echo "test.env created" cat test.env touch env.env echo ENV="$ENV" >> .env echo DB_TYPE="$DB_TYPE" >> .env echo DB_HOST="$DB_HOST" >> .env echo DB_PORT="$DB_PORT" >> .env echo DB_USERNAME="$DB_USERNAME" >> .env echo DB_PASSWORD="$DB_PASSWORD" >> .env echo DB_DATABASE="$DB_DATABASE" >> .env echo HASH_ROUNDS="$HASH_ROUNDS" >> .env echo ACCESS_TOKEN_SECRET="$ACCESS_TOKEN_SECRET" >> .env echo REFRESH_TOKEN_SECRET="$REFRESH_TOKEN_SECRET" >> .env echo AWS_ACCESS_KEY_ID="$AWS_ACCESS_KEY_ID" >> .env echo AWS_SECRET_ACCESS_KEY="$AWS_SECRET_ACCESS_KEY" >> .env echo AWS_REGION="$AWS_REGION" >> .env echo BUCKET_NAME="$BUCKET_NAME" >> .env echo ".env created" cat .env - name: Create Folders run: | mkdir -p ./public/movie mkdir -p ./public/temp - name: Install Depencies run: npm i - name: Build Project run: npm run build - name: Run Test run: npm run test - name: Install Typeorm run: npm i -g typeorm - name: Run Migration run: typeorm migration:run -d ./dist/database/data-source.js - name: Zip Artfact For Deployment run: zip -r deploy.zip . - name: Upload To S3 env: AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}} AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}} AWS_REGION: ${{secrets.AWS_REGION}} run: | aws configure set region $AWS_REGION aws s3 cp deploy.zip s3://nestjs-netflix-bucket/deploy.zip - name: Deploy To AWS Elastic Beanstalk env: AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}} AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}} AWS_REGION: ${{secrets.AWS_REGION}} run: | aws elasticbeanstalk create-application-version \ --application-name "nestjs-netflix" \ --version-label $GITHUB_SHA \ --source-bundle S3Bucket="nestjs-netflix-bucket",S3Key="deploy.zip" aws elasticbeanstalk update-environment \ --application-name "nestjs-netflix" \ --environment-name "Nestjs-netflix-env" \ --version-label $GITHUB_SHA
1)이름과 트리거 조건
name: Deploy to AWS Elastic Beanstalk on: push: branches: - main
이름: Deploy to AWS Elastic Beanstalk
트리거 조건: main 브랜치에 push가 발생할 때 워크플로 실행
2)jobs: build-and-deploy
실행 환경
runs-on: nextjs-latest
nextjs 최신 버전에서 워크플로 실행
3) PostgreSQL 서비스 (CI 테스트용)
services: postgres: image: postgres:16 ...
PostgreSQL 16 버전을 도커로 실행
포트: 5432 사용
pg_isready를 통해 DB 헬스 체크 수행
4)1. 코드 체크아웃
- name: Checkout Code uses: actions/checkout@v3
현재 커밋된 코드를 워크플로에 가져옴
5) 2. Node.js 환경 설정
- name: Set Up NodeJS uses: actions/setup-node@v3 with: node-version: '18'
Node.js 18버전 설치
6) 3. .env 파일 생성
- name: Create Env File
CI/CD에 필요한 .env 파일과 test.env 파일을 생성
GitHub Secrets에서 민감한 정보들을 주입
localhost DB로 지정한 것은 CI 환경에서 테스트용 PostgreSQL을 사용하기 위함
7)폴더 생성
- name: Create Folders
./public/movie, ./public/temp 디렉토리 생성
8) 의존성 설치
- name: Install Dependencies run: npm i
9) 프로젝트 빌드
- name: Build Project run: npm run build
프로젝트 빌드 (예: NestJS 빌드)
10) 테스트 실행
- name: Run Test run: npm run test
테스트 코드 실행
11) TypeORM CLI 설치
- name: Install Typeorm run: npm i -g typeorm
전역으로 TypeORM CLI 설치 (마이그레이션 실행을 위해)
12) 마이그레이션 실행
- name: Run Migration run: typeorm migration:run -d ./dist/database/data-source.js
빌드된 data-source.js를 기반으로 DB 마이그레이션 실행
13) 배포용 압축파일 생성
- name: Zip Artifact For Deployment run: zip -r deploy.zip .
현재 프로젝트 전체를 deploy.zip으로 압축
14) S3 업로드
- name: Upload To S3 run: | aws configure set region $AWS_REGION aws s3 cp deploy.zip s3://nestjs-netflix-bucket/deploy.zip
deploy.zip을 S3 버킷에 업로드 (nestjs-netflix-bucket)
15) Elastic Beanstalk 배포
- name: Deploy To AWS Elastic Beanstalk run: | aws elasticbeanstalk create-application-version ... aws elasticbeanstalk update-environment ...
새 어플리케이션 버전 생성 (커밋 SHA를 버전 라벨로 사용)
해당 버전으로 Elastic Beanstalk 환경 업데이트
(환경명: Nestjs-netflix-env, 앱명: nestjs-netflix)
2. 우분트 22 SSH 배포
다음 참조
✅Spring Boot 3.4 애플리케이션을 우분투 22 서버에 GitHub Actions를 사용해 무중단 배포
1) SSH 키 기반 인증 준비
SSH Key 생성 및 서버 등록
1. 로컬에서 SSH 키 생성
여기서 github-actions@our-sample 는 임의 명이다.
github-deploy-key 또한 원하는 이름으로 변경하면된다.
중요한것은 깃허브에서 actions 에서 우분트 22 에 접속할수 있는 개인 키 등록과 우부트 22에 공개 키 설정이다.
PowerShell 사용 시 (경로를 명시적으로 써야 함)
ssh-keygen -t rsa -b 4096 -C "github-actions@our-sample" -f "$env:USERPROFILE\.ssh\github-deploy-key"
Git Bash 사용 시 (추천).
ssh-keygen -t rsa -b 4096 -C "github-actions@our-sample" -f ~/.ssh/github-deploy-key
2. GitHub에 개인 키 등록
github-deploy-key 내용을 복사
GitHub 저장소> 깃허브 해당 프로젝트에서 > Settings > Secrets and variables > Actions > New secret 이름은 예: DEPLOY_KEY 값을 복붙
nextjs 22 서버의 nextjs계정에 SSH 기반 GitHub Actions 배포 설정
우부트 계정이 nextjs라고 할때
✅ 1단계: 로컬에서 SSH 키 생성 (GitHub Actions용)
ssh-keygen -t rsa -b 4096 -C "github-actions@nextjs" -f ~/.ssh/github-nextjs-key
결과:
개인 키: ~/.ssh/github-nextjs-key
공개 키: ~/.ssh/github-nextjs-key.pub
윈도우에 파워셀 명령어로 키 생성 후 우분투 22 에서 공개키 저장 및 깃허브에 개인키 저장, 다음 명령어로 키를 생성한다
ssh-keygen -t rsa -b 4096 -C "github-actions@our-nextjs" -f "$env:USERPROFILE\.ssh\github-nextjs-key"
✅ 2단계: GitHub에 개인 키 등록 (Secrets)
개인 키 내용 복사: nextjs 사용자라면/home/nextjs/.ssh/github-nextjs-key
cat ~/.ssh/github-nextjs-key
GitHub 저장소 → Settings > Secrets and variables > Actions > New secret
이름: DEPLOY_KEY
값: 위에서 복사한 개인 키 전체 내용
❗ 개인 키는 절대 서버에 저장하지 않습니다.
✅ 3단계: 우분투 서버(nextjs 계정)에 공개 키 등록
서버 접속:
ssh nextjs@your.server.ip
.ssh 디렉토리 및 권한 설정:
mkdir -p ~/.ssh chmod 700 ~/.ssh
로컬에서 공개 키 내용 복사:
cat ~/.ssh/github-nextjs-key.pub
서버에 공개 키 붙여넣기:
echo "<복사한 공개 키 내용>" >> ~/.ssh/authorized_keys cat ~/.ssh/github-nextjs-key.pub >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys
주의
cp로 복사하면 안 되는 이유
1. 기존 authorized_keys 내용이 모두 덮어쓰기 됨
cp는 파일 전체를 덮어쓰기합니다.
이미 authorized_keys에 다른 공개키들이 등록돼 있었다면, 모두 삭제되고 새 키만 남습니다.
2. 공개키 여러 개 사용하는 환경에 적합하지 않음
나중에 다른 팀원 또는 자동화 툴의 키를 추가하려고 할 때 문제가 생깁니다.
✅ 4단계: GitHub Actions에서 SSH 설정
- name: Setup SSH run: | mkdir -p ~/.ssh echo "${{ secrets.DEPLOY_KEY }}" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan your.server.ip >> ~/.ssh/known_hosts
✅ 5단계: 배포 예시 스크립트
- name: Deploy to Server run: | ssh nextjs@your.server.ip "cd ~/app && ./deploy.sh"
✅ 보안 설정 요약
항목설정
접속 계정nextjs 전용 계정 사용
루트 로그인PermitRootLogin no
비밀번호 인증PasswordAuthentication no
개인 키 위치GitHub Actions Secret (DEPLOY_KEY)
공개 키 위치/home/nextjs/.ssh/authorized_keys
설치
sudo apt install nodejs npm npm install -g pm2
2) GitHub에 Secrets 등록
GitHub > Settings > Secrets and variables > Actions > New repository secret
아래 항목 등록:
권한 설정 문제 :
a) DEPLOY_KEY: 개인 키 (~/.ssh/github-deploy-key 내용) b) HOST: sample.com c) USER: nextjs d) TARGET_DIR: /home/nextjs/app e) SERVICE_NAME: nextjs.service f) PORT: 1234 g) ENV : .env 전체 내용을 그대로 붙여넣기
디렉토리 생성 : 샘플
mkdir -p /home/nextjs/app
.env 샘플
#dev = 개발 환경 #prod = 배포 환경 NESTJS_ENV="prod" TARGET_DIR="/home/nextjs/app" #DB DB_TYPE = "postgres" DB_HOST="192.168.0.19" DB_PORT="5432" DB_USERNAME="sample" DB_PASSWORD="sample" DB_DATABASE="sample" # Hash HASH_ROUNDS=10 # JWT $ openssl rand -base64 64 ACCESS_TOKEN_SECRET="sample" REFRESH_TOKEN_SECRET="sample" JWT_SECRET="sample"
3) ssh-deploy.yml
GitHub에 등록한 self-hosted runner가 있다면, runs-on:에는 해당 runner를 구분할 수 있는 라벨(label) 을 지정해야 합니다
runs-on: [self-hosted, nextjs-host]
라벨 지정 방법
1)
2)
서버 실행시 확인
3) sudo systemctl status github-runner
1. runs-on은 runner의 라벨 이름 GitHub Actions에서 runs-on:은 "어떤 runner에서 이 job을 실행할지"를 지정합니다. GitHub에서 직접 제공하는 runner는 예: nextjs-latest, windows-latest, macos-latest Self-hosted runner는 등록할 때 **라벨(label)**을 하나 이상 설정하게 되어 있음 예시:
만약에 등록한 값이 없다면, 깃허브에서 기본적으로 제공하는 nextjs-latest 를 적어 준다.
✅ NestJS Health Check 설정 방법 (캔버스 정리)
NestJS 앱을 배포하고 정상 작동 여부를 확인하려면 Health Check 엔드포인트를 설정하는 것이 중요합니다. 아래는 GitHub Actions와 함께 사용할 수 있도록 헬스 체크를 구성하는 단계별 가이드입니다.
1️⃣ Terminus 모듈 설치
npm install @nestjs/terminus
Terminus는 NestJS에서 헬스 체크를 표준화하기 위한 공식 모듈입니다.
2️⃣ CLI로 Health 리소스 생성
nest g resource health
CLI 질문 응답:
Transport Layer: REST
CRUD 생성 여부: No
생성되는 기본 구조:
src/health/ ├── health.controller.ts ├── health.module.ts └── health.service.ts
3️⃣ health.controller.ts 수정
import { Controller, Get } from '@nestjs/common'; import { HealthCheck, HealthCheckService, HealthCheckResult, } from '@nestjs/terminus'; import { Public } from 'src/auth/decorator/public.decorator'; @Controller('health') export class HealthController { constructor(private readonly health: HealthCheckService) {} @Public() @Get() @HealthCheck() check(): Promise<HealthCheckResult> { return this.health.check([]); } }
이 코드는 단순히 서버가 살아 있는지 확인하는 기본 체크입니다.
4️⃣ health.module.ts 수정
import { Module } from '@nestjs/common'; import { TerminusModule } from '@nestjs/terminus'; import { HealthController } from './health.controller'; import { HealthService } from './health.service'; @Module({ imports: [TerminusModule], controllers: [HealthController], providers: [HealthService], }) export class HealthModule {}
5️⃣ app.module.ts에 등록
import { Module } from '@nestjs/common'; import { HealthModule } from './health/health.module'; @Module({ imports: [HealthModule], }) export class AppModule {}
6️⃣ 헬스 체크 확인
NestJS 서버 실행 후:
GET http://localhost:3000/health
응답 예:
{ "status": "ok", "info": {}, "error": {}, "details": {} }
✅ GitHub Actions 연동
HEALTHCHECK_URL 값을 .env 또는 GitHub Secret에 설정:
Name: HEALTHCHECK_URL Value: http://your-domain.com/health
CI/CD 스크립트에서 해당 URL로 상태 확인 후 배포 성공 여부 결정.
ssh-deploy.yml
name: CI/CD for NestJS on: push: branches: [main] jobs: deploy: runs-on: [self-hosted, nextjs-host] steps: - name: ✅ Checkout repository uses: actions/checkout@v3 - name: ✅ Set up Node.js 18 uses: actions/setup-node@v3 with: node-version: '18' - name: ✅ List directory contents run: | pwd ls -alR - name: ✅ Create .env file from secrets run: | mkdir -p backend echo "${{ secrets.ENV }}" > backend/.env echo ".env created in backend/" - name: ✅ Install backend dependencies working-directory: ./backend run: npm install - name: ✅ Build backend project working-directory: ./backend run: npm run build - name: ✅ Setup SSH private key and known_hosts run: | mkdir -p ~/.ssh echo "${{ secrets.DEPLOY_KEY }}" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan -p ${{ secrets.PORT }} -H ${{ secrets.HOST }} >> ~/.ssh/known_hosts - name: ✅ Compress and transfer build to remote server run: | tar -czf backend.tar.gz backend scp -F /dev/null -P ${{ secrets.PORT }} backend.tar.gz ${{ secrets.USER }}@${{ secrets.HOST }}:${{ secrets.TARGET_DIR }}/backend-latest.tar.gz - name: ✅ Restart service on remote server env: TARGET_DIR: ${{ secrets.TARGET_DIR }} HOST: ${{ secrets.HOST }} USER: ${{ secrets.USER }} PORT: ${{ secrets.PORT }} run: | ssh -F /dev/null -p "$PORT" "$USER@$HOST" << 'EOF' set -e echo "✅ Connected to remote server" echo "✅ Extracting build..." cd "$TARGET_DIR" rm -rf backend_new mkdir backend_new tar -xzf backend-latest.tar.gz -C backend_new --strip-components=1 echo "✅ Fixing permissions (if needed)..." chown -R nextjs:nextjs "$TARGET_DIR/backend_new" echo "✅ Updating symlink..." ln -sfn "$TARGET_DIR/backend_new" "$TARGET_DIR/current" cd "$TARGET_DIR/current" echo "✅ Installing production dependencies..." npm install --omit=dev echo "✅ Restarting PM2 service..." pm2 restart app || pm2 start dist/main.js --name app echo "✅ 현재 실행 중인 모든 애플리케이션의 상태를 저장" pm2 save echo "✅ Deployment complete." EOF
※전송 시 scp로 권한 유지
cat ~/.ssh/github-deploy-key.pub >> ~/.ssh/authorized_keys chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys
authorized_keys 를 루트에서 설정했기 때문에 루트 권한을 가집니다.
따라서 scp 자체는 파일을 원격에서 어떤 유저로 실행하는지가 중요합니다.
만약 scp 전송 명령이 root 권한으로 실행되고 있다면, GitHub Action의 self-hosted runner 권한을 nextjs로 제한하거나,
파일 전송 후 아래처럼 권한을 반드시 조정하세요:
chown nextjs:nextjs backend-latest.tar.gz
authorized_keys 를 루트에서 설정 했기 때문에 github action 에 등록 한 USER 가 일반 접속 유저일경우
항상
일반 유저 파일 권한 변경 추가 다음처럼 권한 변경을 추가해야 합니다.
# inside your SSH script sudo chown -R nextjs:nextjs /home/nextjs/app/backend-latest.tar.gz
4) 서버에 PM2 설치
서버에 SSH 접속해서 아래 명령어 실행:
# Node.js가 설치되어 있어야 합니다 npm install -g pm2
설치 확인:
pm2 -v
Restart service via SSH 설정 설명
- name: Restart service via SSH run: | ssh -p ${{ secrets.PORT }} ${{ secrets.USER }}@${{ secrets.HOST }} << 'EOF' set -e cd ${TARGET_DIR} tar -xzf backend-latest.tar.gz ln -sf ${TARGET_DIR}/backend ${TARGET_DIR}/current cd ${TARGET_DIR}/current npm install --omit=dev npm run build pm2 restart nestjs-app || pm2 start dist/main.js --name nestjs-app --env production EOF
위 명령은:
앱이 이미 실행 중이면 restart
앱이 없으면 새로 start
GitHub Actions에서 서버에 코드 배포
이미 설정하신 이 부분은 그대로 유지하시면 됩니다:
backend를 tar로 압축해서 서버로 전송
서버에서 압축 해제
ln -sf로 /home/nextjs/app/current 심볼릭 링크 생성
즉, current 디렉토리에 항상 최신 NestJS 앱이 배포되게 설정돼 있어야 합니다.
PM2 프로세스 등록 (처음 1번만)
서버에서 다음 명령어로 PM2에 NestJS 앱을 등록합니다
cd /home/nextjs/app/current # .env가 있는 상태여야 함 npm install --omit=dev npm run build # PM2에 등록 (앱 이름은 nestjs-app으로 설정) pm2 start dist/main.js --name nestjs-app --env production
.env는 GitHub Actions에서 이미 자동 생성되어 있으니 괜찮습니다.
5). PM2 로그 보기 (서버에서)
pm2 logs nestjs-app
✅ GitHub Actions에서 self-hosted 러너를 설정
기본 개념
GitHub Actions는 GitHub에서 제공하는 CI/CD(지속적 통합/배포) 도구입니다.
기본적으로 GitHub에서는 무료로 제공되는 호스팅 러너(nextjs-latest 등)를 사용하지만,
필요에 따라 자체 서버(local, VM, 클라우드 등)를 러너로 등록하여 사용할 수 있습니다. 이것이 self-hosted runner입니다.
Self-Hosted 러너를 사용하는 이유
1)성능 제어 : CPU , 메모리, 스토리지 등 자원을 내가 원하는 수준으로 구성 가능
2) 커스텀 환경 : 특정 라이브러리, 툴체인, DB 등을 미리 설치해 둘 수 있음
3) 보안 : 외부에 노출되지 않은 사내 네트워크나 내부 시스템 접근 가능
4)비용 절감 : Actions 사용량이 많을 경우 GitHub의 무료 러너 한도를 초과함 → 자체 서버 사용 시 비용 절감
5) Windows/macOS 필요 시 : GitHub이 기본적으로 Linux 러너만 제공하므로 Windows/macOS 환경이 필요할 경우 직접 구성해야 함
✅ 설정 요약
OS 선택 (Linux, Windows, macOS)
스크립트 복사
자신의 서버에서 실행 (ex. WSL2에서 실행 가능)
깃허브 액션 러너 설정
관리 권한으로 하면 안된다. 또한 접속자 권한으로 실행시에도 다음과 같은 오류가 난다.
actions-runner 디렉터리 내 파일의 소유권을 현재 사용자로 변경하세요
sudo chown -R $USER:$USER /actions-runner
다시 실행 전에 권한을 안전하게 설정해줍니다:
chmod -R u+rwX /actions-runner
위 권한 수정이 완료되면 다시 설정 명령어를 실행하세요:
※ 작업은 sudo 없이 현재 사용자 계정으로 실행되어야 합니다. ./run.sh 역시 마찬가지입니다:
./run.sh
WSL(Windows Subsystem for Linux)로 리눅스 사용하기
✅ WSL이란?
Windows에서 리눅스 커널을 직접 실행할 수 있게 해주는 기능입니다. 일반적으로 nextjs 배포판을 가장 많이 사용합니다.
✅ 설치 순서 (Windows 10/11 기준)
PowerShell(관리자) 열기
wsl --install
자동으로 nextjs 설치됨 (Windows 11에서는 단순 명령어 하나로 끝)
설치 후 초기 설정
사용자 이름 및 비밀번호 설정
WSL2 설정 확인
wsl --set-default-version 2
실행
wsl
또는 시작 메뉴 → nextjs 검색
✅ GitHub Actions Self-Hosted Runner + WSL 사용 가능?
WSL2 환경에서도 self-hosted 러너를 등록할 수 있습니다.
# WSL2에서 러너 등록 mkdir actions-runner && cd actions-runner curl -o actions-runner-linux-x64-2.316.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.316.0/actions-runner-linux-x64-2.316.0.tar.gz tar xzf actions-runner-linux-x64-2.316.0.tar.gz # GitHub에서 발급받은 설정 명령어 붙여넣기 (token 포함) ./config.sh --url https://github.com/your-org/your-repo --token XXXXXX # 실행 ./run.sh
✅ 기본 설치 경로 (권장)
GitHub에서 공식적으로 제시하는 설치 경로 예시:
# 예: nextjs 사용자 cd ~ mkdir actions-runner && cd actions-runner # 설치 및 구성 curl -o actions-runner-linux-x64-*.tar.gz -L https://github.com/actions/runner/releases/download/... tar xzf ./actions-runner-linux-x64-*.tar.gz ./config.sh --url https://github.com/your_org/your_repo --token your_token
이렇게 하면 runner는 ~/actions-runner 디렉토리에 설치되고,
실행 파일은 ~/actions-runner/run.sh에 위치하게 됩니다.
왜 홈 디렉터리에 설치하나?
보안: 시스템 전역 경로(/)나 /opt, /usr/local 등에 설치할 경우 root 권한이 필요하며, 잘못 관리될 경우 보안 문제가 생길 수 있습니다.
유지보수: 여러 사용자 환경에서 독립적인 runner 관리가 쉬워짐.
권장 관행: GitHub 문서가 사용자 단위 설치를 기본으로 안내함.
컨테이너/CI 환경과의 호환성: 일반적으로 비-root 환경에서 실행되도록 구성됨
확인 방법
설치가 어디에 되어 있는지 확인하려면 아래 명령어를 사용하세요
sudo find / -name "run.sh" -path "*/actions-runner/*" 2>/dev/null
✅nextjs 시스템에서 부팅 시 /actions-runner/run.sh 자동 실행을 설정하는 방법
1. run.sh 권한 확인
실행 가능 여부를 먼저 확인합니다:
chmod +x ~/actions-runner/run.sh
2. systemd 서비스 파일 생성
sudo nano /etc/systemd/system/github-runner.service
[Unit] Description=GitHub Actions Runner After=network.target [Service] ExecStart=/home/nextjs/actions-runner/run.sh User=nextjs WorkingDirectory=/home/nextjs/actions-runner Restart=always RestartSec=5 [Install] WantedBy=multi-user.target
3. systemd 서비스 등록 및 활성화
# 권한 다시 로딩 sudo systemctl daemon-reexec sudo systemctl daemon-reload # 서비스 등록 sudo systemctl enable github-runner.service # 즉시 실행 sudo systemctl start github-runner.service # 상태 확인 sudo systemctl status github-runner.service
확인
시스템 재부팅 후에도 run.sh가 자동으로 실행됩니다.
journalctl -u github-runner.service 로 로그 확인 가능
✅ 부팅 시 정상 동작 확인 팁
시스템 재부팅
sudo reboot
2.재부팅 후 로그인 없이도 GitHub Runner가 자동 실행되는지 확인:
sudo systemctl status github-runner
Self-hosted Runner를 위한 네트워크 및 보안 체크리스트
✅ 1. GitHub 서버와의 통신 허용
GitHub에서 runner와 통신하기 위해 아웃바운드 포트가 열려 있어야 합니다.
기본적으로 허용해야 할 포트:
HTTPS (443) → GitHub와의 통신 (최우선)
HTTP (80) → 초기 리디렉션에 사용되기도 함
필수 도메인:
github.com, api.github.com, actions.githubusercontent.com 등
대부분의 경우 아웃바운드만 허용되면 충분합니다. 방화벽이 너무 제한적인 환경이라면 도메인 화이트리스트 등록도 필요할 수 있습니다.
✅ 2. 방화벽 설정
Runner는 GitHub 서버에서 직접 접속하지 않습니다. 즉, GitHub → runner로 인바운드 요청이 발생하지 않음.
따라서 인바운드 포트를 열 필요는 없음, 단:
CI 환경 내에서 테스트 대상 애플리케이션이 서버처럼 동작하고 내부적으로 포트를 사용하는 경우, 예: Django 서버 실행 (python manage.py runserver), 해당 포트를 허용해야 함.
# 로컬에서 테스트 시 8000번 포트를 사용할 수 있게 허용 sudo ufw allow 8000
✅ 3. Runner 보안
self-hosted runner는 외부 요청을 받아 실행하므로 다음을 고려해야 합니다:
별도의 사용자 계정으로 실행 (루트 권한 X)
실행 환경을 주기적으로 초기화하거나 컨테이너화 (예: Docker)하여 안전하게 유지
필요시 CI 서버를 내부망에서만 접근 가능하게 구성
예: nextjs + UFW 환경에서 최소 설정
# 아웃바운드 허용 (기본적으로 허용되어 있음) sudo ufw default allow outgoing # 인바운드는 필요할 때만 허용 (예: Django 서버 테스트용 8000) sudo ufw allow 8000 # UFW 상태 확인 sudo ufw status
댓글 ( 0)
댓글 남기기