]> git.proxmox.com Git - mirror_lxc.git/blame - templates/lxc-busybox.in
lxc-download: make POSIX shellcheck clean
[mirror_lxc.git] / templates / lxc-busybox.in
CommitLineData
eb960fea
DL
1#!/bin/bash
2
3#
4# lxc: linux Container library
5
6# Authors:
7# Daniel Lezcano <daniel.lezcano@free.fr>
8
9# This library is free software; you can redistribute it and/or
10# modify it under the terms of the GNU Lesser General Public
11# License as published by the Free Software Foundation; either
12# version 2.1 of the License, or (at your option) any later version.
13
14# This library is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17# Lesser General Public License for more details.
18
19# You should have received a copy of the GNU Lesser General Public
20# License along with this library; if not, write to the Free Software
250b1eec 21# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
eb960fea 22
a542dd3c
BP
23LXC_MAPPED_UID=
24LXC_MAPPED_GID=
ed52814c 25SSH=
8ec981fc 26
207bf0e4
SG
27# Make sure the usual locations are in PATH
28export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
29
9e214906
SH
30am_in_userns() {
31 [ -e /proc/self/uid_map ] || { echo no; return; }
32 [ "$(wc -l /proc/self/uid_map | awk '{ print $1 }')" -eq 1 ] || { echo yes; return; }
33 line=$(awk '{ print $1 " " $2 " " $3 }' /proc/self/uid_map)
34 [ "$line" = "0 0 4294967295" ] && { echo no; return; }
35 echo yes
36}
37
38in_userns=0
39[ $(am_in_userns) = "yes" ] && in_userns=1
40
88e38993
BP
41copy_binary()
42{
43 binary_path=`which $1`
44 if [ $? -ne 0 ]; then
45 echo "Unable to find $1 binary on the system"
46 return 1
47 fi
48
49 dir_path="${binary_path%/*}"
50 echo /{,usr/}{,s}bin | grep $dir_path >/dev/null 2>&1
51 if [ $? -ne 0 ]; then
52 echo "Binary $1 is located at $binary_path and will not be copied"
53 echo "($dir_path not supported)"
54 return 1
55 fi
56
57 cp $binary_path $rootfs/$binary_path
58 if [ $? -ne 0 ]; then
59 echo "Failed to copy $binary_path to rootfs"
60 return 1
61 fi
62
63 return 0
64}
65
eb960fea
DL
66install_busybox()
67{
68 rootfs=$1
69 name=$2
70 res=0
71 tree="\
32b37181 72$rootfs/selinux \
eb960fea
DL
73$rootfs/dev \
74$rootfs/home \
75$rootfs/root \
76$rootfs/etc \
77$rootfs/etc/init.d \
78$rootfs/bin \
c94e60d1 79$rootfs/usr/bin \
eb960fea 80$rootfs/sbin \
c94e60d1 81$rootfs/usr/sbin \
eb960fea 82$rootfs/proc \
fefddf9f 83$rootfs/sys \
eb960fea
DL
84$rootfs/mnt \
85$rootfs/tmp \
86$rootfs/var/log \
87$rootfs/usr/share/udhcpc \
10e657e5 88$rootfs/dev/pts \
bf6cc736
DL
89$rootfs/dev/shm \
90$rootfs/lib \
91$rootfs/usr/lib \
92$rootfs/lib64 \
93$rootfs/usr/lib64"
eb960fea
DL
94
95 mkdir -p $tree || return 1
96 chmod 755 $tree || return 1
97
98 pushd $rootfs/dev > /dev/null || return 1
99
100 # minimal devices needed for busybox
9e214906 101 if [ $in_userns -eq 1 ]; then
cfe615f0 102 for dev in tty console tty0 tty1 ram0 null urandom; do
f24a52d5 103 echo "lxc.mount.entry = /dev/$dev dev/$dev none bind,optional,create=file 0 0" >> $path/config
9e214906
SH
104 done
105 else
fbbc1539
DE
106 mknod -m 666 tty c 5 0 || res=1
107 mknod -m 666 console c 5 1 || res=1
108 mknod -m 666 tty0 c 4 0 || res=1
109 mknod -m 666 tty1 c 4 0 || res=1
110 mknod -m 666 tty5 c 4 0 || res=1
111 mknod -m 600 ram0 b 1 0 || res=1
112 mknod -m 666 null c 1 3 || res=1
113 mknod -m 666 zero c 1 5 || res=1
114 mknod -m 666 urandom c 1 9 || res=1
9e214906 115 fi
eb960fea
DL
116
117 popd > /dev/null
118
119 # root user defined
120 cat <<EOF >> $rootfs/etc/passwd
121root:x:0:0:root:/root:/bin/sh
122EOF
123
124 cat <<EOF >> $rootfs/etc/group
125root:x:0:root
126EOF
127
eb960fea
DL
128 # mount everything
129 cat <<EOF >> $rootfs/etc/init.d/rcS
130#!/bin/sh
b09ecaf3
DL
131/bin/syslogd
132/bin/mount -a
133/bin/udhcpc
eb960fea
DL
134EOF
135
136 # executable
137 chmod 744 $rootfs/etc/init.d/rcS || return 1
138
eb960fea
DL
139 # launch rcS first then make a console available
140 # and propose a shell on the tty, the last one is
141 # not needed
142 cat <<EOF >> $rootfs/etc/inittab
143::sysinit:/etc/init.d/rcS
0016af97
DL
144tty1::respawn:/bin/getty -L tty1 115200 vt100
145console::askfirst:/bin/sh
eb960fea
DL
146EOF
147 # writable and readable for other
148 chmod 644 $rootfs/etc/inittab || return 1
149
150 cat <<EOF >> $rootfs/usr/share/udhcpc/default.script
151#!/bin/sh
eb960fea 152case "\$1" in
14d9c0f0
SG
153 deconfig)
154 ip addr flush dev \$interface
155 ;;
156
157 renew|bound)
158 # flush all the routes
159 if [ -n "\$router" ]; then
160 ip route del default 2> /dev/null
161 fi
162
163 # check broadcast
164 if [ -n "\$broadcast" ]; then
165 broadcast="broadcast \$broadcast"
166 fi
167
168 # add a new ip address
169 ip addr add \$ip/\$mask \$broadcast dev \$interface
170
171 if [ -n "\$router" ]; then
172 ip route add default via \$router dev \$interface
173 fi
174
175 [ -n "\$domain" ] && echo search \$domain > /etc/resolv.conf
176 for i in \$dns ; do
177 echo nameserver \$i >> /etc/resolv.conf
178 done
179 ;;
eb960fea
DL
180esac
181exit 0
182EOF
183
184 chmod 744 $rootfs/usr/share/udhcpc/default.script
185
186 return $res
187}
188
ed52814c
BP
189install_dropbear()
190{
191 # copy dropbear binary
88e38993 192 copy_binary dropbear || return 1
ed52814c
BP
193
194 # make symlinks to various ssh utilities
195 utils="\
196 $rootfs/usr/bin/dbclient \
197 $rootfs/usr/bin/scp \
198 $rootfs/usr/bin/ssh \
199 $rootfs/usr/sbin/dropbearkey \
200 $rootfs/usr/sbin/dropbearconvert \
201 "
202 echo $utils | xargs -n1 ln -s /usr/sbin/dropbear
203
204 # add necessary config files
205 mkdir $rootfs/etc/dropbear
206 dropbearkey -t rsa -f $rootfs/etc/dropbear/dropbear_rsa_host_key > /dev/null 2>&1
207 dropbearkey -t dss -f $rootfs/etc/dropbear/dropbear_dss_host_key > /dev/null 2>&1
208
209 echo "'dropbear' ssh utility installed"
210
211 return 0
212}
213
214install_openssh()
215{
216 # tools to be installed
217 server_utils="sshd"
218 client_utils="\
219 ssh \
220 scp \
4432b512
BP
221 "
222 client_optional_utils="\
ed52814c
BP
223 sftp \
224 ssh-add \
225 ssh-agent \
226 ssh-keygen \
227 ssh-keyscan \
228 ssh-argv0 \
229 ssh-copy-id \
230 "
231
232 # new folders used by ssh
233 ssh_tree="\
234$rootfs/etc/ssh \
235$rootfs/var/empty/sshd \
236$rootfs/var/lib/empty/sshd \
237$rootfs/var/run/sshd \
238"
239
240 # create folder structure
241 mkdir -p $ssh_tree
242 if [ $? -ne 0 ]; then
243 return 1
244 fi
245
246 # copy binaries
247 for bin in $server_utils $client_utils; do
88e38993 248 copy_binary $bin || return 1
ed52814c
BP
249 done
250
4432b512 251 for bin in $client_optional_utils; do
88e38993 252 tool_path=`which $bin` && copy_binary $bin
4432b512
BP
253 done
254
ed52814c
BP
255 # add user and group
256 cat <<EOF >> $rootfs/etc/passwd
257sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
258EOF
259
260 cat <<EOF >> $rootfs/etc/group
261sshd:x:74:
262EOF
263
264 # generate container keys
265 ssh-keygen -t rsa -N "" -f $rootfs/etc/ssh/ssh_host_rsa_key >/dev/null 2>&1
266 ssh-keygen -t dsa -N "" -f $rootfs/etc/ssh/ssh_host_dsa_key >/dev/null 2>&1
267
268 # by default setup root password with no password
269 cat <<EOF > $rootfs/etc/ssh/sshd_config
270Port 22
271Protocol 2
272HostKey /etc/ssh/ssh_host_rsa_key
273HostKey /etc/ssh/ssh_host_dsa_key
274UsePrivilegeSeparation yes
275KeyRegenerationInterval 3600
276ServerKeyBits 768
277SyslogFacility AUTH
278LogLevel INFO
279LoginGraceTime 120
280PermitRootLogin yes
281StrictModes yes
282RSAAuthentication yes
283PubkeyAuthentication yes
284IgnoreRhosts yes
285RhostsRSAAuthentication no
286HostbasedAuthentication no
287PermitEmptyPasswords yes
288ChallengeResponseAuthentication no
289EOF
290
291 echo "'OpenSSH' utility installed"
292
293 return 0
294}
295
eb960fea
DL
296configure_busybox()
297{
298 rootfs=$1
299
169bf5e0 300 which busybox >/dev/null 2>&1
7674618c 301
eb960fea 302 if [ $? -ne 0 ]; then
14d9c0f0
SG
303 echo "busybox executable is not accessible"
304 return 1
eb960fea
DL
305 fi
306
307 # copy busybox in the rootfs
308 cp $(which busybox) $rootfs/bin
309 if [ $? -ne 0 ]; then
14d9c0f0
SG
310 echo "failed to copy busybox in the rootfs"
311 return 1
eb960fea
DL
312 fi
313
6902a6c6
DE
314 # symlink busybox for the commands it supports
315 # it would be nice to just use "chroot $rootfs busybox --install -s /bin"
316 # but that only works right in a chroot with busybox >= 1.19.0
317 pushd $rootfs/bin > /dev/null || return 1
318 ./busybox --help | grep 'Currently defined functions:' -A300 | \
319 grep -v 'Currently defined functions:' | tr , '\n' | \
320 xargs -n1 ln -s busybox
321 popd > /dev/null
eb960fea
DL
322
323 # relink /sbin/init
324 ln $rootfs/bin/busybox $rootfs/sbin/init
325
6ab1ca03
BP
326 # /etc/fstab must exist for "mount -a"
327 touch $rootfs/etc/fstab
328
eb960fea
DL
329 # passwd exec must be setuid
330 chmod +s $rootfs/bin/passwd
32b37181 331 touch $rootfs/etc/shadow
19d618b1 332
eb960fea
DL
333 return 0
334}
335
336copy_configuration()
337{
338 path=$1
339 rootfs=$2
340 name=$3
341
7a96a068 342grep -q "^lxc.rootfs.path" $path/config 2>/dev/null || echo "lxc.rootfs.path = $rootfs" >> $path/config
eb960fea 343cat <<EOF >> $path/config
55c84efc 344lxc.signal.halt = SIGUSR1
fd998241 345lxc.signal.reboot = SIGTERM
b67771bc 346lxc.uts.name = $name
fe1c5887 347lxc.tty.max = 1
232763d6 348lxc.pty.max = 1
eee3ba81 349lxc.cap.drop = sys_module mac_admin mac_override sys_time
69d66f1e
SG
350
351# When using LXC with apparmor, uncomment the next line to run unconfined:
a1d5fdfd 352#lxc.apparmor.profile = unconfined
f24a52d5
SG
353
354lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed
355lxc.mount.entry = shm /dev/shm tmpfs defaults 0 0
1881820a
SH
356EOF
357
6bc424b5 358 libdirs="\
5d01f616
SG
359 lib \
360 usr/lib \
361 lib64 \
362 usr/lib64"
6bc424b5
SY
363
364 for dir in $libdirs; do
5d01f616 365 if [ -d "/$dir" ] && [ -d "$rootfs/$dir" ]; then
eba7df9e 366 echo "lxc.mount.entry = /$dir $dir none ro,bind 0 0" >> $path/config
6bc424b5
SY
367 fi
368 done
7f1dea04 369 echo "lxc.mount.entry = /sys/kernel/security sys/kernel/security none ro,bind,optional 0 0" >>$path/config
eb960fea
DL
370}
371
a542dd3c
BP
372remap_userns()
373{
374 path=$1
375
376 if [ -n "$LXC_MAPPED_UID" ] && [ "$LXC_MAPPED_UID" != "-1" ]; then
f24a52d5 377 chown $LXC_MAPPED_UID $path/config >/dev/null 2>&1
a542dd3c
BP
378 chown -R root $path/rootfs >/dev/null 2>&1
379 fi
380
381 if [ -n "$LXC_MAPPED_GID" ] && [ "$LXC_MAPPED_GID" != "-1" ]; then
f24a52d5 382 chgrp $LXC_MAPPED_GID $path/config >/dev/null 2>&1
a542dd3c
BP
383 chgrp -R root $path/rootfs >/dev/null 2>&1
384 fi
385}
386
eb960fea
DL
387usage()
388{
389 cat <<EOF
ed52814c 390$1 -h|--help -p|--path=<path> -s|--ssh={dropbear,openssh}
eb960fea
DL
391EOF
392 return 0
393}
394
ed52814c 395options=$(getopt -o hp:n:s: -l help,rootfs:,path:,name:,mapped-uid:,mapped-gid:,ssh: -- "$@")
eb960fea 396if [ $? -ne 0 ]; then
14d9c0f0
SG
397 usage $(basename $0)
398 exit 1
eb960fea
DL
399fi
400eval set -- "$options"
401
402while true
403do
404 case "$1" in
405 -h|--help) usage $0 && exit 0;;
406 -p|--path) path=$2; shift 2;;
1897e3bc 407 --rootfs) rootfs=$2; shift 2;;
14d9c0f0 408 -n|--name) name=$2; shift 2;;
a542dd3c
BP
409 --mapped-uid) LXC_MAPPED_UID=$2; shift 2;;
410 --mapped-gid) LXC_MAPPED_GID=$2; shift 2;;
ed52814c 411 -s|--ssh) SSH=$2; shift 2;;
eb960fea
DL
412 --) shift 1; break ;;
413 *) break ;;
414 esac
415done
416
417if [ "$(id -u)" != "0" ]; then
418 echo "This script should be run as 'root'"
419 exit 1
420fi
421
422if [ -z "$path" ]; then
423 echo "'path' parameter is required"
424 exit 1
425fi
426
1881820a
SH
427# detect rootfs
428config="$path/config"
1897e3bc 429if [ -z "$rootfs" ]; then
7a96a068
CB
430 if grep -q '^lxc.rootfs.path' $config 2>/dev/null ; then
431 rootfs=$(awk -F= '/^lxc.rootfs.path =/{ print $2 }' $config)
1897e3bc
SH
432 else
433 rootfs=$path/rootfs
434 fi
1881820a 435fi
eb960fea
DL
436
437install_busybox $rootfs $name
438if [ $? -ne 0 ]; then
439 echo "failed to install busybox's rootfs"
440 exit 1
441fi
442
443configure_busybox $rootfs
444if [ $? -ne 0 ]; then
445 echo "failed to configure busybox template"
446 exit 1
447fi
448
449copy_configuration $path $rootfs $name
450if [ $? -ne 0 ]; then
451 echo "failed to write configuration file"
452 exit 1
453fi
a542dd3c
BP
454
455remap_userns $path
456if [ $? -ne 0 ]; then
457 echo "failed to remap files to user"
458 exit 1
459fi
ed52814c
BP
460
461if [ -n "$SSH" ]; then
462 case "$SSH" in
463 "dropbear")
464 install_dropbear
465 if [ $? -ne 0 ]; then
466 echo "Unable to install 'dropbear' ssh utility"
467 exit 1
468 fi ;;
469 "openssh")
470 install_openssh
471 if [ $? -ne 0 ]; then
472 echo "Unable to install 'OpenSSH' utility"
473 exit 1
474 fi ;;
475 *)
476 echo "$SSH: unrecognized ssh utility"
477 exit 1
478 esac
479else
480 which dropbear >/dev/null 2>&1
481 if [ $? -eq 0 ]; then
482 install_dropbear
483 fi
484fi