てくなべ (tekunabe)

ansible / network automation / 学習メモ

[Cloudflare] Cloudflare Tunnel のトンネルの起動をサービス化する

はじめに

前回の記事 では、Cloudflare Tunnel を cloudflared tunnel run トンネル名 で起動しました。

フォアグラウンドでの起動ではなく、サービスとして起動したかったので試しました。基本的には以下の公式ドキュメント通りです。試行錯誤したあとに少しアレンジしています。

developers.cloudflare.com

  • 検証環境

設定ファイルの編集

まず設定ファイル(前回の記事でいう /home/admin/.cloudflared/config.yml)を修正します。

修正ポイントは、credentials-file で指定する認証情報の JSON ファイルのパスです。

これまでは、一般ユーザー admin で作業していたので、/home/admin/.cloudflared/config.yml というパスでした。サービス化するにあたって、ココじゃない感があるので /etc/cloudflared ディレクトリ配下にすることにします。

# トンネルのID
tunnel: aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 
# トンネル作成時に生成された認証情報ファイル
credentials-file: /etc/cloudflared/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa.json   # パスを変更

# Ingress rules
# どのホスト名のリクエストを内部のどのサービスに転送するかの設定
ingress:
  - hostname: sv01.example.com
    service: https://10.0.1.1   # ローカルの転送先 sv01
    originRequest:
      noTLSVerify: true         # 証明書検証の無視(ラボ環境のため)
  - hostname: sv02.example.com
    service: https://10.0.1.2   # ローカルの転送先 sv02
    originRequest:
      noTLSVerify: true         # 証明書検証の無視(ラボ環境のため)
  - service: http_status:404    # どのホスト名にもマッチしない場合

パスの変更に合わせて、/etc/cloudflared/ ディレクトリの作成と JSON ファイルもコピーしておきます。(残ったものは後で削除予定

$ whoami
admin
$ sudo mkdir /etc/cloudflared
$ sudo cp /home/admin/.cloudflared/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa.json /etc/cloudflared/
$
$ ll /etc/cloudflared/
total 4
-r--------. 1 root root 161 Aug  6 11:30 aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa.json

なお、credentials-file で指定した JSON ファイルが見つからないと、サービスのインストールコマンド実行時にエラーになってしまいます。

参考: https://community.cloudflare.com/t/cloudflared-tunnel-service-run-failing-setup-ubuntu/472882

サービスのインストール

続いてサービスをインストールします。cloudflared コマンド側にサービスのインストール機能があるようです。

$ sudo cloudflared --config /home/admin/.cloudflared/config.yml service install
2023-08-06T02:36:53Z INF Using Systemd
2023-08-06T02:36:54Z INF Linux service for cloudflared installed successfully
$

補足: 公式ドキュメントの手順との差分

当初、公式ドキュメント通り、一般ユーザーから単に cloudflared service install を実行したら、以下のエラーで失敗しました。

failed to copy /home/admin/.cloudflared/config.yml to /etc/cloudflared/config.yml: open /etc/cloudflared/config.yml: permission denied

設定ファイルを /etc/cloudflared/ ディレクトリにコピーしようとして、権限がないというエラーです。

続いて sudo をつけて sudo cloudflared service install としましたが、今度は設定ファイルが見つからないというエラーになりました。

Cannot determine default configuration path. No file [config.yml config.yaml] in [~/.cloudflared ~/.cloudflare-warp ~/cloudflare-warp /etc/cloudflared /usr/local/etc/cloudflared]

sudo を付けているので ~/.cloudflared は、 /root/.cloudflared ディレクトリを示しますが、そのディレクトリには config.yml がなく、他の候補のディレクトリ(~/.cloudflare-warp など)にもないということです。あるのは /home/admin/.cloudflared/config.yml です。ということで、前述のように、sudo のほか、明示的に設定ファイルのパスを指定するために --config オプション付きで、インストールコマンドを実行しました。

サービスのとトンネルの状態確認

サービス cloudflared はすでにサービスが開始されていました。OS起動時のサービス起動も enabled です。

$ systemctl status cloudflared
● cloudflared.service - cloudflared
     Loaded: loaded (/etc/systemd/system/cloudflared.service; enabled; vendor preset: disabled)
     Active: active (running) since Mon 2023-08-06 11:36:54 JST; 3min 0s ago
   Main PID: 11098 (cloudflared)
      Tasks: 6 (limit: 11060)
     Memory: 26.4M
        CPU: 204ms
     CGroup: /system.slice/cloudflared.service
             └─11098 /usr/bin/cloudflared --no-autoupdate --config /etc/cloudflared/config.yml tunnel run

Aug 06 11:36:54 gateway cloudflared[11098]: 2023-08-06T02:36:54Z INF Initial protocol quic
...()...

トンネルの CONNECTIONS もあります(未接続時は空欄)。

$ cloudflared tunnel list
You can obtain more detailed information for each tunnel with `cloudflared tunnel info <name/uuid>`
ID                                   NAME    CREATED              CONNECTIONS
aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa gateway 2023-08-06T02:27:19Z 2xKIX, 2xNRT

そして、今回ルールを定義した以下 2ホストのアクセスをして目的の画面が開くことを確認します。

不要ファイルの削除

ここまでで、各ファイルの配置は以下のようになっています。

$ ls -l /home/admin/.cloudflared/
total 12
-rw-------. 1 admin admin 1938 Aug  6 11:26 cert.pem
-rw-r--r--. 1 admin admin  754 Aug  6 11:28 config.yml
-r--------. 1 admin admin  161 Aug  6 11:27 aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa.json
$
$ ls -l /etc/cloudflared/
total 8
-rw-r--r--. 1 root root 754 Aug  6 11:36 config.yml
-r--------. 1 root root 161 Aug  6 11:30 aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa.json

/etc/cloudflared/config.yml がサービスのインストールコマンドによってコピーされたファイルです。

$ diff /home/admin/.cloudflared/config.yml /etc/cloudflared/config.yml
$

トンネルの起動に必要なファイルは /ect/cloudflared ディレクトリに寄せたので、/home/admin/.cloudflared/ 配下の設定ファイルと認証情報 JSON ファイルは不要になりました。それぞれ削除します。

$ rm /home/admin/.cloudflared/config.yml
$ rm /home/admin/.cloudflared/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa.json

ホスト追加時のオペレーション

今後、公開したいサーバー/サービスが増えてき場合の手順も、サービス化に伴い少し変わりました。

  1. 設定ファイル ./etc/cloudflared/config.ymlingress の追記
  2. CNAME の追加: cloudflared tunnel route dns gateway 追加ホスト名
  3. トンネルの再開: (sudo systemctl restart cloudflared)

おわりに

Cloudflare Tunnel のトンネル接続をサービス化しました。

積み残し課題は1点。 トンネルは常に利用したいわけではないので、必要に応じて開け締めしたいところです。ですが、トンネル自体を削除すると、UUID が変わったりと不都合です。なので、CNAME レコードの追加と削除をもって、トンネルの開け締めをしようかと検討中です。