lxc-gentoo.in revision 3a74e9097a932729d9eff9ce562288e89731b177
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# LXC template for gentoo
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# Author: Guillaume Zitta <lxc@zitta.fr>
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# Widely inspired from lxc-gentoo script at https://github.com/globalcitizen/lxc-gentoo
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# this version is reworked with :
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# - out of the lxc-create compat
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# - vanilla gentoo config
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# - ready to use cache
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# Detect use under userns (unsupported)
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
250b1eec71b074acdff1c5f6b5a1f0d7d2c20b77Stéphane Graber echo "This template can't be used for unprivileged containers." 1>&2
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber echo "You may want to try the \"download\" template instead." 1>&2
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# Make sure the usual locations are in PATH
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graberexport PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# Ensure strict root's umask doesen't render the VM unusable
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber################################################################################
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# Various helper functions
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber################################################################################
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# param: $1: the name of the lock
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# param: $2: the timeout for the lock
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# The rest contain the command to execute and its parameters
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber printf "Attempting to obtain an exclusive lock (timeout: %s sec) named \"%s\"...\n" "${timeout}" "$lock_name"
211e51e81e7c6ab670d1d282d78e5ef26d039a79Stéphane Graber if [[ $? -ne 0 ]]; then
9c631ea7c2906f41b23f5c8dcc9f6045078879dbDwight Engen printf " => unable to obtain lock, aborting.\n"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber } 50> "@LOCALSTATEDIR@/lock/subsys/lxc-gentoo-${lock_name}"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# a die function is always a good idea
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber printf "\n[the last exit code leading to this death was: %s ]\n" "$?"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# gentoo arch/variant detection
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber printf "### set_default_arch: default arch/variant autodetect...\n"
9c631ea7c2906f41b23f5c8dcc9f6045078879dbDwight Engen if [[ $arch =~ i.86 ]]; then
9c631ea7c2906f41b23f5c8dcc9f6045078879dbDwight Engen elif [[ $arch =~ arm.* ]]; then
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber printf " => warn: unexpected arch:${arch} let me knows if it works :)\n"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber printf " => Got: arch=%s variant=%s\n" "${arch}" "${variant}"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber################################################################################
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# CACHE Preparation
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber################################################################################
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# during setup cachedir is $cacheroot/partial-$arch-$variant
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# at the end, it will be $cacheroot/rootfs-$arch-$variant
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber partialfs="${cacheroot}/partial-${arch}-${variant}"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber #if cache exists and flush not needed, return
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber [[ -d "${cachefs}" && -z "${flush_cache}" ]] && return 0
211e51e81e7c6ab670d1d282d78e5ef26d039a79Stéphane Graber printf "###### cache_setup(): doing cache preparation\n"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber printf "###### cache_setup: Cache should be ready\n"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber printf "### cache_precheck(): doing some pre-start checks ...\n"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber || die 8 "\$cacheroot (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPERATORS, THIS IS *VERY* BAD!\n" "${cacheroot}"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber#get latest stage3 tarball
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber printf "### cache_stage3(): stage3 cache deployment...\n"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber local stage3_baseurl="${mirror}/releases/${arch}/autobuilds"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber local stage3_pointer="${stage3_baseurl}/latest-stage3-${variant}.txt"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber printf "Determining path to latest Gentoo %s (%s) stage3 archive...\n" "${arch}" "${variant}"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber printf " => downloading and processing %s\n" "${stage3_pointer}"
9c631ea7c2906f41b23f5c8dcc9f6045078879dbDwight Engen local stage3_latest_tarball=$(wget -q -O - "${stage3_pointer}" | tail -n1 ) \
9c631ea7c2906f41b23f5c8dcc9f6045078879dbDwight Engen printf " => Got: %s\n" "${stage3_latest_tarball}"
9c631ea7c2906f41b23f5c8dcc9f6045078879dbDwight Engen printf "Downloading/untarring the actual stage3 tarball...\n"
9c631ea7c2906f41b23f5c8dcc9f6045078879dbDwight Engen wget -O - "${stage3_baseurl}/${stage3_latest_tarball}" | tar -xjpf - -C "${partialfs}" \
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber tar -xpf "${tarball}" -C "${partialfs}" || die 6 "unable to untar ${tarball} to ${partialfs}"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber chroot ${partialfs} /bin/true || die 1 "Error: chroot %s /bin/true, failed" "${partialfs}"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber printf " => stage3 cache extracted in : %s\n" "${partialfs}"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber printf "### cache_portage: caching portage tree tarball...\n"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber [[ -z "${flush_cache}" && -f "${portage_cache}" ]] && return 0
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber printf "Downloading Gentoo portage (software build database) snapshot...\n"
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber execute_exclusively portage 60 wget -O "${portage_cache}" "${mirror}/snapshots/portage-latest.tar.bz2" \
4019712d198a7d50b08b326ade17f5ff1666efbbStéphane Graber# custom inittab
# initial warkaround was: sed -i -e 's/^#rc_nostop=""/rc_nostop="net.eth0 net.lo"/' "${partialfs}/etc/rc.conf"
#If backingstore was specified, lxc.rootfs should be present or --rootfs did the rootfs var creation
container_precheck && \
container_rootfs && \
container_consoles && \
container_tz && \
container_portage && \
container_net && \
container_hostname && \
container_auth && \
if [ $? -ne 0 ]; then
|| die 8 "\$name (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPERATORS, THIS IS *VERY* BAD!\n" "${name}"
|| die 8 "\$rootfs (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPERATORS, THIS IS *VERY* BAD!\n" "${rootfs}"
|| die 8 "\$cachefs (%s) IS EMPTY OR MADE OF ONLY DIRECTORY SEPERATORS, THIS IS *VERY* BAD!\n" "${cachefs}"
tar -c -f - -C "${cachefs}" . | tar -x -p -f - -C "${rootfs}" || die 1 "Error: cache copy to rootfs failed"
if [[ ${tty} < 6 ]]; then
die 1 "specified portage_dir (%s) does not contains profiles, is it a portage tree ?\n" "${portage_dir}"
lxc.mount.entry=${portage_dir} ${portage_container/\//} none ro,bind 0 0
lxc.mount.entry=${portage_dir}/distfiles ${portage_container/\//}/distfiles none rw,bind 0 0
store_user_message "container has a shared portage from host's ${portage_dir} to ${portage_container/\//}"
# enable and *tune* this kind of entry to slot binaries, specialy if you use multiples archs and variants
printf "# untaring private portage to %s from %s ... \n" "${rootfs}/${portage_container}" "${portage_cache}"
execute_exclusively portage 60 tar -xp --strip-components 1 -C "${rootfs}/${portage_container}" -f "${portage_cache}" \
local file=${1}
if [[ ${nic_count} == 0 ]]; then
If it is for Lxc, use it next time by adding this to your default.conf :
lxc.network.type = veth
lxc.network.link = ${bridge}
lxc.network.flags = up
lxc.network.hwaddr = fe:xx:xx:xx:xx:xx"
for nic in ${nic_managed}
let sys_nic_index=sys_nic_index+1
and man lxc.conf"
chroot "${rootfs}" useradd --create-home -s /bin/bash "${user}" || die 1 "failed to create user ${user}"
cat <<EOF
$1 -h|--help [-a|--arch <arch>] [-v|--variant <variant>] [-P|--private-portage] [--portage-dir <protagedir>] [-t|--tarball <stage3file>]
[-F|--flush-cache] [-c|--cache-only] [-u|--user <username>] [-w|--password <password>] [--autologin] [-S|--auth-key <keyfile>]
private-portage: by default, /usr/portage is mount-binded with host one if exists (currently: '${private_portage}')
options=$(getopt -o hp:n:a:FcPv:t:S:u:w:s:m: -l help,rootfs:,path:,name:,arch:,flush-cache,cache-only,private-portage,variant:,portage-dir:,tarball:,auth_key:,user:,autologin,password:,settings:,mirror:,tty: -- "$@")
eval set -- "$options"