diff --git a/centos/env.list b/centos/env.list new file mode 100644 index 00000000..01eec530 --- /dev/null +++ b/centos/env.list @@ -0,0 +1 @@ +ROOT_URL=http://localhost \ No newline at end of file diff --git a/centos/install.sh b/centos/install.sh new file mode 100644 index 00000000..2f0bfb63 --- /dev/null +++ b/centos/install.sh @@ -0,0 +1,130 @@ +#!/bin/bash + +#manual +sudo mkdir -p /opt/mongodb +sudo chown ${USER} /opt/mongodb -R +sudo mkdir -p /var/lib/mongodb +sudo mkdir -p /opt/app/ +sudo mkdir -p /opt/app/config +sudo mkdir -p /opt/app/tmp +sudo chown ${USER} /opt/app -R + + +#docker +# Remove the lock +set +e +sudo rm /var/lib/dpkg/lock > /dev/null +sudo rm /var/cache/apt/archives/lock > /dev/null +sudo dpkg --configure -a +set -e + +# Required to update system +sudo yum update + +# Install docker +wget -qO- https://get.docker.com/ | sudo sh +sudo usermod -a -G docker ${USER} +sudo service docker start || sudo service docker restart + + + +#mongo +#sudo mkdir -p /opt/mongodb +#sudo chown ${USER} /opt/mongodb -R + +MONGO_VERSION=3.4.1 + +set -e +# we use this data directory for the backward compatibility +# older mup uses mongodb from apt-get and they used this data directory +#sudo mkdir -p /var/lib/mongodb + +sudo docker pull mongo:$MONGO_VERSION +set +e +docker update --restart=no mongodb +docker exec mongodb mongod --shutdown +sleep 2 +sudo docker rm -f mongodb +set -e + +sudo docker run \ + -d \ + --restart=always \ + --publish=127.0.0.1:27017:27017 \ + --volume=/var/lib/mongodb:/data/db \ + --volume=/opt/mongodb/mongodb.conf:/mongodb.conf \ + --name=mongodb \ + mongo:$MONGO_VERSION mongod -f /mongodb.conf + + + +#meteor +#sudo mkdir -p /opt/app/ +#sudo mkdir -p /opt/app/config +#sudo mkdir -p /opt/app/tmp +#sudo chown ${USER} /opt/app -R + +set -e + +APP_DIR=/opt/app + +# save the last known version +cd $APP_DIR +if [[ -d current ]]; then + sudo rm -rf last + sudo mv current last +fi + +APPNAME=app +# setup the new version +sudo mkdir current +sudo cp $APP_DIR/tmp/bundle.tar.gz $APP_DIR/current/ + + +#meteor app docker +APPNAME=app2 +CLIENTSIZE=10M +APP_PATH=/opt/$APPNAME +BUNDLE_PATH=$APP_PATH/current +ENV_FILE=$APP_PATH/config/env.list +PORT=80 +BIND=0.0.0.0 +NGINX_PROXY_VERSION=latest +LETS_ENCRYPT_VERSION=latest + +# Remove previous version of the app, if exists +#docker rm -f $APPNAME + +# Remove frontend container if exists +#docker rm -f $APPNAME-frontend +#docker network disconnect bridge -f $APPNAME-frontend +#echo "Removed $APPNAME-frontend" + + +# Remove let's encrypt containers if exists +#docker rm -f $APPNAME-nginx-letsencrypt +#docker network disconnect bridge -f $APPNAME-nginx-letsencrypt +#echo "Removed $APPNAME-nginx-letsencrypt" + +#docker rm -f $APPNAME-nginx-proxy +#docker network disconnect bridge -f $APPNAME-nginx-proxy +#echo "Removed $APPNAME-nginx-proxy" + +# We don't need to fail the deployment because of a docker hub downtime +set +e +docker pull abernix/meteord:base +set -e +echo "Pulled abernix/meteord:base" + +docker run \ + -d \ + --restart=always \ + --publish=$BIND:$PORT:80 \ + --volume=$BUNDLE_PATH:/bundle \ + --hostname="$HOSTNAME-$APPNAME" \ + --env-file=$ENV_FILE \ + --link=mongodb:mongodb --env=MONGO_URL=mongodb://mongodb:27017/$APPNAME \ + --name=$APPNAME \ + abernix/meteord:base +echo "Ran abernix/meteord:base" +sleep 15s diff --git a/centos/mongodb.conf b/centos/mongodb.conf new file mode 100644 index 00000000..71404540 --- /dev/null +++ b/centos/mongodb.conf @@ -0,0 +1 @@ +dbpath=/data/db diff --git a/centos/start.sh b/centos/start.sh new file mode 100644 index 00000000..b28463bf --- /dev/null +++ b/centos/start.sh @@ -0,0 +1,70 @@ +#meteor +#sudo mkdir -p /opt/app/ +#sudo mkdir -p /opt/app/config +#sudo mkdir -p /opt/app/tmp +#sudo chown ${USER} /opt/app -R + +set -e + +APP_DIR=/opt/app + +# save the last known version +cd $APP_DIR +if [[ -d current ]]; then + sudo rm -rf last + sudo mv current last +fi + +APPNAME=app +# setup the new version +sudo mkdir current +sudo cp $APP_DIR/tmp/bundle.tar.gz $APP_DIR/current/ + + +#meteor app docker +APPNAME=app2 +CLIENTSIZE=10M +APP_PATH=/opt/$APPNAME +BUNDLE_PATH=$APP_PATH/current +ENV_FILE=$APP_PATH/config/env.list +PORT=80 +BIND=0.0.0.0 +NGINX_PROXY_VERSION=latest +LETS_ENCRYPT_VERSION=latest + +# Remove previous version of the app, if exists +#docker rm -f $APPNAME + +# Remove frontend container if exists +#docker rm -f $APPNAME-frontend +#docker network disconnect bridge -f $APPNAME-frontend +#echo "Removed $APPNAME-frontend" + + +# Remove let's encrypt containers if exists +#docker rm -f $APPNAME-nginx-letsencrypt +#docker network disconnect bridge -f $APPNAME-nginx-letsencrypt +#echo "Removed $APPNAME-nginx-letsencrypt" + +#docker rm -f $APPNAME-nginx-proxy +#docker network disconnect bridge -f $APPNAME-nginx-proxy +#echo "Removed $APPNAME-nginx-proxy" + +# We don't need to fail the deployment because of a docker hub downtime +set +e +sudo docker pull abernix/meteord:base +set -e +echo "Pulled abernix/meteord:base" + +sudo docker run \ + -d \ + --restart=always \ + --publish=$BIND:$PORT:80 \ + --volume=$BUNDLE_PATH:/bundle \ + --hostname="$HOSTNAME-$APPNAME" \ + --env-file=$ENV_FILE \ + --link=mongodb:mongodb --env=MONGO_URL=mongodb://mongodb:27017/$APPNAME \ + --name=$APPNAME \ + abernix/meteord:base +echo "Ran abernix/meteord:base" +sleep 15s diff --git a/src/modules/meteor/index.js b/src/modules/meteor/index.js index 0115ea32..c2f71b1e 100644 --- a/src/modules/meteor/index.js +++ b/src/modules/meteor/index.js @@ -9,6 +9,7 @@ import nodemiral from 'nodemiral'; import random from 'random-seed'; import uuid from 'uuid'; import os from 'os'; +import * as mongo from '../mongo/'; const log = debug('mup:module:meteor'); @@ -273,7 +274,13 @@ export function deploy(api) { process.exit(1); } - return push(api).then(() => envconfig(api)).then(() => start(api)); + return push(api).then( + () => envconfig(api) + ).then( + () => start(api) + ).then( + () => mongo.whitelist(api) + ); } export function stop(api) { diff --git a/src/modules/mongo/assets/iptables.sh b/src/modules/mongo/assets/iptables.sh new file mode 100644 index 00000000..80335724 --- /dev/null +++ b/src/modules/mongo/assets/iptables.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +# Usage: +# timeout 10 docker_iptables.sh +# +# Use the builtin shell timeout utility to prevent infinite loop (see below) + +if [ ! -x /usr/bin/docker ]; then + exit +fi +#clean PRE_DOCKER +iptables -F PRE_DOCKER +iptables --delete FORWARD -o docker0 -j PRE_DOCKER + +# Create a PRE_DOCKER table +iptables -N PRE_DOCKER + +# Default action +iptables -I PRE_DOCKER -j DROP + +# Docker Containers Public Admin access (insert your IPs here) +<% for(var key in ips) { %> + iptables -I PRE_DOCKER -i eth0 -s <%- ips[key] %> -j ACCEPT +<% } %> + +# Docker internal use +iptables -I PRE_DOCKER -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +iptables -I PRE_DOCKER -i docker0 ! -o docker0 -j ACCEPT +iptables -I PRE_DOCKER -m state --state RELATED -j ACCEPT +iptables -I PRE_DOCKER -i docker0 -o docker0 -j ACCEPT + +# Docker container named www-nginx public access policy +WWW_IP_CMD="/usr/bin/docker inspect --format='{{.NetworkSettings.IPAddress}}' <%- name %>" +WWW_IP=$(/usr/bin/docker inspect --format='{{.NetworkSettings.IPAddress}}' <%- name %>) + +# Double check, wait for docker socket (upstart docker.conf already does this) +#while [ ! -e "/var/run/docker.sock" ]; do echo "Waiting for /var/run/docker.sock..."; sleep 1; done + +# Wait for docker web server container IP +#while [ -z "$WWW_IP" ]; do echo "Waiting for www-nginx IP..."; WWW_IP=$($WWW_IP_CMD); done + +# Insert web server container filter rules +<% for(var key in localServers) { %> + WWW_IP=$(/usr/bin/docker inspect --format='{{.NetworkSettings.IPAddress}}' <%- localServers[key] %>) + iptables -I PRE_DOCKER -i eth0 -p tcp -d $WWW_IP --dport 80 -j ACCEPT + iptables -I PRE_DOCKER -i eth0 -p tcp -d $WWW_IP --dport 443 -j ACCEPT +<% } %> + + +# Finally insert the PRE_DOCKER table before the DOCKER table in the FORWARD chain. +iptables -I FORWARD -o docker0 -j PRE_DOCKER \ No newline at end of file diff --git a/src/modules/mongo/assets/mongo-start.sh b/src/modules/mongo/assets/mongo-start.sh index ac4c2ee7..9d2fc0ba 100644 --- a/src/modules/mongo/assets/mongo-start.sh +++ b/src/modules/mongo/assets/mongo-start.sh @@ -17,11 +17,22 @@ set -e echo "Running mongo:<%= mongoVersion %>" -sudo docker run \ - -d \ - --restart=always \ - --publish=127.0.0.1:27017:27017 \ - --volume=/var/lib/mongodb:/data/db \ - --volume=/opt/mongodb/mongodb.conf:/mongodb.conf \ - --name=mongodb \ - mongo:$MONGO_VERSION mongod -f /mongodb.conf +<% if(typeof ipwhitelist === "object") { %> + sudo docker run \ + -d \ + --restart=always \ + --publish=0.0.0.0:27017:27017 \ + --volume=/var/lib/mongodb:/data/db \ + --volume=/opt/mongodb/mongodb.conf:/mongodb.conf \ + --name=mongodb \ + mongo:$MONGO_VERSION mongod -f /mongodb.conf +<% } else { %> + sudo docker run \ + -d \ + --restart=always \ + --publish=127.0.0.1:27017:27017 \ + --volume=/var/lib/mongodb:/data/db \ + --volume=/opt/mongodb/mongodb.conf:/mongodb.conf \ + --name=mongodb \ + mongo:$MONGO_VERSION mongod -f /mongodb.conf +<% } %> \ No newline at end of file diff --git a/src/modules/mongo/index.js b/src/modules/mongo/index.js index f80cead5..7addd0c7 100644 --- a/src/modules/mongo/index.js +++ b/src/modules/mongo/index.js @@ -11,6 +11,7 @@ export function dump() { export function help() { log('exec => mup mongo help'); + console.log('mup mongo', Object.keys(this)); } export function logs(api) { @@ -64,12 +65,13 @@ export function setup(api) { return runTaskList(list, sessions, { verbose: api.getVerbose() }); } -export function start(api) { +export function realStart(api){ log('exec => mup mongo start'); const mongoSessions = api.getSessions(['mongo']); const meteorSessions = api.getSessions(['meteor']); const config = api.getConfig().mongo; + let ipwhitelist = !config.ipwhitelist ? '' : config.ipwhitelist; if ( meteorSessions.length !== 1 || @@ -84,7 +86,8 @@ export function start(api) { list.executeScript('Start Mongo', { script: resolvePath(__dirname, 'assets/mongo-start.sh'), vars: { - mongoVersion: config.version || '3.4.1' + mongoVersion: config.version || '3.4.1', + ipwhitelist:ipwhitelist } }); @@ -92,6 +95,18 @@ export function start(api) { return runTaskList(list, sessions, { verbose: api.getVerbose() }); } +export function start(api) { + log('exec => mup mongo (dummy) start'); + + const config = api.getConfig().mongo; + + if(config.ipwhitelist){ + return realStart(api).then(() => whitelist(api)); + }else{ + return realStart(api) + } +} + export function stop(api) { log('exec => mup mongo stop'); const list = nodemiral.taskList('Stop Mongo'); @@ -103,3 +118,37 @@ export function stop(api) { const sessions = api.getSessions(['mongo']); return runTaskList(list, sessions, { verbose: api.getVerbose() }); } + +export function whitelist(api){ + log('exec => mup whitelist blkmkt'); + const config = api.getConfig().mongo; + const configMeteor = api.getConfig().meteor; + if (!config) { + console.error('error: no configs found for meteor'); + process.exit(1); + } + let ipwhitelist = !config.ipwhitelist ? '' : config.ipwhitelist; + let localServers = []; + if(!configMeteor.ssl){ + localServers.push(configMeteor.name); + }else if(configMeteor.ssl.autogenerate){ + localServers.push(configMeteor.name+"-nginx-letsencrypt"); + localServers.push(configMeteor.name+"-nginx-proxy"); + }else{ + localServers.push(configMeteor.name+"-frontend"); + } + + const list = nodemiral.taskList('Whitelist Mongo'); + + list.executeScript('Whitelist Mongo', { + script: resolvePath(__dirname, 'assets/iptables.sh'), + vars: { + ips: config.ipwhitelist, + name: configMeteor.name, + localServers: localServers + } + }); + + const sessions = api.getSessions(['mongo']); + return runTaskList(list, sessions, { verbose: api.getVerbose() }); +} \ No newline at end of file diff --git a/src/validate/mongo.js b/src/validate/mongo.js index 7c131da8..130cf484 100644 --- a/src/validate/mongo.js +++ b/src/validate/mongo.js @@ -11,7 +11,8 @@ const schema = joi.object().keys({ oplog: joi.bool(), port: joi.number(), version: joi.string(), - servers: joi.object().keys() + servers: joi.object().keys(), + ipwhitelist: joi.array() }); export default function(config) {