Commit 1bf7c923 by John Jarvis

Merge pull request #110 from edx/jarv/edx-sandbox

Jarv/edx sandbox
parents a4e02c8b 33a9a931
......@@ -36,7 +36,34 @@ over time, so expect frequent changes.
## AWS
### Building the stack
### Quick start - Building the stack on a single server
To deploy the entire edX platform on a single ec2 instance
run the following commands:
```
git clone git@github.com:edx/configuration
mkvirtualenv ansible
cd configuration
pip install -r ansible-requirements.txt
cd playbooks
(adjust the settings in edx_sandbox.yml)
`ansible-playbook -vvv --user=ubuntu edx_sandbox.yml -i ec2.py -e 'secure_dir=secure_example`
```
This will install the following services on a single instance
* edX lms (django/python) for courseware
* edX studio (django/python) for course authoring
* mysql (running locally)
* mongo (running locally)
* memcache (running locally)
Note: In order for mail to work properly you will need to add AWS credentials for an account that
has SES permissions, see `secure\_example/vars/edxapp\_sandbox.yml`
### Building the stack with CloudFormation
The first step is to provision the CloudFormation stack. There are
several options for doing this.
......
- name: Create sandbox instance
hosts: localhost
connection: local
user: root
sudo: False
gather_facts: False
vars:
keypair: continuous-integration
instance_type: m1.large
security_group: sandbox
image: ami-d0f89fb9
region: us-east-1
roles:
- launch_instance
- name: Configure instance(s)
hosts: launched
sudo: True
gather_facts: True
vars:
migrate_db: True
vars_files:
- "{{ secure_dir }}/vars/edxapp_sandbox.yml"
- "{{ secure_dir }}/vars/users.yml"
roles:
- common
- nginx
- gunicorn
- edxlocal
- edxapp
- name: Create sandbox instance
hosts: localhost
connection: local
user: root
sudo: False
gather_facts: False
vars:
keypair: continuous-integration
instance_type: m1.large
security_group: sandbox
image: ami-d0f89fb9
region: us-east-1
roles:
- launch_instance
- name: Configure instance(s)
hosts: launched
sudo: True
gather_facts: True
vars:
migrate_db: True
vars_files:
- "{{ secure_dir }}/vars/edxapp_ref_users.yml"
- "{{ secure_dir }}/vars/edxapp_sandbox.yml"
roles:
- common
- nginx
- gunicorn
- edxlocal
- edxapp
......@@ -20,6 +20,7 @@
- update cms templates
- lms asset static failure check
- cms asset static failure check
- syncdb and migrate
- stop edxapp
- start edxapp
tags:
......@@ -236,6 +237,17 @@
- cms
- deploy
- name: syncdb and migrate
shell: sudo -u www-data SERVICE_VARIANT=lms /opt/edx/bin/django-admin.py syncdb --migrate --noinput --settings=lms.envs.aws --pythonpath=/opt/wwc/edx-platform
when: migrate_db is defined
tags:
- deploy
- lms
- lms-xml
- lms-preview
- cms
- syncdb
- name: stop edxapp
service: name=edxapp state=stopped
tags:
......@@ -253,3 +265,4 @@
- lms-preview
- cms
- deploy
......@@ -2,6 +2,16 @@
# when the role is included
---
# Default nginx listen ports
# These should be overrided if you want
# to serve all content on port 80
lms_xml_nginx_port: 18030
lms_nginx_port: 80
lms_preview_nginx_port: 18020
cms_nginx_port: 18010
# These vars are for creating the application json config
# files. There are two for each service that uses the
# 'edx-platform' code. Defining them will create the upstart
......
# Installs packages to run edx locally on a single instance
# requires:
# - group_vars/all
# - common/tasks/main.yml
# - nginx/tasks/main.yml
---
- name: install python-pymongo (req for ansible)
pip: name=pymongo
- name: install python-mysqldb (req for ansible)
apt: pkg=python-mysqldb state=present
- name: install mysql server and recommends
apt: pkg=mysql-server-5.5 state=present install_recommends=yes
- name: create a database
mysql_db: >
db=wwc
state=present
encoding=utf8
- name: install mongo server and recommends
apt: pkg=mongodb-server state=present install_recommends=yes
- name: stop mongo service
service: name=mongodb state=stopped
- name: move mongodb to /mnt
command: mv /var/lib/mongodb /mnt/. creates=/mnt/mongodb
- name: create mongodb symlink
file: src=/mnt/mongodb dest=/var/lib/mongodb state=link
- name: start mongo service
service: name=mongodb state=started
- name: wait for mongo server to start
wait_for: port=27017 delay=2
- name: create a mongodb user
mongodb_user: >
database=wwc
name=edxapp
password=password
state=present
- name: install memcached
apt: pkg=memcached state=present
# Launches an ec2 instance and blocks until the instance is up
# adds it to the host group
- name: Launch instance
local_action: ec2 keypair=$keypair group=$security_group instance_type=$instance_type image=$image wait=true region=$region
register: ec2
- name: Add new instance to host group
local_action: add_host hostname=${item.public_ip} groupname=launched
with_items: ${ec2.instances}
- name: Wait for SSH to come up
local_action: wait_for host=${item.public_dns_name} port=22 delay=60 timeout=320 state=started
with_items: ${ec2.instances}
server {
# CMS configuration file for nginx, templated by ansible
listen 80;
listen {{cms_nginx_port}};
server_name studio.*;
server_name trace-cms.*
studio.lms-dev.m.edx.org;
access_log {{log_base_dir}}/nginx/access.log;
error_log {{log_base_dir}}/nginx/error.log error;
# Send error response when request host isn't under our control
# We will no longer respond to proxy attempts like this with
# anything.
# curl -i -A '' -x http://www.edx.org:80 --proxy-negotiate -U u:p -u u:p http://chat.sdtz.com
set $reject 'no';
if ($host !~* (edx.org|edxonline.org)$ ) {
set $reject 'yes';
}
if ($request_uri ~ ^(/heartbeat)$) {
set $reject 'no';
}
if ( $reject = 'yes' ) {
return 444;
}
# CS184 requires uploads of up to 4MB for submitting screenshots.
# CMS requires larger value for course assest, values provided
# via hiera.
......@@ -61,9 +41,8 @@ server {
# Check security on this
location ~ /static/(?P<file>.*) {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/nginx.htpasswd;
root {{app_base_dir}};
try_files /staticfiles/$file /course_static/$file =404;
# return a 403 for static files that shouldn't be
# in the staticfiles directory
......@@ -73,7 +52,6 @@ server {
# Set django-pipelined files to maximum cache time
location ~ "/static/(?P<collected>.*\.[0-9a-f]{12}\..*)" {
expires max;
# Without this try_files, files that have been run through
# django-pipeline return 404s
try_files /staticfiles/$collected /course_static/$collected =404;
......
server {
# LMS-preview configuration file for nginx, templated by ansible
listen 80;
listen {{lms_preview_nginx_port}};
server_name trace-lms-preview.*
preview.lms-dev.m.edx.org;
server_name preview.*;
#
# Send error response when request host isn't under our control
# We will no longer respond to proxy attempts like this with
# anything.
# curl -i -A '' -x http://www.edx.org:80 --proxy-negotiate -U u:p -u u:p http://chat.sdtz.com
#
set $reject 'no';
#if ($host !~* (edx.org|edxonline.org)$ ) {
# set $reject 'yes';
#}
if ($request_uri ~ ^(/heartbeat)$) {
set $reject 'no';
}
if ( $reject = 'yes' ) {
return 444;
}
# CS184 requires uploads of up to 4MB for submitting screenshots.
# CMS requires larger value for course assest, values provided
# via hiera.
......@@ -88,12 +67,4 @@ server {
if ($do_redirect = "true") {
rewrite ^ https://$host$request_uri? permanent;
}
# Monitoring support for datadog.
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1/32;
deny all;
}
}
server {
# LMS-preview configuration file for nginx, templated by ansible
listen 80;
listen {{lms_xml_nginx_port}};
server_name trace-lms-xml.*
xml.lms-dev.m.edx.org;
#
# Send error response when request host isn't under our control
# We will no longer respond to proxy attempts like this with
# anything.
# curl -i -A '' -x http://www.edx.org:80 --proxy-negotiate -U u:p -u u:p http://chat.sdtz.com
#
set $reject 'no';
#if ($host !~* (edx.org|edxonline.org)$ ) {
# set $reject 'yes';
#}
if ($request_uri ~ ^(/heartbeat)$) {
set $reject 'no';
}
if ( $reject = 'yes' ) {
return 444;
}
# CS184 requires uploads of up to 4MB for submitting screenshots.
# CS184 requires uploads of up to 4MB for submitting screenshots.
# CMS requires larger value for course assest, values provided
# via hiera.
client_max_body_size 4M;
......
server {
# LMS configuration file for nginx, templated by ansible
listen 80;
listen {{lms_nginx_port}} default;
server_name *.edx.org;
access_log {{log_base_dir}}/nginx/access.log;
error_log {{log_base_dir}}/nginx/error.log error;
#
# Send error response when request host isn't under our control
# We will no longer respond to proxy attempts like this with
# anything.
# curl -i -A '' -x http://www.edx.org:80 --proxy-negotiate -U u:p -u u:p http://chat.sdtz.com
#
set $reject 'no';
if ($host !~* (edx.org|edxonline.org)$ ) {
set $reject 'yes';
}
if ($request_uri ~ ^(/heartbeat)$) {
set $reject 'no';
}
if ( $reject = 'yes' ) {
return 444;
}
# CS184 requires uploads of up to 4MB for submitting screenshots.
# CMS requires larger value for course assest, values provided
# via hiera.
......@@ -34,11 +13,6 @@ server {
rewrite ^(.*)/favicon.ico$ /static/images/favicon.ico last;
# CS188 rewrite rule for Arjun 9/19/12
rewrite ^/ai$ http://$host/courses/BerkeleyX/CS188.1x/2012_Fall/about last;
# redirect /ai to the about page for CS188.1x
rewrite ^/ai$ https://$host/courses/BerkeleyX/CS188.1x/2012_Fall/about last;
location @proxy_to_lms_app {
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
......@@ -66,8 +40,6 @@ server {
# Check security on this
location ~ /static/(?P<file>.*) {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/nginx.htpasswd;
root {{app_base_dir}};
try_files /staticfiles/$file /course_static/$file =404;
......@@ -97,12 +69,4 @@ server {
if ($do_redirect = "true") {
rewrite ^ https://$host$request_uri? permanent;
}
# Monitoring support for datadog.
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1/32;
deny all;
}
}
###############################################
# Sandbox configuration
#
# There should be nothing in this configuration
# that would be a problem if made public !!
#
# Configuration overview:
# - mysql installed on localhost
# - mongo installed on localhost
# - memcache installed on localhost
# - SES used for email (ses only perms)
#
# You must fill in credentials for sending
# mail using AWS
#
# Set the following before using this configuration
# configuration.
#
# * AWS_ACCESS_KEY_ID
# * AWS_SECRET_ACCESS_KEY
# * SESSION_COOKIE_DOMAIN
# * FEEDBACK_SUBMISSION_EMAIL
#
#Use YAML references (& and *) and hash merge <<: to factor out shared settings
#see http://atechie.net/2009/07/merging-hashes-in-yaml-conf-files/
generic_auth_config: &generic_auth
'CONTENTSTORE':
'ENGINE': 'xmodule.contentstore.mongo.MongoContentStore'
'ANALYTICS_API_KEY': ''
'ZENDESK_USER': ''
'ZENDESK_API_KEY': ''
'CELERY_BROKER_USER': 'celery'
'CELERY_BROKER_PASSWORD': ''
# "ses-send" user on the main aws account, only
# has access to use ses
'AWS_ACCESS_KEY_ID': ''
'AWS_SECRET_ACCESS_KEY': ''
'CONTENTSTORE':
'OPTIONS':
'db': 'wwc'
'host': [ 'localhost' ]
'password': 'password'
'port': 27017
'user': 'mongo'
'DATABASES':
'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'wwc', 'USER': 'root', 'PASSWORD': '', 'HOST': 'localhost', 'PORT': '3306' }
'MODULESTORE':
'default':
'ENGINE': 'xmodule.modulestore.mongo.MongoModuleStore'
'OPTIONS': &lms_modulestore_default_options
'collection': 'modulestore'
'db': 'wwc'
'default_class': 'xmodule.hidden_module.HiddenDescriptor'
'fs_root': '/opt/wwc/data'
'host': ['localhost']
'password': 'password'
'port': 27017
'render_template': 'mitxmako.shortcuts.render_to_string'
'user': 'mongo'
# Needed for the CMS to be able to run update_templates
'direct':
'ENGINE': 'xmodule.modulestore.mongo.MongoModuleStore'
'OPTIONS': *lms_modulestore_default_options
'OPEN_ENDED_GRADING_INTERFACE': {
'url': '',
'password': '',
'peer_grading': 'peer_grading',
'staff_grading': 'staff_grading',
'grading_controller': 'grading_controller',
'username': 'lms'}
'PEARSON_TEST_PASSWORD': ''
'SECRET_KEY': 'secret'
'XQUEUE_INTERFACE':
'basic_auth': [ 'noauth', 'noauth']
'django_auth': { 'password': 'lms',
'username': 'lms'}
'url': ''
generic_env_config: &generic_env
'BOOK_URL': ''
'CERT_QUEUE': 'certificates'
'LOCAL_LOGLEVEL': 'INFO'
'MITX_FEATURES':
'AUTH_USE_OPENID_PROVIDER': true
'CERTIFICATES_ENABLED': true
'ENABLE_DISCUSSION_SERVICE': false
'ENABLE_INSTRUCTOR_ANALYTICS': false
'ENABLE_PEARSON_HACK_TEST': false
'SUBDOMAIN_BRANDING': false
'SUBDOMAIN_COURSE_LISTINGS': false
'WIKI_ENABLED': true
'SYSLOG_SERVER': 'syslog.a.m.i4x.org'
'SITE_NAME': 'example.com'
'LOG_DIR': '/mnt/logs/edx'
'MEDIA_URL': ''
'ANALYTICS_SERVER_URL': ''
'FEEDBACK_SUBMISSION_EMAIL': ''
'TIME_ZONE': 'America/New_York'
'CACHES': &lms_caches
'default':
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache'
'KEY_FUNCTION': 'util.memcache.safe_key'
'KEY_PREFIX': 'sandbox'
'LOCATION': [ 'localhost:11211' ]
'general':
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache'
'KEY_FUNCTION': 'util.memcache.safe_key'
'KEY_PREFIX': 'sandbox'
'LOCATION': [ 'localhost:11211' ]
'mongo_metadata_inheritance':
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache'
'KEY_FUNCTION': 'util.memcache.safe_key'
'KEY_PREFIX': 'sandbox'
'LOCATION': [ 'localhost:11211' ]
'staticfiles':
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache'
'KEY_FUNCTION': 'util.memcache.safe_key'
'KEY_PREFIX': 'sandbox'
'LOCATION': [ 'localhost:11211' ]
'celery':
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache'
'KEY_FUNCTION': 'util.memcache.safe_key'
'KEY_PREFIX': 'sandbox'
'LOCATION': [ 'localhost:11211' ]
'CELERY_BROKER_TRANSPORT': 'amqp'
'CELERY_BROKER_HOSTNAME': ''
'COMMENTS_SERVICE_URL': ''
'LOGGING_ENV': 'sandbox'
'SESSION_COOKIE_DOMAIN': !!null
'COMMENTS_SERVICE_KEY': ''
lms_auth_config:
<<: *generic_auth
lms_env_config:
<<: *generic_env
lms_xml_auth_config:
<<: *generic_auth
lms_xml_env_config:
<<: *generic_env
cms_auth_config:
<<: *generic_auth
cms_env_config:
<<: *generic_env
lms_preview_auth_config:
<<: *generic_auth
lms_preview_env_config:
<<: *generic_env
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment