SSD Nodes Learn Hosting plans →
คู่มือ Matt Connorโดย Matt Connor

วิธีติดตั้ง NetBird VPN server บน VPS ด้วยตนเอง

คู่มือติดตั้ง NetBird บน VPS ตั้งแต่การตั้งค่า DNS และ TLS ไปจนถึงการใช้งาน setup keys สำหรับ unattended peers พร้อมเปรียบเทียบความแตกต่างระหว่าง NetBird กับ Headscale อย่างละเอียด

ประโยชน์ของการโฮสต์ NetBird VPN server ด้วยตนเอง

การโฮสต์ NetBird VPN server ด้วยตนเองจะทำให้ control plane อยู่บน VPS ของคุณ ซึ่งเป็นส่วนที่เก็บรายการ peer, ตัดสินใจว่าเครื่องใดสามารถเข้าถึงเครื่องใดได้บ้าง และช่วยให้ peer สองเครื่องค้นหากันและกันได้เมื่ออยู่หลัง NAT (network address translation) สำหรับตัว tunnel นั้นยังคงเป็น WireGuard ซึ่งมีการเข้ารหัสโดยตรงระหว่างเครื่องของคุณ สิ่งที่เปลี่ยนไปคือไม่มีบริษัทภายนอกถือครองรายการอุปกรณ์หรือขั้นตอนการเข้าสู่ระบบของคุณ คุณควรทำความเข้าใจให้ชัดเจนว่าสิ่งนี้ให้ประโยชน์อย่างไร เพราะ control plane แบบโฮสต์ก็ไม่ได้ถือครองกุญแจที่ใช้เข้ารหัส traffic ของคุณเช่นกัน และ สิ่งที่ coordination server สามารถทำได้จริงหากถูกบุกรุก นั้นมีขอบเขตจำกัดกว่าที่คนส่วนใหญ่เข้าใจก่อนที่จะได้อ่านรายละเอียด

NetBird อยู่กึ่งกลางระหว่างสิ่งที่คุณอาจรู้จักอยู่แล้ว มันเป็น mesh overlay ดังนั้น peer จึงเชื่อมต่อถึงกันโดยตรงแทนที่จะส่งทุกอย่างผ่าน gateway เดียว นอกจากนี้ยังสามารถโฮสต์เองได้ทั้งหมดตั้งแต่ต้นจนจบ ซึ่งทำให้มันถูกนำไปเปรียบเทียบกับ Headscale ซึ่งเป็น control server สำหรับ Tailscale ที่โฮสต์เองได้ หากคุณเคยใช้งานเพียง tunnel แบบ gateway เดียว ให้ลองอ่าน ความแตกต่างระหว่าง WireGuard แบบปกติกับ mesh overlay ก่อน เพราะแนวคิดนั้นคือสิ่งที่ทำให้เนื้อหาในส่วนที่เหลือของหน้านี้มีประโยชน์

หากสิ่งที่คุณต้องการจริงๆ คือเซิร์ฟเวอร์เพียงเครื่องเดียวที่ traffic ทั้งหมดของคุณวิ่งผ่าน mesh อาจเป็นระบบที่ซับซ้อนเกินความจำเป็น WireGuard VPN แบบปกติบน VPS เครื่องเดียว หรือ Tailscale exit node สามารถทำงานนั้นได้โดยใช้การตั้งค่าที่น้อยกว่ามาก และหากเป้าหมายคือการเข้าถึงเครือข่ายส่วนตัวเครือข่ายหนึ่ง แทนที่จะเป็นการเชื่อมต่อเครื่องเข้าหากัน Tailscale subnet router บน VPS จะทำหน้าที่ประกาศช่วงเครือข่ายนั้นไปยัง tailnet ที่คุณมีอยู่แล้ว โดยไม่ต้องใช้ stack ทั้งหมดที่กล่าวมาข้างต้น

สิ่งที่ stack ทำงานอยู่จริง

โครงสร้างมีการเปลี่ยนแปลงเมื่อเร็วๆ นี้ และเอกสารเก่าส่วนใหญ่ยังคงอธิบายโครงสร้างแบบเดิม จากการตรวจสอบในเดือนตุลาคม 2026 เทียบกับ v0.80.0 และ v0.76.2 ซึ่งเป็นเวอร์ชันที่คู่มือนี้กำหนดไว้ สคริปต์ quickstart จะเขียนไฟล์ Compose ที่มี 3 บริการโดยค่าเริ่มต้น

  • netbird-server ทำหน้าที่จัดการ API, บริการ signal, relay พร้อมตัวรับฟัง STUN ในตัว และผู้ให้บริการระบุตัวตน (identity provider) แบบฝังตัว ในเวอร์ชันเก่าบริการเหล่านี้เป็นคอนเทนเนอร์แยกกัน และผู้ให้บริการระบุตัวตนคือการติดตั้ง Zitadel แยกต่างหากที่คุณต้องสร้างขึ้นก่อน
  • dashboard คือคอนโซลเว็บสำหรับผู้ดูแลระบบ
  • traefik ทำหน้าที่จัดการ TLS (transport layer security) และร้องขอใบรับรองจาก Let's Encrypt ในการเริ่มทำงานครั้งแรก

ยังมีอีก 2 บริการที่มีอยู่แต่จะปิดไว้จนกว่าคุณจะตอบตกลงที่ข้อความแจ้งเตือน บริการ NetBird Proxy จะเผยแพร่บริการภายในผ่านชื่อโฮสต์สาธารณะ ส่วน CrowdSec จะกรองทราฟฟิกที่เป็นอันตราย ทั้งสองบริการไม่จำเป็นสำหรับการสร้าง mesh ที่ใช้งานได้ และทั้งคู่ใช้หน่วยความจำบนเซิร์ฟเวอร์ขนาดเล็ก

หากคุณย้ายมาจาก wg-easy ในคอนเทนเนอร์ Docker เดียว นี่ถือเป็นการเพิ่มจำนวนส่วนประกอบขึ้นพอสมควร สิ่งที่คุณได้รับคือการควบคุมนโยบายการเข้าถึง (access policies), บัญชีผู้ใช้รายบุคคล และ peer ที่เชื่อมต่อถึงกันโดยตรงแทนที่จะผ่านเกตเวย์เพียงจุดเดียว

สิ่งที่ต้องเตรียมก่อนเริ่มต้น

ชื่อโดเมนสาธารณะเป็นสิ่งที่จำเป็น Dashboard, API และ Relay ทั้งหมดทำงานผ่าน HTTPS บนพอร์ต 443 โดย Traefik จะขอใบรับรองจาก Let's Encrypt ผ่านการตรวจสอบแบบ TLS-ALPN-01 ซึ่งต้องตอบกลับบนพอร์ต 443 ดังนั้นจึงจำเป็นต้องมีชื่อโดเมนที่ชี้มายัง VPS ของคุณจากอินเทอร์เน็ตสาธารณะ การใช้เพียง IP address จะไม่สามารถใช้งานในกระบวนการนี้ได้

ให้สร้าง A record หนึ่งรายการ netbird.example.com โดยชี้ไปยัง public IPv4 address ของ VPS และรอให้การตั้งค่ามีผลก่อนเริ่มดำเนินการใดๆ

dig +short netbird.example.com

คำสั่งดังกล่าวต้องแสดงผลเป็นที่อยู่ของเซิร์ฟเวอร์ของคุณ การรันตัวติดตั้งก่อนที่ DNS จะกระจายตัวจะทำให้การขอใบรับรองล้มเหลวในการเริ่มทำงานครั้งแรก และหากการตรวจสอบล้มเหลวซ้ำๆ จะทำให้ติดข้อจำกัดด้านอัตราการร้องขอ (rate limits) ของ Let's Encrypt ซึ่งจะทำให้คุณต้องรอจนกว่าข้อจำกัดจะถูกรีเซ็ตจึงจะลองใหม่ได้

พอร์ต 3 พอร์ตต้องสามารถเข้าถึงได้จากอินเทอร์เน็ต ได้แก่ TCP 80 สำหรับการเปลี่ยนเส้นทางไปยัง HTTPS, TCP 443 สำหรับ Dashboard, API, สัญญาณ (signal) และทราฟฟิกของ Relay รวมถึงการตรวจสอบใบรับรอง และ 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 ของคุณด้วย นี่เป็นการตั้งค่าแยกต่างหากในแผงควบคุมของ VPS ส่วนใหญ่ และเป็นสาเหตุที่ทำให้เซิร์ฟเวอร์ที่ตั้งค่า ufw status ไว้ถูกต้องแล้วยังคงปฏิเสธการเชื่อมต่อ

STUN (session traversal utilities for NAT) คือวิธีที่ peer จะเรียนรู้ public address และพอร์ตที่ NAT ของตนเองกำหนดให้ เพื่อให้ peer สองฝั่งสามารถพยายามสร้างอุโมงค์เชื่อมต่อโดยตรงได้ หากบล็อก UDP 3478 ไว้ peer จะยังคงเชื่อมต่อกันได้ผ่าน Relay บน TCP 443 ทำให้ดูเหมือนไม่มีอะไรเสียหาย แต่คุณจะพบ Connection type: Relayed บนทุก peer แทน และทราฟฟิกทั้งหมดจะวิ่งผ่าน VPS ของคุณแทนที่จะเป็นการเชื่อมต่อแบบ peer-to-peer

ในส่วนของซอฟต์แวร์ คุณต้องมี Docker พร้อมปลั๊กอิน Compose v2 รวมถึง jq และ curl สคริปต์จะตรวจสอบ Docker, Compose และ jq หากขาดรายการใดรายการหนึ่งสคริปต์จะหยุดทำงาน สคริปต์จะใช้ curl โดยไม่มีการตรวจสอบ ดังนั้นควรติดตั้งไว้ก่อน หาก Docker เป็นของใหม่บนเครื่องนี้ ให้ดำเนินการ ติดตั้ง Docker Compose บน VPS ให้เรียบร้อยก่อน

พอร์ตที่ต้องใช้หากไม่ใช้ reverse proxy ที่มาพร้อมกับระบบ

หากไม่มี Traefik เซิร์ฟเวอร์รวมยังคงจัดการการบริหารจัดการ, สัญญาณ และ Relay ไว้บน HTTP backend เดียวกัน ดังนั้นรายการพอร์ตจึงแทบไม่เพิ่มขึ้น ไฟล์ Compose ที่สร้างขึ้นจะเปิดพอร์ตดังนี้:

  • TCP 8080 สำหรับ Dashboard โดยผูกไว้ที่ 127.0.0.1
  • TCP 8081 สำหรับ netbird-server โดยผูกไว้ที่ 127.0.0.1
  • UDP 3478 สำหรับ STUN โดยเปิดใช้งานโดยตรง

Proxy ของคุณเองจะเป็นตัวทำ TLS termination บน TCP 443 และส่งต่อคำขอไปยังพอร์ตภายในทั้งสองพอร์ตนั้น ส่วน STUN จะไม่ผ่าน Proxy ดังนั้น UDP 3478 จึงต้องเปิดไว้บน Firewall ไม่ว่าจะกรณีใดก็ตาม คู่มือที่ระบุพอร์ตแยกต่างหากสำหรับ management gRPC, signal gRPC และ Relay นั้นอ้างอิงถึงโครงสร้างแบบหลายคอนเทนเนอร์รุ่นเก่า

เลือกวิธีนี้เฉพาะเมื่อเซิร์ฟเวอร์ของคุณทำ TLS termination ให้กับบริการอื่นอยู่แล้ว มิฉะนั้นการใช้ Traefik ที่มาพร้อมกับระบบจะช่วยลดกฎการตั้งค่าและลดข้อผิดพลาดได้มากกว่า

ติดตั้ง NetBird server ด้วยสคริปต์ quickstart

คำสั่งบรรทัดเดียวตามเอกสารจะดึง release ล่าสุดมาประมวลผลผ่าน shell โดยตรง:

curl -fsSL https://github.com/netbirdio/netbird/releases/latest/download/getting-started.sh | bash

ควรระบุเวอร์ชันให้ชัดเจน (pin) แทน เพราะ latest มีการเปลี่ยนแปลงอยู่เสมอ การรันคำสั่งเดิมในเวลาที่ห่างกันสองสัปดาห์อาจทำให้ได้การติดตั้งที่ต่างกัน และไม่มีบันทึกในดิสก์ว่าไฟล์ config ถูกสร้างขึ้นโดยเวอร์ชันใด ให้ดาวน์โหลด release ที่ระบุแท็กไว้ ตรวจสอบเนื้อหา แล้วจึงรันสคริปต์

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.sh

สคริปต์จะถามหาโดเมนก่อนเป็นอันดับแรก:

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] ส่วนตัวเลือก 2 ถึง 4 จะเขียนไฟล์ config snippet ไว้ให้และให้คุณจัดการการเชื่อมต่อเอง ส่วนตัวเลือก 5 จะเขียนเฉพาะไฟล์ Compose และแสดงเอกสารการตั้งค่าบน terminal ซึ่งวิธีนี้เหมาะสมกับเครื่องที่มี proxy รันอยู่แล้ว แต่ไม่เหมาะกับเครื่องที่ติดตั้งใหม่ ตัวเลือก 0 จะถามหาที่อยู่อีเมลซึ่ง Traefik จะนำไปลงทะเบียนกับบัญชี Let's Encrypt ของคุณ แม้ prompt จะระบุว่าเป็นที่อยู่สำหรับรับการแจ้งเตือนใบรับรอง แต่ Let's Encrypt ได้หยุดส่งอีเมลแจ้งเตือนหมดอายุตั้งแต่วันที่ 4 มิถุนายน 2025 ดังนั้นปัญหาการต่ออายุจะปรากฏใน log ของ Traefik แทนที่จะอยู่ในกล่องจดหมายของคุณ

สำหรับการติดตั้งครั้งแรก ให้ปฏิเสธการติดตั้ง NetBird Proxy service เพราะมันต้องการ DNS record เพิ่มอีกหนึ่งรายการ คือ wildcard *.netbird.example.com CNAME ที่ชี้ไปยัง netbird.example.com และไม่มีผลใดๆ กับการเชื่อมต่อแบบ mesh ปกติ ส่วน prompt ของ CrowdSec จะปรากฏขึ้นก็ต่อเมื่อเปิดใช้งาน proxy เท่านั้น ดังนั้นการปฏิเสธ proxy จะเป็นการข้ามส่วนนี้ไปด้วย ทั้งสองอย่างสามารถเพิ่มภายหลังได้

สคริปต์จะเขียนไฟล์ลงในไดเรกทอรีปัจจุบัน ได้แก่ docker-compose.yml, config.yaml (ด้วยโหมด 600) และ dashboard.env หากใช้ Traefik ที่มาพร้อมกัน ระบบจะเพิ่ม traefik-dynamic.yaml และ proxy.env เฉพาะเมื่อคุณเปิดใช้งาน NetBird Proxy เท่านั้น ให้ถือว่าไดเรกทอรีนี้เป็นสถานะของระบบที่ต้องเก็บรักษาไว้ เพราะ config.yaml เก็บกุญแจที่ใช้เข้ารหัสข้อมูลใน store หากทำหาย การติดตั้งใหม่ก็ไม่สามารถแก้ไขได้

docker compose ps
docker compose logs -f netbird-server

ทุก service ควรสามารถอ่าน running ได้ และ log ของ server ควรจะนิ่ง ไม่ใช่การรีสตาร์ทวนซ้ำ ให้ตรวจสอบใบรับรองแยกต่างหาก:

docker compose logs traefik | grep -i acme

ACME (automatic certificate management environment) คือโปรโตคอลที่ Traefik ใช้เพื่อขอใบรับรอง ข้อผิดพลาดที่เกิดขึ้นในส่วนนี้มักเกิดจากปัญหา DNS หรือการไม่ได้เปิดพอร์ต 443

สร้างบัญชีผู้ดูแลระบบบัญชีแรก

เปิด https://netbird.example.com ในการติดตั้งใหม่ หน้าเว็บจะแสดงหน้าตั้งค่าแทนที่จะเป็นแบบฟอร์มเข้าสู่ระบบ ให้กรอกที่อยู่อีเมล ชื่อ และรหัสผ่าน จากนั้นคลิก Create Account บัญชีนี้จะกลายเป็นผู้ดูแลระบบคนแรก และหน้าเว็บจะเปลี่ยนเส้นทางไปยังแบบฟอร์มเข้าสู่ระบบ

บัญชีดังกล่าวจะถูกเก็บไว้ในที่เก็บข้อมูลผู้ใช้ของ NetBird เอง ซึ่งขับเคลื่อนโดย identity provider ที่ฝังอยู่ในคอนเทนเนอร์ netbird-server โดยไม่ต้องพึ่งพาระบบภายนอก นี่คือการเปลี่ยนแปลงครั้งใหญ่ที่สุดจาก NetBird เวอร์ชัน self-hosted เมื่อปีก่อน ซึ่งการติดตั้งให้ใช้งานได้จำเป็นต้องตั้งค่า Zitadel หรือ Keycloak ก่อน และต้องคัดลอกค่า OIDC (OpenID Connect) จำนวน 4 ค่าลงใน setup.env ก่อนที่ระบบจะเริ่มทำงานได้

หากคุณพบคำเตือนเรื่องใบรับรองความปลอดภัยของเบราว์เซอร์แทนที่จะเป็นหน้าตั้งค่า แสดงว่าใบรับรองไม่ได้ถูกออกให้สำเร็จ ให้แก้ไขปัญหานี้ก่อนดำเนินการต่อ เนื่องจากแดชบอร์ดต้องสื่อสารกับ API ผ่านชื่อโฮสต์เดียวกัน และจะเกิดข้อผิดพลาดที่ตรวจสอบได้ยากหากใบรับรองไม่ถูกต้อง

เชื่อมต่อ peer เครื่องแรกของคุณ

ติดตั้ง client บนเครื่อง Linux ใดก็ได้ รวมถึงตัว VPS เองหากคุณต้องการให้มันอยู่ใน mesh:

curl -fsSL https://pkgs.netbird.io/install.sh | sh

บน Debian และ Ubuntu สคริปต์ดังกล่าวจะตั้งค่า package repository ของ NetBird จากนั้นจึงติดตั้ง client ผ่าน apt ทำให้ package manager เป็นผู้ดูแลแพ็กเกจนั้นโดยสมบูรณ์ หากคุณไม่ต้องการรันสคริปต์ผ่าน pipe ให้บันทึกไฟล์ไว้ก่อนด้วย curl -fsSL -o install.sh https://pkgs.netbird.io/install.sh และตรวจสอบเนื้อหาก่อนรันด้วย sh install.sh ไม่ว่าจะใช้วิธีใด ให้ตรวจสอบสิ่งที่ติดตั้งลงไป:

apt-cache policy netbird

netbird คือ command line client และ daemon ส่วน netbird-ui คือแอปพลิเคชันบน desktop tray ซึ่งเซิร์ฟเวอร์แบบ headless ไม่จำเป็นต้องใช้งาน

จากนั้นระบุตำแหน่งเซิร์ฟเวอร์ให้ client ทราบ:

sudo netbird up --management-url https://netbird.example.com

หากละเว้น --management-url ไว้ client จะลงทะเบียนกับบริการ hosted ของ NetBird เนื่องจากเป็นค่าเริ่มต้นที่ถูกคอมไพล์มาในตัว คำสั่งจะยังคงทำงานสำเร็จ เครื่องจะได้รับ IP address แต่ dashboard ที่คุณโฮสต์เองจะยังคงว่างเปล่า นี่เป็นจุดที่ผู้ใช้งานส่วนใหญ่พลาดเป็นครั้งแรก

คำสั่งจะแสดง URL เพื่อให้คุณเปิดในเบราว์เซอร์เพื่อดำเนินการล็อกอินให้เสร็จสิ้น หลังจากนั้น:

netbird status
ip addr show wt0

อ่านข้อมูลสี่บรรทัดจาก netbird status: Management: Connected, Signal: Connected, บรรทัด Relays: ที่รายงาน relay ทั้งหมดที่มี และ NetBird IP: ในช่วง overlay range ส่วน wt0 คืออินเทอร์เฟซ WireGuard ที่ NetBird สร้างขึ้น ซึ่งควรจะมี IP address เดียวกันนี้ปรากฏอยู่

การเชื่อมต่อเครื่องที่สองแบบไม่ต้องเฝ้าหน้าจอด้วย setup key

การล็อกอินผ่านเบราว์เซอร์ไม่สามารถทำได้กับเครื่องที่ไม่มีเบราว์เซอร์และไม่มีผู้ใช้งานอยู่หน้าเครื่อง setup key คือโทเค็นสำหรับการยืนยันตัวตนล่วงหน้า ซึ่งช่วยให้ลงทะเบียนเครื่องได้โดยไม่ต้องผ่านขั้นตอนโต้ตอบ คุณสามารถสร้างคีย์นี้ได้ในแดชบอร์ดภายใต้หัวข้อ Setup Keys

คีย์มีอยู่สองประเภท ประเภทใช้ครั้งเดียว (one-off key) จะยืนยันตัวตนได้เพียงหนึ่งเครื่องเท่านั้นแล้วจะถูกยกเลิกไป ส่วนประเภทใช้ซ้ำได้ (reusable key) สามารถลงทะเบียนได้หลายเครื่อง โดยสามารถกำหนดจำนวนสูงสุดได้ ทั้งสองประเภทต้องกำหนดวันหมดอายุ และสามารถกำหนดให้ peer ใหม่เข้ากลุ่มโดยอัตโนมัติ เพื่อให้กฎการเข้าถึงของกลุ่มนั้นมีผลทันทีที่เครื่องปรากฏในระบบ

sudo netbird up --setup-key <SETUP-KEY> \
  --management-url https://netbird.example.com \
  --hostname build-runner-01

--hostname ใช้สำหรับกำหนดชื่อที่จะแสดงในแดชบอร์ด หากไม่กำหนดค่านี้ peer จะใช้ชื่อตามที่เครื่องเรียกตัวเอง ซึ่งการมีรายการจำนวนมากที่ชื่อ ubuntu จะไม่เป็นประโยชน์ต่อการจัดการ

สำหรับคอนเทนเนอร์และ build agent ที่มีอายุการใช้งานสั้น ให้ทำเครื่องหมายคีย์ว่าเป็น ephemeral ในขณะที่สร้าง คีย์ประเภท ephemeral จะทำให้ peer ที่ลงทะเบียนถูกลบออกจากระบบโดยอัตโนมัติเมื่อออฟไลน์นานเกิน 10 นาที ซึ่งช่วยป้องกันไม่ให้มีรายการที่ไม่ได้ใช้งานค้างอยู่ในรายการ peer

ข้อจำกัดประการหนึ่งที่ควรทราบก่อนวางแผนใช้งาน setup key คือ การหมดอายุหรือการเพิกถอนคีย์จะหยุดการลงทะเบียนใหม่เท่านั้น แต่จะไม่ตัดการเชื่อมต่อเครื่องที่ลงทะเบียนไปแล้ว หากต้องการยกเลิกการเข้าถึงของเครื่องใดเครื่องหนึ่ง คุณต้องลบ peer นั้นออกโดยตรง

คุณยังจำเป็นต้องมี Identity Provider แยกต่างหากหรือไม่?

สำหรับการติดตั้งขนาดเล็ก คำตอบคือไม่จำเป็น ระบบจัดเก็บผู้ใช้ในตัวสามารถจัดการบัญชีที่สร้างจากแดชบอร์ดได้ ซึ่งเพียงพอสำหรับผู้ใช้งานจำนวนไม่กี่คน

คุณควรใช้ Identity Provider ภายนอกเมื่อคุณมีระบบดังกล่าวอยู่แล้วและไม่ต้องการจัดการรายชื่อผู้ใช้ซ้ำซ้อน NetBird รองรับ Provider ทุกรายที่ใช้โปรโตคอล OIDC ให้คุณลงทะเบียน confidential OIDC client ใน Provider ของคุณ จากนั้นเพิ่มข้อมูลลงในแดชบอร์ดของ NetBird โดยใช้ค่า 4 รายการ ได้แก่ name, client ID, client secret และ issuer โดย NetBird จะให้ redirect URL เพื่อนำไปกรอกกลับใน Provider ของคุณ ทั้งนี้มีระบบเชื่อมต่อสำเร็จรูปสำหรับ Google, Microsoft Entra ID, Okta, Zitadel, Keycloak, Authentik และ Pocket ID ส่วนบริการอื่นๆ สามารถตั้งค่าเป็น generic OIDC ได้ หากคุณใช้งาน Authentik เป็นระบบ single sign-on แบบ self-hosted อยู่แล้ว นี่คือวิธีที่จะช่วยให้คุณรักษาฐานข้อมูลผู้ใช้ไว้เพียงชุดเดียวแทนที่จะเป็นสองชุด

การล็อกอินแบบ local จะยังคงใช้งานได้หลังจากที่คุณเพิ่ม Provider เข้าไป และ Provider ทุกตัวที่ตั้งค่าไว้จะปรากฏบนหน้าล็อกอิน โปรดรักษาบัญชีผู้ดูแลระบบแบบ local ไว้หนึ่งบัญชีโดยใช้รหัสผ่านที่คาดเดายาก เพื่อให้คุณยังมีช่องทางเข้าถึงระบบได้ในกรณีที่การตั้งค่า OIDC เกิดข้อผิดพลาด

NetBird หรือ Headscale: คุณควรเลือกใช้ control plane ตัวไหน?

ทั้งสองตัวช่วยลดการพึ่งพาบริการภายนอกเหมือนกัน นั่นคือ control server แบบ hosted ที่ไคลเอนต์ของคุณต้องเชื่อมต่อไปหา แต่ทั้งสองโครงการมีลักษณะการทำงานที่แตกต่างกัน

Headscale เป็นการสร้าง control server ของ Tailscale ขึ้นมาใหม่ โดยที่คุณยังคงใช้ไคลเอนต์อย่างเป็นทางการของ Tailscale ต่อไป โครงการนี้ไม่มี web console อย่างเป็นทางการ คุณต้องจัดการผู้ใช้และ pre-authentication keys ผ่านคำสั่ง headscale โดยอ้างอิงกับไฟล์คอนฟิก แม้จะมี web interface ที่พัฒนาโดยชุมชนให้เลือกใช้ แต่สิ่งเหล่านั้นไม่ได้เป็นส่วนหนึ่งของตัวโครงการหลัก วิธีนี้เหมาะสำหรับผู้ที่ต้องการเก็บสถานะไว้ในไฟล์และจัดการการเปลี่ยนแปลงผ่านระบบ version control

NetBird มาพร้อมกับผลิตภัณฑ์ที่ครบวงจร ทั้งไคลเอนต์ของตัวเอง, แดชบอร์ด, identity provider ในตัว และนโยบายการเข้าถึงที่แก้ไขได้ผ่านเบราว์เซอร์ ซึ่งหมายความว่าจะมีส่วนประกอบที่ต้องดูแลบน VPS ของคุณมากขึ้น แต่ก็ช่วยลดภาระงานได้อย่างมากหากต้องส่งต่อให้เพื่อนร่วมงานที่ไม่ต้องการใช้งานผ่าน terminal

เลือกใช้ Headscale หากคุณใช้งานไคลเอนต์ของ Tailscale อยู่แล้ว หรือต้องการ control plane ที่มีขนาดเล็กที่สุดเท่าที่จะเป็นไปได้ เลือกใช้ NetBird หากมีหลายคนจำเป็นต้องจัดการ peer และคุณต้องการคอนโซลรวมถึงระบบ SSO โดยไม่ต้องประกอบระบบขึ้นมาเอง ก่อนที่คุณจะตัดสินใจเลือกตัวใดตัวหนึ่ง โปรดตรวจสอบ สิ่งที่แผนบริการฟรีของ Tailscale ครอบคลุมจริง เพราะกลุ่มที่ไม่แสวงหาผลกำไรที่มีผู้ใช้ไม่เกินหกคนสามารถใช้ hosted control plane ได้ฟรี โดยเริ่มต้นที่อุปกรณ์ของผู้ใช้ไม่จำกัดจำนวนและทรัพยากรที่ติดแท็กได้ 50 รายการ ซึ่งอาจทำให้คุณไม่มีความจำเป็นต้องติดตั้งระบบเองเลย แต่หากเกินขีดจำกัดดังกล่าว ค่าใช้จ่ายจะเพิ่มขึ้นตามจำนวนคนมากกว่าจำนวนเครื่อง ดังนั้นการ คำนวณค่าใช้จ่ายที่ Tailscale จะเรียกเก็บจากกลุ่มของคุณ จะช่วยให้คุณได้ตัวเลขเพื่อนำไปเปรียบเทียบกับค่า VPS และเวลาที่คุณต้องเสียไปกับการดูแล stack นี้ด้วยตัวเอง

VPS ขนาดเล็กที่สุดที่สามารถรันระบบนี้ได้คือเท่าใด

ข้อกำหนดขั้นต่ำที่ระบุไว้คือ CPU 1 คอร์ และหน่วยความจำ 2 GB บันทึกของ NetBird ระบุว่าปัจจุบันสามารถรันได้ที่ RAM ประมาณ 1 GB เนื่องจากมีการจัดการผู้ใช้งานแบบ local แล้ว เมื่อเทียบกับความต้องการเดิมที่ 2 GB ถึง 4 GB ในสมัยที่ต้องติดตั้ง Zitadel ทั้งชุดรวมอยู่ใน stack แนะนำให้ซื้อขนาด 2 GB เพราะพื้นที่หน่วยความจำที่เหลือจะช่วยให้สามารถดึง image ใหม่ระหว่างการอัปเกรดได้ในขณะที่ image เก่ายังคงอยู่ในดิสก์

มี 3 สิ่งที่สามารถตัดออกได้หากใช้เครื่องขนาดเล็ก: ให้ปฏิเสธการติดตั้งบริการ NetBird Proxy ซึ่งทำหน้าที่เผยแพร่บริการภายในออกสู่ชื่อโฮสต์สาธารณะและไม่มีผลต่อการเชื่อมต่อระหว่าง peer ให้ข้ามการติดตั้ง CrowdSec ซึ่งสคริปต์จะเสนอให้ติดตั้งพร้อมกับ proxy เท่านั้น และเป็นสิ่งที่ควรเพิ่มในภายหลังสำหรับเครื่องที่เปิดรับการเชื่อมต่อจากภายนอกมากกว่าที่จะติดตั้งตั้งแต่วันแรก ให้ใช้ SQLite store แบบค่าเริ่มต้นใน volume netbird_data และย้ายไปใช้ PostgreSQL เฉพาะเมื่อคุณแยกการติดตั้งออกเป็นหลายเครื่องหรือเมื่อมีปริมาณการใช้งานพร้อมกันสูงจริง ซึ่งมีการระบุไว้ว่าเป็นขั้นตอนการย้ายข้อมูลที่สามารถทำได้ในภายหลัง

ส่วนประกอบที่คุณไม่สามารถตัดออกได้คือ relay เนื่องจาก peer สองเครื่องที่ NAT กำหนดพอร์ตต่างกันสำหรับทุกปลายทางจะไม่สามารถสร้าง tunnel โดยตรงได้ relay จึงเป็นเส้นทางเดียวที่ทำให้เชื่อมต่อกันได้ การปิดใช้งาน relay ช่วยประหยัดหน่วยความจำได้เพียงเล็กน้อยแต่จะทำให้การเชื่อมต่อล้มเหลวในลักษณะที่ตรวจสอบสาเหตุได้ยาก

เมื่อเครื่องเดียวเริ่มไม่เพียงพอ relay คือสิ่งแรกที่ควรย้ายออกไปรันแยกต่างหาก relay แบบ standalone สามารถรันได้ด้วย NB_LISTEN_ADDRESS, NB_EXPOSED_ADDRESS, NB_AUTH_SECRET และ NB_ENABLE_STUN โดย shared secret จะต้องตรงกันทั้งบน relay และบนเซิร์ฟเวอร์หลัก มิฉะนั้นไคลเอนต์จะไม่สามารถยืนยันตัวตนกับ relay ได้

รูปแบบความล้มเหลวและสิ่งที่คุณจะพบ

แดชบอร์ดแสดงคำเตือนเกี่ยวกับใบรับรอง Traefik ไม่สามารถออกใบรับรองได้ ให้รัน docker compose logs traefik | grep -i acme สาเหตุมีสองประการ ประการแรกคือ dig +short netbird.example.com ยังไม่ชี้มาที่ VPS นี้ หรือประการที่สองคือพอร์ต TCP 443 ถูกปิดกั้นไว้ที่จุดใดจุดหนึ่งระหว่าง Let's Encrypt กับคอนเทนเนอร์ ซึ่งมักเกิดจากไฟร์วอลล์เครือข่ายของผู้ให้บริการมากกว่าที่จะเป็นที่ ufw การตรวจสอบความถูกต้อง (challenge) จะทำผ่านพอร์ต 443 ดังนั้นการเปิดพอร์ต 80 จึงไม่ช่วยในกรณีนี้ โปรดแก้ไขสาเหตุให้เรียบร้อยก่อนจะลองใหม่ซ้ำๆ เพราะ Let's Encrypt อนุญาตให้ตรวจสอบความถูกต้องล้มเหลวได้เพียง 5 ครั้งต่อชื่อโฮสต์ต่อชั่วโมง และการลองซ้ำจะทำให้คุณถูกระงับการขอใบรับรองจนกว่าโควตาจะรีเซ็ต

ไคลเอนต์แจ้งว่าเชื่อมต่อแล้วแต่แดชบอร์ดว่างเปล่า ไคลเอนต์ได้ลงทะเบียนกับบริการโฮสต์ของ NetBird เนื่องจาก --management-url หายไป ให้รัน netbird status --detail และอ่านบรรทัด Management: ซึ่งจะระบุชื่อเซิร์ฟเวอร์ที่ไคลเอนต์กำลังติดต่ออยู่จริง หากเห็น Management: Connected to https://api.netbird.io:443 แสดงว่าไคลเอนต์เชื่อมต่อไปยังระบบคลาวด์ ให้รัน sudo netbird down แล้วตามด้วย sudo netbird up --management-url https://netbird.example.com อีกครั้ง

เพียร์ทุกตัวแสดงสถานะ Connection type: Relayed ไม่มีการสร้างอุโมงค์เชื่อมต่อโดยตรง ทำให้ทราฟฟิกทั้งหมดต้องวิ่งผ่าน VPS ของคุณและเพิ่มความหน่วง (latency) อีกหนึ่งฮอป ให้ตรวจสอบพอร์ต UDP 3478 บนไฟร์วอลล์ของ VPS และไฟร์วอลล์ของผู้ให้บริการ เนื่องจาก STUN คือสิ่งที่ช่วยให้เพียร์ทราบที่อยู่ IP สาธารณะและพอร์ตของตนเอง นอกจากนี้ netbird status --detail ยังแสดง Direct: false และประเภทของ ICE (interactive connectivity establishment) candidate สำหรับเพียร์แต่ละตัว ซึ่งจะแสดงให้เห็นว่ากระบวนการเชื่อมต่อดำเนินไปถึงขั้นใด ในบางเครือข่าย การเชื่อมต่อแบบ relayed อาจเป็นผลลัพธ์เดียวที่เป็นไปได้และไม่ได้หมายความว่ามีสิ่งใดผิดปกติ

เพียร์เข้าร่วมเครือข่ายแล้วแต่ไม่สามารถเข้าถึงสิ่งใดได้ การอยู่ใน mesh ไม่ได้หมายความว่าเพียร์สองตัวจะคุยกันได้เสมอไป นโยบายการเข้าถึง (access policies) เป็นตัวกำหนดเรื่องนี้ และกลุ่มที่ไม่มีนโยบายกำกับไว้จะไม่สามารถเข้าถึงสิ่งใดได้เลย ให้ตรวจสอบนโยบายในแดชบอร์ดก่อนที่คุณจะเริ่มแก้ไขปัญหาเส้นทาง (routes) และไฟร์วอลล์

netbird status รายงานปัญหาเกี่ยวกับ daemon บริการไม่ได้ทำงานอยู่ ให้ใช้ sudo netbird service status และ sudo netbird service start เพื่อตรวจสอบ โดย log ของไคลเอนต์จะอยู่ที่ /var/log/netbird/client.log สำหรับปัญหาใดๆ ที่คุณระบุสาเหตุไม่ได้ netbird debug bundle --anonymize --system-info จะรวบรวม log, สถานะ, เส้นทาง, การตั้งค่า DNS และสถานะไฟร์วอลล์ไว้ในไฟล์เก็บถาวรไฟล์เดียว

การสำรองข้อมูลและการอัปเกรด

มีสองส่วนสำคัญที่ครอบคลุมการติดตั้งทั้งหมด ได้แก่ ไดเรกทอรีที่เก็บ docker-compose.yml และ config.yaml รวมถึง Docker volume ที่เก็บฐานข้อมูลและคีย์เข้ารหัสลับ ให้สำรองข้อมูลทั้งสองส่วนนี้พร้อมกัน 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 -d

Compose จะเติมชื่อโปรเจกต์นำหน้าชื่อ volume ดังนั้น volume ที่ระบุไว้ใน netbird_data มักจะปรากฏในชื่อ netbird_netbird_data ให้รันคำสั่ง docker volume ls ก่อนแล้วใช้ชื่อที่แสดงผลออกมา มิฉะนั้นคำสั่ง docker run ด้านบนจะล้มเหลวโดยการสร้าง volume เปล่าขึ้นมาเงียบๆ และไม่ได้สำรองข้อมูลใดๆ เลย ควรเก็บไฟล์สำรองไว้นอก VPS หากคุณมีเครื่องมือสำรองข้อมูลอยู่แล้ว restic หรือ BorgBackup สามารถจัดการส่วนการสำรองข้อมูลนอกสถานที่ได้

การอัปเกรดเซิร์ฟเวอร์ทำได้โดยการดึงอิมเมจใหม่และสร้างคอนเทนเนอร์ขึ้นมาใหม่:

docker compose pull
docker compose up -d
docker compose ps

ก่อนที่คุณจะดำเนินการดังกล่าว ให้รันคำสั่ง docker compose config | grep image: เสียก่อน แท็กใดก็ตามที่ระบุว่าเป็น latest ควรถูกล็อกเวอร์ชันไว้ (pin) ด้วยเหตุผลเดียวกับที่คุณล็อกเวอร์ชันของสคริปต์ติดตั้ง นั่นคือเพื่อให้คุณทราบว่าซอฟต์แวร์เวอร์ชันใดกำลังทำงานอยู่ และเพื่อให้มีเวอร์ชันที่สามารถย้อนกลับไปได้หากการอัปเกรดเกิดปัญหา ส่วนไคลเอนต์จะอัปเกรดผ่านตัวจัดการแพ็กเกจที่ใช้ติดตั้งโปรแกรมนั้นๆ

FAQ

ฉันจำเป็นต้องมี Identity Provider ของตัวเองเพื่อ self-host NetBird หรือไม่?

ไม่จำเป็น รุ่นปัจจุบันมีระบบจัดเก็บผู้ใช้ในตัว คุณสามารถสร้างบัญชีผู้ดูแลระบบบัญชีแรกผ่านเบราว์เซอร์ได้ที่ https://netbird.example.com และเพิ่มผู้ใช้รายอื่นจากแดชบอร์ดในภายหลัง การใช้ OIDC provider ภายนอกเป็นทางเลือกเสริมและสามารถเพิ่มได้ในภายหลังโดยใช้ค่า 4 รายการ ได้แก่ ชื่อ, client ID, client secret และ issuer คู่มือที่แนะนำให้คุณติดตั้ง Zitadel หรือ Keycloak ก่อน NetBird เป็นการตั้งค่าที่ไม่จำเป็นแล้วในปัจจุบัน และการทำตามคู่มือเหล่านั้นจะทำให้คุณต้องดูแลบริการเพิ่มขึ้นอีกหนึ่งรายการโดยไม่จำเป็น

ทำไม peer ทั้งหมดของฉันถึงแสดงสถานะเป็น Connection type: Relayed?

การเชื่อมต่อโดยตรงไม่สามารถทำได้ ข้อมูลจึงต้องวิ่งผ่าน relay บน VPS ของคุณ สาเหตุทั่วไปคือพอร์ต UDP 3478 ถูกบล็อก ซึ่งเป็นพอร์ต STUN ที่ peer ใช้สำหรับค้นหาที่อยู่ public IP และพอร์ตของตนเอง ให้เปิดพอร์ตนี้บน firewall ของ VPS และบน network firewall ของผู้ให้บริการ จากนั้นรันคำสั่ง netbird status --detail อีกครั้งและตรวจสอบบรรทัด Direct: หากเครือข่ายที่คุณใช้งานมี NAT ที่กำหนดพอร์ตแยกต่างหากสำหรับแต่ละปลายทาง การเชื่อมต่อผ่าน relay จะเป็นผลลัพธ์เดียวที่เป็นไปได้และไม่ได้มีการตั้งค่าผิดพลาดแต่อย่างใด

Client เชื่อมต่อแล้วแต่แดชบอร์ดไม่แสดง peer เกิดอะไรขึ้น?

Client ลงทะเบียนกับบริการ hosted ของ NetBird แทนที่จะเป็นเซิร์ฟเวอร์ของคุณ ซึ่งเป็นสิ่งที่เกิดขึ้นเมื่อไม่ได้ระบุค่า --management-url คำสั่ง netbird status --detail จะแสดงเซิร์ฟเวอร์ที่กำลังติดต่ออยู่บนบรรทัด Management: ดังนั้นค่าอย่างเช่น https://api.netbird.io:443 จึงเป็นการยืนยันว่าเชื่อมต่อผิดที่ ให้รันคำสั่ง sudo netbird down ตามด้วย sudo netbird up --management-url https://netbird.example.com แล้ว peer จะปรากฏในแดชบอร์ดของคุณ

NetBird แบบ self-hosted แตกต่างจาก Headscale อย่างไร?

ทั้งสองอย่างทำหน้าที่แทน control server แบบ hosted ด้วยเซิร์ฟเวอร์ที่คุณดูแลเอง Headscale เป็นเพียง control plane เท่านั้น คุณต้องจัดการผ่านคำสั่ง headscale และไฟล์ config โดยไม่มีเว็บคอนโซลอย่างเป็นทางการ และใช้ร่วมกับ client ของ Tailscale ส่วน NetBird มาพร้อมกับ client, แดชบอร์ดสำหรับผู้ดูแลระบบ และการเชื่อมต่อกับ identity provider ในชุดเดียวกัน Headscale ใช้ทรัพยากรน้อยกว่าและเก็บสถานะไว้ในไฟล์ ส่วน NetBird ใช้งานง่ายกว่าสำหรับผู้ที่ไม่ต้องการใช้ terminal

เซิร์ฟเวอร์ VPS ขนาดเท่าใดที่จำเป็นสำหรับ NetBird แบบ self-hosted?

ข้อกำหนดขั้นต่ำที่ระบุไว้คือ CPU 1 คอร์ และ RAM 2 GB ซึ่ง 2 GB คือขนาดที่ควรเลือกซื้อ ปัจจุบันความต้องการใช้งานจริงลดลงเหลือประมาณ 1 GB ในรุ่นล่าสุดเนื่องจาก identity provider ถูกรวมไว้ในตัวแทนที่จะต้องติดตั้งแยกต่างหาก คุณสามารถเลือกไม่ติดตั้งบริการ proxy เสริมระหว่างการติดตั้ง ซึ่งจะข้ามขั้นตอนของ CrowdSec ไปด้วย และควรใช้ SQLite ที่เป็นค่าเริ่มต้นไปก่อนจนกว่าคุณจะมีความจำเป็นต้องใช้ PostgreSQL จริงๆ