تا اینجا دیدیم که package و حتی ابزارهای خودمان، expressionهای Nix هستند. اما در عمل به یک ساختار استاندارد نیاز داریم که ورودیها (مثل نسخهی Nixpkgs) را دقیق پین کند تا خروجی روی هر ماشینی یکی باشد. این دقیقاً کاری است که flakes انجام میدهد. در این بخش یک محیط توسعهی کاملاً بازتولیدپذیر میسازیم.
flake چیست؟
یک flake یک فایل flake.nix با ساختار مشخص است: بخش inputs وابستگیهای بیرونی (مثل Nixpkgs) را تعریف میکند و بخش outputs چیزهایی که flake تولید میکند (محیطهای توسعه، packageها، و بعداً کل پیکربندی NixOS). مهمترین ویژگی، فایل flake.lock است که نسخهی دقیق هر input را قفل میکند؛ درست مثل lockfile در ابزارهای دیگر.
یک dev shell بازتولیدپذیر
در این flake یک devShell تعریف میکنیم که دقیقاً سه ابزار (jq، ripgrep و python3) را فراهم میکند. با nix develop وارد یک shell میشویم که همان نسخههای پینشده در آن حاضرند، بدون اینکه چیزی روی سیستم میزبان نصب شود:
flake.nix با یک devShell، و ورود به آن با nix develop. هر سه ابزار به مسیرهای دقیق /nix/store اشاره میکنند و نسخههایشان مشخص و ثابت است.پینکردن با flake.lock
وقتی flake را قفل میکنیم، نسخهی دقیق Nixpkgs (یک revision مشخص از Git بههمراه hash محتوایش) در flake.lock ثبت میشود. از این پس هر کسی که این flake را اجرا کند، دقیقاً همان ورودی را میگیرد؛ چه امروز، چه یک سال بعد:
nix flake metadata نشان میدهد input به یک revision مشخص از Nixpkgs قفل شده است. همان revision و narHash در flake.lock ثبت شدهاند و بازتولید را تضمین میکنند.خروجیهای flake
یک flake میتواند چند خروجی داشته باشد. با nix flake show ساختار آن را میبینیم و با nix build هر package را میسازیم؛ همان ابزار greet بخش قبل، اینبار بهصورت یک خروجی flake:
nix flake show خروجیهای flake را فهرست میکند (یک devShell و یک package)، و nix build .#greet آن package را میسازد و اجرا میکند.فعالسازی خودکار با direnv
برای اینکه هر بار دستی nix develop نزنیم، از direnv بههمراه nix-direnv استفاده میکنیم. کافی است در ریشهی پروژه یک فایل .envrc بسازیم؛ از آن پس هر وقت وارد پوشه شویم، محیط بهصورت خودکار فعال و هنگام خروج غیرفعال میشود:
echo "use flake" > .envrc
direnv allow
نتیجه یک تجربهی روان است: هر پروژه محیط خودش را دارد، پینشده و بازتولیدپذیر، بدون آلودهکردن سیستم اصلی.
جمعبندی و بخش بعد
با flakes حالا میتوانیم محیطها و packageها را بهصورت کد و با نسخههای قفلشده تعریف کنیم؛ چیزی که روی لپتاپ، سرور و CI یکسان کار میکند. قدم بعدی طبیعی است: اگر بتوان یک محیط را اینطور توصیف کرد، چرا کل سیستمعامل را نه؟
در بخش بعد وارد NixOS میشویم: یک سیستمعامل که کل پیکربندیاش در یک فایل توصیف میشود و با یک دستور ساخته یا به نسخهی قبل برگردانده میشود.
بخشهای این مجموعه
- بخش ۱: مفاهیم Nix، نصب و Nix store
- بخش ۲: زبان Nix و کار با Nixpkgs
- بخش ۳: Flakes و محیطهای توسعهی بازتولیدپذیر (همین بخش)
- بخش ۴: نصب و پیکربندی اعلانی NixOS
- بخش ۵: NixOS در عمل؛ سرویسها، کاربران و شبکه
- بخش ۶: home-manager و استقرار از راه دور