余白の間:1PanelでYohaku/Shiroiテーマをデプロイする完全ガイド
Noteこれは「Mix Space + Yohaku デプロイシリーズ」の第二弾で、フロントエンドテーマYohakuのインストールに焦点を当てています。バックエンドがまだデプロイされていない場合は、まず第一弾をお読みください——『ゼロから始める · 1PanelでMix Spaceバックエンドをデプロイ』
Yohakuは、日本語の「余白」に由来します。意図的に空けられた空間は、しばしば埋め尽くされた部分よりも大きな意味を持つものです。
これはMix Spaceエコシステムにおける最新世代のフロントエンドテーマです。その物語はオープンソースのShiroから始まり、クローズドソースのスポンサー版Shiroiでの熟成を経て、今日のYohakuへと進化しました。三代にわたる継承の中で、デザイン言語と実装は各段階で静かに反復されてきました。サイト全体は「書くこと」をメタファーとしており、ページはゆっくりと開かれる手紙のように、抑制の効いた色彩と呼吸するようなアニメーションで、読むことそのものを主役にしています。
三代のテーマの関係を簡単に整理します:
- Shiro → Mix Space最初のオープンソースフロントエンドテーマ。コードはGitHubで公開
- Shiroi → Shiroのクローズドソースドネーション版。Shiroをベースに進化し、スポンサーになるとアクセス可能
- Yohaku(余白) → Shiro / Shiroiからさらに進化した全く新しいデザイン。同じくクローズドソースのスポンサー形式でメンテナンスされており、現在最新の世代です
この記事でデプロイする主役はYohakuです。クローズドソーステーマであるため、Dockerイメージを自分でビルドする必要があります。以下で手順を追って説明します。(このチュートリアルはShiroiにも対応しています)
前提説明:この記事では、クローズドソース版リポジトリへのアクセス権を持っており、Mix Spaceバックエンドのデプロイが完了していて、以下の二つのアドレスが手元にあることを前提としています:
バックエンドAPIアドレス:形式https://あなたのドメイン/api/v3(バックエンドバージョンV13以前はv2)バックエンドゲートウェイアドレス:形式https://あなたのドメイン
バックエンドがまだデプロイされていない場合は、まず第一弾を読んで完了させてください。
第一步 · Dockerイメージのビルド
(オープンソース版Shiroを使用する場合は、直接第二步に進んでください) 作者がShiroi / Yohakuテーマの事前ビルド済みDockerイメージを提供していないため、自分でビルドする必要があります。しかし、低スペックサーバー上で直接ビルドしないでください——サーバーのメモリがパンクします 💥
私たちの解決策は、GitHub Actionsを利用してクラウド上でビルドを完了させ、イメージをGitHub Packages(ghcr.io)のプライベートリポジトリにプッシュすることです。サーバーは完成したイメージをプルするだけで済むため、非常に簡単です。
1.1 リポジトリの準備
以下のリポジトリにアクセスし、右上のForkをクリックします:
次に、以下のリンクから新しいリポジトリを作成します(Choose visibility は必ず Private を選択してください!!!)。名前は yohaku にすることを推奨します。異なる場合は、後続のワークフローファイルで対応する修正を行ってください。
1.2 GitHubクラシックアクセストークン(Classic Token)の申請
ActionsがShiroiプライベートリポジトリを読み取り、ビルドしたイメージをGitHub Packagesにプッシュするには権限が必要です。事前にクラシックトークン(Classic Token)を準備します。
https://github.com/settings/tokens/new にアクセスします。
メモ(例:yohaku-build)を入力し、有効期限を無期限に設定して、以下の権限にチェックを入れます:
| 権限 | 用途説明 |
|---|---|
repo | リポジトリの読み書き(プライベートリポジトリへのアクセスを含む) |
workflow | GitHub Actionワークフローの更新 |
write:packages | GitHub Packagesへのイメージプッシュ |
read:packages | GitHub Packagesからのイメージプル |
Generate tokenをクリックし、生成されたTokenをすぐにコピーして安全に保管してください——この一度しか表示されません!
1.3 リポジトリActions変数の設定
Forkしたリポジトリに移動し、順にクリックします:
Settings → Secrets and variables → Actions → Repository secrets
以下の二つの変数を追加します:
| 変数名 | 入力内容 |
|---|---|
BASE_URL | Coreバックエンドがバインドされているドメイン(例:https://jiye.funcun.top) |
GH_PAT | 前の手順で申請したPersonal Access Token |
NEXT_PUBLIC_GATEWAY_URL | オプション、例:https://jiye.funcun.top |
NEXT_PUBLIC_API_URL | オプション、例:https://jiye.funcun.top/api/v3 |
新しく作成したYohakuリポジトリに移動し、先ほどと同様に変数を追加します。
| 変数名 | 入力内容 |
|---|---|
UPSTREAM_REPO_SECRET | 前の手順で申請したPersonal Access Token |
1.4 ビルドの有効化とトリガー
まず、新しく作成したYohakuリポジトリに移動し、Forkリポジトリ内のupstream-sync.ymlファイルをそのリポジトリにアップロードします。次に、サーバーまたは他のデバイスで以下のスクリプトを実行し、プロンプトに従って入力します(デフォルトオプションがある場合はデフォルトを推奨します)。
#!/bin/bash
set -euo pipefail
# =============================================
# スクリプト紹介:
# このスクリプトは、上流リポジトリの指定ブランチを、あなたの個人リポジトリのターゲットブランチに強制的に同期するために使用します。
# 公開/プライベートの上流リポジトリから更新をプルし、自分のブランチにプッシュする(ミラー同期など)場合に適しています。
# 強制プッシュはターゲットブランチの履歴を上書きします。注意して操作してください!
# =============================================
echo "======================================="
echo " 上流リポジトリ → 個人リポジトリ 強制同期ツール"
echo "======================================="
echo ""
echo "このスクリプトは以下の操作を実行します:"
echo "1. 上流リポジトリを一時ディレクトリにクローン"
echo "2. あなたの個人リモートリポジトリを追加"
echo "3. 上流ブランチを個人リポジトリのターゲットブランチに強制プッシュ"
echo "注意:ターゲットブランチの既存の内容は完全に上書きされます!"
echo "======================================="
echo ""
# ---------- あなたの個人リポジトリ情報を収集 ----------
read -r -p "あなたのGitHubユーザー名を入力してください: " USERNAME
read -r -p "あなたのターゲットリポジトリ名を入力してください: " REPO
echo "あなたのGitHub Personal Access Tokenを入力してください(入力時は表示されません。repo権限が必要です):"
read -r -s TOKEN
echo # 改行
# ---------- 上流リポジトリ情報を収集 ----------
read -r -p "上流リポジトリはプライベートですか?(y/n、デフォルト n): " UPSTREAM_PRIVATE
UPSTREAM_PRIVATE=${UPSTREAM_PRIVATE:-n}
read -r -p "上流リポジトリの完全なアドレスを入力してください(例:https://github.com/innei-dev/Yohaku.git): " UPSTREAM
if [ "$UPSTREAM_PRIVATE" = "y" ] || [ "$UPSTREAM_PRIVATE" = "Y" ]; then
echo "上流リポジトリはプライベートです。そのリポジトリにアクセスするためのTokenを入力してください(入力時は表示されません):"
read -r -s UPSTREAM_TOKEN
echo
# 認証付きの上流URLを構築
UPSTREAM_AUTH_URL=$(echo "$UPSTREAM" | sed "s|https://|https://x-access-token:${UPSTREAM_TOKEN}@|")
else
UPSTREAM_AUTH_URL="$UPSTREAM"
fi
read -r -p "一時ディレクトリ名を入力してください(デフォルト temp-upstream): " TEMP_DIR
TEMP_DIR=${TEMP_DIR:-temp-upstream}
read -r -p "上流リポジトリのブランチ名を入力してください(デフォルト main): " SRC_BRANCH
SRC_BRANCH=${SRC_BRANCH:-main}
read -r -p "個人リポジトリにプッシュするターゲットブランチ名を入力してください(デフォルト sync): " DST_BRANCH
DST_BRANCH=${DST_BRANCH:-sync}
# ---------- 個人リモートアドレスを構築 ----------
MY_REMOTE="https://${USERNAME}:${TOKEN}@github.com/${USERNAME}/${REPO}.git"
# ---------- 一時ディレクトリの処理 ----------
while [ -d "$TEMP_DIR" ] && [ "$(ls -A "$TEMP_DIR" 2>/dev/null)" ]; do
echo ""
echo "警告:ディレクトリ '$TEMP_DIR' は既に存在し、空ではありません。"
read -r -p "削除して再作成しますか?(y/n): " answer
if [ "$answer" = "y" ] || [ "$answer" = "Y" ]; then
rm -rf "$TEMP_DIR"
echo "古いディレクトリを削除しました。"
else
read -r -p "新しい一時ディレクトリ名を入力してください: " TEMP_DIR
fi
done
# ---------- 同期の実行 ----------
echo ""
echo "上流リポジトリ $UPSTREAM を $TEMP_DIR にクローンしています..."
git clone "$UPSTREAM_AUTH_URL" "$TEMP_DIR"
cd "$TEMP_DIR"
echo "あなたのリモートリポジトリ myrepo を追加しています..."
git remote add myrepo "$MY_REMOTE"
echo "$SRC_BRANCH -> myrepo/$DST_BRANCH を強制プッシュしています..."
git push --force myrepo "$SRC_BRANCH:$DST_BRANCH"
cd ..
echo "一時ディレクトリ $TEMP_DIR をクリーンアップしています..."
rm -rf "$TEMP_DIR"
echo ""
echo "======================================="
echo "同期完了!"
echo "$UPSTREAM の $SRC_BRANCH ブランチを"
echo "$USERNAME/$REPO の $DST_BRANCH ブランチに強制プッシュしました。"
echo "======================================="
完了したら、ForkリポジトリのActionsタブに移動し、プロンプトが表示されたらクリックして有効にします。次に、ビルドWorkflowを見つけ、右側のRun workflowをクリックして手動でトリガーします。
ビルドプロセスには通常5〜10分かかります。お茶でも淹れて待ちましょう ☕
ビルドが完了すると、リポジトリのサイドバーにあるPackagesであなたのイメージを確認できます。アドレス形式は以下の通りです:
ghcr.io/あなたのユーザー名(全て小文字)/yohaku:latest
1.5 1Panelでのghcr.ioプライベートリポジトリ設定
イメージはプライベートGitHub Container Registryに保存されているため、1Panelがプルするには事前にログイン認証が必要です。
1Panelパネルにログインし、コンテナ → リポジトリ → リポジトリを作成に移動し、以下を入力します:
| フィールド | 内容 |
|---|---|
| 名前 | ghcr.io(任意の識別しやすい名前) |
| リポジトリアドレス | ghcr.io |
| ユーザー名 | あなたのGitHubユーザー名 |
| パスワード | あなたのPersonal Access Token(GH_PAT) |
保存すると、1Panelが自動的に接続を検証します。これで、今後プライベートイメージのプルがスムーズになります 🔐
第二步 · 1PanelでYohakuをインストール
2.1 アプリケーションパッケージのアップロード
1Panelパネルにログインし、左側のメニューからホスト → ファイルに移動し、次のパスにナビゲートします:
/opt/1panel/resource/apps/local
アップロードをクリックし、Forkしたリポジトリからダウンロードしたyohaku.zipファイルを選択します。
2.2 解凍、パスに注意!
アップロードが完了したら、yohaku.zipをクリックし、解凍を選択します。
この手順は初心者が最もつまずきやすいポイントです。必ず注意してください!
解凍時には、ターゲットパスを手動で以下のように補完する必要があります:
/opt/1panel/resource/apps/local/yohaku
パスが正しくないと、誤ったディレクトリにファイルが散らばり、アプリストアがこのローカルアプリを認識できなくなる可能性があります。
2.3 ローカルアプリの同期
1Panelアプリストアに移動し、右上のローカルアプリを同期ボタンをクリックします。しばらく待ってから検索ボックスにyohakuと入力すると、追加したばかりのアプリが表示されます。
インストールをクリックし、設定ページに進みます。
2.4 インストール設定項目の入力
インストールページには4つの必須項目(および読み取り専用の説明が1つ)があります。上から順に入力します:
🐳 イメージアドレス(Image Address)
ここにコンテナイメージを入力します。デプロイするバージョンに応じて選択します:
オープンソース版 Shiro(公式の事前ビルドイメージを直接使用):
innei/shiro:latest
クローズドソース版 Shiroi / Yohaku(第一步で自分でビルドしたプライベートイメージを入力):
ghcr.io/あなたのユーザー名(全て小文字)/shiroi:latest
📡 公開APIアドレス(PUBLICAPIURL)
あなたのMix SpaceバックエンドAPIアドレスを入力します:
https://あなたのバックエンドドメイン/api/v2
末尾の/api/v2パスを保持することに注意してください。
🌐 公開ゲートウェイアドレス(PUBLICGATEWAYURL)
あなたのMix Spaceバックエンドゲートウェイアドレス(つまりバックエンドのルートドメイン)を入力します:
https://あなたのバックエンドドメイン
パスサフィックスを追加する必要はありません。
🔗 API URLとクライアントAPIアドレス
API_URLとNEXT_PUBLIC_CLIENT_API_URLの二つの項目の値は、公開APIアドレスと同じにします。同じ内容を入力してください:
https://あなたのバックエンドドメイン/api/v2
2.5 インストール開始 🎉
設定に間違いがないか確認し、インストール開始をクリックします。
1Panelが自動的にイメージをプルし、コンテナを起動します。このプロセスはネットワーク状況によって数分かかる場合があります。ステータスが実行中(Running)と表示されれば、Yohakuは正式に公開されました!
第三步 · リバースプロキシとHTTPSの設定
前回のブログ記事を参照してください。設定済みの場合はスキップできます。
附:Yohakuがサポートする拡張Markdown記法
YohakuはShiro体系から継承しており、あなたのブログ投稿をプレーンテキスト以上のものにする、豊富な拡張Markdown記法をサポートしています。以下は、執筆時に使用できる特徴的な記法です——
数学公式(KaTeX)
インライン公式:
質量エネルギー方程式 $E = mc^2$ は、人類の宇宙に対する認識を変えました。
ブロックレベル公式:
$$
\int_{-\infty}^{+\infty} e^{-x^2} dx = \sqrt{\pi}
$$
ヒントバナー(Notice / Banner)
::: warning
ここは警告内容です。背景は目立つ色で表示されます。
:::
::: banner {note}
ここは備考です。追加の説明を添えるのに適しています。
:::
::: banner {error}
ここはエラープロンプトです。危険な操作を強調するために使用します。
:::
GFM Alert 記法
> [!NOTE]
> これは備考です。読者に特定の事項に注意を促します。
> [!IMPORTANT]
> これは重要な情報です。見逃せません。
> [!WARNING]
> これは警告です。潜在的なリスクが含まれる可能性があります。
ネタバレマスク(Spoiler)
この映画の結末は ||主人公は実はすでに死んでいた|| という、意外なものでした。
注意:これは取り消し線~~テキスト~~の効果とは異なります。Spoilerはマスクで内容を隠し、マウスオーバーしたときにのみ表示されます。
リッチリンク(Rich Link)
独立した行にあるリンクについて、Yohakuは自動的にカバー画像と要約付きのカードスタイルでレンダリングします:
https://github.com/Innei/Yohaku
認識可能なプラットフォームには、GitHubリポジトリ、コミット、Issue、Gist、そしてYouTube、Twitterなどが含まれます。
インラインリンクアイコン
インラインリンクには、自動的に対応ウェブサイトのFaviconが付与されます:
[Inneiのホームページ](https://innei.in) にアクセスして詳細をご覧ください。
メンション(Mention)
[Innei]{GH@Innei} がこんなに美しいテーマを作ってくれたことに感謝します。
GH@ユーザー名 は、自動的にアバター付きのGitHubユーザーカードとしてレンダリングされます。
折りたたみブロック(Collapse)
<details>
<summary>クリックして展開し、詳細を表示</summary>
ここに折りたたまれた詳細な説明があります……
</details>
よくある質問
Q:イメージのプル速度が極端に遅い、または失敗する場合は?
国内サーバーでghcr.ioをプルする場合、遅くなることがあります。GitHub ActionsのビルドWorkflowに、Alibaba Cloud ACRへの同期プッシュ手順を追加し、Alibaba Cloudからプルすることができます。具体的な設定は薄荷の小屋のチュートリアルを参照してください。
Q:Actionsビルドが失敗した場合、どのようにトラブルシューティングしますか?
リポジトリのActionsページに移動し、失敗したWorkflowをクリックして詳細なログを確認します。一般的な原因は以下の通りです:
GH_PATの権限が不足している。repoとwrite:packagesにチェックが入っているか確認してくださいDOCKER_NAMESPACEが全て小文字になっていない- リポジトリが公開に設定されており、権限の競合が発生している
Q:解凍後にアプリストアでyohakuが検索できない?
おそらく解凍パスが間違っています。解凍先が/opt/1panel/resource/apps/local/yohakuであることを確認してください(/opt/1panel/resource/apps/localではありません)。確認後、再度「ローカルアプリを同期」をクリックしてください。
Q:ページにはアクセスできるが、バックエンド接続失敗のプロンプトが表示される?
以下の点を確認してください:
- 4つのAPIアドレス設定項目が正しく入力されているか。特に
/api/v2パスが欠落していないか - Mix Spaceバックエンドの
ALLOWED_ORIGINSに、Yohakuフロントエンドのドメインが含まれているか - バックエンドのリバースプロキシとHTTPS証明書が正常に動作しているか
Q:error.api_fetchError Not found というエラーが発生する?
これはソースコードのバグです。手記を一つ公開すれば直ります...
参考資料
この記事の執筆にあたり、以下の資料を参考にしました。寛大に共有してくださったブロガーの皆様に感謝します 💝
- 1Panel オンラインインストールドキュメント
- GitHub Action で Shiroi Docker イメージをビルド · Mikuの極光星
- Mix Space + Shiro 完全コンテナ化デプロイガイド · 薄荷の小屋
- 1Panel アプリのセルフサービス作成 · FIT2CLOUD コミュニティフォーラム
- 1Panel アプリセルフサービス作成ツール
- Shiro Markdown 拡張記法ドキュメント
- Yohaku テーマドキュメント
- NEXT_PUBLIC_CLIENT_API_URL の追加
- API_URL の追加
- 雑談 | Actions で上流プロジェクトを同期し、自分のブランチにマージする
- GitHub Actions で Yohaku の Docker イメージをビルド
余白は、一つの態度です。 あなたのブログもまた、丁寧に開かれるに値する一通の手紙となりますように 🌿
