VPSにNetBird VPNサーバーをセルフホストする方法
VPS 1台で NetBird のメッシュVPNを構築します。DNSとTLS、固定した quickstart script、無人接続用の setup key、Headscaleとの違いを詳しく解説します。
NetBird VPN サーバーをセルフホストするメリット
NetBird VPN サーバーをセルフホストすると、自分が所有する VPS にコントロールプレーンを配置できます。コントロールプレーンは、ピアの一覧を保持し、どのマシンがどのマシンへ到達できるかを決定し、NAT(ネットワークアドレス変換)の背後にある2つのピアが相互に検出できるよう支援します。トンネル自体は引き続き WireGuard であり、マシン間で直接暗号化されます。変わるのは、デバイス一覧やログイン処理を外部企業が保持しなくなる点です。ただし、これによって得られるものを正しく理解してください。ホスト型コントロールプレーンがトラフィックを暗号化する鍵を保持するわけではありません。また、侵害された調整サーバーが実際に実行できることは、内容を確認する前に多くの人が想定するより限定的です。詳しくは調整サーバーが侵害された場合に実際に可能なことを参照してください。
NetBird は、すでに知っているかもしれない2つの仕組みの中間に位置します。メッシュオーバーレイなので、すべての通信を1つのゲートウェイ経由で送るのではなく、ピア同士が接続します。また、エンドツーエンドでセルフホストできるため、セルフホスト型の Tailscale コントロールサーバーである Headscale と比較できます。単一ゲートウェイ型のトンネルしか運用したことがない場合は、まず通常の WireGuard とメッシュオーバーレイの違いを読んでください。この違いを理解すると、このページの後半を把握しやすくなります。
実際に必要なのが、すべての通信を1台のサーバーから外部へ出す構成だけであれば、メッシュは目的に対して過剰な仕組みです。単一の VPS 上に構築する通常の WireGuard VPN、またはTailscale の exit nodeなら、稼働させるコンポーネントを大幅に減らして同じことを実現できます。また、目的がマシン同士を接続することではなく、1つのプライベートネットワークへ到達することなら、VPS 上の Tailscale subnet routerを使えば、以下のスタックを導入せずに、そのネットワーク範囲を既存の tailnet に通知できます。
実際に動作する構成
構成は最近変更されており、古い記事の多くは以前の構成を説明しています。2026 年 10 月に v0.80.0 と、このガイドで固定しているリリースである v0.76.2 を確認したところ、quickstart スクリプトはデフォルトで 3 つのサービスを含む Compose ファイルを作成します。
netbird-serverは管理 API、signal サービス、STUN リスナーを組み込んだ relay、組み込みの identity provider を提供します。以前のリリースでは、これらは個別のコンテナで動作し、identity provider も別途 Zitadel をインストールして、先に構築する必要がありました。dashboardは管理用 Web コンソールです。traefikは TLS (transport layer security) を終端し、初回起動時に Let's Encrypt へ証明書を要求します。
さらに 2 つのサービスがあります。プロンプトで有効にすることを選択しない限り、これらは起動しません。NetBird Proxy サービスは、内部サービスをパブリックホスト名で公開します。CrowdSec は悪意のあるトラフィックをフィルタリングします。動作するメッシュを構築するだけなら、どちらも必要ありません。また、小規模なサーバーではメモリを消費します。
単一の Docker コンテナで動作する wg-easy から移行する場合、サービス数は大幅に増えます。その代わり、アクセスポリシーとユーザーごとのアカウントを利用でき、ピア同士が 1 つのゲートウェイを経由せずに直接接続できます。
開始前に必要なもの
公開ドメイン名は必須です。ダッシュボード、API、relay はすべて port 443 の HTTPS を使用します。Traefik は、port 443 で応答する TLS-ALPN-01 challenge を使って Let's Encrypt から証明書を取得します。このため、パブリックインターネットからこの VPS に解決できる名前が必要です。IP アドレスだけではこの手順を利用できません。
A record を 1 つ作成し、netbird.example.com を VPS の公開 IPv4 アドレスに向けます。何かを実行する前に、反映を待ってください。
dig +short netbird.example.comこのコマンドはサーバーのアドレスを出力する必要があります。DNS の反映前に installer を実行すると、初回起動時に証明書の要求が失敗します。失敗した検証を繰り返すと Let's Encrypt の rate limit に達するため、再試行できるまで制限の回復を待つことになります。
インターネットから到達できる必要がある port は 3 つです。TCP 80 は HTTPS への redirect、TCP 443 はダッシュボード、API、signal、relay の通信と証明書 challenge、UDP 3478 は STUN に使用します。
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 3478/udp
sudo ufw reload
sudo ufw statusプロバイダーの network firewall でもこれらを開放してください。多くの VPS panel では、これは別の制御項目です。そのため、サーバー自身の ufw status が正しく見えても接続を拒否されます。
STUN (session traversal utilities for NAT) により、peer は自身の NAT が割り当てた公開アドレスと port を確認できます。これにより、2 つの peer は直接 tunnel を試行できます。UDP 3478 を block しても、peer は TCP 443 の relay 経由で接続できるため、問題が表面化しないことがあります。直接経路を見つけられない peer には Connection type: Relayed が表示され、通信は peer 間ではなく VPS を経由します。同じ LAN 上の peer は、ローカルアドレスを使って引き続き直接接続できます。
ソフトウェア側では、Compose v2 plugin 付きの Docker と、jq、curl が必要です。script は Docker、Compose、jq を確認し、どれかが不足していると停止します。curl は確認せずに使用するため、先に install してください。この VPS で Docker を初めて使用する場合は、まず VPS で Docker Compose を動作させる を実施してください。
bundled reverse proxy を使用しない場合の port
Traefik を使用しない場合でも、統合 server は 1 つの HTTP backend で management、signal、relay を処理するため、port の数はほとんど増えません。生成される Compose file は次を publish します。
- TCP 8080、dashboard。デフォルトでは 127.0.0.1 に bind
- TCP 8081、
netbird-server。デフォルトでは 127.0.0.1 に bind - UDP 3478、STUN。直接 publish
独自の proxy で TCP 443 の TLS を終端し、これら 2 つの local port に転送します。STUN は proxy を経由しないため、どちらの場合も firewall で UDP 3478 を開放したままにします。management gRPC、signal gRPC、relay 用に個別の port を列挙している guide は、以前の multi-container 構成を説明しています。
この構成は、別の用途ですでに TLS を終端している場合だけ選択してください。それ以外では、bundled Traefik の方が rule が少なく、ミスも減ります。
quickstart script で NetBird server を install する
公式に記載されている one-liner は、最新の release を直接 shell に pipe します。
curl -fsSL https://github.com/netbirdio/netbird/releases/latest/download/getting-started.sh | bashrelease を固定してください。latest は変化するため、2 週間離れて同じ command を実行すると異なる install になります。また、どの release が config を書き込んだかを示す情報も disk 上に残りません。tag 付きの release を download して内容を確認し、その後で実行してください。
mkdir -p ~/netbird
cd ~/netbird
curl -fsSL -o getting-started.sh \
https://github.com/netbirdio/netbird/releases/download/v0.76.2/getting-started.sh
less getting-started.sh
bash getting-started.shscript は最初に domain を尋ねます。
Enter the domain you want to use for NetBird (e.g. netbird.my-domain.com):次に TLS の処理方法を尋ねます。
Which reverse proxy will you use?
[0] Traefik (recommended - automatic TLS, included in Docker Compose)
[1] Existing Traefik (labels for external Traefik instance)
[2] Nginx (generates config template)
[3] Nginx Proxy Manager (generates config + instructions)
[4] External Caddy (generates Caddyfile snippet)
[5] Other/Manual (displays setup documentation)
Enter choice [0-5] (default: 0):[0] を選択してください。Option 2 から 4 は config snippet を書き込み、接続設定を自分で行う必要があります。Option 5 は Compose file、dashboard.env、config.yaml を書き込み、setup documentation を terminal に表示します。これはすでに proxy が動作している server では正しい選択ですが、新規の server では適切ではありません。続く option 0 では email address を尋ねます。Traefik はその address を Let's Encrypt account に登録します。prompt では現在も証明書通知用の address と表示されますが、Let's Encrypt は June 4, 2025 に expiry email の送信を停止しました。そのため、renewal の問題は inbox ではなく Traefik log に現れます。
初回 install では NetBird Proxy service に no と答えてください。追加で 1 つの DNS record、つまり *.netbird.example.com CNAME を netbird.example.com に向ける wildcard record が必要になります。また、通常の mesh では何も行いません。CrowdSec の prompt は proxy を有効にした場合にだけ表示されるため、proxy を拒否すると CrowdSec も skip されます。どちらも後から追加できます。
script は current directory に次を書き込みます。docker-compose.yml、mode 600 の config.yaml、dashboard.env です。bundled Traefik を使用する場合、NetBird Proxy を有効にしたときだけ traefik-dynamic.yaml と proxy.env も追加します。この directory は保持する state として扱ってください。config.yaml には store 内の data を暗号化する key が保存されています。これを失っても reinstall では解決できません。
docker compose ps
docker compose logs -f netbird-serverすべての service は running の status を running と表示し、server log は loop 状態で restart せずに安定する必要があります。証明書は個別に確認します。
docker compose logs traefik | grep -i acmeACME (automatic certificate management environment) は、Traefik が証明書を取得するために使用する protocol です。ここでの error は、ほぼ常に DNS または閉じた port 443 が原因です。
最初の管理者アカウントを作成する
https://netbird.example.comを開きます。新規インストール直後はログインフォームではなく、セットアップページが表示されます。メールアドレス、名前、パスワードを入力し、Create Accountをクリックします。このアカウントが最初の管理者になり、ページはログインフォームへリダイレクトされます。
このアカウントは、netbird-serverコンテナに組み込まれたアイデンティティプロバイダーを基盤とする、NetBird独自のユーザーストアに保存されます。外部のコンポーネントは必要ありません。これは、1年前のセルフホスト型NetBirdからの最大の変更点です。当時は、動作する環境を用意するには、まずZitadelまたはKeycloakを構築し、4つのOIDC(OpenID Connect)値をsetup.envにコピーする必要がありました。それを済ませなければ、何も起動しませんでした。
セットアップページではなく、ブラウザーに証明書の警告が表示された場合、証明書は発行されていません。先にこの問題を解決してください。ダッシュボードは同じホスト名を使用してAPIと通信するため、証明書に問題があると分かりにくい形で失敗します。
最初のピアを追加する
メッシュに参加させる場合は、VPS 自体を含む任意の Linux マシンにクライアントをインストールします。
curl -fsSL https://pkgs.netbird.io/install.sh | shDebian と Ubuntu では、このスクリプトが NetBird のパッケージリポジトリを設定し、その後 apt でクライアントをインストールします。そのため、どちらの場合も最終的にはパッケージマネージャーが管理します。シェルへスクリプトをパイプで渡す方法が気になる場合は、まず curl -fsSL -o install.sh https://pkgs.netbird.io/install.sh で保存し、実行前に内容を確認してから sh install.sh を実行します。いずれの場合も、インストールされた内容を確認します。
apt-cache policy netbirdnetbird はコマンドラインクライアントとデーモンです。netbird-ui はデスクトップのトレイアプリであり、ヘッドレスサーバーでは使用しません。
次に、クライアントをサーバーへ接続します。
sudo netbird up --management-url https://netbird.example.com--management-url を省略すると、コンパイル時のデフォルトにより、クライアントは NetBird のホステッドサービスに登録されます。コマンドは正常終了し、マシンにもアドレスが割り当てられますが、セルフホストのダッシュボードには何も表示されません。この点で、ほぼ全員が一度はつまずきます。
コマンドは、ログインを完了するためにブラウザーで開く URL を表示します。その後、次を実行します。
netbird status
ip addr show wt0netbird status から 4 行を読み取ります。Management: Connected、Signal: Connected、利用可能なすべてのリレーを示す Relays: 行、そしてオーバーレイ範囲内の NetBird IP: です。wt0 は NetBird が作成する WireGuard インターフェースであり、同じアドレスが割り当てられている必要があります。
セットアップキーで2台目のマシンを無人で登録する
ブラウザーがなく、前に操作する人もいないマシンでは、ブラウザーログインを使えません。セットアップキーは、対話的な手順なしでマシンを登録する事前認証トークンです。ダッシュボードの Setup Keys で作成します。
種類は2つあります。使い捨てキーは、1台のマシンだけを認証して、その後は使用済みになります。再利用可能なキーは複数のマシンを登録でき、登録数に上限を設定することもできます。どちらにも有効期限を設定できます。また、新しい peer をグループに自動追加できるため、そのグループのアクセスルールがマシンの登録直後から適用されます。
sudo netbird up --setup-key <SETUP-KEY> \
--management-url https://netbird.example.com \
--hostname build-runner-01--hostname は、ダッシュボードに表示する名前を設定します。指定しない場合、peer にはマシン自身が名乗る名前が設定されます。すべてのエントリが ubuntu という名前になると、管理の役に立ちません。
コンテナーや短期間だけ使用するビルドエージェントでは、作成時にキーを ephemeral として設定します。ephemeral キーで登録した peer は、10 minutes を超えてオフラインになると自動的に削除されます。これにより、不要になったエントリが peer 一覧に残りません。
セットアップキーを前提に計画する前に、次の制限を理解しておく必要があります。キーの有効期限が切れるか、キーを失効させると、新しい登録は停止します。ただし、そのキーですでに登録済みのマシンは切断されません。マシンのアクセスを削除するには、その peer を削除します。
個別の ID プロバイダーはまだ必要ですか?
小規模な構成では、通常は必要ありません。組み込みのユーザーストアでダッシュボードから作成したアカウントを管理できるため、数人程度であれば十分です。
すでに ID プロバイダーを運用しており、ユーザー一覧を別に持ちたくない場合は、外部 ID プロバイダーを使用します。NetBird は OIDC に対応する任意のプロバイダーを受け入れます。プロバイダーで confidential OIDC client を登録し、NetBird のダッシュボードに name、client ID、client secret、issuer の4つの値を入力します。NetBird は redirect URL を表示するため、それをプロバイダーに貼り付けます。Google、Microsoft Entra ID、Okta、Zitadel、Keycloak、Authentik、Pocket ID には専用の連携設定があり、それ以外は generic OIDC として設定します。すでに セルフホスト型のシングルサインオンとして Authentik を運用している場合は、アカウント一覧を2つに分けずに済む方法です。
プロバイダーを追加した後もローカルログインは利用でき、設定済みの各プロバイダーがログインページに表示されます。強力なパスワードを設定したローカルの admin アカウントを1つ残してください。OIDC の設定に問題があっても、そのアカウントからログインできます。
NetBird と Headscale: どちらのコントロールプレーンを運用すべきか
どちらも、クライアントが通常接続するホスト型コントロールサーバーへの依存をなくします。ただし、プロジェクトの構成は同じではありません。
Headscale は Tailscale のコントロールサーバーを再実装したもので、公式の Tailscale クライアントを使い続けます。公式の Web コンソールはありません。設定ファイルに対して headscale コマンドを実行し、ユーザーと事前認証キーを管理します。コミュニティ製の Web インターフェースは存在しますが、プロジェクトには含まれません。状態をファイルで管理し、変更をバージョン管理に入れたい人に適しています。
NetBird は、専用クライアント、専用ダッシュボード、組み込みの ID プロバイダー、ブラウザーで編集するアクセスポリシーを含む製品全体をリリースします。VPS 上の構成要素が増えますが、ターミナルを開くことがない同僚に引き継ぐ作業は大幅に少なくなります。Headscale ではなくホスト型 Tailscale と NetBird を比較するのであれば、どちらも基盤で WireGuard を使用しています。そのため、NetBird と Tailscale の比較では、実際の違いである、コントロールプレーンを誰が運用するか、アクセスルールをどのように記述するか、リレーがどのようにトラフィックを転送するかを説明しています。
すでに Tailscale クライアントを使っている場合や、可能な限り小規模なコントロールプレーンを求める場合は Headscale を運用します。複数の人がピアを管理する必要があり、コンソールと SSO を自分で組み立てずに使いたい場合は NetBird を運用します。どちらかに決める前に、Tailscale の無料プランに実際に含まれる内容を確認してください。6 ユーザー以内に収まる非営利のグループなら、ホスト型コントロールプレーンを無料で利用でき、ユーザーのデバイス数は無制限、開始時点でタグ付きリソースを 50 個利用できます。そのため、コントロールプレーンを自分で運用する理由がない場合もあります。この上限を超えると、料金はマシン数ではなく人数に応じて増えます。したがって、Tailscale がグループに請求する金額を算出する方法を確認し、VPS の費用と、この構成の運用にかかる時間と比較してください。
この構成を実行できる VPS の最小構成はどの程度ですか?
文書上の最小要件は、1 CPU と 2 GB のメモリです。2 GB のプランを選択してください。
小規模なサーバーでは、安全に省略できるものが3つあります。NetBird Proxy service は無効にしてください。これは内部サービスを公開ホスト名で公開するためのものであり、peer の接続には関係ありません。CrowdSec も省略してください。script では proxy と組み合わせてのみ提示されます。初日から導入するより、後で外部公開するサーバーに追加する方が適しています。netbird_data volume ではデフォルトの SQLite store を使用してください。複数のマシンに deployment を分割する場合や、実際に同時実行性が必要になった場合にのみ PostgreSQL に移行します。この移行は後から実行できる手順として文書化されています。
relay は省略できない唯一の component です。NAT が宛先ごとに異なる port を割り当てる2つの peer は、直接 tunnel を確立できません。そのため、relay が接続を成立させる唯一の経路になります。無効にしてもメモリ使用量はほとんど減らず、原因の追跡が難しい形で接続が壊れます。
1台のサーバーでは不十分になった場合、最初に外部へ移すのは relay です。standalone relay は NB_LISTEN_ADDRESS、NB_EXPOSED_ADDRESS、NB_AUTH_SECRET、NB_ENABLE_STUN で実行します。shared secret は relay とメインサーバーで完全に一致している必要があります。一致しない場合、client は relay への認証に失敗します。
障害の種類と確認できる現象
ダッシュボードに証明書の警告が表示される。 Traefik が証明書を取得できていません。docker compose logs traefik | grep -i acme を実行します。原因は 2 つあります。dig +short netbird.example.com がまだこの VPS を返していないか、Let's Encrypt とコンテナの間のどこかで TCP 443 が閉じています。通常は ufw ではなく、プロバイダーのネットワークファイアウォールが原因です。チャレンジへの応答は 443 で行われるため、80 番ポートが開いていても解決しません。ループで再試行する前に原因を修正してください。Let's Encrypt では、1 時間あたり、アカウントごとにホスト名 1 つにつき認証失敗が 5 回までしか許可されません。上限が回復するまで再試行できなくなります。
クライアントは接続したと表示するが、ダッシュボードが空です。 --management-url が未指定だったため、クライアントは NetBird のホスト型サービスに登録されています。netbird status --detail を実行し、実際に接続しているサーバーを示す Management: の行を確認します。Management: Connected to https://api.netbird.io:443 が表示される場合、クラウドに接続しています。sudo netbird down を実行してから、もう一度 sudo netbird up --management-url https://netbird.example.com を実行します。
すべての peer に Connection type: Relayed と表示される。 直接トンネルが確立されていないため、すべてのトラフィックが VPS を経由し、遅延が 1 ホップ分増えています。STUN は peer が自身のパブリックアドレスとポートを認識するために使われるため、VPS のファイアウォールとプロバイダーのファイアウォールで UDP 3478 を確認します。netbird status --detail は Direct: false と、各 peer の ICE(interactive connectivity establishment)候補タイプも出力します。これにより、接続試行がどこまで進んだかを確認できます。一部のネットワークでは relayed しか利用できず、異常ではありません。
peer は参加するが、何にも到達できない。 mesh に参加していることは、2 つの peer 間の通信が許可されていることを意味しません。通信可否はアクセスポリシーで決まり、ポリシーが割り当てられていないグループからはどこにも到達できません。ルートやファイアウォールの調査を始める前に、ダッシュボードでポリシーを確認します。
netbird status が daemon の問題を報告する。 サービスが実行されていません。sudo netbird service status と sudo netbird service start を使用します。クライアントのログは /var/log/netbird/client.log にあります。原因を特定できない場合は、netbird debug bundle --anonymize --system-info を実行すると、ログ、状態、ルート、DNS 設定、ファイアウォールの状態が 1 つのアーカイブに収集されます。
バックアップとアップグレード
インストール全体を支えるものは 2 つあります。docker-compose.yml と config.yaml を格納するディレクトリと、データベースおよび暗号化キーを保持する Docker ボリュームです。これらを一緒にバックアップしてください。config.yaml にはストア内のデータを暗号化するキーが保存されています。そのため、これがないデータベースのコピーを復元しても、読み取れるデータは何も復元できません。
docker volume ls
docker compose down
sudo tar czf netbird-config.tgz -C ~ netbird
docker run --rm -v netbird_netbird_data:/data -v "$PWD":/backup \
alpine tar czf /backup/netbird-data.tgz -C /data .
docker compose up -dCompose はボリューム名にプロジェクトディレクトリの名前を付けます。そのため、netbird_data と記載されているボリュームは通常、netbird_netbird_data として表示されます。最初に docker volume ls を実行し、表示された名前を使用してください。そうしないと、docker run は空のボリュームを作成して何もアーカイブせず、失敗したことも通知しません。アーカイブは VPS の外部に保管してください。すでにバックアップツールを使用している場合は、restic または BorgBackup でオフサイトへの保存を処理できます。
サーバーのアップグレードは、イメージを pull して再作成する手順です。
docker compose pull
docker compose up -d
docker compose psこの方法を前提に運用する前に、docker compose config | grep image: を実行してください。latest と表示されるタグは、バージョンに固定してください。インストールスクリプトを固定した理由と同じで、実行中のバージョンを把握し、アップグレードで問題が発生した場合に戻せるバージョンを確保するためです。クライアントは、インストールに使用したパッケージマネージャーを使用してアップグレードします。
FAQ
NetBird をセルフホストする場合、自分で ID プロバイダーを用意する必要がありますか?
いいえ。現在のリリースにはユーザーストアが組み込まれているため、https://netbird.example.com でブラウザーから最初の管理者アカウントを作成し、その後ダッシュボードからユーザーを追加できます。外部 OIDC プロバイダーは任意で、後から name、client ID、client secret、issuer の 4 つの値を指定して追加できます。NetBird の前に Zitadel や Keycloak をデプロイするよう案内するガイドは、現在は不要な構成を説明しています。従うと、運用するサービスが 1 つ余分に増えます。
すべての peer に Connection type: Relayed と表示されるのはなぜですか?
直接接続が確立されていないため、トラフィックが VPS 上の relay を経由しています。通常の原因は UDP 3478 がブロックされていることです。これは peer が自分のパブリックアドレスとポートを検出するために使用する STUN ポートです。VPS のファイアウォールと、プロバイダー側の別のネットワークファイアウォールでこのポートを開き、もう一度 netbird status --detail を実行して Direct: の行を確認します。両方の peer が宛先ごとに異なるポートを割り当てる NAT の背後にある場合は、relayed になるのが通常であり、設定ミスではありません。
client は接続しましたが、ダッシュボードに peer が表示されません。何が起きていますか?
--management-url を省略した場合に発生する動作で、client がサーバーではなく NetBird のホステッドサービスに登録されています。netbird status --detail は Management: の行に接続先のサーバーを表示するため、https://api.netbird.io:443 のような値であれば、そのことを確認できます。sudo netbird down を実行し、続けて sudo netbird up --management-url https://netbird.example.com を実行すると、peer がダッシュボードに表示されます。
セルフホスト型 NetBird は Headscale とどう違いますか?
どちらも、ホステッドの control server を自分で運用するサーバーに置き換えます。Headscale は control plane のみです。headscale コマンドと設定ファイルで管理し、公式の Web コンソールはなく、公式の Tailscale client を動作させます。NetBird には、独自の client、管理ダッシュボード、ID プロバイダー連携が同じスタックに含まれています。Headscale は運用規模が小さく、状態をファイルに保存します。NetBird は、ターミナルを使わない人に渡して運用してもらいやすい構成です。
セルフホスト型 NetBird サーバーには、どの程度のサイズの VPS が必要ですか?
ドキュメント上の最小要件は 1 CPU と 2 GB のメモリで、購入するなら 2 GB の構成にします。インストール時に任意の proxy service を選択しないでください。これにより CrowdSec の確認も省略できます。PostgreSQL が本当に必要になるまでは、デフォルトの SQLite ストアを使用します。