הקמת שרת Headscale עצמאי: מדריך מלא לניהול Tailscale
למדו כיצד להריץ שרת בקרה עצמאי עבור Tailscale על גבי VPS. המדריך מפרט התקנה מתוך חבילת .deb, הגדרת server_url נכונה לפני הפעלת השירות וחיבור הצומת הראשון לרשת הפרטית שלכם.
מהו Headscale
Headscale הוא מימוש בניהול עצמי של שרת הבקרה של Tailscale, כך שהמכונה שמתאמת את הרשת הפרטית שלכם היא שרת VPS שבבעלותכם. זהו פרויקט קהילתי שאינו מופעל על ידי Tailscale Inc. כל מכונה עדיין מריצה את הלקוח הרשמי tailscale, המופנה לשרת שלכם באמצעות דגל אחד, --login-server.
שרת הבקרה הוא הרכיב שמכיר את המשתמשים השייכים לרשת. הוא מקצה לכל צומת כתובת מתוך 100.64.0.0/10, מפיץ מפתחות ציבוריים, ומנחה את הצמתים היכן למצוא זה את זה. המנהרות נשארות מבוססות WireGuard, ונבנות ישירות בין צומת לצומת. תעבורה בין שתי מכונות שלכם אינה עוברת דרך השרת שמריץ את Headscale, אלא אם לא ניתן ליצור נתיב ישיר והצמתים נאלצים להשתמש ב־relay. הרצת תפקיד התיאום בעצמכם משנה את הגורם שמחזיק בו, ולא את היכולות שלו; לכן כדאי להבין מה שרת בקרה יכול ומה הוא לא יכול להשיג במודל זה לפני שמתייחסים למעבר כאל יתרון אבטחה מובן מאליו.
Headscale משרת tailnet אחד (רשת Tailscale אחת) לכל מופע, מה שהפרויקט מגדיר כמתאים לשימוש אישי או לארגון קטן. עם שלוש או ארבע מכונות, VPN מבוסס WireGuard פשוט על VPS שבבעלותכם דורש הרצת פחות תוכנה ופחות רכיבים שעלולים להתקלקל. Headscale הופך למשתלם כאשר אינכם רוצים לכתוב בלוק [Peer] ידנית עבור כל מחשב נייד חדש. עלות היא לרוב הגורם שמניע אנשים לחפש פתרון מלכתחילה, לכן כדאי לקרוא מה התוכנית החינמית המנוהלת באמת כוללת לפני שאתם מקימים שרת, שכן מספר קטן של מכונות אישיות בדרך כלל נכנס תחתיה. אם כבר עברתם את התקרה הזו, בצעו חישוב מול עלות התוכניות בתשלום, המחושבת לפי משתמש ולא לפי מכשיר, כיוון שמשק בית תחת חשבון אחד יכול להישאר זול זמן רב לאחר שמספר המכשירים מפסיק להיות רלוונטי. אם אתם מעוניינים במישור בקרה בניהול עצמי אך מעדיפים לקוח משלכם וממשק אינטרנטי לניהול עמיתים במקום תחליף ישיר לזה של Tailscale, NetBird על גבי VPS יחיד היא החלופה שכדאי לשקול. להשוואה רחבה יותר בין שני המודלים, ראו במה שונים WireGuard ו־Tailscale.
דרישות קדם להתקנה
- שרת VPS המריץ Ubuntu 24.04 עם כתובת IPv4 ציבורית והרשאות sudo. אם השרת חדש, בצעו תחילה את עשר הדקות הראשונות בשרת VPS חדש.
- רשומת DNS מסוג A המצביעה לכתובת זו. מדריך זה משתמש ב-
headscale.example.com. - דומיין או סאב-דומיין נוסף עבור MagicDNS. מדריך זה משתמש ב-
tailnet.example.net. הוא חייב להיות שונה מהדומיין המשמש ב-server_url. - מכונת לקוח אחת לחיבור, המריצה Linux, macOS, Windows, Android או iOS.
התקנת headscale מחבילת .deb רשמית
הפרויקט מפרסם חבילות .deb בדף ה-releases ב-GitHub. נכון ליולי 2026, הגרסה העדכנית היא 0.29.3. בדקו תחילה את הארכיטקטורה שלכם, שכן היא מופיעה בשם הקובץ.
sudo apt update
sudo apt install -y wget
dpkg --print-architectureפקודה זו מדפיסה amd64 בשרת VPS רגיל מבוסס x86, ו-arm64 בתוכניות מסוג Ampere או Graviton. הציבו את התוצאה במשתנה להלן.
HEADSCALE_VERSION="0.29.3"
HEADSCALE_ARCH="amd64"
wget --output-document=headscale.deb \\
"https://github.com/juanfont/headscale/releases/download/v${HEADSCALE_VERSION}/headscale_${HEADSCALE_VERSION}_linux_${HEADSCALE_ARCH}.deb"
sudo apt install -y ./headscale.deb
headscale versionהתו ./ לפני שם הקובץ הוא הכרחי. בלעדיו, apt יחפש חבילה בשם headscale.deb במאגרים שלכם וייכשל.
החבילה יוצרת משתמש מערכת בשם headscale, כותבת קובץ /etc/headscale/config.yaml כברירת מחדל, ומתקינה יחידת systemd. היא אינה מפעילה את השירות, וזהו סדר הפעולות התקין. התצורה שמגיעה עם החבילה מצביעה ב-server_url על http://127.0.0.1:8080, שאינה כתובת שניתן להגיע אליה מאף לקוח שלכם, לכן שירות שיופעל כעת יהיה שגוי גם אם יעלה. הרצת sudo systemctl is-active headscale בשלב זה תדפיס inactive. זהו מצב צפוי, ולא תקלה.
הגדרת server_url לפני הפעלת השירות
ערכו את /etc/headscale/config.yaml באמצעות sudo nano /etc/headscale/config.yaml, או החילו את שלושת השינויים הבאים באמצעות sed. שמרו עותק של הקובץ המקורי, שכן הוא ארוך, עמוס בהערות ומהווה את המקור הטוב ביותר לשאר ההגדרות.
sudo cp /etc/headscale/config.yaml /etc/headscale/config.yaml.orig
sudo sed -i 's|^server_url:.*|server_url: https://headscale.example.com|' /etc/headscale/config.yaml
sudo sed -i 's|^listen_addr:.*|listen_addr: 127.0.0.1:8080|' /etc/headscale/config.yaml
sudo sed -i 's|^ base_domain:.*| base_domain: tailnet.example.net|' /etc/headscale/config.yaml
sudo grep -E '^(server_url|listen_addr):|^ base_domain:' /etc/headscale/config.yamlserver_url הוא הכתובת ש-headscale כותב לתוך כל רישום של לקוח. לקוחות יתחברו למחרוזת זו באופן קבוע לאחר מכן, לכן עליה להיות שם המתחם הציבורי עם https:// בתחילתו, ולעולם לא 127.0.0.1.
listen_addr הוא המקום שבו התהליך מאזין. השאירו אותו על loopback. שרת reverse proxy על אותו שרת מבצע TLS termination ומעביר את התעבורה אליו, כך שאין צורך ששום גורם מחוץ לשרת יגיע לפורט 8080.
base_domain הוא הסיומת של MagicDNS, המתחם שתחתיו יקבלו הצמתים שלכם שמות. עליו להיות שם מתחם מלא (FQDN) ללא נקודה בסופו, ועליו להיות מתחם שונה מזה שב-server_url, שכן אחרת מרחבי השמות יתנגשו.
השאירו את סעיף מסד הנתונים כפי שהוא. ברירת המחדל היא SQLite ב-/var/lib/headscale/db.sqlite, בתוך תיקייה שהחבילה יצרה ושייכת לה, ו-SQLite מספיק עבור tailnet בגודל זה.
הפעלת headscale ואימות פעילותו
sudo systemctl enable --now headscale
sudo systemctl is-active headscale
curl -sS -o /dev/null -w '%{http_code}\\n' http://127.0.0.1:8080/healthהפקודה is-active מדפיסה active, והפקודה curl מדפיסה 200. הפקודה enable --now מבצעת את שני חלקי המשימה: היא מפעילה את השירות ומסמנת אותו להפעלה אוטומטית לאחר אתחול המערכת.
אם is-active מדפיסה failed, קראו את הלוגים באמצעות sudo journalctl -u headscale -n 50 --no-pager. כשל בשלב זה נובע כמעט תמיד מקובץ התצורה, כיוון ש-headscale מנתח את כל הקובץ לפני פתיחת ה-socket. לכן, הזחה שגויה או מפתח לא מוכר יעצרו את התהליך עוד לפני שהשירות יתחיל להאזין. תקנו את הקובץ ולאחר מכן הריצו sudo systemctl restart headscale. כל שינוי תצורה עתידי יחייב ביצוע פעולת restart דומה. הלקוחות יתחברו מחדש באופן עצמאי לאחר מכן. אם יחידות systemd הן נושא חדש עבורכם, המדריך הרצת שירותים וטיימרים עצמאיים עם systemd מכסה את הפקודות שבהן נעשה שימוש כאן.
בדקו את קובצי המצב בזמן שאתם ב-shell:
stat -c '%U %n' /var/lib/headscale/db.sqlite /var/lib/headscale/noise_private.keyשתי השורות מתחילות ב-headscale, המשתמש חסר ההרשאות המיוחדות שנוצר על ידי החבילה. הקובץ noise_private.key הוא הזהות של השרת מול הלקוחות שלו. שמרו עליו. אם תמחקו אותו, headscale ייצור זהות חדשה וכל צומת יצטרך לבצע רישום מחדש.
הצבת TLS לפני headscale
לקוחות חייבים להגיע אל server_url באמצעות HTTPS. השימוש ב-Caddy הוא הדרך המהירה ביותר, כיוון שהוא מבקש ומחדש את התעודה באופן עצמאי.
sudo apt install -y caddyהחליפו את /etc/caddy/Caddyfile בבלוק מתוך התיעוד של headscale:
headscale.example.com {
reverse_proxy 127.0.0.1:8080 {
header_up True-Client-IP {remote_host}
header_up X-Real-IP {remote_host}
}
}sudo caddy validate --adapter caddyfile --config /etc/caddy/Caddyfile
sudo systemctl restart caddy
sudo systemctl is-active caddyהפקודה validate תציג adapted config to JSON כאשר הקובץ עובר ניתוח (parse) בהצלחה. אזהרה על כך שהקובץ אינו מעוצב היא קוסמטית בלבד. מהמחשב הנייד שלכם, curl -sS -o /dev/null -w '%{http_code}\\n' https://headscale.example.com/health אמורה גם היא להציג 200. בדיקה בודדת זו מוכיחה כי ה-DNS, ה-firewall, התעודה וה-proxy פועלים כולם יחד.
להלן פרט טכני ב-proxy שגורם לאנשים לאבד ערב שלם. חיבור הבקרה של Tailscale הוא מסוג HTTP upgrade; הוא מתחיל ב-POST במקום ב-GET, והערך של ה-header מסוג Upgrade הוא tailscale-control-protocol. Caddy מעביר זאת ללא הגדרה נוספת. לעומת זאת, nginx אינו עושה זאת, ולכן חזית (front end) של nginx זקוקה למיפוי ה-upgrade הבא:
map $http_upgrade $connection_upgrade {
default keep-alive;
'' close;
}
server {
listen 443 ssl;
server_name headscale.example.com;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering off;
proxy_pass http://127.0.0.1:8080;
}
}השמטת שורות אלו תאפשר לבקשות רגילות להצליח, וזו הסיבה ש-/health מחזיר 200 והכל נראה תקין, בעוד שחיבור הבקרה ארוך-הטווח לעולם אינו נוצר והצמתים שלכם נרשמים אך נשארים במצב offline. אם בחרתם בנתיב של nginx, המדריך Certbot ב-Ubuntu 24.04 עם nginx מכסה את החלק של התעודות.
אילו פורטים לפתוח ב-UFW
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verboseפורט 443 נושא את כל התקשורת מול הלקוחות. פורט 80 קיים אך ורק עבור ה-HTTP challenge של ACME (סביבת ניהול תעודות אוטומטית) ועבור ההפניה ל-HTTPS; Caddy זקוק לו כדי להנפיק תעודה מלכתחילה.
פורט 8080 נשאר סגור. listen_addr הוא 127.0.0.1:8080, לכן ה-proxy מגיע אל headscale דרך ממשק ה-loopback ולא מעורב בכך חוק firewall. פתיחת פורט 8080 לאינטרנט מעניקה ללקוחות ערוץ בקרה בטקסט גלוי ואינה מועילה בדבר. זכרו שרוב ספקי הענן מפעילים firewall נוסף בלוח הבקרה שלהם, בנפרד מ-UFW, כך שפורט יכול להיות פתוח בשרת ועדיין חסום בקצה הרשת. המדריך יסודות ה-firewall של UFW ב-VPS סוקר את תחביר החוקים בפירוט רב יותר.
יצירת משתמש ומפתח preauth
sudo headscale users create alice
sudo headscale users listהפקודה headscale היא לקוח. היא מתקשרת עם ה-daemon הפעיל דרך ה-unix socket בנתיב /var/run/headscale/headscale.sock, אשר מוגדר במצב 0770 ובבעלות הקבוצה headscale. מכך נובעים שני דברים. הפקודה נכשלת כאשר השירות אינו פעיל, וזו הסיבה הנוספת לכך שסדר הפעולות במדריך זה חשוב; כמו כן, נדרשות הרשאות sudo אלא אם תוסיפו את חשבונכם לקבוצה headscale.
users list מדפיסה מזהה (ID) לצד כל שם. עליכם להשתמש במספר זה, כיוון שפקודת המפתח מקבלת מזהה משתמש מספרי ולא שם.
sudo headscale preauthkeys create --user 1 --expiration 24hהמפתח מודפס פעם אחת בלבד. העתיקו אותו כעת. מפתח preauth מיועד לשימוש חד-פעמי ותקף לשעה אחת אלא אם צוין אחרת, לכן כדאי להגדיר --expiration 24h כל עוד אתם בשלב הבדיקות. הוסיפו את --reusable עבור מפתח המיועד לרישום מספר מכונות, והתייחסו אליו כאל סיסמה, שכן כל מי שמחזיק בו יכול להצטרף לרשת שלכם.
חיבור הלקוח הראשון באמצעות --login-server
במכונה שאותה ברצונך לצרף:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --login-server https://headscale.example.com --auth-key 'hskey-auth-PASTE-YOUR-KEY-HERE'
tailscale status
tailscale ip -4tailscale ip -4 מדפיס את הכתובת ש־headscale הקצה, משהו בסגנון 100.64.0.1. בחזרה בשרת, sudo headscale nodes list מציג את הצומת עם ה־ID שלו, המשתמש שלו ומצב החיבור שלו.
הערך של --login-server חייב להתאים בדיוק ל־server_url, כולל הסכימה וללא לוכסן בסוף. הערכים מושווים כמחרוזות, ואי-התאמה משמעותה שהלקוח נרשם מול כתובת אחת ואז מתבקש לתקשר עם כתובת אחרת.
מכונה שהייתה מחוברת בעבר לשירות המנוהל של Tailscale שומרת את פרטי ההתחברות ההם. יש להריץ עליה תחילה את sudo tailscale logout, ולאחר מכן להריץ את tailscale up עם --login-server.
אם תשמיט את --auth-key, הלקוח ידפיס URL במקום זאת. פתח אותו והדף יציג את המזהה עבור ניסיון הרישום הזה, אותו תאשר בשרת:
sudo headscale auth register --user alice --auth-id PASTE-THE-ID-FROM-THE-PAGEטופס זה נוח יותר עבור המחשב הנייד האישי שלך. מפתחות Preauth עדיפים עבור כל תהליך מתוסרט, שכן אין צורך בנוכחות אדם. ברגע שה־VPS עצמו הוא צומת, הוא יכול גם להעביר את תעבורת האינטרנט של המכונות האחרות שלך, וזהו הגדרת צומת יציאה (exit node), עם ההבדל היחיד שאתה מאשר את הנתיב המפורסם בשרת באמצעות הפקודה headscale במקום בקונסולת ניהול מנוהלת. אם מה שאתה מחפש הוא גישה לרשת פרטית שנמצאת מאחורי אותו VPS ולא דרך יציאה לאינטרנט, אותו שלב אישור מכסה את פרסום רשת משנה (subnet) לשאר ה-tailnet שלך. פרסום יישום בודד מצומת, במקום ניתוב רשתות שלמות דרכו, הוא משימה שונה, ו-serve ו-funnel הן שתי הדרכים לבצע זאת, אם כי שתיהן נשענות על מנגנון התעודות והכניסה של Tailscale עצמה, לכן יש להתייחס אליהן כאל תכונות של tailnet מנוהל ולא כמשהו ש־headscale מספק לך.
DERP, ומה מעביר תעבורה כאשר נתיב ישיר נכשל
DERP (ראשי תיבות של designated encrypted relay for packets) הוא נתיב הגיבוי. כאשר שני צמתים אינם מצליחים לפתוח חיבור WireGuard ישיר, בדרך כלל משום ששניהם נמצאים מאחורי NAT (תרגום כתובות רשת) מחמיר, הם שולחים חבילות דרך ממסר (relay) במקום זאת. הממסר אינו מחזיק במפתחות, ולכן אין באפשרותו לקרוא את התעבורה שלכם. הוא אמנם רואה אילו צמתים מתקשרים ומהו נפח הנתונים העובר ביניהם.
חשוב להבין מה עושה תצורת ברירת המחדל. Headscale מופץ כשהוא מצביע על https://controlplane.tailscale.com/derpmap/default עם auto_update_enabled: true ו-update_frequency: 3h, כך שמישור הבקרה (control plane) הוא שלכם, בעוד שהממסרים הם של Tailscale. עבור רוב האנשים זו פשרה הוגנת. אם זה לא מתאים לכם, הריצו ממסר משלכם.
כדי להריץ ממסר משלכם, הגדירו את enabled: true תחת derp.server בתוך config.yaml, הפעילו מחדש את headscale, ופתחו את פורט ה-STUN (ראשי תיבות של session traversal utilities for NAT) באמצעות sudo ufw allow 3478/udp. קובץ התצורה מצהיר על הדרישה בבירור: ה-server_url חייב להשתמש ב-https, כיוון ש-DERP דורש TLS. ריקון רשימת ה-derp.urls מסיר את הממסרים של Tailscale מהמפה, ואם תעשו זאת ללא ממסר מוטמע תקין, כל זוג צמתים שאינו יכול להתחבר ישירות לא יוכל להתחבר כלל.
מתוך לקוח, tailscale netcheck מדפיס את השיהוי (latency) לכל אזור ממסר מוכר, ו-tailscale status מסמן כל עמית (peer) כ-direct עם כתובת או כ-relay עם קוד אזור. עמית שתקוע על relay מעיד על בעיית NAT, לא על בעיה ב-headscale. עמית שהוא direct ועדיין איטי הוא שאלה אחרת, ו-התשובה המקובלת שם היא MTU ולא המנהרה עצמה.
מדוע צומת מופיע כלא מקוון (offline)?
ה-proxy חוסם את ה-upgrade. זוהי הסיבה הנפוצה ביותר, והסימן המזהה שלה הוא שכל שאר הרכיבים נראים תקינים: /health מחזיר 200, headscale nodes list מציג את הצומת, אך הצומת לעולם לא עובר למצב מקוון. חיבור הבקרה הוא מסוג POST הנושא Upgrade: tailscale-control-protocol, ו-proxy שאינו מעביר אותו קוטע את הערוץ היחיד שמדווח על מצב הצומת. השוו את תצורת ה-nginx שלכם מול בלוק ה-map לעיל, או עברו ל-Caddy כדי לשלול בעיות ב-proxy.
ה-server_url השתנה לאחר רישום הצמתים. צמתים ממשיכים להתחבר לערך שניתן להם בעת הרישום. אם ערכתם אותו, הריצו sudo tailscale up --login-server https://headscale.example.com --force-reauth בכל צומת.
הלקוח אינו פועל. בצומת, בדקו את sudo systemctl is-active tailscaled ו-sudo journalctl -u tailscaled -n 50 --no-pager. לקוח שאינו מצליח לבצע resolution או להגיע לדומיין שלכם יתעד שם את הניסיונות החוזרים שלו.
המפתח פג תוקף. נושא זה מכוסה בסעיף הבא.
כדי לנטר את צד השרת בזמן הבדיקה, הריצו sudo journalctl -u headscale -f ב-VPS והפעילו מחדש את tailscaled בלקוח. צומת שמגיע ל-headscale מייצר שורות לוג באופן מיידי. שתיקה משמעותה שהבקשה אינה מגיעה, לכן בדקו את ה-DNS, ה-firewall וה-proxy לפני שתבדקו את headscale.
תוקף מפתח, והצומת שמפסיק לעבוד כעבור שבועות
קיימים שני סוגי תוקף נפרדים, ובלבול ביניהם גוזל זמן יקר.
מפתחות preauth פוקעים במהירות מעצם תכנונם. ברירת המחדל היא שעה אחת ושימוש אחד. אם tailscale up מסרב לקבל את המפתח, צרו מפתח חדש בשרת במקום לערוך הגדרות כלשהן בלקוח.
מפתחות צומת (node keys) הם החלק בעל אורך החיים הארוך. הסעיף node בתוך config.yaml מגדיר את expiry: 0, והערך 0 משמעותו שאין תוקף ברירת מחדל: צומת רשום נשאר תקף עד שתבטלו אותו ידנית. צמתים עם תגיות (tagged nodes) לעולם אינם פוקעים. הגדירו את expiry: 180d אם ברצונכם שרישומים יפוגו עם הזמן, אך הבינו את המשמעות: כל צומת ללא תגית יזדקק ל-sudo tailscale up --login-server https://headscale.example.com --force-reauth לפי לוח זמנים זה, ושרת ללא ממשק (headless) שאף אחד לא מבצע בו אימות מחדש, ינותק מהרשת באופן אוטומטי.
בצעו זאת ידנית כאשר מישהו מאבד מחשב נייד. הפקודה sudo headscale nodes list תציג לכם את ה-ID, לאחר מכן sudo headscale nodes expire -i 3 תנתק את אותו צומת, ו-sudo headscale nodes delete -i 3 תסיר אותו מהרשת לחלוטין.
גיבויים ושדרוגים
/var/lib/headscale ו-/etc/headscale יחד מהווים את כל השרת. עצרו את השירות לפני העתקתם, כיוון ש-SQLite עשוי לבצע כתיבות בזמן אמת, ומסד נתונים שמועתק תחת עומס עלול להיות לא עקבי.
sudo systemctl stop headscale
sudo tar czf /root/headscale-state.tgz -C /var/lib headscale
sudo tar czf /root/headscale-config.tgz -C /etc headscale
sudo systemctl start headscale
sudo chmod 600 /root/headscale-*.tgzהעבירו את שני הקבצים אל מחוץ לשרת. הם מכילים את מפתחות ההצפנה הפרטיים ואת כל הרישומים, ולכן הם דורשים את אותה רמת הגנה כמו השרת עצמו. גיבויי restic משרת VPS מסביר כיצד לבצע זאת באופן מתוזמן ומוצפן.
שדרוגים חוזרים על תהליך ההתקנה: הורידו את .deb ו-sudo apt install ./headscale.deb החדשים, לאחר מכן בצעו הפעלה מחדש והריצו שוב את בדיקות is-active ו-/health. החל מגרסה 0.29 נתיב השדרוג הוא קשיח. דילוג על גרסה משנית חסום, וכך גם הורדת גרסה לגרסה משנית ישנה יותר. עברו גרסה משנית אחת בכל פעם, בצעו גיבוי לפני כל שלב, וקראו תחילה את הערות השחרור של אותה גרסה, כיוון שאותו שחרור שינה את התנהגות מדיניות ה-ACL והעביר מספר מפתחות תצורה.
FAQ
מדוע headscale נכשל בעלייה מיד לאחר התקנת ה-.deb?
החבילה מתקינה את ה-unit אך משאירה את השירות במצב עצור, וקובץ ה-/etc/headscale/config.yaml המוגדר כברירת מחדל הוא תבנית ולא תצורה תקינה. עליכם לערוך תחילה את server_url, listen_addr ו-base_domain, לאחר מכן להריץ את sudo systemctl enable --now headscale ולאשר עם sudo systemctl is-active headscale. אם השירות עדיין נכשל, sudo journalctl -u headscale -n 50 --no-pager יצביע על מקור הבעיה; בשלב זה מדובר כמעט תמיד בשגיאת YAML, כיוון ש-headscale מנתח את כל הקובץ לפני שהוא מבצע bind לפורט.
האם עליי להתקין את לקוח Tailscale הרגיל על המכונות שלי?
כן. headscale מחליף רק את שרת הבקרה (control server). כל צומת מריץ את הלקוח הרשמי של Tailscale, ואתם מפנים אותו לשרת שלכם באמצעות sudo tailscale up --login-server https://headscale.example.com. דגל זה קיים בלקוח הסטנדרטי, כך שאין צורך בביצוע patch או בבנייה מחדש.
האם התעבורה שלי עוברת דרך שרת ה-headscale?
בדרך כלל לא. headscale מתאם את הרשת ומחלק מפתחות וכתובות, בעוד נתיב הנתונים הוא WireGuard ישיר בין הצמתים שלכם. התעבורה עוברת דרך השרת רק כאשר שני צמתים אינם יכולים להגיע זה לזה ישירות ומבצעים fallback ל-DERP relay. בתצורה שמגיעה עם התוכנה, ה-relays הללו הם השרתים הציבוריים של Tailscale. הריצו tailscale status על צומת כדי לראות אם עמית מסוים הוא direct או נמצא על relay.
מדוע הצומת שלי נשאר במצב offline לאחר הרישום?
צומת שמופיע ב-headscale nodes list אך לעולם אינו הופך ל-online, איבד בדרך כלל את חיבור הבקרה שלו ב-reverse proxy. חיבור זה הוא HTTP upgrade שנשלח כ-POST עם ה-header Upgrade: tailscale-control-protocol, ו-nginx מפיל אותו אלא אם תוסיפו את בלוק ה-map $http_upgrade $connection_upgrade ואת שורות ה-proxy_set_header התואמות. Caddy מעביר את הבקשה ללא צורך בתצורה נוספת, מה שהופך אותו לדרך מהירה לבדוק אם ה-proxy הוא מקור התקלה.
האם אני זקוק לשם מתחם (domain) ול-TLS עבור headscale?
בפועל, כן. לקוחות מתחברים לכל מחרוזת שתגדירו ב-server_url, תעודות מונפקות עבור שמות ולא עבור כתובות IP חשופות, וקובץ התצורה מציין ש-DERP דורש TLS. שילוב של שם מתחם עם Caddy אורך כחמש דקות ומעניק לכם נקודת קצה HTTPS שמתחדשת מעצמה. הרצת שרת הבקרה על גבי HTTP רגיל משמעותה שכל תקשורת של הלקוח מולו עוברת באינטרנט בטקסט גלוי.