क्या एक और छोटा NixOS ISO बनाया जा सकता है?
(natkr.com)- NixOS में सिर्फ कॉन्फ़िगरेशन के आधार पर VM या ISO बनाना आसान है, लेकिन लगभग न्यूनतम live image भी शुरू से ही 458MiB बनती है, जो Alpine VM ISO के लगभग 66MiB से काफी बड़ी है
- आकार का अधिकांश हिस्सा nix-store.squashfs ले रहा था, और उसके अंदर Python 3.13.13, Linux modules, systemd, Perl, GRUB, दस्तावेज़, और Nix से जुड़ी dependencies शामिल थीं
nix.enable = false,documentation.enable = false, औरregister-nix-pathsहटाने के बाद ISO का आकार 458MiB → 384MiB → 360MiB तक घटा, और Boost dependency भी हट गई- OpenSSH client, default packages, GRUB installation tools, runtime kernel modules, और Perl-आधारित activation path हटाने के बाद अंतिम आकार 183MiB तक आ गया
- छोटे experimental boot image के लिए यह उपयोगी संदर्भ हो सकता है, लेकिन इसमें बहुत-सी ज़रूरी सुविधाएँ हट जाती हैं, इसलिए इसे desktop या महत्वपूर्ण environment में सीधे इस्तेमाल करना कठिन है
NixOS कॉन्फ़िगरेशन से ISO बनाना
- NixOS में कॉन्फ़िगरेशन के आधार पर VM आसानी से बनाया जा सकता है
nixos-rebuild build-vmमौजूदा system configuration का VM बनाता हैpkgs.nixosका उपयोग करके system configuration न होने पर भी मनचाहा configuration लेकर VM बनाया जा सकता है
- बुनियादी उदाहरण
system.stateVersion = "26.05"औरservices.getty.autologinUser = "root"के साथ एक न्यूनतम VM बनाता है - यह VM thin VM की तरह काम करता है
- disk image में सिर्फ वही फ़ाइलें जाती हैं जो VM के अंदर सीधे बनाई गई हों
/nix/storeजैसी बाकी चीज़ें host OS से mount होती हैं
- अगर host पर Nix नहीं है, या remote host, या सामान्य hypervisor पर चलाना हो, तो self-contained ISO चाहिए
- NixOS के
iso-image.nixmodule को import करके ISO build किया जा सकता हैimage.baseName = lib.mkForce "nixos"से output ISO का नाम तय होता है- चलाने का उदाहरण
qemu-system-x86_64 --cdrom .../nixos.iso -m 1G --accel kvmजैसा है - अगर environment amd64 का आधुनिक Linux नहीं है, तो architecture या acceleration method बदलनी पड़ सकती है
शुरुआती बिंदु: 458MiB ISO
- default ISO build का परिणाम 458MiB था
- इस image में अभी
vimभी शामिल नहीं था- boot के बाद
vimचलाने परcommand not foundआता था
- boot के बाद
- तुलना के लिए Alpine का VM ISO लगभग 66MiB का था
- Damn Small Linux का ज़िक्र ऐसे उदाहरण के रूप में आता है, जिसने बहुत छोटे आकार में भी अच्छा desktop environment दिया था
- लक्ष्य Damn Small Linux के स्तर तक पहुँचना नहीं, बल्कि यह देखना था कि NixOS ISO को कुछ हद तक और छोटा किया जा सकता है या नहीं
ISO के अंदर आकार का विश्लेषण
- ISO को mount करके
duसे देखने पर आकार का बँटवारा इस तरह थाnix-store.squashfs: 416MiB- initrd: 26MiB
- kernel: 13MiB
- पूरा ISO: 458MiB
- आकार का मुख्य कारण मुख्य user space यानी
nix-store.squashfsथा - squashfs को mount करने पर उसके अंदर Nix store जैसी paths दिखाई देती हैं
python3-3.13.13: 128MiBlinux-6.18.35-modules: 144MiBsystemd-260.1: 60MiBperl-5.42.0: 56MiBgrub-2.12: कई items मिलाकर लगभग 62MiBnix-manual-2.34.7,nixos-manual-htmlजैसे दस्तावेज़ भी शामिल थे
- ISO host पर build होती है, इसलिए ISO के अंदर की store paths को host के
/nix/storeमें भी trace किया जा सकता है nix why-dependsसे dependency के source की जाँच की गई- Boost, Nix daemon path के जरिए शामिल हो रहा था
nix-daemon.conf,nix,libnixutil.soके रास्तेboost-1.89.0तक पहुँचा गया
Nix और दस्तावेज़ हटाना
nix.enable = falseसे image से Nix को हटाने की कोशिश की गईdocumentation.enable = falseसे documentation भी बंद की गई- पहला परिणाम 458MiB → 384MiB था
- लेकिन Boost अभी भी बचा हुआ था
register-nix-paths.serviceboot के समय ISO store की contents register करने की कोशिश करता है- यही path फिर Nix और Boost को वापस खींच लाता है
systemd.services.register-nix-paths = lib.mkForce {}से उस service को खाली करके हटा दिया गया- इसके बाद ISO 360MiB का रह गया, और
nix why-dependsने पुष्टि की कि Boost dependency नहीं बची
OpenSSH और default packages हटाना
- इसी तरह
environment.defaultPackagesको भी खाली किया जा सका sshहटाना अधिक मुश्किल थाmodules/programs/ssh.nixOpenSSH कोenvironment.corePackagesमें जोड़ता है- इसे नियंत्रित करने के लिए
programs.ssh.enableजैसा विकल्प नहीं मिला services.openssh.enableserver configuration है, client हटाने का विकल्प नहीं
disabledModulesके जरिएprograms/ssh.nixको बाहर किया जा सकता था, लेकिन दूसरे modulesprograms.sshoption के मौजूद होने की अपेक्षा करते थे, जिससे chain errors आने लगे- समाधान यह था कि
programs.sshoption का उपयोग न करने वाला एक अलग stub option module दिया जाएoptions.programs.ssh = lib.mkOption {};- उसके बाद
disabledModules = [ "programs/ssh.nix" ];से असली SSH module को हटाया गया
- इस दौरान नीचे की settings भी साथ में लागू की गईं
documentation.man.enable = falsenetworking.firewall.enable = falseenvironment.defaultPackages = lib.mkForce []
NixOS module संरचना पर नोट
- NixOS modules को मोटे तौर पर तीन हिस्सों में बाँटा जा सकता है
- module-level items:
imports,disabledModules - option definitions:
options.* - implementation:
config.*
- module-level items:
- जो modules options define नहीं करते, वे
config.prefix के बिना implementation properties लिखने वाला संक्षिप्त रूप इस्तेमाल कर सकते हैं - बाकी configuration में यही संक्षिप्त रूप बनाए रखने के लिए
programs.sshstub option को अलग import module में रखा गया
GRUB installation tools हटाना
- बचे हुए बड़े items में से एक लगभग 62MiB के GRUB-संबंधित फ़ाइलें थीं
- bootloader खुद ज़रूरी है, लेकिन सारे installation tools शामिल करना आवश्यक नहीं माना गया
- NixOS ISO preset UEFI और BIOS दोनों versions के GRUB को bundle करता है
- इसे बंद करने का कोई स्पष्ट option नहीं मिला, इसलिए थोड़ा कठोर तरीका अपनाकर इन values को reset किया गया
system.extraDependencies = lib.mkForce []environment.systemPackages = lib.mkForce config.environment.corePackages
environment.systemPackagesको पूरी तरह खाली नहीं किया गया- अगर
bashन हो, तो getty लगातार crashloop में जा सकता है, इसलिए shell को कुछ हद तक काम करने देने के लिएcorePackagesरखे गए
- अगर
kernel modules हटाना
linux-6.18.35-modulesका आकार 144MiB था, यानी कुल आकार का लगभग एक-चौथाई- NixOS में runtime पर इस्तेमाल होने वाले kernel modules को सीमित करने के लिए कोई अच्छा hook नहीं दिखा
- इसकी जगह system output से
kernel-modulesफ़ोल्डर हटा दिया गयाsystem.systemBuilderCommands = lib.mkAfter "rm $out/kernel-modules";
- इस तरीके से runtime module loading लगभग निष्क्रिय हो गई
- ज़रूरी modules को
boot.initrd.kernelModulesयाavailableKernelModulesमें रखना पड़ेगा
- ज़रूरी modules को
- इस बदलाव के बाद अधिक सुविधाजनक display resolution पर switch करने की क्षमता खो गई, लेकिन boot होना संभव रहा
- ISO का आकार 197MiB तक घट गया
Perl हटाना और experimental replacement features
- अभी भी 56MiB का Perl शामिल था
nix why-dependsसे पता चला कि Perl system activation के दौरान users और/etcconfigure करने में इस्तेमाल हो रहा था- users और
/etcconfiguration को पूरी तरह छोड़ा नहीं जा सकता था - इसकी जगह experimental features के जरिए मौजूदा path बदला गया
/etcmanagement के लिए overlay method का उपयोग- user management के लिए native userborn का उपयोग
- लागू की गई settings ये थीं
system.etc.overlay.enable = truesystem.etc.overlay.mutable = falseservices.userborn.enable = true
- अंतिम ISO आकार 183MiB रह गया
अंतिम स्थिति और सीमाएँ
- शुरुआती 458MiB से घटकर अंतिम आकार 183MiB तक आ गया, यानी मूल का लगभग एक-तिहाई
- फिर भी इसे “अच्छा” कहना मुश्किल माना गया
- वास्तव में इस्तेमाल होने वाले desktop या महत्वपूर्ण environment के लिए यह उपयुक्त नहीं है
- हटाई गई सभी सुविधाओं के होने के अपने कारण हैं
- अगर छोटे experimental boot image की ज़रूरत हो और बहुत सीमित काम करना हो, तो यह उपयोगी संदर्भ हो सकता है
- अंतिम configuration को ज्यों का त्यों कॉपी करके इस्तेमाल करने पर आपके उद्देश्य के लिए ज़रूरी सुविधाएँ गायब हो सकती हैं
और छोटा करने की गुंजाइश
- इस काम में मुख्य ध्यान उन चीज़ों पर था जिन्हें “बस हटाया जा सकता था” या जिनके लिए अपेक्षाकृत साफ़ replacement उपलब्ध था
- कुछ ऐसे क्षेत्र अभी भी बचे हैं जहाँ और गहरा काम चाहिए
- इस समय
systemdMinimalऔरsystemdदोनों bundle हो रहे हैं - इनमें से किसी एक को हटाने की कोशिश करने पर दूसरी build path टूट जाती थी
- इस समय
- छोटे-छोटे items भी और हटाए जा सकते हैं, और कुल मिलाकर उनका असर सार्थक हो सकता है
- आगे की optimization के लिए और अधिक जाँच तथा प्रयोग की आवश्यकता है
1 टिप्पणियां
Lobste.rs की राय
ठीक इसी काम के लिए बना एक मॉड्यूल है। काफ़ी compilation चाहिए, लेकिन पूरा NixOS user space शामिल करने वाला पूरी तरह standalone initrd को zstd compression के साथ लगभग 80MiB तक बनाया जा सकता है
यह काम सिर्फ standalone initrd तक सीमित नहीं है, बल्कि किसी भी NixOS का आकार घटाने में इस्तेमाल हो सकता है। शायद install ISO पर भी लागू किया जा सकता है
https://github.com/wucke13/minimal-nixos/
TinyCore Linux का बेस सिस्टम 17MB का Core है
अगर X और FLTK/FLWM भी चाहिए तो 23MB का TinyCore है, और अगर ज़्यादा window managers और apps चाहिएँ तो 248MB का CorePlus है
http://www.tinycorelinux.net/downloads.html
NixCon में NixOS को Yocto alternative के रूप में छोटा करने पर हुई यह talk recommend करूँगा: https://youtu.be/AsXY61laNb8
यह उतनी detailed नहीं थी जितनी उम्मीद थी, लेकिन conference में Óli और Matthew से सीधे जो सुना वह काफ़ी शानदार था। सोच रहा हूँ क्या इसका कोई write-up है
NixOS में छोटा installation footprint बनाना हमेशा थोड़ा frustrating लगता है
SSH वाली तरफ़ का size नीचे की settings से कम किया जा सकता है
"${nixpkgs}/nixos/modules/profiles/minimal.nix"को भी import किया जा सकता है। उसमें post में की गई कुछ optimizations शामिल हैंफिर भी, ज़्यादातर मामलों में यह तरीका ज़्यादा समझदारी भरा हो सकता है
"${nixpkgs}/nixos/modules/profiles/minimal.nix"मैंने पहले देखा था, लेकिन लगा था कि यह उम्मीद से कम उपयोगी है, इसलिए investigation शुरू करते समय इसे शामिल करने का ख़याल नहीं आया। जब बाद में याद आया, तब तक मैं लगभग आधा काम कर चुका था, इसलिए उसे शुरुआत में होना चाहिए था वहाँ बाद में जोड़ना थोड़ा बेईमानी जैसा लगाआजकल अजीब लगता है कि Perl कितनी बार आधुनिक सिस्टम में खिंचकर आ जाता है। छोटे ISO में भी Perl, और अगर शुरू से कुछ ढंग की चीज़ compile करनी हो तो openssl -> Perl तक बात पहुँच जाती है
पढ़ने से पहले ही लगा था कि वजह कोई बेवकूफ़ी भरा Perl script होगा जिसे किसी ने C में rewrite नहीं किया
संपादन: हाँ, वही निकला
NixOS 26.05 से default initrd में systemd इस्तेमाल करता है। क्योंकि ऐसे कई initrd use cases हैं जिन्हें आधुनिक operating systems को support करना पड़ता है
systemdMinimalकम flags और dependencies के साथ compile किया गया systemd binary है, इसलिए यह initrd को छोटा रखने में मदद करता हैलेकिन अगर लक्ष्य minimal ISO है, तो लगता है दोनों को एक ही binary पर depend कराया जा सकता है