2024-07-03 18:00:33 +00:00
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o xtrace
2018-03-07 23:52:40 +00:00
2019-04-02 19:38:19 +00:00
: ${ REALMFS_BUILDER_BASE : = "/usr/share/realmfs-builder" }
source ${ REALMFS_BUILDER_BASE } /common.inc
2018-03-07 23:52:40 +00:00
umount_if_tmpfs( ) {
if findmnt -t tmpfs -M ${ 1 } > /dev/null; then
info "unmounting existing rootfs tmpfs"
umount ${ 1 }
fi
}
setup_rootfs( ) {
umount_if_tmpfs ${ ROOTFS }
if [ [ -d ${ ROOTFS } ] ] ; then
info " Removing existing rootfs at ${ ROOTFS } "
rm -rf ${ ROOTFS }
fi
mkdir --parents ${ ROOTFS }
if [ [ ${ USE_TMPFS } -eq 1 ] ] ; then
mount -t tmpfs rootfs-tmp ${ ROOTFS }
fi
2018-12-31 23:32:43 +00:00
chmod 0755 ${ ROOTFS }
2018-03-07 23:52:40 +00:00
}
run_debootstrap( ) {
[ [ -f ${ CACHE_DIR } /lock ] ] && rm -f ${ CACHE_DIR } /lock
mkdir --parents ${ CACHE_DIR } ${ ROOTFS } /var/cache/apt/archives
info " Bind mounting ${ CACHE_DIR } to ${ ROOTFS } /var/cache/apt/archives "
mount --bind ${ CACHE_DIR } ${ ROOTFS } /var/cache/apt/archives
info "Launching debootstrap"
debootstrap --verbose --merged-usr --variant= minbase \
--include= systemd-sysv,locales \
${ DEBIAN_RELEASE } ${ ROOTFS } ${ DEBIAN_MIRROR }
}
setup_chroot( ) {
mount chproc ${ ROOTFS } /proc -t proc
mount chsys ${ ROOTFS } /sys -t sysfs
mount chtmp ${ ROOTFS } /tmp -t tmpfs
2019-04-02 19:38:19 +00:00
# Install a copy of realmfs-builder inside new image
2018-03-07 23:52:40 +00:00
mkdir -p ${ ROOTFS } /usr/share
2019-04-02 19:38:19 +00:00
cp -a ${ REALMFS_BUILDER_BASE } ${ ROOTFS } /usr/share
ln -s /usr/share/realmfs-builder/stage-one.sh ${ ROOTFS } /usr/bin/realmfs-builder
2018-03-07 23:52:40 +00:00
2019-04-02 19:38:19 +00:00
# $BUILDFILE and any extra files go in /tmp/realmfs-build of rootfs
mkdir -p ${ ROOTFS } /tmp/realmfs-build
cp ${ BUILDFILE } ${ ROOTFS } /tmp/realmfs-build/build.conf
2018-03-07 23:52:40 +00:00
}
cleanup_chroot( ) {
umount ${ ROOTFS } /proc
umount ${ ROOTFS } /sys
umount ${ ROOTFS } /tmp
umount ${ ROOTFS } /var/cache/apt/archives
# Remove cache files in case we are creating a tarball for distribution
rm -f ${ ROOTFS } /var/cache/apt/pkgcache.bin
rm -f ${ ROOTFS } /var/cache/apt/srcpkgcache.bin
}
run_chroot_stage( ) {
setup_chroot
#
# Run second-stage.sh inside chroot(), pass in various environment variables
#
DEBIAN_FRONTEND = noninteractive \
DEBCONF_NONINTERACTIVE_SEEN = true \
LC_ALL = C LANGUAGE = C LANG = C \
DEBIAN_RELEASE = ${ DEBIAN_RELEASE } DEBIAN_MIRROR = ${ DEBIAN_MIRROR } \
2019-04-02 19:38:19 +00:00
chroot ${ ROOTFS } /usr/share/realmfs-builder/stage-two.sh /tmp/realmfs-build/build.conf
2018-03-07 23:52:40 +00:00
info "chroot installation stage finished, cleaning chroot setup"
cleanup_chroot
}
generate_tarball( ) {
2019-04-02 19:38:19 +00:00
local tarball = ${ WORKDIR } /realmfs-rootfs.tar
2018-03-07 23:52:40 +00:00
info "----- Generating rootfs tarball -----"
tar -C ${ ROOTFS } --numeric-owner -c --xattrs --xattrs-include= * -f $tarball .
if [ [ ${ DO_XZ } -eq 1 ] ] ; then
info " Compressing $tarball "
xz --force --threads= 0 $tarball
tarball = ${ tarball } .xz
fi
echo
ls -hl $tarball
echo
}
2019-04-02 19:38:19 +00:00
generate_image( ) {
# BLOCKS=$(du -ks ${ROOTFS} | cut -f1)
# BLOCKS=$(expr ${BLOCKS} \* 12 / 10)
# SIZE=$(expr ${BLOCKS} \* 1024)
# echo "Size is ${SIZE}"
2019-11-30 02:19:32 +00:00
BLOCKS = $( expr 440 \* 1024)
2019-04-02 19:38:19 +00:00
# allow online resize up to 32G
dd if = /dev/zero of = ${ WORKDIR } /citadel-realmfs.ext4 seek = ${ BLOCKS } count = 0 bs = 4096
2019-11-30 02:19:32 +00:00
mkfs.ext4 -d ${ ROOTFS } -i 4096 -b 4096 -F ${ WORKDIR } /citadel-realmfs.ext4 ${ BLOCKS } || exit 1
2019-04-02 19:38:19 +00:00
}
2018-03-07 23:52:40 +00:00
usage( ) {
cat <<-EOF
2019-04-02 19:38:19 +00:00
USAGE: realmfs-builder [ options] [ config-file]
2018-03-07 23:52:40 +00:00
OPTIONS
--new Create a configuration file template called build.conf in the current directory
2019-04-02 19:38:19 +00:00
-d <directory> Choose a non-default directory for build output ( currently: $( pwd ) /realmfs)
2018-03-07 23:52:40 +00:00
-t Create a tarball but don' t compress it
-z Create a tarball compressed with xz
--no-tmpfs Do not use tmpfs as rootfs build directory
--no-confirm Do not ask for confirmation before beginning
2019-04-02 19:38:19 +00:00
For more documentation see /usr/share/realmfs-builder/README
2018-03-07 23:52:40 +00:00
EOF
exit 0
}
ask_confirm( ) {
local use_tmpfs = "No"
[ [ ${ USE_TMPFS } -eq 1 ] ] && use_tmpfs = "Yes"
2019-04-02 19:38:19 +00:00
printf "About to build RealmFS image with the following parameters:\n\n"
2018-03-07 23:52:40 +00:00
printf " \tBuild Configuration File : ${ BUILDFILE } \n "
printf " \tOutput rootfs directory : ${ ROOTFS } \n "
printf " \tBuild rootfs on tmpfs : ${ use_tmpfs } \n "
[ [ -e ${ ROOTFS } ] ] && printf "\nWarning: rootfs directory from a prior build exists and will be deleted before building new image\n\n"
read -p "Ok to proceed? (y/N): " confirm
[ [ $confirm = ~ ^[ Yy] ] ] || exit 0
}
try_config( ) {
local rp
rp = $( realpath ${ 1 } 2> /dev/null) || return 1
[ [ -f ${ rp } ] ] || return 1
printf " ${ rp } "
}
2019-04-02 19:38:19 +00:00
WORKDIR = " $( pwd ) /realmfs "
2024-07-03 18:00:33 +00:00
BUILDFILE = ""
2018-03-07 23:52:40 +00:00
DO_TAR = 0
DO_XZ = 0
USE_TMPFS = 1
NO_CONFIRM = 0
2019-04-02 19:38:19 +00:00
DO_IMG = 0
2018-03-07 23:52:40 +00:00
while [ [ $# -gt 0 ] ] ; do
key = ${ 1 }
case $key in
-d)
2018-03-15 16:15:52 +00:00
mkdir -p " ${ 2 } "
2018-03-07 23:52:40 +00:00
WORKDIR = " $( realpath ${ 2 } ) "
shift
shift
; ;
-t)
DO_TAR = 1
shift
; ;
-z)
DO_TAR = 1 DO_XZ = 1
shift
; ;
2019-04-02 19:38:19 +00:00
-i)
DO_IMG = 1
shift
; ;
2018-03-07 23:52:40 +00:00
--no-tmpfs)
USE_TMPFS = 0
shift
; ;
--no-confirm)
NO_CONFIRM = 1
shift
; ;
--new)
2019-04-02 19:38:19 +00:00
cp --verbose ${ REALMFS_BUILDER_BASE } /build-template.conf build.conf
2018-03-07 23:52:40 +00:00
exit 0
; ;
--help| -h| help )
usage
; ;
-*)
printf " Unknown option ${ key } \n "
usage
; ;
*)
BUILDFILE = $( try_config ${ 1 } ) || fatal " Cannot find config file ' ${ 1 } ' "
shift
; ;
esac
done
if [ " $EUID " -ne 0 ] ; then
2019-04-02 19:38:19 +00:00
echo "The realmfs-builder must be run with root privileges."
2018-03-07 23:52:40 +00:00
exit 1
fi
if [ [ -z ${ BUILDFILE } ] ] ; then
2019-04-02 19:38:19 +00:00
BUILDFILE = $( try_config " ${ PWD } /build.conf " || try_config " ${ REALMFS_BUILDER_BASE } /basic-image.conf " ) || fatal "Could not find a configuration file to use"
2018-03-07 23:52:40 +00:00
fi
ROOTFS = ${ WORKDIR } /rootfs
CACHE_DIR = ${ WORKDIR } /var-cache-apt-archives
[ [ ${ NO_CONFIRM } -ne 1 ] ] && ask_confirm
# black magick from stack overflow
2019-04-02 19:38:19 +00:00
exec > >( tee -a $WORKDIR /realmfs-build.log) 2>& 1
2018-03-07 23:52:40 +00:00
2019-04-02 19:38:19 +00:00
info " Starting build of RealmFS image from configuration file ${ BUILDFILE } "
2018-03-07 23:52:40 +00:00
source ${ BUILDFILE }
setup_rootfs
run_debootstrap
run_chroot_stage
2019-04-02 19:38:19 +00:00
2018-03-07 23:52:40 +00:00
info "rootfs build is completed:"
info " $( du -sh ${ ROOTFS } ) "
2019-04-02 19:38:19 +00:00
if [ [ ${ DO_IMG } -eq 1 ] ] ; then
generate_image
elif [ [ ${ DO_TAR } -eq 1 ] ] ; then
2018-03-07 23:52:40 +00:00
generate_tarball
fi
if [ [ ${ USE_TMPFS } -eq 1 ] ] ; then
info "Root directory is a tmpfs. To remove mount and directory contents:"
info " sudo umount ${ ROOTFS } "
fi