開発ログ
本ページは「いつ・何を実施したか」の時系列ログです。各ナレッジ資料(Phase 1-4 ナレッジ等)が「なぜそうなったか・どう調べて解決したか」を中心に記述するのに対し、本ページは意思決定の経緯・方針変更の背景・試行錯誤のプロセスを時系列で追えるよう記録します。
設計理解・エラー解決の詳細は各ナレッジ資料に集約しています。本ログの各エントリ末尾には、関連するナレッジ項目へのリンクを記載しています。
1. 現在地サマリー(2026-06-10 時点)
| 区分 | 状態 | 備考 |
|---|---|---|
| Phase 1-1 Raspberry Pi 基礎環境構築 | 完了 | Docker / FastAPI コンテナ起動、ローカル疎通確認済み |
| Phase 1-2 Cloudflare Tunnel 外部公開検証 | 完了 | Quick Tunnel 経由で Wi-Fi・モバイル回線から疎通確認済み |
| Phase 1-3 データアップロード安定性検証 | 完了 | 10MB ファイルのアップロード・MD5 整合性確認済み |
| Phase 1-4 本番用ドメイン適用検証 | 完了 | https://api.your-domain.com/ping → {"message":"pong"} 確認済み |
| Phase 2 要件定義準備 | 進行中 | PoC 結果レポート・堅牢性強化構成案・DNS 移管手順書・ドキュメントサイト作成済み |
2. 方針変更・決定事項一覧
| 日付 | 変更内容 | 理由・背景 | 影響資料 |
|---|---|---|---|
| 2026-03-下旬 | Raspberry Pi 5 を API サーバーとして採用 | 低コストで常時稼働可能なサーバー基盤として適切。グローバル IP 不要・ポート開放不要という要件にも合致 | PoC レポート |
| 2026-04-01 | Phase 1-2 では Named Tunnel でなく Quick Tunnel を使用 | Named Tunnel の Public Hostname 設定にはドメインが Cloudflare DNS ゾーンで管理されていることが前提。当時はドメインが Squarespace 管理下で Cloudflare DNS 未登録のため設定不可。Phase 1-2 の目的は「外部から繋がるか確認する」であり URL 固定は不要と判断 | PoC レポート、K-01 |
| 2026-04-12 | FastAPI の保存先パスを /data/uploads から /app/data に変更 |
Docker ボリュームマウント先(/app/data)と main.py の保存先(/data/uploads)が不一致。アップロードしたファイルが Pi 上で見つからない事象が発生し、パスを統一して解決 |
PoC レポート 3.3 |
| 2026-04-29 | DNS 管理を Squarespace(Google Cloud DNS)から Cloudflare へ移行 | Named Tunnel の Public Hostname 機能を使うには Cloudflare DNS ゾーンへの登録が必須。「ドメイン移管(Transfer)」ではなく「DNS 管理移行(Connect a domain)」であり、所有権は Squarespace のまま NS レコードを変更するだけと判明。事前確認で MX レコードなし・SPF が -all のためメールへの影響なしと判断し実施 |
DNS 移管手順書、K-03, K-04, K-05 |
| 2026-04-29 | cloudflared の起動オプションから --url を削除し --token のみに統一 |
Named Tunnel(--token)と Quick Tunnel(--url)を同時指定していたため、転送先が未定義となりタイムアウトが発生。Named Tunnel では転送先は Cloudflare ダッシュボードの Public Hostname 設定で管理されるため --url は不要かつ競合の原因だった |
K-02, K-06、設計書 Phase 1-4 |
| 2026-05-04 | Phase 2 として堅牢性強化構成案・ドキュメントサイト整備を優先 | 開発者打ち合わせに向けた要件定義準備のため。Phase 1 の知見を整理・共有可能な形にすることを優先 | 堅牢性強化構成案 |
| 2026-06-10 | ドキュメントサイトを GitHub Pages + Cloudflare Access で公開 | 開発者・関係者への資料共有のため。特定メールアドレスのみアクセス可能な形で公開。機密情報(ドメイン名・IP・Zone ID 等)は HTML から一括マスク処理し、git 履歴も orphan ブランチで書き換えて公開 | 本ドキュメントサイト |
3. 時系列ログ
Phase 1-1 着手:Raspberry Pi 5 セットアップ
Raspberry Pi 5 に Ubuntu Server をインストールし、Docker / Docker Compose を導入。
FastAPI コンテナを起動し、http://localhost:8000/ping → {"message":"pong"} を確認。
Windows PC からローカルネットワーク越しの疎通も確認。
| 検証項目 | 結果 |
|---|---|
| Ubuntu Server インストール | 成功 |
| Docker / Docker Compose インストール | 成功 |
| FastAPI コンテナ起動・ローカル疎通 | 成功 |
| Windows PC からのローカルネットワーク越し疎通 | 成功 |
課題: Docker コマンドに sudo が必要
事象: docker ps 等の実行時に permission denied while trying to connect to the Docker daemon socket が発生。
原因: 実行ユーザー(damio01)が docker グループに未所属。Docker デーモンのソケットはデフォルトで docker グループのみアクセス可能。
対応: sudo usermod -aG docker damio01 を実行し、再ログイン後に解消。以降 sudo なしで docker コマンドが使用可能になった。
課題: SSH 接続時のユーザー名誤り・パーミッション不備
事象 1: SSH 接続時に damio で接続試行 → Permission denied (publickey)。正しいユーザー名は damio01。
事象 2: ユーザー名修正後も SSH キー認証が失敗。~/.ssh ディレクトリのパーミッションが 755 になっており、OpenSSH のセキュリティポリシー(700 以外は拒否)に抵触していた。
対応: chmod 700 ~/.ssh および chmod 600 ~/.ssh/authorized_keys で修正。
Phase 1-1 完了
Raspberry Pi 5 上で FastAPI コンテナが稼働し、Windows PC からローカルネットワーク越しに疎通確認完了。 Phase 1-2(Cloudflare Tunnel 外部公開検証)へ移行。
Phase 1-2 着手:Cloudflare Tunnel 外部公開検証
cloudflared コンテナを使った外部公開を試みる。当初は Named Tunnel(--token)の使用を検討したが、
ドメインが Cloudflare DNS ゾーンに未登録のため Public Hostname 設定が不可と判明。
Quick Tunnel(--url オプション)で代替することを決定。
意思決定: Quick Tunnel を採用した理由
背景: Phase 1-2 の目標は「外部ネットワークから Raspberry Pi の API に到達できるか確認する」こと。 URL の固定は必須要件ではなかった。
Named Tunnel を使えなかった理由:
Named Tunnel の「Public Hostname」設定(どのドメインのリクエストをどのサービスに転送するか)は、
対象ドメインが Cloudflare の DNS ゾーンで管理されている場合のみ利用可能。
当時はドメイン(your-domain.com)の DNS 管理が Squarespace(実体は Google Cloud DNS)にあり、
Cloudflare ダッシュボードで Public Hostname を設定しようとしてもドメインが選択肢に表示されなかった。
Quick Tunnel の特性と割り切り:
Quick Tunnel(cloudflared tunnel --url http://localhost:8000)は Cloudflare アカウントやドメイン登録不要で即使えるが、
コンテナ再起動のたびに URL が変わる(例: occur-thompson-theorem-bracket.trycloudflare.com)。
Phase 1-2 は「繋がるか確認する」フェーズなので URL 変動は許容し、Quick Tunnel で実施することを決定。
Named Tunnel への移行は Phase 1-4 で対応する計画とした。
Phase 1-2 完了:Quick Tunnel 経由の外部疎通確認
Quick Tunnel URL: https://occur-thompson-theorem-bracket.trycloudflare.com
- Wi-Fi 環境からの疎通:
/ping→{"message":"pong"}✅ - モバイル回線(iPhone テザリング)からの疎通 ✅
- Cloudflare エッジ接続プロトコル: QUIC(東京リージョン)
重要な発見: Quick Tunnel はコンテナ再起動のたびに URL が変わる仕様を実際に確認。 継続的なテスト・本番運用には Named Tunnel が必須であることを改めて認識。 Phase 1-4 での Named Tunnel 移行を確定方針とした。
Phase 1-3 着手:データアップロード安定性検証
10MB のダミーファイルを作成し、Quick Tunnel 経由でアップロードして安定性を検証。
Windows PowerShell から curl.exe を使用(PowerShell では curl が Invoke-WebRequest のエイリアスになっているため curl.exe と明示する必要あり)。
# Windows PowerShell でダミーファイル作成
fsutil file createnew dummy_10mb.dat 10485760
# curl でアップロード(PowerShell では curl.exe と明示)
curl.exe -X POST https://occur-thompson-theorem-bracket.trycloudflare.com/upload `
-F "file=@dummy_10mb.dat"
課題: FastAPI の保存先パスと Docker ボリュームマウント先の不一致
事象: ファイルアップロードは成功(HTTP 200)するが、Raspberry Pi 上で ls -lh ~/poc-api/data/ を確認してもファイルが存在しない。
原因: main.py の保存先が /data/uploads に設定されていたが、
docker-compose.yml のボリュームマウント定義は ./data:/app/data(コンテナ内 /app/data をホストの ./data にマウント)。
ファイルはコンテナ内の /data/uploads に書き込まれていたが、このパスはマウントされていないためホスト側には反映されていなかった。
対応: main.py の保存先を /app/data に修正し、
docker compose up -d --build で再ビルドして解決。
# 修正前(main.py)
UPLOAD_DIR = "/data/uploads"
# 修正後(main.py)
UPLOAD_DIR = "/app/data"
Phase 1-3 完了:10MB アップロード・MD5 整合性確認
- 10MB ファイルのアップロード成功 ✅
- Raspberry Pi 側でのファイル保存確認(
ls -lh ~/poc-api/data/)✅ - MD5 ハッシュ値による整合性確認(送信前後で一致)✅
| 制限項目 | 制限値 | 検証結果 |
|---|---|---|
| 最大アップロードサイズ | 100MB(Free プラン) | 10MB で問題なし |
| タイムアウト | 100秒 | 10MB では問題なし |
注: 50MB 以上のファイルテストは Phase 2 以降に持ち越し。 Cloudflare Free プランの 100MB 制限に対して余裕があることを確認。
Phase 1-4 着手:Named Tunnel への移行と本番ドメイン適用
Quick Tunnel から Named Tunnel に移行し、固定ドメイン(api.your-domain.com)での
HTTPS アクセスを確立することを目標とする。
Named Tunnel への移行には以下の2つの課題が存在することが判明した。
- ドメインが Cloudflare DNS ゾーンに未登録 → DNS 管理を Cloudflare に移行する必要あり
- 既存の
docker-compose.ymlに--url(Quick Tunnel 用)が残っている → 削除が必要
意思決定: DNS 管理を Cloudflare に移行する判断プロセス
問題の発見:
Named Tunnel を作成してトークンを取得し、Cloudflare ダッシュボードで Public Hostname を設定しようとしたところ、
ドメイン(your-domain.com)が選択肢に表示されなかった。
Cloudflare アカウントは持っているのに、なぜドメインが使えないのかが分からなかった。
原因の特定: 調査の結果、Named Tunnel の Public Hostname 機能は「対象ドメインが Cloudflare の DNS ゾーンで管理されている」場合のみ利用可能と判明。 当時はドメインの所有権も DNS 管理も Squarespace(実体は Google Cloud DNS)にあり、 Cloudflare からは「管理外のドメイン」として扱われていた。
「ドメイン移管」と「DNS 管理移行」の違いの確認: 「DNS を Cloudflare に移す」と調べると「ドメイン移管(Transfer)」という言葉が出てきた。 移管は複雑でリスクがあると聞き、本当にやる必要があるのか不安になったが、 調査の結果、今回必要なのは「ドメイン移管(Transfer)」ではなく「DNS 管理移行(Connect a domain)」と判明。 前者はレジストラ(所有権)ごと変更する大がかりな手続きだが、後者は NS レコードを変更するだけで完了する。
| 種別 | 内容 | 今回の判断 |
|---|---|---|
| ドメイン移管(Transfer) | 所有権ごと別レジストラへ移す。手続きが複雑・リスクあり | 不要 |
| DNS 管理移行(Connect a domain) | 所有権はそのまま、NS レコードを変更して DNS 管理のみ Cloudflare へ委譲 | 採用 |
DNS 移行前のリスク評価(Google Workspace への影響確認)
DNS 管理を Cloudflare に移行する前に、既存のメール設定(Google Workspace)に影響が出ないか確認した。 DNS 移行で一番怖いのは「メールが止まること」であるため、事前に現在の DNS レコードを調査した。
# PowerShell で現在の DNS レコードを確認
Resolve-DnsName -Name "your-domain.com" -Type MX # メール受信設定
Resolve-DnsName -Name "your-domain.com" -Type TXT # SPF/DKIM/DMARC
Resolve-DnsName -Name "your-domain.com" -Type A # ウェブサイト
確認結果:
- MX レコード: 存在しない(メール受信設定なし)
- SPF レコード:
v=spf1 -all(全送信元を拒否 = メール送信も実質無効) - DMARC:
v=DMARC1; p=none(ポリシーなし)
判断: MX レコードが存在せず、SPF が -all(全拒否)であったため、
Google Workspace メールへの影響なしと判断。安全に DNS 移行を実施できると結論。
DNS 移管実施:Squarespace → Cloudflare
Cloudflare の「Connect a domain」機能を使って your-domain.com を登録。
Cloudflare が既存 DNS レコードを自動スキャンし、現在のレコードを取り込んだ。
注意が必要だった点:
自動スキャン後、不要なプレースホルダーレコード(Tunnel api 等)が混入していたため手動で削除。
既存の A レコード・TXT レコード(SPF/DKIM/DMARC)は Cloudflare 側に正しく引き継がれていることを確認した。
Squarespace の DNS 設定で NS レコードを Cloudflare のネームサーバーに変更。
- 変更後のネームサーバー:
xxxx.ns.cloudflare.com/yyyy.ns.cloudflare.com - DNS 伝播完了・Cloudflare でのアクティブ確認: 約 24〜48 時間後
詳細手順(スクリーンショット付き): DNS 移管手順書
課題: --token と --url の同時指定によるタイムアウト
事象: DNS 移行後、Named Tunnel(--token)を設定したにもかかわらず、
https://api.your-domain.com/ping へのアクセスが ERR_CONNECTION_TIMED_OUT でタイムアウト。
Cloudflare ダッシュボードでは Tunnel は「Healthy」と表示されており、DNS 解決(CNAME)も正常。
なぜリクエストが届かないのか原因が分からなかった。
原因:
Phase 1-2 で Quick Tunnel 用に設定した --url http://api:8000 が
docker-compose.yml に残ったまま、Named Tunnel 用の --token を追加していた。
Named Tunnel では転送先(どのローカルサービスにリクエストを流すか)は
Cloudflare ダッシュボードの「Public Hostname」設定で管理されるため、
--url は無視されるどころか競合の原因となり、転送先が未定義のままタイムアウトとなっていた。
# 修正前(誤):--token と --url を同時指定
command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN} --url http://api:8000
# 修正後(正):--token のみ。転送先はダッシュボードの Public Hostname で設定
command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN}
対応: --url http://api:8000 を削除し、
転送先は Cloudflare Zero Trust ダッシュボードの Public Hostname 設定で管理する形に統一。
Public Hostname 設定・Named Tunnel 疎通確認
Cloudflare Zero Trust ダッシュボードで Public Hostname を設定。
Named Tunnel は「トンネルを掘る(--token)」部分と「どこに繋ぐか(Public Hostname)」の設定が分離しており、
トークンだけではリクエストの転送先が定まらない。この2段階の設定が必要であることを理解した上で実施。
| 設定項目 | 値 |
|---|---|
| Subdomain | api |
| Domain | your-domain.com |
| Service Type | HTTP |
| Service URL | http://api:8000(http:// プロトコル指定が必須) |
注意点: Service URL の入力で api:8000 のみでは
「Invalid format」エラーが発生。http://api:8000 と明示的にプロトコルを指定する必要あり。
Phase 1-4 完了:本番ドメインでの HTTPS 疎通確認
Named Tunnel(your-tunnel-name)が Healthy 状態(Uptime 6日以上、Active replicas 1)で稼働。
固定ドメインでの HTTPS アクセスを確認。
curl https://api.your-domain.com/ping
# → {"message":"pong"} ✅
Phase 1 全4フェーズが完了。Phase 2(要件定義準備・ドキュメント整備)へ移行。
Quick Tunnel から Named Tunnel への移行に際して発生した課題(DNS 移行・--url 競合・Public Hostname 設定)は
すべて Phase 1-4 ナレッジ に整理した。
Phase 2 着手:要件定義準備・ドキュメント整備
開発者打ち合わせに向けた要件定義準備として、Phase 1 の知見を整理・共有可能な形にすることを優先。 以下のドキュメントを作成した。
| 資料名 | 内容 | 状態 |
|---|---|---|
| PoC 結果レポート(Phase 1) | Phase 1 全体の結果・達成事項・課題まとめ | 作成済み |
| システム通信経路一覧と図解 | 全通信経路の一覧表と ASCII アート図解 | 作成済み |
| 堅牢性強化システム構成案 | 本番運用に向けた堅牢性強化要素と「なぜ必要か」解説 | 作成済み |
| DNS 移管手順書 | Squarespace → Cloudflare の DNS 移管手順(スクリーンショット付き) | 作成済み |
| 本ドキュメントサイト | 全資料を一元管理する HTML ドキュメントサイト(相互リンク・インデックス付き) | 作成済み |
ドキュメントサイトの GitHub 公開・機密情報マスク処理
作成したドキュメントサイトを GitHub Pages + Cloudflare Access で公開。 特定メールアドレスのみアクセス可能な形(Cloudflare Access のワンタイムコード認証)で運用。
公開前の機密情報マスク処理: HTML ファイル内に直接記述されていた以下の情報を一括置換した。
| 種別 | 置換前 | 置換後 | 箇所数 |
|---|---|---|---|
| ドメイン名 | 実ドメイン名 | your-domain.com | 39箇所 |
| IP アドレス | Cloudflare エッジ IP | xxx.xxx.xxx.xxx | 2箇所 |
| Tunnel 名 | 実 Tunnel 名 | your-tunnel-name | 7箇所 |
| ネームサーバー名 | アカウント固有の NS 名 | xxxx.ns.cloudflare.com | 8箇所 |
git 履歴の書き換え:
過去のコミット履歴にも機密情報が含まれていたため、orphan ブランチで履歴を完全に書き換え、
initial commit の1コミットのみの状態で force push した。
GitHub 上でコミット履歴をさかのぼっても機密情報が表示されないことを確認。
次の作業(Phase 2 続き)
- 開発者打ち合わせアジェンダの作成
- Phase 2 要件定義書の作成(API 仕様・認証方式・エラーハンドリング仕様)
- 50MB 以上のファイルアップロードテスト(Phase 1-3 の持ち越し)
- iPhone アプリとの実際の接続テスト(E2E 検証)
- FCM(プッシュ通知)導入要否の検討
- 認証・認可の実装(API キー認証または JWT 認証)
4. 実装済みコンポーネント一覧
| コンポーネント | 構成 | 状態 |
|---|---|---|
| FastAPI(poc-api コンテナ) | Python 3.11-slim / uvicorn、ポート 8000 | 稼働中(restart: always) |
| cloudflared(Named Tunnel) | cloudflare/cloudflared:latest、--token 方式 |
稼働中(Uptime 6日以上) |
| /ping エンドポイント | GET /ping → {"message":"pong"} |
確認済み |
| /upload エンドポイント | POST /upload、ファイルを /app/data に保存 |
10MB ファイルで確認済み |
| 認証・認可 | 未実装 | Phase 2 以降 |
| 自動リトライ | 未実装 | Phase 2 以降 |
5. 関連リソース
| 種別 | 参照先 |
|---|---|
| PoC 結果レポート | poc-report.html |
| Phase 1-4 ナレッジ資料 | knowledge-phase1-4.html |
| 基本・詳細設計書(Phase 1-4) | design-phase1-4.html |
| DNS 移管手順書 | dns-migration.html |
| システム通信経路一覧と図解 | network-routes.html |
| 堅牢性強化システム構成案 | robustness.html |
| ガントチャート | poc_gantt_chart_20260504.xlsx(Phase 1 全体、更新済み) |