شغّل Relayium كخدمة استقبال دائمة التشغيل
آخر تحديث: 2026-08-06
يتعامل relayium serve --once مع عملية نقل واردة واحدة ثم يخرج — وهذا مناسب لعملية سحب لمرة واحدة. لكن إذا أردت أن تكون آلة ما نقطة إنزال دائمة — خادم منزلي تصل إليه النسخ الاحتياطية ليلًا، أو آلة بناء يدفع إليها CI منتجاتها، أو NAS يستطيع هاتفك إرسال الصور إليه في أي وقت — فأنت تريد أن يظل serve قيد التشغيل طوال الوقت، لا أن يُشغَّل يدويًا لكل عملية نقل.
يغطّي هذا الدليل بدء مُستمِع طويل التشغيل، والموافقة على من يُسمَح له بالدفع إليه، والتفويض المسبق للنظراء في الحالات التي لا يكون فيها أحد أمام الطرفية، وتشغيله تحت systemd، والسماح لمُرسِل يستخدم sync --delete بأن يعكس عمليات الحذف.
قبل أن تبدأ
كل ما يلي هو relayium CLI، فثبّته أولًا إن لم تكن قد فعلت. على macOS وLinux، يُسقط أمر واحد ملفًا ثنائيًا مُسبق البناء في PATH الخاص بك:
curl -fsSL https://relayium.com/install.sh | sh
- تفضّل اختيار الملف بنفسك، أو تعمل على Windows؟ احصل على ملف ثنائي من صفحة الإصدارات — يسرد relayium.com/cli كل خيارات التثبيت (أو go build -o relayium ./cmd/relayium إن كان لديك Go).
- يؤكّد relayium --version أنه مثبَّت. تخطَّ هذا وستطبع الأوامر أدناه ‘command not found’ لا غير.
ابدأ المُستمِع
ما تحتاجه قبل الخطوة 1
- الـ CLI على الجهازين معًا. يطبع relayium version سطر إصدار على كلٍّ منهما، وإذا ردّت الصدفة بـ command not found فهو غير مثبَّت هناك بعد.
- دليل للملفات الواردة على هذا الجهاز، ومساحة قرص تكفي لما سيصل إليه.
- عنوان يستطيع المرسِل الوصول إليه، ومنفذ وارد مفتوح. وما لم تمرّر --port فإن serve يُنصِت على 9031.
- إن كان هذا الجهاز سيعمل بلا طرفية — وهذا هو مغزى تحويله إلى خدمة — فستحتاج بصمة المرسِل مسبقًا. لها قسم كامل أدناه، وهي أكثر الأسباب شيوعًا لرفض المستقبِل الدائم كلَّ شيء.
يستمع serve إلى عمليات الدفع بأسلوب daemon direct (relayium://host:port) عبر اتصال TLS 1.3 مثبَّت ويكتب ما يستقبله في مجلد. لا حاجة إلى مشاركة أي شيء مسبقًا لبدئه — لا بصمات لنسخها، ولا خادم للتسجيل فيه:
relayium serve --dir ~/inbox
relayium serve --dir /srv/drop --port 9040 # منفذ غير افتراضي
relayium serve --dir ~/inbox --allow-delete # السماح لمُرسِل يستخدم sync --delete بعكس عمليات الحذف
اختر مكان وصول الملفات وشغّل المُنصِت. لا شيء يحتاج إلى مشاركة مسبقة حتى هذه النقطة.
relayium serve --dir ~/inboxمن الجهاز المرسِل، ادفع ملفًا إلى هذا المضيف عبر عنوان relayium:// الخاص به.
relayium push ./report.pdf relayium://drop.example.com:9031عد إلى المستقبِل وأجب عن طلب الموافقة. الإجابة y تكتب البصمة في authorized_fingerprints، فلا يُسأل عن الدفعات التالية من الجهاز نفسه مطلقًا.
تأكّد أن الملف وصل فعلًا إلى --dir وليس إلى الدليل الذي شغّلت منه serve.
ls -l ~/inbox
كيف يبدو مُنصِت يعمل بشكل صحيح
يعلن serve منذ البداية أنه بلا أقران مُصرَّح لهم، ثم يسأل عند أول دفعة من جهاز جديد ويصمت في كل ما بعدها. ينتهي المرسِل بالرمز 0 ويكون الملف داخل --dir.
$ relayium serve --dir ~/inbox
no authorized peers yet — you'll be asked to approve each new peer on its first push.
Incoming push from 203.0.113.7:54021
fingerprint: 74318e3b…
Accept and remember this peer? [y/N] y- --dir يحدد المكان الذي تصل إليه الملفات (الافتراضي هو المجلد الحالي).
- --port يحدد منفذ الاستماع (الافتراضي هو 9031)؛ افتحه في جدار الحماية إذا كان المُرسِل في مكان آخر.
- بدون --once، يظل serve قيد التشغيل ويقبل عمليات الدفع حتى توقفه أنت أو يعيد مدير عمليات تشغيله — وهذا ما يجعله خدمة دائمة التشغيل.
وافق على من يُسمَح له بالدفع
في أول مرة يدفع فيها نظير جديد، يعرض لك serve — إن كان يعمل في طرفية — من أين أتت الدفعة وبصمتها ويطلب منك الموافقة عليها، بالطريقة نفسها التي يسأل بها SSH عن مضيف مجهول عند أول اتصال:
Incoming push from 203.0.113.7:54021
fingerprint: 74318e3b…
Accept and remember this peer? [y/N] y
- أجب بـ y مرة واحدة، فتُكتَب تلك البصمة في authorized_fingerprints؛ وتمرّ كل دفعة لاحقة من الآلة نفسها دون أي مطالبة.
- تُعرّف البصمة آلةً لا عنوان شبكة، لذا تبقى صالحة حتى لو تغيّر عنوان IP الخاص بالمُرسِل.
- هذه الخطوة تفاعلية بحكم التصميم — تحتاج إلى شخص أمام لوحة المفاتيح، وهو ما لن يتحقق بمجرد انتقال serve إلى systemd (التالي).
فوّض النظراء مسبقًا للإعدادات غير التفاعلية
حين لا يملك serve طرفيةً يطالب عليها — خدمة systemd، أو عملية في الخلفية، أو أنبوب — فإنه لا يستطيع السؤال، ولذلك يرفض أي بصمة لا يعرفها مسبقًا. بدلًا من ذلك، فوّض النظراء مسبقًا. على الآلة التي ستدفع، شغّل relayium id لطباعة بصمتها؛ وعلى المُستقبِل، أضِفها قبل وصول أول دفعة:
# على الآلة التي ستدفع: اطبع بصمتها
relayium id
# على هذا المُستقبِل الدائم التشغيل: فوّضها مسبقًا
relayium authorize 74318e3b...
على الجهاز الذي سيدفع، اطبع بصمته. إنها 64 حرفًا ست عشريًا وتُعرِّف الجهاز نفسه لا عنوانه.
relayium idصرّح له على هذا المستقبِل — بالـ --config-dir نفسه الذي ستعمل به الخدمة. فالتصريح بمستخدم آخر، أو بالمسار الافتراضي بينما تستعمل الوحدة مسارًا غيره، يكتب البصمة في ملف لا تقرؤه الخدمة أبدًا.
relayium authorize 74318e3b… --config-dir /etc/relayium
- authorize عملية عديمة الأثر عند التكرار (idempotent) — تشغيلها مجددًا لبصمة تثق بها مسبقًا لا يفعل شيئًا.
- توجد ملفات الهوية والثقة ضمن --config-dir، وقيمته الافتراضية ~/.config/relayium (id.key/id.crt هي هوية هذا المضيف، وauthorized_fingerprints هي قائمة السماح للنظراء).
شغّله تحت systemd
للحصول على خدمة تصمد أمام عمليات إعادة التشغيل والأعطال، سلّم serve إلى systemd. وجّه --config-dir إلى مسار ثابت حتى تبقى هوية المضيف وقائمة نظرائه المفوَّضين في مكانها عبر عمليات إعادة التشغيل:
# /etc/systemd/system/relayium-serve.service
[Unit]
Description=Relayium always-on receiver
After=network-online.target
[Service]
ExecStart=/usr/local/bin/relayium serve --dir /srv/drop --port 9031 --config-dir /etc/relayium --allow-delete
Restart=always
User=relayium
[Install]
WantedBy=multi-user.target
صرّح لكل قرين يُفترض أن يستطيع الدفع، قبل وجود الخدمة أصلًا. فهي لا تستطيع السؤال، وكل ما ليس موثوقًا سلفًا مرفوض.
اكتب ملف الوحدة أعلاه في /etc/systemd/system/relayium-serve.service، بحيث يشير --config-dir إلى المسار الثابت نفسه الذي صرّحت تحته.
أعد تحميل systemd وشغّل الخدمة، مع تفعيلها لتعود بعد إعادة التشغيل.
sudo systemctl daemon-reloadsudo systemctl enable --now relayium-serveتأكّد أنها تعمل وأن التحذير الذي يرفض كل شيء غائب عن السجل. والثاني وحده هو الخاص بهذا الإعداد.
systemctl is-active relayium-servejournalctl -u relayium-serve -n 20 --no-pager
كيف تبدو خدمة تعمل بشكل صحيح
يجيب is-active بـ active، ولا يظهر تحذير الإقلاع عن غياب الأقران المُصرَّح لهم. وذلك التحذير هو السطر الوحيد الذي يخبرك، قبل أن يشتكي أي مرسِل، أن هذه الخدمة سترفض كل دفعة.
$ systemctl is-active relayium-serve
active
$ journalctl -u relayium-serve -n 20 --no-pager | grep -c 'all pushes will be rejected'
0- قبل تمكين الخدمة، شغّل relayium authorize <fingerprint> لكل نظير ينبغي أن يكون قادرًا على الدفع — فالخدمة نفسها لا تستطيع المطالبة.
- systemctl enable --now relayium-serve يشغّلها ويعيدها عند كل إقلاع.
- اجعل /etc/relayium/id.key قابلًا للقراءة من مستخدم الخدمة فقط؛ فـ relayium يرفض تحميل مفتاح ذي أذونات أكثر تساهلًا.
شغّله عند الإقلاع على macOS (launchd)
لا يملك macOS نظام systemd — فمدير خدماته هو launchd. لإبقاء serve قيد التشغيل على جهاز Mac (مثلًا Mac mini مُبقى مشغّلًا كنقطة إنزال)، ثبّته كـ LaunchDaemon حتى يبدأ عند الإقلاع، قبل أن يسجّل أحد الدخول. اضبط UserName حتى يعمل باسمك لا باسم root، وامنح --dir و--config-dir مسارات مطلقة حتى تبقى ملفات هويته وثقته في ~/.config/relayium الخاص بك:
<!-- /Library/LaunchDaemons/com.relayium.serve.plist (replace YOU with your macOS username) -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key> <string>com.relayium.serve</string>
<key>UserName</key> <string>YOU</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/relayium</string>
<string>serve</string>
<string>--dir</string> <string>/Users/YOU/inbox</string>
<string>--port</string> <string>9031</string>
<string>--config-dir</string> <string>/Users/YOU/.config/relayium</string>
<string>--allow-delete</string>
</array>
<key>RunAtLoad</key> <true/>
<key>KeepAlive</key> <true/>
<key>StandardOutPath</key> <string>/Users/YOU/relayium-serve.log</string>
<key>StandardErrorPath</key> <string>/Users/YOU/relayium-serve.log</string>
</dict>
</plist>
# 1) authorize each pusher first — launchd gives serve no terminal to prompt on:
relayium authorize <fingerprint> # get the fingerprint from the pusher's relayium id
# 2) save the plist above to that path, then load it (root-owned, starts at boot):
sudo chown root:wheel /Library/LaunchDaemons/com.relayium.serve.plist
sudo launchctl bootstrap system /Library/LaunchDaemons/com.relayium.serve.plist
# check it's running / follow logs / stop it:
sudo launchctl print system/com.relayium.serve | grep state
tail -f ~/relayium-serve.log
sudo launchctl bootout system/com.relayium.serve
- لا يمنح launchd الخادم serve أي طرفية، فلا يستطيع المطالبة — شغّل relayium authorize <fingerprint> لكل جهة تدفع أولًا، تمامًا كما مع systemd. تأتي البصمة من relayium id الخاص بتلك الآلة.
- يعيد KeepAlive تشغيل serve إذا تعطّل؛ ويبدأه RunAtLoad مع LaunchDaemon في /Library/LaunchDaemons عند الإقلاع دون تسجيل دخول — وهو الخيار المناسب لجهاز Mac mini بلا شاشة.
- أتريد خدمة على نطاق تسجيل الدخول بدلًا من ذلك؟ ضع الـ plist نفسه (مع إسقاط مفتاح UserName) في ~/Library/LaunchAgents/ وحمّله بـ launchctl bootstrap gui/$(id -u) <path> — يبدأ عند تسجيل دخولك لا عند الإقلاع.
- إذا كان جدار حماية تطبيقات macOS مفعّلًا، فاسمح بالاتصالات الواردة لـ relayium (إعدادات النظام ← الشبكة ← جدار الحماية)، وإلا فستُحجَب عمليات الدفع إلى منفذك.
اسمح لمُرسِل يستخدم sync --delete بعكس عمليات الحذف
افتراضيًا، لا يقوم serve إلا بإضافة الملفات أو تحديثها — فالمُرسِل الذي يشغّل sync --delete تجاهه لا يزال ينسخ الملفات الجديدة والمتغيّرة، لكن أي عمليات حذف يطلبها تُتخطّى، مع تسجيل تحذير على المُستقبِل. شغّل serve مع --allow-delete للاشتراك في النسخ المطابق الحقيقي، حيث تُحذَف هنا أيضًا الملفات المحذوفة على جانب المُرسِل:
relayium serve --dir /srv/mirror --allow-delete
- --allow-delete اشتراك اختياري على جانب المُستقبِل؛ ولا يزال على المُرسِل أن يطلبه بـ sync --delete.
- بدونه، لا يُحذَف أي شيء أبدًا على هذه الآلة، مهما طلب المُرسِل.
حين لا ينجح الأمر
في أربع من هذه الإخفاقات الخمسة تبقى الخدمة تعمل وتبدو سليمة — فالمُنصِت الذي يرفض كل شيء يظل مُنصِتًا. ولكلٍّ منها سطر تقرؤه أو أمر تشغّله يحسم المسألة.
العَرَض، الفحص، الإصلاح
- تبدأ الخدمة وتظل تعمل، لكن كل دفعة تُرفَض.
journalctl -u relayium-serve -n 20 --no-pager # warning: no authorized peers and no terminal to approve on; all pushes will be rejected.الخدمة بلا طرفية، فلا يمكنها أبدًا تنفيذ طلب الموافقة عند أول دفعة، وكل ما تراه بصمة مجهولة. صرّح لكل مرسِل مسبقًا: relayium id على الجهاز المرسِل، وrelayium authorize <البصمة> هنا، بالـ --config-dir نفسه المستخدَم في الوحدة. وهذا التحذير يُطبع عند الإقلاع، فهو موجود في السجل من سطره الأول.
- لا تبدأ الخدمة إطلاقًا وتشتكي من أذونات غير آمنة على id.key.
stat -c '%a %U %n' /etc/relayium/id.key # 400 relayium /etc/relayium/id.keyيجب أن تكون أذونات المفتاح 0600 بالضبط. ليس 0644، والأهم — وهنا يقع أكثر الناس — ليس 0400 أيضًا، فتشديدها أكثر يعطّل الخدمة بالقدر نفسه الذي يعطّلها به تخفيفها. نفّذ chmod 600 على المفتاح وتأكّد أن مالكه هو المستخدم المحدَّد في User= داخل الوحدة.
- يبلّغ المرسِل بأن الاتصال قد رُفِض.
relayium push ./build relayium://drop.example.com:9031 # hint: if the peer refused the connection, it may not have authorized this host.المستقبِل لا يعرف هذا المرسِل. شغّل relayium id على المرسِل، وصرّح لتلك البصمة على المستقبِل بـ relayium authorize. وإن كنت فعلت ذلك سلفًا فتحقّق أنك فعلته تحت --config-dir الخاص بالوحدة: فملف الثقة مرتبط بالدليل، والبصمة المُصرَّح بها في ~/.config/relayium غير موجودة أصلًا بالنسبة لخدمة تقرأ /etc/relayium.
- الدفع ينجح حين تشغّل serve يدويًا، لكنه يفشل عبر الخدمة أو من جهاز آخر.
sudo ss -tlnp | grep 9031سببان مختلفان يفصل بينهما فحص واحد. إن لم يكن هناك أي إنصات فالوحدة غير مفعَّلة — استخدم systemctl is-enabled relayium-serve. وإن كانت تُنصِت فالمنفذ مغلق: افتح 9031 في جدار حماية المضيف وفي أي مجموعة أمان سحابية. وأي --port غير افتراضي يجب أن يطابق المنفذ في relayium://host:N لدى المرسِل.
- عمليات الحذف التي يطلبها مرسِل sync --delete لا تحدث على هذا الجهاز أبدًا.
journalctl -u relayium-serve | grep -i deleteالحذف اختيار يفعّله الطرف المستقبِل وهو معطَّل افتراضيًا: الملفات الجديدة والمعدَّلة تُنسخ كالمعتاد، وكل عملية حذف متخطَّاة تُسجَّل هنا كتحذير. أضف --allow-delete إلى ExecStart في الوحدة وأعد التشغيل. ولا يكفي أن يطلبها المرسِل، وهذا التفاوت مقصود — فالمستقبِل لا يفقد ملفات بسبب راية كُتبت في مكان آخر.
الأسئلة الشائعة
ما المنفذ الذي يستمع إليه serve افتراضيًا؟
9031. غيّره بـ --port على كلٍّ من المُستمِع (serve --port N) وهدف الجهة الدافعة (relayium://host:N).
هل عليّ الموافقة على كل دفعة يدويًا؟
الدفعة الأولى فقط من بصمة معيّنة، وفقط حين يعمل serve مع طرفية موصولة. وتُحفَظ بعد ذلك. أما تشغيل serve بشكل غير تفاعلي (systemd، أو أنبوب) فيتخطّى المطالبة كليًا ويرفض النظراء المجهولين — ففوّضهم مسبقًا بـ relayium authorize بدلًا من ذلك.
هل يستطيع مُرسِل حذف ملفات على مُستقبِلي الدائم التشغيل؟
فقط إذا بدأت serve بـ --allow-delete وكان المُرسِل يشغّل sync --delete. بدون --allow-delete، تُتخطّى عمليات الحذف بصمت وينتقل كل شيء آخر كالمعتاد.
هل تشغيل مُستقبِل دائم التشغيل مجاني؟
نعم. relayium serve جزء من واجهة سطر الأوامر (CLI) المجانية القابلة للاستضافة الذاتية — بلا حساب، وبلا فئة مدفوعة، على أي من طرفي الاتصال.
أين يحفظ serve هويته وقائمة نظرائه؟
في ~/.config/relayium افتراضيًا (id.key/id.crt لهوية هذا المضيف، وauthorized_fingerprints لقائمة السماح). وجّه --config-dir إلى مكان ثابت، مثل /etc/relayium، لخدمة systemd.
كيف أشغّل serve عند الإقلاع على macOS؟
لا يملك macOS نظام systemd — استخدم launchd. ثبّت serve كـ LaunchDaemon في /Library/LaunchDaemons (يبدأ عند الإقلاع؛ اضبط UserName ليعمل باسمك)، أو كـ LaunchAgent في ~/Library/LaunchAgents (يبدأ عند تسجيل الدخول). يحتوي هذا الدليل على ملف plist جاهز للتحرير؛ ولا توجد خدمة Homebrew. فوّض الجهات الدافعة مسبقًا بـ relayium authorize أولًا، لأن launchd لا يمنح serve أي طرفية للمطالبة عليها.
حوّل أي آلة تملكها إلى مُستقبِل مجاني دائم التشغيل — عمليات دفع مباشرة عبر TLS مثبَّت، دون أي مُرحِّل.
احصل على واجهة سطر الأوامر (CLI)