Remove obsolete build directories
This commit is contained in:
@@ -1,4 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
echo "127.0.0.1 localhost" >> /tmp/hosts
|
|
||||||
echo "$HOST_ADDR host" >> /tmp/hosts
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export LC_ALL=C
|
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
|
||||||
minimal_apt_get_install='apt-get install -y --no-install-recommends'
|
|
||||||
@@ -1,314 +0,0 @@
|
|||||||
#!/usr/bin/python2 -u
|
|
||||||
import os, os.path, sys, stat, signal, errno, argparse, time, json, re, posixfile
|
|
||||||
|
|
||||||
KILL_PROCESS_TIMEOUT = 5
|
|
||||||
KILL_ALL_PROCESSES_TIMEOUT = 5
|
|
||||||
|
|
||||||
LOG_LEVEL_ERROR = 1
|
|
||||||
LOG_LEVEL_WARN = 1
|
|
||||||
LOG_LEVEL_INFO = 2
|
|
||||||
LOG_LEVEL_DEBUG = 3
|
|
||||||
|
|
||||||
log_level = None
|
|
||||||
|
|
||||||
class AlarmException(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def error(message):
|
|
||||||
if log_level >= LOG_LEVEL_ERROR:
|
|
||||||
sys.stderr.write("*** %s\n" % message)
|
|
||||||
|
|
||||||
def warn(message):
|
|
||||||
if log_level >= LOG_LEVEL_WARN:
|
|
||||||
print("*** %s" % message)
|
|
||||||
|
|
||||||
def info(message):
|
|
||||||
if log_level >= LOG_LEVEL_INFO:
|
|
||||||
print("*** %s" % message)
|
|
||||||
|
|
||||||
def debug(message):
|
|
||||||
if log_level >= LOG_LEVEL_DEBUG:
|
|
||||||
print("*** %s" % message)
|
|
||||||
|
|
||||||
def ignore_signals_and_raise_keyboard_interrupt(signame):
|
|
||||||
signal.signal(signal.SIGTERM, signal.SIG_IGN)
|
|
||||||
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
|
||||||
raise KeyboardInterrupt(signame)
|
|
||||||
|
|
||||||
def raise_alarm_exception():
|
|
||||||
raise AlarmException('Alarm')
|
|
||||||
|
|
||||||
def listdir(path):
|
|
||||||
try:
|
|
||||||
result = os.stat(path)
|
|
||||||
except OSError:
|
|
||||||
return []
|
|
||||||
if stat.S_ISDIR(result.st_mode):
|
|
||||||
return sorted(os.listdir(path))
|
|
||||||
else:
|
|
||||||
return []
|
|
||||||
|
|
||||||
def is_exe(path):
|
|
||||||
try:
|
|
||||||
return os.path.isfile(path) and os.access(path, os.X_OK)
|
|
||||||
except OSError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def import_envvars(clear_existing_environment = True):
|
|
||||||
new_env = {}
|
|
||||||
for envfile in listdir("/etc/container_environment"):
|
|
||||||
name = os.path.basename(envfile)
|
|
||||||
with open("/etc/container_environment/" + envfile, "r") as f:
|
|
||||||
value = f.read()
|
|
||||||
new_env[name] = value
|
|
||||||
if clear_existing_environment:
|
|
||||||
os.environ.clear()
|
|
||||||
for name, value in new_env.items():
|
|
||||||
os.environ[name] = value
|
|
||||||
|
|
||||||
def export_envvars(to_dir = True):
|
|
||||||
shell_dump = ""
|
|
||||||
for name, value in os.environ.items():
|
|
||||||
if to_dir:
|
|
||||||
with open("/etc/container_environment/" + name, "w") as f:
|
|
||||||
f.write(value)
|
|
||||||
shell_dump += "export " + shquote(name) + "=" + shquote(value) + "\n"
|
|
||||||
with open("/etc/container_environment.sh", "w") as f:
|
|
||||||
f.write(shell_dump)
|
|
||||||
with open("/etc/container_environment.json", "w") as f:
|
|
||||||
f.write(json.dumps(dict(os.environ)))
|
|
||||||
|
|
||||||
_find_unsafe = re.compile(r'[^\w@%+=:,./-]').search
|
|
||||||
|
|
||||||
def shquote(s):
|
|
||||||
"""Return a shell-escaped version of the string *s*."""
|
|
||||||
if not s:
|
|
||||||
return "''"
|
|
||||||
if _find_unsafe(s) is None:
|
|
||||||
return s
|
|
||||||
|
|
||||||
# use single quotes, and put single quotes into double quotes
|
|
||||||
# the string $'b is then quoted as '$'"'"'b'
|
|
||||||
return "'" + s.replace("'", "'\"'\"'") + "'"
|
|
||||||
|
|
||||||
def waitpid_reap_other_children(pid):
|
|
||||||
done = False
|
|
||||||
status = None
|
|
||||||
try:
|
|
||||||
this_pid, status = os.waitpid(pid, os.WNOHANG)
|
|
||||||
except OSError as e:
|
|
||||||
if e.errno == errno.ECHILD or e.errno == errno.ESRCH:
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
while not done:
|
|
||||||
this_pid, status = os.waitpid(-1, 0)
|
|
||||||
done = this_pid == pid
|
|
||||||
return status
|
|
||||||
|
|
||||||
def stop_child_process(name, pid, signo = signal.SIGTERM, time_limit = KILL_PROCESS_TIMEOUT):
|
|
||||||
info("Shutting down %s (PID %d)..." % (name, pid))
|
|
||||||
try:
|
|
||||||
os.kill(pid, signo)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
signal.alarm(time_limit)
|
|
||||||
try:
|
|
||||||
try:
|
|
||||||
waitpid_reap_other_children(pid)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
except AlarmException:
|
|
||||||
warn("%s (PID %d) did not shut down in time. Forcing it to exit." % (name, pid))
|
|
||||||
try:
|
|
||||||
os.kill(pid, signal.SIGKILL)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
waitpid_reap_other_children(pid)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
signal.alarm(0)
|
|
||||||
|
|
||||||
def run_command_killable(*argv):
|
|
||||||
filename = argv[0]
|
|
||||||
status = None
|
|
||||||
pid = os.spawnvp(os.P_NOWAIT, filename, argv)
|
|
||||||
try:
|
|
||||||
status = waitpid_reap_other_children(pid)
|
|
||||||
except BaseException as s:
|
|
||||||
warn("An error occurred. Aborting.")
|
|
||||||
stop_child_process(filename, pid)
|
|
||||||
raise
|
|
||||||
if status != 0:
|
|
||||||
if status is None:
|
|
||||||
error("%s exited with unknown status\n" % filename)
|
|
||||||
else:
|
|
||||||
error("%s failed with status %d\n" % (filename, os.WEXITSTATUS(status)))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
def run_command_killable_and_import_envvars(*argv):
|
|
||||||
run_command_killable(*argv)
|
|
||||||
import_envvars()
|
|
||||||
export_envvars(False)
|
|
||||||
|
|
||||||
def kill_all_processes(time_limit):
|
|
||||||
info("Killing all processes...")
|
|
||||||
try:
|
|
||||||
os.kill(-1, signal.SIGTERM)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
signal.alarm(time_limit)
|
|
||||||
try:
|
|
||||||
# Wait until no more child processes exist.
|
|
||||||
done = False
|
|
||||||
while not done:
|
|
||||||
try:
|
|
||||||
os.waitpid(-1, 0)
|
|
||||||
except OSError as e:
|
|
||||||
if e.errno == errno.ECHILD:
|
|
||||||
done = True
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
except AlarmException:
|
|
||||||
warn("Not all processes have exited in time. Forcing them to exit.")
|
|
||||||
try:
|
|
||||||
os.kill(-1, signal.SIGKILL)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
signal.alarm(0)
|
|
||||||
|
|
||||||
def run_startup_files():
|
|
||||||
# Run /opt/init.d/*
|
|
||||||
for name in listdir("/opt/init.d"):
|
|
||||||
filename = "/opt/init.d/" + name
|
|
||||||
if is_exe(filename):
|
|
||||||
info("Running %s..." % filename)
|
|
||||||
run_command_killable_and_import_envvars(filename)
|
|
||||||
|
|
||||||
# Run /etc/rc.local.
|
|
||||||
if is_exe("/etc/rc.local"):
|
|
||||||
info("Running /etc/rc.local...")
|
|
||||||
run_command_killable_and_import_envvars("/etc/rc.local")
|
|
||||||
|
|
||||||
def start_runit():
|
|
||||||
info("Booting runit daemon...")
|
|
||||||
pid = os.spawnl(os.P_NOWAIT, "/usr/bin/runsvdir", "/usr/bin/runsvdir",
|
|
||||||
"-P", "/etc/service", "log: %s" % ('.' * 395))
|
|
||||||
info("Runit started as PID %d" % pid)
|
|
||||||
return pid
|
|
||||||
|
|
||||||
def wait_for_runit_or_interrupt(pid):
|
|
||||||
try:
|
|
||||||
status = waitpid_reap_other_children(pid)
|
|
||||||
return (True, status)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
return (False, None)
|
|
||||||
|
|
||||||
def shutdown_runit_services():
|
|
||||||
debug("Begin shutting down runit services...")
|
|
||||||
os.system("/usr/bin/sv down /etc/service/*")
|
|
||||||
|
|
||||||
def wait_for_runit_services():
|
|
||||||
debug("Waiting for runit services to exit...")
|
|
||||||
done = False
|
|
||||||
while not done:
|
|
||||||
done = os.system("/usr/bin/sv status /etc/service/* | grep -q '^run:'") != 0
|
|
||||||
if not done:
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
def install_insecure_key():
|
|
||||||
info("Installing insecure SSH key for user root")
|
|
||||||
run_command_killable("/usr/sbin/enable_insecure_key")
|
|
||||||
|
|
||||||
def main(args):
|
|
||||||
import_envvars(False)
|
|
||||||
export_envvars()
|
|
||||||
|
|
||||||
if args.enable_insecure_key:
|
|
||||||
install_insecure_key()
|
|
||||||
|
|
||||||
if not args.skip_startup_files:
|
|
||||||
run_startup_files()
|
|
||||||
|
|
||||||
runit_exited = False
|
|
||||||
exit_code = None
|
|
||||||
|
|
||||||
if not args.skip_runit:
|
|
||||||
runit_pid = start_runit()
|
|
||||||
try:
|
|
||||||
exit_status = None
|
|
||||||
if len(args.main_command) == 0:
|
|
||||||
runit_exited, exit_code = wait_for_runit_or_interrupt(runit_pid)
|
|
||||||
if runit_exited:
|
|
||||||
if exit_code is None:
|
|
||||||
info("Runit exited with unknown status")
|
|
||||||
exit_status = 1
|
|
||||||
else:
|
|
||||||
exit_status = os.WEXITSTATUS(exit_code)
|
|
||||||
info("Runit exited with status %d" % exit_status)
|
|
||||||
else:
|
|
||||||
info("Running %s..." % " ".join(args.main_command))
|
|
||||||
pid = os.spawnvp(os.P_NOWAIT, args.main_command[0], args.main_command)
|
|
||||||
try:
|
|
||||||
exit_code = waitpid_reap_other_children(pid)
|
|
||||||
if exit_code is None:
|
|
||||||
info("%s exited with unknown status." % args.main_command[0])
|
|
||||||
exit_status = 1
|
|
||||||
else:
|
|
||||||
exit_status = os.WEXITSTATUS(exit_code)
|
|
||||||
info("%s exited with status %d." % (args.main_command[0], exit_status))
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
stop_child_process(args.main_command[0], pid)
|
|
||||||
except BaseException as s:
|
|
||||||
warn("An error occurred. Aborting.")
|
|
||||||
stop_child_process(args.main_command[0], pid)
|
|
||||||
raise
|
|
||||||
sys.exit(exit_status)
|
|
||||||
finally:
|
|
||||||
if not args.skip_runit:
|
|
||||||
shutdown_runit_services()
|
|
||||||
if not runit_exited:
|
|
||||||
stop_child_process("runit daemon", runit_pid)
|
|
||||||
wait_for_runit_services()
|
|
||||||
|
|
||||||
# Parse options.
|
|
||||||
parser = argparse.ArgumentParser(description = 'Initialize the system.')
|
|
||||||
parser.add_argument('main_command', metavar = 'MAIN_COMMAND', type = str, nargs = '*',
|
|
||||||
help = 'The main command to run. (default: runit)')
|
|
||||||
parser.add_argument('--enable-insecure-key', dest = 'enable_insecure_key',
|
|
||||||
action = 'store_const', const = True, default = False,
|
|
||||||
help = 'Install the insecure SSH key')
|
|
||||||
parser.add_argument('--skip-startup-files', dest = 'skip_startup_files',
|
|
||||||
action = 'store_const', const = True, default = False,
|
|
||||||
help = 'Skip running /opt/init.d/* and /etc/rc.local')
|
|
||||||
parser.add_argument('--skip-runit', dest = 'skip_runit',
|
|
||||||
action = 'store_const', const = True, default = False,
|
|
||||||
help = 'Do not run runit services')
|
|
||||||
parser.add_argument('--no-kill-all-on-exit', dest = 'kill_all_on_exit',
|
|
||||||
action = 'store_const', const = False, default = True,
|
|
||||||
help = 'Don\'t kill all processes on the system upon exiting')
|
|
||||||
parser.add_argument('--quiet', dest = 'log_level',
|
|
||||||
action = 'store_const', const = LOG_LEVEL_WARN, default = LOG_LEVEL_INFO,
|
|
||||||
help = 'Only print warnings and errors')
|
|
||||||
args = parser.parse_args()
|
|
||||||
log_level = args.log_level
|
|
||||||
|
|
||||||
if args.skip_runit and len(args.main_command) == 0:
|
|
||||||
error("When --skip-runit is given, you must also pass a main command.")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# Run main function.
|
|
||||||
signal.signal(signal.SIGTERM, lambda signum, frame: ignore_signals_and_raise_keyboard_interrupt('SIGTERM'))
|
|
||||||
signal.signal(signal.SIGINT, lambda signum, frame: ignore_signals_and_raise_keyboard_interrupt('SIGINT'))
|
|
||||||
signal.signal(signal.SIGALRM, lambda signum, frame: raise_alarm_exception())
|
|
||||||
try:
|
|
||||||
main(args)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
warn("Init system aborted.")
|
|
||||||
exit(2)
|
|
||||||
finally:
|
|
||||||
if args.kill_all_on_exit:
|
|
||||||
kill_all_processes(KILL_ALL_PROCESSES_TIMEOUT)
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
mkdir -p $BTSYNC_DATA
|
|
||||||
if [ ! -e $BTSYNC_CONFIG ]; then
|
|
||||||
mkdir -p `dirname $BTSYNC_CONFIG`
|
|
||||||
/opt/btsync --dump-sample-config > $BTSYNC_CONFIG
|
|
||||||
sed -i "s,\(\"storage_path\"\s*:\).*,\1 \"$BTSYNC_DATA\"\,," $BTSYNC_CONFIG
|
|
||||||
fi
|
|
||||||
/opt/btsync --nodaemon --config $BTSYNC_CONFIG
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
/usr/sbin/cron -f
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
/usr/sbin/sshd -D
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
|
|
||||||
SYSLOGNG_OPTS=""
|
|
||||||
|
|
||||||
[ -r /etc/default/syslog-ng ] && . /etc/default/syslog-ng
|
|
||||||
|
|
||||||
case "x$CONSOLE_LOG_LEVEL" in
|
|
||||||
x[1-8])
|
|
||||||
dmesg -n $CONSOLE_LOG_LEVEL
|
|
||||||
;;
|
|
||||||
x)
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "CONSOLE_LOG_LEVEL is of unaccepted value."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ ! -e /dev/xconsole ]
|
|
||||||
then
|
|
||||||
mknod -m 640 /dev/xconsole p
|
|
||||||
fi
|
|
||||||
|
|
||||||
syslog-ng -F -p /var/run/syslog-ng.pid $SYSLOGNG_OPTS
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Temporarily disable dpkg fsync to make building faster.
|
|
||||||
echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/02apt-speedup
|
|
||||||
|
|
||||||
## Prevent initramfs updates from trying to run grub and lilo.
|
|
||||||
## https://journal.paul.querna.org/articles/2013/10/15/docker-ubuntu-on-rackspace/
|
|
||||||
## http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=594189
|
|
||||||
export INITRD=no
|
|
||||||
mkdir -p /etc/container_environment
|
|
||||||
echo -n no > /etc/container_environment/INITRD
|
|
||||||
|
|
||||||
## Update package list
|
|
||||||
apt-get update
|
|
||||||
|
|
||||||
## Fix some issues with APT packages
|
|
||||||
## See https://github.com/dotcloud/docker/issues/1024
|
|
||||||
dpkg-divert --local --rename --add /sbin/initctl
|
|
||||||
ln -sf /bin/true /sbin/initctl
|
|
||||||
|
|
||||||
## Replace the 'ischroot' tool to make it always return true
|
|
||||||
## Prevent initscripts updates from breaking /dev/shm
|
|
||||||
## https://journal.paul.querna.org/articles/2013/10/15/docker-ubuntu-on-rackspace/
|
|
||||||
## https://bugs.launchpad.net/launchpad/+bug/974584
|
|
||||||
dpkg-divert --local --rename --add /usr/bin/ischroot
|
|
||||||
ln -sf /bin/true /usr/bin/ischroot
|
|
||||||
|
|
||||||
## Install HTTPS support for APT
|
|
||||||
$minimal_apt_get_install apt-transport-https
|
|
||||||
|
|
||||||
## Upgrade all packages
|
|
||||||
apt-get dist-upgrade -y --no-install-recommends
|
|
||||||
|
|
||||||
## Fix locale
|
|
||||||
$minimal_apt_get_install language-pack-en
|
|
||||||
locale-gen en_US
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Boot entries
|
|
||||||
mkdir /opt/init.d/
|
|
||||||
mv /build/boot/*.sh /opt/init.d/
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install cron daemon
|
|
||||||
$minimal_apt_get_install cron
|
|
||||||
mkdir -p /etc/service/cron
|
|
||||||
mv /build/runit/cron /etc/service/cron/run
|
|
||||||
|
|
||||||
## Remove useless cron entries
|
|
||||||
# Checks for lost+found and scans for mtab
|
|
||||||
rm -f /etc/cron.daily/standard
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install init process
|
|
||||||
mv /build/init /opt/
|
|
||||||
mkdir -p /etc/container_environment
|
|
||||||
touch /etc/container_environment.sh
|
|
||||||
touch /etc/container_environment.json
|
|
||||||
chmod 700 /etc/container_environment
|
|
||||||
chmod 600 /etc/container_environment.sh /etc/container_environment.json
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install logrotate
|
|
||||||
$minimal_apt_get_install logrotate
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install runit
|
|
||||||
$minimal_apt_get_install runit
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install the SSH server
|
|
||||||
$minimal_apt_get_install openssh-server
|
|
||||||
mkdir /var/run/sshd
|
|
||||||
mkdir -p /etc/service/sshd
|
|
||||||
cp /build/runit/sshd /etc/service/sshd/run
|
|
||||||
|
|
||||||
## Install root key
|
|
||||||
cd /opt
|
|
||||||
AUTHORIZED_KEYS=/root/.ssh/authorized_keys
|
|
||||||
DIR=`dirname "$AUTHORIZED_KEYS"`
|
|
||||||
mkdir -p "$DIR"
|
|
||||||
chmod 700 "$DIR"
|
|
||||||
chown root:root "$DIR"
|
|
||||||
pwd
|
|
||||||
ssh-keygen -t rsa -N "" -f id_rsa
|
|
||||||
cat /opt/id_rsa.pub >> "$AUTHORIZED_KEYS"
|
|
||||||
|
|
||||||
## X11 forwarding
|
|
||||||
$minimal_apt_get_install xauth
|
|
||||||
|
|
||||||
## Setup environment
|
|
||||||
sed -i "1iexport HOME=/root" /root/.profile
|
|
||||||
sed -i "1isource /etc/container_environment.sh" /root/.profile
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install a syslog daemon
|
|
||||||
$minimal_apt_get_install syslog-ng-core
|
|
||||||
mkdir /etc/service/syslog-ng
|
|
||||||
mv /build/runit/syslog-ng /etc/service/syslog-ng/run
|
|
||||||
mkdir -p /var/lib/syslog-ng
|
|
||||||
sed -i "s/^\(#SYSLOGNG_OPTS=\).*$/\1\"--no-caps --default-modules=affile,afprog,afsocket,afuser,basicfuncs,csvparser,dbparser,syslogformat\"/" /etc/default/syslog-ng
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Hosts file hack
|
|
||||||
LD_LIBRARY_PATH=/root/lib
|
|
||||||
mkdir -p $LD_LIBRARY_PATH
|
|
||||||
cp /lib/x86_64-linux-gnu/libnss_files.so.2 $LD_LIBRARY_PATH
|
|
||||||
sed -i 's,/etc/hosts,/tmp/hosts,' $LD_LIBRARY_PATH/libnss_files.so.2
|
|
||||||
|
|
||||||
## Environment variable
|
|
||||||
echo -n $LD_LIBRARY_PATH > /etc/container_environment/LD_LIBRARY_PATH
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Often used tools
|
|
||||||
$minimal_apt_get_install wget curl python-pip inetutils-ping telnet sox
|
|
||||||
|
|
||||||
## Often used python modules
|
|
||||||
pip install argparse
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Redis
|
|
||||||
cd opt
|
|
||||||
wget -O btsync.tar.gz http://download-lb.utorrent.com/endpoint/btsync/os/linux-x64/track/stable
|
|
||||||
tar xzf btsync.tar.gz
|
|
||||||
rm btsync.tar.gz
|
|
||||||
|
|
||||||
export BTSYNC_CONFIG=/host/etc/btsync.conf
|
|
||||||
export BTSYNC_DATA=/host/var/btsync
|
|
||||||
|
|
||||||
## Runit script
|
|
||||||
mkdir /etc/service/btsync
|
|
||||||
mv /build/runit/btsync /etc/service/btsync/run
|
|
||||||
|
|
||||||
## Environment variables
|
|
||||||
echo -n $BTSYNC_CONFIG > /etc/container_environment/BTSYNC_CONFIG
|
|
||||||
echo -n $BTSYNC_DATA > /etc/container_environment/BTSYNC_DATA
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
apt-get clean
|
|
||||||
rm -rf /build
|
|
||||||
rm -rf /tmp/* /var/tmp/*
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
rm -f /etc/dpkg/dpkg.cfg.d/02apt-speedup
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
echo "127.0.0.1 localhost" >> /tmp/hosts
|
|
||||||
echo "$HOST_ADDR host" >> /tmp/hosts
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export LC_ALL=C
|
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
|
||||||
minimal_apt_get_install='apt-get install -y --no-install-recommends'
|
|
||||||
@@ -1,314 +0,0 @@
|
|||||||
#!/usr/bin/python2 -u
|
|
||||||
import os, os.path, sys, stat, signal, errno, argparse, time, json, re, posixfile
|
|
||||||
|
|
||||||
KILL_PROCESS_TIMEOUT = 5
|
|
||||||
KILL_ALL_PROCESSES_TIMEOUT = 5
|
|
||||||
|
|
||||||
LOG_LEVEL_ERROR = 1
|
|
||||||
LOG_LEVEL_WARN = 1
|
|
||||||
LOG_LEVEL_INFO = 2
|
|
||||||
LOG_LEVEL_DEBUG = 3
|
|
||||||
|
|
||||||
log_level = None
|
|
||||||
|
|
||||||
class AlarmException(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def error(message):
|
|
||||||
if log_level >= LOG_LEVEL_ERROR:
|
|
||||||
sys.stderr.write("*** %s\n" % message)
|
|
||||||
|
|
||||||
def warn(message):
|
|
||||||
if log_level >= LOG_LEVEL_WARN:
|
|
||||||
print("*** %s" % message)
|
|
||||||
|
|
||||||
def info(message):
|
|
||||||
if log_level >= LOG_LEVEL_INFO:
|
|
||||||
print("*** %s" % message)
|
|
||||||
|
|
||||||
def debug(message):
|
|
||||||
if log_level >= LOG_LEVEL_DEBUG:
|
|
||||||
print("*** %s" % message)
|
|
||||||
|
|
||||||
def ignore_signals_and_raise_keyboard_interrupt(signame):
|
|
||||||
signal.signal(signal.SIGTERM, signal.SIG_IGN)
|
|
||||||
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
|
||||||
raise KeyboardInterrupt(signame)
|
|
||||||
|
|
||||||
def raise_alarm_exception():
|
|
||||||
raise AlarmException('Alarm')
|
|
||||||
|
|
||||||
def listdir(path):
|
|
||||||
try:
|
|
||||||
result = os.stat(path)
|
|
||||||
except OSError:
|
|
||||||
return []
|
|
||||||
if stat.S_ISDIR(result.st_mode):
|
|
||||||
return sorted(os.listdir(path))
|
|
||||||
else:
|
|
||||||
return []
|
|
||||||
|
|
||||||
def is_exe(path):
|
|
||||||
try:
|
|
||||||
return os.path.isfile(path) and os.access(path, os.X_OK)
|
|
||||||
except OSError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def import_envvars(clear_existing_environment = True):
|
|
||||||
new_env = {}
|
|
||||||
for envfile in listdir("/etc/container_environment"):
|
|
||||||
name = os.path.basename(envfile)
|
|
||||||
with open("/etc/container_environment/" + envfile, "r") as f:
|
|
||||||
value = f.read()
|
|
||||||
new_env[name] = value
|
|
||||||
if clear_existing_environment:
|
|
||||||
os.environ.clear()
|
|
||||||
for name, value in new_env.items():
|
|
||||||
os.environ[name] = value
|
|
||||||
|
|
||||||
def export_envvars(to_dir = True):
|
|
||||||
shell_dump = ""
|
|
||||||
for name, value in os.environ.items():
|
|
||||||
if to_dir:
|
|
||||||
with open("/etc/container_environment/" + name, "w") as f:
|
|
||||||
f.write(value)
|
|
||||||
shell_dump += "export " + shquote(name) + "=" + shquote(value) + "\n"
|
|
||||||
with open("/etc/container_environment.sh", "w") as f:
|
|
||||||
f.write(shell_dump)
|
|
||||||
with open("/etc/container_environment.json", "w") as f:
|
|
||||||
f.write(json.dumps(dict(os.environ)))
|
|
||||||
|
|
||||||
_find_unsafe = re.compile(r'[^\w@%+=:,./-]').search
|
|
||||||
|
|
||||||
def shquote(s):
|
|
||||||
"""Return a shell-escaped version of the string *s*."""
|
|
||||||
if not s:
|
|
||||||
return "''"
|
|
||||||
if _find_unsafe(s) is None:
|
|
||||||
return s
|
|
||||||
|
|
||||||
# use single quotes, and put single quotes into double quotes
|
|
||||||
# the string $'b is then quoted as '$'"'"'b'
|
|
||||||
return "'" + s.replace("'", "'\"'\"'") + "'"
|
|
||||||
|
|
||||||
def waitpid_reap_other_children(pid):
|
|
||||||
done = False
|
|
||||||
status = None
|
|
||||||
try:
|
|
||||||
this_pid, status = os.waitpid(pid, os.WNOHANG)
|
|
||||||
except OSError as e:
|
|
||||||
if e.errno == errno.ECHILD or e.errno == errno.ESRCH:
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
while not done:
|
|
||||||
this_pid, status = os.waitpid(-1, 0)
|
|
||||||
done = this_pid == pid
|
|
||||||
return status
|
|
||||||
|
|
||||||
def stop_child_process(name, pid, signo = signal.SIGTERM, time_limit = KILL_PROCESS_TIMEOUT):
|
|
||||||
info("Shutting down %s (PID %d)..." % (name, pid))
|
|
||||||
try:
|
|
||||||
os.kill(pid, signo)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
signal.alarm(time_limit)
|
|
||||||
try:
|
|
||||||
try:
|
|
||||||
waitpid_reap_other_children(pid)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
except AlarmException:
|
|
||||||
warn("%s (PID %d) did not shut down in time. Forcing it to exit." % (name, pid))
|
|
||||||
try:
|
|
||||||
os.kill(pid, signal.SIGKILL)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
waitpid_reap_other_children(pid)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
signal.alarm(0)
|
|
||||||
|
|
||||||
def run_command_killable(*argv):
|
|
||||||
filename = argv[0]
|
|
||||||
status = None
|
|
||||||
pid = os.spawnvp(os.P_NOWAIT, filename, argv)
|
|
||||||
try:
|
|
||||||
status = waitpid_reap_other_children(pid)
|
|
||||||
except BaseException as s:
|
|
||||||
warn("An error occurred. Aborting.")
|
|
||||||
stop_child_process(filename, pid)
|
|
||||||
raise
|
|
||||||
if status != 0:
|
|
||||||
if status is None:
|
|
||||||
error("%s exited with unknown status\n" % filename)
|
|
||||||
else:
|
|
||||||
error("%s failed with status %d\n" % (filename, os.WEXITSTATUS(status)))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
def run_command_killable_and_import_envvars(*argv):
|
|
||||||
run_command_killable(*argv)
|
|
||||||
import_envvars()
|
|
||||||
export_envvars(False)
|
|
||||||
|
|
||||||
def kill_all_processes(time_limit):
|
|
||||||
info("Killing all processes...")
|
|
||||||
try:
|
|
||||||
os.kill(-1, signal.SIGTERM)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
signal.alarm(time_limit)
|
|
||||||
try:
|
|
||||||
# Wait until no more child processes exist.
|
|
||||||
done = False
|
|
||||||
while not done:
|
|
||||||
try:
|
|
||||||
os.waitpid(-1, 0)
|
|
||||||
except OSError as e:
|
|
||||||
if e.errno == errno.ECHILD:
|
|
||||||
done = True
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
except AlarmException:
|
|
||||||
warn("Not all processes have exited in time. Forcing them to exit.")
|
|
||||||
try:
|
|
||||||
os.kill(-1, signal.SIGKILL)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
signal.alarm(0)
|
|
||||||
|
|
||||||
def run_startup_files():
|
|
||||||
# Run /opt/init.d/*
|
|
||||||
for name in listdir("/opt/init.d"):
|
|
||||||
filename = "/opt/init.d/" + name
|
|
||||||
if is_exe(filename):
|
|
||||||
info("Running %s..." % filename)
|
|
||||||
run_command_killable_and_import_envvars(filename)
|
|
||||||
|
|
||||||
# Run /etc/rc.local.
|
|
||||||
if is_exe("/etc/rc.local"):
|
|
||||||
info("Running /etc/rc.local...")
|
|
||||||
run_command_killable_and_import_envvars("/etc/rc.local")
|
|
||||||
|
|
||||||
def start_runit():
|
|
||||||
info("Booting runit daemon...")
|
|
||||||
pid = os.spawnl(os.P_NOWAIT, "/usr/bin/runsvdir", "/usr/bin/runsvdir",
|
|
||||||
"-P", "/etc/service", "log: %s" % ('.' * 395))
|
|
||||||
info("Runit started as PID %d" % pid)
|
|
||||||
return pid
|
|
||||||
|
|
||||||
def wait_for_runit_or_interrupt(pid):
|
|
||||||
try:
|
|
||||||
status = waitpid_reap_other_children(pid)
|
|
||||||
return (True, status)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
return (False, None)
|
|
||||||
|
|
||||||
def shutdown_runit_services():
|
|
||||||
debug("Begin shutting down runit services...")
|
|
||||||
os.system("/usr/bin/sv down /etc/service/*")
|
|
||||||
|
|
||||||
def wait_for_runit_services():
|
|
||||||
debug("Waiting for runit services to exit...")
|
|
||||||
done = False
|
|
||||||
while not done:
|
|
||||||
done = os.system("/usr/bin/sv status /etc/service/* | grep -q '^run:'") != 0
|
|
||||||
if not done:
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
def install_insecure_key():
|
|
||||||
info("Installing insecure SSH key for user root")
|
|
||||||
run_command_killable("/usr/sbin/enable_insecure_key")
|
|
||||||
|
|
||||||
def main(args):
|
|
||||||
import_envvars(False)
|
|
||||||
export_envvars()
|
|
||||||
|
|
||||||
if args.enable_insecure_key:
|
|
||||||
install_insecure_key()
|
|
||||||
|
|
||||||
if not args.skip_startup_files:
|
|
||||||
run_startup_files()
|
|
||||||
|
|
||||||
runit_exited = False
|
|
||||||
exit_code = None
|
|
||||||
|
|
||||||
if not args.skip_runit:
|
|
||||||
runit_pid = start_runit()
|
|
||||||
try:
|
|
||||||
exit_status = None
|
|
||||||
if len(args.main_command) == 0:
|
|
||||||
runit_exited, exit_code = wait_for_runit_or_interrupt(runit_pid)
|
|
||||||
if runit_exited:
|
|
||||||
if exit_code is None:
|
|
||||||
info("Runit exited with unknown status")
|
|
||||||
exit_status = 1
|
|
||||||
else:
|
|
||||||
exit_status = os.WEXITSTATUS(exit_code)
|
|
||||||
info("Runit exited with status %d" % exit_status)
|
|
||||||
else:
|
|
||||||
info("Running %s..." % " ".join(args.main_command))
|
|
||||||
pid = os.spawnvp(os.P_NOWAIT, args.main_command[0], args.main_command)
|
|
||||||
try:
|
|
||||||
exit_code = waitpid_reap_other_children(pid)
|
|
||||||
if exit_code is None:
|
|
||||||
info("%s exited with unknown status." % args.main_command[0])
|
|
||||||
exit_status = 1
|
|
||||||
else:
|
|
||||||
exit_status = os.WEXITSTATUS(exit_code)
|
|
||||||
info("%s exited with status %d." % (args.main_command[0], exit_status))
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
stop_child_process(args.main_command[0], pid)
|
|
||||||
except BaseException as s:
|
|
||||||
warn("An error occurred. Aborting.")
|
|
||||||
stop_child_process(args.main_command[0], pid)
|
|
||||||
raise
|
|
||||||
sys.exit(exit_status)
|
|
||||||
finally:
|
|
||||||
if not args.skip_runit:
|
|
||||||
shutdown_runit_services()
|
|
||||||
if not runit_exited:
|
|
||||||
stop_child_process("runit daemon", runit_pid)
|
|
||||||
wait_for_runit_services()
|
|
||||||
|
|
||||||
# Parse options.
|
|
||||||
parser = argparse.ArgumentParser(description = 'Initialize the system.')
|
|
||||||
parser.add_argument('main_command', metavar = 'MAIN_COMMAND', type = str, nargs = '*',
|
|
||||||
help = 'The main command to run. (default: runit)')
|
|
||||||
parser.add_argument('--enable-insecure-key', dest = 'enable_insecure_key',
|
|
||||||
action = 'store_const', const = True, default = False,
|
|
||||||
help = 'Install the insecure SSH key')
|
|
||||||
parser.add_argument('--skip-startup-files', dest = 'skip_startup_files',
|
|
||||||
action = 'store_const', const = True, default = False,
|
|
||||||
help = 'Skip running /opt/init.d/* and /etc/rc.local')
|
|
||||||
parser.add_argument('--skip-runit', dest = 'skip_runit',
|
|
||||||
action = 'store_const', const = True, default = False,
|
|
||||||
help = 'Do not run runit services')
|
|
||||||
parser.add_argument('--no-kill-all-on-exit', dest = 'kill_all_on_exit',
|
|
||||||
action = 'store_const', const = False, default = True,
|
|
||||||
help = 'Don\'t kill all processes on the system upon exiting')
|
|
||||||
parser.add_argument('--quiet', dest = 'log_level',
|
|
||||||
action = 'store_const', const = LOG_LEVEL_WARN, default = LOG_LEVEL_INFO,
|
|
||||||
help = 'Only print warnings and errors')
|
|
||||||
args = parser.parse_args()
|
|
||||||
log_level = args.log_level
|
|
||||||
|
|
||||||
if args.skip_runit and len(args.main_command) == 0:
|
|
||||||
error("When --skip-runit is given, you must also pass a main command.")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# Run main function.
|
|
||||||
signal.signal(signal.SIGTERM, lambda signum, frame: ignore_signals_and_raise_keyboard_interrupt('SIGTERM'))
|
|
||||||
signal.signal(signal.SIGINT, lambda signum, frame: ignore_signals_and_raise_keyboard_interrupt('SIGINT'))
|
|
||||||
signal.signal(signal.SIGALRM, lambda signum, frame: raise_alarm_exception())
|
|
||||||
try:
|
|
||||||
main(args)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
warn("Init system aborted.")
|
|
||||||
exit(2)
|
|
||||||
finally:
|
|
||||||
if args.kill_all_on_exit:
|
|
||||||
kill_all_processes(KILL_ALL_PROCESSES_TIMEOUT)
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
/usr/sbin/cron -f
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
/usr/sbin/sshd -D
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
|
|
||||||
SYSLOGNG_OPTS=""
|
|
||||||
|
|
||||||
[ -r /etc/default/syslog-ng ] && . /etc/default/syslog-ng
|
|
||||||
|
|
||||||
case "x$CONSOLE_LOG_LEVEL" in
|
|
||||||
x[1-8])
|
|
||||||
dmesg -n $CONSOLE_LOG_LEVEL
|
|
||||||
;;
|
|
||||||
x)
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "CONSOLE_LOG_LEVEL is of unaccepted value."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ ! -e /dev/xconsole ]
|
|
||||||
then
|
|
||||||
mknod -m 640 /dev/xconsole p
|
|
||||||
fi
|
|
||||||
|
|
||||||
syslog-ng -F -p /var/run/syslog-ng.pid $SYSLOGNG_OPTS
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Temporarily disable dpkg fsync to make building faster.
|
|
||||||
echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/02apt-speedup
|
|
||||||
|
|
||||||
## Prevent initramfs updates from trying to run grub and lilo.
|
|
||||||
## https://journal.paul.querna.org/articles/2013/10/15/docker-ubuntu-on-rackspace/
|
|
||||||
## http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=594189
|
|
||||||
export INITRD=no
|
|
||||||
mkdir -p /etc/container_environment
|
|
||||||
echo -n no > /etc/container_environment/INITRD
|
|
||||||
|
|
||||||
## Update package list
|
|
||||||
apt-get update
|
|
||||||
|
|
||||||
## Fix some issues with APT packages
|
|
||||||
## See https://github.com/dotcloud/docker/issues/1024
|
|
||||||
dpkg-divert --local --rename --add /sbin/initctl
|
|
||||||
ln -sf /bin/true /sbin/initctl
|
|
||||||
|
|
||||||
## Replace the 'ischroot' tool to make it always return true
|
|
||||||
## Prevent initscripts updates from breaking /dev/shm
|
|
||||||
## https://journal.paul.querna.org/articles/2013/10/15/docker-ubuntu-on-rackspace/
|
|
||||||
## https://bugs.launchpad.net/launchpad/+bug/974584
|
|
||||||
dpkg-divert --local --rename --add /usr/bin/ischroot
|
|
||||||
ln -sf /bin/true /usr/bin/ischroot
|
|
||||||
|
|
||||||
## Install HTTPS support for APT
|
|
||||||
$minimal_apt_get_install apt-transport-https
|
|
||||||
|
|
||||||
## Upgrade all packages
|
|
||||||
apt-get dist-upgrade -y --no-install-recommends
|
|
||||||
|
|
||||||
## Fix locale
|
|
||||||
$minimal_apt_get_install language-pack-en
|
|
||||||
locale-gen en_US
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Boot entries
|
|
||||||
mkdir /opt/init.d/
|
|
||||||
mv /build/boot/*.sh /opt/init.d/
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install cron daemon
|
|
||||||
$minimal_apt_get_install cron
|
|
||||||
mkdir -p /etc/service/cron
|
|
||||||
mv /build/runit/cron /etc/service/cron/run
|
|
||||||
|
|
||||||
## Remove useless cron entries
|
|
||||||
# Checks for lost+found and scans for mtab
|
|
||||||
rm -f /etc/cron.daily/standard
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install init process
|
|
||||||
mv /build/init /opt/
|
|
||||||
mkdir -p /etc/container_environment
|
|
||||||
touch /etc/container_environment.sh
|
|
||||||
touch /etc/container_environment.json
|
|
||||||
chmod 700 /etc/container_environment
|
|
||||||
chmod 600 /etc/container_environment.sh /etc/container_environment.json
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install logrotate
|
|
||||||
$minimal_apt_get_install logrotate
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install runit
|
|
||||||
$minimal_apt_get_install runit
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install the SSH server
|
|
||||||
$minimal_apt_get_install openssh-server
|
|
||||||
mkdir /var/run/sshd
|
|
||||||
mkdir -p /etc/service/sshd
|
|
||||||
cp /build/runit/sshd /etc/service/sshd/run
|
|
||||||
|
|
||||||
## Install root key
|
|
||||||
cd /opt
|
|
||||||
AUTHORIZED_KEYS=/root/.ssh/authorized_keys
|
|
||||||
DIR=`dirname "$AUTHORIZED_KEYS"`
|
|
||||||
mkdir -p "$DIR"
|
|
||||||
chmod 700 "$DIR"
|
|
||||||
chown root:root "$DIR"
|
|
||||||
pwd
|
|
||||||
ssh-keygen -t rsa -N "" -f id_rsa
|
|
||||||
cat /opt/id_rsa.pub >> "$AUTHORIZED_KEYS"
|
|
||||||
|
|
||||||
## X11 forwarding
|
|
||||||
$minimal_apt_get_install xauth
|
|
||||||
|
|
||||||
## Setup environment
|
|
||||||
sed -i "1iexport HOME=/root" /root/.profile
|
|
||||||
sed -i "1isource /etc/container_environment.sh" /root/.profile
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install a syslog daemon
|
|
||||||
$minimal_apt_get_install syslog-ng-core
|
|
||||||
mkdir /etc/service/syslog-ng
|
|
||||||
mv /build/runit/syslog-ng /etc/service/syslog-ng/run
|
|
||||||
mkdir -p /var/lib/syslog-ng
|
|
||||||
sed -i "s/^\(#SYSLOGNG_OPTS=\).*$/\1\"--no-caps --default-modules=affile,afprog,afsocket,afuser,basicfuncs,csvparser,dbparser,syslogformat\"/" /etc/default/syslog-ng
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Hosts file hack
|
|
||||||
LD_LIBRARY_PATH=/root/lib
|
|
||||||
mkdir -p $LD_LIBRARY_PATH
|
|
||||||
cp /lib/x86_64-linux-gnu/libnss_files.so.2 $LD_LIBRARY_PATH
|
|
||||||
sed -i 's,/etc/hosts,/tmp/hosts,' $LD_LIBRARY_PATH/libnss_files.so.2
|
|
||||||
|
|
||||||
## Environment variable
|
|
||||||
echo -n $LD_LIBRARY_PATH > /etc/container_environment/LD_LIBRARY_PATH
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## User
|
|
||||||
adduser --disabled-password --gecos "" user
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Often used tools
|
|
||||||
$minimal_apt_get_install wget curl python-pip inetutils-ping telnet sox
|
|
||||||
|
|
||||||
## Often used python modules
|
|
||||||
pip install argparse
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Firefox
|
|
||||||
$minimal_apt_get_install firefox
|
|
||||||
|
|
||||||
## Pulseaudio script
|
|
||||||
echo "PULSE_SERVER=host firefox" > /opt/firefox
|
|
||||||
chmod +x /opt/firefox
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Pulseaudio
|
|
||||||
$minimal_apt_get_install pulseaudio
|
|
||||||
|
|
||||||
## Setup environment
|
|
||||||
sed -i "1iexport PULSE_SERVER=host" /root/.profile
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
apt-get clean
|
|
||||||
#rm -rf /build
|
|
||||||
rm -rf /tmp/* /var/tmp/*
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
rm -f /etc/dpkg/dpkg.cfg.d/02apt-speedup
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
echo "127.0.0.1 localhost" >> /tmp/hosts
|
|
||||||
echo "$HOST_ADDR host" >> /tmp/hosts
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
cd /opt
|
|
||||||
dpkg -i hamachi.deb
|
|
||||||
kill -9 `pgrep hamachid`
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export LC_ALL=C
|
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
|
||||||
minimal_apt_get_install='apt-get install -y --no-install-recommends'
|
|
||||||
@@ -1,314 +0,0 @@
|
|||||||
#!/usr/bin/python2 -u
|
|
||||||
import os, os.path, sys, stat, signal, errno, argparse, time, json, re, posixfile
|
|
||||||
|
|
||||||
KILL_PROCESS_TIMEOUT = 5
|
|
||||||
KILL_ALL_PROCESSES_TIMEOUT = 5
|
|
||||||
|
|
||||||
LOG_LEVEL_ERROR = 1
|
|
||||||
LOG_LEVEL_WARN = 1
|
|
||||||
LOG_LEVEL_INFO = 2
|
|
||||||
LOG_LEVEL_DEBUG = 3
|
|
||||||
|
|
||||||
log_level = None
|
|
||||||
|
|
||||||
class AlarmException(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def error(message):
|
|
||||||
if log_level >= LOG_LEVEL_ERROR:
|
|
||||||
sys.stderr.write("*** %s\n" % message)
|
|
||||||
|
|
||||||
def warn(message):
|
|
||||||
if log_level >= LOG_LEVEL_WARN:
|
|
||||||
print("*** %s" % message)
|
|
||||||
|
|
||||||
def info(message):
|
|
||||||
if log_level >= LOG_LEVEL_INFO:
|
|
||||||
print("*** %s" % message)
|
|
||||||
|
|
||||||
def debug(message):
|
|
||||||
if log_level >= LOG_LEVEL_DEBUG:
|
|
||||||
print("*** %s" % message)
|
|
||||||
|
|
||||||
def ignore_signals_and_raise_keyboard_interrupt(signame):
|
|
||||||
signal.signal(signal.SIGTERM, signal.SIG_IGN)
|
|
||||||
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
|
||||||
raise KeyboardInterrupt(signame)
|
|
||||||
|
|
||||||
def raise_alarm_exception():
|
|
||||||
raise AlarmException('Alarm')
|
|
||||||
|
|
||||||
def listdir(path):
|
|
||||||
try:
|
|
||||||
result = os.stat(path)
|
|
||||||
except OSError:
|
|
||||||
return []
|
|
||||||
if stat.S_ISDIR(result.st_mode):
|
|
||||||
return sorted(os.listdir(path))
|
|
||||||
else:
|
|
||||||
return []
|
|
||||||
|
|
||||||
def is_exe(path):
|
|
||||||
try:
|
|
||||||
return os.path.isfile(path) and os.access(path, os.X_OK)
|
|
||||||
except OSError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def import_envvars(clear_existing_environment = True):
|
|
||||||
new_env = {}
|
|
||||||
for envfile in listdir("/etc/container_environment"):
|
|
||||||
name = os.path.basename(envfile)
|
|
||||||
with open("/etc/container_environment/" + envfile, "r") as f:
|
|
||||||
value = f.read()
|
|
||||||
new_env[name] = value
|
|
||||||
if clear_existing_environment:
|
|
||||||
os.environ.clear()
|
|
||||||
for name, value in new_env.items():
|
|
||||||
os.environ[name] = value
|
|
||||||
|
|
||||||
def export_envvars(to_dir = True):
|
|
||||||
shell_dump = ""
|
|
||||||
for name, value in os.environ.items():
|
|
||||||
if to_dir:
|
|
||||||
with open("/etc/container_environment/" + name, "w") as f:
|
|
||||||
f.write(value)
|
|
||||||
shell_dump += "export " + shquote(name) + "=" + shquote(value) + "\n"
|
|
||||||
with open("/etc/container_environment.sh", "w") as f:
|
|
||||||
f.write(shell_dump)
|
|
||||||
with open("/etc/container_environment.json", "w") as f:
|
|
||||||
f.write(json.dumps(dict(os.environ)))
|
|
||||||
|
|
||||||
_find_unsafe = re.compile(r'[^\w@%+=:,./-]').search
|
|
||||||
|
|
||||||
def shquote(s):
|
|
||||||
"""Return a shell-escaped version of the string *s*."""
|
|
||||||
if not s:
|
|
||||||
return "''"
|
|
||||||
if _find_unsafe(s) is None:
|
|
||||||
return s
|
|
||||||
|
|
||||||
# use single quotes, and put single quotes into double quotes
|
|
||||||
# the string $'b is then quoted as '$'"'"'b'
|
|
||||||
return "'" + s.replace("'", "'\"'\"'") + "'"
|
|
||||||
|
|
||||||
def waitpid_reap_other_children(pid):
|
|
||||||
done = False
|
|
||||||
status = None
|
|
||||||
try:
|
|
||||||
this_pid, status = os.waitpid(pid, os.WNOHANG)
|
|
||||||
except OSError as e:
|
|
||||||
if e.errno == errno.ECHILD or e.errno == errno.ESRCH:
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
while not done:
|
|
||||||
this_pid, status = os.waitpid(-1, 0)
|
|
||||||
done = this_pid == pid
|
|
||||||
return status
|
|
||||||
|
|
||||||
def stop_child_process(name, pid, signo = signal.SIGTERM, time_limit = KILL_PROCESS_TIMEOUT):
|
|
||||||
info("Shutting down %s (PID %d)..." % (name, pid))
|
|
||||||
try:
|
|
||||||
os.kill(pid, signo)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
signal.alarm(time_limit)
|
|
||||||
try:
|
|
||||||
try:
|
|
||||||
waitpid_reap_other_children(pid)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
except AlarmException:
|
|
||||||
warn("%s (PID %d) did not shut down in time. Forcing it to exit." % (name, pid))
|
|
||||||
try:
|
|
||||||
os.kill(pid, signal.SIGKILL)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
waitpid_reap_other_children(pid)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
signal.alarm(0)
|
|
||||||
|
|
||||||
def run_command_killable(*argv):
|
|
||||||
filename = argv[0]
|
|
||||||
status = None
|
|
||||||
pid = os.spawnvp(os.P_NOWAIT, filename, argv)
|
|
||||||
try:
|
|
||||||
status = waitpid_reap_other_children(pid)
|
|
||||||
except BaseException as s:
|
|
||||||
warn("An error occurred. Aborting.")
|
|
||||||
stop_child_process(filename, pid)
|
|
||||||
raise
|
|
||||||
if status != 0:
|
|
||||||
if status is None:
|
|
||||||
error("%s exited with unknown status\n" % filename)
|
|
||||||
else:
|
|
||||||
error("%s failed with status %d\n" % (filename, os.WEXITSTATUS(status)))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
def run_command_killable_and_import_envvars(*argv):
|
|
||||||
run_command_killable(*argv)
|
|
||||||
import_envvars()
|
|
||||||
export_envvars(False)
|
|
||||||
|
|
||||||
def kill_all_processes(time_limit):
|
|
||||||
info("Killing all processes...")
|
|
||||||
try:
|
|
||||||
os.kill(-1, signal.SIGTERM)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
signal.alarm(time_limit)
|
|
||||||
try:
|
|
||||||
# Wait until no more child processes exist.
|
|
||||||
done = False
|
|
||||||
while not done:
|
|
||||||
try:
|
|
||||||
os.waitpid(-1, 0)
|
|
||||||
except OSError as e:
|
|
||||||
if e.errno == errno.ECHILD:
|
|
||||||
done = True
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
except AlarmException:
|
|
||||||
warn("Not all processes have exited in time. Forcing them to exit.")
|
|
||||||
try:
|
|
||||||
os.kill(-1, signal.SIGKILL)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
signal.alarm(0)
|
|
||||||
|
|
||||||
def run_startup_files():
|
|
||||||
# Run /opt/init.d/*
|
|
||||||
for name in listdir("/opt/init.d"):
|
|
||||||
filename = "/opt/init.d/" + name
|
|
||||||
if is_exe(filename):
|
|
||||||
info("Running %s..." % filename)
|
|
||||||
run_command_killable_and_import_envvars(filename)
|
|
||||||
|
|
||||||
# Run /etc/rc.local.
|
|
||||||
if is_exe("/etc/rc.local"):
|
|
||||||
info("Running /etc/rc.local...")
|
|
||||||
run_command_killable_and_import_envvars("/etc/rc.local")
|
|
||||||
|
|
||||||
def start_runit():
|
|
||||||
info("Booting runit daemon...")
|
|
||||||
pid = os.spawnl(os.P_NOWAIT, "/usr/bin/runsvdir", "/usr/bin/runsvdir",
|
|
||||||
"-P", "/etc/service", "log: %s" % ('.' * 395))
|
|
||||||
info("Runit started as PID %d" % pid)
|
|
||||||
return pid
|
|
||||||
|
|
||||||
def wait_for_runit_or_interrupt(pid):
|
|
||||||
try:
|
|
||||||
status = waitpid_reap_other_children(pid)
|
|
||||||
return (True, status)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
return (False, None)
|
|
||||||
|
|
||||||
def shutdown_runit_services():
|
|
||||||
debug("Begin shutting down runit services...")
|
|
||||||
os.system("/usr/bin/sv down /etc/service/*")
|
|
||||||
|
|
||||||
def wait_for_runit_services():
|
|
||||||
debug("Waiting for runit services to exit...")
|
|
||||||
done = False
|
|
||||||
while not done:
|
|
||||||
done = os.system("/usr/bin/sv status /etc/service/* | grep -q '^run:'") != 0
|
|
||||||
if not done:
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
def install_insecure_key():
|
|
||||||
info("Installing insecure SSH key for user root")
|
|
||||||
run_command_killable("/usr/sbin/enable_insecure_key")
|
|
||||||
|
|
||||||
def main(args):
|
|
||||||
import_envvars(False)
|
|
||||||
export_envvars()
|
|
||||||
|
|
||||||
if args.enable_insecure_key:
|
|
||||||
install_insecure_key()
|
|
||||||
|
|
||||||
if not args.skip_startup_files:
|
|
||||||
run_startup_files()
|
|
||||||
|
|
||||||
runit_exited = False
|
|
||||||
exit_code = None
|
|
||||||
|
|
||||||
if not args.skip_runit:
|
|
||||||
runit_pid = start_runit()
|
|
||||||
try:
|
|
||||||
exit_status = None
|
|
||||||
if len(args.main_command) == 0:
|
|
||||||
runit_exited, exit_code = wait_for_runit_or_interrupt(runit_pid)
|
|
||||||
if runit_exited:
|
|
||||||
if exit_code is None:
|
|
||||||
info("Runit exited with unknown status")
|
|
||||||
exit_status = 1
|
|
||||||
else:
|
|
||||||
exit_status = os.WEXITSTATUS(exit_code)
|
|
||||||
info("Runit exited with status %d" % exit_status)
|
|
||||||
else:
|
|
||||||
info("Running %s..." % " ".join(args.main_command))
|
|
||||||
pid = os.spawnvp(os.P_NOWAIT, args.main_command[0], args.main_command)
|
|
||||||
try:
|
|
||||||
exit_code = waitpid_reap_other_children(pid)
|
|
||||||
if exit_code is None:
|
|
||||||
info("%s exited with unknown status." % args.main_command[0])
|
|
||||||
exit_status = 1
|
|
||||||
else:
|
|
||||||
exit_status = os.WEXITSTATUS(exit_code)
|
|
||||||
info("%s exited with status %d." % (args.main_command[0], exit_status))
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
stop_child_process(args.main_command[0], pid)
|
|
||||||
except BaseException as s:
|
|
||||||
warn("An error occurred. Aborting.")
|
|
||||||
stop_child_process(args.main_command[0], pid)
|
|
||||||
raise
|
|
||||||
sys.exit(exit_status)
|
|
||||||
finally:
|
|
||||||
if not args.skip_runit:
|
|
||||||
shutdown_runit_services()
|
|
||||||
if not runit_exited:
|
|
||||||
stop_child_process("runit daemon", runit_pid)
|
|
||||||
wait_for_runit_services()
|
|
||||||
|
|
||||||
# Parse options.
|
|
||||||
parser = argparse.ArgumentParser(description = 'Initialize the system.')
|
|
||||||
parser.add_argument('main_command', metavar = 'MAIN_COMMAND', type = str, nargs = '*',
|
|
||||||
help = 'The main command to run. (default: runit)')
|
|
||||||
parser.add_argument('--enable-insecure-key', dest = 'enable_insecure_key',
|
|
||||||
action = 'store_const', const = True, default = False,
|
|
||||||
help = 'Install the insecure SSH key')
|
|
||||||
parser.add_argument('--skip-startup-files', dest = 'skip_startup_files',
|
|
||||||
action = 'store_const', const = True, default = False,
|
|
||||||
help = 'Skip running /opt/init.d/* and /etc/rc.local')
|
|
||||||
parser.add_argument('--skip-runit', dest = 'skip_runit',
|
|
||||||
action = 'store_const', const = True, default = False,
|
|
||||||
help = 'Do not run runit services')
|
|
||||||
parser.add_argument('--no-kill-all-on-exit', dest = 'kill_all_on_exit',
|
|
||||||
action = 'store_const', const = False, default = True,
|
|
||||||
help = 'Don\'t kill all processes on the system upon exiting')
|
|
||||||
parser.add_argument('--quiet', dest = 'log_level',
|
|
||||||
action = 'store_const', const = LOG_LEVEL_WARN, default = LOG_LEVEL_INFO,
|
|
||||||
help = 'Only print warnings and errors')
|
|
||||||
args = parser.parse_args()
|
|
||||||
log_level = args.log_level
|
|
||||||
|
|
||||||
if args.skip_runit and len(args.main_command) == 0:
|
|
||||||
error("When --skip-runit is given, you must also pass a main command.")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# Run main function.
|
|
||||||
signal.signal(signal.SIGTERM, lambda signum, frame: ignore_signals_and_raise_keyboard_interrupt('SIGTERM'))
|
|
||||||
signal.signal(signal.SIGINT, lambda signum, frame: ignore_signals_and_raise_keyboard_interrupt('SIGINT'))
|
|
||||||
signal.signal(signal.SIGALRM, lambda signum, frame: raise_alarm_exception())
|
|
||||||
try:
|
|
||||||
main(args)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
warn("Init system aborted.")
|
|
||||||
exit(2)
|
|
||||||
finally:
|
|
||||||
if args.kill_all_on_exit:
|
|
||||||
kill_all_processes(KILL_ALL_PROCESSES_TIMEOUT)
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
/usr/sbin/cron -f
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
/opt/logmein-hamachi/bin/hamachid -c $HAMACHI_DATA
|
|
||||||
strace -qqe '' -p `pgrep hamachid`
|
|
||||||
/host/bin/proxy
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
/usr/sbin/sshd -D
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
|
|
||||||
SYSLOGNG_OPTS=""
|
|
||||||
|
|
||||||
[ -r /etc/default/syslog-ng ] && . /etc/default/syslog-ng
|
|
||||||
|
|
||||||
case "x$CONSOLE_LOG_LEVEL" in
|
|
||||||
x[1-8])
|
|
||||||
dmesg -n $CONSOLE_LOG_LEVEL
|
|
||||||
;;
|
|
||||||
x)
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "CONSOLE_LOG_LEVEL is of unaccepted value."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ ! -e /dev/xconsole ]
|
|
||||||
then
|
|
||||||
mknod -m 640 /dev/xconsole p
|
|
||||||
fi
|
|
||||||
|
|
||||||
syslog-ng -F -p /var/run/syslog-ng.pid $SYSLOGNG_OPTS
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Temporarily disable dpkg fsync to make building faster.
|
|
||||||
echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/02apt-speedup
|
|
||||||
|
|
||||||
## Prevent initramfs updates from trying to run grub and lilo.
|
|
||||||
## https://journal.paul.querna.org/articles/2013/10/15/docker-ubuntu-on-rackspace/
|
|
||||||
## http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=594189
|
|
||||||
export INITRD=no
|
|
||||||
mkdir -p /etc/container_environment
|
|
||||||
echo -n no > /etc/container_environment/INITRD
|
|
||||||
|
|
||||||
## Update package list
|
|
||||||
apt-get update
|
|
||||||
|
|
||||||
## Fix some issues with APT packages
|
|
||||||
## See https://github.com/dotcloud/docker/issues/1024
|
|
||||||
dpkg-divert --local --rename --add /sbin/initctl
|
|
||||||
ln -sf /bin/true /sbin/initctl
|
|
||||||
|
|
||||||
## Replace the 'ischroot' tool to make it always return true
|
|
||||||
## Prevent initscripts updates from breaking /dev/shm
|
|
||||||
## https://journal.paul.querna.org/articles/2013/10/15/docker-ubuntu-on-rackspace/
|
|
||||||
## https://bugs.launchpad.net/launchpad/+bug/974584
|
|
||||||
dpkg-divert --local --rename --add /usr/bin/ischroot
|
|
||||||
ln -sf /bin/true /usr/bin/ischroot
|
|
||||||
|
|
||||||
## Install HTTPS support for APT
|
|
||||||
$minimal_apt_get_install apt-transport-https
|
|
||||||
|
|
||||||
## Upgrade all packages
|
|
||||||
apt-get dist-upgrade -y --no-install-recommends
|
|
||||||
|
|
||||||
## Fix locale
|
|
||||||
$minimal_apt_get_install language-pack-en
|
|
||||||
locale-gen en_US
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Boot entries
|
|
||||||
mkdir /opt/init.d/
|
|
||||||
mv /build/boot/*.sh /opt/init.d/
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install cron daemon
|
|
||||||
$minimal_apt_get_install cron
|
|
||||||
mkdir -p /etc/service/cron
|
|
||||||
mv /build/runit/cron /etc/service/cron/run
|
|
||||||
|
|
||||||
## Remove useless cron entries
|
|
||||||
# Checks for lost+found and scans for mtab
|
|
||||||
rm -f /etc/cron.daily/standard
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install init process
|
|
||||||
mv /build/init /opt/
|
|
||||||
mkdir -p /etc/container_environment
|
|
||||||
touch /etc/container_environment.sh
|
|
||||||
touch /etc/container_environment.json
|
|
||||||
chmod 700 /etc/container_environment
|
|
||||||
chmod 600 /etc/container_environment.sh /etc/container_environment.json
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install logrotate
|
|
||||||
$minimal_apt_get_install logrotate
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install runit
|
|
||||||
$minimal_apt_get_install runit
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install the SSH server
|
|
||||||
$minimal_apt_get_install openssh-server
|
|
||||||
mkdir /var/run/sshd
|
|
||||||
mkdir -p /etc/service/sshd
|
|
||||||
cp /build/runit/sshd /etc/service/sshd/run
|
|
||||||
|
|
||||||
## Install root key
|
|
||||||
cd /opt
|
|
||||||
AUTHORIZED_KEYS=/root/.ssh/authorized_keys
|
|
||||||
DIR=`dirname "$AUTHORIZED_KEYS"`
|
|
||||||
mkdir -p "$DIR"
|
|
||||||
chmod 700 "$DIR"
|
|
||||||
chown root:root "$DIR"
|
|
||||||
pwd
|
|
||||||
ssh-keygen -t rsa -N "" -f id_rsa
|
|
||||||
cat /opt/id_rsa.pub >> "$AUTHORIZED_KEYS"
|
|
||||||
|
|
||||||
## X11 forwarding
|
|
||||||
$minimal_apt_get_install xauth
|
|
||||||
|
|
||||||
## Setup environment
|
|
||||||
sed -i "1iexport HOME=/root" /root/.profile
|
|
||||||
sed -i "1isource /etc/container_environment.sh" /root/.profile
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install a syslog daemon
|
|
||||||
$minimal_apt_get_install syslog-ng-core
|
|
||||||
mkdir /etc/service/syslog-ng
|
|
||||||
mv /build/runit/syslog-ng /etc/service/syslog-ng/run
|
|
||||||
mkdir -p /var/lib/syslog-ng
|
|
||||||
sed -i "s/^\(#SYSLOGNG_OPTS=\).*$/\1\"--no-caps --default-modules=affile,afprog,afsocket,afuser,basicfuncs,csvparser,dbparser,syslogformat\"/" /etc/default/syslog-ng
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Hosts file hack
|
|
||||||
LD_LIBRARY_PATH=/root/lib
|
|
||||||
mkdir -p $LD_LIBRARY_PATH
|
|
||||||
cp /lib/x86_64-linux-gnu/libnss_files.so.2 $LD_LIBRARY_PATH
|
|
||||||
sed -i 's,/etc/hosts,/tmp/hosts,' $LD_LIBRARY_PATH/libnss_files.so.2
|
|
||||||
|
|
||||||
## Environment variable
|
|
||||||
echo -n $LD_LIBRARY_PATH > /etc/container_environment/LD_LIBRARY_PATH
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Often used tools
|
|
||||||
$minimal_apt_get_install wget curl python-pip inetutils-ping telnet sox
|
|
||||||
|
|
||||||
## Often used python modules
|
|
||||||
pip install argparse
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Hamachi dependency
|
|
||||||
$minimal_apt_get_install lsb-core net-tools socat strace
|
|
||||||
|
|
||||||
## Hamachi
|
|
||||||
cd /opt
|
|
||||||
export HAMACHI_DATA=/host/var/lib/logmein-hamachi
|
|
||||||
export HAMACHI_VERSION=2.1.0.119
|
|
||||||
wget -O hamachi.deb https://secure.logmein.com/labs/logmein-hamachi_$HAMACHI_VERSION-1_amd64.deb
|
|
||||||
mkdir -p /etc/service/hamachi
|
|
||||||
cp /build/runit/hamachi /etc/service/hamachi/run
|
|
||||||
|
|
||||||
## Environment variables
|
|
||||||
echo -n $HAMACHI_DATA > /etc/container_environment/HAMACHI_DATA
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
apt-get clean
|
|
||||||
rm -rf /build
|
|
||||||
rm -rf /tmp/* /var/tmp/*
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
rm -f /etc/dpkg/dpkg.cfg.d/02apt-speedup
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
echo "127.0.0.1 localhost" >> /tmp/hosts
|
|
||||||
echo "$HOST_ADDR host" >> /tmp/hosts
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
export LC_ALL=C
|
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
|
||||||
minimal_apt_get_install='apt-get install -y --no-install-recommends'
|
|
||||||
@@ -1,314 +0,0 @@
|
|||||||
#!/usr/bin/python2 -u
|
|
||||||
import os, os.path, sys, stat, signal, errno, argparse, time, json, re, posixfile
|
|
||||||
|
|
||||||
KILL_PROCESS_TIMEOUT = 5
|
|
||||||
KILL_ALL_PROCESSES_TIMEOUT = 5
|
|
||||||
|
|
||||||
LOG_LEVEL_ERROR = 1
|
|
||||||
LOG_LEVEL_WARN = 1
|
|
||||||
LOG_LEVEL_INFO = 2
|
|
||||||
LOG_LEVEL_DEBUG = 3
|
|
||||||
|
|
||||||
log_level = None
|
|
||||||
|
|
||||||
class AlarmException(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def error(message):
|
|
||||||
if log_level >= LOG_LEVEL_ERROR:
|
|
||||||
sys.stderr.write("*** %s\n" % message)
|
|
||||||
|
|
||||||
def warn(message):
|
|
||||||
if log_level >= LOG_LEVEL_WARN:
|
|
||||||
print("*** %s" % message)
|
|
||||||
|
|
||||||
def info(message):
|
|
||||||
if log_level >= LOG_LEVEL_INFO:
|
|
||||||
print("*** %s" % message)
|
|
||||||
|
|
||||||
def debug(message):
|
|
||||||
if log_level >= LOG_LEVEL_DEBUG:
|
|
||||||
print("*** %s" % message)
|
|
||||||
|
|
||||||
def ignore_signals_and_raise_keyboard_interrupt(signame):
|
|
||||||
signal.signal(signal.SIGTERM, signal.SIG_IGN)
|
|
||||||
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
|
||||||
raise KeyboardInterrupt(signame)
|
|
||||||
|
|
||||||
def raise_alarm_exception():
|
|
||||||
raise AlarmException('Alarm')
|
|
||||||
|
|
||||||
def listdir(path):
|
|
||||||
try:
|
|
||||||
result = os.stat(path)
|
|
||||||
except OSError:
|
|
||||||
return []
|
|
||||||
if stat.S_ISDIR(result.st_mode):
|
|
||||||
return sorted(os.listdir(path))
|
|
||||||
else:
|
|
||||||
return []
|
|
||||||
|
|
||||||
def is_exe(path):
|
|
||||||
try:
|
|
||||||
return os.path.isfile(path) and os.access(path, os.X_OK)
|
|
||||||
except OSError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def import_envvars(clear_existing_environment = True):
|
|
||||||
new_env = {}
|
|
||||||
for envfile in listdir("/etc/container_environment"):
|
|
||||||
name = os.path.basename(envfile)
|
|
||||||
with open("/etc/container_environment/" + envfile, "r") as f:
|
|
||||||
value = f.read()
|
|
||||||
new_env[name] = value
|
|
||||||
if clear_existing_environment:
|
|
||||||
os.environ.clear()
|
|
||||||
for name, value in new_env.items():
|
|
||||||
os.environ[name] = value
|
|
||||||
|
|
||||||
def export_envvars(to_dir = True):
|
|
||||||
shell_dump = ""
|
|
||||||
for name, value in os.environ.items():
|
|
||||||
if to_dir:
|
|
||||||
with open("/etc/container_environment/" + name, "w") as f:
|
|
||||||
f.write(value)
|
|
||||||
shell_dump += "export " + shquote(name) + "=" + shquote(value) + "\n"
|
|
||||||
with open("/etc/container_environment.sh", "w") as f:
|
|
||||||
f.write(shell_dump)
|
|
||||||
with open("/etc/container_environment.json", "w") as f:
|
|
||||||
f.write(json.dumps(dict(os.environ)))
|
|
||||||
|
|
||||||
_find_unsafe = re.compile(r'[^\w@%+=:,./-]').search
|
|
||||||
|
|
||||||
def shquote(s):
|
|
||||||
"""Return a shell-escaped version of the string *s*."""
|
|
||||||
if not s:
|
|
||||||
return "''"
|
|
||||||
if _find_unsafe(s) is None:
|
|
||||||
return s
|
|
||||||
|
|
||||||
# use single quotes, and put single quotes into double quotes
|
|
||||||
# the string $'b is then quoted as '$'"'"'b'
|
|
||||||
return "'" + s.replace("'", "'\"'\"'") + "'"
|
|
||||||
|
|
||||||
def waitpid_reap_other_children(pid):
|
|
||||||
done = False
|
|
||||||
status = None
|
|
||||||
try:
|
|
||||||
this_pid, status = os.waitpid(pid, os.WNOHANG)
|
|
||||||
except OSError as e:
|
|
||||||
if e.errno == errno.ECHILD or e.errno == errno.ESRCH:
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
while not done:
|
|
||||||
this_pid, status = os.waitpid(-1, 0)
|
|
||||||
done = this_pid == pid
|
|
||||||
return status
|
|
||||||
|
|
||||||
def stop_child_process(name, pid, signo = signal.SIGTERM, time_limit = KILL_PROCESS_TIMEOUT):
|
|
||||||
info("Shutting down %s (PID %d)..." % (name, pid))
|
|
||||||
try:
|
|
||||||
os.kill(pid, signo)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
signal.alarm(time_limit)
|
|
||||||
try:
|
|
||||||
try:
|
|
||||||
waitpid_reap_other_children(pid)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
except AlarmException:
|
|
||||||
warn("%s (PID %d) did not shut down in time. Forcing it to exit." % (name, pid))
|
|
||||||
try:
|
|
||||||
os.kill(pid, signal.SIGKILL)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
waitpid_reap_other_children(pid)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
signal.alarm(0)
|
|
||||||
|
|
||||||
def run_command_killable(*argv):
|
|
||||||
filename = argv[0]
|
|
||||||
status = None
|
|
||||||
pid = os.spawnvp(os.P_NOWAIT, filename, argv)
|
|
||||||
try:
|
|
||||||
status = waitpid_reap_other_children(pid)
|
|
||||||
except BaseException as s:
|
|
||||||
warn("An error occurred. Aborting.")
|
|
||||||
stop_child_process(filename, pid)
|
|
||||||
raise
|
|
||||||
if status != 0:
|
|
||||||
if status is None:
|
|
||||||
error("%s exited with unknown status\n" % filename)
|
|
||||||
else:
|
|
||||||
error("%s failed with status %d\n" % (filename, os.WEXITSTATUS(status)))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
def run_command_killable_and_import_envvars(*argv):
|
|
||||||
run_command_killable(*argv)
|
|
||||||
import_envvars()
|
|
||||||
export_envvars(False)
|
|
||||||
|
|
||||||
def kill_all_processes(time_limit):
|
|
||||||
info("Killing all processes...")
|
|
||||||
try:
|
|
||||||
os.kill(-1, signal.SIGTERM)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
signal.alarm(time_limit)
|
|
||||||
try:
|
|
||||||
# Wait until no more child processes exist.
|
|
||||||
done = False
|
|
||||||
while not done:
|
|
||||||
try:
|
|
||||||
os.waitpid(-1, 0)
|
|
||||||
except OSError as e:
|
|
||||||
if e.errno == errno.ECHILD:
|
|
||||||
done = True
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
except AlarmException:
|
|
||||||
warn("Not all processes have exited in time. Forcing them to exit.")
|
|
||||||
try:
|
|
||||||
os.kill(-1, signal.SIGKILL)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
signal.alarm(0)
|
|
||||||
|
|
||||||
def run_startup_files():
|
|
||||||
# Run /opt/init.d/*
|
|
||||||
for name in listdir("/opt/init.d"):
|
|
||||||
filename = "/opt/init.d/" + name
|
|
||||||
if is_exe(filename):
|
|
||||||
info("Running %s..." % filename)
|
|
||||||
run_command_killable_and_import_envvars(filename)
|
|
||||||
|
|
||||||
# Run /etc/rc.local.
|
|
||||||
if is_exe("/etc/rc.local"):
|
|
||||||
info("Running /etc/rc.local...")
|
|
||||||
run_command_killable_and_import_envvars("/etc/rc.local")
|
|
||||||
|
|
||||||
def start_runit():
|
|
||||||
info("Booting runit daemon...")
|
|
||||||
pid = os.spawnl(os.P_NOWAIT, "/usr/bin/runsvdir", "/usr/bin/runsvdir",
|
|
||||||
"-P", "/etc/service", "log: %s" % ('.' * 395))
|
|
||||||
info("Runit started as PID %d" % pid)
|
|
||||||
return pid
|
|
||||||
|
|
||||||
def wait_for_runit_or_interrupt(pid):
|
|
||||||
try:
|
|
||||||
status = waitpid_reap_other_children(pid)
|
|
||||||
return (True, status)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
return (False, None)
|
|
||||||
|
|
||||||
def shutdown_runit_services():
|
|
||||||
debug("Begin shutting down runit services...")
|
|
||||||
os.system("/usr/bin/sv down /etc/service/*")
|
|
||||||
|
|
||||||
def wait_for_runit_services():
|
|
||||||
debug("Waiting for runit services to exit...")
|
|
||||||
done = False
|
|
||||||
while not done:
|
|
||||||
done = os.system("/usr/bin/sv status /etc/service/* | grep -q '^run:'") != 0
|
|
||||||
if not done:
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
def install_insecure_key():
|
|
||||||
info("Installing insecure SSH key for user root")
|
|
||||||
run_command_killable("/usr/sbin/enable_insecure_key")
|
|
||||||
|
|
||||||
def main(args):
|
|
||||||
import_envvars(False)
|
|
||||||
export_envvars()
|
|
||||||
|
|
||||||
if args.enable_insecure_key:
|
|
||||||
install_insecure_key()
|
|
||||||
|
|
||||||
if not args.skip_startup_files:
|
|
||||||
run_startup_files()
|
|
||||||
|
|
||||||
runit_exited = False
|
|
||||||
exit_code = None
|
|
||||||
|
|
||||||
if not args.skip_runit:
|
|
||||||
runit_pid = start_runit()
|
|
||||||
try:
|
|
||||||
exit_status = None
|
|
||||||
if len(args.main_command) == 0:
|
|
||||||
runit_exited, exit_code = wait_for_runit_or_interrupt(runit_pid)
|
|
||||||
if runit_exited:
|
|
||||||
if exit_code is None:
|
|
||||||
info("Runit exited with unknown status")
|
|
||||||
exit_status = 1
|
|
||||||
else:
|
|
||||||
exit_status = os.WEXITSTATUS(exit_code)
|
|
||||||
info("Runit exited with status %d" % exit_status)
|
|
||||||
else:
|
|
||||||
info("Running %s..." % " ".join(args.main_command))
|
|
||||||
pid = os.spawnvp(os.P_NOWAIT, args.main_command[0], args.main_command)
|
|
||||||
try:
|
|
||||||
exit_code = waitpid_reap_other_children(pid)
|
|
||||||
if exit_code is None:
|
|
||||||
info("%s exited with unknown status." % args.main_command[0])
|
|
||||||
exit_status = 1
|
|
||||||
else:
|
|
||||||
exit_status = os.WEXITSTATUS(exit_code)
|
|
||||||
info("%s exited with status %d." % (args.main_command[0], exit_status))
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
stop_child_process(args.main_command[0], pid)
|
|
||||||
except BaseException as s:
|
|
||||||
warn("An error occurred. Aborting.")
|
|
||||||
stop_child_process(args.main_command[0], pid)
|
|
||||||
raise
|
|
||||||
sys.exit(exit_status)
|
|
||||||
finally:
|
|
||||||
if not args.skip_runit:
|
|
||||||
shutdown_runit_services()
|
|
||||||
if not runit_exited:
|
|
||||||
stop_child_process("runit daemon", runit_pid)
|
|
||||||
wait_for_runit_services()
|
|
||||||
|
|
||||||
# Parse options.
|
|
||||||
parser = argparse.ArgumentParser(description = 'Initialize the system.')
|
|
||||||
parser.add_argument('main_command', metavar = 'MAIN_COMMAND', type = str, nargs = '*',
|
|
||||||
help = 'The main command to run. (default: runit)')
|
|
||||||
parser.add_argument('--enable-insecure-key', dest = 'enable_insecure_key',
|
|
||||||
action = 'store_const', const = True, default = False,
|
|
||||||
help = 'Install the insecure SSH key')
|
|
||||||
parser.add_argument('--skip-startup-files', dest = 'skip_startup_files',
|
|
||||||
action = 'store_const', const = True, default = False,
|
|
||||||
help = 'Skip running /opt/init.d/* and /etc/rc.local')
|
|
||||||
parser.add_argument('--skip-runit', dest = 'skip_runit',
|
|
||||||
action = 'store_const', const = True, default = False,
|
|
||||||
help = 'Do not run runit services')
|
|
||||||
parser.add_argument('--no-kill-all-on-exit', dest = 'kill_all_on_exit',
|
|
||||||
action = 'store_const', const = False, default = True,
|
|
||||||
help = 'Don\'t kill all processes on the system upon exiting')
|
|
||||||
parser.add_argument('--quiet', dest = 'log_level',
|
|
||||||
action = 'store_const', const = LOG_LEVEL_WARN, default = LOG_LEVEL_INFO,
|
|
||||||
help = 'Only print warnings and errors')
|
|
||||||
args = parser.parse_args()
|
|
||||||
log_level = args.log_level
|
|
||||||
|
|
||||||
if args.skip_runit and len(args.main_command) == 0:
|
|
||||||
error("When --skip-runit is given, you must also pass a main command.")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# Run main function.
|
|
||||||
signal.signal(signal.SIGTERM, lambda signum, frame: ignore_signals_and_raise_keyboard_interrupt('SIGTERM'))
|
|
||||||
signal.signal(signal.SIGINT, lambda signum, frame: ignore_signals_and_raise_keyboard_interrupt('SIGINT'))
|
|
||||||
signal.signal(signal.SIGALRM, lambda signum, frame: raise_alarm_exception())
|
|
||||||
try:
|
|
||||||
main(args)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
warn("Init system aborted.")
|
|
||||||
exit(2)
|
|
||||||
finally:
|
|
||||||
if args.kill_all_on_exit:
|
|
||||||
kill_all_processes(KILL_ALL_PROCESSES_TIMEOUT)
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
/usr/sbin/cron -f
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
#mpd
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
/usr/sbin/sshd -D
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
|
|
||||||
SYSLOGNG_OPTS=""
|
|
||||||
|
|
||||||
[ -r /etc/default/syslog-ng ] && . /etc/default/syslog-ng
|
|
||||||
|
|
||||||
case "x$CONSOLE_LOG_LEVEL" in
|
|
||||||
x[1-8])
|
|
||||||
dmesg -n $CONSOLE_LOG_LEVEL
|
|
||||||
;;
|
|
||||||
x)
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "CONSOLE_LOG_LEVEL is of unaccepted value."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ ! -e /dev/xconsole ]
|
|
||||||
then
|
|
||||||
mknod -m 640 /dev/xconsole p
|
|
||||||
fi
|
|
||||||
|
|
||||||
syslog-ng -F -p /var/run/syslog-ng.pid $SYSLOGNG_OPTS
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Temporarily disable dpkg fsync to make building faster.
|
|
||||||
echo force-unsafe-io > /etc/dpkg/dpkg.cfg.d/02apt-speedup
|
|
||||||
|
|
||||||
## Prevent initramfs updates from trying to run grub and lilo.
|
|
||||||
## https://journal.paul.querna.org/articles/2013/10/15/docker-ubuntu-on-rackspace/
|
|
||||||
## http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=594189
|
|
||||||
export INITRD=no
|
|
||||||
mkdir -p /etc/container_environment
|
|
||||||
echo -n no > /etc/container_environment/INITRD
|
|
||||||
|
|
||||||
## Update package list
|
|
||||||
apt-get update
|
|
||||||
|
|
||||||
## Fix some issues with APT packages
|
|
||||||
## See https://github.com/dotcloud/docker/issues/1024
|
|
||||||
dpkg-divert --local --rename --add /sbin/initctl
|
|
||||||
ln -sf /bin/true /sbin/initctl
|
|
||||||
|
|
||||||
## Replace the 'ischroot' tool to make it always return true
|
|
||||||
## Prevent initscripts updates from breaking /dev/shm
|
|
||||||
## https://journal.paul.querna.org/articles/2013/10/15/docker-ubuntu-on-rackspace/
|
|
||||||
## https://bugs.launchpad.net/launchpad/+bug/974584
|
|
||||||
dpkg-divert --local --rename --add /usr/bin/ischroot
|
|
||||||
ln -sf /bin/true /usr/bin/ischroot
|
|
||||||
|
|
||||||
## Install HTTPS support for APT
|
|
||||||
$minimal_apt_get_install apt-transport-https
|
|
||||||
|
|
||||||
## Upgrade all packages
|
|
||||||
apt-get dist-upgrade -y --no-install-recommends
|
|
||||||
|
|
||||||
## Fix locale
|
|
||||||
$minimal_apt_get_install language-pack-en
|
|
||||||
locale-gen en_US
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Boot entries
|
|
||||||
mkdir /opt/init.d/
|
|
||||||
mv /build/boot/*.sh /opt/init.d/
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install cron daemon
|
|
||||||
$minimal_apt_get_install cron
|
|
||||||
mkdir -p /etc/service/cron
|
|
||||||
mv /build/runit/cron /etc/service/cron/run
|
|
||||||
|
|
||||||
## Remove useless cron entries
|
|
||||||
# Checks for lost+found and scans for mtab
|
|
||||||
rm -f /etc/cron.daily/standard
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install init process
|
|
||||||
mv /build/init /opt/
|
|
||||||
mkdir -p /etc/container_environment
|
|
||||||
touch /etc/container_environment.sh
|
|
||||||
touch /etc/container_environment.json
|
|
||||||
chmod 700 /etc/container_environment
|
|
||||||
chmod 600 /etc/container_environment.sh /etc/container_environment.json
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install logrotate
|
|
||||||
$minimal_apt_get_install logrotate
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install runit
|
|
||||||
$minimal_apt_get_install runit
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install the SSH server
|
|
||||||
$minimal_apt_get_install openssh-server
|
|
||||||
mkdir /var/run/sshd
|
|
||||||
mkdir -p /etc/service/sshd
|
|
||||||
cp /build/runit/sshd /etc/service/sshd/run
|
|
||||||
|
|
||||||
## Install root key
|
|
||||||
cd /opt
|
|
||||||
AUTHORIZED_KEYS=/root/.ssh/authorized_keys
|
|
||||||
DIR=`dirname "$AUTHORIZED_KEYS"`
|
|
||||||
mkdir -p "$DIR"
|
|
||||||
chmod 700 "$DIR"
|
|
||||||
chown root:root "$DIR"
|
|
||||||
pwd
|
|
||||||
ssh-keygen -t rsa -N "" -f id_rsa
|
|
||||||
cat /opt/id_rsa.pub >> "$AUTHORIZED_KEYS"
|
|
||||||
|
|
||||||
## X11 forwarding
|
|
||||||
$minimal_apt_get_install xauth
|
|
||||||
|
|
||||||
## Setup environment
|
|
||||||
sed -i "1iexport HOME=/root" /root/.profile
|
|
||||||
sed -i "1isource /etc/container_environment.sh" /root/.profile
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Install a syslog daemon
|
|
||||||
$minimal_apt_get_install syslog-ng-core
|
|
||||||
mkdir /etc/service/syslog-ng
|
|
||||||
mv /build/runit/syslog-ng /etc/service/syslog-ng/run
|
|
||||||
mkdir -p /var/lib/syslog-ng
|
|
||||||
sed -i "s/^\(#SYSLOGNG_OPTS=\).*$/\1\"--no-caps --default-modules=affile,afprog,afsocket,afuser,basicfuncs,csvparser,dbparser,syslogformat\"/" /etc/default/syslog-ng
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Hosts file hack
|
|
||||||
LD_LIBRARY_PATH=/root/lib
|
|
||||||
mkdir -p $LD_LIBRARY_PATH
|
|
||||||
cp /lib/x86_64-linux-gnu/libnss_files.so.2 $LD_LIBRARY_PATH
|
|
||||||
sed -i 's,/etc/hosts,/tmp/hosts,' $LD_LIBRARY_PATH/libnss_files.so.2
|
|
||||||
|
|
||||||
## Environment variable
|
|
||||||
echo -n $LD_LIBRARY_PATH > /etc/container_environment/LD_LIBRARY_PATH
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Often used tools
|
|
||||||
$minimal_apt_get_install wget curl python-pip inetutils-ping telnet sox
|
|
||||||
|
|
||||||
## Often used python modules
|
|
||||||
pip install argparse
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Mpd
|
|
||||||
$minimal_apt_get_install mpd
|
|
||||||
mkdir -p /etc/service/mpd
|
|
||||||
cp /build/runit/mpd /etc/service/mpd/run
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
## Pulseaudio
|
|
||||||
$minimal_apt_get_install pulseaudio
|
|
||||||
|
|
||||||
## Setup environment
|
|
||||||
sed -i "1iexport PULSE_SERVER=host" /root/.profile
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
source /build/config
|
|
||||||
set -x
|
|
||||||
|
|
||||||
apt-get clean
|
|
||||||
#rm -rf /build
|
|
||||||
rm -rf /tmp/* /var/tmp/*
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
rm -f /etc/dpkg/dpkg.cfg.d/02apt-speedup
|
|
||||||
Reference in New Issue
Block a user