GitHub Actions로 Hugo 블로그 자동 배포 설정하기#
Hugo 블로그 구축이 완료되고 나서 가장 귀찮은 일 중 하나가 바로 배포였습니다. 포스트를 하나 쓸 때마다 로컬에서 빌드하고, 서버에 접속해서 파일을 업데이트하고, Docker 컨테이너를 재시작하고… 이런 반복 작업이 정말 번거로웠어요.
“이 과정을 자동화할 수 없을까?” 하는 생각에 GitHub Actions를 도입해봤는데, 결과적으로 커밋만 하면 자동으로 배포되는 완벽한 워크플로우를 만들 수 있었습니다. 이번 포스트에서는 그 과정을 상세히 공유해보겠습니다.
GitHub Actions가 뭐길래?#
간단히 말해서, GitHub에서 제공하는 CI/CD 서비스입니다. 코드를 푸시하면 자동으로 정해진 작업들을 수행해주죠. 우리의 경우에는 “Hugo 빌드 → 서버 배포"를 자동으로 해주는 겁니다.
무료 계정도 월 2,000분까지 사용할 수 있어서 개인 블로그 용도로는 충분해요!
1. 워크플로우 파일 생성하기#
먼저 프로젝트에 .github/workflows/deploy.yml
파일을 만들어야 합니다. 이 파일이 GitHub Actions의 핵심이에요.
name: Hugo Blog Auto Deploy
on:
push:
branches: [ main ] # main 브랜치에 푸시될 때 실행
pull_request:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: true # BlowFish 테마를 submodule로 사용하는 경우
fetch-depth: 0 # Hugo가 .GitInfo를 사용하는 경우
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: '0.149.0'
extended: true
- name: Build Hugo site
run: hugo --minify --cleanDestinationDir
- name: Deploy to server via SSH
uses: appleboy/[email protected]
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
port: ${{ secrets.SERVER_PORT }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: |
cd ~/coderblog
git pull origin main
hugo --minify --cleanDestinationDir
docker stop hugo-blog 2>/dev/null || true
docker rm hugo-blog 2>/dev/null || true
docker run -d --name hugo-blog --restart unless-stopped \
-p 9572:80 -v ~/coderblog/public:/usr/share/nginx/html:ro nginx:alpine
echo "✅ 블로그 배포 완료!"
코드를 보면 순서가 명확해요:
- Checkout: 코드를 가져옴
- Setup Hugo: Hugo 설치
- Build: 정적 사이트 빌드
- Deploy: SSH로 서버에 접속해서 배포
2. GitHub Secrets 설정 - 보안이 중요해요!#
워크플로우에서 ${{ secrets.SERVER_HOST }}
같은 표현을 봤을 텐데, 이건 GitHub에서 제공하는 보안 기능입니다. 서버 정보를 코드에 직접 적으면 안 되니까요.
GitHub Repository → Settings → Secrets and variables → Actions에서 다음 4개를 추가해야 합니다:
SERVER_HOST
: 서버 IP 주소SERVER_USER
: SSH 사용자명SERVER_PORT
: SSH 포트 (저는 55455를 사용했어요)SERVER_SSH_KEY
: SSH 개인키 내용
3. SSH 키 생성하기 - 가장 까다로운 부분#
GitHub Actions가 서버에 접속하려면 SSH 키가 필요합니다. 이 부분에서 많이 헤맸어요.
서버에서 다음 명령을 실행:
# 새로운 SSH 키 생성 (암호 없이!)
ssh-keygen -t ed25519 -f ~/.ssh/github_actions_key -N ""
# 공개키를 authorized_keys에 추가
cat ~/.ssh/github_actions_key.pub >> ~/.ssh/authorized_keys
# 개인키 내용 출력 (이걸 GitHub Secrets에 복사)
cat ~/.ssh/github_actions_key
마지막 명령으로 나온 내용을 전체 복사해서 GitHub Secrets의 SERVER_SSH_KEY
에 붙여넣으면 됩니다.
주의사항: 개인키는 -----BEGIN OPENSSH PRIVATE KEY-----
부터 -----END OPENSSH PRIVATE KEY-----
까지 전체를 복사해야 해요!
4. 첫 실행해보기#
설정이 끝났으면 이제 테스트해볼 차례입니다.
# 워크플로우 파일 커밋
git add .github/workflows/deploy.yml
git commit -m "GitHub Actions 자동 배포 설정 추가"
git push origin main
푸시하자마자 GitHub Repository → Actions 탭에 가보세요. 워크플로우가 실행되는 걸 실시간으로 볼 수 있어요!
처음에는 실패할 수도 있는데, 당황하지 마세요. 저도 SSH 키 설정에서 몇 번 삽질했거든요. 😅
자주 만나는 문제들과 해결법#
SSH 연결이 안 될 때#
# 서버에서 직접 테스트해보기
ssh -i ~/.ssh/github_actions_key 사용자명@서버IP -p 포트번호
이 명령이 성공하면 키는 제대로 설정된 거예요.
Hugo 빌드가 실패할 때#
- 로컬 Hugo 버전과 Actions에서 사용하는 버전이 같은지 확인
- 테마를 submodule로 사용한다면
submodules: true
설정 확인
Docker 권한 문제#
서버에서 사용자가 Docker를 실행할 권한이 없을 때 발생해요:
sudo usermod -aG docker $USER
고급 기능들#
특정 파일만 변경되었을 때만 배포하기#
모든 커밋에 대해 배포하는 건 비효율적일 수 있어요. 설정 파일만 수정했다면 굳이 배포할 필요 없으니까요.
on:
push:
branches: [ main ]
paths:
- 'content/**'
- 'static/**'
- 'config/**'
- 'themes/**'
이렇게 설정하면 콘텐츠 관련 파일이 변경될 때만 배포됩니다.
슬랙으로 배포 알림 받기#
배포 성공/실패를 슬랙으로 알림 받을 수도 있어요:
- name: Slack notification
if: always() # 성공/실패 관계없이 항상 실행
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: 블로그 배포가 ${{ job.status }}되었습니다!
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
최종 권장 워크플로우#
여러 시행착오를 거쳐서 만든 최종 버전입니다:
name: Hugo Blog Deploy
on:
push:
branches: [ main ]
paths:
- 'content/**'
- 'static/**'
- 'config/**'
- 'themes/**'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: '0.149.0'
extended: true
- name: Build
run: hugo --minify --cleanDestinationDir
- name: Deploy to server
uses: appleboy/[email protected]
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
port: ${{ secrets.SERVER_PORT }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: |
cd ~/coderblog
git pull origin main
hugo --minify --cleanDestinationDir
docker stop hugo-blog 2>/dev/null || true
docker rm hugo-blog 2>/dev/null || true
docker run -d --name hugo-blog --restart unless-stopped \
-p 9572:80 -v ~/coderblog/public:/usr/share/nginx/html:ro nginx:alpine
echo "✅ 블로그 배포 완료!"
마무리#
GitHub Actions 자동 배포를 설정하고 나니 블로그 운영이 정말 편해졌어요. 이제 포스트 작성에만 집중하면 되고, 커밋 한 번으로 모든 배포가 끝나니까요.
처음 설정할 때는 SSH 키 부분에서 좀 헤맬 수 있지만, 한 번만 제대로 설정하면 그 다음부터는 정말 편리해요. 특히 모바일에서 GitHub 앱으로도 Actions 실행 상태를 확인할 수 있어서, 언제 어디서든 배포 상황을 체크할 수 있답니다!
자동화의 힘을 제대로 느낄 수 있는 기능이에요. 한 번 설정해두면 계속 도움이 되니 꼭 시도해보세요! 🚀
참고 링크