4 # lxc: linux Container library
7 # Daniel Lezcano <daniel.lezcano@free.fr>
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.
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.
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
21 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 # Make sure the usual locations are in PATH
28 export PATH
=$PATH:/usr
/sbin
:/usr
/bin
:/sbin
:/bin
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; }
39 [ $
(am_in_userns
) = "yes" ] && in_userns
=1
62 $rootfs/usr/share/udhcpc \
70 mkdir
-p $tree ||
return 1
71 chmod 755 $tree ||
return 1
73 pushd $rootfs/dev
> /dev
/null ||
return 1
75 # minimal devices needed for busybox
76 if [ $in_userns -eq 1 ]; then
77 for dev
in tty console tty0 tty1 ram0 null urandom
; do
78 echo "lxc.mount.entry = /dev/$dev dev/$dev none bind,optional,create=file 0 0" >> $path/config
81 mknod
-m 666 tty c
5 0 || res
=1
82 mknod
-m 666 console c
5 1 || res
=1
83 mknod
-m 666 tty0 c
4 0 || res
=1
84 mknod
-m 666 tty1 c
4 0 || res
=1
85 mknod
-m 666 tty5 c
4 0 || res
=1
86 mknod
-m 600 ram0 b
1 0 || res
=1
87 mknod
-m 666 null c
1 3 || res
=1
88 mknod
-m 666 zero c
1 5 || res
=1
89 mknod
-m 666 urandom c
1 9 || res
=1
95 cat <<EOF >> $rootfs/etc/passwd
96 root:x:0:0:root:/root:/bin/sh
99 cat <<EOF >> $rootfs/etc/group
104 cat <<EOF >> $rootfs/etc/init.d/rcS
112 chmod 744 $rootfs/etc
/init.d
/rcS ||
return 1
114 # launch rcS first then make a console available
115 # and propose a shell on the tty, the last one is
117 cat <<EOF >> $rootfs/etc/inittab
118 ::sysinit:/etc/init.d/rcS
119 tty1::respawn:/bin/getty -L tty1 115200 vt100
120 console::askfirst:/bin/sh
122 # writable and readable for other
123 chmod 644 $rootfs/etc
/inittab ||
return 1
125 cat <<EOF >> $rootfs/usr/share/udhcpc/default.script
129 ip addr flush dev \$interface
133 # flush all the routes
134 if [ -n "\$router" ]; then
135 ip route del default 2> /dev/null
139 if [ -n "\$broadcast" ]; then
140 broadcast="broadcast \$broadcast"
143 # add a new ip address
144 ip addr add \$ip/\$mask \$broadcast dev \$interface
146 if [ -n "\$router" ]; then
147 ip route add default via \$router dev \$interface
150 [ -n "\$domain" ] && echo search \$domain > /etc/resolv.conf
152 echo nameserver \$i >> /etc/resolv.conf
159 chmod 744 $rootfs/usr
/share
/udhcpc
/default.
script
166 # copy dropbear binary
167 cp $
(which dropbear
) $rootfs/usr
/sbin
168 if [ $?
-ne 0 ]; then
169 echo "Failed to copy dropbear in the rootfs"
173 # make symlinks to various ssh utilities
175 $rootfs/usr/bin/dbclient \
176 $rootfs/usr/bin/scp \
177 $rootfs/usr/bin/ssh \
178 $rootfs/usr/sbin/dropbearkey \
179 $rootfs/usr/sbin/dropbearconvert \
181 echo $utils |
xargs -n1 ln -s /usr
/sbin
/dropbear
183 # add necessary config files
184 mkdir
$rootfs/etc
/dropbear
185 dropbearkey
-t rsa
-f $rootfs/etc
/dropbear
/dropbear_rsa_host_key
> /dev
/null
2>&1
186 dropbearkey
-t dss
-f $rootfs/etc
/dropbear
/dropbear_dss_host_key
> /dev
/null
2>&1
188 echo "'dropbear' ssh utility installed"
195 # tools to be installed
209 # new folders used by ssh
212 $rootfs/var/empty/sshd \
213 $rootfs/var/lib/empty/sshd \
214 $rootfs/var/run/sshd \
217 # create folder structure
219 if [ $?
-ne 0 ]; then
224 for bin
in $server_utils $client_utils; do
225 tool_path
=`which $bin`
226 cp $tool_path $rootfs/$tool_path
227 if [ $?
-ne 0 ]; then
228 echo "Unable to copy $tool_path in the rootfs"
234 cat <<EOF >> $rootfs/etc/passwd
235 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
238 cat <<EOF >> $rootfs/etc/group
242 # generate container keys
243 ssh-keygen
-t rsa
-N "" -f $rootfs/etc
/ssh
/ssh_host_rsa_key
>/dev
/null
2>&1
244 ssh-keygen
-t dsa
-N "" -f $rootfs/etc
/ssh
/ssh_host_dsa_key
>/dev
/null
2>&1
246 # by default setup root password with no password
247 cat <<EOF > $rootfs/etc/ssh/sshd_config
250 HostKey /etc/ssh/ssh_host_rsa_key
251 HostKey /etc/ssh/ssh_host_dsa_key
252 UsePrivilegeSeparation yes
253 KeyRegenerationInterval 3600
260 RSAAuthentication yes
261 PubkeyAuthentication yes
263 RhostsRSAAuthentication no
264 HostbasedAuthentication no
265 PermitEmptyPasswords yes
266 ChallengeResponseAuthentication no
269 echo "'OpenSSH' utility installed"
278 which busybox
>/dev
/null
2>&1
280 if [ $?
-ne 0 ]; then
281 echo "busybox executable is not accessible"
285 file -L $
(which busybox
) |
grep -q "statically linked"
286 if [ $?
-ne 0 ]; then
287 echo "warning : busybox is not statically linked."
288 echo "warning : The template script may not correctly"
289 echo "warning : setup the container environment."
292 # copy busybox in the rootfs
293 cp $
(which busybox
) $rootfs/bin
294 if [ $?
-ne 0 ]; then
295 echo "failed to copy busybox in the rootfs"
299 # symlink busybox for the commands it supports
300 # it would be nice to just use "chroot $rootfs busybox --install -s /bin"
301 # but that only works right in a chroot with busybox >= 1.19.0
302 pushd $rootfs/bin
> /dev
/null ||
return 1
303 .
/busybox
--help |
grep 'Currently defined functions:' -A300 | \
304 grep -v 'Currently defined functions:' |
tr , '\n' | \
305 xargs -n1 ln -s busybox
309 ln $rootfs/bin
/busybox
$rootfs/sbin
/init
311 # passwd exec must be setuid
312 chmod +s
$rootfs/bin
/passwd
313 touch $rootfs/etc
/shadow
315 # setting passwd for root
316 CHPASSWD_FILE
=$rootfs/root
/chpasswd.sh
318 cat <<EOF >$CHPASSWD_FILE
319 echo "setting root password to \"root\""
321 mount -n --bind /lib $rootfs/lib
322 if [ \$? -ne 0 ]; then
323 echo "Failed bind-mounting /lib at $rootfs/lib"
327 chroot $rootfs chpasswd <<EOFF 2>/dev/null
332 if [ \$? -ne 0 ]; then
333 echo "Failed to change root password"
341 lxc-unshare
-s MOUNT
-- /bin
/sh
< $CHPASSWD_FILE
353 grep -q "^lxc.rootfs" $path/config
2>/dev
/null ||
echo "lxc.rootfs = $rootfs" >> $path/config
354 cat <<EOF >> $path/config
355 lxc.haltsignal = SIGUSR1
356 lxc.rebootsignal = SIGTERM
360 lxc.cap.drop = sys_module mac_admin mac_override sys_time
362 # When using LXC with apparmor, uncomment the next line to run unconfined:
363 #lxc.aa_profile = unconfined
365 lxc.mount.auto = cgroup:mixed proc:mixed sys:mixed
366 lxc.mount.entry = shm /dev/shm tmpfs defaults 0 0
375 for dir
in $libdirs; do
376 if [ -d "/$dir" ] && [ -d "$rootfs/$dir" ]; then
377 echo "lxc.mount.entry = /$dir $dir none ro,bind 0 0" >> $path/config
380 echo "lxc.mount.entry = /sys/kernel/security sys/kernel/security none ro,bind,optional 0 0" >>$path/config
387 if [ -n "$LXC_MAPPED_UID" ] && [ "$LXC_MAPPED_UID" != "-1" ]; then
388 chown
$LXC_MAPPED_UID $path/config
>/dev
/null
2>&1
389 chown
-R root
$path/rootfs
>/dev
/null
2>&1
392 if [ -n "$LXC_MAPPED_GID" ] && [ "$LXC_MAPPED_GID" != "-1" ]; then
393 chgrp
$LXC_MAPPED_GID $path/config
>/dev
/null
2>&1
394 chgrp
-R root
$path/rootfs
>/dev
/null
2>&1
401 $1 -h|--help -p|--path=<path> -s|--ssh={dropbear,openssh}
406 options
=$
(getopt
-o hp
:n
:s
: -l help,rootfs
:,path
:,name
:,mapped-uid
:,mapped-gid
:,ssh: -- "$@")
407 if [ $?
-ne 0 ]; then
411 eval set -- "$options"
416 -h|
--help) usage
$0 && exit 0;;
417 -p|
--path) path
=$2; shift 2;;
418 --rootfs) rootfs
=$2; shift 2;;
419 -n|
--name) name
=$2; shift 2;;
420 --mapped-uid) LXC_MAPPED_UID
=$2; shift 2;;
421 --mapped-gid) LXC_MAPPED_GID
=$2; shift 2;;
422 -s|
--ssh) SSH
=$2; shift 2;;
423 --) shift 1; break ;;
428 if [ "$(id -u)" != "0" ]; then
429 echo "This script should be run as 'root'"
433 if [ -z "$path" ]; then
434 echo "'path' parameter is required"
439 config
="$path/config"
440 if [ -z "$rootfs" ]; then
441 if grep -q '^lxc.rootfs' $config 2>/dev
/null
; then
442 rootfs
=$
(awk -F= '/^lxc.rootfs =/{ print $2 }' $config)
448 install_busybox
$rootfs $name
449 if [ $?
-ne 0 ]; then
450 echo "failed to install busybox's rootfs"
454 configure_busybox
$rootfs
455 if [ $?
-ne 0 ]; then
456 echo "failed to configure busybox template"
460 copy_configuration
$path $rootfs $name
461 if [ $?
-ne 0 ]; then
462 echo "failed to write configuration file"
467 if [ $?
-ne 0 ]; then
468 echo "failed to remap files to user"
472 if [ -n "$SSH" ]; then
476 if [ $?
-ne 0 ]; then
477 echo "Unable to install 'dropbear' ssh utility"
482 if [ $?
-ne 0 ]; then
483 echo "Unable to install 'OpenSSH' utility"
487 echo "$SSH: unrecognized ssh utility"
491 which dropbear
>/dev
/null
2>&1
492 if [ $?
-eq 0 ]; then