Nix و NixOS برای زیرساخت بازتولیدپذیر، بخش ۱: مفاهیم Nix، نصب و Nix store

در این مجموعه یاد می‌گیریم چطور با Nix و NixOS یک زیرساخت بازتولیدپذیر بسازیم: محیط‌ها و سرورهایی که پیکربندی‌شان به‌صورت کد و اعلانی نوشته می‌شود، دقیقاً همان چیزی می‌سازند که توصیف کرده‌اید، و اگر چیزی خراب شد با یک دستور به وضعیت قبلی برمی‌گردند. در این بخش اول با خود Nix شروع می‌کنیم: مدل ذهنی آن، نصب، و اینکه چرا /nix/store همه‌چیز را عوض می‌کند.

Nix چیست؟

Nix یک package manager با رویکرد functional و pure است. برخلاف apt یا dnf که فایل‌ها را در مسیرهای مشترک سیستم (مثل /usr/bin) می‌ریزند و نسخه‌ها روی هم می‌نویسند، Nix هر package را با تمام وابستگی‌هایش در یک مسیر جداگانه و تغییرناپذیر می‌سازد. نتیجه سه ویژگی کلیدی است:

  • بازتولیدپذیری: یک ورودی مشخص همیشه همان خروجی را می‌سازد؛ روی لپ‌تاپ شما، روی سرور و در CI یکسان است.
  • ایزوله بودن: نصب یک package نسخه‌ی چیز دیگری را خراب نمی‌کند؛ هر چیزی مسیر مخصوص خودش را دارد.
  • بازگشت‌پذیری: هر تغییر یک نسل (generation) تازه است و می‌توانید در لحظه به نسل قبلی rollback کنید.

‏Nix store؛ قلب ماجرا

هر چیزی که Nix می‌سازد در /nix/store با یک مسیر آدرس‌دهی‌شده با hash قرار می‌گیرد؛ چیزی شبیه /nix/store/<hash>-hello-2.12.3. آن hash از تمام ورودی‌های ساخت (کد، وابستگی‌ها، flagها) گرفته می‌شود. اگر حتی یک ورودی عوض شود، مسیر هم عوض می‌شود. به همین دلیل دو نسخه‌ی متفاوت با هم تداخل ندارند و «روی سیستم من کار می‌کرد» تقریباً از بین می‌رود.

نصب Nix

Nix روی هر توزیع لینوکسی (و macOS) نصب می‌شود؛ در این آزمایشگاه از Ubuntu استفاده می‌کنیم. برای نصب از installer استفاده می‌کنیم که خودش daemon چندکاربره را راه می‌اندازد و flakes را هم فعال می‌کند (در بخش‌های بعد به flakes می‌رسیم). بعد از نصب، بدون اینکه چیزی را دائمی نصب کنیم، یک package را فقط برای یک‌بار اجرا می‌گیریم:

نصب Nix و اجرای cowsay بدون نصب دائمی با nix run
نصب Nix، بررسی نسخه، و اجرای cowsay با nix run. نکته‌ی مهم اینجاست: nix run این package و وابستگی‌هایش را می‌گیرد و اجرا می‌کند، بدون اینکه چیزی به محیط دائمی شما اضافه شود.

همین الگو با nix shell nixpkgs#<package> هم کار می‌کند و یک shell موقت با آن ابزار به شما می‌دهد؛ وقتی از shell خارج شوید، اثری روی سیستم نمی‌ماند. این یعنی امتحان کردن ابزارها بدون شلوغ‌کردن سیستم.

نصب دائمی در profile کاربر

وقتی بخواهید ابزاری همیشه در دسترس باشد، آن را به profile کاربر اضافه می‌کنید. این کار همچنان ایزوله و بازگشت‌پذیر است:

نصب package در profile کاربر با nix profile add و فهرست profile
نصب hello در profile کاربر با nix profile add، اجرای آن، و فهرست‌کردن محتوای profile. هر ورودی به یک مسیر مشخص در /nix/store اشاره می‌کند.

مسیرهای store، اندازه‌ی closure و rollback

حالا می‌توانیم سه ایده‌ی کلیدی را کنار هم ببینیم. اول اینکه فایل اجرایی hello در واقع به یک مسیر تغییرناپذیر در store اشاره می‌کند. دوم، «closure» یعنی مجموعه‌ی کامل چیزهایی که آن package برای اجرا به آن‌ها نیاز دارد؛ Nix اندازه‌ی آن را دقیق می‌داند. و سوم، هر تغییر در profile یک نسل تازه است که می‌توان به آن rollback کرد:

مسیر store، اندازه‌ی closure و تاریخچه‌ی نسل‌ها و rollback در Nix
مسیر واقعی hello در /nix/store، اندازه‌ی closure آن، و تاریخچه‌ی نسل‌های profile. با nix profile rollback می‌توان بدون هیچ نصب مجددی به نسل قبلی برگشت.

جمع‌بندی و بخش بعد

در این بخش دیدیم Nix چیست، چرا مدل /nix/store بازتولیدپذیری و ایزوله بودن را ممکن می‌کند، و چطور بدون نصب دائمی یا با profile کاربر از آن استفاده کنیم. تا اینجا با Nix به‌صورت دستوری کار کردیم؛ قدرت واقعی وقتی آشکار می‌شود که همه‌چیز را به‌صورت کد بنویسیم.

در بخش بعد وارد زبان Nix و Nixpkgs می‌شویم: چطور package و محیط‌ها را با کد توصیف کنیم و اولین derivation خودمان را بسازیم.

← بازگشت به وبلاگ