install required packages
[sysadmin-cookbook] / recepies / lxc / lxc-debian
1 #!/bin/bash
2
3 #
4 # lxc: linux Container library
5
6 apt-get install debootstrap
7
8 # Authors:
9 # Daniel Lezcano <daniel.lezcano@free.fr>
10
11 # This library is free software; you can redistribute it and/or
12 # modify it under the terms of the GNU Lesser General Public
13 # License as published by the Free Software Foundation; either
14 # version 2.1 of the License, or (at your option) any later version.
15
16 # This library is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 # Lesser General Public License for more details.
20
21 # You should have received a copy of the GNU Lesser General Public
22 # License along with this library; if not, write to the Free Software
23 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
25 configure_debian()
26 {
27     rootfs=$1
28     hostname=$2
29
30     # configure the inittab
31     cat <<EOF > $rootfs/etc/inittab
32 id:3:initdefault:
33 si::sysinit:/etc/init.d/rcS
34 l0:0:wait:/etc/init.d/rc 0
35 l1:1:wait:/etc/init.d/rc 1
36 l2:2:wait:/etc/init.d/rc 2
37 l3:3:wait:/etc/init.d/rc 3
38 l4:4:wait:/etc/init.d/rc 4
39 l5:5:wait:/etc/init.d/rc 5
40 l6:6:wait:/etc/init.d/rc 6
41 # Normally not reached, but fallthrough in case of emergency.
42 z6:6:respawn:/sbin/sulogin
43 1:2345:respawn:/sbin/getty 38400 console
44 c1:12345:respawn:/sbin/getty 38400 tty1 linux
45 c2:12345:respawn:/sbin/getty 38400 tty2 linux
46 c3:12345:respawn:/sbin/getty 38400 tty3 linux
47 c4:12345:respawn:/sbin/getty 38400 tty4 linux
48 EOF
49
50     # disable selinux in debian
51     mkdir -p $rootfs/selinux
52     echo 0 > $rootfs/selinux/enforce
53
54     # by default setup root password with no password
55     cat <<EOF > $rootfs/etc/ssh/sshd_config
56 Port 22
57 Protocol 2
58 HostKey /etc/ssh/ssh_host_rsa_key
59 HostKey /etc/ssh/ssh_host_dsa_key
60 UsePrivilegeSeparation yes
61 KeyRegenerationInterval 3600
62 ServerKeyBits 768
63 SyslogFacility AUTH
64 LogLevel INFO
65 LoginGraceTime 120
66 PermitRootLogin yes
67 StrictModes yes
68 RSAAuthentication yes
69 PubkeyAuthentication yes
70 IgnoreRhosts yes
71 RhostsRSAAuthentication no
72 HostbasedAuthentication no
73 PermitEmptyPasswords yes
74 ChallengeResponseAuthentication no
75 EOF
76
77     # configure the network using the dhcp
78     cat <<EOF > $rootfs/etc/network/interfaces
79 auto lo
80 iface lo inet loopback
81
82 auto eth0
83 iface eth0 inet dhcp
84 EOF
85
86     # set the hostname
87     cat <<EOF > $rootfs/etc/hostname
88 $hostname
89 EOF
90
91     # reconfigure some services
92     chroot $rootfs /usr/sbin/dpkg-reconfigure locales
93
94     # remove pointless services in a container
95     chroot $rootfs /usr/sbin/update-rc.d -f umountfs remove
96     chroot $rootfs /usr/sbin/update-rc.d -f hwclock.sh remove
97     chroot $rootfs /usr/sbin/update-rc.d -f hwclockfirst.sh remove
98 }
99
100 arch=$(arch)
101
102 download_debian()
103 {
104     packages=\
105 ifupdown,\
106 locales,\
107 libui-dialog-perl,\
108 dialog,\
109 dhcp-client,\
110 netbase,\
111 net-tools,\
112 iproute,\
113 openssh-server
114
115     cache=$1
116
117     # check the mini debian was not already downloaded
118     mkdir -p "$cache/partial-$arch"
119     if [ $? -ne 0 ]; then
120         echo "Failed to create '$cache/partial-$arch' directory"
121         return 1
122     fi
123
124     # download a mini debian into a cache
125     echo "Downloading debian minimal ..."
126     debootstrap --verbose --variant=minbase --arch=$arch \
127         --include $packages \
128         lenny $cache/partial-$arch http://ftp.debian.org/debian
129     if [ $? -ne 0 ]; then
130         echo "Failed to download the rootfs, aborting."
131         return 1
132     fi
133
134     mv "$1/partial-$arch" "$1/rootfs-$arch"
135     echo "Download complete."
136
137     return 0
138 }
139
140 copy_debian()
141 {
142     cache=$1
143     rootfs=$3
144
145     # make a local copy of the minidebian
146     echo -n "Copying rootfs to $rootfs..."
147     cp -a $cache/rootfs-$arch $rootfs || return 1
148     return 0
149 }
150
151 install_debian()
152 {
153     cache="/var/cache/lxc/debian"
154     rootfs=$1
155     mkdir -p /var/lock/subsys/
156     (
157         flock -n -x 200
158         if [ $? -ne 0 ]; then
159             echo "Cache repository is busy."
160             return 1
161         fi
162
163         if [ "$arch" == "x86_64" ]; then
164             arch=amd64
165         fi
166
167         if [ "$arch" == "i686" ]; then
168             arch=i386
169         fi
170
171         echo "Checking cache download in $cache/rootfs-$arch ... "
172         if [ ! -e "$cache/rootfs-$arch" ]; then
173             download_debian $cache $arch
174             if [ $? -ne 0 ]; then
175                 echo "Failed to download 'debian base'"
176                 return 1
177             fi
178         fi
179
180         copy_debian $cache $arch $rootfs
181         if [ $? -ne 0 ]; then
182             echo "Failed to copy rootfs"
183             return 1
184         fi
185
186         return 0
187
188         ) 200>/var/lock/subsys/lxc
189
190     return $?
191 }
192
193 copy_configuration()
194 {
195     path=$1
196     rootfs=$2
197     name=$3
198
199     cat <<EOF >> $path/config
200 lxc.tty = 4
201 lxc.pts = 1024
202 lxc.rootfs = $rootfs
203 lxc.cgroup.devices.deny = a
204 # /dev/null and zero
205 lxc.cgroup.devices.allow = c 1:3 rwm
206 lxc.cgroup.devices.allow = c 1:5 rwm
207 # consoles
208 lxc.cgroup.devices.allow = c 5:1 rwm
209 lxc.cgroup.devices.allow = c 5:0 rwm
210 lxc.cgroup.devices.allow = c 4:0 rwm
211 lxc.cgroup.devices.allow = c 4:1 rwm
212 # /dev/{,u}random
213 lxc.cgroup.devices.allow = c 1:9 rwm
214 lxc.cgroup.devices.allow = c 1:8 rwm
215 lxc.cgroup.devices.allow = c 136:* rwm
216 lxc.cgroup.devices.allow = c 5:2 rwm
217 # rtc
218 lxc.cgroup.devices.allow = c 254:0 rwm
219 EOF
220
221     if [ $? -ne 0 ]; then
222         echo "Failed to add configuration"
223         return 1
224     fi
225
226     return 0
227 }
228
229 clean()
230 {
231     cache="/var/cache/lxc/debian"
232
233     if [ ! -e $cache ]; then
234         exit 0
235     fi
236
237     # lock, so we won't purge while someone is creating a repository
238     (
239         flock -n -x 200 
240         if [ $? != 0 ]; then
241             echo "Cache repository is busy."
242             exit 1
243         fi
244
245         echo -n "Purging the download cache..."
246         rm --preserve-root --one-file-system -rf $cache && echo "Done." || exit 1
247         exit 0
248
249     ) 200>/var/lock/subsys/lxc
250 }
251
252 usage()
253 {
254     cat <<EOF
255 $1 -h|--help -p|--path=<path> -a|--arch=stable --clean
256 EOF
257     return 0
258 }
259
260 options=$(getopt -o hp:n:ca: -l help,path:,name:,clean,arch: -- "$@")
261 if [ $? -ne 0 ]; then
262         usage $(basename $0)
263         exit 1
264 fi
265 eval set -- "$options"
266
267 while true
268 do
269     case "$1" in
270         -h|--help)      usage $0 && exit 0;;
271         -p|--path)      path=$2; shift 2;;
272                 -n|--name)      name=$2; shift 2;;
273                 -c|--clean)     clean=$2; shift 2;;
274                 -a|--arch)              arch=$2; shift 2;;
275         --)             shift 1; break ;;
276         *)              break ;;
277     esac
278 done
279
280 if [ ! -z "$clean" -a -z "$path" ]; then
281     clean || exit 1
282     exit 0
283 fi
284
285 type debootstrap
286 if [ $? -ne 0 ]; then
287     echo "'debootstrap' command is missing"
288     exit 1
289 fi
290
291 if [ -z "$path" ]; then
292     echo "'path' parameter is required"
293     exit 1
294 fi
295
296 if [ "$(id -u)" != "0" ]; then
297     echo "This script should be run as 'root'"
298     exit 1
299 fi 
300
301 rootfs=$path/rootfs
302
303 install_debian $rootfs
304 if [ $? -ne 0 ]; then
305     echo "failed to install debian"
306     exit 1
307 fi
308
309 configure_debian $rootfs $name
310 if [ $? -ne 0 ]; then
311     echo "failed to configure debian for a container"
312     exit 1
313 fi
314
315 copy_configuration $path $rootfs
316 if [ $? -ne 0 ]; then
317     echo "failed write configuration file"
318     exit 1
319 fi
320
321 if [ ! -z $clean ]; then
322     clean || exit 1
323     exit 0
324 fi