Mastodonの自鯖をCloudflare Tunnelで公開する — 詰まった点と解決メモ

目的

自宅のUbuntuマシンで動かしているMastodonを、これまでは mastodon.demo2.jp のDNS(Aレコード)を自宅回線のグローバルIPへ向けて公開していました。

ただしこの方式だと

  • 自宅グローバルIPが露出する
  • ポート開放する必要がある
  • IPアドレスが変わった際の対応が必要

という問題があった。IPアドレスの変更にはDDNSサービスを使うことで解決できるが、セキュリティ面も含めて考えた結果 Cloudflare Tunnel を使い、ポート開放なしで公開する方式へ移行した。

手順の大まかな流れ

  1. Cloudflareに demo2.jp を追加(※ドメイン移管は不要)
  2. ネームサーバーをCloudflareに変更
  3. DNSレコードを整理
  4. Cloudflare Zero TrustでTunnel作成
  5. Ubuntuにcloudflared導入 & 常駐化
  6. mastodon.demo2.jp をTunnelへ接続(CNAME)
  7. nginxをTunnel向けに調整
  8. ルーターのポート転送をOFF

書きだしてみると大したことではないのだが、既にMastodonサーバーを公開して運用していた故にキャッシュの問題など色々と詰まって想像以上に時間がかかってしまった。

Cloudflareにdemo2.jp を追加

demo2.jpのドメインでは、Mastodonの他にこのHP、メール、Blueskyなどを運用しています。
その為、これらもまとめてCloudflareのDNSに設定をする必要があります。
初期設定で自動でDNSレコードをスキャンして取り込んでくれますが、一部取り込めていないものもあったのでその際は手動で現在のネームサーバーの設定をコピーして追加します。
レコードの設定が終わったらネームサーバーをCloudflareに切り替えます。

切り替え後、HPへのアクセスやメールの送受信が問題無いか確認します。
問題無ければTunnelの設定をしていきます。

Tunnel(Zero Trust)の設定

CloudflareのZero TrustからTunnelを作成していきます。途中のスクショは撮っていなかったので、詳しい作成方法は割愛します。最初にチーム名とかを聞かれて戸惑いますが、適当な名前でOKです。

作成ができたら、「コネクタをインストールして実行する」という画面が表示されるので、表示されているコマンドをそのままコピー&ペーストしてインストールします。
その後、「公開されたアプリケーションルート」のタブを開き新しく追加します。

ChatGPT(以下、ちゃっぴー)に聞いたところ、HTTPSではなくHTTPでやるのが無難との事だったので、このようにしています。

ここで確認の為に、mastodon.demo2.jpにアクセスすると、”ページの自動転送設定が正しくありません このアドレスへのリクエストに対するサーバーの自動転送設定がループしています。”と表示されてしまいました😱

原因はこうだったようです。

  • Tunnelは Cloudflare側ではHTTPS
  • でもオリジン(自宅nginx)へはHTTPで入ってくる
  • nginxが「HTTPならHTTPSへ301」する → その結果、Cloudflare側でもう一度HTTPS化…となり、条件によってループする

どうすりゃいいのかわからんので、ちゃっぴーにnginxの設定を書いてもらいました。
最終的なものがこれ

server {
  listen 80;
  listen [::]:80;
  server_name mastodon.demo2.jp;
  root /home/mastodon/live/public;

  location /.well-known/acme-challenge/ { allow all; }

  # 直アクセスのHTTPはHTTPSへ(通常のブラウザアクセス用)
  # Tunnel経由は X-Forwarded-Proto: https が付くので、ここを通らずに下のproxyへ行く
  if ($http_x_forwarded_proto != "https") {
    return 301 https://$host$request_uri;
  }

  # 静的ファイル
  location /system/ {
    try_files $uri =404;
    add_header Cache-Control "public, max-age=31536000, immutable";
  }

  # Streaming (WebSocket)
  location /api/v1/streaming {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

    proxy_pass http://127.0.0.1:4000;
  }

  # Web
  location / {
    try_files $uri @proxy;
  }

  location @proxy {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;

    proxy_pass http://127.0.0.1:3000;
  }
}

はい、これにて一件落着…と思いきや、ここでポートを閉じたところMastodonにアクセスできなくなってしまいました😱

ポートを閉じるとアクセスできなかった原因

Ubuntu上で

getent ahosts mastodon.demo2.jp

を打つと 旧IP を返していた。

外部の1.1.1.1/8.8.8.8ではCloudflare IPを返しているのに、サーバだけ旧IPになってしまうことがある。

これが原因で

  • サーバから curl <https://mastodon.demo2.jp/>... がタイムアウト
  • 一部の動作確認が混乱
  • 直アクセス(旧IP)とTunnel経由(Cloudflare IP)が混在

という感じで原因がわかりづらくなっていた。

切り分けで使ったコマンド

外部DNSが正しいか:

dig +short A mastodon.demo2.jp @1.1.1.1
dig +short A mastodon.demo2.jp @8.8.8.8

Ubuntuが何を使っているか:

resolvectl query mastodon.demo2.jp

解決:UbuntuのDNSを固定(NetworkManager)

最終的に nmcli con show --active で接続名を確認し、DNSを固定した。

nmcli con show --active

IPv4だけ固定(IPv6は disabled)

sudo nmcli con mod"netplan-enp1s0" ipv4.ignore-auto-dnsyes ipv4.dns"1.1.1.1 8.8.8.8"sudo nmcli con mod"netplan-enp1s0" ipv6.ignore-auto-dnsyessudo nmcli con up"netplan-enp1s0"sudo resolvectl flush-caches

確認:

resolvectl status | sed -n'1,120p'
getent ahosts mastodon.demo2.jp |head -n 10

ここで Cloudflareのアドレスが返ればOK。


動作確認(API/Streaming)

最後に、APIとStreamingが通るかで確定できる。

curl -I <https://mastodon.demo2.jp/api/v2/instance> --connect-timeout 10
curl -I <https://mastodon.demo2.jp/api/v1/streaming/health> --connect-timeout 10

両方 200 ならOK。

ブラウザからアクセスができない

これで解決!と思いきや、クライアントのブラウザからアクセスできません😱😱
色々試してわかったのが、ここでもDNSが混在してしまっているという事でした。

まずブラウザのキャッシュを消します。
Chrome系なら以下の手順

Mastodonを開いた状態で
F12 → Application→Storage → Clear site data

WindowsのDNSキャッシュもクリアします

ipconfig /flushdns
netsh winsock reset

はい、これで解決!

と思いきやまた時間が経つとアクセスできなくなってしまいました😱😱😱

結局これは、ルーターがまた旧IPを指してたみたいなんですね。
なのでネットワークのDNSサーバをDHCPから1.1.1.1/8.8.8.8に変えることで、再発しなくなりました。

反省

もうね、ちゃっぴーに相談しながらトラブルシューティングしたけど、問題が混在していて原因を切り分けるのが大変だったし、Ubuntu側でチャットしたりWindows側でチャットしたりしちゃったせいで途中の会話が消えたりして振り返るのも大変だったり、二度とやりたくない…
Webサービスを公開する時は計画的にやりましょう(最初からCloudflareで公開しとくべきだった)

今回のと同時にMastodonからの通知メールが迷惑メール判定されてしまう問題を解決していたんですが、それについては次の記事で書きます。

コメント

タイトルとURLをコピーしました