리눅스/LFS

[LFS1] 바닥부터 만드는 나만의 OS: VMware 환경에서 LFS 구축기

sik13579 2026. 1. 20. 12:49

1. 왜 'Linux From Scratch'인가?

우리는 보통 리눅스를 사용할 때 Ubuntu, Debian 같은 배포판을 설치합니다.

밥상 위에 숟가락만 얹는 셈이죠. 하지만 시스템 엔지니어나 보안 전문가에게 "OS가 어떻게 동작하는가?"라는 질문은 단순한 호기심 이상의 의미를 갖습니다.

 

 LFS는 아무것도 없는 무의 상태에서 컴파일러 하나로 커널, 라이브러리, 쉘을 하나하나 쌓아 올리는 과정입니다.
이 프로젝트를 시작한 이유는 명확합니다.

  • 시스템의 순수성 이해 : OS 내부의 유기적인 연결 고리를 파헤칩니다.
  • 인프라 보안의 기초 : 커널 수준에서 어떤 보안 설정이 가능한지, 불필요한 패키지를 걷어낸 초경량 시스템은 얼마나 안전한지 직접 확인하기 위함입니다.
  • 기술적 도전 : 32비트와 64비트를 모두 지원하는 Multilib(m32) 환경을 구축하여 시스템 호환성의 깊이를 이해하기 위함 입니다.

2. 빌드 환경 구축 (Host System)

LFS를 만들기 위해서는 먼저 '작업대'가 필요합니다. 이를 호스트(Host) 시스템이라고 부릅니다.

 

가상 머신 사양(VMware)

  • OS : Ubuntu 24.04 LTS 
  • CPU : 2 GHz dual-core 이상
  • Memory : 4 GB 이상
  • Storagge : 25GB 이상의 여유 공간 (LFS용 별도 디스크 포함)

호스트 시스템 필수 패키지 설치

Ubuntu를 갓 설치한 상태라면 LFS 빌드에 필요한 도구가 부족합니다.
아래 명령어로 컴파일러와 텍스트 처리 도구들을 설치해 줍니다.

sudo apt update
sudo apt install -y build-essential bison gawk m4 texinfo python3 patch bzip2 xz-utils libelf-dev

중요 포인트 

  • /bin/sh 체크 : Ubuntu는 기본 쉘이 dash로 되어 있지만, LFS의 빌드 스크립트들은 bash의 문법을 요구합니다.
    따라서 반드시 아래 명령어로 링크를 바꿔줘야 합니다.
sudo ln -sf bash /bin/sh

설정이 잘 되었는지 확인하려면 ls -l /bin/sh를 입력했을 때 ->bash라고 나오면 성공입니다.

 

호스트 시스템 검사 스크립트 실행

패키지 설치와 쉘 설정이 끝났다면, LFS 문서에서 제공하는 검사 스크립트를 실행해 모든 준비가 완벽한지 확인해야 합니다.

 

스크립트 파일 생성 : 

cat > version-check.sh << "EOF"
#!/bin/bash
export LC_ALL=C
bash --version | head -n1 | cut -d" " -f2-4
echo "/bin/sh -> `readlink -f /bin/sh`"
echo -n "Binutils: "; ld --version | head -n1 | cut -d" " -f3-
bison --version | head -n1
if [ -h /usr/bin/yacc ]; then echo "/usr/bin/yacc -> `readlink -f /usr/bin/yacc`";
elif [ -x /usr/bin/yacc ]; then echo yacc is `/usr/bin/yacc --version | head -n1`
else echo "yacc not found"; fi
bzip2 --version 2>&1 < /dev/null | head -n1 | cut -d" " -f1,6-
echo -n "Coreutils: "; chown --version | head -n1 | cut -d")" -f2
diff --version | head -n1
find --version | head -n1
gawk --version | head -n1
if [ -h /usr/bin/awk ]; then echo "/usr/bin/awk -> `readlink -f /usr/bin/awk`";
elif [ -x /usr/bin/awk ]; then echo awk is `/usr/bin/awk --version | head -n1`
else echo "awk not found"; fi
gcc --version | head -n1
g++ --version | head -n1
ldd --version | head -n1 | cut -d" " -f2-
grep --version | head -n1
gzip --version | head -n1
cat /proc/version
m4 --version | head -n1
make --version | head -n1
patch --version | head -n1
echo Perl `perl -V:version`
sed --version | head -n1
tar --version | head -n1
makeinfo --version | head -n1
xz --version | head -n1
echo 'int main(){}' > dummy.c && g++ -o dummy dummy.c
if [ -x dummy ]; then echo "g++ compilation OK";
else echo "g++ compilation failed"; fi
rm -f dummy.c dummy
EOF

 

스크립트 실행 : 

bash version-check.sh

 

결과 확인하기

스크립트를 실행했을 때 모든 항목의 버전 숫자가 출력되고 마지막에 g++ compilation OK가 나오면 준비 완료입니다.

만약 특정 항목이 "not found"라고 뜨면 해당 패키지를 apt install로 다시 설치해야 합니다.

3. 파티션과 파일 시스템

이제 LFS가 설치될 실제 공간을 준비할 차례입니다. VMware에서 추가한 빈 하드디스크(/dev/sdb)를 마운트해 봅시다.

 

파티션 생성 및 포맷

fdisk를 이용해 새 파티션을 만들고, 리눅스 표준인 ext4 파일 시스템으로 포맷합니다.

sudo fdisk /dev/sdb    # 파티션 생성 (n -> p -> 1 -> enter -> enter -> w)
sudo mkfs -v -t ext4 /dev/sdb1  # ext4로 포맷

 

마운트와 환경 변수 ($LFS)

LFS 빌드 과정에서 가장 중요한 변수인 $LFS를 설정합니다. 이 변수가 지정하는 경로가 곧 제가 만들 새로운 OS의 루트가 됩니다.

export LFS=/mnt/lfs
sudo mkdir -pv $LFS
sudo mount -v -t ext4 /dev/sdb1 $LFS

 

4. 격리된 작업 환경 : 'lfs' 유저

보안과 안정성을 위해 root 계정에서 직접 빌드하는 것은 금물입니다. 실수로 호스트 시스템의 파일 삭제하는 대참사를 막기 위해 전용 유저를 생성합니다.

groupadd lfs
useradd -s /bin/bash -g lfs -m -k /dev/null lfs
chown -v lfs $LFS/sources
chown -v lfs $LFS/tools

 

이제 lfs 유저의. bashrc에 $LFS 변수와 PATH를 등록함으로써, 언제든 터미널을 열면 바로 빌드 작업에 뛰어들 수 있는 최적의 환경을 갖췄습니다.

 

5. 패키지와 패치 (Packages and Patches)

집 터를 닦았으니 이제 집을 쌓을 재료들을 모아야 합니다. LFS는 수십 개의 오픈소스 패키지 소스 코드를 직접 컴파일하므로,
이들을 한데 모으고 관리하는 과정이 필수적입니다.

 

소스 디렉터리 생성 및 권한 설정

모든 소스 파일은 $LFS/sources 폴더에 저장합니다. 이 폴더는 lfs 유저가 자유롭게 접근할 수 있도록 권한을 부여해야 합니다.

mkdir -v $LFS/sources
chmod -v a+wt $LFS/sources  # 모든 유저가 쓸 수 있게 하되 삭제는 소유자만 가능하도록 설정

 

소스 코드 일괄 다운로드

LFS 공식 문서에서 제공하는 wget-list를 이용하면 필요한 모든 패키지와 패치 파일을 한 번에 내려받을 수 있습니다.

cd $LFS/sources
wget https://www.linuxfromscratch.org/~thomas/multilib-m32/wget-list
wget --input-file=wget-list --continue --directory-prefix=$LFS/sources
  • 패키지 종류 : Linux Kernel, GCC, Glibc, Binutils 등 핵심 도구부터 각종 유틸리티까지 포함됩니다.
  • 패치(Patches) : 특정 환경(특히 Multilib)에서 발생할 수 있는 버그를 수정하거나 기능을 개선하기 위해 필수적으로 적용해야 하는 수정 파일들입니다.

무결성 검증 (MD5 Checksum)

다운로드 중 파일이 깨지거나 변조되지 않았는지 확인하는 과정은 매우 중요합니다.

단 하나의 파일이라도 손상되면 수 시간의 빌드 작업이 수포로 돌아갈 수 있기 때문입니다.

wget https://www.linuxfromscratch.org/~thomas/multilib-m32/md5sums
md5sum -c md5sums

모든 파일 옆에 OK 가 뜨는 것을 확인합니다.

 

6. 현재 작업까지 진행하며 주의 사항

  1. Ubuntu 기본 쉘 dash를 bash로 심볼릭 링크를 변경해야 합니다.
    이거 안 하면 나중에 빌드 스크립트 다 깨집니다. 
  2. 반드시 전용 유저를 생성하고 소유권을 부여하여 안전한 '샌드박스' 환경 구축해야 합니다.
    앞서 말했다시피 실수로 호스트 시스템의 파일 삭제하는 대참사를 막기 위해 전용 유저를 생성해야 합니다.

 

 자! 이제 재료(Packages & Patches)는 모두 준비되었습니다. 
다음 포스팅에서는 임시 툴체인의 핵심인 BinutilsGCC Pass 1을 빌드하며 본격적인 리눅스 건축 과정을 다뤄보겠습니다.