Skip to content

Instantly share code, notes, and snippets.

@rjmoggach
Last active August 18, 2017 12:41
Show Gist options
  • Save rjmoggach/1d038a31e5d998bbcf37 to your computer and use it in GitHub Desktop.
Save rjmoggach/1d038a31e5d998bbcf37 to your computer and use it in GitHub Desktop.
Webfaction MongoDB/Meteor Install
#!/usr/local/bin/python2.7
import xmlrpclib
import os
import socket
import wget
import getpass
from subprocess import call
# Set some defaults
MONGO_VERSION="mongodb-linux-x86_64-2.4.12"
NODE_VERSION="0.10.33" # "wget http://nodejs.org/dist/v0.10.33/node-v0.10.33-linux-x64.tar.gz"
NODE_DIR="node-v%s"%NODE_VERSION
SERVER_IP_ADDRESS=socket.gethostbyname(socket.gethostname())
SERVER_HOSTNAME=socket.gethostname().split('.')[0].capitalize()
USERNAME=getpass.getuser()
# This is the install specific docs for node and meteor that get returned to the user
# during the install process - easier than trying to automate for now
BUILD_NODE_INFO='''
Open another ssh session and build/install node.js in the {app_dir} app as follows:
# this is slow so better to do it in a separate shell
cd $HOME/webapps/{app_dir}/{node_dir}
./configure --prefix=$HOME
make
make install
npm install -g forever demeteorizer
Then you have to get the latest meteor installed because the npm bundled one is old.
You also need to tweak the script a bit to change the PREFIX to $HOME.
cd $HOME/webapps/{app_dir}
wget https://install.meteor.com -O install_meteor.sh
sed -i 's/^PREFIX=.*$/PREFIX=$HOME/g' install_meteor.sh
./install_meteor.sh
meteor create {app_name}
cd {app_name}
demeteorizer -o $HOME/webapps/{app_dir}/deploy
cd ../deploy
npm install
\n\nHave you finished buiding/installing Node.js and Meteor?"
'''
# Template for the mongo startup script - pretty basic and could be better
MONGO_SCRIPT='''
#!/bin/bash
PIDFILE="$HOME/webapps/{mongo_app}/mongod.pid"
if [ -e "${{PIDFILE}}" ] && (ps -u $(whoami) -opid= | grep -P "^\s*$(cat ${{PIDFILE}})$" &> /dev/null); then
echo "Already running."
exit 99
fi
$HOME/webapps/{mongo_app}/{mongo_version}/bin/mongod --auth --dbpath $HOME/webapps/{mongo_app}/data/ --port {mongo_port} > $HOME/webapps/{mongo_app}/mongod.log &
echo $! > "${{PIDFILE}}"
chmod 644 "${{PIDFILE}}"
echo "Mongo Started."
'''
# command to create the database admin user/password
MONGO_CREATE_USER = "$HOME/webapps/{mongo_app}/{mongo_version}/bin/mongo localhost:{mongo_port}/admin --eval \"db.createUser({{user: '{mongo_user}', pwd: '{mongo_pass}', roles: ['userAdminAnyDatabase']}})\""
# Template for the meteor startup script - pretty basic and could be better
METEOR_SCRIPT='''
#!/bin/sh
APPPATH="$HOME/webapps/{webfaction_app}"
PIDFILE="$APPPATH/meteor.pid"
LOGDIR="$APPPATH/logs"
MONGO_URL="mongodb://{mongo_user}:{mongo_pass}@localhost:{mongo_port}/{app_name}?autoReconnect=true"
PORT={meteor_port}
ROOT_URL={meteor_url}
forever start --pidfile $APPPATH/meteor.pid -l $APPPATH/meteor.log $APPPATH/deploy/main.js
'''
# This is the question and answer part of the script...
username = raw_input("\nEnter your webfaction username\n username [{username}]: ".format(username=USERNAME) ) or USERNAME
password = getpass.getpass("\nEnter your webfaction password\n password: ")
app_name = raw_input("\nEnter the app name you want to use\n (This will create 2 apps Eg. 'app_name_mongodb' & 'app_name_meteor'\n app_name: ")
app_domain = raw_input("\nEnter the domain name you want to use (or press Enter for none)\n app_domain: ")
app_user = raw_input("\nEnter the app admin username or press Enter to use your username\n app_user [{username}]: ".format(username=USERNAME) ) or USERNAME
app_pass = getpass.getpass("\nEnter the app admin password or press Enter to use your password\n app_pass: ") or password
app_machine = raw_input("\nWhich machine are we putting this one? Case-sensitive!\n app_machine [{hostname}]: ".format(hostname=SERVER_HOSTNAME)) or SERVER_HOSTNAME
meteor_apps={}
# Setup the API
server = xmlrpclib.ServerProxy('https://api.webfaction.com/')
try:
session_id, account = server.login(username, password, app_machine)
except:
print 'Your username or password was incorrect.'
raise "Authentication Error!"
def confirm(prompt_text, default="Y"):
# this method is for convenience to make the script interactive
question = "\n{prompt}\n Enter Y or N [{default}] : ".format(prompt=prompt_text, default=default)
CONFIRM = raw_input(question) or default
if CONFIRM in ["Y", "y"]:
return True
else:
return False
def get_apps(app_prefix):
# the API returns a tuple but I prefer a dict
for webapp in server.list_apps(session_id):
if webapp['name'].startswith(app_prefix):
if webapp['name'].endswith('mongodb'):
meteor_apps['mongodb'] = webapp
if webapp['name'].endswith('meteor'):
meteor_apps['meteor'] = webapp
def server_cmd(cmd):
# shortcut for running a system command
server.system(session_id, cmd)
def create_domain(app_domain):
# delete the domain if it exists and re-add it
domain=app_domain.split('.')
if len(domain) < 2:
raise "Your domain is invalid!"
if len(domain) == 2:
server.create_domain(session_id, app_domain)
else:
tld='.'.join(domain[-2:])
if len(domain) == 3:
subdomain = domain[0]
if len(domain) > 3:
subdomain = '.'.join(domain[:-2])
if confirm("Create %s subdomain for %s tld?" % (subdomain, tld)):
server.delete_domain(session_id, tld, subdomain)
server.create_domain(session_id, tld, subdomain)
create_domain(app_domain)
for app_suffix in ['mongodb', 'meteor']:
app_fullname = '_'.join([app_name, app_suffix])
print "\nStarting setup of %s app\n----------------------------------------" % app_fullname
app_path = os.path.expanduser("~/webapps/{app_name}".format(app_name=app_fullname))
if confirm("Delete and create the %s App?" % app_suffix):
try:
server.delete_app(session_id, app_fullname)
except:
pass
server.create_app(session_id, app_fullname, 'custom_app_with_port')
get_apps(app_name)
app_port = meteor_apps[app_suffix]['port']
if app_suffix == 'mongodb':
mongo_port = app_port
MONGO_SCRIPT = MONGO_SCRIPT.format(
mongo_app=app_fullname,
mongo_version=MONGO_VERSION,
mongo_port=app_port)
mongo_script_path = os.path.expanduser('~/webapps/{app_name}/start.sh'.format(app_name=app_fullname))
mongo_script_file=open(mongo_script_path, 'a')
mongo_script_file.write(MONGO_SCRIPT)
mongo_script_file.close()
mongo_create_user = MONGO_CREATE_USER.format(
mongo_app=app_fullname,
mongo_version=MONGO_VERSION,
mongo_port=app_port,
mongo_user=app_user,
mongo_pass=app_pass)
os.chdir(app_path)
server_cmd("cd $HOME/webapps/%s" % app_fullname)
server_cmd("rm -f index.html")
server_cmd("chmod 750 %s" % mongo_script_path)
url="http://downloads.mongodb.org/linux/%s.tgz" % MONGO_VERSION
print "Downloading %s" % MONGO_VERSION
wget.download(url)
server_cmd("tar xzvf %s.tgz" % MONGO_VERSION)
server_cmd("mkdir data")
if confirm("\n\nOpen another ssh session and run the {app_name} start script\n\nHave you started {app_name}?".format(app_name=app_suffix)):
if confirm('Create admin user?'):
server_cmd(mongo_create_user)
if confirm('Create cron jobs for %s?' % app_suffix, 'N'):
mongo_cron='8,28,48 * * * * ~/webapps/{app_name}/start.sh > /dev/null 2>&1'.format(app_name=app_fullname)
server.delete_cronjob(session_id, mongo_cron)
server.create_cronjob(session_id, mongo_cron)
print "Created cron job"
if app_suffix == 'meteor':
meteor_app = app_fullname
METEOR_SCRIPT = METEOR_SCRIPT.format(
webfaction_app=app_fullname,
meteor_app=app_name,
mongo_user=app_user,
mongo_pass=app_pass,
mongo_port=mongo_port,
meteor_port=app_port,
app_name=app_name,
meteor_url="http://{domain}".format(domain=app_domain))
meteor_script_path = os.path.expanduser('~/webapps/{app_name}/start.sh'.format(app_name=app_fullname))
meteor_script_file=open(meteor_script_path, 'a')
meteor_script_file.write(METEOR_SCRIPT)
meteor_script_file.close()
os.chdir(app_path)
server_cmd("cd $HOME/webapps/%s" % app_fullname)
server_cmd("rm -f index.html")
server_cmd("chmod 750 %s" % meteor_script_path)
server_cmd("mkdir logs deploy")
url="http://nodejs.org/dist/v{node_version}/node-v{node_version}.tar.gz".format(node_version=NODE_VERSION)
print "Downloading Node.js"
wget.download(url)
server_cmd("tar xvzf node-v{node_version}.tar.gz".format(node_version=NODE_VERSION))
if confirm(BUILD_NODE_INFO.format(app_dir=app_fullname, node_dir=NODE_DIR, app_name=app_name)):
if confirm("\n\nOpen another ssh session and run the {app_name} start script\n\nHave you started {app_name}?".format(app_name=app_suffix)):
if confirm('Create cron jobs for %s?' % app_suffix, 'N'):
meteor_cron='8,28,48 * * * * ~/webapps/{app_name}/start.sh start > /dev/null 2>&1'.format(app_name=app_fullname)
server.delete_cronjob(session_id, meteor_cron)
server.create_cronjob(session_id, meteor_cron)
print "Created cron job"
if confirm("Connect app to domain?"):
if not app_domain is None:
server.create_website(session_id,
'%s_site' % app_name,
SERVER_IP_ADDRESS,
False,
[app_domain],
[meteor_app, '/']
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment