# ドメイン設定（お名前.com + Cloudflare Tunnel + Synology NAS）

> 最終更新: 2026-03-30（HTTPS 対応・ドメイン割り当て完了）

## 全体構成図

```
[ブラウザ / Alexa / 外部API]
    │
    │ HTTPS (koh-devvv.com)
    ▼
[Cloudflare Edge]
    │ SSL終端（Let's Encrypt 自動発行・自動更新）
    │ CDN + DDoS防御
    ▼
[Cloudflare Tunnel]
    │ cloudflared コンテナがCloudflareへの
    │ 外向き接続を維持（ポート開放不要）
    ▼
[Synology NAS DS220+]  192.168.11.200
    │
    │ cloudflared → https://192.168.11.200:8443
    ▼
[Docker: match_12]
    │ Nginx（自己署名SSL証明書）
    │   :80 (→8080)  → HTTPS へ 301 リダイレクト
    │   :443 (→8443) → Laravel アプリ（HTTPS）
    │   :8080(→8085) → Laravel Reverb WebSocket
    ▼
[Laravel 12 アプリ]
    ├── Web UI
    ├── /api/alexa-zundamon/webhook
    ├── Claude AI（応答テキスト生成）
    └── VOICEVOX :50021（音声合成）
```

### 接続方式の比較

```
【従来】ポート転送方式（クロスパス回線では不可）
  外部 → ルーター:443 → NAS:443 → DSMリバースプロキシ → Docker:8080

【現在】Cloudflare Tunnel 方式（ポート開放不要）★採用
  外部 → Cloudflare Edge(SSL終端) → Tunnel → cloudflared → Docker:8443(HTTPS)

【LAN内アクセス】
  http://192.168.11.200:8080  → 301 → https://192.168.11.200/（ポート指定なし）
  https://192.168.11.200:8443 → 直接アクセス（自己署名証明書の警告あり）
```

---

## ドメイン・環境情報

| 項目 | 値 |
|------|-----|
| ドメイン | `koh-devvv.com` |
| レジストラ | お名前.com |
| DNS / CDN | Cloudflare（Free プラン） |
| SSL証明書 | Cloudflare 発行 Let's Encrypt（自動更新） |
| Tunnel | Cloudflare Tunnel（cloudflared Docker コンテナ） |
| ISP | ARTERIA Networks（VECTANT）マンションタイプ |
| 接続方式 | クロスパス（DS-Lite / IPv4 over IPv6） |
| ルーター | Buffalo WSR-3200AX4S（192.168.11.1） |
| NAS | Synology DS220+（192.168.11.200） |
| APP_URL | `https://koh-devvv.com` |

> クロスパス方式ではルーターでのポート転送ができないため、Cloudflare Tunnel を採用。

---

## Cloudflare 料金

### 無料の範囲（今回の使い方）

| 機能 | 料金 |
|------|------|
| Cloudflare Tunnel | 無料（トラフィック制限なし） |
| DNS | 無料 |
| SSL 証明書（Let's Encrypt） | 無料（自動発行・自動更新） |
| CDN / DDoS 防御 | 無料 |
| トンネル数 | 最大 1,000 個まで |

### 課金されるケース

| ケース | 料金 |
|--------|------|
| Zero Trust Access で **50 ユーザー超**のアクセス制御 | $7/ユーザー/月 |
| Pro プランにアップグレード | $20/月 |
| Workers / R2 等の有料サービスを有効化 | 従量課金 |

> 有料サービスを自分で有効化しない限り課金されない。クレジットカード登録は必須だが Free プランは $0/月。

---

## セットアップ手順

### Step 1. お名前.com でドメイン取得

[お名前.com](https://www.onamae.com/) で `koh-devvv.com` を取得済み。

---

### Step 2. Cloudflare にドメインを追加

```
https://dash.cloudflare.com/
  → Add a site
    → koh-devvv.com
      → Free プランを選択
        → DNS レコードを自動インポート
          → Continue to activation
```

---

### Step 3. お名前.com でネームサーバーを変更

```
お名前.com Navi にログイン
  → ネームサーバー設定
    → koh-devvv.com を選択
      → 「その他のサービス」タブ
```

| ネームサーバー | 値 |
|--------------|-----|
| ネームサーバー1 | `benedict.ns.cloudflare.com` |
| ネームサーバー2 | `sharon.ns.cloudflare.com` |

→ 確認画面へ進む → 設定する

> 反映まで数時間〜最大 24 時間かかる場合がある

#### 反映確認

Cloudflare ダッシュボードの Overview で Status が「Active」になれば完了。

---

### Step 4. Cloudflare Tunnel を作成

```
Cloudflare ダッシュボード
  → Zero Trust
    → Networks → Connectors
      → Create a tunnel
        → Cloudflared を選択
          → トンネル名: match_12
```

---

### Step 5. NAS で cloudflared コンテナを起動

NAS に SSH して実行:

```bash
docker run -d --restart unless-stopped --name cloudflared \
  cloudflare/cloudflared:latest \
  tunnel --no-autoupdate run --token あなたのトークン
```

- トークンは Cloudflare Tunnel 作成画面で Docker を選択すると表示される
- `--restart unless-stopped` で NAS 再起動後も自動起動
- Container Manager にも表示されるので GUI でも管理可能

#### 接続確認

Cloudflare の Connectors 画面で Status が **Connected** / **HEALTHY** になれば OK。

---

### Step 6. Public Hostname を設定

```
Cloudflare ダッシュボード
  → Zero Trust
    → Networks → Connectors
      → match_12 を選択
        → Public Hostname タブ
          → Add a public hostname
```

| 項目 | 設定値 |
|------|--------|
| Subdomain | （空） |
| Domain | `koh-devvv.com` |
| Path | （空） |
| Service Type | **HTTPS** |
| URL | **192.168.11.200:8443** |

→ **Additional application settings** → **TLS** を展開:

| 項目 | 設定値 |
|------|--------|
| **No TLS Verify** | **有効**（自己署名証明書を許可） |
| Origin Server Name | （空のまま） |

→ Save hostname

> - 既存の A レコードがある場合は Cloudflare DNS で削除してから設定する
> - Cloudflare Edge が SSL 終端するため、Cloudflare ↔ オリジン間は自己署名証明書でもセキュリティ上問題ない
> - DSM の Let's Encrypt 証明書発行は不要（Cloudflare が証明書を管理するため）

---

### Step 7. Cloudflare SSL/TLS 設定

```
Cloudflare ダッシュボード
  → koh-devvv.com
    → SSL/TLS
      → Overview
        → 暗号化モードを「Full」に設定
```

| モード | 説明 |
|--------|------|
| Off | 非暗号化（非推奨） |
| Flexible | Cloudflare↔ブラウザ間のみSSL、オリジンはHTTP |
| **Full** | **Cloudflare↔オリジン間もSSL（自己署名証明書OK）← これを選択** |
| Full (Strict) | 正規CA証明書が必要 |

---

### Step 8. Laravel の APP_URL を更新

NAS の `.env` を編集:

```ini
APP_URL=https://koh-devvv.com
```

```bash
docker exec match_12 php artisan config:cache
```

---

### Step 9. 動作確認

```bash
# 外部からHTTPSでアクセスできるか
curl -I https://koh-devvv.com/

# Alexa Webhook エンドポイント
curl -I https://koh-devvv.com/api/alexa-zundamon/webhook

# LAN内アクセス（自己署名証明書のため -k が必要）
curl -kI https://192.168.11.200:8443/
```

ブラウザで `https://koh-devvv.com/login` にアクセスし、鍵マーク付きで表示されれば成功。

---

### Step 10. Alexa Developer Console でエンドポイント設定

```
Alexa Developer Console
  → スキル選択
    → Endpoint
      → HTTPS
        → デフォルトの地域:
          https://koh-devvv.com/api/alexa-zundamon/webhook
        → SSL証明書の種類:
          My development endpoint has a certificate
          from a trusted certificate authority
```

---

## リクエストの流れ（図解）

```
「アレクサ、ずんだもんを開いて」
        │
        ▼
[Amazon Alexa Cloud]
        │
        │ POST https://koh-devvv.com/api/alexa-zundamon/webhook
        ▼
[Cloudflare Edge]
        │ SSL終端（Let's Encrypt 証明書）
        ▼
[Cloudflare Tunnel]
        │ cloudflared コンテナ（NAS内）
        │ → https://192.168.11.200:8443
        ▼
[Docker match_12 :443]
        │ Nginx（自己署名SSL）→ PHP-FPM
        │
        ├──→ [Claude AI API] テキスト生成
        │
        └──→ [VOICEVOX :50021] 音声合成（WAV→MP3）
        │
        ▼
[Alexa 応答 JSON]
SSML <audio> タグでずんだもん音声を返す
        │
        ▼
「申し訳ないのだ！...」
（ずんだもんの声で再生）
```

---

## Docker コンテナの HTTPS 構成

### ポートマッピング（docker-compose.yml）

| ホスト側 | コンテナ側 | 用途 |
|----------|-----------|------|
| 8080 | 80 | HTTP（HTTPS へ 301 リダイレクト） |
| 8443 | 443 | HTTPS（自己署名 SSL 証明書） |
| 8085 | 8080 | Laravel Reverb WebSocket |

### Nginx SSL 設定（docker/nginx.conf）

```nginx
# HTTP → HTTPS リダイレクト
server {
    listen 80 default_server;
    server_name _;

    location /.well-known/acme-challenge/ {
        root /var/www/html/public;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

# HTTPS サーバー
server {
    listen 443 ssl default_server;
    server_name _;

    ssl_certificate     /etc/nginx/ssl/server.crt;
    ssl_certificate_key /etc/nginx/ssl/server.key;
    ssl_protocols TLSv1.2 TLSv1.3;

    root /var/www/html/public;
    # ... Laravel 設定（FastCGI、try_files 等）
}
```

### 自己署名証明書の自動生成（docker/entrypoint.sh）

コンテナ初回起動時に `/etc/nginx/ssl/` に自動生成される。
証明書が既に存在する場合はスキップ。有効期限: 10年（3650日）。

```bash
openssl req -x509 -nodes -days 3650 \
    -newkey rsa:2048 \
    -keyout /etc/nginx/ssl/server.key \
    -out /etc/nginx/ssl/server.crt \
    -subj "/C=JP/ST=Tokyo/L=Tokyo/O=match_12/CN=${APP_DOMAIN:-localhost}"
```

> Cloudflare Edge が SSL 終端するため、エンドユーザーには Cloudflare の Let's Encrypt 証明書が見える。
> コンテナの自己署名証明書はあくまで Cloudflare ↔ オリジン間の暗号化用。

---

## Synology DSM リバースプロキシ（オプション）

LAN 内で `https://match12.local` 等でアクセスしたい場合に設定。
Cloudflare Tunnel 経由のアクセスには不要。

### 設定手順

```
DSM → コントロールパネル
  → ログインポータル
    → 詳細 → リバースプロキシ
      → 作成
```

| 項目 | 値 |
|------|-----|
| 説明 | match_12 |
| ソースプロトコル | HTTPS |
| ソースホスト名 | `match12.local`（または任意） |
| ソースポート | 443 |
| 送信先プロトコル | HTTPS |
| 送信先ホスト名 | `192.168.11.200` |
| 送信先ポート | 8443 |

### カスタムヘッダー設定

| ヘッダー名 | 値 |
|-----------|-----|
| X-Forwarded-Proto | https |
| X-Forwarded-For | $proxy_add_x_forwarded_for |

> DSM のリバースプロキシは Synology の Let's Encrypt 証明書を使用できるため、
> LAN 内でも「保護された通信」表示が可能。
> ただし DSM からの Let's Encrypt 発行には外部からのHTTPアクセスが必要なため、
> Cloudflare Tunnel 環境ではドメイン検証が通らない場合がある。

---

## 運用

### cloudflared コンテナの管理

```bash
# ステータス確認
docker ps | grep cloudflared

# ログ確認
docker logs cloudflared --tail 50

# 再起動
docker restart cloudflared

# 停止・削除（Tunnel を停止する場合）
docker stop cloudflared && docker rm cloudflared
```

### match_12 コンテナの再構築

```bash
cd /volume1/docker/match_12
docker compose down
docker compose build --no-cache
docker compose up -d

# 起動確認
docker compose logs -f app
# → "[entrypoint] 起動完了" が表示されれば OK
```

### cloudflared が停止してしまった場合の復旧手順

```bash
# 1. 状態確認
docker ps | grep cloudflared

# 2. コンテナが存在するが停止している場合 → 起動
docker start cloudflared

# 3. コンテナが存在しない or 起動できない場合 → 削除して再作成
docker rm cloudflared 2>/dev/null
docker run -d --restart unless-stopped --name cloudflared \
  --network host \
  cloudflare/cloudflared:latest \
  tunnel --no-autoupdate run --token あなたのトークン

# 4. 接続確認
docker logs cloudflared --tail 5
# → "Registered tunnel connection" が表示されれば OK
```

> トークンは Cloudflare ダッシュボード → **Zero Trust** → **Networks** → **Connectors** → `match_12` → **Configure** で再確認できる

### 永続化について

- `--restart unless-stopped` で作成しているため、NAS 再起動後も自動起動する
- Cloudflare 側の設定（DNS、Tunnel、Public Hostname）はクラウドに保存されているため消えない
- お名前.com のネームサーバー設定も永続的
- SSL 証明書は Cloudflare が自動更新（90日ごと）

### Tunnel の状態確認

Cloudflare ダッシュボード → Zero Trust → Networks → Connectors で確認。
Status が **HEALTHY** / **Connected** であれば正常。

### Cloudflare の重要な設定値（現在の設定）

| 設定項目 | 場所 | 値 |
|---------|------|-----|
| SSL/TLS 暗号化モード | koh-devvv.com → SSL/TLS | Full |
| Tunnel Service Type | Zero Trust → Connectors → match_12 → Public Hostname | HTTPS |
| Tunnel Service URL | 同上 | `192.168.11.200:8443` |
| Tunnel TLS | Public Hostname → Additional settings → TLS → No TLS Verify | 有効 |
| DNS レコード | koh-devvv.com → DNS → Records | CNAME Tunnel タイプ、Proxied |

---

## トラブルシューティング

| 症状 | 原因と対処 |
|------|-----------|
| Cloudflare で「Invalid nameservers」 | お名前.com のネームサーバー変更が未反映 → 数時間待つ |
| Tunnel が HEALTHY にならない | `docker logs cloudflared` でエラー確認、トークンが正しいか確認 |
| `https://koh-devvv.com` でアクセスできない | ネームサーバー未反映 or Tunnel の Public Hostname 未設定 |
| 502 Bad Gateway | match_12 コンテナが停止 or Service URL が間違い |
| 503 Service Unavailable | cloudflared からオリジンに接続できない → Service URL と match_12 の状態を確認 |
| Tunnel で 502 + TLS エラー | Public Hostname → TLS → **No TLS Verify** を有効にする |
| ERR_SSL_PROTOCOL_ERROR（LAN内） | HTTP ポート（8080）に HTTPS でアクセスしている → `https://...:8443` を使う |
| `:8443` にリダイレクトされる | ブラウザキャッシュが古い → Ctrl+Shift+Delete でキャッシュクリア or シークレットウィンドウで確認 |
| 自己署名証明書の警告（LAN内） | LAN 内直接アクセス時は正常。Cloudflare 経由なら表示されない |
| DSM の Let's Encrypt 発行が失敗 | Cloudflare Tunnel 環境では不要。Cloudflare が証明書を管理する |
| DNS でタイムアウト | PC/スマホの DNS キャッシュが古い → `ipconfig /flushdns` or DNS を `8.8.8.8` に変更 |
| Alexa から「すみません」 | エンドポイント URL が間違い or Tunnel 停止中 |
| NAS 再起動後にアクセスできない | `docker ps` で cloudflared と match_12 が起動しているか確認 |
| 「保護されていない通信」と表示 | DNS が旧 IP を返している → IPv6 DNS も Google DNS に変更 |
