أمر واحد يحوّل مشروعك المحلي إلى رابط HTTPS عام على دومينك.
بدون فتح بورت، بدون Port Forwarding، بدون شهادات SSL، بدون إنشاء سجلات DNS يدويًا.
$ linko 3000
✓ DNS record created (x92ka.example.com)
✓ Route published (x92ka.example.com -> http://localhost:3000)
✓ Tunnel connected
Public URL https://x92ka.example.com
Forwards http://localhost:3000
Press Ctrl+C to stop- ما تحتاجه
- التثبيت
- توكن Cloudflare ← أهم خطوة
- الإعداد
- قاعدة المستوى الواحد ← اقرأها قبل أن تحتاجها
- الاستخدام والأوامر
- حل المشاكل
- حساب Cloudflare مجاني
- دومين موجّهة nameservers الخاصة به إلى Cloudflare
لا تحتاج Go، ولا تحتاج تثبيت cloudflared — يُنزَّل تلقائيًا عند أول استخدام.
curl -fsSL https://raw.githubusercontent.com/Devehab/linko/main/install.sh | bashيكتشف السكربت نظامك، ينزّل الملف التنفيذي الجاهز، ويضعه في مجلد موجود في مسارك. للتحقق:
linko --versionنزّل ملف .zip من صفحة الإصدارات،
فك الضغط، وضع linko.exe في مجلد ضمن PATH.
هذه الطريقة تحتاج Go. إن لم يكن مثبتًا:
# macOS
brew install go
# Ubuntu / Debian
sudo apt install golang-go
# أو نزّل الحزمة الرسمية من https://go.dev/dl/ثم:
go install github.com/Devehab/linko@latestهذه الخطوة التي تتعثّر فيها الأغلبية. القاعدة في سطر واحد:
توكن واحد، صلاحيتان معًا. ليس توكنًا للـ DNS وآخر للنفق — بل توكن واحد يحمل الاثنتين. وكلتاهما Edit لا Read.
١. افتح dash.cloudflare.com/profile/api-tokens ← Create Token ← انزل إلى أسفل الصفحة واختر Create Custom Token.
٢. في قسم Permissions أضف السطرين. اضغط + Add more لإضافة الثاني:
| # | الأول | الثاني | الثالث |
|---|---|---|---|
| ١ | Zone |
DNS |
Edit |
| ٢ | Account |
Cloudflare Tunnel |
Edit |
٣. حدّد الموارد:
- Account Resources ← اختر حسابك
- Zone Resources ←
Include→Specific zone→ دومينك
⚠️ إن تركت Zone Resources فارغًا فسيتصل التوكن بنجاح لكنه لن يرى أي دومين، وستحصل علىno zone named ….
٤. اضغط Continue to summary ← Create Token، وانسخ الرمز — يُعرض مرة واحدة فقط.
linko initيسألك ثلاثة أسئلة فقط: الرمز، الدومين، اسم النفق. اضغط Enter لقبول الافتراضي.
Cloudflare credentials
Cloudflare API token: (مخفي أثناء الكتابة)
✓ Cloudflare connected
Domain
Domain: [example.com]
✓ DNS zone found (example.com)
Base subdomain: [example.com]
✓ URLs will look like https://abc12.example.com
Tunnel
Tunnel name: [example-linko-tunnel]
✓ Tunnel created
✓ Configuration saved to ~/.linko/config.json
✓ cloudflared installed
You're ready.عند سؤال Base subdomain اترك الإجابة على الدومين نفسه: example.com.
لا تكتب demo.example.com — السبب في القسم التالي.
export LINKO_API_TOKEN='...'
linko init --yes --domain example.com --base example.comشهادة Cloudflare المجانية تُصدَر لاسمين اثنين فقط:
example.com ← الجذر
*.example.com ← مستوى واحد
و* في الشهادات لا تعبر النقطة — تطابق تسمية واحدة فقط:
| الرابط | يعمل؟ |
|---|---|
demo.example.com |
✅ يطابق *.example.com |
demo.app.example.com |
❌ مستويان — لا شهادة تغطيه |
⚠️ هذا أصعب عطل في التشخيص كله. الـ DNS صحيح، والنفق متصل، وlinko doctorأخضر بالكامل — ومع ذلك يرفض المتصفح الاتصال بـERR_SSL_VERSION_OR_CIPHER_MISMATCH، لأن الرفض يحدث قبل وصول أي طلب إلى نفقك. لهذا يحذّركlinko initمنه مسبقًا.
تريد مستويين؟ يلزمك Advanced Certificate Manager من Cloudflare (١٠ دولارات شهريًا للدومين) ثم تفعيل Total TLS. البدائل المجانية (Subdomain setup، إعداد CNAME جزئي) محصورة بخطط Enterprise وBusiness.
الأبسط والمجاني: اجعل التمييز في الاسم نفسه —
myapp-dev.example.com بدلًا من myapp.dev.example.com.
شغّل مشروعك أولًا، ثم:
linko 3000أهم قاعدة: كل منفذ يملك رابطًا واحدًا ثابتًا. أوقف بـ Ctrl+C وشغّل الأمر
نفسه غدًا — يعيد لك نفس الرابط، لا رابطًا جديدًا. الرابط الذي أرسلته لزميلك
يبقى يعمل، ولا تتراكم سجلات DNS في حسابك.
linko 3000 # أول مرة: يولّد x92ka.example.com
linko 3000 # كل مرة بعدها: نفس x92ka.example.com
linko 3000 --new # تريد رابطًا جديدًا؟ يولّده ويحذف القديم
linko 3000 --name crm # تريد اسمًا محددًا؟ crm.example.com
linko 3000 --temp # رابط لمرة واحدة، يُحذف عند الإيقافأغلق الطرفية والنفق يبقى شغالًا:
linko 3000 -d # يشتغل بالخلفية ويرجعك للسطر فورًا
linko ps # ماذا يعمل الآن؟
linko stop crm # أوقفه
linko stop --all # أوقف كل شيءlinko service install 3000 --name crm # يعمل تلقائيًا عند كل إقلاع
linko service list
linko service uninstall crmعلى macOS يسجّل الأداة في launchd، وعلى لينكس في systemd --user، ويعيد
تشغيلها تلقائيًا إن توقفت.
linko 3000 --openينتظر حتى يستجيب الرابط فعلًا ثم يفتحه — لا يفتح صفحة خطأ لأن DNS لم ينتشر بعد.
| الأمر | الوظيفة |
|---|---|
linko init |
الإعداد لمرة واحدة |
linko 3000 |
نشر المنفذ — نفس الرابط في كل مرة |
linko 3000 --new |
رابط عشوائي جديد بدل القديم |
linko 3000 --name crm |
اسم تختاره أنت |
linko 3000 --temp |
رابط مؤقت يُحذف عند الإيقاف |
linko 3000 -d |
تشغيل بالخلفية |
linko 3000 --open |
يفتح المتصفح عند جاهزية الرابط |
linko ps |
ما الذي يعمل بالخلفية |
linko stop crm |
إيقاف نفق بالخلفية |
linko list |
عرض روابطك |
linko status |
حالة النفق وعدد الاتصالات |
linko remove crm |
حذف رابط (المسار + سجل DNS) |
linko remove --all |
حذف كل الروابط |
linko service install 3000 -n crm |
يبدأ مع الجهاز |
linko doctor |
فحص شامل للإعداد |
linko docs |
هذا الدليل في الطرفية |
| ما تكتبه | ما يعنيه |
|---|---|
linko 3000 |
http://localhost:3000 |
linko 127.0.0.1:8080 |
عنوان محدد |
linko https://localhost:8443 |
أصل يعمل بـ HTTPS |
# نافذة طرفية لكل مشروع
linko 3000 -n web
linko 8080 -n apiكلاهما يمرّ عبر نفس النفق.
كل ما يلي أخطاء حقيقية ظهرت أثناء التطوير، وهذه أسبابها الفعلية.
السبب: التوكن ينقصه صلاحية Zone، أو أن Zone Resources فيه فارغة.
الحل: أضف Zone → DNS → Edit مع Zone Resources → Include → Specific zone → دومينك.
linko يعرض لك النطاقات التي يراها التوكن فعلًا، فتعرف فورًا أين الخلل.
السبب: صلاحية DNS مضبوطة على Read بدل Edit. العثور على الدومين يحتاج قراءة
فقط، لذلك يمر الإعداد كاملًا ثم يفشل عند أول كتابة.
الحل: غيّر القائمة المنسدلة من Read إلى Edit.
السبب: التوكن يغطي DNS فقط ولا يملك صلاحية النفق.
الحل: أضف Account → Cloudflare Tunnel → Edit على نفس التوكن.
السبب: رابطك بعمق مستويين. لا شهادة مجانية تغطيه.
الحل: أعد الإعداد بـ linko init --force --base example.com.
السبب: شغّلت linko init --yes بلا رمز.
الحل: export LINKO_API_TOKEN='...' قبل الأمر، أو مرّر --token '...'.
السبب: مجلد التثبيت ليس في مسارك.
الحل: أعد فتح الطرفية، أو exec $SHELL. المثبّت يضيف السطر تلقائيًا.
السبب: النفق يعمل لكن لا شيء يستمع على المنفذ.
الحل: تأكد بـ curl http://localhost:3000. وإن كان تطبيقك يستمع على 127.0.0.1
فقط، جرّب linko 127.0.0.1:3000.
linko doctorيفحص ثمانية أشياء بالترتيب — من وجود cloudflared إلى الاتصالات الحيّة — ويقول لك
أين توقّف بالضبط.
linko remove --all --yes
rm -rf ~/.linko
linko initlinko ينشئ نفقًا واحدًا في حسابك، وكل مشروع يصبح اسمًا داخله موجّهًا إلى منفذ مختلف.
crm.example.com ──┐
│ ┌──▶ localhost:3000
api.example.com ──┼──▶ Cloudflare Edge ─┼──▶ localhost:8080
│ (نفق واحد) │
test.example.com ──┘ └──▶ localhost:5173
▲
│ اتصال صادر فقط
cloudflared على جهازك
عند تشغيل linko 3000 تحدث ثلاثة أشياء: يُنشأ سجل CNAME يشير إلى نفقك، وتُضاف
قاعدة توجيه تربط الاسم بـ localhost:3000، ثم يُشغَّل cloudflared فيفتح اتصالًا
صادرًا نحو Cloudflare. لا شيء على جهازك ينتظر اتصالات واردة — لهذا لا تحتاج
لمسّ الراوتر أو جدار الحماية.
- الرابط عام. أي شخص يملكه يصل إلى مشروعك. لا تنشر بيانات حساسة. للحماية أضف Cloudflare Access من لوحة Zero Trust.
- الرمز محفوظ في
~/.linko/config.jsonبصلاحيات0600— لا ترفعه إلى Git. للفرق وCI استخدمLINKO_API_TOKEN. - لا يحذف سجلًا ليس له. إن كان الاسم يشير إلى موقعك الحقيقي فلن يلمسه
linko.
github.com/Devehab/linko · رخصة MIT