SSD Nodes Learn Hosting plans →
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-11-01

كيف تستضيف خادم Tailscale بنفسك باستخدام headscale

شغّل خادم تحكم Tailscale على VPS تملكه: ثبّت headscale من حزمة .deb الرسمية، اضبط server_url، أعد تشغيل الخدمة، ثم أضف أول عقدة إلى شبكتك.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, July 30, 2026.

ما هو 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، لذلك يتوقف الاختيار على طريقة كتابة قواعد الوصول وطريقة عمل relays. ومن المفيد مقارنة NetBird مع Tailscale في هذين الجانبين قبل تثبيت أي منهما. وللاطلاع على المقارنة الأوسع بين النموذجين، راجع أوجه اختلاف 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 0.29.6 إصدار 1.80.0 أو أحدث من عميل Tailscale.

تثبيت headscale من حزمة .deb الرسمية

ينشر المشروع حزم .deb في صفحة إصداراته على GitHub. اعتباراً من October 27, 2026، أحدث إصدار مستقر هو 0.29.6، وقد صدر في October 24, 2026. تحقّق من البنية أولاً، لأن اسم الملف يتضمنها.

sudo apt update
sudo apt install -y wget
dpkg --print-architecture

يطبع ذلك amd64 على VPS عادي بمعمارية x86، وarm64 على خطة من نمط Ampere أو Graviton. ضع الإجابة في المتغير أدناه.

HEADSCALE_VERSION="0.29.6"
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، ثم تبدأ الخدمة. لذلك تكون headscale قيد التشغيل بالفعل عند عودة apt، ويطبع sudo systemctl is-active headscale القيمة active. لكن الحزمة لا تفعّل الوحدة عند الإقلاع في تثبيت جديد، لذلك لن تعود الخدمة بعد إعادة التشغيل إلى أن تفعّلها، وهو ما تنفذه خطوة إعادة التشغيل أدناه. كما أنها تعمل باستخدام الإعداد المشحون، وهذا الإعداد يربط server_url بالعنوان http://127.0.0.1:8080، وهو عنوان لا يستطيع أي عميل لديك الوصول إليه. لا يوجد شيء مكشوف بعد، لأن listen_addr المشحون يستمع على loopback أيضاً، لكن لا تُضف أي عميل قبل ضبط server_url وإعادة تشغيل الخدمة، وهو ما تنفذه الخطوتان التاليتان.

اضبط 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.yaml

يحدّد server_url العنوان العام الذي يستخدمه headscale عند إنشاء عناوين URL للتسجيل. يستخدم العملاء عنوان التحكم المكوّن عبر --login-server، لذلك استخدم الاسم العام نفسه مع https:// في الموضعين، ولا تستخدم 127.0.0.1 مطلقاً. توضّح وثائق headscale أن HTTP العادي، أو HTTPS على منفذ غير 443، ممكنان، لكنها توصي بشدة باستخدام HTTPS على المنفذ 443 في بيئات الإنتاج، ويفترض باقي هذا الدليل ذلك.

يحدّد listen_addr العنوان الذي تستمع عليه العملية. اتركه على loopback. ينهي reverse proxy على الخادم نفسه TLS (أمان طبقة النقل) ثم يمرّر الاتصالات إليه، لذلك لا يحتاج أي شيء خارج الخادم إلى الوصول إلى المنفذ 8080.

يحدّد base_domain لاحقة MagicDNS، أي النطاق الذي تحصل عقدك على أسمائها تحته. يجب أن يكون اسم نطاق مؤهلاً بالكامل من دون نقطة في نهايته، ويجب أن يختلف عن النطاق المستخدَم في server_url، وإلا قد تتعارض مساحتا الأسماء.

اترك قسم قاعدة البيانات كما هو. الإعداد الافتراضي هو SQLite في /var/lib/headscale/db.sqlite، داخل مجلد أنشأته الحزمة وتملكه، وSQLite كافية لشبكة tailnet بهذا الحجم.

أعد تشغيل headscale وتحقق من أنه يعمل

sudo systemctl restart headscale
sudo systemctl enable headscale
sudo systemctl is-active headscale
sudo systemctl is-enabled headscale
curl -sS -o /dev/null -w '%{http_code}\\n' http://127.0.0.1:8080/health

يطبع is-active القيمة active، ويطبع is-enabled القيمة enabled، بينما يطبع curl القيمة 200. إعادة التشغيل هي الخطوة التي تُحمّل تعديلاتك. يقرأ headscale إعداداته مرة واحدة عند بدء التشغيل، لذلك تواصل العملية التي بدأتها الحزمة استخدام server_url المضمّن إلى أن تعيد تشغيلها. لا تنفّذ sudo systemctl enable --now headscale هذه المهمة: الخدمة تعمل بالفعل، لذلك لا يغيّر بدء --now شيئاً، وتبقى القيمة القديمة فعّالة. بدء التشغيل تلقائياً عند الإقلاع هو مهمة enable، ولا تُنفَّذ تلقائياً: عند التثبيت الجديد، تبدأ الحزمة الخدمة من دون تفعيلها، لذلك نفّذ sudo systemctl enable headscale مرة واحدة، كما سبق.

إذا طبع is-active أي قيمة غير active، أو لم يطبع curl القيمة 200، فاقرأ journal باستخدام sudo journalctl -u headscale -n 50 --no-pager. يكون الفشل في هذه المرحلة ناتجاً في الغالب عن ملف الإعداد، لأن headscale يحلّل الملف بالكامل قبل أن يفتح مقبساً، ولذلك يمنع تنسيق المسافة البادئة غير الصحيح أو إعداد مطلوب غير صالح العملية من العمل قبل أن يبدأ أي شيء بالاستماع. أصلح الملف، ثم نفّذ sudo systemctl restart headscale. تحتاج كل التغييرات اللاحقة في الإعداد إلى إعادة التشغيل نفسها. يعيد العملاء الاتصال تلقائياً بعد ذلك. إذا كانت وحدات 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 عند تحليل الملف بنجاح. أما التحذير من أن الملف غير منسق، فهو تجميلي. من حاسوبك المحمول، يجب أن يطبع curl -sS -o /dev/null -w '%{http_code}\\n' https://headscale.example.com/health القيمة 200 أيضاً. يثبت هذا الفحص الواحد أن DNS والجدار الناري والشهادة والـproxy تعمل معاً.

إليك تفصيلاً في الـproxy يستهلك من الناس أمسية كاملة. اتصال التحكم في Tailscale هو ترقية HTTP، ويبدأ باستخدام POST بدلاً من GET، وقيمة ترويسة Upgrade هي tailscale-control-protocol. يمرر Caddy ذلك دون إعداد إضافي. أما nginx فلا يفعل ذلك، لذلك يجب على واجهة nginx الأمامية تمرير الترويحتين Upgrade وConnection صراحةً. تنفذ وثائق headscale ذلك باستخدام خريطة ترقية:

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 ويبدو كل شيء سليماً، بينما لا يتشكل اتصال التحكم أبداً: لا يمكن للعقد الجديدة التسجيل، ولا يمكن للعقد الموجودة إعادة الاتصال والإبلاغ عن أنها متصلة. إذا اخترت 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 اتصال التحكم الخاص بكل عميل إلى headscale. إذا فعّلت لاحقاً مرحّل DERP المضمّن، فسيحتاج أيضاً إلى المنفذ 3478/udp، كما هو موضح أدناه. يُستخدم المنفذ 80 لتحدي HTTP الخاص بـACME (بيئة إدارة الشهادات التلقائية) ولإعادة التوجيه إلى HTTPS. لا يزال بإمكان Caddy الحصول على شهادة مع إغلاق المنفذ 80، لأنّه يستطيع استخدام تحدي TLS-ALPN على المنفذ 443، لكن فتح المنفذ 80 يتيح التحديين معاً ويعيد توجيه طلبات http:// العادية.

يبقى المنفذ 8080 مغلقاً. listen_addr هو 127.0.0.1:8080، لذلك يصل الـproxy إلى headscale عبر واجهة loopback ولا تكون هناك حاجة إلى قاعدة في الجدار الناري. لن يؤدي فتح المنفذ 8080 في UFW إلى كشف أي شيء، لأنّه لا توجد خدمة تستمع إليه من الخارج، كما أنّه لا يحقق أي فائدة. تذكّر أنّ معظم مزوّدي الخدمة يشغّلون جداراً نارياً ثانياً في لوحة التحكم الخاصة بهم، منفصلاً عن UFW، لذلك قد يكون المنفذ مفتوحاً على الخادم ومغلقاً عند الحافة في الوقت نفسه. يشرح أساسيات جدار UFW الناري على VPS صياغة القواعد بمزيد من التفصيل.

إنشاء مستخدم ومفتاح مصادقة مسبقة

sudo headscale users create alice
sudo headscale users list

الأمر headscale هو عميل. ويتصل بالـdaemon قيد التشغيل عبر مقبس Unix الموجود في /var/run/headscale/headscale.sock، وهو مضبوط على الوضع 0770 وتملكه المجموعة headscale. وينتج عن ذلك أمران. يفشل الأمر عندما تكون الخدمة متوقفة، وهذا سبب آخر لأهمية ترتيب الخطوات في هذا الدليل، كما يتطلب sudo ما لم تضف حسابك إلى المجموعة headscale.

يطبع users list معرّفاً بجانب كل اسم. تحتاج إلى هذا الرقم، لأن أمر المفتاح يتطلب معرّف مستخدم رقمياً وليس اسماً.

sudo headscale preauthkeys create --user 1 --expiration 24h

يُطبع المفتاح مرة واحدة. انسخه الآن. مفتاح المصادقة المسبقة يُستخدم مرة واحدة ويظل صالحاً لمدة ساعة واحدة ما لم تحدد خلاف ذلك، لذلك من المفيد ضبط --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 -4

يعرض tailscale ip -4 العنوان الذي عيّنه headscale، مثل 100.64.0.1. بالعودة إلى الخادم، يعرض sudo headscale nodes list العقدة مع معرّفها ومستخدمها وحالتها المتصلة.

استخدم عنوان HTTPS العام من server_url مع --login-server. يزيل العميل الشرطات المائلة اللاحقة من عنوان التحكم الخاص به؛ ولا توجد مقارنة نصية حرفية تفرض حذف إحدى هذه الشرطات.

يحتفظ الجهاز الذي سبق تسجيل دخوله إلى الخدمة المستضافة من 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

هذا النموذج أسهل للحاسوب المحمول الشخصي. أما مفاتيح المصادقة المسبقة فهي أفضل لأي شيء يُشغَّل بالبرمجة النصية، لأنك لن تحتاج إلى شخص يراقبه. بعد أن تصبح VPS نفسها عقدة، يمكنها أيضاً نقل حركة الإنترنت الخاصة بأجهزتك الأخرى، وهذا هو إعداد عقدة الخروج، مع اختلاف واحد: توافق على المسار المُعلَن على الخادم باستخدام الأمر headscale بدلاً من ذلك في وحدة تحكم إدارية مستضافة. إذا كنت تريد الوصول إلى شبكة خاصة موجودة خلف VPS، بدلاً من توفير مخرج إلى الإنترنت، فتغطي خطوة الموافقة نفسها إعلان تلك الشبكة الفرعية لبقية tailnet. أما نشر تطبيق واحد من عقدة، بدلاً من توجيه شبكات كاملة عبرها، فهو مهمة مختلفة، وserve وfunnel هما الطريقتان لتنفيذ ذلك، لكن كليهما يعتمد على آلية الشهادات والإدخال الخاصة بـTailscale، لذلك تعامل معهما كميزات في tailnet المستضاف، لا كميزات يوفّرها headscale مباشرة.

DERP، وما الذي يرحّل حركة المرور عند فشل المسار المباشر

DERP (المرحل المشفّر المخصّص للحزم) هو مسار الرجوع الاحتياطي. عندما يتعذر على عقدتين فتح اتصال WireGuard مباشر، وغالباً لأن كلتيهما خلف NAT صارم (ترجمة عناوين الشبكة)، ترسلان الحزم عبر مرحل بدلاً من ذلك. لا يحتفظ المرحل بأي مفاتيح، لذلك لا يمكنه قراءة حركة مرورك. لكنه يرى أي عقد تتواصل وأي كمية من البيانات تنتقل.

يجب أن تعرف بوضوح ما يفعله الإعداد الافتراضي. يأتي Headscale مضبوطاً للإشارة إلى https://controlplane.tailscale.com/derpmap/default مع auto_update_enabled: true وupdate_frequency: 3h، ولذلك تكون طبقة التحكم ملكك، بينما تكون المرحلات تابعة لـTailscale. هذا حل مناسب لمعظم المستخدمين. إذا لم يكن مناسباً لك، فشغّل مرحلك الخاص.

لتشغيل مرحلك الخاص، اضبط enabled: true ضمن derp.server في config.yaml، واستبدل ipv4: 198.51.100.1 وipv6: 2001:db8::1 المضمّنين بعناوين مرحلك العامة، أو أزل الإعدادين معاً لاستخدام DNS، ثم أعد تشغيل headscale وافتح منفذ STUN (أدوات اجتياز الجلسات لـNAT) باستخدام sudo ufw allow 3478/udp. تتجاوز إعدادات العناوين هذه DNS، لذلك يؤدي ترك أي عنصر نائب منها إلى توجيه العملاء إلى عنوان يتعذر الوصول إليه. يوضح ملف الإعداد المتطلب صراحةً: يجب أن يستخدم server_url البروتوكول https، لأن DERP يتطلب TLS. يؤدي تفريغ قائمة derp.urls إلى إزالة مرحلات Tailscale من الخريطة؛ لذلك أبقِ مرحلاً مضمّناً أو مخصصاً عاملاً قبل تنفيذ ذلك. يرفض Headscale بدء التشغيل عند وجود خريطة مرحلات فارغة، كما أن الخريطة التي تحتوي على مرحل يتعذر الوصول إليه فقط تترك العقد التي لا تستطيع الاتصال مباشرةً عاجزة عن التواصل.

من عميل، يطبع tailscale netcheck زمن الاستجابة لكل منطقة مرحلات يعرفها، بينما يعرض tailscale status direct مع عنوان أو relay مع رمز منطقة للاتصالات النشطة مع الأقران. يحتاج النظير العالق في relay إلى فحص مساره المباشر، بما في ذلك قواعد NAT والجدار الناري. أما النظير الذي تكون حالته direct وما زال بطيئاً، فهذه مسألة مختلفة، والإجابة المعتادة فيها هي MTU وليس النفق نفسه الإجابة المعتادة هناك هي MTU وليست النفق نفسه.

لماذا تظهر عقدة على أنها غير متصلة؟

الـproxy يُسقط طلب الترقية. علامته أن /health يعيد الرمز 200، بينما تفشل التسجيلات الجديدة أو لا تتمكن العقد الموجودة من إعادة الاتصال. اتصال التحكم هو طلب POST يحمل Upgrade: tailscale-control-protocol، وأي proxy لا يمرره يمنع التسجيل وقناة الإبلاغ عن حالة العقدة. قارن إعدادات nginx لديك بأسطر الترقية أعلاه، أو بدّل إلى Caddy لاستبعاد الـproxy كسبب.

تغيّر عنوان التحكم العام. تواصل العقد الاتصال بالعنوان المُعد باستخدام --login-server؛ ولا يؤدي تغيير 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. يسجل العميل الذي لا يستطيع حل نطاقك أو الوصول إليه محاولات إعادة الاتصال في ذلك السجل.

انتهت صلاحية المفتاح. يشرح القسم التالي هذه الحالة.

لمراقبة جانب الخادم أثناء الاختبار، نفّذ sudo journalctl -u headscale -f على VPS وأعد تشغيل tailscaled على العميل. افحص سجل العميل أيضاً: وصول طلب إلى headscale لا يضمن ظهور سطر في مستوى السجل الافتراضي، لذلك لا يثبت صمت سجل الخادم وحده وجود فشل في DNS أو جدار الحماية أو الـproxy.

انتهاء صلاحية المفاتيح، والعقدة التي تتوقف عن العمل بعد أسابيع

يوجد نوعان منفصلان من انتهاء الصلاحية، والخلط بينهما يهدر الوقت.

تنتهي صلاحية مفاتيح Preauth بسرعة عن قصد. الإعداد الافتراضي هو ساعة واحدة واستخدام واحد. إذا رفض tailscale up المفتاح، فأنشئ مفتاحاً جديداً على الخادم بدلاً من تعديل أي شيء على العميل.

مفاتيح العقد هي الجزء طويل الأمد. يحدّد قسم node في config.yaml الإعداد expiry: 0، ويعني 0 عدم وجود انتهاء صلاحية افتراضي؛ لكن يمكن أن يظل انتهاء الصلاحية المحدد للعميل أو انتهاء صلاحية OIDC سارياً. تُستثنى العقد الموسومة من الانتهاء التلقائي، مع إمكانية أن يفرض المسؤول انتهاء صلاحيتها صراحةً. عيّن expiry: 180d إذا أردت إعداداً افتراضياً مدته 180 يوماً للتسجيلات غير الموسومة، لكن تكون الأولوية لانتهاء الصلاحية الذي يطلبه العميل، ويمكن لـOIDC تجاوز الإعداد الافتراضي. لا يغيّر تعديل هذا الإعداد التسجيلات الحالية بأثر رجعي. تحتاج العقدة التي لها تاريخ انتهاء صلاحية إلى إعادة المصادقة قبل ذلك الموعد باستخدام sudo tailscale up --login-server https://headscale.example.com --force-reauth، وسينقطع خادم بلا واجهة، لا يعيد أحد المصادقة عليه، عن الشبكة عند انتهاء صلاحية تسجيله.

نفّذ ذلك يدوياً عندما يفقد شخص ما حاسوباً محمولاً. يعرض لك sudo headscale nodes list المعرّف، ثم يسجّل 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 ونقل عدة مفاتيح إعداد. يتضمن الإصدار 0.29.6 أيضاً تحديثات أمنية للتحقق من الشهادات والتبعيات، ولذلك ينبغي للتثبيتات الحالية من 0.29 تثبيت هذا الإصدار التصحيحي.

FAQ

هل يعمل headscale مباشرة بعد تثبيت ملف .deb؟

نعم. تبدأ الحزمة الخدمة فور تثبيتها، باستخدام /etc/headscale/config.yaml المضمّن معها، والذي يستمع على loopback فقط ويضبط server_url على http://127.0.0.1:8080. في التثبيت الجديد، لا تفعّل الحزمة الخدمة للإقلاع، لذلك لن تبدأ عند تشغيل النظام حتى تنفّذ sudo systemctl enable headscale. العنوان المضمّن غير مفيد للعملاء، لذلك عدّل server_url وlisten_addr وbase_domain، ثم نفّذ sudo systemctl restart headscale وتحقق باستخدام sudo systemctl is-active headscale. يجب أن تكون القيمة restart، لأن headscale يقرأ الملف عند بدء تشغيله فقط. كما أن enable --now على خدمة قيد التشغيل يفعّلها للإقلاع، لكنه لا يعيد تشغيلها، لذلك تبقى القيم القديمة فعّالة. إذا فشلت الخدمة بعد إعادة التشغيل، يحدّد sudo journalctl -u headscale -n 50 --no-pager المشكلة. في هذه المرحلة يكون السبب غالباً خطأ في YAML، لأن headscale يحلّل الملف بأكمله قبل أن يستمع على منفذ.

هل ما زلت أحتاج إلى تثبيت عميل Tailscale العادي على أجهزتي؟

نعم. يستبدل headscale خادم التحكم فقط. يعمل على كل عقدة العميل الرسمي من Tailscale، وتوجّهه إلى خادمك باستخدام sudo tailscale up --login-server https://headscale.example.com. هذا الخيار موجود في العميل القياسي، لذلك لا تحتاج إلى تصحيح أي شيء أو إعادة بناء العميل.

هل تمر حركة الشبكة عبر خادم headscale؟

عادةً لا. ينسّق headscale الشبكة ويوزّع المفاتيح والعناوين، بينما يمر مسار البيانات مباشرة عبر WireGuard بين العقد. لا تسلك حركة الشبكة مساراً بديلاً إلا عندما يتعذر على عقدتين الوصول إلى بعضهما مباشرة، فتنتقلان إلى مرحّل DERP. وبالإعداد المضمّن، تكون هذه المرحّلات هي المرحّلات العامة التابعة لـTailscale. نفّذ tailscale status على عقدة لمعرفة ما إذا كان نظير معيّن في حالة direct أو على relay.

لماذا تظل عقدتي غير متصلة بعد تسجيلها؟

تحتاج العقدة التي تظهر في headscale nodes list لكنها لا تتصل مطلقاً إلى فحص اتصال التحكم الخاص بها، بما في ذلك الـreverse proxy. هذا الاتصال هو ترقية HTTP تُرسل باستخدام POST مع الرأس Upgrade: tailscale-control-protocol. ويسقطه nginx ما لم تمرّر رأسي Upgrade وConnection صراحةً باستخدام proxy_set_header، وهو ما ينجزه الإعداد أعلاه من خلال كتلة map $http_upgrade $connection_upgrade. كما أن إسقاط هذين الرأسين يمنع العقد الجديدة من التسجيل. يمرّر Caddy هذا الاتصال دون إعداد إضافي، لذلك يمكن استخدامه لاختبار ما إذا كان الـproxy هو سبب المشكلة.

هل أحتاج إلى اسم نطاق وTLS لاستخدام headscale؟

نعم، في هذا الإعداد استخدم اسم نطاق وHTTPS. يمكن للشهادات أيضاً تغطية عناوين IP العارية، لكن ملف الإعداد يوضح أن DERP يتطلب TLS. يستغرق إعداد نطاق مع Caddy نحو خمس دقائق، ويوفّر نقطة نهاية HTTPS تجدّد شهادتها تلقائياً. يمكن استخدام HTTP العادي، لكن توثيق headscale يوصي بشدة باستخدام HTTPS على المنفذ 443 في بيئات الإنتاج، ويذكر أن عميل Tailscale يفترض استخدام HTTPS على المنفذ 443 في حالات معينة.

هل كان هذا المقال مفيدًا؟