前言#
以前のブログでは Typecho を使用していましたが、2024 年に偶然 Mix-Space というフロントエンドとバックエンドが分離された個人スペースを発見し、とても気に入ったので、ブログを移行しました。現在は成功裏にデプロイが完了し、同じようにデプロイしたい方々の助けになればと思います。|| また、自分自身のためのメモとして qwq||
この記事のチュートリアルは、バックエンドに Docker を使用してデプロイし、フロントエンドは Github Action を利用して Shiro を構築し、サーバーにプッシュする方法です(もちろん、より便利な Docker を選択することもできますが、クローズドソース版は提供されていません)。
Mix-Space と Shiro テーマ関連リンク#
Mix Space は小型の個人スペースサイトプログラムです。従来のブログプログラムとは異なり、フロントエンドとバックエンドが分離された設計を採用しており、異なるスタイルやタイプの執筆を好む愛好者に適しています。
Mix Space - An Alternative Personal Space - Mix Space 文書
Shiro は Innei によって制作された Mix Space にサービスを提供する個人サイトのフロントエンドです。
極めてミニマリストな個人サイトで、紙の純粋さと雪の新鮮さを体現しています。
1 Panel インストール#
公式サイトの オンラインインストール - 1Panel 文書 の手順を参考にしてください。ここでは Ubuntu システムを使用しているので、以下のコマンドを実行します。
curl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh && sudo bash quick_start.sh
指示に従って一歩ずつ進めてください。その間にいくつかのアカウントやパスワード、1 Panel のデフォルトポートなどを入力するよう求められますが、デフォルトを使用するためにそのまま Enter を押しても大丈夫です。すべてはパネル内で変更可能です。
最終的にログが出力され、その中にパネルのアドレス、ユーザー名、パスワードが含まれています。そのアドレスとアカウントを使用してパネルにログインできます。
バックエンド Core デプロイ#
Docker の確認とインストール#
私は Docker を使用してバックエンドをデプロイしており、これは推奨される方法です。
1 Panel パネルはデフォルトで Docker をインストールするため、すでにインストールされているかどうかを確認する必要はありません。
設定ファイルの取得と変更#
コマンドラインを使用してファイルを取得することも、1 Panel パネルを使用して取得することもできます。保存パスは自分で変更できます。
# ルートディレクトリに戻り、mx-space/core フォルダを作成し、core フォルダに移動します
cd && mkdir -p mx-space/core && cd $_
# docker-compose.yml ファイルを取得
wget https://fastly.jsdelivr.net/gh/mx-space/core@master/docker-compose.yml
docker-compose.yml 内の一部の内容を変更します。
services:
app:
container_name: mx-server
image: innei/mx-server:latest
environment:
- TZ=Asia/Shanghai
- NODE_ENV=production
- DB_HOST=mongo
- REDIS_HOST=redis
# 自分のブログのドメインを入力し、複数の場合はカンマで区切ります。ここにローカルアドレスを追加して自己アクセスを許可することもできます。
- ALLOWED_ORIGINS=blog.lolita.best,localhost:*,127.0.0.1:*
# 自分で生成した JWT 秘密鍵を入力します。16≤鍵の長さ≤32 文字(必ず自分の秘密鍵を保存し、漏洩しないようにしてください)
- JWT_SECRET=xxxxx
# 暗号化の関連設定を有効にするかどうか。ここではデフォルトで false と空にしておきます。暗号化が必要な場合は公式の設定文書を参照してください。
- ENCRYPT_ENABLE=false
- ENCRYPT_KEY=
volumes:
- ./data/mx-space:/root/.mx-space
ports:
#-'2333:2333' docker のポートマッピングを変更し、ポートを開放しません
- '127.0.0.1:2333:2333'
depends_on:
- mongo
- redis
networks:
- mx-space
restart: unless-stopped
healthcheck:
test: ['CMD', 'curl', '-f', 'http://127.0.0.1:2333/api/v2/ping']
interval: 1m30s
timeout: 30s
retries: 5
start_period: 30s
mongo:
container_name: mongo
image: mongo
volumes:
- ./data/db:/data/db
networks:
- mx-space
restart: unless-stopped
redis:
image: redis:alpine
container_name: redis
volumes:
- ./data/redis:/data
healthcheck:
test: ['CMD-SHELL', 'redis-cli ping | grep PONG']
start_period: 20s
interval: 30s
retries: 5
timeout: 3s
networks:
- mx-space
restart: unless-stopped
networks:
mx-space:
driver: bridge
Core の起動#
設定が完了したら、現在のディレクトリで以下のコマンドを使用して Core を起動します。
# その後、バックエンドを更新する必要がある場合や yaml 設定を変更してコンテナを更新する場合も同じコマンドを使用します
docker compose pull && docker compose up -d
起動に成功すると、1 Panel のコンテナ内で mx-server、redis、mongo の 3 つのコンテナの実行状況を確認できます。
これでバックエンドのデプロイが成功しました。
リバースプロキシ設定#
バックエンドのデプロイが完了したら、アクセスできるようにリバースプロキシを設定する必要があります。ここで SSL 証明書も一緒に取得します。
ウェブサイト証明書の申請#
1 Panel パネル内のウェブサイト / 証明書で直接証明書を申請できます。
まず、Acme アカウントを作成する必要があります。メールアドレスを入力した後、他はデフォルトのままで大丈夫です。
次に、証明書申請時の検証方法ですが、ここでは DNS アカウントの方法を使用します。DNS アカウントを作成する必要があります。パネル内では多くの DNS サービスプロバイダーがサポートされているので、自分のものを選択してください。ここでは CloudFLare を使用しています。
CloudFlare の API トークンは「アカウント管理 / アカウント API トークン」で申請できます。直接「DNS ゾーンの編集」テンプレートを使用します。
上記の手順が完了したら、準備が整ったので、証明書を申請し、自分のウェブサイトのドメインを入力してください。
ウェブサイトの作成とリバースプロキシの設定#
初めて 1 Panel を使用する場合、アプリストア内で OpenResty をインストールするように求められます。指示に従って直接インストールしてください。
静的ウェブサイトを作成することを選択し、ドメインを入力し、他はデフォルトのままで大丈夫です。
ウェブページ設定をクリックし、HTTPS に移動し、以前に申請した証明書を選択すれば SSL の設定が完了します。
次に、設定ファイルに移動し、以下の内容をコピーして最後に追加し、保存してリロードしてください(コメントの部分は自分のものに変更することを忘れないでください)。
ここでは単一ドメインの方法を使用しています。フロントエンドとバックエンドの二重ドメインが必要な場合は、公式の設定文書を参照してください。
# WebSocket アドレス
location /socket.io {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:2333/socket.io;
}
# API アドレス
location /api/v2 {
proxy_pass http://127.0.0.1:2333/api/v2;
}
# 簡易レンダリングアドレス
location /render {
proxy_pass http://127.0.0.1:2333/render;
}
# Shiro アドレス
location / {
proxy_pass http://127.0.0.1:2323;
}
# バックエンドアドレス
location /proxy {
proxy_pass http://127.0.0.1:2333/proxy;
}
location /qaqdmin { # 自分のバックエンドアドレスを変更する必要がある場合はここを変更できます
proxy_pass http://127.0.0.1:2333/proxy/qaqdmin;
}
# RSS アドレス
location ~* \/(feed|sitemap|atom.xml) {
proxy_pass http://127.0.0.1:2333/$1;
}
設定が完了したら、https://あなたのドメイン/qaqdmin
を通じてバックエンド管理アドレスにアクセスできるようになります。指示に従って対応する内容を入力してください。
フロントエンドデプロイ#
私は Shiro のクローズドソース版を使用し、Github Action の方法で自動デプロイを行っています。オープンソース版も以下の手順に従って行うことができるはずです。
Github で Shiroi-deploy-action リポジトリをフォークし、workflows ファイルを変更#
リポジトリアドレス:GitHub - innei-dev/shiroi-deploy-action
フォーク後、workflows フォルダ内の deploy.yml
ファイルを変更します。(変更が必要な部分には日本語のコメントが追加されています)
name: Build and Deploy
on:
workflow_dispatch: # 手動でワークフローを実行するために追加
push:
branches:
- main
# schedule:
# - cron: '0 3 * * *'
repository_dispatch:
types: [trigger-workflow]
permissions: write-all
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
PNPM_VERSION: 9.x.x
HASH_FILE: build_hash
jobs:
prepare:
name: Prepare
runs-on: ubuntu-latest
if: ${{ github.event.head_commit.message != 'Update hash file' }}
outputs:
hash_content: ${{ steps.read_hash.outputs.hash_content }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Read HASH_FILE content
id: read_hash
run: |
content=$(cat ${{ env.HASH_FILE }}) || true
echo "hash_content=$content" >> "$GITHUB_OUTPUT"
check:
name: Check Should Rebuild
runs-on: ubuntu-latest
needs: prepare
outputs:
canceled: ${{ steps.use_content.outputs.canceled }}
steps:
- uses: actions/checkout@v4
with:
repository: innei-dev/shiroi # アクセスしたいリポジトリを入力します。オープンソース版は innei/shiro です。
token: ${{ secrets.GH_PAT }} # `GH_PAT` はあなたの PAT を含む秘密です。
fetch-depth: 0
lfs: true
- name: Use content from prev job and compare
id: use_content
env:
FILE_HASH: ${{ needs.prepare.outputs.hash_content }}
run: |
file_hash=$FILE_HASH
current_hash=$(git rev-parse --short HEAD)
echo "File Hash: $file_hash"
echo "Current Git Hash: $current_hash"
if [ "$file_hash" == "$current_hash" ]; then
echo "Hashes match. Stopping workflow."
echo "canceled=true" >> $GITHUB_OUTPUT
else
echo "Hashes do not match. Continuing workflow."
fi
build:
name: Build artifact
runs-on: ubuntu-latest
needs: check
if: ${{needs.check.outputs.canceled != 'true'}}
strategy:
matrix:
node-version: [20.x]
outputs:
sha_short: ${{ steps.store.outputs.sha_short }}
branch: ${{ steps.store.outputs.branch }}
steps:
- uses: actions/checkout@v4
with:
repository: innei-dev/shiroi # アクセスしたいリポジトリを入力します。オープンソース版は innei/shiro です。
token: ${{ secrets.GH_PAT }} # `GH_PAT` はあなたの PAT を含む秘密です。
fetch-depth: 0
lfs: true
- name: Checkout LFS objects
run: git lfs checkout
- uses: pnpm/action-setup@v2
with:
version: ${{ env.PNPM_VERSION }}
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- uses: jongwooo/next-cache@v1
- name: Install dependencies
run: pnpm install
- name: Build project
run: |
sh ./ci-release-build.sh
# - uses: actions/upload-artifact@v4
# with:
# name: dist
# path: assets/release.zip
# retention-days: 7
- name: Cache Build Artifacts
id: cache-primes
uses: actions/cache/save@v4
with:
path: assets
key: ${{ github.run_number }}-release
- name: Store artifact commit version
shell: bash
id: store
run: |
sha_short=$(git rev-parse --short HEAD)
branch_name=$(git rev-parse --abbrev-ref HEAD)
echo "sha_short=$sha_short" >> "$GITHUB_OUTPUT"
echo "branch=$branch_name" >> "$GITHUB_OUTPUT"
deploy:
name: Deploy artifact
runs-on: ubuntu-latest
needs: build
steps:
# - name: Download artifact
# uses: actions/download-artifact@v4
# with:
# name: dist
- name: Restore cached Build Artifacts
id: cache-primes-restore
uses: actions/cache/restore@v4
with:
path: |
assets
key: ${{ github.run_number }}-release
- name: Move assets to root
run: mv assets/release.zip release.zip
- name: copy file via ssh password
uses: appleboy/[email protected]
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USER }}
password: ${{ secrets.PASSWORD }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
source: 'release.zip'
target: '/tmp/shiro'
- name: Exec deploy script with SSH
uses: appleboy/ssh-action@master
with:
command_timeout: 5m
host: ${{ secrets.HOST }}
username: ${{ secrets.USER }}
password: ${{ secrets.PASSWORD }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
#script_stop: true 改行指令を削除しました。この指令はすでに使用停止されており、警告が表示されますが、影響はありません。変更しなくても大丈夫です。
script: |
set -e
export NVM_DIR=~/.nvm # .nvm のインストールディレクトリを定義します。そうしないと、ターミナル実行時にインストールされていてもコマンドが見つからないことがあります。
source ~/.nvm/nvm.sh # nvm コマンドを認識させます。そうしないと、command not found エラーが発生する可能性があります。
source $HOME/.bashrc
basedir=$HOME/mx-space/shiro # 自分が希望するパスを入力します。私のバックエンドファイルは mx-space にあるので、shiro も mx-space フォルダ内に置きたいと思います。管理が便利です。
workdir=$basedir/${{ github.run_number }}
mkdir -p $workdir
mkdir -p $basedir/.cache
mv /tmp/shiro/release.zip $workdir/release.zip
rm -r /tmp/shiro
cd $workdir
unzip -qq -o $workdir/release.zip
rm -rf $workdir/standalone/.env
ln -s $HOME/mx-space/shiro/.env $workdir/standalone/.env # .env ファイルのパス。私は mx-space/shiro フォルダ内に保存しています。管理が便利です。
export NEXT_SHARP_PATH=$(npm root -g)/sharp
# workdir の ecosystem.config.js を basedir にコピーします。存在しない場合のみ。
if [ ! -f $basedir/ecosystem.config.js ]; then
cp $workdir/standalone/ecosystem.config.js $basedir/ecosystem.config.js
fi
# https://github.com/Unitech/pm2/issues/3054
# workdir のノードエントリファイルを basedir にシンボリックリンクします。
ln -sf $workdir/standalone/server.js $basedir/server.js
mkdir -p $workdir/standalone/.next
rm -rf $workdir/standalone/.next/cache
ln -sf $basedir/.cache $workdir/standalone/.next/cache
cd $basedir
pm2 reload ecosystem.config.js --update-env
rm $workdir/release.zip
pm2 save
echo "Deployed successfully"
- name: After deploy script
run: |
hash=${{ needs.build.outputs.sha_short }}
# curl -X "POST" "https://mx.innei.in/api/v2/fn/shiro/new-version-hook" -H 'Content-Type: application/json' -d "{\"hash\": \"$hash\", \"key\": \"\"}"
${{ secrets.AFTER_DEPLOY_SCRIPT }}
store:
name: Store artifact commit version
runs-on: ubuntu-latest
needs: [deploy, build]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false # そうしないと、使用されるトークンは GITHUB_TOKEN になり、あなたの個人トークンではなくなります。
fetch-depth: 0 # そうしないと、リファレンスをデスティネーションリポジトリにプッシュできません。
# ビルドジョブからコミットバージョンを取得します。
- name: Use outputs from build
env:
SHA_SHORT: ${{ needs.build.outputs.sha_short }}
BRANCH: ${{ needs.build.outputs.branch }}
run: |
echo "SHA Short from build: $SHA_SHORT"
echo "Branch from build: $BRANCH"
- name: Write hash to file
env:
SHA_SHORT: ${{ needs.build.outputs.sha_short }}
run: echo $SHA_SHORT > ${{ env.HASH_FILE }}
- name: Commit files
run: |
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add ${{ env.HASH_FILE }}
git commit -a -m "Update hash file"
- name: Push changes
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.ref }}
ワークフローの Secrets を設定#
HOST
サーバーアドレスUSER
サーバーユーザー名PASSWORD
サーバーパスワードPORT
サーバー SSH ポートKEY
サーバー SSH キー(オプション、パスワードまたはキーのいずれかを選択)GH_PAT
以前のリポジトリにアクセスするための Github トークン
.env ファイルの設定#
1 Panel に戻り、ワークフロー内で指定した場所に .env
ファイルを作成し、以下の内容をコピーして自分の内容に変更します。
上記は root/mx-space/shiro です。
# バックエンド API アドレス
NEXT_PUBLIC_API_URL=https://blog.lolita.best/api/v2
# バックエンドゲートウェイアドレス
NEXT_PUBLIC_GATEWAY_URL=https://blog.lolita.best
# TMDB 情報取得
TMDB_API_KEY=あなたの TMDB-API を入力
# GitHub トークン、フロントエンドバージョンハッシュを取得するため
GH_TOKEN=あなたのトークンを入力
サーバーに必要な環境をインストール#
Shiro テーマを自分でデプロイするには Node.js
, npm
, pnpm
, pm2
, sharp
をインストールする必要があります。
1 Panel のターミナル内で以下のコマンドを入力してインストールできます。
現在 Node.js 公式サイト でもインストール方法が提供されていますので、指示に従ってください。
# nvm をダウンロードしてインストールします:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
# シェルを再起動する代わりに
\. "$HOME/. Nvm/nvm. Sh"
# Node.js をダウンロードしてインストールします:
Nvm install 23
# Node.js バージョンを確認します:
Node -v # "v 23.8.0" と表示されるはずです。
Nvm current # "v 23.8.0" と表示されるはずです。
# pnpm をダウンロードしてインストールします:
Corepack enable pnpm
# pnpm バージョンを確認します:
Pnpm -v
# 以下は追加の補足内容です
npm i -g pm2 # pm2 をインストールします
npm i -g sharp # sharp をインストールします
ワークフロー内で unzip を使用して解凍操作を行っているため、サーバーに unzip がインストールされているか確認する必要があります。そうでないとエラーが発生します。
# ソフトウェアパッケージを更新し、unzip をインストールします
sudo apt update && sudo apt install -y unzip
# 以下のコマンドでインストールされているか確認します
unzip -v
ワークフローを起動#
GitHub 内で手動でワークフローを実行し、ワークフローが完了するのを待ちます。エラーが出なければ成功です。
管理バックエンドで Shiro テーマのクラウド関数を設定#
Warning
注意
クラウド関数の設定変更は即時に反映されず、時間がかかる場合がありますので、しばらくお待ちください。
Shiro テーマはクラウド関数と連携して使用する必要があります。管理バックエンド / 追加機能 / 設定とクラウド関数内に入り、関連ファイルをインポートします。
右上の新規ボタンをクリックし、編集ページで以下の設定を入力します。
- 名前:shiro
- 引用:theme
- データタイプ:JSON
- データ:右側にある以下の例をコピーし、自分の情報に変更します。
データ内容の参考:設定 - Mix Space 文書
{
"footer": {
"otherInfo": {
"date": "2019-{{now}}",
"icp": {
"text": "萌ICP备20248012号",
"link": "https://icp.gov.moe/?keyword=20248012"
}
},
"linkSections": [
{
"name": "关于",
"links": [
{
"name": "关于本站",
"href": "/about-site"
},
{
"name": "关于我",
"href": "/about",
"external": true
}
]
},
{
"name": "更多",
"links": [
{
"name": "时间线",
"href": "/timeline"
},
{
"name": "友链",
"href": "/friends",
"external": true
}
]
},
{
"name": "联系",
"links": [
{
"name": "写留言",
"href": "/message",
"external": true
},
{
"name": "发邮件",
"href": "mailto:[email protected]",
"external": true
},
{
"name": "GitHub",
"href": "https://github.com/Sumikanya",
"external": true
}
]
}
]
},
"config": {
"color": {
"light": [
"#33A6B8",
"#FF6666",
"#26A69A",
"#fb7287",
"#69a6cc",
"#F11A7B",
"#78C1F3",
"#FF6666",
"#7ACDF6"
],
"dark": [
"#F596AA",
"#A0A7D4",
"#ff7b7b",
"#99D8CF",
"#838BC6",
"#FFE5AD",
"#9BE8D8",
"#A1CCD1",
"#EAAEBA"
]
},
"bg": [
"https://github.com/Innei/static/blob/master/images/F0q8mwwaIAEtird.jpeg?raw=true",
"https://github.com/Innei/static/blob/master/images/IMG_2111.jpeg.webp.jpg?raw=true"
],
"custom": {
"css": [],
"styles": [],
"js": [],
"scripts": []
},
"site": {
"favicon": "https://cn.cravatar.com/avatar/08d99bea604c306b51ebe162e93412f1?s=36",
"faviconDark": "https://cn.cravatar.com/avatar/08d99bea604c306b51ebe162e93412f1?s=36"
},
"hero": {
"title": {
"template": [
{
"type": "h1",
"text": "Hi, I'm ",
"class": "font-light text-4xl"
},
{
"type": "h1",
"text": "星野纯夏",
"class": "font-medium mx-2 text-4xl"
},
{
"type": "h1",
"text": "💕。",
"class": "font-light text-4xl"
},
{
"type": "br"
},
{
"type": "h1",
"text": "一个喜欢科技数码的Lo娘 ",
"class": "font-light text-4xl"
},
{
"type": "code",
"text": "🦋<INFP>🦋",
"class": "font-medium mx-2 text-3xl rounded p-1 bg-gray-200 dark:bg-gray-800/0 hover:dark:bg-gray-800/100 bg-opacity-0 hover:bg-opacity-100 transition-background duration-200"
},
{
"type": "span",
"class": "inline-block w-[1px] h-8 -bottom-2 relative bg-gray-800/80 dark:bg-gray-200/80 opacity-0 group-hover:opacity-100 transition-opacity duration-200 group-hover:animation-blink"
}
]
},
"description": "希望在这个世界上可以留下属于我的痕迹",
"Hitokoto": {
"random": true,
"custom": "自定义一言"
}
},
"module": {
"activity": {
"enable": true,
"endpoint": "/fn/ps/update"
},
"donate": {
"enable": false,
"link": "https://afdian.net/@Innei",
"qrcode": [
"https://cdn.jsdelivr.net/gh/Innei/img-bed@master/20191211132347.png",
"https://cdn.innei.ren/bed/2023/0424213144.png"
]
},
"bilibili": {
"liveId": 19781
}
}
}
}
PM2
サービスを再起動後にプロセスを復元する設定#
pm2 startup
pm2 save
Shiro を手動で起動するにはどうすればよいですか? Shiro のフロントエンドパスに入り、以下のコードを実行します。
デフォルトでは GitHub のワークフロー設定内ですでに起動されています。
pm2 start ecosystem.config.js
現在実行中のプロセスを確認するには、以下のコマンドを使用できます。
pm2 list
デプロイ完了#
フロントエンドとバックエンドの両方が成功裏にデプロイされた後、あなたのウェブサイトに直接アクセスして現在の効果を確認できます。
参考リンク#
公式およびその他の関連チュートリアルに感謝します
Mix-Space デプロイ最新フロントエンド Shiro - 华岁云小屋
Github Action を使用して Shiroi を構築およびデプロイする試み - 华岁云小屋
Mix Space - An Alternative Personal Space - Mix Space 文書
mx-space + Shiro:紙のように純粋な新しいブログ・Arthals' ink
Shiroi デプロイの大まかな流れと補足 - Ethan
WordPress から Mix Space へのデータ移行 - FoskyM's Blog
この記事は Mix Space によって xLog に同期更新されました。
元のリンクは https://blog.lolita.best/posts/blog/MxspaceDeployShiro