Tailscaleのセルフホスト:DockerでHeadscaleをデプロイするためのガイド

HomeLab tutorial - IT technology blog
HomeLab tutorial - IT technology blog

クラウドなしの6ヶ月:Headscaleへの移行体験記

長年ホームラボ(HomeLab)を構築してきましたが、ある時「CGNAT」という壁にぶつかりました。Tailscaleは接続の問題を即座に解決してくれましたが、ネットワークのメタデータが企業のサーバーに保存されることに抵抗がありました。また、エンタープライズプランに移行することなく、無料プランの100ノード制限を回避したいとも考えていました。そこで、メッシュネットワーク全体をHeadscaleに移行することにしました。

Headscaleは、Tailscaleコントロールサーバーのオープンソースでセルフホスト可能な実装です。NATトラバーサル、WireGuardによるセキュリティ、シームレスなP2P接続といった、Tailscaleの優れた機能はそのままに、運用の「脳」にあたる部分を自前のハードウェアで管理できます。3つの拠点にある25台のデバイスで半年間運用してきましたが、私のシステムスタックの中で最も安定した部分になっています。

クイックスタート:5分で稼働させる

月額5ドルのVPSや古いローカルマシンがあれば、数分でHeadscaleを稼働させることができます。必要なのは、パブリックIPを持つLinuxホスト、または適切にポートフォワーディングされた環境だけです。

1. ディレクトリ構造の準備

まずは、設定ファイルとデータベースファイルを保存するための専用スペースを作成します。

mkdir -p ~/headscale/config
cd ~/headscale
touch config/config.yaml

2. Docker Composeファイルの作成

docker-compose.ymlファイルを作成します。軽量でセキュリティパッチの適用が早い公式イメージの使用をお勧めします。

services:
  headscale:
    image: headscale/headscale:latest
    container_name: headscale
    volumes:
      - ./config:/etc/headscale
      - ./data:/var/lib/headscale
    ports:
      - "8080:8080"
      - "9090:9090"
    command: headscale serve
    restart: always

3. 基本設定

デフォルトのconfig.yamlはかなり長いですが、開始するために確認が必要なキー項目はわずかです。データベースのパスがDockerのボリューム設定と一致していることを確認してください。

server_url: http://<YOUR_SERVER_IP>:8080
listen_addr: 0.0.0.0:8080
metrics_listen_addr: 0.0.0.0:9090
db_type: sqlite3
db_path: /var/lib/headscale/db.sqlite

derp:
  urls:
    - https://controlplane.tailscale.com/derpmap/default

docker-compose up -dを実行します。これで、あなた専用のプライベートなコントロールプレーンが稼働しました。

アーキテクチャの仕組み

Tailscaleはスプリットプレーン(分離プレーン)アーキテクチャを採用しています。データプレーンは実際のトラフィックを処理し、エンドツーエンドで暗号化され、通常はデバイス間で直接通信されます。一方、コントロールプレーン(Headscale)は、ノードの登録とキーの交換のみを管理します。

この構成が強力なのは、セキュリティをサードパーティの稼働状況から切り離せる点にあります。デバイスが参加すると、自分のDockerコンテナに問い合わせてピア(通信相手)を見つけます。もしパブリックなインターネットがダウンしても、ローカルデバイスがHeadscaleインスタンスにアクセスできれば、内部メッシュは完全に機能し続けます。

最初のユーザーを作成する

Headscaleでは「ユーザー」を使用してノードをグループ化します。最初のラップトップやスマートフォンを接続する前に、少なくとも1つのユーザーを作成する必要があります。

docker exec headscale headscale users create mynetwork

応用編:活用の幅を広げる

基本設定が完了したら、Headscaleをプロフェッショナルなネットワークツールへと進化させる機能を解放しましょう。

サブネットルーター:レガシーハードウェアへのアクセス

私は1080pのIPカメラ数台と、Tailscaleを実行できない古いBrother製プリンターを持っています。これを解決するために、Raspberry Pi 4をサブネットルーターにしました。これにより、外出先のカフェからでもスマホで192.168.1.0/24の範囲全体にアクセスできるようになります。

クライアントデバイスで以下を実行します:

tailscale up --login-server http://<YOUR_IP>:8080 --advertise-routes=192.168.1.0/24

次に、Headscaleサーバーでルートを有効にします:

docker exec headscale headscale nodes list
docker exec headscale headscale routes enable -r <ID>

Pre-Authキーによる自動化

一時的なDockerコンテナやCI/CDランナーを立ち上げる際、手動でのログインは面倒です。再利用可能なPre-Authキーを使用すれば、人の手を介さずに新しいノードを自動的にメッシュに参加させることができます。

docker exec headscale headscale preauthkeys create -u mynetwork --reusable --expiration 24h

本番環境で6ヶ月運用して得た教訓

半年間この構成に頼ってきたことで、安定したメッシュネットワークを維持するためのポイントがいくつか見えてきました。

  • リバースプロキシを使用する: ポート8080を直接公開するのはリスクがあります。Nginx Proxy ManagerやCaddyを使用してHTTPS化しましょう。モバイルクライアントは、有効なSSL証明書を使用したポート443経由の方が、より安定して接続できます。
  • データベースを保護する: db.sqliteファイルはネットワークの心臓部です。これが破損すると、すべてのノードを手動で再認証しなければならなくなります。私は簡単なcronジョブを使って、毎晩NASにバックアップを取っています。
  • MagicDNSを有効にする: Headscaleは内部DNSをサポートしています。100.64.x.xといったIPアドレスを何十個も覚えるよりも、ssh proxmox.mynetwork.meshのように入力する方がはるかに簡単です。
  • iOSの隠し設定: iPhoneでサーバーを変更するのは少しコツがいります。Tailscaleアプリを開き、設定に移動して、上部にある「Tailscale」ロゴを10回ほどタップしてください。すると、HeadscaleのURLを入力するための隠しフィールドが表示されます。

Headscaleへの切り替えは、私のホームラボにとって最良の選択でした。将来の価格改定に対する不安がなくなり、ネットワークマップを完全にコントロールできるようになりました。クラウドに縛られず、プライベートで高性能なVPNを求めているなら、これが正解です。

Share: