1 |
dpavlin |
174 |
#!/bin/bash |
2 |
|
|
|
3 |
|
|
# |
4 |
|
|
# lxc: linux Container library |
5 |
|
|
|
6 |
dpavlin |
246 |
apt-get install debootstrap |
7 |
|
|
|
8 |
dpavlin |
174 |
# 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 |
dpavlin |
176 |
arch=$(arch) |
101 |
|
|
|
102 |
dpavlin |
174 |
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 |
dpavlin |
176 |
$1 -h|--help -p|--path=<path> -a|--arch=stable --clean |
256 |
dpavlin |
174 |
EOF |
257 |
|
|
return 0 |
258 |
|
|
} |
259 |
|
|
|
260 |
dpavlin |
176 |
options=$(getopt -o hp:n:ca: -l help,path:,name:,clean,arch: -- "$@") |
261 |
dpavlin |
174 |
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 |
dpavlin |
176 |
-n|--name) name=$2; shift 2;; |
273 |
|
|
-c|--clean) clean=$2; shift 2;; |
274 |
|
|
-a|--arch) arch=$2; shift 2;; |
275 |
dpavlin |
174 |
--) 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 |