
شغّل Firefox في حاوية Podman rootless مع إسقاط الصلاحيات (capabilities)، وعزل الشبكة، وتخزين مؤقت (ephemeral) لاحتواء محاولات الهروب من بيئة العزل (sandbox) ومنع اختراق المضيف.
قم بتشغيل Firefox في حاوية Podman بدون صلاحيات الجذر لعزل الأمان. يعمل متصفحك بدون أي صلاحيات Linux تقريبًا، في مساحة مستخدم وشبكة خاصة به، معزولًا عن المضيف — بينما لا يزال يتمتع بتسريع GPU كامل، وصوت، ودعم DRM.
يمتلك Firefox بالفعل صندوق رمل متعدد العمليات يعزل عارضات محتوى الويب باستخدام مساحات أسماء Linux وseccomp-bpf. بالنسبة لمعظم التهديدات، هذا فعال. يضيف foxcage جدارًا ثانيًا: إذا استغل مهاجم ثغرة تهرب من صندوق رمل Firefox (وهذا يحدث — توجد CVEs لهذا)، فسيستقر داخل حاوية مقفلة بدلاً من جلسة المستخدم الكاملة.
~/.ssh، ~/.gnupg، ملفات تعريف المتصفح للمتصفحات الأخرى، قواعد بيانات مدير كلمات المرور، المستندات، الكود المصدري. في foxcage، يرى المهاجم فقط ما قمت بتركيبه صراحةً.@tmp المؤقت لا يترك أي أثر على القرص بعد إغلاق النافذة — بما في ذلك الإضافات، حالة HSTS، ذاكرة التخزين المؤقت لجلسة TLS، وذاكرة التخزين المؤقت لـ DNS التي لا يزال Firefox في التصفح الخاص يحتفظ بها. تعمل أقفاص @tmp المتعددة بشكل متزامن دون التداخل مع بعضها البعض.~/.config/autostart، ~/.bashrc، cron، أو أي مكان آخر للبقاء بعد إعادة التشغيل. الحاوية المؤقتة لـ foxcage (--rm) تعني أن لا شيء يستمر ما لم تقم بتركيبه عبر bind.localhost. على Firefox العاري، يمتلك هروب صندوق الرمل وصولًا كاملًا للشبكة. (استخدم [network] mode = "host" إذا كان القفص يحتاج وصولًا إلى localhost، مثل التطوير المحلي — ولكن راجع التحذير تحت "الشبكات": وضع المضيف يكشف أيضًا مآخذ Unix المجردة للمضيف.)CAP_SYS_CHROOT وتمنع اكتساب امتيازات جديدة. ثنائيات Setuid، استغلالات النواة عبر استدعاءات النظام الغامضة، ومسارات التصعيد المماثلة مقطوعة.profile، downloads_dir، تركيبات bind إضافية) يمكن الوصول إليه بالكامل من قبل متصفح مخترق. إذا قمت بتركيب دليل ملف تعريف مضيف، يمكن للمهاجم العبث به تمامًا كما هو الحال على Firefox العاري.تعمل الحاوية مع:
CAP_SYS_CHROOT يُعاد إضافتها لصندوق رمل محتوى Firefox؛ CAP_SETUID/CAP_SETGID تُضاف مؤقتًا عند تكوين init.root)no-new-privileges لمنع تصعيد الامتيازات--userns keep-id)/dev/shm خاص (غير مشترك مع المضيف) — حجم قابل للتكوين عبر shm_sizenetwork.dns)XDG_RUNTIME_DIR تُركب عبر bind (Wayland، PulseAudio، PipeWire، ووكيل D-Bus المفلتر) — دليل وقت التشغيل الكامل للمضيف لا يُكشف أبدًاxdg-dbus-proxy مفلتر يعمل على المضيف. فقط org.freedesktop.Notifications، ، ، و(للفروع) مساحة اسم الفرع نفسه (مثل ) قابلة للوصول — خدمات الجلسة مثل keyring ووكيل SSH/GPG محظورةكل خيار [network] و [mounts] تقوم بتمكينه يقايض بعض العزل من أجل الراحة. الافتراضيات هي التكوين الأكثر تقييدًا الذي لا يزال يمنحك متصفحًا قابلاً للاستخدام.
sudo apt install passt) — ما لم يكن network.mode = "host"sudo apt install xdg-dbus-proxy)/dev/dri يحذر foxcage ويعرض Firefox برمجيًا. يتم تثبيت برامج تشغيل VA-API لـ Intel وAMD وnouveau في الصورة، لذا يعمل فك تشفير الفيديو عبر الأجهزة بدون حزم برامج تشغيل المضيف — راجع فك تشفير الفيديو عبر الأجهزةشغّل foxcage كمستخدم سطح مكتب عادي، وليس كجذر أو عبر sudo — يقوم الصندوق الرملي بتعيين مستخدمك في الحاوية، والتشغيل كجذر يزيل العزل الذي يوجد foxcage لتوفيره. يرفض البدء كجذر.
البيئة المختبرة: Debian 13 (Trixie) مع GNOME 3. قد تعمل توزيعات Linux الأخرى وWayland compositors الأخرى ولكن لم يتم اختبارها.
foxcage هو سكربت Python واحد بدون تبعيات خارج المكتبة القياسية لـ Python. انسخه إلى دليل في PATH الخاص بك:```sh
sudo cp foxcage /usr/local/bin/foxcage
أو للتثبيت المحلي للمستخدم:```sh
cp foxcage ~/.local/bin/foxcage
تأكد من أن السكربت قابل للتنفيذ (chmod +x foxcage).
تحقق من الإصدار الذي لديك باستخدام foxcage --version — مفيد عند الإبلاغ عن مشكلة، حيث يتم تثبيت foxcage عن طريق نسخ ملف واحد.
./foxcage
عند التشغيل الأول، يقوم السكربت ببناء صورة الحاوية (يقوم بتنزيل Firefox من Mozilla، وتثبيت الحد الأدنى من تبعيات Debian) ثم يبدأ تشغيل Firefox. في عمليات التشغيل اللاحقة، يتحقق foxcage من تحديثات Firefox ويعيد بناء الصورة تلقائيًا عند توفر إصدار جديد. كما يتم إعادة بناء الصورة بشكل دوري (كل 7 أيام افتراضيًا) لالتقاط تحديثات حزم النظام. إذا فشل فحص التحديث (خطأ في الشبكة، انتهاء المهلة)، يتم تسجيل تحذير واستخدام الصورة الموجودة — لا يتم حظر بدء التشغيل أبدًا.
مرر الوسائط إلى Firefox:```sh
./foxcage https://example.com
اجمع قفصًا مسمّىً مع أعلام Firefox:```sh ./foxcage @work --kiosk https://example.com
إذا كان القفص (cage) يعمل بالفعل، يُفتح الرابط في تبويب جديد داخل المتصفح الموجود بدلاً من تشغيل حاوية ثانية. تشغيل `foxcage` (أو `foxcage @cage`) بدون رابط ضد قفص يعمل يخرج بنجاح مع رسالة "القفص يعمل بالفعل" — لا يمكن لـ foxcage رفع نافذة Wayland موجودة من خارج الحاوية، لذلك لا يحاول ذلك.
لا تنطبق خيارات التشغيل لكل إطلاق (**per-launch flags**) عندما يكون القفص يعمل بالفعل. يتم استهلاك `--dns` و`--ipv4-only` و`--lifetime` و`--color` و`--fork` عند بدء تشغيل الحاوية، ولا يمكن تغيير إعدادات الحاوية قيد التشغيل من الخارج، لذلك يتم تجاهلها مع تحذير. أغلق القفص وأعد تشغيله لتطبيقها.
> استخدم مفتاح الإعداد `private_browsing` لجلسات الوضع الخاص — *وليس* خيار سطر الأوامر الخام `--private-window` الخاص بـ Firefox. يضبط مفتاح الإعداد الوضع الخاص على مستوى الجلسة (`browser.privatebrowsing.autostart`)، بحيث يمكن لاستدعاءات `foxcage @cage URL` اللاحقة إعادة الفتح في تبويبات. `--private-window` كتمرير مباشر لـ Firefox سيجعل النافذة الأولى فقط خاصة وسيكسر سلوك إعادة الفتح في التبويب أعلاه.
>
> **تنبيه:** الجلسات المفعّلة عبر `private_browsing = true` لا تُظهر مؤشرات واجهة النافذة الخاصة المعتادة في Firefox (شريط التمييز البنفسجي، أيقونة القناع، "(Private Browsing)" في العنوان). ذلك لأن كل نافذة في الجلسة خاصة، لذا لا يملك Firefox نافذة غير خاصة للمقارنة البصرية — فهو يخفي المؤشر. الجلسة *خاصة فعلياً*؛ تحقق إذا أردت بزيارة `about:privatebrowsing` داخل القفص (تعرض صفحة معلومات التصفح الخاص القياسية) أو `about:config` والتحقق من `browser.privatebrowsing.autostart = true`.
### التصفح المؤقت مع `@tmp`
للروابط لمرة واحدة التي يجب ألا تترك أي أثر، استخدم القفص المحجوز `tmp`:```sh
./foxcage @tmp https://somewhere-suspicious.example
كل إطلاق @tmp هو نافذة Firefox مؤقتة جديدة تمامًا بدون ملف تعريف دائم. عند إغلاق النافذة، يختفي كل شيء — ملفات تعريف الارتباط، وذاكرة التخزين المؤقت، والسجل، والإضافات، وحالة HSTS، وذاكرة تخزين جلسات TLS المؤقتة، وذاكرة تخزين DNS المؤقتة، وحالة التبويبات المحفوظة. هذا يتجاوز التصفح الخاص في Firefox، الذي لا يزال يحتفظ بالإضافات وجزءًا لا بأس به من الحالة المخزنة على القرص.
تعمل أقفاص @tmp المتعددة في وقت واحد، وكل منها معزول عن الآخرين. يعرض شريط القوائم FoxCage - tmp (<short id>) حتى تتمكن من التمييز بين النوافذ المؤقتة المتزامنة.
تفتح الأقفاص المؤقتة صفحة فارغة عند بدء التشغيل وتبويبات جديدة فارغة — الصفحة الرئيسية الافتراضية لـ Firefox ومحتوى التبويب الجديد (المواقع الأعلى، توصيات Pocket، تدفق النشاط) هي مجرد ضوضاء على ملف تعريف جديد على وشك التخلص منه، لذلك يتم كبتها. تحتفظ الأقفاص الدائمة بإعدادات Firefox الافتراضية.
إذا كنت تريد اسمًا ذا معنى لجلسة مؤقتة (على سبيل المثال، حفرة بحث أرنب سترغب في إعادة فتحها في تبويب جديد)، استخدم @tmp-<name>:```sh
./foxcage @tmp-research https://example.com # first call → new window
./foxcage @tmp-research https://another.example # second call → new tab in the existing window
`@tmp-<name>` لا يزال مؤقتًا — عند إغلاق النافذة، يختفي كل شيء. الفرق عن `@tmp` المجرد هو أن عمليات الإطلاق الثانية بنفس الاسم **تعيد استخدام النافذة الموجودة** (مثل الأقفاص الدائمة)، لذا يمكنك إضافة المزيد من علامات التبويب لاحقًا دون بدء نسخة موازية. يحافظ `@tmp` المجرد على سلوكه "كل إطلاق هو نسخة جديدة تُرمى".
يعرض تسمية شريط القوائم الاسم الذي اخترته (`FoxCage - tmp-research`) بحيث تكون النافذة معنونة بشكل واضح.
#### تخصيص الإعدادات الافتراضية المؤقتة
أنشئ `~/.config/foxcage/tmp.toml` لتعيين الإعدادات الافتراضية لجميع الأقفاص المؤقتة (سواء `@tmp` المجرد أو كل `@tmp-<name>`). على سبيل المثال:```toml
private_browsing = true
lifetime = "30m"
extensions = ["ublock-origin"]
[network]
dns = "cloudflare"
كل إطلاق مؤقت الآن يحصل على نافذة خاصة، وuBlock Origin، وCloudflare DoH، ويُغلق تلقائيًا بعد 30 دقيقة — مع الحفاظ الكامل على الطبيعة المؤقتة. الإطلاقات المؤقتة المسماة ترث tmp.toml افتراضيًا؛ إذا أردت تجاوز ذلك لكل اسم، أنشئ ~/.config/foxcage/tmp-<name>.toml. عندها يُطبَّق هذا الملف بدلًا من tmp.toml — لا دمج، الملف الأكثر تحديدًا يفوز تمامًا. انسخ الإعدادات الافتراضية المشتركة إليه إذا أردتها.
أي شيء يمكنك ضبطه في إعدادات قفص عادي يعمل هنا، باستثناء المفتاح الوحيد الذي قد يُبطل الطبيعة المؤقتة نفسها:
profile — خطأ صارم.إنه يشير إلى دليل ملف تعريف دائم على المضيف، وهو ما يتعارض مباشرةً مع الغرض من @tmp. إذا أردت قفصًا معزولًا بملف تعريف دائم، استخدم قفصًا مسماةً عاديًا (@work، @research، إلخ.) لا يبدأ بـ tmp-.
يمكن أن يحتوي القفص على إضافات مدمجة في صورته ومثبّتة قسريًا عند كل إطلاق:```toml extensions = ["ublock-origin"]
ضع ذلك في `~/.config/foxcage/tmp.toml` و**كل قفص مؤقت يبدأ مع تشغيل uBlock Origin بالفعل** — وهو أمر مهم، لأن القفص المؤقت هو بخلاف ذلك أقل متصفح محمي لديك، ويُستخدم تحديدًا على الروابط التي تثق بها أقل. ملف تعريف `@tmp` الجديد لا يحتوي على أي إضافات على الإطلاق، وتثبيت واحدة يدويًا لا طائل منه في جلسة تُمزق نفسها عند الإغلاق.
يمكن أن يكون كل إدخال هو الاسم المختصر من رابط الإضافة على addons.mozilla.org، أو رابط القائمة نفسه، أو معرّف الإضافة:```toml
extensions = [
"ublock-origin",
"https://addons.mozilla.org/firefox/addon/noscript/",
"[email protected]",
]
الإضافات تُحل عبر واجهة برمجة تطبيقات addons.mozilla.org عند الإطلاق، وتُحمَّل أثناء بناء الصورة، وتُتحقق منها مقابل بصمة SHA-256 التي تنشرها AMO. الإصدار المُحل جزء من ملف Containerfile، لذا فإن إصدارًا جديدًا من إضافة يغيّر تجزئة الصورة ويُطلق إعادة بناء — تتحدّث الإضافات بنفس الطريقة التي يتحدّث بها Firefox، ولنفس السبب: لا يُثبَّت أي شيء في وقت التشغيل، لذا فإن ملف تعريف مؤقت جديد لا يعيد تنزيل أي شيء أبدًا.
لأنها مُثبَّتة بسياسة المؤسسة وليس يدويًا:
about:addons يعرضها كمثبَّتة من قِبل مؤسستك).private_browsing = true. يتطلب هذا Firefox 136 أو ESR 128.8؛ الإصدارات الأقدم تتجاهل الإعداد وتترك الإضافة خاملة في النوافذ الخاصة.القيود:
.xpi مكشوف يُرفض.@tmp وكل @tmp-<name> يبنون صورة foxcage-tmp واحدة، لذا فإن إعطاء قفص مؤقت مُسمّى قائمة extensions مختلفة عن tmp.toml يجعل الاثنين يعيدان البناء فوق بعضهما في عمليات إطلاق متناوبة. أبقِ قوائم الإضافات المؤقتة في tmp.toml.علم --dns (ومفتاح الإعداد المكافئ network.dns) يقبل ثلاثة أشكال:```sh
./foxcage @tmp --dns 1.1.1.1 https://example.com # IP
./foxcage @tmp --dns cloudflare https://example.com # alias
./foxcage @tmp --dns https://dns.nextdns.io/ # custom DoH URI
**عندما تتطابق القيمة مع مزوّد معروف (بواسطة الاسم المستعار أو عنوان IP)، يقوم foxcage تلقائيًا بتمكين DNS القسري عبر HTTPS لهذا المزوّد.** يتم ضبط TRR الخاص بـ Firefox على الوضع 3 (صارم، بدون تراجع إلى النص الصريح) مع تعبئة عنوان bootstrap بحيث لا يكون هناك تسريب دقة غير مشفّر عند بدء التشغيل. سترى إشعارًا من سطر واحد على stderr مثل `Enabling DNS over HTTPS via Cloudflare`.
الأسماء المستعارة المدمجة:
| الاسم المستعار | IP | التصفية |
|-------|------|-----------|
| `cloudflare` | 1.1.1.1 | لا شيء |
| `cloudflare-security` | 1.1.1.2 | يحظر البرامج الضارة |
| `cloudflare-family` | 1.1.1.3 | يحظر البرامج الضارة + المحتوى للبالغين |
| `google` | 8.8.8.8 | لا شيء |
| `quad9` | 9.9.9.9 | يحظر البرامج الضارة (Quad9 الافتراضي) |
| `quad9-unfiltered` | 9.9.9.10 | لا شيء |
| `adguard` | 94.140.14.14 | يحظر الإعلانات + أدوات التتبع |
| `adguard-family` | 94.140.14.15 | الإعلانات + أدوات التتبع + المحتوى للبالغين |
| `opendns` | 208.67.222.222 | بعض |
عنوان IP غير الموجود في الجدول (مثل Pi-hole على شبكتك المحلية) يبقى نصًا صريحًا فقط — لا يتم تمكين DoH، لأن foxcage لا يعرف نقطة نهاية DoH المقابلة. استخدم صيغة URI لذلك: `--dns https://pi.hole/dns-query` (مع شهادة صالحة) تُمكّن DoH وتترك DNS الحاوية كما هو.
صيغة URI تتخطى ضبط DNS النص الصريح للحاوية، لذا أي شيء داخل الحاوية ليس Firefox سيظل يستخدم DNS الخاص بالمضيف. هذا مقصود — `--dns URI` تعني "اجعل Firefox يستخدم محلل DoH هذا"، وانتهى الأمر.
`--dns` غير متوافق مع `network.mode = "host"`، الذي يمتلك بالفعل وصولًا كاملًا لشبكة المضيف.
### تحديد القفص بصريًا
يحصل كل قفص مسمّى على لون مميز في شريط القوائم حتى تتمكن من التمييز بين النوافذ بنظرة واحدة. **لا تحتاج إلى تكوين أي شيء** — يتم اشتقاق اللون حتميًا من اسم القفص (يتم تجزئته عبر SHA256 إلى درجة لونية، مع تشبّع وإضاءة ثابتين). `@banking`، `@work`، `@personal`، `@tmp-research` جميعها تحصل على ألوان مميزة وثابتة دون أن ترفع إصبعك.
القفص الافتراضي (المجهول) يحتفظ باللون البرتقالي المدمج.
إذا كنت تريد تجاوز اللون المشتق تلقائيًا، اضبطه صراحةً:```toml
# ~/.config/foxcage/banking.toml
color = "#dc2626" # red — overrides the auto-derived colour
Since the input is empty, I have nothing to translate. Please provide the chunk content you'd like me to translate.```sh ./foxcage @experiment --color "#10b981" https://example.com # teal, one-off
يقبل ألوان CSS السداسية القياسية: `#rgb`، `#rrggbb`، أو `#rrggbbaa` (مع قناة الشفافية). الألوان المشتقة تلقائيًا مضبوطة لتكون مرئية على أشرطة القوائم الفاتحة والداكنة معًا (الإضاءة مثبتة عند 55%، والتشبع عند 75%)، لذا لا ينبغي أن تحتاج إلى تجاوزها لأسباب تتعلق بالسمة.
### الأقفاص المحدودة زمنيًا
العلامة `--lifetime` (ومفتاح الإعداد المكافئ `lifetime` في ملف الإعداد) تغلق القفص تلقائيًا بعد مدة محددة. الصيغة هي `<رقم><وحدة>` مع وحدة `s` أو `m` أو `h`:```sh
./foxcage @tmp --lifetime 10m https://example.com
./foxcage @work --lifetime 2h
يبدأ العد التنازلي عند إطلاق Firefox فعليًا داخل القفص — وقت بدء تشغيل الحاوية ووقت بناء الصورة لا يُحتسبان من ميزانيتك. تُظهر تسمية شريط القوائم في القفص العد التنازلي بجانب هوية القفص — مثل FoxCage - tmp (a3f2b1) | 9m — ويتم تحديثها مرة واحدة في الدقيقة عندما يتبقى أكثر من دقيقة، ومرة واحدة في الثانية خلال الدقيقة الأخيرة. عندما يصل العد التنازلي إلى الصفر، يُغلق Firefox نفسه وتخرج الحاوية. إذا أغلقت Firefox بنفسك قبل انتهاء العمر الافتراضي، لا يحدث أي شيء غير عادي.
اضبط عمرًا افتراضيًا لكل قفص في إعداده:```toml
lifetime = "15m" private_browsing = true
`--lifetime` في سطر الأوامر يتغلب على أي قيمة في ملف الإعدادات.
فرض إعادة بناء كاملة للصورة (إعادة تنزيل Firefox وجميع حزم النظام):```sh
./foxcage --rebuild
حاوية قيد التشغيل تحتفظ بالصورة التي بدأت منها، حتى بعد أن يعيد foxcage بناء وسم الصورة. إذا حاولت فتح تبويب في قفص (cage) تم تحديث صورته منذ ذلك الحين (عبر --rebuild، أو تحديث Firefox، أو إعادة البناء المجدولة)، يرفض foxcage ذلك مع ظهور خطأ (يظهر أيضًا كإشعار سطح مكتب) ويطلب منك إغلاق Firefox وإعادة تشغيله — مما يبدأ حاوية جديدة على الصورة الحالية. عند استخدام --rebuild مع قفص نشط، يحذّر foxcage مسبقًا، وينفذ البناء، ثم يطبق نفس الفحص.
يتحقق foxcage من إصدارات المتصفح الجديدة عند كل تشغيل — واجهة إصدارات Mozilla لـ Firefox، ونقطة نهاية الإصدارات في GitLab لـ LibreWolf. إذا كان هناك تحديث متاح، تتم إعادة بناء صورة الحاوية تلقائيًا. كما تُعاد بناء الصورة بشكل دوري (كل 7 أيام افتراضيًا) لالتقاط تحديثات أمان Debian. يتم تعطيل أداة التحديث التلقائي المدمجة في المتصفح نظرًا لأن التحديثات تتم على مستوى الصورة.
إذا فشل فحص التحديث (لا توجد شبكة، أو انتهت مهلة API)، تتم طباعة تحذير ويتم استخدام الصورة الموجودة — يمكنك دائمًا التصفح.
يقع تواتر التحديث في المستوى الأعلى من الإعدادات؛ بينما يقع تثبيت الإصدار والقناة في قسم كل فرع (fork):```toml rebuild_days = 14 # rebuild for base-image updates every 14 days (0 to disable)
[firefox] channel = "beta" # track the beta channel instead of stable (firefox only) version = "149" # pin to Firefox 149.x (latest patch release)
**تثبيت نسخة ESR يتطلب القناة أيضًا.** فهرس إصدارات Mozilla يعرض إصدارات ESR دون اللاحقة `esr` التي تحملها ملفات التنزيل الخاصة بها، لذا فإن `version = "140"` المجردة على القناة الافتراضية تشير إلى إصدار غير موجود. حدد كلاهما:```toml
[firefox]
channel = "esr"
version = "140" # → 140.13.0esr
دبوس لا يطابق أي إصدار أصبح الآن خطأً يسمّي الدبوس، بدلاً من الرجوع بصمت إلى أحدث إصدار. لا يزال الفشل المؤقت في الوصول إلى واجهة برمجة تطبيقات Mozilla يُصدر تحذيرًا ويواصل العمل بالصورة الحالية، لذا فإن الشبكة المتقطعة لا تمنع بدء التشغيل أبدًا.
يجب أن تكون الدبابيس ذات اللاحقة مؤهلة بالكامل — "140.13.0esr" و"150.0b9" يعملان، بينما يتم رفض "140esr" و"150b9" عند تحميل الإعدادات لأنه لا يمكن لأي إصدار مطابقتها أبدًا. وينطبق الشيء نفسه على مراجعات LibreWolf: "146.0.1-1" يعمل، بينما "146-1" لا يعمل.
لفرض إعادة بناء كاملة فورية: ./foxcage --rebuild
يرفض foxcage تثبيت بناء متصفح تم توقيعه بواسطة مفتاح توقيع فرعي ألغاه المشروع الأصلي باعتباره مخترقًا (سبب الإلغاء RFC 4880 0x02). لا يقوم gpg --verify بذلك من تلقاء نفسه: فهو يطبع تحذيرًا ويخرج بالرمز 0، لذا بدون الفحص الإضافي، سيظل مفتاح التوقيع المسرّب يوثّق تنزيلًا معدّلًا.
يبدو الرفض هكذا، ويفشل البناء بدلاً من التثبيت:``` foxcage: REFUSING /tmp/SHA512SUMS - signed by 09BEED63F3462A2DFFAB3B875ECB6497C1A20256, which its owner revoked as compromised. This build cannot be trusted; wait for upstream to re-sign this release with a current key.
لا يوجد شيء لتكوينه ولا أي تجاوز. إذا واجهت هذا، فإن الإصلاح من upstream: إما تثبيت إصدار موقّع بمفتاح حالي، أو انتظار إعادة توقيع الإصدار المتأثر.
يُعامل تدوير المفاتيح الروتيني بشكل مختلف. المفتاح الفرعي الذي تم إبطاله كبديل أو متقاعد أو بدون سبب مذكور لا يُبطل التوقيعات التي تمت *قبل* الإبطال، لذا تُثبَّت تلك الإصدارات مع تحذير. التوقيع المؤرخ *بعد* أي إبطال يُرفض مهما كان السبب المذكور.
**تدوير مفاتيح Mozilla في أغسطس 2026.** أبطلت Mozilla المفتاح الفرعي للتوقيع `09BEED63…C1A20256` في 2026-08-06 بعد أن تم إيداع نسخة غير مشفرة في مستودع GitHub خاص، واستبدلته بـ `827E6586…76767AA3`. إصدارات Firefox الموقعة بالمفتاح الفرعي القديم — كل ما بين 2025-03-13 و2026-08-06، والذي لا يزال وقت كتابة هذا يشمل ESR الحالي (`140.13.0esr`) وأي تثبيت `version` ضمن تلك النافذة — تُرفض بواسطة الفحص أعلاه. قناتا الإصدار التجريبي والإصدار المستقر غير متأثرتين. يجلب foxcage المفاتيح من `keys.openpgp.org` بدلاً من `keyserver.ubuntu.com` لأن الأخير لم يقدم لا المفتاح الفرعي البديل ولا الإبطال لأيام بعد التدوير؛ خادم مفاتيح قديم من شأنه أن يكسر البناءات تماماً ويقلل بصمت فحص الإبطال إلى عملية فارغة.
### شوكات Firefox (LibreWolf)
يمكن لـ foxcage تشغيل شوكة Firefox موجهة للخصوصية بدلاً من Firefox الرئيسي:```toml
fork = "librewolf" # default is "firefox"
[librewolf]
version = "146.0.1-1" # optional pin; partial pins ("146", "146.0.1") also work
أو عند كل إطلاق عبر CLI:```sh foxcage @tmp --fork librewolf https://example.com
**LibreWolf**: إصدار Firefox مُعدَّل لتعزيز الخصوصية — حماية صارمة من التتبع، DoH، RFP، والقياس عن بُعد معطّل افتراضيًا. حزمة Linux الموقّعة من GitLab (`librewolf-community/browser/bsys6`)، تم التحقق منها عبر GPG مقابل مفتاح صانعي LibreWolf `662E 3CDD 6FE3 2900 2D0C A5BB 4033 9DD8 2B12 EF16` مع فحص متقاطع لملف `.sha256sum` مجاور، تحت نفس [قواعد الإبطال](#revoked-signing-keys) الخاصة بـ Firefox. يتم الحفاظ على ملف `librewolf.cfg` المرفق مع LibreWolf؛ يضيف foxcage تفضيلاته الخاصة فوقه بدلاً من استبداله. قام الصانعون بتدوير مفتاح التوقيع الفرعي الخاص بهم في 2026-04-25 دون ذكر سبب؛ الحزم الحالية تم توقيعها قبل ذلك التاريخ، لذا يتم تثبيتها مع تحذير بدلاً من رفضها.
**القناة مخصصة لـ Firefox فقط**: يتم رفض `firefox.channel = "beta" | "esr"` عندما يكون `fork` أي شيء آخر غير `"firefox"`. لدى LibreWolf مسار إصدار واحد.
تغيير `fork` (عبر الإعدادات أو `--fork`) يغيّر تجزئة Containerfile، مما يؤدي إلى إعادة بناء عند الإطلاق التالي — لا حاجة لـ `--rebuild` يدوي.
#### توافق الملف الشخصي
> **استخدم ملفًا شخصيًا مخصصًا لكل fork.** الخيار الأكثر أمانًا هو ترك foxcage يوفّر ملفه الشخصي الخاص (احذف `profile` من الإعدادات)، أو وجّه `profile` إلى مجلد لا تفتحه أيضًا من النظام المضيف.
- **LibreWolf**: *عادةً* من الآمن مشاركته مع ملفك الشخصي في Firefox على النظام المضيف — يتتبع LibreWolf إصدارات Firefox خلال بضعة أيام، لذا نادرًا ما تحدث تعارضات في مخطط `compatibility.ini`. المخاطر: (1) الاستخدام المتسلسل فقط هو الآمن (ملف قفل Firefox يمنع الفتح المتزامن)؛ (2) في الفترة القصيرة بعد إصدار Firefox المستقر، قد يؤدي تشغيل Firefox أولاً ثم LibreWolf إلى ظهور حوار ترحيل "مستخدم بواسطة إصدار أحدث"؛ (3) الميزات التي يزيلها LibreWolf (Sync، Pocket، حساب Mozilla) لا تعمل بصمت لكنها لا تُفسد البيانات.
### أقفاص مسماة
شغّل مثيلات منفصلة معزولة بإعداداتها وملفها الشخصي الخاص بـ Firefox:```sh
./foxcage @work
هذا يقوم بتحميل ~/.config/foxcage/work.toml ويستخدم صورة منفصلة (foxcage-work)، وحاوية (foxcage-work)، وحجم تخزين (foxcage-work-profile). يجب أن يكون ملف الإعداد موجودًا للأقفاص المسماة. قد تحتوي أسماء الأقفاص على أحرف وأرقام وشرطات وشرطات سفلية فقط.
توجد ملفات الإعداد في $XDG_CONFIG_HOME/foxcage/ (الافتراضي هو ~/.config/foxcage/).
config.toml — القفص الافتراضي (اختياري، مع إعدادات افتراضية معقولة بدونه)<name>.toml — قفص مسمى، يتم تحميله باستخدام @<name> (مطلوب)يتم رفض مفاتيح الإعداد غير المعروفة مع ظهور خطأ. راجع config.toml.example لجميع الخيارات المتاحة مع الإعدادات الافتراضية.
profile = "~/.mozilla/firefox/xxxxxxxx.default-release"
downloads_dir = "~/Downloads"
[firefox]
[librewolf]
[network]
[mounts]
bind = [ "~/Documents:ro", ]
[init]
### ملف تعريف Firefox للمضيف
لمشاركة ملف تعريف Firefox الخاص بالمضيف مع القفص، اضبط `profile` على دليل الملف الشخصي. ابحث عن مسار ملفك الشخصي بزيارة `about:profiles` في Firefox على المضيف — أو أشر فقط إلى دليل فارغ جديد إذا كنت تريد أن يبدأ القفص بملف تعريف نظيف يستمر على المضيف.```toml
profile = "~/.mozilla/firefox/xxxxxxxx.default-release"
فقط هذا الدليل الوحيد يتم تركيبه (bind-mounted) داخل القفص. الملفات الشقيقة تحت ~/.mozilla/firefox/ وسجل profiles.ini غير مكشوفة — لا يمكن لقفص مخترق العبث بها.
إذا كان profile غير مضبوط، يتم تخزين ملف تعريف Firefox في وحدة تخزين Podman مسماة بدلاً من ذلك (انظر "ما الذي يبقى" أدناه). إذا كان نفس الملف التعريفي مفتوحًا بالفعل في Firefox على المضيف، فسيؤدي ملف قفل Firefox الخاص بالملف التعريفي إلى تعارض — استخدم ملفًا تعريفيًا مخصصًا لكل قفص.
بشكل افتراضي، تستخدم الحاوية pasta مع حظر حلقة الاسترجاع (loopback) الخاصة بالمضيف وDNS المضيف. يتطلب pasta إصدار podman 4.4 أو أحدث (وهو الافتراضي بدون صلاحيات الجذر منذ podman 5.0).
شبكات المضيف تزيل عزل الشبكة تمامًا. استخدم هذا عندما يحتاج القفص إلى الوصول إلى الخدمات على localhost الخاص بالمضيف (مثل خادم تطوير محلي، أو قاعدة بيانات على 127.0.0.1):```toml
[network]
mode = "host"
`dns` لا يمكن دمجه مع `mode = "host"` — شبكة المضيف تستخدم بالفعل محلل أسماء المضيف.
> **وضع المضيف يتخلى عن أكثر من localhost.** فهو يضع القفص في مساحة شبكة المضيف، وتكون مآخذ Unix المجردة محصورة في تلك المساحة بدلاً من نظام الملفات. لذا يمكن لقفص في وضع المضيف الوصول مباشرة إلى مآخذ العناوين المجردة على المضيف — بما في ذلك `@/tmp/.X11-unix/X0` الخاص بـ Xwayland إذا كنت تشغّل X11 أو Xwayland (تسجيل الإدخال، على الرغم من أن foxcage مخصص لـ Wayland فقط)، وناقل جلسة مُهيأ بـ `unix:abstract=…`، مما قد يتجاوز وكيل D-Bus المُصفّى. هذا متأصل في مشاركة حزمة الشبكة، وليس شيئًا يمكن لـ foxcage تصفيته. استخدم وضع المضيف عندما تحتاجه، وفضّل قفصًا مسمّى تشغّله فقط لهذا الغرض.
**أقفاص IPv4 فقط** تعطّل IPv6 بالكامل:```toml
[network]
ipv4_only = true
أو عند الإطلاق باستخدام علامة --ipv4-only (الصيغة المختصرة -4، كما في ssh/curl/pasta):```sh
./foxcage @tmp -4 https://example.com
هذا يشغّل pasta في وضع IPv4 فقط (`-4`)، لذا لا يحتوي الحاوية على مكدس IPv6 إطلاقًا، ويضبط أيضًا `network.dns.disableIPv6` في Firefox بحيث لا يحلّ سجلات AAAA — وهو أمر مهم عند تفعيل DoH، لأن إجابات DoH تتجاوز محلل الحاوية. لا يمكن دمج `ipv4_only` مع `mode = "host"` — فشبكة المضيف تستخدم مكدس شبكة المضيف مباشرة، لذا عطّل IPv6 على المضيف بدلًا من ذلك.
### أوامر التهيئة
شغّل أوامر مخصصة في وقت البناء أو عند بدء تشغيل الحاوية عبر `[init]`:
- **`build`** — يعمل في وقت بناء الصورة بصلاحيات الجذر. استخدمه لتثبيت الحزم أو أي إعداد بطيء آخر. التغييرات على أوامر البناء تؤدي تلقائيًا إلى إعادة بناء الصورة.
- **`root`** — يعمل عند بدء تشغيل الحاوية بصلاحيات الجذر، قبل Firefox. استخدمه لمهام الجذر السريعة في وقت التشغيل (تعديل الصلاحيات، كتابة ملفات الإعداد).
- **`user`** — يعمل عند بدء تشغيل الحاوية بصلاحيات المستخدم الخاص بك، قبل Firefox. استخدمه لإنشاء الدلائل، وإعداد حالة على مستوى المستخدم.```toml
[init]
build = [
"apt-get update && apt-get install -y --no-install-recommends fonts-noto-cjk",
"rm -rf /var/lib/apt/lists/*",
]
root = ["chmod 777 /tmp/shared"]
user = ["mkdir -p ~/workspace"]
جميع المفاتيح الثلاثة هي قوائم من سلاسل أوامر الصدفة. إذا فشل أي أمر، يخرج الحاوية دون تشغيل Firefox.
ملاحظة أمنية: عند تعيين init.root، تبدأ الحاوية كجذر مع إضافة CAP_SETUID و CAP_SETGID (بالإضافة إلى CAP_SYS_CHROOT الافتراضي) حتى تتمكن من العودة إلى المستخدم العادي. هذه الصلاحيات تُحتفظ بها فقط خلال مرحلة تهيئة الجذر — بعد خفض الامتيازات، لا تمتلك عملية المستخدم العادي أي صلاحيات إضافية. بدون init.root، تعمل الحاوية مع مجموعة الصلاحيات الافتراضية الدنيا.
بدون تكوين، يقوم مجلد Podman مسمى بتخزين ملف تعريف Firefox (الإشارات المرجعية، الإعدادات، الإضافات، مكوّن Widevine DRM). كل شيء آخر مؤقت.
foxcage-profilefoxcage-<name>-profileلبدء من جديد، قم بإزالة المجلد:```sh podman volume rm foxcage-profile
إذا تم تعيين `profile`، يتم ربط دليل المضيف مباشرةً (bind-mount) ولا يتم إنشاء أي وحدة تخزين (volume).
الإضافات المدرجة في `extensions` ليست جزءًا من تلك الحالة: فهي موجودة في الصورة (image) ويتم إعادة تثبيتها عند كل إطلاق، لذا فإن إزالة وحدة التخزين (أو استخدام قفص مؤقت (ephemeral cage) لا يملك واحدة) لا يؤدي إلى فقدانها.
### استخدام القرص
حجم كل صورة قفص (cage image) حوالي 1 جيجابايت. إعادة البناء تعيد وسم الصورة وتترك الصورة السابقة خلفها كإدخال غير موسوم `<none>`، لذلك يقوم foxcage بإزالة الصورة التي حلّت محلها بعد كل بناء ناجح. وهو يزيل فقط تلك الصورة المحددة، ولا يزيل أبدًا صورة لا يزال قفص قيد التشغيل يستخدمها.
الصور التي أصبحت يتيمة (orphaned) قبل وجود هذا السلوك لا يتم تنظيفها بأثر رجعي. لاستعادتها:```sh
podman images --filter dangling=true # review first
podman image prune # then remove
تحديثات Firefox تُكتشف تلقائيًا عند كل إطلاق. لفرض إعادة بناء كاملة (مثلًا لالتقاط تحديثات أمان النظام فورًا):```sh ./foxcage --rebuild
## التنسيق (Theming)
يقوم foxcage تلقائيًا بتمرير ما يلي من النظام المضيف، بحيث يبدو Firefox داخل الحاوية ويُستخدم كتطبيق أصلي:
- **الخطوط (Fonts).** خطوط النظام (`/usr/share/fonts`) وخطوط المستخدم (`~/.local/share/fonts`) تُركَّب (bind-mounted) للقراءة فقط. كما يتم تمرير إعدادات الخطوط من `~/.config/fontconfig`.
- **سمة GTK والوضع الداكن.** يتم اكتشافها عبر `GTK_THEME` أو `gsettings` وتمريرها إلى الحاوية. تُركَّب إعدادات GTK من `~/.config/gtk-3.0` و`~/.config/gtk-4.0` للقراءة فقط.
- **المنطقة الزمنية.** يتم تمرير اسم المنطقة الزمنية للنظام المضيف (المكتشف من `TZ`، أو الرابط الرمزي `/etc/localtime`، أو `/etc/timezone`) إلى الحاوية كقيمة `TZ`، ويُركَّب `/etc/localtime` للقراءة فقط. كلاهما ضروري: يستمد Firefox المنطقة الزمنية لجافاسكريبت من *اسم* المنطقة، وليس من محتويات الملف — بدون `TZ`، ستظهر المواقع الأوقات بتوقيت UTC.
- **الإعدادات المحلية (Locale).** يتم تمرير `LANG`. يتم توليد الإعدادات المحلية للنظام المضيف في صورة الحاوية وقت البناء.
**تسمية القفص (Cage label).** يعرض شريط قوائم Firefox "FoxCage" (أو "FoxCage - name" للأقفاص المسماة) حتى تتمكن من معرفة في لمحة أنك في جلسة حاوية. يكون شريط القوائم مرئيًا دائمًا عبر سياسة المؤسسة.
تتضمن الحاوية سمة GTK الخاصة بـ Adwaita فقط. على أسطح مكتب GNOME يعمل هذا مباشرة دون إعدادات. على KDE أو أسطح مكتب أخرى، سيعود Firefox إلى Adwaita إذا لم تكن سمة GTK الخاصة بك (مثل Breeze) مثبتة في الحاوية. لا يزال اكتشاف الوضع الداكن يعمل طالما تم ضبط التفضيل عبر `gsettings` أو `GTK_THEME`.
## فك تشفير الفيديو عبر العتاد (VA-API)
تحتوي الحاوية على بيئة المستخدم الخاصة بها، لذا فإن برامج تشغيل VA-API المثبتة على النظام المضيف
غير ذات صلة — الصورة تشحن برامجها الخاصة. يسحب `va-driver-all` كلًا من `i965-va-driver` (إنتل
الأقدم) و`mesa-va-drivers` (AMD، nouveau)، إلى جانب `intel-media-va-driver-non-free`
(إنتل Gen8+، برنامج iHD) و`libva2`/`libva-drm2`، التي يقوم Firefox بتحميلها وقت التشغيل.
يتطلب فك التشفير عبر العتاد تمرير `/dev/dri`، وهو ما يفعله foxcage تلقائيًا
عندما يتوفر لدى النظام المضيف. لا شيء لتكوينه.
برنامج تشغيل إنتل هو الإصدار **غير الحر (non-free)**، لذا تُمكّن الصورة مكوّن `non-free`
من Debian. إصدار Debian الحر `intel-media-va-driver` هو إعادة تغليف `+dfsg` مع
إزالة نوى الترميز غير القابلة لإعادة التوزيع، وما يخسره هو فك تشفير AV1 — الصيغة
التي يقدمها YouTube افتراضيًا الآن. الإصدار الحر سيترك AV1 يعود إلى البرمجيات
على كل جهاز إنتل.
للتحقق من أنه يعمل فعليًا، شغّل `vainfo` داخل قفص مباشر:```bash
podman exec foxcage-<name> vainfo
يجب أن يعرض السائق المستخدم (iHD على Intel، radeonsi على AMD) والملفات الشخصية المدعومة — VAProfileH264*، VAProfileVP9Profile0، VAProfileAV1Profile0 وهكذا. الفحص المكافئ من داخل المتصفح هو about:support ← الوسائط، حيث يجب أن يظهر عمود فك التشفير بالأجهزة كـ مدعوم لـ H264 وVP8 وVP9 وHEVC وAV1. أثناء تشغيل فيديو، يُظهر intel_gpu_top على المضيف نشاطًا على محرك الفيديو.
تشفير الأجهزة منفصل، وعلى Intel يأتي من نفس السائق: يجب أن يظهر H264 وHEVC كـ مدعوم في ذلك العمود، وهو ما يستخدمه WebRTC لدفق الكاميرا الصادر في مكالمات الفيديو وما يستخدمه MediaRecorder. يبقى تشفير VP8 وVP9 وAV1 كـ غير مدعوم — يقوم Firefox فقط بتوصيل مشفرات H264 وHEVC الخاصة بـ VA-API، مهما كانت قدرات وحدة معالجة الرسومات.
تظهر برامج الترميز الصوتية (AAC، MP3، Opus، Vorbis، FLAC، Wave) كـ غير مدعوم تحت فك التشفير بالأجهزة على كل جهاز — لا توجد وحدة معالجة رسومات استهلاكية تحتوي على كتلة فك تشفير صوتي. هذا الصف ليس خطأ في الإعداد.
إذا أبلغ vainfo عن failed to initialize display، فلا يمكن للحاوية فتح /dev/dri/renderD128. على سطح مكتب systemd عادي، يمنحك logind صلاحية ACL على هذا الجهاز، لذا فإن هذا يعني عادةً أن foxcage يُشغَّل من جلسة لا تملك المقعد (SSH، أو TTY مختلف).
يعمل Widevine DRM مباشرة دون إعدادات إضافية. عند أول زيارة لموقع محمي بـ DRM، سيقوم Firefox بتنزيل Widevine CDM تلقائيًا. قد يستغرق ذلك لحظة.
يستخدم foxcage وكيل D-Bus مُصفّى لمنح Firefox وصولًا إلى بوابة سطح المكتب XDG وخدمة الإشعارات الخاصة بالمضيف. هذه الميزات آمنة لأن كل الوصول يتم بوساطة المستخدم — يعرض المضيف حوارات أصلية يجب عليك التفاعل معها. لا يمكن لمتصفح مخترق الوصول بصمت إلى موارد المضيف.
mailto:، روابط المغناطيس، إلخ. تُفتح عبر منتقي التطبيقات في المضيفتمرر هذه الأجهزة المضيفة مباشرة إلى الحاوية وهي معطلة افتراضيًا — على عكس ميزات البوابة أعلاه، لا يوجد تأكيد من جانب المضيف. يمكن لمتصفح مخترق استخدام الأجهزة بصمت.```toml webcam = true # /dev/video* — webcam for video calls local_printers = true # CUPS socket — USB printers (network printers work by default) security_keys = true # /dev/hidraw* — FIDO2/U2F hardware keys
## غير مدعوم بعد
بعض ميزات منصة الويب لا تعمل داخل الحاوية بسبب نقص التكامل مع النظام المضيف. هذه الميزات مذكورة هنا من أجل الشفافية.
**البلوتوث، USB، المنفذ التسلسلي، وNFC.** تتطلب واجهات برمجة تطبيقات Web Bluetooth وWebUSB وWeb Serial وWebNFC الوصول إلى الأجهزة وخدمات النظام (BlueZ، udev) غير المتوفرة داخل الحاوية.
**أذرع التحكم (Gamepads) وMIDI.** تحتاج واجهة برمجة تطبيقات Gamepad إلى الوصول إلى `/dev/input/`. يحتاج Web MIDI إلى الوصول إلى منسق ALSA. لا يتم تمرير أي منهما.
**تثبيت PWA.** لا يمكن تثبيت تطبيقات الويب التقدمية على سطح المكتب المضيف من داخل الحاوية.
**إمكانية الوصول.** دعم قارئ الشاشة عبر AT-SPI معطّل (`NO_AT_BRIDGE=1`) — لا توجد للحاوية أي صلة بحافلة إمكانية الوصول الخاصة بالمضيف. يعمل تركيب Web Speech API: تم تثبيت `speech-dispatcher` مع محرك `espeak-ng` في القفص (cage) ويتم تشغيله تلقائيًا عند أول استخدام، مع توجيه الصوت عبر مقبس PulseAudio المشترك.
## إعداد المضيف
### موصى به: تخزين overlay
قد يتراجع Podman بدون صلاحيات الجذر إلى برنامج تشغيل التخزين `vfs`، الذي ينسخ طبقات الصور بالكامل بدلاً من استخدام تركيبات overlay. هذا يجعل بدء تشغيل الحاوية بعد البناء أبطأ بكثير. تحقق من برنامج التشغيل الذي لديك:```sh
podman info --format '{{.Store.GraphDriverName}} {{.Store.GraphStatus}}'
overlay مع Native Overlay Diff:true هو المسار السريع ولا يحتاج إلى أي إعداد — على نواة 5.13 أو أحدث مع نظام ملفات داعم ext4/xfs، يستخدم Podman overlayfs غير المميز مباشرة. إذا كان هذا ما تراه، فلا يوجد ما يجب فعله، ولن يساعد تثبيت fuse-overlayfs.
فقط إذا وصلت إلى vfs (نواة قديمة، أو نظام ملفات داعم لا يمكنه تنفيذ overlay غير مميز) قم بتثبيت fuse-overlayfs وأضفه إلى ~/.config/containers/storage.conf:```toml
[storage]
driver = "overlay"
[storage.options.overlay] mount_program = "/usr/bin/fuse-overlayfs"
هذا هو حل احتياطي، وليس ترقية: FUSE يمرّر كل عملية نظام ملفات عبر مساحة المستخدم وهو أبطأ من overlay الأصلي. تعيين `mount_program` على نظام يدعم overlay الأصلي يجعل الأمور أسوأ، وليس أفضل.
### تعيين foxcage كمتصفحك الافتراضي
أولاً، تأكد من أن سكربت `foxcage` في موقعه الدائم (مثل `~/bin/foxcage` أو `/usr/local/bin/foxcage`). يسجّل أمر التثبيت المسار الحالي للسكربت في ملف `.desktop`، لذا فإن نقله لاحقاً سيكسر المشغّل.
ثم شغّل:```sh
foxcage --install
ينشئ هذا ملف .desktop يشير إلى الموقع الحالي للسكربت، ويُثبّت أيقونة foxcage، ويُحدّث قواعد بيانات سطح المكتب والأيقونات. يجب أن يظهر FoxCage بعد ذلك في قائمة التطبيقات لديك.
لتعيين foxcage كمتصفح ويب افتراضي بحيث تُفتح الروابط التي يتم النقر عليها في التطبيقات الأخرى داخل foxcage:```sh xdg-settings set default-web-browser foxcage.desktop
إذا كانت نافذة المتصفح (cage) تعمل بالفعل، تُفتح عناوين URL كعلامة تبويب جديدة في المتصفح الحالي.
للتراجع:```sh
foxcage --uninstall
StartupNotify=true مضبوط في ملف .desktop، وهو ما يخبر مدير النوافذ بعرض مؤشر تحميل دوّار أثناء بدء تشغيل foxcage. عندما يكون بناء الصورة مطلوبًا (والذي قد يستغرق عدة دقائق)، يرسل foxcage إشعارًا سطح مكتبيًا حتى تعرف أن Firefox في طريقه. كما يتم عرض أي خطأ خروج مبكر (خطأ إملائي في الإعدادات، اعتماد مفقود، اسم قفص غير صحيح) كإشعار سطح مكتبي حتى لا يظل المستخدمون الذين يطلقون التطبيق من سطح المكتب ينظرون إلى لا شيء عندما يفشل foxcage دون وجود طرفية مرفقة. كلاهما يتطلب notify-send (من libnotify-bin على Debian/Ubuntu) — إذا لم يكن مثبتًا، يتم تخطي الإشعارات بصمت ويظل الخطأ يُرسل إلى stderr.
إذا كنت تفضل إنشاء ملف .desktop يدويًا، فأنشئ ~/.local/share/applications/foxcage.desktop:```ini
[Desktop Entry]
Type=Application
Name=FoxCage
Comment=Firefox in a rootless Podman container
Exec=/path/to/foxcage %u
Icon=foxcage
MimeType=text/html;x-scheme-handler/http;x-scheme-handler/https;
Terminal=false
Categories=Network;WebBrowser;
StartupNotify=true
StartupWMClass=foxcage
استبدل `/path/to/foxcage` بالمسار الفعلي للبرنامج النصي. سجّله:```sh
update-desktop-database ~/.local/share/applications
تستخدم مجموعة الاختبارات pytest + pytest-cov، المُعلنة كاعتماديات خاصة بالتطوير فقط في requirements-dev.txt.```
pip install -r requirements-dev.txt
pytest
الاختبارات معزولة تمامًا — لا podman، ولا شبكة، ولا نظام ملفات حقيقي يتجاوز `tmp_path` الخاص بـ pytest. تفرض المجموعة **تغطية 100% للأسطر والفروع** (مُهيأة في `pytest.ini` و`.coveragerc`)؛ أي سطر غير مغطى، أو جانب غير مُختبر من شرط، يُفشل التشغيل. يشغّل CI المجموعة عند كل push عبر `.gitlab-ci.yml`.
## شكر وتقدير
تم تطوير هذا المشروع بواسطة Mike Cardwell، بمساعدة [Claude Code](https://claude.ai/claude-code)، أداة الذكاء الاصطناعي للبرمجة من Anthropic.
## الدعم/تقدير عملي
- [Bitcoin](bitcoin:1PQLtWnjUi1itHLG6QCQeHM3Nxua8pRsq1): 1PQLtWnjUi1itHLG6QCQeHM3Nxua8pRsq1
- [Paypal](https://www.paypal.me/grepular)
org.freedesktop.portal.Desktoporg.mozilla.*org.librewolf.*org.freedesktop.portal.Desktop ككل، لأن هذه هي طريقة عمل منتقي الملفات، "فتح الرابط في تطبيق آخر"، ومشاركة الشاشة. كما يكشف RemoteDesktop (لوحة مفاتيح/فأرة اصطناعية للجلسة بأكملها)، Camera و Location. تلك محكومة بحوارات الموافقة الخاصة بسطح المكتب لديك وليس بواسطة foxcage — ويشبه موجه RemoteDesktop موجه مشاركة الشاشة، لذا اقرأ حوارات الموافقة قبل قبولها. لا يمتلك xdg-dbus-proxy قاعدة "رفض واجهة واحدة"، لذا تضييق هذا يعني تعداد كل واجهة يحتاجها Firefox؛ راجع docs/DESIGN.md لمعرفة لماذا لا يتم ذلك افتراضيًاprofile، downloads_dir، تركيبات [mounts] bind الإضافية) تستخدم nosuid,noexecgpg --verify، الذي يخرج بـ 0 لتوقيع مصنوع بمفتاح ملغى ولأي مفتاح في keyring. يتطلب foxcage أيضًا أن تتصل السلسلة بالمفتاح الأساسي المثبت، ويرفض أي إصدار موقع بمفتاح فرعي ألغى مالكه كونه مخترقًا — راجع مفاتيح التوقيع الملغاة--rm) — تُفقد كتابات نظام الملفات عند الخروج