| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- #!/bin/sh
- set -xeu
- chroot_dir="/mnt"
- arch="$(uname -m)"
- mirror="https://dl-cdn.alpinelinux.org/alpine"
- alpine_version="v3.20"
- apk_version="2.14.4-r1"
- apk_link="${mirror}/${alpine_version}/main/${arch}/apk-tools-static-${apk_version}.apk"
- fatal() {
- echo "$1" >&2
- }
- die() {
- fatal "$2"
- exit "$1"
- }
- usage() {
- cat >&2 <<EOF
- Usage: $0 <action> [-r <chroot_dir>] [-h]
- Action:
- rootfs deploy alpine rootfs in <chroot_dir>
- setup setup rootfs inside chroot environment
- full deploy rootfs and run setup inside chroot
- Options:
- -r <chroot_dir> specify chroot directory
- [default: $chroot_dir]
- -h show this help message
- EOF
- exit "$1"
- }
- ensure_root() {
- if [ "$(id -u)" = 0 ]; then
- return 0
- fi
- die 1 "The script must be run as root"
- }
- parse_action() {
- case "$1" in
- rootfs|setup|full) action="$1" ;;
- *)
- fatal "unknown op: $1"
- usage 1
- ;;
- esac
- }
- parse_args() {
- [ "$#" -lt 1 ] && usage 1
- parse_action "$1" && shift
- while getopts "r:h" opt; do
- case "$opt" in
- r) chroot_dir="$(realpath "$OPTARG")" ;;
- h) usage 0 ;;
- ?) usage 1 ;;
- esac
- done
- }
- # download static apk and print the executable filename
- download_apk() {
- local tmpdir
- tmpdir="$(mktemp -d)"
- curl -L "$apk_link" | tar -C "$tmpdir" -xzf -
- echo "$tmpdir/sbin/apk.static"
- }
- install_rootfs() {
- apk_bin="$(download_apk)"
- mkdir -p "$chroot_dir/etc/apk"
- "$apk_bin" -X "$mirror/$alpine_version/main" -U --allow-untrusted \
- -p "$chroot_dir" --initdb add alpine-base e2fsprogs
- cat > "$chroot_dir/etc/resolv.conf" <<EOF
- nameserver 1.1.1.1
- nameserver 1.0.0.1
- nameserver 8.8.8.8
- EOF
- cat > "$chroot_dir/etc/apk/repositories" <<EOF
- $mirror/$alpine_version/main
- $mirror/$alpine_version/community
- EOF
- }
- umount_vfs_cleanup() {
- for fs in proc sys dev; do
- umount "$chroot_dir/$fs"
- done
- }
- bind_mount_vfs() {
- for fs in proc sys dev; do
- mount -o bind "/$fs" "$chroot_dir/$fs"
- done
- }
- install_inside_chroot() {
- deploy_name="$(realpath "$0")"
- inside_deploy_path="$chroot_dir/deploy.sh"
- cp "$deploy_name" "$inside_deploy_path"
- chmod +x "$inside_deploy_path"
- bind_mount_vfs
- trap umount_vfs_cleanup EXIT
- chroot "$chroot_dir" /deploy.sh setup
- trap - EXIT
- umount_vfs_cleanup
- }
- extra_setup_vim() {
- apk add vim
- ln -s "$(which vim)" /usr/local/bin/vi
- }
- extra_setup_fish() {
- apk add fish
- # chsh -s "$(which fish)"
- }
- setup_extra() {
- extra_setup_vim
- extra_setup_fish
- }
- install_kernel() {
- apk add linux-virt linux-firmware-none
- }
- install_packages() {
- apk add chrony acpi busybox-mdev-openrc
- apk add grub grub-bios
- apk add openssh blkid
- install_kernel
- }
- part_uuid() {
- blkid -o export -s UUID "$1" | sed -n -e 2p
- }
- mountpoint_dev() {
- mount | grep "on $1 " | awk '{ print $1 }'
- }
- mountpoint_fstype() {
- mount | grep "on $1 " | awk '{ print $5 }'
- }
- mountpoint_options() {
- mount | grep "on $1 " | awk '{ print $6 }' | tr -d '()'
- }
- # $1: mountpoint
- # $2: check on boot
- gen_fstab_entry() {
- _mnt="$1"
- _dev="$(mountpoint_dev "$_mnt")"
- _fs="$(mountpoint_fstype "$_mnt")"
- _options="$(mountpoint_options "$_mnt")"
- _uuid="$(part_uuid "$_dev")"
- case "$2" in
- y|Y|1) _check=1 ;;
- *) _check=0 ;;
- esac
- echo "$_uuid $_mnt $_fs $_options 0 $_check"
- }
- gen_fstab() {
- gen_fstab_entry / y
- echo "tmpfs /tmp tmpfs nosuid,nodev 0 0"
- }
- populate_fstab() {
- gen_fstab | tee /etc/fstab
- }
- enable_services() {
- rc-update add devfs sysinit
- rc-update add dmesg sysinit
- rc-update add mdev sysinit
- rc-update add hwclock boot
- rc-update add modules boot
- rc-update add sysctl boot
- rc-update add hostname boot
- rc-update add bootmisc boot
- rc-update add syslog boot
- rc-update add localmount boot
- rc-update add networking boot
- rc-update add mount-ro shutdown
- rc-update add killprocs shutdown
- rc-update add savecache shutdown
- rc-update add acpid default
- rc-update add crond default
- rc-update add chronyd default
- rc-update add sshd default
- }
- setup_rootfs() {
- install_packages
- enable_services
- echo "Set root password:"
- passwd
- setup_extra
- }
- full_install() {
- install_rootfs
- install_inside_chroot
- }
- parse_args "$@"
- ensure_root
- case "$action" in
- rootfs) install_rootfs ;;
- setup) setup_rootfs ;;
- full) full_install ;;
- *) usage 1;;
- esac
|