静的サイトジェネレーター(SSG)で作ったサイトをGitHub Actionsを使ってサーバに公開するところまでの手順をまとめます。 2~3年目の自分向けに詳細に書いてます。
▲ 構成の全体図。masterを更新したらGitHub actionsでビルドしてさくらのVPSにデプロイします。GitHub actionsからサーバへはrsyncで接続しているため、サーバにNodeがなくてもOK。サーバではNginxとLet's Encriptを利用して配信してます。
以上の構成を建てるところまで順に紹介していきます。
Nuxtjsで作りましたが、NextやGatsbyなどのSSG、SPAも同様にデプロイできます。
また、サーバもさくらのVPSでなくEC2や他のサーバも大丈夫です。
初のCIなので不備があるかもしれません。ご指摘頂けるとありがたいです。
Table of Contents
デプロイするアプリの概要
今回はNuxt/contentで作ったサイトをデプロイします。
- 完成品: https://nuxt-content-sample.suzu6.net/
- コード: GitHub
デプロイで必要な実行するコマンド。
yarn install
: 必要なnode_modulesを追加する。yarn lint
: Lintをチェック。yarn test
: Jetでユニットテスト。yarn generate
: 静的サイトを生成する。
yarnを利用している。./dist
ディレクトリに生成されるので、これをサーバにアップロードする必要がある。また、GENERATED_BY
という環境変数をトップページで使います。
サイトの作り方はnuxt/contentでブログを作るで紹介してます。
rsync出来るようにサーバを設定する
GitHub actionsで生成したサイトをサーバに設置するのにrsyncを使います (GitHub actionsのワークフローでmarketplaceのssh-deployを利用しており、その中でrsyncを利用している)。そのため、外部からrsync出来るようにサーバを設定します。SSHには公開鍵認証を利用します。
今回、さくらのVPSにCentOS7を建ててホスティングします。 5つの手順でrsync出来るところまでサーバをたてます。
- さくらのVPSでCentOS 7を建てる
- rsync用のユーザを追加
- 公開鍵の作成と登録をする
- sshd_configの設定
- SSHのポート番号の変更
サーバにデプロイする設定までです。 別の記事でNginxとLet's Encriptの設定をします。
1. さくらのVPSでCentOS 7を建てる
さくらのVPSの概要は公式の入門講座を参照してください。 ネコでもわかる!さくらのVPS講座 ~第二回「サーバーをさわってみよう!」で契約からSSH接続まで紹介されてます。
作成したユーザでSSHのパスワード接続が出来ていていればOK。 もしくはこれからの手順でユーザが追加できる。
2. rsync用のユーザを追加
rsync用のユーザを作成する。 ユーザグループとパスワードはsudo実行のために付けたが、設定が終われば外してよさそう。
## ユーザ追加
# useradd rsync_user
## ユーザグループに追加
# gpasswd -a rsync_user wheel
## パスワード設定
# passwd $user
visudo
でrsyncするときroot権限で実行できるように設定する
# visudo
rsync_user ALL=(ALL) NOPASSWD:/usr/bin/rsync
※ 公開先のディレクトリのパーミッションをちゃんと設定すれば、root権限渡さなくても良いかも。
3. 公開鍵の作成と登録をする
rsync_userの公開鍵を作成します。
$ sudo su rsync_user
$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
# 次の二つが出来る。
# /home/rsync_user/.ssh/id_rsa
# /home/rsync_user/.ssh/id_rsa.pub
ssh-deployが対応していないため、パスフレーズは設定しない。
id_rsa.pub
をこのユーザの公開鍵として、id_rsa
がGitHub actionsに登録する秘密鍵とします。ローカルで鍵を作った方は適宜読み替えてください。
rsync_userの公開鍵を登録します。
# authorized_keysを作成
$ cd /home/rsync_user/.ssh/
$ cp id_rsa.pub authorized_keys
# 権限を変更
$ sudo chmod 700 /home/rsync_user/.ssh
$ sudo chmod 600 /home/rsync_user/.ssh/authorized_keys
authorized_keys
が既に登録済みの場合は、末尾に公開鍵を追加する。
.ssh
ディレクトリとauthorized_keys
の権限をそれぞれ700
と600
にする。
ここまでで、ssh接続ができるようになっているはず。
# サーバの中から
$ ssh rsync_user@localhost -i /home/rsync_user/.ssh/id_rsa
# ローカルのPCから
> ssh rsync_user@{サーバのIP・ホスト名} -i path/to/id_rsa
接続出来ない場合はauthorized_keys
の権限とsshd
を確認する。
サーバの中からできて外部から出来ない場合は、さくらのVPSの場合パケットフィルタのポートとIPを確認する。
rsync -avz rsync://rsync_user1@10.0.1.108/tmp /var/www/test
4. sshd_configを設定する
セキュリティを高めるための設定です。 rsyncに直接関係ないので後からでもよい。
まず、sshd_configをバックアップはしておく。消しちゃったら建て直せばいい。
cd /etc/ssh
sudo cp sshd_config sshd_config.org
sshd_config
を編集する。
$ sudo vi sshd_config
PermitRootLogin no
PasswordAuthentication no
AuthorizedKeysFile .ssh/authorized_key
PermitRootLogin no
はrootユーザでのログインを拒絶する。
PasswordAuthentication no
はパスワードでのログインを拒絶する。
どちらもセキュリティを高めるための設定です。
AuthorizedKeysFile .ssh/authorized_key
は公開鍵のパスを指定している。デフォルトで変更の必要ないはず。
sshdの設定を更新する。
$ sudo systemctl restart sshd
$ sudo systemctl status sshd
* sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2020-12-22 22:27:56 JST; 1 day 1h ago
Docs: man:sshd(8)
man:sshd_config(5)
Main PID: 20149 (sshd)
CGroup: /system.slice/sshd.service
`-20149 /usr/sbin/sshd -D
参考: ネコでもわかる!さくらのVPS講座 ~第二回「サーバーをさわってみよう!」
5. SSHのポート番号の変更
SSHのポートを2022に変更してみる。
$ sudo vi sshd_config
Port 2022
sshdの設定を更新する。
sudo systemctl restart sshd
ポートの変更ではfirewalld
のsshの設定も変更します。
$ cd /usr/lib/firewalld/services/
# コピーする
$ sudo cp ssh.xml ssh.xml.org
# firewallの設定を変更する
$ vi /usr/lib/firewalld/services/ssh.xml
22 -> 1022
ポートを変更したらfirewalld
を再起動する。
$ sudo systemctl restart firewalld.service
success
$ sudo systemctl status firewalld.service
* firewalld.service - firewalld - dynamic firewall daemon
Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2020-12-21 22:41:40 JST; 2 days ago
Docs: man:firewalld(1)
ここまでで、22での接続が出来ず、2022での接続が確認できる。
# サーバの中から
$ ssh rsync_user@localhost -p 2022 -i /home/rsync_user/.ssh/id_rsa
# ローカルのPCから
> ssh rsync_user@{サーバのIP・ホスト名} -p 2022 -i path/to/id_rsa
参考: CentOS 7 firewalld よく使うコマンド
さくらのVPSの場合はパケットフィルタの設定も行う。
- カスタムTCP
- ポート: 2022
- すべて許可する
GitHub actions
GitHub actionsのワークフローの設定と環境変数を設定します。
ワークフローの設定
generateまではNuxt.jsのプロジェクトを作成したときに出来たワークフローです。 サーバへデプロイするところは、マーケットプレイスのssh-deployを利用しています。
nuxt-content-sample/.github/workflows/ci.ymlに全文があります。
理解したことをブロック単位で説明を添えてみます。
on:
push:
branches:
- master
pull_request:
branches:
- master
▲ トリガーとなる動作。masterへのプッシュとプルリクエストでCIが動き出す。ブランチごとにテスト用とか分けられる。
ワークフローの確認には手動で実行できるworkflow_dispatchもあるるようです。
jobs:
ci:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
node: [14]
▲ ここからワークフローのジョブを定義する。runs-on
で動作する環境を選ぶ。Ubuntu
の最新版でNode v14
の環境でビルドします。
steps:
- name: Checkout 🛎
uses: actions/checkout@master
▲ リポジトリからチェックアウト。
- name: Setup node env 🏗
uses: actions/setup-node@v2.1.2
with:
node-version: ${{ matrix.node }}
▲ Nodeのバージョンを定義する。strategy
でセットしたパラメータが使える。
- name: Get yarn cache directory path 🛠
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Cache node_modules 📦
uses: actions/cache@v2
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install dependencies 👨🏻💻
run: yarn
▲ node-modulesのキャッシュを定義して、yarnでインストールする。 キャッシュがあると次回のビルドでnode-modulesのインストール時間を軽減できる。 初心者にこの設定を組むのは厳しいので、Nuxt.jsのプリセットが有って助かった!
- name: Run linter 👀
run: yarn lint
- name: Run tests 🧪
run: yarn test
- name: Run generate
run: yarn generate
▲ lintとテストとビルドを実行している。 lintとテストでエラーが出た場合はちゃんとワークフローも止まります。 ちゃんとプッシュする前に確認する習慣がつきそう。
- name: Deploy to Server
uses: easingthemes/ssh-deploy@v2.1.5
env:
SSH_PRIVATE_KEY: ${{ secrets.SERVER_SSH_KEY }}
ARGS: "-rltgoDzvO --delete"
SOURCE: "dist/"
REMOTE_HOST: ${{ secrets.REMOTE_HOST }}
REMOTE_USER: ${{ secrets.REMOTE_USER }}
REMOTE_PORT: ${{ secrets.REMOTE_PORT }}
TARGET: ${{ secrets.REMOTE_TARGET }}
▲ サーバへデプロイするssh-deployの処理です。
generateで生成した./dist
ディレクトリ以下をsecrets.REMOTE_TARGET
に置きます。
サーバのsecrets.REMOTE_TARGET
のパスからNginxがホスティングしている。
rsync
のコマンドを自由度高めに設定できる。
secrets
はリポジトリで設定した環境変数です。${{ secrets.REMOTE_HOST }}`のようにして使えます。
https://github.com/marketplace/actions/ssh-deploy
環境変数を設定
ワークフローの中で利用できる環境変数は、リポジトリのSetting
→ Secrets
→ New repository secret
から追加できる。
ワークフローでは${{ secrets.REMOTE_HOST }}`のように使える。
どうもEnvironment secrets
とRepository secrets
があって使い分け出来る。
Repository secrets
の方が暗号化されていて個人ではリポジトリのオーナーだけ見られるようです。
おわりに
以上でさくらのVPSにNuxt.jsの静的サイトをデプロイまでの手順を紹介しました。
1記事にまとめましたがかなり手順があって大変です。前回NetlifyからVercelへの移行を検討した話という話を書いた。Netlifyが遅い点をディスったが、Netlifyの無料で手軽にデプロイできるのは凄いことだなと改めて感じた。
マルチドメインで使えるようなNginxのバーチャルホストの設定や、Let’s EncriptでのSSL対応もしたのでこちらも記事にします。
とうとう自分のサーバを契約してブログだけでは持て余してしまう。 アプリを作りたいが、リソース管理やセキュリティの方面も学んでいきたい。 来年は使い倒していく。