Closed6

Cloudflare Tunnel で Raspberry Pi Model 4B(Ubuntu 23.0) 自宅サーバーを公開する

yoshida567yoshida567

自宅APIサーバーをドメイン付きで公開したくなったのでやってみる。

何をするか

  • 自宅の Raspberry Pi 4 Model B (Ubuntu 23.0) で動作させているAPIサーバをインターネット上から実行できるようにしたい
  • APIは固定ドメインでコールできるようにしたい
    例: curl -X POST https://example.domain/foo
yoshida567yoshida567

Cloudflare側のドメイン設定

こちらの記事 を参考に設定した。
上記記事では Cloudflare で取得したドメインを使っているが、今回ドメインはCloudflareで取得したものを使用したので、適宜記事を読み替えてドメイン設定を行った。

cloudflared をラズパイにインストール

公式のcloudflaredの記事 を参考に、以下のコマンドをラズパイ上で実行。

wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb && sudo dpkg -i cloudflared-linux-amd64.deb

これだと「パッケージアーキテクチャ(amd64)がシステム(arm64)と一致しません」とエラーが出て失敗する。再度アーキテクチャを変えて実行。

wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64.deb && sudo dpkg -i cloudflared-linux-arm64.deb

上記コマンドだと問題なくインストールできた。
最後に問題なく動作しているかチェックする。

cloudflared --version

きちんとバージョンが表示されたのでOK。

メモ
最新のリリースは https://github.com/cloudflare/cloudflared/releases で確認できる。

yoshida567yoshida567

cloudflared から Cloudflare にログイン

以下を実行する。

cloudflared tunnel login

ブラウザ側でログインし、接続に利用するドメインを選ぶ。
これで証明書がダウンロードされて/home/ユーザー名/.cloudflared/cert.pem にあれば完了。

...なのだが、あまりにもブラウザが重すぎてダウンロードに失敗してしまった。
代わりに手動でダウンロードする方法がコマンドラインに表示されるのでそれを試す。

ログイン用のURLと Get "https://login.cloudflareaccess.org/xxxxxx-yyyyyy_zzzz" のような文言が表示されているはずなのでこれらを使って証明書をDLする。
はじめにラズパイではドメインが login.cloudflareaccess.org になっている方のURLに対してGETリクエストを送る。

wget https://login.cloudflareaccess.org/xxxxxx-yyyyyy_zzzz > ~/.cloudflare/cert.pem

リクエスト待ち状態に入るので、別のコンピュータでログイン用のURLにアクセスし、ログインを行ってドメインを選択する。Authorize が完了すると自動的にラズパイ側もGETリクエストが完了し、証明書がダウンロードされる。最後にダウンロードされた証明書を~/.cloudflare/cert.pem に配置する。

配置を確認する。

ls /home/ユーザー名/.cloudflared/cert.pem 

これでログインはOK。

yoshida567yoshida567

tunnel を作成する

設定ファイル作成。

今回は以下の設定値を使った設定を行う。

  • トンネル名: ubuntu-foo
  • 取得済みドメイン名: mydomain.xyz

設定ファイルを作成する。

cloudflared tunnel create ubuntu-foo

# Tunnel credentials written to /home/ユーザ名/.cloudflared/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.json. cloudflared chose this file based on where your origin certificate was found. Keep this file secret. To revoke these credentials, delete the tunnel.

# Created tunnel ubuntu-foo with id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

~/.cloudfraled/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.json が作成される。
このUUID xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx は後で用いる。

続いて設定ファイルを作成する。名前はなんでも良い。

touch ~/.cloudflared/config_ubuntu_foo.yml

設定ファイルを手動編集する。
ubuntu-foo.mydomain.xyz への通信は http://127.0.0.1:8000 につながる。

tunnel: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
credentials-file: /home/ユーザ名/.cloudflared/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.json

ingress:
  - hostname: ubuntu-foo.mydomain.xyz
    service:  http://127.0.0.1:8000
  - hostname: bar.mydomain.xyz
    service:  http://127.0.0.1:8001
  - service: http_status:404

warp-routing:
    enabled: true

複数のルーティングを割り当てる場合、ubuntu-foo.mydomain.xyzubuntu-bar.mydomain.xyz を割り当てる場合には以下のようにすることができる。

tunnel: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
credentials-file: /home/ユーザ名/.cloudflared/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.json

ingress:
  - hostname: ubuntu-foo.mydomain.xyz
    service:  http://127.0.0.1:8000
  - hostname: ubuntu-bar.mydomain.xyz
    service:  http://127.0.0.1:8001
  - service: http_status:404

warp-routing:
    enabled: true

CNAMEを設定する

このままではDNSレコードがないため Cloudflare にCNAMEを登録する必要がある。
以下のコマンドで ubuntu-foo に向いた mydomain.xyz のサブドメインを Cloudflare に登録できる。

cloudflared tunnel route dns xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ubuntu-foo.mydomain.xyz

Cloudflare 管理画面で DNS Record から mydomain.xyz を開き CNAME (サブドメイン)が登録されていればOK。画像では chatbot-ui-rag と言う名前で登録した。

yoshida567yoshida567

アクセスする

以下を有効化する。

cloudflared tunnel run ubuntu-foo

これで https://ubuntu-foo.mydomain.xyz にアクセスできるようになる。ただし、リクエストはまだ通らない。

これは Zero Trust の Access が許可されていないため。なので管理画面を開いて Access を許可する。

Access の設定

Zero Trust > Access > Applications から Add Application を選択する。

Self-Hosted を選択する。
続いて次の画面でサブドメインに ubuntu-foo, ドメインに自分のドメインを登録する。
他の項目はそのままで次へ。

次の画面で認証方法を設定する。この認証に合格したユーザーだけがローカルサーバへアクセスすることができる。今回は特定のメールアドレスだけを許可し、ワンタイムパスワードを送信することでアクセス権を付与する形にした。

他の設定はそのままでOK。最後まで登録を進める。

改めて https://ubuntu-foo.mydomain.xyz アクセスすると、メールアドレスで認証が通るようになり、アクセスできることが確認できる。

WIP: アクセスが通らないケースあり。調査中。

yoshida567yoshida567

参考

arch コマンドで取得できるARMアーキテクチャのバージョン名

  • aarch64: ARMアーキテクチャバージョン8 / Raspberry Pi OS 64bit 版で採用
  • armhf: ARMアーキテクチャバージョン7 / Raspberry Pi OS 32bit 版で採用
  • armv6: ARMアーキテクチャバージョン6 / 初代 Raspberry Pi で採用(らしい)
  • armv6l: ARMアーキテクチャバージョン6のうちメモリフォーマットがリトルエンディアンのもの / Raspberry Pi Zero で実行できる Raspberry Pi OS 32bit 版で採用

64bit版になるのは aarch64 、それ以前は32bitである様子。
cloudflared は armv7 以上を要求するため、 Raspberry Pi Zero では動作しない。
(Issue: https://github.com/cloudflare/cloudflared/issues/359 )

このスクラップは2023/09/04にクローズされました