-
-
Save JohnMertz/30c2ae004093a999beb036fd028d0e67 to your computer and use it in GitHub Desktop.
lxc template for Debian Wheezy to install on Debian Stretch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# lxc: linux Container library | |
# Authors: | |
# Daniel Lezcano <daniel.lezcano@free.fr> | |
# This library is free software; you can redistribute it and/or | |
# modify it under the terms of the GNU Lesser General Public | |
# License as published by the Free Software Foundation; either | |
# version 2.1 of the License, or (at your option) any later version. | |
# This library is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
# Lesser General Public License for more details. | |
# You should have received a copy of the GNU Lesser General Public | |
# License along with this library; if not, write to the Free Software | |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
DEBIANVERSION=wheezy | |
SUITE=debian-${DEBIANVERSION} | |
MIRROR=${MIRROR:-http://cdn.debian.net/debian} | |
configure_debian() | |
{ | |
rootfs=$1 | |
hostname=$2 | |
fqdn=$3 | |
# squeeze only has /dev/tty and /dev/tty0 by default, | |
# therefore creating missing device nodes for tty1-4. | |
for tty in $(seq 1 4); do | |
if [ ! -e $rootfs/dev/tty$tty ]; then | |
mknod $rootfs/dev/tty$tty c 4 $tty | |
fi | |
done | |
# configure the inittab | |
cat <<EOF > $rootfs/etc/inittab | |
id:2:initdefault: | |
si::sysinit:/etc/init.d/rcS | |
l0:0:wait:/etc/init.d/rc 0 | |
l1:1:wait:/etc/init.d/rc 1 | |
l2:2:wait:/etc/init.d/rc 2 | |
l3:3:wait:/etc/init.d/rc 3 | |
l4:4:wait:/etc/init.d/rc 4 | |
l5:5:wait:/etc/init.d/rc 5 | |
l6:6:wait:/etc/init.d/rc 6 | |
# Normally not reached, but fallthrough in case of emergency. | |
z6:6:respawn:/sbin/sulogin | |
1:2345:respawn:/sbin/getty 38400 console | |
c1:12345:respawn:/sbin/getty 38400 tty1 linux | |
c2:12345:respawn:/sbin/getty 38400 tty2 linux | |
c3:12345:respawn:/sbin/getty 38400 tty3 linux | |
c4:12345:respawn:/sbin/getty 38400 tty4 linux | |
EOF | |
# disable selinux in debian | |
mkdir -p $rootfs/selinux | |
echo 0 > $rootfs/selinux/enforce | |
# configure the network using the dhcp | |
cat <<EOF > $rootfs/etc/network/interfaces | |
auto lo | |
iface lo inet loopback | |
auto eth0 | |
iface eth0 inet dhcp | |
EOF | |
# set the hostname | |
cat <<EOF > $rootfs/etc/hostname | |
$hostname | |
EOF | |
# set minimal hosts | |
cat <<EOF > $rootfs/etc/hosts | |
127.0.0.1 $fqdn $hostname localhost | |
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 | |
EOF | |
# reconfigure some services | |
LANG="${LANG:-en_US.UTF-8}" | |
locale="$LANG $(echo $LANG | cut -d. -f2)" | |
chroot $rootfs echo "locales locales/default_environment_locale select $LANG" | chroot $rootfs sh -c "LANG=C debconf-set-selections" | |
chroot $rootfs echo "locales locales/default_environment_locale seen true" | chroot $rootfs sh -c "LANG=C debconf-set-selections" | |
chroot $rootfs echo "locales locales/locales_to_be_generated seen true" | chroot $rootfs sh -c "LANG=C debconf-set-selections" | |
chroot $rootfs sed -i -e "0,/^[# ]*$locale *$/ s/^[# ]*$locale *$/$locale/" /etc/locale.gen | |
chroot $rootfs sh -c "LANG=C dpkg-reconfigure locales -f noninteractive" | |
# remove pointless services in a container | |
chroot $rootfs /usr/sbin/update-rc.d -f checkroot.sh remove # S | |
chroot $rootfs /usr/sbin/update-rc.d checkroot.sh stop 09 S . | |
chroot $rootfs /usr/sbin/update-rc.d -f umountfs remove # 0 6 | |
chroot $rootfs /usr/sbin/update-rc.d umountfs start 09 0 6 . | |
chroot $rootfs /usr/sbin/update-rc.d -f umountroot remove # 0 6 | |
chroot $rootfs /usr/sbin/update-rc.d umountroot start 10 0 6 . | |
# The following initscripts don't provide an empty start or stop block. | |
# To prevent them being enabled on upgrades, we leave a start link on | |
# runlevel 3. | |
chroot $rootfs /usr/sbin/update-rc.d -f hwclock.sh remove # S 0 6 | |
chroot $rootfs /usr/sbin/update-rc.d hwclock.sh start 10 3 . | |
chroot $rootfs /usr/sbin/update-rc.d -f hwclockfirst.sh remove # S | |
chroot $rootfs /usr/sbin/update-rc.d hwclockfirst start 08 3 . | |
chroot $rootfs /usr/sbin/update-rc.d -f module-init-tools remove # S | |
chroot $rootfs /usr/sbin/update-rc.d module-init-tools start 10 3 . | |
echo "root:root" | chroot $rootfs chpasswd | |
echo "Root password is 'root', please change !" | |
return 0 | |
} | |
cleanup() | |
{ | |
rm -rf $cache/partial-$SUITE-$arch | |
rm -rf $cache/rootfs-$SUITE-$arch | |
} | |
download_debian() | |
{ | |
packages=\ | |
ifupdown,\ | |
locales,\ | |
libui-dialog-perl,\ | |
dialog,\ | |
isc-dhcp-client,\ | |
netbase,\ | |
net-tools,\ | |
iproute,\ | |
openssh-server | |
cache=$1 | |
arch=$2 | |
trap cleanup EXIT SIGHUP SIGINT SIGTERM | |
# check the mini debian was not already downloaded | |
mkdir -p "$cache/partial-$SUITE-$arch" | |
if [ $? -ne 0 ]; then | |
echo "Failed to create '$cache/partial-$SUITE-$arch' directory" | |
return 1 | |
fi | |
# download a mini debian into a cache | |
echo "Downloading debian minimal ..." | |
debootstrap --verbose --variant=minbase --arch=$arch \ | |
--include=$packages \ | |
"$DEBIANVERSION" "$cache/partial-$SUITE-$arch" $MIRROR | |
if [ $? -ne 0 ]; then | |
echo "Failed to download the rootfs, aborting." | |
return 1 | |
fi | |
mv "$1/partial-$SUITE-$arch" "$1/rootfs-$SUITE-$arch" | |
echo "Download complete." | |
trap EXIT | |
trap SIGINT | |
trap SIGTERM | |
trap SIGHUP | |
return 0 | |
} | |
copy_debian() | |
{ | |
cache=$1 | |
arch=$2 | |
rootfs=$3 | |
# make a local copy of the minidebian | |
echo -n "Copying rootfs to $rootfs..." | |
mkdir -p $rootfs | |
rsync -a "$cache/rootfs-$SUITE-$arch"/ $rootfs/ || return 1 | |
return 0 | |
} | |
install_debian() | |
{ | |
cache="/var/cache/lxc/"$SUITE | |
rootfs=$1 | |
mkdir -p /var/lock/subsys/ | |
( | |
flock -x 200 | |
if [ $? -ne 0 ]; then | |
echo "Cache repository is busy." | |
return 1 | |
fi | |
# Code taken from debootstrap | |
if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then | |
arch=`/usr/bin/dpkg --print-architecture` | |
elif type udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then | |
arch=`/usr/bin/udpkg --print-architecture` | |
else | |
arch=$(arch) | |
case $arch in | |
686) arch="i386";; | |
x86_64) arch="amd64";; | |
ppc) arch="powerpc";; | |
esac | |
fi | |
echo "Checking cache download in $cache/rootfs-$SUITE-$arch ... " | |
if [ ! -e "$cache/rootfs-$SUITE-$arch" ]; then | |
download_debian $cache $arch | |
if [ $? -ne 0 ]; then | |
echo "Failed to download 'debian base'" | |
return 1 | |
fi | |
fi | |
copy_debian $cache $arch $rootfs | |
if [ $? -ne 0 ]; then | |
echo "Failed to copy rootfs" | |
return 1 | |
fi | |
return 0 | |
) 200>/var/lock/subsys/lxc | |
return $? | |
} | |
copy_configuration() | |
{ | |
path=$1 | |
rootfs=$2 | |
name=$3 | |
fqdn=$4 | |
ipaddress=$5 | |
cat >> $path/config << EOF | |
# $path/config | |
## Container | |
lxc.utsname = $fqdn | |
lxc.rootfs = $rootfs | |
lxc.tty = 4 | |
lxc.pts = 1024 | |
lxc.mount = /var/lib/lxc/$name/fstab | |
lxc.network.ipv4 = $ipaddress | |
#lxc.console = /var/log/lxc/$name.console | |
## Capabilities | |
lxc.cap.drop = sys_admin | |
# uncomment the next line to run the container unconfined: | |
#lxc.aa_profile = unconfined | |
## Devices | |
#lxc.cgroup.devices.allow = a | |
lxc.cgroup.devices.deny = a | |
# /dev/null | |
lxc.cgroup.devices.allow = c 1:3 rwm | |
# /dev/zero | |
lxc.cgroup.devices.allow = c 1:5 rwm | |
# /dev/tty[1-4] consoles | |
lxc.cgroup.devices.allow = c 5:1 rwm | |
lxc.cgroup.devices.allow = c 5:0 rwm | |
lxc.cgroup.devices.allow = c 4:0 rwm | |
lxc.cgroup.devices.allow = c 4:1 rwm | |
# /dev/{,u}random | |
lxc.cgroup.devices.allow = c 1:9 rwm | |
lxc.cgroup.devices.allow = c 1:8 rwm | |
lxc.cgroup.devices.allow = c 136:* rwm | |
lxc.cgroup.devices.allow = c 5:2 rwm | |
# /dev/rtc | |
lxc.cgroup.devices.allow = c 254:0 rwm | |
## Limits | |
#lxc.cgroup.cpu.shares = 1024 | |
#lxc.cgroup.cpuset.cpus = 0 | |
#lxc.cgroup.memory.limit_in_bytes = 256M | |
#lxc.cgroup.memory.memsw.limit_in_bytes = 1G | |
## Filesystem | |
#lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0 | |
#lxc.mount.entry = sysfs sys sysfs defaults,ro 0 0 | |
#lxc.mount.entry = /srv/$name srv/$name none defaults,bind 0 0 | |
EOF | |
if [ -z "$ipaddress" ]; then | |
sed -i 's/^lxc\.network\.ipv4/#lxc.network.ipv4/g' $path/config | |
fi | |
cat <<EOF > $path/fstab | |
proc proc proc nodev,noexec,nosuid 0 0 | |
sysfs sys sysfs defaults,ro 0 0 | |
tmpfs /var/lib/lxc/$name/rootfs/run/shm tmpfs rw,nosuid,nodev,noexec 0 0 | |
EOF | |
if [ $? -ne 0 ]; then | |
echo "Failed to add configuration" | |
return 1 | |
fi | |
return 0 | |
} | |
clean() | |
{ | |
cache="/var/cache/lxc/debian" | |
if [ ! -e $cache ]; then | |
exit 0 | |
fi | |
# lock, so we won't purge while someone is creating a repository | |
( | |
flock -x 200 | |
if [ $? != 0 ]; then | |
echo "Cache repository is busy." | |
exit 1 | |
fi | |
echo -n "Purging the download cache..." | |
rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1 | |
exit 0 | |
) 200>/var/lock/subsys/lxc | |
} | |
usage() | |
{ | |
cat <<EOF | |
$1 -h|--help -p|--path=<path>|--fqdn=<fully qualified hostname>|--ip=<static ip address> --clean | |
EOF | |
return 0 | |
} | |
options=$(getopt -o hp:n:c -l help,rootfs:,path:,name:,ip:,clean,fqdn: -- "$@") | |
if [ $? -ne 0 ]; then | |
usage $(basename $0) | |
exit 1 | |
fi | |
eval set -- "$options" | |
while true | |
do | |
case "$1" in | |
-h|--help) usage $0 && exit 0;; | |
--rootfs) rootfs=$2; shift 2;; | |
-p|--path) path=$2; shift 2;; | |
--fqdn) fqdn=$2; shift 2;; | |
--ip) ipaddress=$2; shift 2;; | |
-n|--name) name=$2; shift 2;; | |
-c|--clean) clean=$2; shift 2;; | |
--) shift 1; break ;; | |
*) break ;; | |
esac | |
done | |
if [ ! -z "$clean" -a -z "$path" ]; then | |
clean || exit 1 | |
exit 0 | |
fi | |
if [ -z "$fqdn" ]; then | |
fqdn=$name; | |
fi | |
type debootstrap | |
if [ $? -ne 0 ]; then | |
echo "'debootstrap' command is missing" | |
exit 1 | |
fi | |
if [ -z "$path" ]; then | |
echo "'path' parameter is required" | |
exit 1 | |
fi | |
if [ "$(id -u)" != "0" ]; then | |
echo "This script should be run as 'root'" | |
exit 1 | |
fi | |
install_debian $rootfs | |
if [ $? -ne 0 ]; then | |
echo "failed to install debian" | |
exit 1 | |
fi | |
configure_debian $rootfs $name $fqdn | |
if [ $? -ne 0 ]; then | |
echo "failed to configure debian for a container" | |
exit 1 | |
fi | |
copy_configuration $path $rootfs $name $fqdn $ipaddress | |
if [ $? -ne 0 ]; then | |
echo "failed write configuration file" | |
exit 1 | |
fi | |
if [ ! -z $clean ]; then | |
clean || exit 1 | |
exit 0 | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
LXC as packaged in Stretch (perhaps Jessie as well) specifies the rootfs, rather than inferring it from "$path/rootfs". The template from which this was forked did not understand the "--rootfs=" option, now it does and is tested to work.
FYI. I'm installing Wheezy on a Stretch box to keep alive a piece of software that depends on PHP5 which is no longer packaged. I'd be installing in LXC anyways and the container has no access to the internet, so it is less trouble than compling PHP5 (and several modules) on an updated machine. You probably shouldn't use this template unless you are in a similar situation.