diff --git a/.jshintrc b/.jshintrc index ad6d169fb..30d7ea440 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,7 +1,8 @@ { - "node": true, - "browser": true, - "unused": true, - "globalstrict": true, - "predef": [ "angular", "$" ] + "node": true, + "browser": true, + "unused": true, + "globalstrict": true, + "predef": [ "angular", "$" ], + "esnext": true } diff --git a/setup/container/sudoers b/setup/container/sudoers index e1d76bf26..cb0a20e2c 100644 --- a/setup/container/sudoers +++ b/setup/container/sudoers @@ -31,6 +31,3 @@ yellowtent ALL=(root) NOPASSWD: /home/yellowtent/box/src/scripts/collectlogs.sh Defaults!/home/yellowtent/box/src/scripts/retire.sh env_keep="HOME BOX_ENV" yellowtent ALL=(root) NOPASSWD: /home/yellowtent/box/src/scripts/retire.sh -Defaults!/home/yellowtent/box/src/scripts/setup_infra.sh env_keep="HOME BOX_ENV" -yellowtent ALL=(root) NOPASSWD: /home/yellowtent/box/src/scripts/setup_infra.sh - diff --git a/src/platform.js b/src/platform.js index f7984406a..d4986ed99 100644 --- a/src/platform.js +++ b/src/platform.js @@ -13,17 +13,15 @@ var apps = require('./apps.js'), certificates = require('./certificates.js'), debug = require('debug')('box:platform'), fs = require('fs'), + hat = require('hat'), infra = require('./infra_version.js'), ini = require('ini'), mailboxes = require('./mailboxes.js'), - path = require('path'), paths = require('./paths.js'), safe = require('safetydance'), shell = require('./shell.js'), util = require('util'); -var SETUP_INFRA_CMD = path.join(__dirname, 'scripts/setup_infra.sh'); - var gAddonVars = null; function initialize(callback) { @@ -75,18 +73,142 @@ function stopContainers(callback) { callback(); } -function startAddons(callback) { - assert.strictEqual(typeof callback, 'function'); +function startGraphite(callback) { + const tag = infra.images.graphite.tag; + const dataDir = paths.DATA_DIR; + + const cmd = `docker run --restart=always -d --name="graphite" \ + -m 75m \ + --memory-swap 150m \ + -p 127.0.0.1:2003:2003 \ + -p 127.0.0.1:2004:2004 \ + -p 127.0.0.1:8000:8000 \ + -v "${dataDir}/graphite:/app/data" \ + --read-only -v /tmp -v /run "${tag}"`; + + shell.execSync('startGraphite', cmd); + + callback(); +} + +function startMysql(callback) { + const tag = infra.images.mysql.tag; + const dataDir = paths.DATA_DIR; + const rootPassword = hat(256); + + if (!safe.fs.writeFileSync(paths.DATA_DIR + '/addons/mysql_vars.sh', + 'MYSQL_ROOT_PASSWORD=' + rootPassword +'\nMYSQL_ROOT_HOST=172.17.0.1', 'utf8')) { + return callback(new Error('Could not create mysql var file:' + safe.error.message)); + } + + const cmd = `docker run --restart=always -d --name="mysql" \ + -m 256m \ + --memory-swap 512m \ + -v "${dataDir}/mysql:/var/lib/mysql" \ + -v "${dataDir}/addons/mysql_vars.sh:/etc/mysql/mysql_vars.sh:ro" \ + --read-only -v /tmp -v /run "${tag}"`; + + shell.execSync('startMysql', cmd); + + callback(); +} + +function startPostgresql(callback) { + const tag = infra.images.postgresql.tag; + const dataDir = paths.DATA_DIR; + const rootPassword = hat(256); + + if (!safe.fs.writeFileSync(paths.DATA_DIR + '/addons/postgresql_vars.sh', 'POSTGRESQL_ROOT_PASSWORD=' + rootPassword, 'utf8')) { + return callback(new Error('Could not create postgresql var file:' + safe.error.message)); + } + + const cmd = `docker run --restart=always -d --name="postgresql" \ + -m 100m \ + --memory-swap 200m \ + -v "${dataDir}/postgresql:/var/lib/postgresql" \ + -v "${dataDir}/addons/postgresql_vars.sh:/etc/postgresql/postgresql_vars.sh:ro" \ + --read-only -v /tmp -v /run "${tag}"`; + + shell.execSync('startPostgresql', cmd); + + callback(); +} + +function startMongodb(callback) { + const tag = infra.images.mongodb.tag; + const dataDir = paths.DATA_DIR; + const rootPassword = hat(256); + + if (!safe.fs.writeFileSync(paths.DATA_DIR + '/addons/mongodb_vars.sh', 'MONGODB_ROOT_PASSWORD=' + rootPassword, 'utf8')) { + return callback(new Error('Could not create mongodb var file:' + safe.error.message)); + } + + const cmd = `docker run --restart=always -d --name="mongodb" \ + -m 100m \ + --memory-swap 200m \ + -v "${dataDir}/mongodb:/var/lib/mongodb" \ + -v "${dataDir}/addons/mongodb_vars.sh:/etc/mongodb_vars.sh:ro" \ + --read-only -v /tmp -v /run "${tag}"`; + + shell.execSync('startMongodb', cmd); + + callback(); +} + +function startMail(callback) { + // mail (note: 2525 is hardcoded in mail container and app use this port) + // MAIL_SERVER_NAME is the hostname of the mailserver i.e server uses these certs + // MAIL_DOMAIN is the domain for which this server is relaying mails + // mail container uses /app/data for backed up data and /run for restart-able data + + const tag = infra.images.mail.tag; + const dataDir = paths.DATA_DIR; + const rootPassword = hat(256); + const fqdn = config.fqdn(); + const mailFqdn = config.adminFqdn(); + + if (!safe.fs.writeFileSync(paths.DATA_DIR + '/addons/mail_vars.sh', + 'MAIL_ROOT_USERNAME=no-reply\nMAIL_ROOT_PASSWORD=' + rootPassword, 'utf8')) { + return callback(new Error('Could not create mail var file:' + safe.error.message)); + } certificates.getAdminCertificatePath(function (error, certFilePath, keyFilePath) { if (error) return callback(error); - shell.sudo('setup_infra', [ SETUP_INFRA_CMD, paths.DATA_DIR, config.fqdn(), config.adminFqdn(), certFilePath, keyFilePath ], function (error) { - callback(error); - }); + const cmd = `docker run --restart=always -d --name="mail" \ + -m 75m \ + --memory-swap 150m \ + -e "MAIL_DOMAIN=${fqdn}" \ + -e "MAIL_SERVER_NAME=${mailFqdn}" \ + -v "${dataDir}/box/mail:/app/data" \ + -v "${dataDir}/mail:/run" \ + -v "${dataDir}/addons/mail_vars.sh:/etc/mail/mail_vars.sh:ro" \ + -v "${certFilePath}:/etc/tls_cert.pem:ro" \ + -v "${keyFilePath}:/etc/tls_key.pem:ro" \ + -p 587:2525 \ + -p 993:9993 \ + -p 4190:4190 \ + -p 25:2525 \ + --read-only -v /tmp ${tag}`; + + shell.execSync('startMongodb', cmd); + + callback(); }); } +function startAddons(callback) { + assert.strictEqual(typeof callback, 'function'); + + async.series([ + startGraphite, + startMysql, + startPostgresql, + startMongodb, + startMail + ], callback); +} + function loadAddonVars(callback) { gAddonVars = { mail: ini.parse(fs.readFileSync(paths.DATA_DIR + '/addons/mail_vars.sh', 'utf8')), diff --git a/src/scripts/setup_infra.sh b/src/scripts/setup_infra.sh deleted file mode 100755 index 1dd2103d5..000000000 --- a/src/scripts/setup_infra.sh +++ /dev/null @@ -1,114 +0,0 @@ -#!/bin/bash - -set -eu -o pipefail - -if [[ ${EUID} -ne 0 ]]; then - echo "This script should be run as root." > /dev/stderr - exit 1 -fi - -if [[ $# == 1 && "$1" == "--check" ]]; then - echo "OK" - exit 0 -fi - -readonly script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -readonly infra_version="${script_dir}/../infra_version.js" - -readonly data_dir="$1" -readonly fqdn="$2" -readonly mail_fqdn="$3" -readonly mail_tls_cert="$4" -readonly mail_tls_key="$5" - -# graphite -readonly graphite_image=$(node -e "console.log(require('${infra_version}').images.graphite.tag);") -graphite_container_id=$(docker run --restart=always -d --name="graphite" \ - -m 75m \ - --memory-swap 150m \ - -p 127.0.0.1:2003:2003 \ - -p 127.0.0.1:2004:2004 \ - -p 127.0.0.1:8000:8000 \ - -v "${data_dir}/graphite:/app/data" \ - --read-only -v /tmp -v /run \ - "${graphite_image}") -echo "Graphite container id: ${graphite_container_id}" - -# mail (note: 2525 is hardcoded in mail container and app use this port) -# MAIL_SERVER_NAME is the hostname of the mailserver i.e server uses these certs -# MAIL_DOMAIN is the domain for which this server is relaying mails -# mail container uses /app/data for backed up data and /run for restart-able data -readonly mail_image=$(node -e "console.log(require('${infra_version}').images.mail.tag);") -mail_addon_root_password=$(pwgen -1 -s) -cat > "${data_dir}/addons/mail_vars.sh" < "${data_dir}/addons/mysql_vars.sh" < "${data_dir}/addons/postgresql_vars.sh" < "${data_dir}/addons/mongodb_vars.sh" </dev/null; then - echo "node is not in PATH for the root user. Create a symlink to /usr/bin/node possibly" - exit 1 -fi - image_missing="" images=$(node -e "var i = require('${SOURCE_DIR}/src/infra_version.js'); console.log(Object.keys(i.images).map(function (x) { return i.images[x].tag; }).join('\n'));"; echo $TEST_IMAGE)