すでにTailscaleは稼働済み — 1台のLXCをサブネットルーターとして設定し、残りのコンテナをtailnet上に公開していました。つまり、リモートからアクセスはできていたのです。ただ、IPアドレスを覚えておく必要がありました。

https://proxmox.home.lab:8006 が欲しかったのです。数字ではなく名前を入力したかったのです。

Tailscale App Connectors がその答えでした。そこに至るまでに思ったより時間がかかったので、実際に動作する手順をまとめます。


最終的な構成

1台のLXCが3つの役割を担います:サブネットルーター、アプリコネクター、DNSサーバーです。tailnet上の任意のデバイスは <service>.home.lab を正しいコンテナIPに解決し、トラフィックを自動的にルーティングします。App Connectors は すべてのTailscaleプラン で利用可能です — プランは変更される可能性があるので、料金ページで確認してください。

このガイドは、すでにTailscale LXCをサブネットルーターとして稼働させていることを前提としています。ない場合は この動画 でセットアップ方法を確認し、ステップ2に戻ってアプリコネクターの役割を追加してください。

設定全体を通じて3つの値が一貫して使用されます。 いずれかの値がステップ間でずれていると、何かでサイレントに失敗します:

一致が必要な場所
タグ名(例:tag:app-connector ACL tagOwners、ACL nodeAttrs、ACL autoApprovers、tailscale up コマンド
ドメインサフィックス(例:home.lab ACL domainsリスト、dnsmasqエントリ、Tailscale Appsページ、split DNS制限
LANサブネット(例:192.168.1.0/24 ACL autoApprovers、tailscale up コマンド、dnsmasq IP

ステップ1:Tailscale ACLポリシーの更新

Tailscale管理コンソールAccess Controls に移動します。現在のポリシーを表示するhuJSONエディタが表示されます。置き換えるのではなく、これらのセクションをトップレベルキーとしてマージしてください。すでに grants ブロックがある場合は、新しいルールをその中に追加してください。

{
  "tagOwners": {
    "tag:app-connector": []
  },

  "grants": [
    { "src": ["*"], "dst": ["*"], "ip": ["*"] }
  ],

  "autoApprovers": {
    "routes": {
      "0.0.0.0/0": ["tag:app-connector"],
      "::/0":      ["tag:app-connector"]
    }
  },

  "nodeAttrs": [
    {
      "target": ["*"],
      "app": {
        "tailscale.com/app-connectors": [
          {
            "name": "[CHOOSE_NAME_FOR_THE_APP_CONNECTOR]",
            "connectors": ["tag:app-connector"],
            "domains": [
              // whatever domains you need to expose
              "proxmox.home.lab",
              "homeassistant.home.lab"
            ]
          }
        ]
      }
    }
  ]
}

Enter fullscreen mode Exit fullscreen mode

注意点: nodeAttrstarget["*"] である必要があります。最初に ["tag:app-connector"] を試しましたが動作しませんでした。Tailscaleは次のエラーを返します:tailscale.com/app-connectors: can only be specified with target "*"。アプリ定義内の connectors フィールドで、どのノードが作業を行うかを制御します。target はどのノードがこの設定を受け取るかを制御し、アプリコネクターの場合は全員である必要があります。


ステップ2:LXCをアプリコネクターとして設定

dnsmasqをインストールする前に、systemd-resolved がポート53を占有していないか確認してください — 占有している場合、dnsmasqは起動に失敗します:

systemctl is-active systemd-resolved

Enter fullscreen mode Exit fullscreen mode

アクティブな場合は、スタブリスナーを無効にします:

sed -i 's/#DNSStubListener=yes/DNSStubListener=no/' /etc/systemd/resolved.conf
systemctl restart systemd-resolved

Enter fullscreen mode Exit fullscreen mode

次に、Tailscale LXCにSSH接続し、新しい役割をアドバタイズします:

tailscale up \
  --advertise-connector \
  --advertise-tags=tag:app-connector \
  --advertise-routes=192.168.1.0/24

Enter fullscreen mode Exit fullscreen mode

192.168.1.0/24 を実際のLANサブネットに置き換えてください。

注意点: ノードは --advertise-connector で明示的にオプトインする必要があります。管理コンソールにノードをコネクターとして指定するボタンがあるのではないかと探していましたが、存在しませんでした。ノードはCLI経由で自身の役割をアドバタイズします。これを実行するまで、Apps UIで選択可能なものとして表示されません。

動作確認: 管理コンソール → Machines に移動します。LXCにアプリコネクターバッジが表示されているはずです。


ステップ3:dnsmasqのインストールと設定

App Connectorsはルーティングを処理しますが、ドメイン名をIPに解決しません。そのためにローカルDNSサーバーが必要です。同じLXC上のdnsmasqが最もシンプルな選択肢です。

apt update && apt install -y dnsmasq

Enter fullscreen mode Exit fullscreen mode

/etc/dnsmasq.conf を編集し、以下を追記します:

# Without this, dnsmasq rejects queries from the Tailscale interface.
# The systemd unit passes --local-service which restricts to local subnets;
# adding interface=tailscale0 overrides that behaviour.
interface=tailscale0
bind-interfaces

# One line per container — use your actual LAN IPs
address=/proxmox.home.lab/192.168.1.2
address=/homeassistant.home.lab/192.168.1.3

Enter fullscreen mode Exit fullscreen mode

すでにdnsmasqをDHCPや他の目的で使用している場合:既存の interface= 行を置き換えるのではなく、interface=tailscale0 行を追加してください。

起動と確認:

systemctl enable --now dnsmasq
systemctl status dnsmasq   # should be active, no "limited to local subnets"

dig @127.0.0.1 proxmox.home.lab
# ANSWER SECTION should show your container's IP

Enter fullscreen mode Exit fullscreen mode

注意点: 初回起動後、ステータスに DNS service limited to local subnets と表示される場合があります。これはsystemdユニットファイルに組み込まれた --local-service に起因します — これをオーバーライドする設定ファイルオプションはありません。修正方法は interface=tailscale0 で、Tailscaleインターフェース上でクエリを受け入れるようdnsmasqに指示します。再起動後、警告は消えます。


ステップ4:管理コンソールでアプリを登録

管理コンソール → AppsAdd an app

  • Name: 任意の説明的な名前
  • Type: Custom
  • Domains: home.lab ドメイン(ステップ1と同じ)をカンマ区切りで
  • Connector tag: tag:app-connector
  • Save

ドメインはACLの nodeAttrs とここに表示されます。目的が異なります:ACLはルーティングポリシーを制御(どのノードがどのトラフィックを処理するか)し、Apps UIはDNS-over-HTTPS転送のためにTailscaleが使用するコネクター関連付けを登録します。両方に同じドメインが必要です。


ステップ5:Split DNSネームサーバーの追加

管理コンソール → DNSAdd nameserver

  • Nameserver: LXCのtailnet IPv4アドレス — 100.x.y.z のもの(LXCで tailscale ip -4 を実行)
  • Restrict to domain にチェック
  • Domain: home.lab
  • Save

同じページで Magic DNS もオンになっていることを確認してください。Split DNSはこれなしでは動作しません。

これはTailscaleに次のことを指示します:home.lab 以下のものはこの特定のネームサーバーに問い合わせ、それ以外は通常のDNSを使用する。


ステップ6:クライアントの設定

Linux:

tailscale set --accept-routes=true --accept-dns=true

Enter fullscreen mode Exit fullscreen mode

macOS(GUIアプリ使用):
Tailscaleメニューバー → Preferences → Use Tailscale DNS を有効化。完了。

macOS CLIのみ(GUIアプリなし):

注意点: macOSのTailscale CLIはシステムDNSを管理できません。tailscale set --accept-dns=true はフラグを黙って受け入れますが、何も実行しません — CLIにはGUIアプリなしで必要なNetwork Extensionをインストールするメカニズムがありません。tailscale debug resolve your-domain.home.lab は、netmapにルートが正しく設定されているにもかかわらず no such host を返します。

回避策 — Wi-FiのDNSを手動でLXCに向ける:

sudo networksetup -setdnsservers Wi-Fi <LXC tailnet IPv4>

Enter fullscreen mode Exit fullscreen mode

元に戻す:

sudo networksetup -setdnsservers Wi-Fi "Empty"

Enter fullscreen mode Exit fullscreen mode


サービスへのアクセス

https://proxmox.home.lab:8006
http://homeassistant.home.lab:8123

Enter fullscreen mode Exit fullscreen mode

App Connectorsはポートについては何も行いません — ブラウザはデフォルトで80を使用します。80または443で動作しないサービスにはポートを含めてください。ポートを完全に削除したい場合は、サービスの前にリバースプロキシ(Caddyまたはnginx)を配置してください。


もう1つの注意点:ChromeのDNS-over-HTTPS

これはmacOSだけでなく、クロスプラットフォームの問題です。ChromeにはシステムDNSを完全にバイパスする独自のDoHがあります。dig は正しく解決するのにChromeが「ページに到達できません」と言う場合、それが原因です。

無効化:Settings → Privacy and security → Security → Use secure DNS → off。


新しいコンテナの追加

正確に同じドメイン名を使用する3つの場所:

  1. dnsmasq設定address=/newservice.home.lab/<LAN IP> を追加し、systemctl restart dnsmasq を実行
  2. ACL nodeAttrsdomains リストに "newservice.home.lab" を追加し、保存
  3. 管理コンソール → Apps — ホームラボアプリを編集し、ドメインを追加

トラブルシューティング

症状 修正方法
can only be specified with target "*" nodeAttrsで "target": ["tag:app-connector"]"target": ["*"] に変更
dnsmasqに「limited to local subnets」と表示される /etc/dnsmasq.confinterface=tailscale0 + bind-interfaces を追加し、再起動
dnsmasqが起動しない ポート53の競合 — systemd-resolvedスタブを無効化: sed -i 's/#DNSStubListener=yes/DNSStubListener=no/' /etc/systemd/resolved.conf && systemctl restart systemd-resolved
dig @<LXC IP> service.home.lab は動作するがシステムDNSは動作しない macOS CLIはsplit DNSを管理できない — GUIアプリを使用するか sudo networksetup -setdnsservers Wi-Fi <LXC tailnet IPv4>
Chrome:「ページに到達できません」(dig は解決しているにもかかわらず) ChromeのセキュアDNSを無効化:Settings → Privacy and security → Security → Use secure DNS → off
ブラウザ:「ページに到達できません」(どのブラウザでも) ポートが欠落 — https://service.home.lab:<port> を試す
管理コンソールにLXCがアプリコネクターとして表示されない LXCで tailscale up --advertise-connector --advertise-tags=tag:app-connector を実行