Skip to content

Instantly share code, notes, and snippets.

@abiosoft
Last active March 8, 2023 03:00
Show Gist options
  • Save abiosoft/64ccedb1ca206d5840e90fdc1422874d to your computer and use it in GitHub Desktop.
Save abiosoft/64ccedb1ca206d5840e90fdc1422874d to your computer and use it in GitHub Desktop.
Systemd Arch Machine

Arch Dev Container Setup

Prerequisites

Linux distro using Systemd with systemd-container package installed.

Install arch boostrap

$ curl -LO https://raw.githubusercontent.com/tokland/arch-bootstrap/master/arch-bootstrap.sh
$ sudo install -m 755 arch-bootstrap.sh /usr/local/bin/arch-bootstrap

Bootstrap

You can use other names apart from dev.

# arch-boostrap /var/lib/machines/dev

Prepare machine

enter machine with systemd-nspawn

# systemd-nspawn -D /var/lib/machines/dev

In the machine, set a root password and add pts/0 to /etc/securetty to allow root login on any tt.

# passwd
# echo "pts/0" >> /etc/securetty
# exit

Use host network [and setup folder mounts]

Edit /etc/systemd/nspawn/dev.nspawn and paste the following

[Service]
ExecStart=
ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --machine=%i 

[Files]
# Example bind, you can have multiple of this
# Bind=/home/user

# enable x11 for GUI apps
# BindReadOnly=/tmp/.X11-unix

Reload daemon

systemctl daemon-reload

Start machine

All should be done now. Start the machine with machinectl.

# machinectl start dev

If you want to have the machine start automatically

# machinectl enable dev

Connecting to machine

# machinectl login dev

You should be able to login with your previously set root password and have a functional arch linux container.

Misc

Grant non-root user read access to the container filesystem edit /usr/lib/tmpfiles.d/systemd-nspawn.conf and change to 0755 on the line Q /var/lib/machines 0700 - - -

#!/usr/bin/env bash
USAGE="machine-run MACHINE CMD [ARGS...]"
# show usage on empty args
if [ $# -eq 0 ]; then
>&2 echo "usage:"
>&2 echo " $USAGE"
exit 1
fi
machine="$1"
shift
ARGS=$@
# default to sh on missing command
if [ $# -eq 0 ]; then
ARGS="sh"
fi
# limit access to home directory
test "${PWD##/home/}" != "${PWD}"
if [[ $? -ne 0 ]]; then
>&2 echo "working directory must be within HOME"
exit 1
fi
# bind mount user configured directories
DIRS=$(grep -v "^[[:blank:]]*[#]" $HOME/.machinedirs 2> /dev/null)
BINDFLAGS=""
for a in ${DIRS[@]}
do
BINDFLAGS="${BINDFLAGS} --bind $a $a"
done
# exec
env -i bwrap \
--bind /var/lib/machines/$machine / \
$(echo $BINDFLAGS | envsubst) \
--bind $PWD $PWD \
--dev /dev \
--proc /proc \
--chdir $PWD \
--unshare-all \
--share-net \
--die-with-parent \
--uid $(id -u)\
--setenv HOME $HOME \
--setenv TERM xterm \
--setenv PATH "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" \
$ARGS
#!/usr/bin/env bash
# Consider adding the following to sudo file with `visudo` for smoother experience.
# Replace `user` with your user, `dev` with machine name.
# user ALL=(root) NOPASSWD: /usr/bin/systemd-run --pty -M dev --uid 1000 --quiet *
USAGE="machine-shell MACHINE CMD [ARGS...]"
# show usage on empty args
if [ $# -eq 0 ]; then
>&2 echo "usage:"
>&2 echo " $USAGE"
exit 1
fi
machine="$1"
shift
ARGS=$@
# default to sh on missing command
if [ $# -eq 0 ]; then
ARGS="sh"
fi
# validate machine
machinectl show $machine > /dev/null || exit 1
NSPAWNFILE="/etc/systemd/nspawn/$machine.nspawn"
# check configured bind dirs
DIRS=$(grep 'Bind=' $NSPAWNFILE 2> /dev/null | awk -F'=' '{print $2}')
VALIDDIR=1
WORKDIR=$PWD
for a in ${DIRS[@]}
do
# split directories with different paths on host/container. e.g. /host:/container
HDIR=$(echo $a | awk -F':' '{print $1}')
CDIR=$(echo $a | awk -F':' '{print $NF}')
test "${PWD##$HDIR}" != "${PWD}"
if [[ $? -eq 0 ]]; then
VALIDDIR=0
WORKDIR=$(echo $PWD | sed -e "s|$HDIR|$CDIR|")
fi
done
# limit access to mounted directory
if [[ $VALIDDIR -ne 0 ]]; then
>&2 echo "working directory must be in a mounted directory, configure at $NSPAWNFILE"
exit 1
fi
# exec
sudo systemd-run --pty -M $machine --uid $(id -u) --quiet /usr/bin/env -C $WORKDIR $ARGS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment