더 작은 NixOS ISO를 만들 수 있을까?
요약
NixOS의 기본 ISO 크기를 분석하고, 불필요한 패키지와 의존성을 제거하여 크기를 최적화하는 실험 과정을 다룹니다. Python, Perl, 문서 등 주요 구성 요소를 제외함으로써 458MiB에서 183MiB까지 용량을 줄이는 방법을 제시합니다.
핵심 포인트
- NixOS 기본 ISO는 약 458MiB로 구성됨
- nix-store.squashfs가 전체 크기의 대부분을 차지함
- 문서, Python, Perl, Boost 등 의존성 제거로 크기 최적화 가능
- 최종적으로 183MiB까지 축소 가능하나 기능 제한 주의
NixOS는 설정만으로 VM이나 ISO를 만들기 쉽지만, 최소에 가까운 라이브 이미지도 처음부터 458MiB 로 생성되어 Alpine VM ISO 약 66MiB 와 큰 차이를 보임
크기의 대부분은 nix-store.squashfs 가 차지했고, 그 안에는 Python 3.13.13, Linux modules, systemd, Perl, GRUB, 문서, Nix 관련 의존성이 들어 있었음
nix.enable = false
, documentation.enable = false
, register-nix-paths
제거를 거치며 ISO는 458MiB → 384MiB → 360MiB 로 줄었고 Boost 의존성도 빠짐
OpenSSH 클라이언트, 기본 패키지, GRUB 설치 도구, 런타임 커널 모듈, Perl 기반 활성화 경로까지 걷어내 최종 크기는 183MiB 까지 내려감
작은 실험용 부팅 이미지에는 참고할 만하지만, 필요한 기능을 많이 제거하므로 데스크톱이나 중요한 환경에 그대로 쓰기는 어려움
NixOS 설정에서 ISO 만들기
NixOS 는 설정을 기반으로 VM을 쉽게 만들 수 있음
nixos-rebuild build-vm
은 현재 시스템 설정의 VM을 생성함
pkgs.nixos
를 사용하면 시스템 설정이 아니더라도 임의 설정으로 VM을 만들 수 있음
기본 예시는 system.stateVersion = "26.05"
와 services.getty.autologinUser = "root"
만 둔 최소 VM을 생성함
이 VM은 thin VM 으로 동작함
디스크 이미지에는 VM 안에서 직접 만든 파일만 들어감
/nix/store
등 나머지는 호스트 OS에서 마운트됨
호스트에 Nix가 없거나 원격 호스트, 일반 하이퍼바이저에서 실행하려면 자체 포함 ISO 가 필요함
NixOS의 iso-image.nix
모듈을 import하면 ISO를 빌드할 수 있음
image.baseName = lib.mkForce "nixos"
로 출력 ISO 이름을 지정함
실행 예시는 qemu-system-x86_64 --cdrom .../nixos.iso -m 1G --accel kvm
형태임
amd64의 현대 Linux 환경이 아니라면 아키텍처나 가속 방식 변경이 필요할 수 있음
시작점: 458MiB ISO
기본 ISO 빌드 결과는 458MiB 였음
이 이미지는 아직 vim
도 포함하지 않음
부팅 후 vim
실행 시 command not found
가 나옴
비교 대상으로 든 Alpine의 VM ISO는 약 66MiB 임
Damn Small Linux는 훨씬 작은 크기로 완성도 있는 데스크톱 환경을 제공했던 사례로 등장함
목표는 Damn Small Linux 수준에 도달하는 것이 아니라, NixOS ISO를 어느 정도라도 더 줄일 수 있는지 확인하는 데 있음
ISO 내부 크기 분석
ISO를 마운트해 du
로 확인하니 크기는 다음처럼 나뉨
nix-store.squashfs
: 416MiB
initrd: 26MiB
kernel: 13MiB
전체 ISO: 458MiB
핵심 크기 요인은 주 사용자 공간 인 nix-store.squashfs
였음
squashfs를 마운트하면 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
: 여러 항목 합산 약 62MiB
nix-manual-2.34.7
, nixos-manual-html
등 문서도 포함됨
ISO는 호스트에서 빌드되므로, ISO 안의 store 경로는 호스트 /nix/store
에서도 추적할 수 있음
nix why-depends
로 의존성의 출처를 확인함
Boost는 Nix daemon 경로를 통해 들어왔음
nix-daemon.conf
, nix
, libnixutil.so
를 거쳐 boost-1.89.0
에 도달함
Nix와 문서 제거
nix.enable = false
로 Nix 자체를 이미지에서 제거하려고 시도함
documentation.enable = false
로 문서도 비활성화함
첫 결과는 458MiB → 384MiB 였음
하지만 Boost는 여전히 남아 있었음
register-nix-paths.service
가 ISO store 내용을 부팅 시 등록하려고 함
이 경로가 다시 Nix와 Boost를 끌어옴
systemd.services.register-nix-paths = lib.mkForce {}
로 해당 서비스를 비워 제거함
그 결과 ISO는 360MiB 가 되었고, nix why-depends
에서 Boost 의존성이 없다고 확인됨
OpenSSH와 기본 패키지 제거
비슷한 방식으로 environment.defaultPackages
도 비울 수 있었음
ssh
제거는 더 까다로웠음
modules/programs/ssh.nix
가 OpenSSH를 environment.corePackages
에 추가함
이를 제어할 programs.ssh.enable
같은 옵션을 찾을 수 없었음
services.openssh.enable
은 서버 설정이지 클라이언트 제거 옵션이 아님
disabledModules
로 programs/ssh.nix
를 제외할 수는 있었지만, 다른 모듈들이 programs.ssh
옵션 존재를 기대해 연쇄 오류가 발생함
해결책은 programs.ssh
옵션을 쓰지 않는 stub 옵션 을 별도 모듈로 제공하는 방식이었음
options.programs.ssh = lib.mkOption {};
이후 disabledModules = [ "programs/ssh.nix" ];
로 실제 SSH 모듈을 제외함
이 과정에서 다음 설정도 함께 적용함
documentation.man.enable = false
networking.firewall.enable = false
environment.defaultPackages = lib.mkForce []
NixOS 모듈 구조 메모
NixOS 모듈은 크게 세 부분을 가짐
모듈 수준 항목: imports
, disabledModules
옵션 정의: options.*
구현: config.*
옵션을 정의하지 않는 모듈은 config.
접두어 없이 구현 속성을 쓰는 축약형을 사용할 수 있음
나머지 설정에서 축약형을 유지하기 위해, programs.ssh
stub 옵션은 별도 import 모듈로 분리함
GRUB 설치 도구 제거
남은 큰 항목 중 하나는 약 62MiB 의 GRUB 관련 파일이었음
부트로더 자체는 필요하지만, 설치 도구를 모두 포함할 필요는 없다고 판단함
NixOS ISO preset은 UEFI와 BIOS 버전 GRUB를 모두 번들함
이를 끄는 명확한 옵션은 없어, 더 거친 방식으로 다음 값을 재설정함
system.extraDependencies = lib.mkForce []
environment.systemPackages = lib.mkForce config.environment.corePackages
environment.systemPackages
를 완전히 비우지는 않음
bash
가 없으면 getty가 계속 crashloop할 수 있어, 셸이 어느 정도 동작하도록 corePackages
는 유지함
커널 모듈 제거
linux-6.18.35-modules
는 144MiB 였고, 전체 크기의 약 4분의 1에 해당함
NixOS에는 런타임에 사용할 커널 모듈을 제한하는 좋은 훅이 보이지 않았음
대신 시스템 출력에서 kernel-modules
폴더를 제거함
system.systemBuilderCommands = lib.mkAfter "rm $out/kernel-modules";
이 방식은 런타임 모듈 로딩을 사실상 비활성화 함
필요한 모듈은 boot.initrd.kernelModules
또는 availableKernelModules
에 넣어야 함
이 변경 뒤 더 편한 디스플레이 해상도로 전환하는 기능을 잃었지만, 부팅은 가능했음
ISO 크기는 197MiB 까지 내려감
Perl 제거와 실험적 대체 기능
여전히 56MiB 의 Perl 이 포함되어 있었음
nix why-depends
로 확인하니 Perl은 시스템 활성화 중 사용자와 /etc
를 구성하는 데 쓰였음
사용자와 /etc
구성을 완전히 버릴 수는 없었음
대신 실험적 기능으로 기존 경로를 대체함
/etc
관리는 overlay 방식 사용
사용자 관리는 native userborn 사용
적용한 설정은 다음과 같음
system.etc.overlay.enable = true
system.etc.overlay.mutable = false
services.userborn.enable = true
최종 ISO 크기는 183MiB 가 됨
최종 상태와 한계
시작점 458MiB 에서 최종 183MiB 까지 줄어, 원본의 거의 3분의 1 수준이 됨
그래도 결과를 “좋다”고 부르기는 어렵다고 봄
실제로 사용해야 하는 데스크톱이나 중요한 환경에는 적합하지 않음
작은 실험용 부팅 이미지가 필요하고 아주 작은 작업만 수행하면 되는 경우에는 참고할 수 있음
최종 설정을 그대로 복사해 쓰면 목적에 필요한 기능이 빠져 있을 수 있음
더 줄일 여지
이번 작업은 “그냥 제거 가능”하거나 비교적 명확한 대체 수단이 있는 항목에 집중함
더 깊은 작업이 필요한 영역도 남아 있음
현재 systemdMinimal
과 systemd
가 모두 번들됨
둘 중 하나를 제거하려고 하면 다른 빌드 경로가 깨졌음
작은 항목들도 더 걷어낼 수 있고, 합산하면 의미 있는 크기가 될 수 있음
추가 최적화에는 더 많은 조사와 실험이 필요함
댓글과 토론
AI 자동 생성 콘텐츠
본 콘텐츠는 GeekNews의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기