Cloudflare Tunnel クライアントの自動起動

[前回](https://qiita.com/b-wind/items/36a654c2151d54613368)で設定が終了したと思っていましたが、「Cloudflare Tunnel Client (cloudflared)」を**自動起動**する設定を忘れていました。

サービス管理システム（systemd）を利用し、Docker コンテナが起動してから cloudflared を自動起動するように設定していきます。

## サービス管理システム（systemd）
サービス管理システム（systemd）とは、Linuxシステムの起動 および 各サービスの管理を行う仕組みを指します。
所定のフォルダに格納された「ユニットファイル（設定ファイル）」の内容に基づき、サービスの起動・停止・再起動 や 自動起動 などを制御します。

### ユニットファイル
ユニットファイル（設定ファイル）は基本的にサービス毎に用意し、所定のフォルダへ格納しておきます。
「Cloudflare Tunnel Client (cloudflared)」は手動で導入する Dockerコンテナ なので、ユニットファイルの格納場所は ```/etc/systemd/system/``` となります。

|フォルダ　　　　　　　　　　　　|説明|
|:-|:-|
|/etc/systemd/system/|システム または 手動でインストールしたソフトウェアのユニットファイルを格納する。|
|/lib/systemd/system/|パッケージマネージャーがインストールしたソフトウェアのユニットファイルを格納する。|

### systemd ターゲット
各サービスの起動制御の実施契機となる「システムの特定の状態」のことで、古い Linux における「ランレベル」に相当します。
ユニットファイルに起動契機を記述する際、ターゲット名を記述します。
|ターゲット|ランレベル|説明|
|:-|:-:|:-|
|poweroff.target|0|システムの停止|
|rescue.target|1|緊急用rootシェル(Single-User)|
|multi-user.target|2,3,4|CLIでMulti-Userログインが可能|
|graphical.target|5|GUIでMulti-Userログインが可能|
|reboot.target|6|システムの再起動|

## cloudflared ユニットファイル
```nano``` コマンドで、```cloudflared.service``` というユニットファイルを作成します。

```bash
$ sudo nano /etc/systemd/system/cloudflared.service
```

```conf
[Unit]
# サービスの説明
Description=Cloudflare Tunnel Client

# ネットワーク の起動を試みる。
#   起動に失敗したときも、本サービスの起動処理を継続する。
Wants=network-online.target

# 次の順で各サービスを起動する。
#   1) ネットワーク
#   2) Docker サービス
#   3) 本サービス
After=network-online.target docker.service

# Docker サービスが「動作中」の場合にのみ、本サービスを起動する。
Requires=docker.service

[Service]
# docker コマンドを dockerインストールユーザー で実行。
User={docker インストールユーザーの名前}

# プロセスが異常終了した後にサービスを再起動。
Restart=on-failure

# サービス制御
#   ExecStart    : サービス開始用コマンド
#   ExecStop     : サービス停止用コマンド
#   ExecStopPost : サービス停止後に実行するコマンド
ExecStart=/usr/bin/docker run -d --name cloudflare-d --network=host cloudflare/cloudflared:latest tunnel --no-autoupdate run --token eyJhIj（途中省略）aSJ9
ExecStop=/usr/bin/docker stop cloudflare-d
ExecStopPost=/usr/bin/docker rm cloudflare-d

[Install]
# サービスを起動する Systemdターゲット
#   multi-user.target(CLIでMulti-Userログインが可能) 状態になったら
#   本サービスを起動する。
WantedBy=multi-user.target
```

**User={docker インストールユーザーの名前}**
```ExecStart``` ```ExecStop``` ```ExecStopPost``` に記述している docker コマンドを実行するユーザーの名前を指定します。（例. User=taro）
docker コマンドをプロンプトから実行できるユーザーなら、「docker をインストールしたユーザー」でなくても良いと思います。

**--name cloudflare-d**
```ExecStop (docker stop)``` と ```ExecStopPost (docker rm)``` の両コマンドで コンテナ名 を明示的に指定するため、```ExecStart (docker run)``` コマンドのオプションで、「**コンテナ名 "cloudflare-d"**」を指定しています。

## サービスの登録・起動
### systemd 設定内容の再構築
systemd は各ユニットファイルの内容をメモリ上に記憶します。
ファイルを追加しただけでは反映されないので、以下のコマンドでメモリ情報の再構築を実施します。
```base
$ sudo systemctl daemon-reload
```

### サービスの自動起動を有効化
```[Install]``` セクションの ```WantedBy``` ディレクティブに記述したターゲットで**自動起動**を設定します。
```bash
$ sudo systemctl enable cloudflared.service
Created symlink /etc/systemd/system/multi-user.target.wants/cloudflared.service → /etc/systemd/system/cloudflared.service.
```
:::note info
ユニットファイルの ```WantedBy=multi-user.target``` という記述に基づき、```/etc/systemd/system/multi-user.target.wants/```フォルダ下に ```cloudflared.service``` へのシンボリックリンクが作成されます。
:::

### サービスを開始
Ubuntu を再起動すればサービスが自動的に起動しますが、次のコマンドを実行すれば OSを再起動せずに 即サービスを開始できます。
```bash
$ sudo systemctl start cloudflared.service
```

### サービスステータスの確認
次のコマンドでサービスの状態を確認できます。
```bash
$ sudo systemctl status cloudflared.service
```

下記は実行例です。
```Active: active (running)``` と表示されていれば、cloudflared は正常に起動されています。

```bash
$ sudo systemctl status cloudflared.service
[sudo] ********* のパスワード: 
● cloudflared.service - Cloudflare Tunnel Client
     Loaded: loaded (/etc/systemd/system/cloudflared.service; enabled; preset: enabled)
     Active: active (running) since Mon 2025-04-28 22:54:30 JST; 3min 58s ago
   Main PID: 3053 (docker)
      Tasks: 10 (limit: 18722)
     Memory: 33.1M (peak: 33.3M)
        CPU: 41ms
     CGroup: /system.slice/cloudflared.service
             └─3053 /usr/bin/docker run --name cloudflare-d --network=host cloudflare/cloudflared:latest tunnel --no-a＞

 4月 28 22:54:31 ■■■■■ docker[3053]: 2025-04-28T13:54:31Z INF Using [CurveID(4588) CurveID(25497) CurveP256] as cu＞
 4月 28 22:54:31 ■■■■■ docker[3053]: 2025/04/28 13:54:31 failed to sufficiently increase receive buffer size (was:＞
 4月 28 22:54:31 ■■■■■ docker[3053]: 2025-04-28T13:54:31Z INF Registered tunnel connection connIndex=0 connection=＞
 4月 28 22:54:31 ■■■■■ docker[3053]: 2025-04-28T13:54:31Z INF Using [CurveID(4588) CurveID(25497) CurveP256] as cu＞
 4月 28 22:54:31 ■■■■■ docker[3053]: 2025-04-28T13:54:31Z INF Updated to new configuration config=”{￥”ingress￥”:[{＞
 4月 28 22:54:32 ■■■■■ docker[3053]: 2025-04-28T13:54:32Z INF Registered tunnel connection connIndex=1 connection=＞
 4月 28 22:54:32 ■■■■■ docker[3053]: 2025-04-28T13:54:32Z INF Using [CurveID(4588) CurveID(25497) CurveP256] as cu＞
 4月 28 22:54:33 ■■■■■ docker[3053]: 2025-04-28T13:54:33Z INF Registered tunnel connection connIndex=2 connection=＞
 4月 28 22:54:33 ■■■■■ docker[3053]: 2025-04-28T13:54:33Z INF Using [CurveID(4588) CurveID(25497) CurveP256] as cu＞
 4月 28 22:54:34 ■■■■■ docker[3053]: 2025-04-28T13:54:34Z INF Registered tunnel connection connIndex=3 connection=＞
lines 1-20/20 (END)
```

## 終わりに
Ubuntu のパッケージアップデートを実施して OS を再起動すると Cloudflare Tunnel へ接続できない状態となり、**サービスの自動起動** を設定していなかったことに気が付きました。
何度か OS 再起動を繰り返して自動起動されることを確認したので、これで本当に運用の準備が整ったはずです。

小規模な Dify アプリの作成を繰り返す「一人 ハッカソン」を予定しているので、次回こそは アプリ作成 に関する記事を投稿したいと思います。