FreeBSD jails بمقابلہ Docker containers: فرق کیا ہے؟
FreeBSD jails مکمل userland اور Docker layered images چلاتا ہے۔ software، state، networking اور resource limits کے فرق کو واضح مثالوں کے ساتھ سمجھیں۔
FreeBSD jails بمقابلہ Docker containers، ایک پیراگراف میں
FreeBSD jails اور Docker containers ایک ہی مسئلے کو دو مختلف طریقوں سے حل کرتے ہیں۔ دونوں ایک مشترکہ kernel پر الگ تھلگ userlands چلاتے ہیں، اس لیے دونوں میں سے کوئی بھی virtual machine نہیں ہے۔ فرق اس بات میں ہے کہ اندر کیا چلتا ہے۔ Docker container ایک registry سے حاصل کی گئی layered image سے ایک process چلاتا ہے۔ jail ایک مکمل FreeBSD userland چلاتی ہے: اس کا اپنا /etc، اپنے rc startup scripts، اپنا pkg database، اور جتنے چاہیں processes۔ اس صفحے پر موجود تقریباً ہر دوسرا فرق اسی بنیادی فرق سے پیدا ہوتا ہے۔
SSD Nodes، FreeBSD images پیش نہیں کرتا۔ آپ اس platform پر FreeBSD server کرائے پر نہیں لے سکتے، اور ذیل میں موجود مواد اس machine کے لیے installation guide نہیں ہے جسے آپ یہاں خرید سکتے ہیں۔ یہ isolation کے دو models کا موازنہ ہے، تاکہ آپ سمجھ سکیں کہ کسی workload کو حقیقتاً کون سا model درکار ہے، اور FreeBSD team کے setup کو اندازے کے بغیر پڑھ سکیں۔
اصل میں jail کیا ہے
Jails مارچ 2000 میں FreeBSD 4.0 میں شامل ہوئے۔ اس وجہ سے یہ cgroups سے پرانے اور Docker سے تقریباً ایک دہائی پہلے کے ہیں۔ یہ طریقۂ کار ایک kernel call پر مشتمل ہے۔ jail(8) ایک directory tree لیتا ہے اور اس کے اندر processes شروع کرتا ہے، جن کے ساتھ jail ID منسلک ہوتی ہے۔ اس کے بعد kernel اس ID رکھنے والے ہر process کے لیے مخصوص operations کو مسترد کر دیتا ہے۔ jailed process اپنے jail سے باہر کے processes نہیں دیکھ سکتا، filesystems mount یا unmount نہیں کر سکتا، kernel modules load نہیں کر سکتا، اور ان network addresses پر bind نہیں کر سکتا جو اسے نہیں دیے گئے۔ سیکھنے کے لیے کوئی الگ namespace type نہیں ہے اور نہ ہی ہر feature کو الگ سے فعال کرنا پڑتا ہے۔ پابندیاں ایک اکائی کے طور پر نافذ ہوتی ہیں، جنہیں jail کی config میں parameters کے ذریعے تبدیل کیا جاتا ہے۔
host پر jls چلنے والے jails کی فہرست دکھاتا ہے، جبکہ jexec web sh نام web والے jail کے اندر shell کھولتا ہے۔
آپ ایک directory میں FreeBSD userland رکھ کر jail بناتے ہیں۔ base system یہ کام آپ کے لیے کرتا ہے:
sudo bsdinstall jail /usr/local/jails/containers/webیہ آپ کی release کے لیے base distribution set حاصل کرتا ہے اور معمول کے post-install steps چلاتا ہے۔ اس لیے آپ root password مقرر کرتے ہیں اور timezone منتخب کرتے ہیں، بالکل اسی طرح جیسے نئے server پر کرتے ہیں۔ نتیجے میں ایک folder کے اندر FreeBSD installation موجود ہوتی ہے۔ پھر آپ اسے /etc/jail.conf میں بیان کرتے ہیں:
web {
host.hostname = "web.example.internal";
path = "/usr/local/jails/containers/web";
ip4.addr = "10.0.0.10";
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
mount.devfs;
}اسے start کریں، پھر اس کی جانچ کریں:
sudo service jail start web
jlsاب jls کو JID، hostname اور IP address کے ساتھ web دکھانا چاہیے۔ اگر jail ظاہر نہ ہو تو sudo jail -c web براہِ راست چلائیں۔ یہ وہی configuration foreground میں لاگو کرتا ہے اور وہ parameter دکھاتا ہے جسے قبول نہیں کیا جا سکا، بجائے اس کے کہ failure کو service output میں چھوڑ دے۔
جس line کو دوبارہ پڑھنا چاہیے وہ exec.start = "/bin/sh /etc/rc" ہے۔ jail start کرنے سے اس کے اندر FreeBSD کا معمول کا boot script چلتا ہے۔ اس لیے jail اپنے /etc/rc.conf میں enabled ہر service کو start کرتا ہے۔ Docker container میں اس کے مساوی کوئی step نہیں ہوتا، کیونکہ وہ image کے entrypoint process کو چلاتا ہے اور اس process کے رکنے پر خود بھی رک جاتا ہے۔
آپ سافٹ ویئر کیسے حاصل کرتے ہیں: images اور registries بمقابلہ وہ userland جسے آپ خود تیار کرتے ہیں
یہ وہ فرق ہے جو پہلے ہی دن محسوس ہوتا ہے۔
Docker میں آپ سافٹ ویئر کا نام دیتے ہیں اور اسے حاصل کر لیتے ہیں۔ docker pull nginx ایک layered، content-addressed image fetch کرتا ہے جسے کسی دوسرے فریق نے build اور test کیا ہوتا ہے، اور docker compose up -d اسے اس کے volumes اور network کے ساتھ start کر دیتا ہے۔ registry ہی اصل product ہے۔ Docker workflow کی زیادہ تر قدر اس بات میں ہے کہ ہزاروں projects working image publish کرتے ہیں۔ اسی وجہ سے VPS پر Docker چلانا ایک مختصر کام رہتا ہے، مکمل project نہیں۔
FreeBSD میں jail images کے لیے کوئی default public registry شامل نہیں ہوتی۔ آپ ایک خالی userland بناتے ہیں اور اس میں software install کرتے ہیں، بالکل اسی طرح جیسے bare server تیار کیا جاتا ہے۔ اس میں زیادہ typing درکار ہوتی ہے۔ یہ طریقہ زیادہ شفاف بھی ہے، کیونکہ jail میں وہی چلتا ہے جو pkg نے وہاں install کیا ہو، اور وہ بھی اسی package set سے جسے host استعمال کرتا ہے۔
Tooling اس عمل کو مختصر بنا دیتی ہے۔ BastilleBSD عام jail manager ہے اور یہ ایک package کے طور پر دستیاب ہے:
sudo pkg install bastille
sudo sysrc bastille_enable=YES
sudo bastille setup
sudo bastille bootstrap 15.1-RELEASEbastille setup آپ کے لیے networking، storage اور firewall configure کرتا ہے۔ bastille bootstrap ایک release ایک مرتبہ download کرتا ہے، اور اس کے بعد بننے والی ہر jail اسے دوبارہ استعمال کرتی ہے۔ FreeBSD 15.1 موجودہ production release ہے، جو June 2026 میں جاری ہوئی؛ آپ جو release چلا رہے ہیں اسے استعمال کریں۔
اس کے بعد jail بنانا ایک command کا کام ہے، اور اسے تیار کرنا مزید ایک command کا:
sudo bastille create web 15.1-RELEASE 10.17.89.10/24
sudo bastille pkg web install nginx
sudo bastille service web nginx start
sudo bastille console webbastille console web jail کے اندر login shell فراہم کرتا ہے، جبکہ bastille list دکھاتا ہے کہ host پر کیا موجود ہے۔ Build دوبارہ چلانے کے لیے Bastille templates مراحل کو ایک file میں محفوظ کرتے ہیں اور انہیں jail پر apply کرتے ہیں۔ یہ اس ماحول میں Dockerfile سے ملتی جلتی چیز ہے۔ ہر jail پر template دوبارہ apply کیا جاتا ہے۔ کچھ بھی پہلے سے built حالت میں نہیں آتا۔
لہٰذا مختصر اور درست خلاصہ یہ ہے: Docker آپ کو دوسرے لوگوں کے builds فراہم کرتا ہے۔ Jails آپ کو اپنی installations تیار کرنے دیتے ہیں۔ اگر آپ کی مختصر فہرست میں موجود software صرف container image کے طور پر دستیاب ہے اور کسی اور شکل میں نہیں، تو باقی تمام عوامل پر غور کرنے سے پہلے ہی فیصلہ ہو جاتا ہے۔
حالت اور اپ گریڈز: ZFS میں بدلنے والا حصہ
Docker جان بوجھ کر state کو الگ رکھتا ہے۔ Container filesystem عارضی ہوتا ہے، آپ کا data named volume یا bind mount میں رہتا ہے، اور upgrade میں docker compose pull کے بعد docker compose up -d آتا ہے۔ Container تبدیل کر دیا جاتا ہے، اور volume میں نہ رکھا گیا ہر data ختم ہو جاتا ہے۔ اس اصول کی پابندی کی جائے تو یہ ایک سہولت ہے، لیکن اسے بھولنے پر data loss کا واقعہ پیش آتا ہے۔ اسی لیے Compose stack میں bind mounts اور named volumes کے درمیان انتخاب بہت اہم ہے۔
Jail state کو الگ نہیں کرتا، اور یہ ZFS کی وجہ سے ممکن ہے۔ پوری jail ایک dataset ہوتی ہے:
sudo zfs snapshot zroot/jails/containers/web@pre-upgrade
sudo pkg -j web upgrade
sudo zfs rollback zroot/jails/containers/web@pre-upgradeاس command کو چلانے سے پہلے zfs list سے اصل dataset name کی تصدیق کریں؛ اوپر دیا گیا path handbook میں استعمال ہونے والا layout ہے۔ Snapshot تقریباً 1 second میں بن جاتا ہے اور اس وقت تک تقریباً کوئی جگہ نہیں لیتا جب تک jail کے contents تبدیل نہ ہوں۔ اگر upgrade سے service خراب ہو جائے تو rollback پورے userland کو اس کی سابقہ حالت میں واپس لے آتا ہے۔ اس میں package database اور وہ config files بھی شامل ہیں جنہیں آپ نے رات 2 بجے ہاتھ سے edit کیا تھا۔ Docker میں اس کا built-in متبادل نہیں ہے، کیونکہ اس کا model یہ فرض کرتا ہے کہ آپ کو کبھی ایسی سہولت درکار نہیں تھی۔
zfs clone دوسرا اہم حصہ ہے۔ Snapshot کا clone ایک نئی writable jail ہوتا ہے جو اپنے parent کے ساتھ غیر تبدیل شدہ blocks share کرتا ہے۔ اس لیے 3 GB jail کی staging copy disk پر تقریباً کوئی اضافی جگہ نہیں لیتی، جب تک آپ اس میں تبدیلیاں شروع نہ کریں۔ اسی طریقے سے FreeBSD administrator upgrade کی مشق کے لیے production جیسی jail تیار کرتا ہے۔
Base system upgrade packages سے الگ ہوتا ہے۔ ایسی jail کے لیے جو userland کی اپنی copy رکھتی ہو:
sudo freebsd-update -b /usr/local/jails/containers/web fetch installThin jails یہ کام بار بار کرنے سے بچاتی ہیں۔ وہ nullfs کے ذریعے ایک shared read-only base mount کرتی ہیں اور ہر jail کو اپنی ایک چھوٹی writable layer دیتی ہیں۔ اس طرح آپ base کو ایک بار patch کرتے ہیں اور ہر jail کو نتیجہ نظر آتا ہے۔ Bastille بطور default thin jails بناتا ہے۔
نیٹ ورکنگ: published ports بمقابلہ addressing کا فیصلہ
Docker آپ کے لیے networking کا فیصلہ کرتا ہے اور exceptions کو publish کرنے کا کہتا ہے۔ Containers ایک bridge پر آتے ہیں، user-defined network پر service name کے ذریعے ایک دوسرے تک پہنچتے ہیں، اور -p 8080:80 ان میں سے ایک کو host کے لیے expose کرتا ہے۔ Docker یہ عمل ممکن بنانے کے لیے اپنے packet filter rules لکھتا ہے۔ اسی وجہ سے published container port براہِ راست ufw سے آگے نکل جاتا ہے۔
jail میں آپ کو شروع ہی میں model منتخب کرنا ہوتا ہے، اور دو models ہیں۔
Shared IP۔ ip4.addr = "10.0.0.10" یہ address موجودہ host interface میں شامل کرتا ہے اور jail کو اسی address تک محدود رکھتا ہے۔ jail کا اپنا network stack نہیں ہوتا، اس لیے یہ اپنا firewall نہیں چلا سکتا۔ یہ ہر address پر حقیقی طور پر bind بھی نہیں کر سکتا۔ jail کا کوئی socket 0.0.0.0 کے لیے درخواست کرے تو kernel اسے jail کے اپنے address پر rewrite کر دیتا ہے۔ ایک ہی address کے port 80 پر دو jails بیک وقت listen نہیں کر سکتے۔ اس لیے ہر jail کو الگ address دیں، یا سامنے reverse proxy رکھیں۔
VNET۔ jail میں vnet; شامل کریں تو اسے مکمل network stack مل جاتا ہے: اپنے interfaces، اپنی routing table، اور اپنے firewall rules۔ اسے host سے epair کے ذریعے جوڑیں۔ یہ ایک virtual cable ہے جس کا ایک سرا ہر طرف ہوتا ہے۔ پھر host والے سرے کو bridge پر رکھیں۔ یہ Docker کے فراہم کردہ model سے سب سے زیادہ مشابہ ہے، اور Bastille کے -V اور -B jail types کے پیچھے یہی mode ہے۔
Host port کو jail میں forward کرنا pf redirect rule ہے۔ Bastille اسے اس طرح wrap کرتا ہے:
sudo bastille rdr web tcp 80 80یہاں EXPOSE موجود نہیں ہے اور automatic publishing بھی نہیں ہوتی۔ کوئی چیز jail تک نہیں پہنچ سکتی، جب تک اس کا address یا redirect rule اسے اجازت نہ دے۔ آغاز نسبتاً سست ہوتا ہے، لیکن firewall زیادہ پرسکون رہتا ہے۔
وسائلِ وسائل کی حدود: cgroups بمقابلہ rctl
Docker کسی container کی حد cgroups کے ذریعے مقرر کرتا ہے، اور یہ حدود اسی جگہ موجود ہوتی ہیں جہاں container کی تعریف کی گئی ہو: کمانڈ لائن میں --memory=1g --cpus=1.5، یا Compose فائل میں متعلقہ keys کے ذریعے۔ اگر آپ اپنا stack پہلے ہی VPS پر موجود Docker Compose فائل میں رکھتے ہیں تو حد اسی service کے ساتھ درج ہوتی ہے جس پر یہ لاگو ہوتی ہے، اور git میں service کے ساتھ منتقل ہو جاتی ہے۔
FreeBSD میں rctl استعمال ہوتا ہے، اور اسے ایک subsystem کے طور پر فعال کرنا ضروری ہے۔ Resource accounting بطورِ ڈیفالٹ بند ہوتی ہے کیونکہ ہر allocation پر اس کی معمولی لاگت آتی ہے۔ یہ tunable /boot/loader.conf میں شامل کریں اور reboot کریں:
kern.racct.enable=1اس کے بعد ایک rule مقرر کریں اور اسے monitor کریں:
sudo rctl -a jail:web:vmemoryuse:deny=1g
rctl -hu jail:webrctl -hu jail:web jail کا موجودہ استعمال انسان کے لیے قابلِ مطالعہ units میں دکھاتا ہے۔ اس سے معلوم ہو جاتا ہے کہ کسی چیز کے ناکام ہونے سے پہلے استعمال حد کے کتنا قریب ہے۔ deny action حد سے زیادہ allocation کو jail کے اندر ناکام بنا دیتا ہے۔ اس طرح host پر kill message کے بجائے application کی اپنی allocation error دکھائی دیتی ہے۔
rctl -a کے ذریعے شامل کیے گئے rules اگلے reboot پر ختم ہو جاتے ہیں۔ FreeBSD کی rctl service انہیں /etc/rctl.conf سے دوبارہ load کرتی ہے۔ اس لیے rule اسی فائل میں لکھیں اور service کو enable کریں:
sudo sysrc rctl_enable=YESیہ وہ معاملہ ہے جہاں Docker واضح طور پر زیادہ آسان ہے۔ Compose فائل میں موجود limit کو اسی service کے ساتھ review کیا جا سکتا ہے جس پر یہ پابندی عائد کرتی ہے۔ rctl rule ایک الگ فائل میں موجود ایسی line ہے جس میں اس jail کا نام درج ہوتا ہے جس کی تعریف کہیں اور کی گئی ہو۔
جب جواب virtual machine ہو: bhyve
jail میزبان kernel کا اشتراک کرتا ہے، اس لیے کچھ کام مستقل طور پر اس کی دسترس سے باہر رہتے ہیں۔ یہ kernel کا مختلف version نہیں چلا سکتا، kernel module لوڈ نہیں کر سکتا، اور Linux container کی طرح Linux binaries نہیں چلا سکتا۔ FreeBSD میں Linux compatibility layer موجود ہے جسے linuxulator کہتے ہیں، لیکن یہ Linux system calls کے صرف ایک subset کو implement کرتی ہے۔ یہ من مانے Linux images کے لیے عمومی حل نہیں ہے۔
bhyve، FreeBSD کا hypervisor ہے۔ جب آپ کو حقیقی machine boundary درکار ہو تو یہی درست tool ہے: مختلف operating system، مختلف kernel، یا ایسا tenant جس کے ساتھ آپ kernel کا اشتراک نہیں کرنا چاہتے۔ اس کے عوض memory shared ہونے کے بجائے reserve ہوتی ہے، اور patch کرنے کے لیے دوسرا kernel درکار ہوتا ہے۔ یہی فیصلہ آپ Linux پر containers اور مکمل virtual machines کے درمیان کرتے ہیں۔ اسی سے طے ہوتا ہے کہ آیا آپ کو اندرونی سطح پر nested virtualization کو سپورٹ کرنے والا VPS درکار ہے۔
وہ ecosystem، جس کی وجہ سے زیادہ تر ٹیمیں دیانت داری سے Docker استعمال کرتی ہیں
اوپر بیان کی گئی ہر بات model سے متعلق ہے۔ زیادہ تر ٹیموں کے لیے انتخاب کا فیصلہ ہر model کے گرد موجود ecosystem کے حجم سے ہوتا ہے۔
Docker کے ساتھ Docker Hub اور GHCR، docker compose، جب ایک box کافی نہ رہے تو Kubernetes، container support کے ساتھ پہلے سے مربوط CI runners، اور تقریباً ہر project کی README میں one-command quickstart دستیاب ہوتا ہے۔ Jails کے ساتھ FreeBSD ports tree ملتا ہے، جو بڑا اور احتیاط سے maintain کیا جاتا ہے، لیکن ready-to-run application bundles کا مجموعہ کہیں چھوٹا ہے۔ جب کوئی project صرف container image شائع کرتا ہے اور کچھ نہیں، تو FreeBSD کا طریقہ یہ ہے کہ اس کی documentation پڑھیں اور تمام اجزا خود assemble کریں۔
Jails اس trade-off کے دوسرے رخ پر اپنی جگہ بناتے ہیں۔ انہیں اس وقت منتخب کریں جب آپ پہلے ہی ZFS چلا رہے ہوں اور پوری service کے snapshot اور rollback کو اہمیت دیتے ہوں، جب آپ کی services FreeBSD native ہوں، جب آپ ایک single process کے بجائے ہر tenant کے لیے مکمل userland چاہتے ہوں، یا جب آپ kernel، packet filter، filesystem اور documentation کو ایک ہی system کے طور پر باہم مربوط انداز میں maintain کرنا چاہتے ہوں۔ اسی آخری نکتے کی وجہ سے لوگ FreeBSD کو coherent کہتے ہیں۔ اس کی مزید تفصیل Linux اور FreeBSD کا server platforms کے طور پر وسیع تقابل اور FreeBSD 15 میں server استعمال کے لیے ہونے والی تبدیلیاں میں دی گئی ہے۔
آخر میں ایک فیصلہ کن بات۔ اگر آپ کی ٹیم پہلے ہی Docker جانتی ہے تو منتقل ہونے کی لاگت حقیقی ہے، اور اس کا فائدہ کسی مخصوص ضرورت سے وابستہ ہونا چاہیے۔ isolation quality کی وجہ سے switch نہ کریں؛ دونوں models اس قدر قریب ہیں کہ آپ کی configuration زیادہ اہم ہے۔ switch اس لیے کریں کہ آپ پوری services کے لیے ZFS-backed rollback چاہتے ہیں، یا اس لیے کہ آپ پہلے ہی FreeBSD استعمال کر رہے ہیں۔
FAQ
کیا میں FreeBSD پر Docker images چلا سکتا ہوں؟
Linux images نہیں، اور یہ ایک supported طریقہ بھی نہیں ہے۔ FreeBSD میں OCI container support موجود ہے: sudo pkg install -y podman-suite، Podman install کرتا ہے، جو ocijail کے ذریعے containers چلاتا ہے۔ یہ runtime اندرونی طور پر حقیقی jails بناتا ہے۔ Container monitor کے لیے fdescfs کو /dev/fd پر mount کرنا ضروری ہے، جبکہ container NAT (network address translation) کے لیے pf درکار ہے۔ FreeBSD-native OCI images بہترین کام کرتی ہیں۔ Linux images کے لیے اضافی طور پر Linux compatibility layer درکار ہوتی ہے، اور August 2026 تک FreeBSD Podman port کو اب بھی experimental بیان کیا جاتا ہے۔ اگر آپ کی deployment، Linux images کے stack پر مشتمل ہے تو اسے Linux پر چلائیں۔ RHEL family میں اس کا مطلب Rocky Linux یا AlmaLinux پر Docker install کرنا ہے، جہاں آپ نے کچھ بھی install کرنے سے پہلے Podman دوبارہ اس package کے طور پر سامنے آتا ہے جو پہلے ہی docker command کا مالک ہے۔
کیا FreeBSD jails، Docker containers سے زیادہ محفوظ ہیں؟
دونوں ایک ہی host kernel استعمال کرتے ہیں، اس لیے kernel bug دونوں کے لیے خطرہ ہے، اور حقیقی طور پر غیر معتبر code کے لیے آپ ان میں سے کسی کو بھی مناسب boundary نہیں سمجھیں گے۔ فرق ابتدائی configuration میں ہے۔ Jail میں operations کا ایک وسیع مجموعہ ابتدا ہی سے ممنوع ہوتا ہے، اور آپ انہیں ایک ایک parameter کے ذریعے دوبارہ فعال کرتے ہیں۔ Docker container، کچھ capabilities drop کی گئی ہوں تو بھی، namespaces کے ایک set کے اندر root کے طور پر شروع ہوتا ہے، اور مزید hardening اختیاری ہوتی ہے۔ عملی طور پر configuration، model سے زیادہ فیصلہ کن ہوتی ہے: allow.mount اور allow.raw_sockets کے ساتھ چلنے والا jail، احتیاط سے configured container سے زیادہ محفوظ نہیں ہوتا۔
میں jail کا backup کیسے بناؤں؟
Dataset کا snapshot بنائیں اور اسے منتقل کریں۔ sudo zfs snapshot zroot/jails/containers/web@backup، پھر اس snapshot کو کسی دوسرے pool میں یا ایسی file میں zfs send کریں جسے آپ host سے باہر copy کر سکیں۔ چونکہ jail اپنا پورا userland ایک ہی dataset میں رکھتا ہے، اس لیے snapshot installed packages اور data کو ایک ہی consistent point پر capture کرتا ہے، نیز ہر وہ config file بھی شامل ہوتی ہے جسے آپ نے دستی طور پر edit کیا ہو۔ یہ Docker کے اس طریقے کے برعکس ہے جس میں آپ named volumes اور Compose file کا backup لیتے ہیں، جبکہ باقی environment کو image سے دوبارہ بناتے ہیں۔
کیا مجھے BastilleBSD کی ضرورت ہے، یا base system کافی ہے؟
Base system کافی ہے، اور آغاز کے لیے یہی بہتر جگہ ہے۔ jail.conf، jls، jexec اور service jail start پورے model کا احاطہ کرتے ہیں، اور جب آپ انہیں سمجھ لیتے ہیں تو host کی tooling پہلے سیکھے بغیر کسی بھی FreeBSD host کو پڑھ سکتے ہیں۔ Bastille اس کے اوپر ایک سہولت کی layer ہے: یہ releases کو bootstrap کرتا ہے، thin jails بناتا ہے، templates لاگو کرتا ہے، اور pf redirect rules آپ کے لیے لکھتا ہے۔ پہلے base commands سیکھیں، پھر جب jails کی تعداد اتنی بڑھ جائے کہ typing دشوار لگنے لگے تو Bastille شامل کریں۔