Meilisearch セットアップ
Hetzner US(Ashburn)の VPS で Meilisearch を Docker セルフホストし、
Cloudflare Tunnel 経由で Cloudflare Workers (subseek-api) から到達する構成。
アーキテクチャ概要
Cloudflare Workers (subseek-api / subseek-api-staging)
│
│ HTTPS (Cloudflare 内部ネットワーク)
▼
meili.subseek.cc / meili-staging.subseek.cc
(Cloudflare DNS + CNAME)
│
│ Cloudflare Tunnel (cloudflared)
▼
Hetzner VM 上の cloudflared (systemd)
│
│ http://localhost:7700 / :7701
▼
Meilisearch コンテナ (Docker, 127.0.0.1 バインド)
Why Cloudflare Tunnel か
Cloudflare Workers の fetch() は HTTP(平文)+ 直 IP + 非標準ポート の宛先に対し、
Cloudflare のエッジネットワーク経由で Cloudflare 1003 ページ
(error code: 1003 = "Direct IP access not allowed")を返してしまうケースがある。
Hetzner VM 上の Meilisearch を http://<HETZNER_VM_IP>:7700 で直接呼ぼうとすると
Workers 側で SyntaxError: ... is not valid JSON が発生し検索が壊れる。
Cloudflare Tunnel を使うと:
- 経路の大半が Cloudflare 内部ネットワーク → Workers から確実に到達
- 自動 HTTPS 化(証明書管理不要)
- VM 側の inbound ポートを完全に閉じられる(Tunnel は outbound のみで成立)
サーバー情報
| 項目 | 値 |
|---|---|
| プロバイダー | Hetzner Cloud |
| プロジェクト | subseek |
| サーバー名 | meilisearch |
| ロケーション | Ashburn, VA(us-east) |
| プラン | CPX11(Shared, Regular Performance) |
| OS | Ubuntu 24.04 |
| IPv4 | <HETZNER_VM_IP> |
コンテナ構成
1台の VM 上で Production / Staging の2コンテナを起動する。いずれも 127.0.0.1 限定バインドで、
外部ネットワークからは直接到達不可。Cloudflare Tunnel 経由でのみ公開される。
| 環境 | コンテナ名 | バインド | MEILI_ENV |
|---|---|---|---|
| Production | meilisearch-production | 127.0.0.1:7700 | production |
| Staging | meilisearch-staging | 127.0.0.1:7701 | development |
| Development | ローカル Docker | 0.0.0.0:7700 | development |
初回セットアップ手順
Phase 1. SSH 接続
ssh root@`<HETZNER_VM_IP>`
Phase 2. Docker インストール
curl -fsSL https://get.docker.com | sh
Phase 3. Meilisearch 起動(localhost バインド)
mkdir -p /opt/meilisearch/data/{production,staging}
# マスターキー生成
PROD_KEY=$(openssl rand -hex 32)
STG_KEY=$(openssl rand -hex 32)
echo "Production MEILI_MASTER_KEY: $PROD_KEY"
echo "Staging MEILI_MASTER_KEY: $STG_KEY"
# Production(127.0.0.1:7700)
docker run -d \
--name meilisearch-production \
--restart unless-stopped \
-p 127.0.0.1:7700:7700 \
-v /opt/meilisearch/data/production:/meili_data \
-e MEILI_MASTER_KEY="$PROD_KEY" \
-e MEILI_ENV=production \
getmeili/meilisearch:v1.13
# Staging(127.0.0.1:7701)
docker run -d \
--name meilisearch-staging \
--restart unless-stopped \
-p 127.0.0.1:7701:7700 \
-v /opt/meilisearch/data/staging:/meili_data \
-e MEILI_MASTER_KEY="$STG_KEY" \
-e MEILI_ENV=development \
getmeili/meilisearch:v1.13
重要:
MEILI_MASTER_KEYの値は安全な場所に保管すること。docker inspectで後から確認可能だが、紛失すると API キーの再取得ができなくなる。
Why
127.0.0.1:プレフィックスが必須か: Docker は-p 7700:7700のように IP を省略すると iptables を直接操作して ufw のルールを bypass し、外部からアクセス可能になる。Tunnel のみで公開する 構成では必ず-p 127.0.0.1:7700:7700の形でバインドし、ホスト側ループバックに 限定する必要がある。
Phase 4. ローカル動作確認
curl localhost:7700/health # → {"status":"available"}
curl localhost:7701/health # → {"status":"available"}
Phase 5. Cloudflare Tunnel セットアップ
Phase 5.1. cloudflared インストール
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
. /etc/os-release
echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared $UBUNTU_CODENAME main" | tee /etc/apt/sources.list.d/cloudflared.list
apt-get update
apt-get install -y cloudflared