カスタマイズ性が高い、オープンソースのヘッドレス CMS として人気の Strapi ですが、仕事で使用するヘッドレス CMS の候補として少し勉強したかったので、さくらの VPS (Ubuntu 20.04) でセルフホストしてみました。その手順について簡単にまとめておきます (ちなみに、セルフホストしなくても Strapi Cloud という SaaS 版もあります)。
Strapi の動作環境
今回は、この記事を書いている時点における、Strapi の最新バージョンである v5.1.0 を前提に進めます。
まず、Strapi を利用する場合の推奨環境については GitHub リポジトリにまとまっていますが、下記のような感じです。
OS
OS | 推奨 | 最低限 |
---|---|---|
Ubuntu | 24.04 | LTS |
Debian | 11 | LTS |
RHEL | 9 | LTS |
macOS | 14 | 12 |
Windows Desktop | 11 | 10 |
Windows Server | 非サポート | 非サポート |
Node.js
Node.js に関しては、「Active LTS」、もしくは 「Maintenance LTS」 ステータスのバージョンのみサポートなので注意してください。要するに偶数番号リリースで、LTS ステータスに移行済みの Node.js を使用する必要があります (現在であれば、「v20.18.0 (LTS)」、もしくは 「v18.20.4 (LTS)」 がサポートされています)。
データベース
データベース | 推奨 | 最低限 |
---|---|---|
MySQL | 8.0 | 8.0 |
MariaDB | 11.2 | 10.3 |
PostgreSQL | 16.0 | 14.0 |
SQLite | 3 | 3 |
ちなみに、SQLite を使用する場合は、Python のインストールが必要です。
今回、私の環境では、MySQL を使用しています。
Strapi のインストール
冒頭にも書いたとおり、今回使用するサーバ OS は、Ubuntu 20.04 です。また、下記はすでにインストールされている前提で進めます。
- node.js
- npm (yarn など別のパッケージマネージャでもよい)
- MySQL
- nginx
- certbot
- PM2
Web サーバの準備
今回使用する Web サーバは、nginx です。
まず、Strapi をインストールするためのディレクトリを作ります。strapi.example.com
というドメインで運用する前提です。
sudo mkdir -p /var/www/strapi.example.com/html
sudo chown -R www-data:www-data /var/www/strapi.example.com
sudo chmod -R 755 /var/www/strapi.example.com
strapi.example.com
用の設定ファイルを新規作成し、
sudo vim /etc/nginx/sites-available/strapi.example.com
とりあえず下記のように記述して保存しておきます。
server {
listen 80;
listen [::]:80;
root /var/www/strapi.example.com/html;
index index.html index.htm index.nginx-debian.html;
server_name strapi.example.com;
add_header Access-Control-Allow-Origin '*';
location / {
proxy_pass http://localhost:1337;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header 'Access-Control-Allow-Origin';
}
}
作成した設定ファイルのシンボリックリンクを nginx が起動時に読み取る sites-enabled
ディレクトリに作成することで設定が有効になります。
sudo ln -s /etc/nginx/sites-available/strapi.example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
ついでに、Let's Encrypt でサーバ証明書を取得し、HTTPS で接続可能にしましょう。certbot を使います。
sudo certbot --nginx -d strapi.example.com
質問に答えていくだけなので簡単。設定ファイルも certbot に書き換えてもらいましょう。
自動更新が有効になっているか確認して完了です。
sudo systemctl status certbot.timer
最後に nginx を再起動。
sudo nginx -t
sudo systemctl reload nginx
MySQL の準備
MySQL にログインし、ユーザーと Strapi で使用するデータベース (今回は 「strapi」 という名前で) を作成します。当然ながら、すでにユーザーが設定済みの場合はデータベースの作成だけで問題ありません。
mysql> CREATE USER '<username>'@'localhost' IDENTIFIED BY '<password>';
mysql> CREATE DATABASE strapi;
mysql> GRANT ALL ON strapi.* TO <username>@localhost;
mysql> FLUSH PRIVILEGES;
mysql> EXIT;
今作ったユーザーでログインできることを確認し、
mysql -u <username> -p
データベースも問題なく作成されていることを一応確認します。
mysql> SHOW DATABASES;
文字コードなどはデフォルトのままで問題ないと思いますが、こちらも一応確認して必要なら設定を変更します。
mysql> STATUS;
Strapi 本体のインストール
まず、先ほど作成した Strapi インストールディレクトリに移動します。
cd /var/www/strapi.example.com/html
インストールには npx
コマンドが使用できますので、あとはウィザード形式で質問に答えていくだけです。
sudo npx create-strapi@latest
最初に 「プロジェクト名どうする?」 と聞かれますので、今回は strapi
と入力して Enter します。これで、Strapi は /var/www/strapi.example.com/html/strapi
にインストールされることになります。
次に、「Strapi Cloud に Login/Signup するか?」 っていう質問が来るので、ここは 「Skip」 を選択しましょう。
続けて、「データベースはデフォルトのを使う?」 って聞かれるので、ここも 「No」 を選択し、次に出てくるデータベースの選択肢で 「MySQL」 を選択します。
あとは聞かれた事に答えれば終わると思います。参考までに下記が私が選択した結果 (途中で MySQL のユーザー名やパスワードを聞かれているのもわかると思います)。
? Please log in or sign up. Skip
? Do you want to use the default database (sqlite) ? No
? Choose your default database client mysql
? Database name: strapi
? Host: localhost
? Port: 3306
? Username: username
? Password: ***************************
? Enable SSL connection: No
? Start with an example structure & data? No
? Start with Typescript? Yes
? Install dependencies with npm? Yes
? Initialize a git repository? No
質問に答え終わるとインストールが進んでいくのであとは終わるまで待ちましょう。途中でエラーが出なければ成功です。
インストールされたディレクトリに移動します。
cd strapi
公開 URL の設定
インストールディレクトリ直下に、.env
ファイルがありますのでエディタで開きます。
sudo vim .env
.env
ファイルには、インストールウィザードで質問されたことなども自動的にここに反映されていますので、内容を確認しつつ、下記の記述を追加して上書きします。
# Server
HOST=localhost
PORT=1337
PUBLIC_URL=https://strapi.example.com //←これ追記
...以下略...
次に、config/server.ts
を編集します。
sudo vim config/server.ts
config/server.ts
の内容は下記のようになっていますが、url
オプションを追加して、こちらも上書き保存しておきましょう。
export default ({ env }) => ({
host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 1337),
url: env('PUBLIC_URL'), //←これ追記
app: {
keys: env.array('APP_KEYS'),
},
});
管理画面の日本語化
これは必要ない人はやらなくてもよいですが、一応、管理画面を日本語化できます。とはいっても、すべてのパーツに日本語訳が当たっているわけではないので、一部が日本語になるだけの中途半端なものですから、気休め程度に思ってください。
インストールディレクトリ内の、src/admin
に、app.example.tsx
というファイルがありますので、これを app.tsx
にリネームします。その後、その app.tsx
を編集しましょう。
sudo cp src/admin/app.example.tsx src/admin/app.tsx
sudo vim src/admin/app.tsx
下記のような内容になっていて、初期状態だと locales
の部分がすべてコメントアウトされていますが、この中から 'ja'
のコメントアウトを外して上書き保存します。
import type { StrapiApp } from '@strapi/strapi/admin';
export default {
config: {
locales: [
// 'ar',
// 'fr',
// 'cs',
// 'de',
// 'dk',
// 'es',
// 'he',
// 'id',
// 'it',
'ja',
// 'ko',
// 'ms',
// 'nl',
// 'no',
// 'pl',
// 'pt-BR',
// 'pt',
// 'ru',
// 'sk',
// 'sv',
// 'th',
// 'tr',
// 'uk',
// 'vi',
// 'zh-Hans',
// 'zh',
],
},
bootstrap(app: StrapiApp) {
console.log(app);
},
};
Strapi の起動と設定
自分が、Strapi のインストールディレクトリ (/var/www/strapi.example.com/html/strapi
) にいることを確認したら、PM2 を使用して Strapi を起動します。
sudo pm2 start npm --name strapi -- run develop
PM2 のログを確認して、問題なく Strapi が起動したことを確認します。
sudo pm2 logs strapi --lines 50
ブラウザから設定
問題なさそうなら、https://strapi.example.com
にブラウザでアクセスすると、アカウント作成画面になると思いますので、アカウントを作ってログインします。
最初に、「Content-Type Builder」 を使用して、コンテンツタイプを作りましょう。今回はサンプルとして 「Article」 という記事更新用のコンテンツタイプを作りました。
ここで設定している 「API ID (Singular)」 と 「API ID (Plural)」 は後ほど API でデータを取得する際に使いますのでわかりやすいものを設定しましょう。
コンテンツタイプを作ったら、適当に記事を登録したりして試してみるとよいでしょう。
次に、投稿された記事データを API で取得できるようにします。設定によっては認証不要で (API のエンドポイントを知っている人なら) 誰でも API からデータを取得可能にすることもできますが、通常の運用でそんなことはしないと思いますので、API 用のアクセストークンを発行して、認証に使用できるようにします。
メインメニューの 「API Tokens」 を選択したら、適当な名前を付けて保存します。アクセストークンは 1 度しか表示されないので確実に保存しましょう。
API から記事データを読み取るだけであれば、「Token Type」 を 「Read-only (読み取り専用)」 にしておきます。
画面下部に先ほど作ったコンテンツタイプ 「Article」 が表示されていると思いますが、「find」 と 「findOne」 権限が有効になっていれば、データは取得できます。
アクセストークンを保存したら、次は権限設定を行います。
メインメニューの 「Roles」 を選択したら、「Authenticated (認証済みアカウント)」 の権限設定に進みましょう。
コンテンツタイプ 「Article」 の権限を開き、「find」 と 「findOne」 権限を有効にします。
これで、API から 「Article」 コンテンツタイプのデータを取得可能になります。
あと、管理画面の言語設定については、アカウントの設定画面から行えます。必要なら変更しておきましょう。
Strapi のアップデート
稼働中の Strapi を最新版にアップデートしたい場合も、npx
コマンドが使用できますので、それに任せましょう。基本的に最新版にアップデートするならインストールディレクトリに移動後、下記のコマンドを実行すれば OK です。
sudo npx @strapi/upgrade latest
詳しいドキュメントは下記にあります。
Strapi API を Astro で使ってみる
Astro で、Strapi API からデータを取得して、ページをレンダリングする方法を簡単に試してみます。Astro のインストール手順などは省きます。
まず、src/lib
に Strapi.ts
を作成します。内容は下記のような感じで、Strapi API からデータを取得するための処理を記述します。
// src/libStrapi.ts
import type Article from "../interfaces/article";
export const fetchApi = async (): Promise<Article> => {
const url = import.meta.env.PUBLIC_STRAPI_URL;
const authToken = import.meta.env.STRAPI_API_KEY;
const key = {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${authToken}`
},
}
const res = await fetch(`${url}/articles`, key).catch((err) => {
console.error(err);
throw new Error("Failed to fetch data");
});
if (!res) {
throw new Error("No response from fetch");
}
const json = await res.json();
return json;
}
事前に .env
ファイルを作成し、環境変数、PUBLIC_STRAPI_URL
と STRAPI_API_KEY
を設定しておきましょう。PUBLIC_STRAPI_URL
には、API の ベース URL (今回の例だと https://strapi.example.com/api
) を、STRAPI_API_KEY
には、管理画面から取得した API のアクセストークンを指定します。
Strapi の API に関するリファレンスは下記にあります。
エンドポイントとしては、/api/:pluralApiId
へのリクエストで指定したコンテンツの一覧を取得できます。:pluralApiId
は、コンテンツタイプを作成するときに設定した、「API ID (Plural)」 の値ですね。
なので、今回のサンプルソースだと、https://strapi.example.com/api/articles
をエンドポイントとして指定しています。
なお、読み込んでいる型定義、src/interfaces/article.ts
の中身は下記のような感じです。ここは、作ったコンテンツタイプの設定によります。
title
、description
、content
、slug
の各項目は、私が 「Article」 コンテンツタイプを更新するために設定した各フィールドですが、あくまで例です。
// src/interfaces/article.ts
export default interface Article {
data: {
id: number;
title: string;
description: string;
content: string;
slug: string;
createdAt: string;
updatedAt: string;
publishedAt: string;
}[];
meta: {
pagination: {
page: number;
pageSize: number;
pageCount: number;
total: number;
};
};
}
あとは、src/pages
内で読み込んで使えば終わり。例えば、かなり雑ですが、下記のように。
// src/pages/index.astro
---
import Layout from "../layouts/Layout.astro";
import { fetchApi } from "../lib/Strapi";
const json = await fetchApi();
const articles = json.data;
---
<Layout title="Strapi Test">
<main>
<ul>
{
articles.map((article) => (
<li>
<a href={`/articles/${article.slug}/`}>{article.title}</a>
</li>
))
}
</ul>
</main>
</Layout>
実際の運用においては、Webhook の設定をはじめ、コンテンツの更新にあわせたビルド・デプロイの仕組みを用意しなければなりませんが、GitHub Actions、あるいは Varcel や Netlify などを利用すれば比較的手軽に環境構築は可能です。
ということで、簡単にですが Strapi をセルフホストするための環境構築からインストール手順、基本的な設定と Astro での使用例までまとめてみました。
今の時代、なるべくヘッドレスな CMS を使用して、Web サイトの構築や更新を Git ワークフロー内で完結したいわけですけども、Strapi はひとつの選択肢として使いやすいと思いますので、個人的にはオススメです。