source: lab.git/lxc/0.7.5-3ubuntu63/templates/lxc-ubuntu @ 995c968

vendor
Last change on this file since 995c968 was 995c968, checked in by mitty <mitty@…>, 12 years ago
  • /usr/lib/lxc/templates of lxc 0.7.5-3ubuntu63 on Ubuntu 12.04.1

git-svn-id: https://lab.mitty.jp/svn/lab/vendor@174 7d2118f6-f56c-43e7-95a2-4bb3031d96e7

  • Property mode set to 100755
File size: 19.0 KB
Line 
1#!/bin/bash
2
3#
4# template script for generating ubuntu container for LXC
5#
6# This script consolidates and extends the existing lxc ubuntu scripts
7#
8
9# Copyright © 2011 Serge Hallyn <serge.hallyn@canonical.com>
10# Copyright © 2010 Wilhelm Meier
11# Author: Wilhelm Meier <wilhelm.meier@fh-kl.de>
12#
13# This program is free software; you can redistribute it and/or modify
14# it under the terms of the GNU General Public License version 2, as
15# published by the Free Software Foundation.
16
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20# GNU General Public License for more details.
21
22# You should have received a copy of the GNU General Public License along
23# with this program; if not, write to the Free Software Foundation, Inc.,
24# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25#
26
27set -e
28
29if [ -r /etc/default/lxc ]; then
30    . /etc/default/lxc
31fi
32
33configure_ubuntu()
34{
35    rootfs=$1
36    hostname=$2
37    release=$3
38
39   # configure the network using the dhcp
40    cat <<EOF > $rootfs/etc/network/interfaces
41# This file describes the network interfaces available on your system
42# and how to activate them. For more information, see interfaces(5).
43
44# The loopback network interface
45auto lo
46iface lo inet loopback
47
48auto eth0
49iface eth0 inet dhcp
50EOF
51
52    # set the hostname
53    cat <<EOF > $rootfs/etc/hostname
54$hostname
55EOF
56    # set minimal hosts
57    cat <<EOF > $rootfs/etc/hosts
58127.0.0.1   localhost
59127.0.1.1   $hostname
60
61# The following lines are desirable for IPv6 capable hosts
62::1     ip6-localhost ip6-loopback
63fe00::0 ip6-localnet
64ff00::0 ip6-mcastprefix
65ff02::1 ip6-allnodes
66ff02::2 ip6-allrouters
67EOF
68
69    if [ ! -f $rootfs/etc/init/container-detect.conf ]; then
70        # suppress log level output for udev
71        sed -i "s/=\"err\"/=0/" $rootfs/etc/udev/udev.conf
72
73        # remove jobs for consoles 5 and 6 since we only create 4 consoles in
74        # this template
75        rm -f $rootfs/etc/init/tty{5,6}.conf
76    fi
77
78    if [ -z "$bindhome" ]; then
79        chroot $rootfs useradd --create-home -s /bin/bash ubuntu
80        echo "ubuntu:ubuntu" | chroot $rootfs chpasswd
81    fi
82
83    return 0
84}
85
86# finish setting up the user in the container by injecting ssh key and
87# adding sudo group membership.
88# passed-in user is either 'ubuntu' or the user to bind in from host.
89finalize_user()
90{
91    user=$1
92
93    sudo_version=$(chroot $rootfs dpkg-query -W -f='${Version}' sudo)
94
95    if chroot $rootfs dpkg --compare-versions $sudo_version gt "1.8.3p1-1"; then
96        groups="sudo"
97    else
98        groups="sudo admin"
99    fi
100
101    for group in $groups; do
102        chroot $rootfs groupadd --system $group >/dev/null 2>&1 || true
103        chroot $rootfs adduser ${user} $group >/dev/null 2>&1 || true
104    done
105
106    if [ -n "$auth_key" -a -f "$auth_key" ]; then
107        u_path="/home/${user}/.ssh"
108        root_u_path="$rootfs/$u_path"
109
110        mkdir -p $root_u_path
111        cp $auth_key "$root_u_path/authorized_keys"
112        chroot $rootfs chown -R ${user}: "$u_path"
113
114        echo "Inserted SSH public key from $auth_key into /home/${user}/.ssh/authorized_keys"
115    fi
116    return 0
117}
118
119write_sourceslist()
120{
121    # $1 => path to the rootfs
122    # $2 => architecture we want to add
123    # $3 => whether to use the multi-arch syntax or not
124
125    case $2 in
126      amd64|i386)
127            MIRROR=${MIRROR:-http://archive.ubuntu.com/ubuntu}
128            SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.ubuntu.com/ubuntu}
129            ;;
130      *)
131            MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
132            SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports}
133            ;;
134    esac
135    if [ -n "$3" ]; then
136        cat >> "$1/etc/apt/sources.list" << EOF
137deb [arch=$2] $MIRROR ${release} main restricted universe multiverse
138deb [arch=$2] $MIRROR ${release}-updates main restricted universe multiverse
139deb [arch=$2] $SECURITY_MIRROR ${release}-security main restricted universe multiverse
140EOF
141    else
142        cat >> "$1/etc/apt/sources.list" << EOF
143deb $MIRROR ${release} main restricted universe multiverse
144deb $MIRROR ${release}-updates main restricted universe multiverse
145deb $SECURITY_MIRROR ${release}-security main restricted universe multiverse
146EOF
147    fi
148}
149
150download_ubuntu()
151{
152    cache=$1
153    arch=$2
154    release=$3
155
156    packages=vim,ssh
157    echo "installing packages: $packages"
158
159    # check the mini ubuntu was not already downloaded
160    mkdir -p "$cache/partial-$arch"
161    if [ $? -ne 0 ]; then
162        echo "Failed to create '$cache/partial-$arch' directory"
163        return 1
164    fi
165
166    # download a mini ubuntu into a cache
167    echo "Downloading ubuntu $release minimal ..."
168    if [ -n "$(which qemu-debootstrap)" ]; then
169        qemu-debootstrap --verbose --components=main,universe --arch=$arch --include=$packages $release $cache/partial-$arch $MIRROR
170    else
171        debootstrap --verbose --components=main,universe --arch=$arch --include=$packages $release $cache/partial-$arch $MIRROR
172    fi
173
174    if [ $? -ne 0 ]; then
175        echo "Failed to download the rootfs, aborting."
176            return 1
177    fi
178
179    # Serge isn't sure whether we should avoid doing this when
180    # $release == `distro-info -d`
181    echo "Installing updates"
182    > $cache/partial-$arch/etc/apt/sources.list
183    write_sourceslist $cache/partial-$arch/ $arch
184
185    chroot "$1/partial-${arch}" apt-get update
186    if [ $? -ne 0 ]; then
187        echo "Failed to update the apt cache"
188        return 1
189    fi
190    cat > "$1/partial-${arch}"/usr/sbin/policy-rc.d << EOF
191#!/bin/sh
192exit 101
193EOF
194    chmod +x "$1/partial-${arch}"/usr/sbin/policy-rc.d
195
196    lxc-unshare -s MOUNT -- chroot "$1/partial-${arch}" apt-get dist-upgrade -y
197    ret=$?
198    rm -f "$1/partial-${arch}"/usr/sbin/policy-rc.d
199
200    if [ $ret -ne 0 ]; then
201        echo "Failed to upgrade the cache"
202        return 1
203    fi
204
205    mv "$1/partial-$arch" "$1/rootfs-$arch"
206    echo "Download complete"
207    return 0
208}
209
210copy_ubuntu()
211{
212    cache=$1
213    arch=$2
214    rootfs=$3
215
216    # make a local copy of the miniubuntu
217    echo "Copying rootfs to $rootfs ..."
218    mkdir -p $rootfs
219    rsync -a $cache/rootfs-$arch/ $rootfs/ || return 1
220    return 0
221}
222
223install_ubuntu()
224{
225    rootfs=$1
226    release=$2
227    flushcache=$3
228    cache="/var/cache/lxc/$release"
229    mkdir -p /var/lock/subsys/
230
231    (
232        flock -x 200
233        if [ $? -ne 0 ]; then
234            echo "Cache repository is busy."
235            return 1
236        fi
237
238
239        if [ $flushcache -eq 1 ]; then
240            echo "Flushing cache..."
241            rm -rf "$cache/partial-$arch"
242            rm -rf "$cache/rootfs-$arch"
243        fi
244
245        echo "Checking cache download in $cache/rootfs-$arch ... "
246        if [ ! -e "$cache/rootfs-$arch" ]; then
247            download_ubuntu $cache $arch $release
248            if [ $? -ne 0 ]; then
249                echo "Failed to download 'ubuntu $release base'"
250                return 1
251            fi
252        fi
253
254        echo "Copy $cache/rootfs-$arch to $rootfs ... "
255        copy_ubuntu $cache $arch $rootfs
256        if [ $? -ne 0 ]; then
257            echo "Failed to copy rootfs"
258            return 1
259        fi
260
261        return 0
262
263    ) 200>/var/lock/subsys/lxc
264
265    return $?
266}
267
268copy_configuration()
269{
270    path=$1
271    rootfs=$2
272    name=$3
273    arch=$4
274    release=$5
275
276    if [ $arch = "i386" ]; then
277        arch="i686"
278    fi
279
280    ttydir=""
281    if [ -f $rootfs/etc/init/container-detect.conf ]; then
282        ttydir=" lxc"
283    fi
284
285    # if there is exactly one veth network entry, make sure it has an
286    # associated hwaddr.
287    nics=`grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' $path/config | wc -l`
288    if [ $nics -eq 1 ]; then
289        grep -q "^lxc.network.hwaddr" $path/config || cat <<EOF >> $path/config
290lxc.network.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')
291EOF
292    fi
293
294    cat <<EOF >> $path/config
295lxc.utsname = $name
296
297lxc.devttydir =$ttydir
298lxc.tty = 4
299lxc.pts = 1024
300lxc.rootfs = $rootfs
301lxc.mount  = $path/fstab
302lxc.arch = $arch
303lxc.cap.drop = sys_module mac_admin
304lxc.pivotdir = lxc_putold
305
306# uncomment the next line to run the container unconfined:
307#lxc.aa_profile = unconfined
308
309lxc.cgroup.devices.deny = a
310# Allow any mknod (but not using the node)
311lxc.cgroup.devices.allow = c *:* m
312lxc.cgroup.devices.allow = b *:* m
313# /dev/null and zero
314lxc.cgroup.devices.allow = c 1:3 rwm
315lxc.cgroup.devices.allow = c 1:5 rwm
316# consoles
317lxc.cgroup.devices.allow = c 5:1 rwm
318lxc.cgroup.devices.allow = c 5:0 rwm
319#lxc.cgroup.devices.allow = c 4:0 rwm
320#lxc.cgroup.devices.allow = c 4:1 rwm
321# /dev/{,u}random
322lxc.cgroup.devices.allow = c 1:9 rwm
323lxc.cgroup.devices.allow = c 1:8 rwm
324lxc.cgroup.devices.allow = c 136:* rwm
325lxc.cgroup.devices.allow = c 5:2 rwm
326# rtc
327lxc.cgroup.devices.allow = c 254:0 rwm
328#fuse
329lxc.cgroup.devices.allow = c 10:229 rwm
330#tun
331lxc.cgroup.devices.allow = c 10:200 rwm
332#full
333lxc.cgroup.devices.allow = c 1:7 rwm
334#hpet
335lxc.cgroup.devices.allow = c 10:228 rwm
336#kvm
337lxc.cgroup.devices.allow = c 10:232 rwm
338EOF
339
340    cat <<EOF > $path/fstab
341proc            proc         proc    nodev,noexec,nosuid 0 0
342sysfs           sys          sysfs defaults  0 0
343EOF
344
345    if [ $? -ne 0 ]; then
346        echo "Failed to add configuration"
347        return 1
348    fi
349
350    return 0
351}
352
353trim()
354{
355    rootfs=$1
356    release=$2
357
358    # provide the lxc service
359    cat <<EOF > $rootfs/etc/init/lxc.conf
360# fake some events needed for correct startup other services
361
362description     "Container Upstart"
363
364start on startup
365
366script
367        rm -rf /var/run/*.pid
368        rm -rf /var/run/network/*
369        /sbin/initctl emit stopped JOB=udevtrigger --no-wait
370        /sbin/initctl emit started JOB=udev --no-wait
371end script
372EOF
373
374    # fix buggus runlevel with sshd
375    cat <<EOF > $rootfs/etc/init/ssh.conf
376# ssh - OpenBSD Secure Shell server
377#
378# The OpenSSH server provides secure shell access to the system.
379
380description "OpenSSH server"
381
382start on filesystem
383stop on runlevel [!2345]
384
385expect fork
386respawn
387respawn limit 10 5
388umask 022
389# replaces SSHD_OOM_ADJUST in /etc/default/ssh
390oom never
391
392pre-start script
393    test -x /usr/sbin/sshd || { stop; exit 0; }
394    test -e /etc/ssh/sshd_not_to_be_run && { stop; exit 0; }
395    test -c /dev/null || { stop; exit 0; }
396
397    mkdir -p -m0755 /var/run/sshd
398end script
399
400# if you used to set SSHD_OPTS in /etc/default/ssh, you can change the
401# 'exec' line here instead
402exec /usr/sbin/sshd
403EOF
404
405    cat <<EOF > $rootfs/etc/init/console.conf
406# console - getty
407#
408# This service maintains a console on tty1 from the point the system is
409# started until it is shut down again.
410
411start on stopped rc RUNLEVEL=[2345]
412stop on runlevel [!2345]
413
414respawn
415exec /sbin/getty -8 38400 /dev/console
416EOF
417
418    cat <<EOF > $rootfs/lib/init/fstab
419# /lib/init/fstab: cleared out for bare-bones lxc
420EOF
421
422    # reconfigure some services
423    if [ -z "$LANG" ]; then
424        chroot $rootfs locale-gen en_US.UTF-8
425        chroot $rootfs update-locale LANG=en_US.UTF-8
426    else
427        chroot $rootfs locale-gen $LANG
428        chroot $rootfs update-locale LANG=$LANG
429    fi
430
431    # remove pointless services in a container
432    chroot $rootfs /usr/sbin/update-rc.d -f ondemand remove
433
434    chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls u*.conf); do mv $f $f.orig; done'
435    chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls tty[2-9].conf); do mv $f $f.orig; done'
436    chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls plymouth*.conf); do mv $f $f.orig; done'
437    chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls hwclock*.conf); do mv $f $f.orig; done'
438    chroot $rootfs /bin/bash -c 'cd /etc/init; for f in $(ls module*.conf); do mv $f $f.orig; done'
439
440    # if this isn't lucid, then we need to twiddle the network upstart bits :(
441    if [ $release != "lucid" ]; then
442        sed -i 's/^.*emission handled.*$/echo Emitting lo/' $rootfs/etc/network/if-up.d/upstart
443    fi
444}
445
446post_process()
447{
448    rootfs=$1
449    release=$2
450    trim_container=$3
451
452    if [ $trim_container -eq 1 ]; then
453        trim $rootfs $release
454    elif [ ! -f $rootfs/etc/init/container-detect.conf ]; then
455        # Make sure we have a working resolv.conf
456        cresolvonf="${rootfs}/etc/resolv.conf"
457        mv $cresolvonf ${cresolvonf}.lxcbak
458        cat /etc/resolv.conf > ${cresolvonf}
459
460        # for lucid, if not trimming, then add the ubuntu-virt
461        # ppa and install lxcguest
462        if [ $release = "lucid" ]; then
463            chroot $rootfs apt-get install --force-yes -y python-software-properties
464            chroot $rootfs add-apt-repository ppa:ubuntu-virt/ppa
465        fi
466
467        chroot $rootfs apt-get update
468        chroot $rootfs apt-get install --force-yes -y lxcguest
469
470        # Restore old resolv.conf
471        rm -f ${cresolvonf}
472        mv ${cresolvonf}.lxcbak ${cresolvonf}
473    fi
474
475    # If the container isn't running a native architecture, setup multiarch
476    if [ -x "$(ls -1 ${rootfs}/usr/bin/qemu-*-static 2>/dev/null)" ]; then
477        dpkg_version=$(chroot $rootfs dpkg-query -W -f='${Version}' dpkg)
478        if chroot $rootfs dpkg --compare-versions $dpkg_version ge "1.16.2"; then
479            chroot $rootfs dpkg --add-architecture ${hostarch}
480        else
481            mkdir -p ${rootfs}/etc/dpkg/dpkg.cfg.d
482            echo "foreign-architecture ${hostarch}" > ${rootfs}/etc/dpkg/dpkg.cfg.d/lxc-multiarch
483        fi
484
485        # Save existing value of MIRROR and SECURITY_MIRROR
486        DEFAULT_MIRROR=$MIRROR
487        DEFAULT_SECURITY_MIRROR=$SECURITY_MIRROR
488
489        # Write a new sources.list containing both native and multiarch entries
490        > ${rootfs}/etc/apt/sources.list
491        write_sourceslist $rootfs $arch "native"
492
493        MIRROR=$DEFAULT_MIRROR
494        SECURITY_MIRROR=$DEFAULT_SECURITY_MIRROR
495        write_sourceslist $rootfs $hostarch "multiarch"
496
497        # Finally update the lists and install upstart using the host architecture
498        chroot $rootfs apt-get update
499        chroot $rootfs apt-get install --force-yes -y --no-install-recommends upstart:${hostarch} mountall:${hostarch} iproute:${hostarch} isc-dhcp-client:${hostarch}
500    fi
501
502    # rmdir /dev/shm for containers that have /run/shm
503    # I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did
504    # get bind mounted to the host's /run/shm.  So try to rmdir
505    # it, and in case that fails move it out of the way.
506    if [ ! -L $rootfs/dev/shm ] && [ -d $rootfs/run/shm ] && [ -e $rootfs/dev/shm ]; then
507        mv $rootfs/dev/shm $rootfs/dev/shm.bak
508        ln -s /run/shm $rootfs/dev/shm
509    fi
510}
511
512do_bindhome()
513{
514    rootfs=$1
515    user=$2
516
517    # copy /etc/passwd, /etc/shadow, and /etc/group entries into container
518    pwd=`getent passwd $user` || { echo "Failed to copy password entry for $user"; false; }
519    echo $pwd >> $rootfs/etc/passwd
520
521    # make sure user's shell exists in the container
522    shell=`echo $pwd | cut -d: -f 7`
523    if [ ! -x $rootfs/$shell ]; then
524        echo "shell $shell for user $user was not found in the container."
525        pkg=`dpkg -S $(readlink -m $shell) | cut -d ':' -f1`
526        echo "Installing $pkg"
527        chroot $rootfs apt-get --force-yes -y install $pkg
528    fi
529
530    shad=`getent shadow $user`
531    echo "$shad" >> $rootfs/etc/shadow
532
533    # bind-mount the user's path into the container's /home
534    h=`getent passwd $user | cut -d: -f 6`
535    mkdir -p $rootfs/$h
536
537    # use relative path in container
538    h2=${h#/}
539    while [ ${h2:0:1} = "/" ]; do
540        h2=${h2#/}
541    done
542    echo "$h $h2 none bind 0 0" >> $path/fstab
543
544    # Make sure the group exists in container
545    grp=`echo $pwd | cut -d: -f 4`  # group number for $user
546    grpe=`getent group $grp` || return # if host doesn't define grp, ignore in container
547    chroot $rootfs getent group "$grpe" || echo "$grpe" >> $rootfs/etc/group
548}
549
550usage()
551{
552    cat <<EOF
553$1 -h|--help [-a|--arch] [-b|--bindhome <user>] [--trim] [-d|--debug]
554   [-F | --flush-cache] [-r|--release <release>] [ -S | --auth-key <keyfile>]
555release: the ubuntu release (e.g. precise): defaults to host release on ubuntu, otherwise uses latest LTS
556trim: make a minimal (faster, but not upgrade-safe) container
557bindhome: bind <user>'s home into the container
558          The ubuntu user will not be created, and <user> will have
559          sudo access.
560arch: the container architecture (e.g. amd64): defaults to host arch
561auth-key: SSH Public key file to inject into container
562EOF
563    return 0
564}
565
566options=$(getopt -o a:b:hp:r:xn:FS:d -l arch:,bindhome:,help,path:,release:,trim,name:,flush-cache,auth-key:,debug -- "$@")
567if [ $? -ne 0 ]; then
568    usage $(basename $0)
569    exit 1
570fi
571eval set -- "$options"
572
573release=precise # Default to the last Ubuntu LTS release for non-Ubuntu systems
574if [ -f /etc/lsb-release ]; then
575    . /etc/lsb-release
576    if [ "$DISTRIB_ID" = "Ubuntu" ]; then
577        release=$DISTRIB_CODENAME
578    fi
579fi
580
581bindhome=
582arch=$(arch)
583
584# Code taken from debootstrap
585if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then
586    arch=`/usr/bin/dpkg --print-architecture`
587elif type udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then
588    arch=`/usr/bin/udpkg --print-architecture`
589else
590    arch=$(arch)
591    if [ "$arch" = "i686" ]; then
592        arch="i386"
593    elif [ "$arch" = "x86_64" ]; then
594        arch="amd64"
595    elif [ "$arch" = "armv7l" ]; then
596        arch="armel"
597    fi
598fi
599
600debug=0
601trim_container=0
602hostarch=$arch
603flushcache=0
604while true
605do
606    case "$1" in
607    -h|--help)      usage $0 && exit 0;;
608    -p|--path)      path=$2; shift 2;;
609    -n|--name)      name=$2; shift 2;;
610    -F|--flush-cache) flushcache=1; shift 1;;
611    -r|--release)   release=$2; shift 2;;
612    -b|--bindhome)  bindhome=$2; shift 2;;
613    -a|--arch)      arch=$2; shift 2;;
614    -x|--trim)      trim_container=1; shift 1;;
615    -S|--auth-key)  auth_key=$2; shift 2;;
616    -d|--debug)     debug=1; shift 1;;
617    --)             shift 1; break ;;
618        *)              break ;;
619    esac
620done
621
622if [ $debug -eq 1 ]; then
623    set -x
624fi
625
626if [ -n "$bindhome" ]; then
627    pwd=`getent passwd $bindhome`
628    if [ $? -ne 0 ]; then
629        echo "Error: no password entry found for $bindhome"
630        exit 1
631    fi
632fi
633
634
635if [ "$arch" == "i686" ]; then
636    arch=i386
637fi
638
639if [ $hostarch = "i386" -a $arch = "amd64" ]; then
640    echo "can't create amd64 container on i386"
641    exit 1
642fi
643
644type debootstrap
645if [ $? -ne 0 ]; then
646    echo "'debootstrap' command is missing"
647    exit 1
648fi
649
650if [ -z "$path" ]; then
651    echo "'path' parameter is required"
652    exit 1
653fi
654
655if [ "$(id -u)" != "0" ]; then
656    echo "This script should be run as 'root'"
657    exit 1
658fi
659
660rootfs=$path/rootfs
661
662install_ubuntu $rootfs $release $flushcache
663if [ $? -ne 0 ]; then
664    echo "failed to install ubuntu $release"
665    exit 1
666fi
667
668configure_ubuntu $rootfs $name $release
669if [ $? -ne 0 ]; then
670    echo "failed to configure ubuntu $release for a container"
671    exit 1
672fi
673
674copy_configuration $path $rootfs $name $arch $release
675if [ $? -ne 0 ]; then
676    echo "failed write configuration file"
677    exit 1
678fi
679
680post_process $rootfs $release $trim_container
681
682if [ -n "$bindhome" ]; then
683    do_bindhome $rootfs $bindhome
684    finalize_user $bindhome
685else
686    finalize_user ubuntu
687fi
688
689echo ""
690echo "##"
691echo "# The default user is 'ubuntu' with password 'ubuntu'!"
692echo "# Use the 'sudo' command to run tasks as root in the container."
693echo "##"
694echo ""
Note: See TracBrowser for help on using the repository browser.