1 poin oleh GN⁺ 4 jam lalu | 1 komentar | Bagikan ke WhatsApp
  • NixOS memudahkan pembuatan VM atau ISO hanya dari konfigurasi, tetapi image live yang nyaris minimal pun sejak awal sudah berukuran 458MiB, jauh lebih besar dibanding ISO VM Alpine yang sekitar 66MiB
  • Sebagian besar ukuran diambil oleh nix-store.squashfs, yang berisi Python 3.13.13, Linux modules, systemd, Perl, GRUB, dokumentasi, dan dependensi terkait Nix
  • Setelah melalui nix.enable = false, documentation.enable = false, dan penghapusan register-nix-paths, ukuran ISO turun dari 458MiB → 384MiB → 360MiB, dan dependensi Boost juga hilang
  • Dengan menyingkirkan klien OpenSSH, paket bawaan, alat instalasi GRUB, modul kernel runtime, dan jalur aktivasi berbasis Perl, ukuran akhir turun hingga 183MiB
  • Ini bisa jadi referensi untuk image boot eksperimental berukuran kecil, tetapi karena banyak fungsi penting dihapus, hasilnya sulit dipakai apa adanya untuk desktop atau lingkungan penting

Membuat ISO dari konfigurasi NixOS

  • NixOS memudahkan pembuatan VM berbasis konfigurasi
    • nixos-rebuild build-vm membuat VM dari konfigurasi sistem saat ini
    • Dengan pkgs.nixos, VM juga bisa dibuat dari konfigurasi arbitrer meskipun bukan konfigurasi sistem aktif
  • Contoh dasar hanya memakai system.stateVersion = "26.05" dan services.getty.autologinUser = "root" untuk membuat VM minimal
  • VM ini bekerja sebagai thin VM
    • Image disk hanya berisi file yang dibuat langsung di dalam VM
    • Sisanya seperti /nix/store dimount dari OS host
  • Jika host tidak memiliki Nix, atau targetnya host jarak jauh maupun hypervisor umum, maka diperlukan ISO yang self-contained
  • Dengan mengimpor modul iso-image.nix milik NixOS, ISO bisa dibangun
    • image.baseName = lib.mkForce "nixos" menentukan nama file ISO keluaran
    • Contoh menjalankan: qemu-system-x86_64 --cdrom .../nixos.iso -m 1G --accel kvm
    • Jika bukan lingkungan Linux modern amd64, arsitektur atau metode akselerasinya mungkin perlu diubah

Titik awal: ISO 458MiB

  • Hasil build ISO bawaan berukuran 458MiB
  • Image ini bahkan belum menyertakan vim
    • Setelah boot, menjalankan vim menghasilkan command not found
  • Sebagai pembanding, ISO VM Alpine yang disebut berukuran sekitar 66MiB
  • Damn Small Linux juga disebut sebagai contoh yang dulu mampu memberi lingkungan desktop yang matang dalam ukuran jauh lebih kecil
  • Tujuannya bukan menyamai Damn Small Linux, melainkan melihat apakah ukuran ISO NixOS setidaknya bisa diperkecil sampai batas tertentu

Analisis ukuran di dalam ISO

  • Setelah ISO dimount dan diperiksa dengan du, pembagian ukurannya seperti berikut
    • nix-store.squashfs: 416MiB
    • initrd: 26MiB
    • kernel: 13MiB
    • total ISO: 458MiB
  • Faktor ukuran utama adalah ruang user-space utama, yaitu nix-store.squashfs
  • Saat squashfs dimount, isinya terlihat seperti path di Nix store
    • python3-3.13.13: 128MiB
    • linux-6.18.35-modules: 144MiB
    • systemd-260.1: 60MiB
    • perl-5.42.0: 56MiB
    • grub-2.12: total beberapa item sekitar 62MiB
    • Dokumentasi seperti nix-manual-2.34.7, nixos-manual-html, dan lainnya juga ikut masuk
  • Karena ISO dibangun di host, path store di dalam ISO juga bisa ditelusuri dari /nix/store milik host
  • Asal dependensi diperiksa dengan nix why-depends
    • Boost masuk melalui jalur Nix daemon
    • Rutenya melewati nix-daemon.conf, nix, libnixutil.so, lalu sampai ke boost-1.89.0

Menghapus Nix dan dokumentasi

  • nix.enable = false dicoba untuk menghapus Nix itu sendiri dari image
  • Dokumentasi juga dimatikan dengan documentation.enable = false
  • Hasil pertama: 458MiB → 384MiB
  • Namun Boost masih tetap ada
    • register-nix-paths.service mencoba mendaftarkan isi store ISO saat boot
    • Jalur ini kembali menarik Nix dan Boost masuk
  • Layanan tersebut dikosongkan dan dihapus dengan systemd.services.register-nix-paths = lib.mkForce {}
  • Hasilnya ISO menjadi 360MiB, dan nix why-depends mengonfirmasi bahwa dependensi Boost sudah hilang

Menghapus OpenSSH dan paket bawaan

  • Dengan cara serupa, environment.defaultPackages juga bisa dikosongkan
  • Penghapusan ssh lebih rumit
    • modules/programs/ssh.nix menambahkan OpenSSH ke environment.corePackages
    • Tidak ditemukan opsi seperti programs.ssh.enable untuk mengendalikannya
    • services.openssh.enable adalah pengaturan server, bukan opsi untuk membuang klien
  • programs/ssh.nix memang bisa dikecualikan dengan disabledModules, tetapi modul lain mengasumsikan opsi programs.ssh tetap ada sehingga memicu error berantai
  • Solusinya adalah menyediakan opsi stub terpisah yang tidak memakai opsi programs.ssh
    • options.programs.ssh = lib.mkOption {};
    • Lalu modul SSH asli dikecualikan dengan disabledModules = [ "programs/ssh.nix" ];
  • Dalam proses ini, pengaturan berikut juga diterapkan
    • documentation.man.enable = false
    • networking.firewall.enable = false
    • environment.defaultPackages = lib.mkForce []

Catatan tentang struktur modul NixOS

  • Modul NixOS secara umum terdiri dari tiga bagian besar
    • Item tingkat modul: imports, disabledModules
    • Definisi opsi: options.*
    • Implementasi: config.*
  • Modul yang tidak mendefinisikan opsi bisa memakai bentuk singkat dengan properti implementasi tanpa awalan config.
  • Agar bentuk singkat tetap bisa dipakai pada konfigurasi lainnya, opsi stub programs.ssh dipisahkan ke modul impor tersendiri

Menghapus alat instalasi GRUB

  • Salah satu item besar yang tersisa adalah file terkait GRUB sekitar 62MiB
  • Bootloader itu sendiri masih dibutuhkan, tetapi tidak semua alat instalasinya perlu ikut disertakan
  • Preset ISO NixOS membundel GRUB versi UEFI dan BIOS sekaligus
  • Karena tidak ada opsi yang jelas untuk mematikannya, dipakai cara yang lebih kasar dengan mereset nilai berikut
    • system.extraDependencies = lib.mkForce []
    • environment.systemPackages = lib.mkForce config.environment.corePackages
  • environment.systemPackages tidak dikosongkan total
    • Tanpa bash, getty bisa terus crashloop, jadi corePackages tetap dipertahankan agar shell masih bisa berfungsi sampai batas tertentu

Menghapus modul kernel

  • linux-6.18.35-modules berukuran 144MiB, sekitar seperempat dari total ukuran
  • Di NixOS tidak terlihat ada hook yang baik untuk membatasi modul kernel yang dipakai saat runtime
  • Sebagai gantinya, folder kernel-modules dihapus dari keluaran sistem
    • system.systemBuilderCommands = lib.mkAfter "rm $out/kernel-modules";
  • Cara ini pada dasarnya menonaktifkan pemuatan modul runtime
    • Modul yang dibutuhkan harus dimasukkan ke boot.initrd.kernelModules atau availableKernelModules
  • Setelah perubahan ini, kemampuan beralih ke resolusi layar yang lebih nyaman hilang, tetapi sistem masih bisa boot
  • Ukuran ISO turun lagi menjadi 197MiB

Menghapus Perl dan fitur pengganti eksperimental

  • Perl sebesar 56MiB masih ikut terbawa
  • Dari nix why-depends, Perl dipakai saat aktivasi sistem untuk menyusun user dan /etc
  • Penyusunan user dan /etc tidak bisa dibuang sepenuhnya
  • Sebagai gantinya, jalur lama diganti dengan fitur eksperimental
    • Pengelolaan /etc memakai pendekatan overlay
    • Pengelolaan user memakai userborn native
  • Konfigurasi yang diterapkan adalah
    • system.etc.overlay.enable = true
    • system.etc.overlay.mutable = false
    • services.userborn.enable = true
  • Ukuran ISO akhir menjadi 183MiB

Hasil akhir dan keterbatasan

  • Dari titik awal 458MiB, ukuran akhirnya turun menjadi 183MiB, hampir sepertiga dari ukuran awal
  • Meski begitu, hasilnya masih sulit disebut “bagus”
  • Ini tidak cocok untuk desktop yang benar-benar akan dipakai atau lingkungan penting
    • Semua fitur yang dihapus memang ada alasannya
  • Jika yang dibutuhkan adalah image boot kecil untuk eksperimen dan hanya menjalankan tugas yang sangat terbatas, hasil ini bisa dijadikan referensi
  • Menyalin konfigurasi akhir apa adanya juga berisiko membuat fungsi yang dibutuhkan justru hilang

Peluang pengurangan lebih lanjut

  • Pekerjaan kali ini fokus pada hal-hal yang “bisa langsung dibuang” atau punya alternatif yang relatif jelas
  • Masih ada area yang butuh pekerjaan lebih dalam
    • Saat ini systemdMinimal dan systemd sama-sama dibundel
    • Saat mencoba membuang salah satunya, jalur build lain justru rusak
  • Item-item kecil lainnya juga masih bisa terus dibersihkan, dan jika dijumlahkan ukurannya bisa tetap berarti
  • Optimalisasi tambahan masih memerlukan lebih banyak riset dan eksperimen

1 komentar

 
GN⁺ 4 jam lalu
Komentar Lobste.rs
  • Ada modul yang dibuat tepat untuk kegunaan seperti ini. Memang perlu cukup banyak kompilasi, tetapi bisa membuat initrd mandiri sepenuhnya yang mencakup seluruh user space NixOS menjadi sekitar 80MiB dengan kompresi zstd
    Pekerjaan ini tidak terbatas hanya pada initrd mandiri, dan bisa dipakai untuk mengurangi ukuran NixOS apa pun. Mungkin juga bisa diterapkan pada ISO instalasi
    https://github.com/wucke13/minimal-nixos/

  • Sistem dasar TinyCore Linux adalah Core berukuran 17MB
    Jika ingin X dan FLTK/FLWM juga, ada TinyCore berukuran 23MB, dan jika ingin lebih banyak window manager serta aplikasi, ada CorePlus berukuran 248MB
    http://www.tinycorelinux.net/downloads.html

    • Saya tidak tahu apa hubungannya itu dengan konfigurasi deklaratif atau VM yang dapat direproduksi
  • Saya merekomendasikan presentasi di NixCon tentang mengecilkan NixOS sebagai alternatif Yocto: https://youtu.be/AsXY61laNb8
    Tidak sedetail yang saya harapkan, tetapi apa yang saya dengar langsung dari Óli dan Matthew di konferensi sangat mengesankan. Saya penasaran apakah ada tulisan rangkumannya

  • Di NixOS, rasanya selalu agak frustrasi saat mencoba membuat jejak instalasi yang kecil
    Ukuran bagian SSH sepertinya bisa dikurangi dengan pengaturan berikut

    programs.ssh.setXAuthLocation = false;  
    security.pam.services.su.forwardXAuth = lib.mkForce false;  
    fonts.fontconfig.enable = false;  
    

    "${nixpkgs}/nixos/modules/profiles/minimal.nix" juga bisa di-import. Di situ sudah ada sebagian optimasi yang disebut di tulisan

    • Dalam kasus penggunaan yang mendorong saya menulis tulisan aslinya, sebenarnya ssh sendiri hampir tidak diperlukan
      Meski begitu, dalam kebanyakan kasus pendekatan ini kemungkinan lebih masuk akal
      "${nixpkgs}/nixos/modules/profiles/minimal.nix" pernah saya lihat sebelumnya dan terasa kurang memuaskan dibanding harapan, jadi saya tidak terpikir untuk memasukkannya saat mulai menyelidiki. Ketika saya teringat lagi belakangan, pekerjaan saya sudah setengah jalan, jadi rasanya agak tidak jujur untuk menyelipkannya ke tahap awal yang seharusnya memang memasukkannya sejak awal
  • Aneh sekali bahwa Perl terlalu sering ikut tertarik masuk ke sistem modern. Bahkan untuk ISO kecil pun ada Perl, dan saat mencoba mengompilasi sesuatu yang layak dari awal pun jadinya openssl -> Perl

  • Bahkan sebelum membaca, saya menduga ini gara-gara skrip Perl bodoh yang belum ditulis ulang ke C
    Edit: ternyata benar

  • Mulai 26.05, NixOS menggunakan systemd di initrd bawaan. Alasannya karena ada banyak kasus penggunaan initrd yang perlu didukung sistem operasi modern
    systemdMinimal adalah biner systemd yang dikompilasi dengan lebih sedikit flag dan dependensi, sehingga membantu menjaga ukuran initrd tetap kecil
    Namun, jika targetnya adalah ISO minimal, tampaknya keduanya juga bisa dibuat bergantung pada biner yang sama