🤖
Nginx + Systemd +Github Actionsを用いたローカルGO(Echo)APIをVPSに自動デプロイ
初めまして!サーバーサイドの勉強をしているもちです。
今回チーム開発をしているときに初めて簡単なCI/CDパイプラインを構築したため、構築手順と遭遇したエラーなどまとめていきたいと思います。
システム構成
- 開発:ローカル(Mac)
- ソース管理:GitHub
- VPS:ubuntu
- Webサーバー:Nginx(リバースプロキシ)
- プロセス管理:Systemd
- CI/CD:GitHub Actions
Part1:VPS環境の構築
自動化をする前に手動で完璧に動作する環境をVPS上に構築します。
Step1:Goアプリの準備とビルド
-
ソースコードの準備
githubなどにソースコードを準備しておいてVPSにSSH接続し、GitHubからプロジェクトをクローンします。
Bash
ssh YOUR_USER@YOUR_VPS_IP
cd /path/to/project
git pull origin main
API実行のテストになるGo(echo)のコードを置いておきます。
main.go
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
message := "Hello, goApi"
data := map[string]string{
"message": message,
}
return c.JSON(http.StatusOK, data)
})
e.Logger.Fatal(e.Start(":8001"))
}
-
Goアプリのビルド
APIのソースコードがあるディレクトリに移動して、go buildで実行ファイルを作成します。-oフラグで出力ファイル名をmy-api(任意の名前)に固定するのがポイントとなります。
Bash
cd /your-goproject-path
go build -v -o my-api .
Step2:systemdでアプリをサービス化
Goアプリが常にバックグラウンドで稼働し、クラッシュしても再起動するようにsystemdに登録をします。
-
サービスファイルの作成
sudoでサービス定義ファイルを作成します。
Bash
sudo nano /etc/systemd/system/go-api.service
-
サービスファイルの内容
User,Group,WorkingDirectory,ExecStartを自身の環境に合わせてください
ini,TOML
[Unit]
Description=Go Echo API Server
After=network.target
[Service]
User=YOUR_USER
Group=YOUR_USER
WorkingDirectory=/path/to/project/goApi
ExecStart=/path/to/project/goApi/my-api
Restart=always
[Install]
WantedBy=multi-user.target
- サービスの有効化と起動
Bash
sudo systemctl daemon-reload
sudo systemctl enable go-api.service
sudo systemctl start go-api.service
これらを実行したのちsudo systemctl status go-api.serviceactive(running)`になっていれば成功です。
Step3:Nginxでリバースプロキシ設定
外部からのアクセス(80番ポート)を、内部で動いているGoアプリ(今回は8001番ポート)に中継させます。
- Nginx設定ファイルの作成
Bash
sudo nano /etc/nginx/sites-available/go-api
-
設定内容
/testというパスでAPIを公開する設定です。
Nginx
server {
listen 80;
server_name YOUR_DOMAIN_OR_IP;
location /reference/ {
# 末尾のスラッシュが重要!
proxy_pass http://127.0.0.1:8001/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
- 設定の有効化とNginxの再起動
Bash
sudo ln -s /etc/nginx/sites-available/go-api /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
- ファイアウォールの設定
Bash
sudo ufw allow 'Nginx Full'
sudo ufw reload
この時点で、http://YOUR_BOMAIN_OR_IP/test/にアクセスしてAPIが応答すれば、VPS側の設定は完了です。
Part2:GitHub Actionsによるデプロイを自動化
vpsで手動作業でgit pullをしている作業をローカルからgit pushだけで完結するようにします。
Step4:GitHub ActionsとVPSの連携
- SSHキーの作成(ローカルPC)
Bash
ssh-keygen -t rsa -b 4096 -f ~/.ssh/github_actions_vps_key -N ""
-
公開鍵の登録
ローカルの公開鍵 (~/.ssh/github_actions_vps_key.pub) の中身を、VPSの~/.ssh/authorized_keysに追記します。 -
GitHub Secretsの登録
リポジトリのSettings>Secrets and variables>Actionsで、以下の4つのSecretを登録します。
-
GO_HOST: VPSのドメインまたはIP -
GO_USER: VPSのSSHユーザー名 -
PROJECT_PATH: VPS上のプロジェクトの絶対パス (例:/home/user/project) -
GO_SSH_PRIVATE_KEY: ローカルの秘密鍵 (~/.ssh/github_actions_vps_key) の中身
-
sudoのパスワードなしで実行設定(VPS)
sudo visudoでファイルを開き、末尾に以下を追記します
YOUR_USER ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart go-api.service
Step5:ワークフローファイルの作成
ローカルPCのプロジェクトルートに.github/workflows/deploy.ymlを作成します
YAML
name: Deploy Go API to VPS
on:
push:
branches: [ "main" ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy to VPS and Restart Service
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.GO_HOST }}
username: ${{ secrets.GO_USER }}
key: ${{ secrets.GO_SSH_PRIVATE_KEY }}
script: |
cd ${{ secrets.PROJECT_PATH }}
git pull origin main
cd goApi
go build -v -o my-api .
sudo systemctl restart go-api.service
echo "🚀 Deployment Successful!"
このファイルをgit pushすれば、CI/CDパイプラインの完成です。
Part3:トラブルと対処法
私が構築中に遭遇したトラブルと対処法です
問題1:APIにアクセスすると404 Not Foundになる
-
症状:
http://.../test/にアクセスしてもAPIの応答ではなく、Nginxの404エラーページが表示される -
原因:
proxy_passの末尾のスラッシュ抜け -
調査:Nginxの設定ファイルを確認。
proxy_pass http://127.0.0.1:8001となっていた -
解決策:
/test/の部分を剥がして転送するために、proxy_pass http://127.0.0.1:8001/;のように末尾にスラッシュを追加した。
問題2:GitHub Actionsのgit pullでPermission denied
-
症状:ワークフローの
git pull origin mainのステップでPermission denied (publickey)エラーが発生して失敗する。 - 原因:GitHub ActionsからVPSへの接続は成功したが、その後VPSからGitHubへのアクセスが許可されていなかった。
- 解決策:VPS上で専用のSSHキーを作成し、GitHubリポジトリのDeploy Keyとして公開鍵を登録する必要があった。
問題3:Deploy KeyがGitHub上で無効にされていた
-
症状:リポジトリの
SettingsにDeploy keysのメニュー自体が表示されない、または「Disabled by ...」と表示される。 - 原因:所属しているOrganization全体のセキュリティポリシーで、Deploy Keyの使用が禁止されていた。
-
解決策:代替案としてPersonal Access Tokenを利用した
- 自分のGitHubアカウントで
repo権限を持つPATを発行 - VPS上でgitの接続先URLを、トークンを含んだHTTPS形式に変更した。
- 自分のGitHubアカウントで
Bash
git remote set-url origin https://<YOUR_TOKEN>@github.com/ORG/REPO.git
問題4:git pullを手動で実行するとパスフレーズを聞かれる
-
症状:VPSにログインして手動で
git pullすると、Enter passphrase for key ...と表示され、自動化の妨げになる。 -
原因:VPSがGitHubに接続する際、パスフレーズ付きのデフォルトキー(
~/.ssh/id_rsa)を優先して使おうとしていた。 -
解決策:
~/.ssh/configファイルを作成し、GitHubへの接続にはパスフレーズなしで作成した専用キー(github_deploy_key)を明示的に使うよう設定した。
# ~/.ssh/config の内容
Host github.com
IdentityFile ~/.ssh/github_deploy_key
Discussion