Chroot
chroot (루트 바꾸기)는 메인 시스템의 루트에서 논리적으로 나누는 새 환경을 만들때 눈에 보이는 루트 디렉터리를 바꾸는데 사용하는 유닉스 시스템 유틸리티입니다. 이 새 환경은 "chroot 감옥"으로 알려져 있습니다. 감옥 안의 chroot 감옥에 가둬진 이상 사용자 운영 내부를 보거나 외부로의 파일 접근이 불가능합니다.
chroot의 주된 사용 목적은 테스트나 프로그램 호환성을 이유로 현재의 최상단 리눅스 시스템에서의 분할 시스템 만들기 입니다. 종종 가상화의 간편한 대안이기도 한데, chroot는 하이퍼바이저의 부담없이 실행할 수 있기 때문입니다.
선행 과정
환경 설정
chroot를 새로 설정할 때 처음 필요한 건 chroot로 진입할 디렉터리입니다. 예를 들자면, /mnt/mychroot에 chroot를 만들 수 있습니다.
user $
mkdir /mnt/mychroot
user $
cd /mnt/mychroot
파티션에 이미 있는 설치로 마운트 하려면 다음과 같이 하시면 됩니다. 하단의 예제에서 <DEVICE>
문자열 대신, 기존 설치 환경에 있는 드라이브 와 파티션으로 바꾸십시오:
user $
mkdir /mnt/mychroot
user $
mount /dev/DEVICE /mnt/mychroot
현재 루트 파일 시스템의 하위 디렉터리에 이미 설치했다면 위 단계를 건너뛸 수 있습니다:
시스템 파일 및 포티지 트리 압축 해제(새 설치)
새 설치를 빌드한다면 다음 단계는 스테이지 3와 포티지 다르볼을 다운로드 하고 chroot 위치로 설치하는 것입니다. 이 과정에 대한 더 많은 정보를 보려면 젠투 핸드북의 스테이지 타르볼 다운로드 와 스테이지 타르볼 압축 해제를 참고하십시오.
root #
tar xvjpf stage3-*.tar.bz2 -C /mnt/mychroot
root #
links http://distfiles.gentoo.org/snapshots/
root #
tar xvjf portage-*.tar.bz2 -C /mnt/mychroot/usr
설정
chroot로 진입하기 전 몇가지 디렉터리를 마운트해야 합니다:
root #
mount --rbind /dev /mnt/mychroot/dev
root #
mount --make-rslave /mnt/mychroot/dev
root #
mount -t proc /proc /mnt/mychroot/proc
root #
mount --rbind /sys /mnt/mychroot/sys
root #
mount --make-rslave /mnt/mychroot/sys
root #
mount --rbind /tmp /mnt/mychroot/tmp
그리고 호스트로부터 몇가지 기본 설정 파일을 복사해야 하는데, 기존 설치에서 이미 make.conf를 사용중이면 복사하지 마십시오:
user $
cp /etc/portage/make.conf /mnt/mychroot/etc/portage # If you use an existing installation, skip this command.
user $
cp /etc/resolv.conf /mnt/mychroot/etc
사용법
끝내고 나면 다음 명령을 실행하여 chroot 환경으로 진입할 수 있습니다:
root #
chroot /mnt/mychroot /bin/bash
root #
source /etc/profile
root #
env-update
root #
export PS1="(chroot) $PS1"
새로 설치할 때 모든 항목이 최신인지 확인하려면 포티지를 동기화 해야합니다.
(chroot) root #
emerge --sync
시스템을 준비했습니다. 프로그램을 설치하고, 문자열로 화면을 어지럽히며 시험 패키지를 테스트하고, 메인 시스템에 영향을 주지 않는 설정을 할 수 있습니다. chroot에서 빠져나가려면 exit를 입력하거나 Ctrl+d를 입력하시면 됩니다. 이렇게 하면 보통 환경으로 되돌아갈 수 있습니다. 마운트한 디렉터리에 대해 umount 명령 실행을 잊지 마십시오.
systemd-nspawn
If the system uses systemd, systemd-nspawn can be used, which can automatically handle much of the boilerplate required in administering chroots. For example, to enter a chroot via systemd-nspawn with the same configuration as specified in the Configuration section, simply run:
root #
cp /etc/portage/make.conf /mnt/mychroot/etc/portage
root #
systemd-nspawn -D /mnt/mychroot --bind=/tmp --resolv-conf=/etc/resolv.conf
초기화 스크립트
chroot 작업을 자주 사용하도록 설정했다면 init 스크립트로 디렉터리 마운트를 빠르게 진행할 수 있습니다. 시스템을 부팅할 때 자동으로 설정하도록 기본 런레벨에 스크립트를 추가할 수 있습니다:
#!/sbin/openrc-run
depend() {
need localmount
need bootmisc
}
start() {
ebegin "Mounting chroot directories"
mount -o rbind /dev /mnt/mychroot/dev > /dev/null &
mount -t proc none /mnt/mychroot/proc > /dev/null &
mount -o bind /sys /mnt/mychroot/sys > /dev/null &
mount -o bind /tmp /mnt/mychroot/tmp > /dev/null &
eend $? "An error occurred while mounting chroot directories"
}
stop() {
ebegin "Unmounting chroot directories"
umount -f /mnt/mychroot/dev > /dev/null &
umount -f /mnt/mychroot/proc > /dev/null &
umount -f /mnt/mychroot/sys > /dev/null &
umount -f /mnt/mychroot/tmp > /dev/null &
eend $? "An error occurred while unmounting chroot directories"
}
다른 디렉터리나 파티션을 사용한다면, 필요한 마운트 명령을 start()
에 적고, /mnt/chroot을 적당한 이름으로 바꾸십시오.
Sound and graphics
The software running inside the chroot will by default not have access to the system sound- and display-server. Fixing this is done by either sharing a socket, or by running the communication with TCP over localhost.
Wayland
Wayland uses a socket to connect clients with the compositor. This socket needs to be shared with the chroot to make graphical applications work. The general procedure for finding this socket is:[1]
- If WAYLAND_SOCKET is set, interpret it as a file descriptor number on which the connection is already established, assuming that the parent process configured the connection for us.
- If WAYLAND_DISPLAY is set, concat with XDG_RUNTIME_DIR to form the path to the Unix socket.
- Assume the socket name is
wayland-0
and concat with XDG_RUNTIME_DIR to form the path to the Unix socket.
Using WAYLAND_DISPLAY and XDG_RUNTIME_DIR is fine in most cases and will be used here. By default XDG_RUNTIME_DIR is set to /run/user/$(uid). This directory will not be available in the chroot because the #Configuration instructions bind mounts /run non-recursively. Assuming the user's uid is 1000, this can be solved by either bind-mounting /run/user/1000 with:
root #
mkdir -p /mnt/mychroot/run/user/1000
root #
mount --bind /run/user/1000 /mnt/mychroot/run/user/1000
or by simply recursively bind mounting /run with:
root #
mount --rbind /run /mnt/mychroot/run
The Wayland library dev-libs/wayland uses the same procedure for finding out the socket as listed above. So to share the socket with the chroot, the only thing that's needed to do is defining XDG_RUNTIME_DIR and WAYLAND_DISPLAY. Here it is assumed that the Wayland socket name WAYLAND_DISPLAY is wayland-0
.
(chroot) root #
useradd -m user
(chroot) root #
su -l user
(chroot) user $
export XDG_RUNTIME_DIR=/run/user/1000
(chroot) user $
export WAYLAND_DISPLAY=wayland-0
(chroot) user $
MOZ_ENABLE_WAYLAND=1 firefox-bin
Permission errors will occur if the user in the chroot does not have permissions to access the Wayland socket. This can be solved by using user namespace remapping or ACLs. The easiest solution is to just make sure that the user ids match. The useradd -u, --uid UID option can be used when creating a user.
PipeWire
Like Wayland, PipeWire uses a socket to connect clients to the PipeWire daemon.
Applications assume that the PipeWire socket will be located in ${XDG_RUNTIME_DIR}/pipewire-0
,
so the only thing that's needed to get PipeWire clients to connect to the host's daemon is to expose
XDG_RUNTIME_DIR to the chroot. This process is identical to the one described in #Wayland.
To expose XDG_RUNTIME_DIR, often /run/user/$(uid), the following commands are used:
root #
mkdir -p /mnt/mychroot/run/user/1000
root #
mount --bind /run/user/1000 /mnt/mychroot/run/user/1000
XDG_RUNTIME_DIR will not be set when logging in inside the chroot, therefore XDG_RUNTIME_DIR needs to exported so the PipeWire client can find the socket:
(chroot) user $
export XDG_RUNTIME_DIR=/run/user/1000
(chroot) user $
pw-cli
Xorg
Xorg by default listens on a socket located in /tmp/.X11-unix/X${DISPLAY}
, as well as on localhost TCP port 6000 + ${DISPLAY}
[2]. The instructions in #Configuration bind mounts /tmp, and therefore no additional configuration is needed except setting the DISPLAY variable before running a graphical application:
(chroot) user $
DISPLAY=:0 firefox-bin
If the uid of the user inside the chroot does not match the uid outside the chroot, then setting permissions with xhost will be needed. To allow all local connections, run outside the chroot:
user $
xhost +local:
추가 참조
External resources
- chroot on Archlinux's wiki
References
- ↑ https://wayland-book.com/protocol-design/wire-protocol.html
- ↑ So if DISPLAY=:12, then Xorg will listen on localhost TCP port 6012