From 8c023b595f9c0d8e30b0ffd3e1c9e1719837aa55 Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Wed, 26 Jun 2024 08:00:00 +0800 Subject: chroot-dev.html --- chroot-dev.html | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ index.html | 3 +- 2 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 chroot-dev.html diff --git a/chroot-dev.html b/chroot-dev.html new file mode 100644 index 0000000..e05cc47 --- /dev/null +++ b/chroot-dev.html @@ -0,0 +1,119 @@ + + + + + Using chroots as simple "containers" + + + + + + + + + +
+

Using chroots as simple "containers"

+
+ +
+

+ Please note that what I am about to do isn't actually containerization or isolation. It merely separates trusted code such that it would generally not pollute the host system. Chroot is generally not a security measure; for example, processes inside the chroot could easily escape with /proc/x/root for a PID x that runs outside the chroot. +

+

+ Often times I want to install a program that is not available in my current distribution (e.g. the Soju IRC bouncer is not available on Debian Bookworm, but I want to use a distribution-packaged version instead of running go build myself because I want to receive updates), or perhaps I want to run something like rustup without the fear of polluting my system. But I don't want to use Docker or LXC because they feel too complicated. +

+

+ I ended up creating Alpine Linux chroots. Specifically, Alpine Linux Edge, because the edge/testing repository is huge and frequently updated. There's an article called Alpine Linux in a chroot on the Alpine Linux wiki that provided the steps that I use in my scripts. (The official alpine-chroot-install scripts exist but haven't been updated for quite a while.) +

+

The rxchroot scripts

+

+ Check the Git repository linked above for the complete set of scripts; here is a short explanation from excerpts of the script. +

+

+ The first step, of course, is to create the chroot. Basically: +

+
umask 022 # or something else that ensures unprivileged users could access the chroot
+curl -LO "https://dl-cdn.alpinelinux.org/alpine/edge/main/${arch}/APKINDEX.tar.gz"
+tar xvf APKINDEX.tar.gz
+curl -LO "https://dl-cdn.alpinelinux.org/alpine/edge/main/${arch}/apk-tools-static-$(sed -n '/P:apk-tools-static/{n;p;}' APKINDEX | cut -d ':' -f 2).apk"
+tar -xzf apk-tools-static-*.apk
+./sbin/apk.static -X https://dl-cdn.alpinelinux.org/alpine/edge/main -U --allow-untrusted -p "${chroot_dir}" --initdb add alpine-base
+cp -L /etc/resolv.conf ${chroot_dir}/etc/
+mkdir -p "${chroot_dir}"/etc/apk
+echo "https://dl-cdn.alpinelinux.org/alpine/edge/main" > "${chroot_dir}"/etc/apk/repositories
+echo "https://dl-cdn.alpinelinux.org/alpine/edge/community" >> "${chroot_dir}"/etc/apk/repositories
+echo "https://dl-cdn.alpinelinux.org/alpine/edge/testing" >> "${chroot_dir}"/etc/apk/repositories
+

+ Every time the chroot needs to be used, some special directories must be mounted. Don't double-mount though as that often causes issues. +

+
mount -o bind /dev "${chroot_dir}/dev"
+mount -t proc none "${chroot_dir}/proc"
+mount -o bind /sys "${chroot_dir}/sys"
+

+ Then just enter the chroot: +

+
chroot "${chroot_dir}" /bin/ash -l
+

+ And perhaps install stuff: +

+
apk add build-base soju vim
+

+ I'm running on a Debian host, and perhaps I want to start services in the Alpine chroot with systemd: +

+
# alpine.service ###############################################
+
+[Unit]
+Description=Alpine chroot mounts
+Wants=network-online.target
+After=network-online.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=true
+User=root
+Group=root
+RuntimeDirectory=/alpine
+ExecStart=/root/rxchroot/alpine-chroot-activate /alpine
+ExecReload=/root/rxchroot/alpine-chroot-activate /alpine
+ExecStop=/root/rxchroot/alpine-chroot-deactivate /alpine
+
+[Install]
+WantedBy=multi-user.target
+
+# soju.service #################################################
+
+[Unit]
+Description=soju in an Alpine chroot
+Requires=alpine.service
+After=alpine.service
+
+[Service]
+Type=simple
+User=root
+Group=root
+# Fix the userspec to match the Alpine UID/GUID
+ExecStart=/sbin/chroot --userspec=101:102 /alpine /usr/bin/soju
+ExecReload=/bin/kill -HUP $MAINPID
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
+

Since a chroot doesn't have its own kernel and all system calls pass through the host kernel, network services open ports as if they just run in the host system.

+
+ + + + diff --git a/index.html b/index.html index db622e8..49824b2 100644 --- a/index.html +++ b/index.html @@ -54,7 +54,8 @@

Some of these are just stubs or quick notes.

See also: Documents archive