diff --git a/playbooks/edxapp_stage.yml b/playbooks/edxapp_stage.yml index 5dc1152d661..a15d711dc96 100644 --- a/playbooks/edxapp_stage.yml +++ b/playbooks/edxapp_stage.yml @@ -6,4 +6,5 @@ - "vars/secure/edxapp_stage_users.yml" roles: - common + - nginx - lms diff --git a/playbooks/group_vars/all b/playbooks/group_vars/all new file mode 100644 index 00000000000..c6c9f87b34b --- /dev/null +++ b/playbooks/group_vars/all @@ -0,0 +1,25 @@ +# Variables for all playbooks +# +# These variables should apply to all roles and environments. +# All definitions can be overrided in the +# the group files that are in this directory +# +# If a new variable is added please document it! +--- +nginx_cfg: + # - link - turn on + # - absent - turn off + sites_enabled: + basic_auth: link + edx_release: link + # path to version files for the basic + # nginx configuration + version_html: /opt/wwc/versions.html + version_json: /opt/wwc/versions.json + # default htpasswd contents set to edx/edx + # this value can be overiden in vars/secure/.yml + htpasswd: | + edx:$apr1$2gWcIvlc$Nu7b/KTwd5HoIDEkSPNUk/ +pkgs: + nginx: + state: installed diff --git a/playbooks/roles/common/tasks/main.yml b/playbooks/roles/common/tasks/main.yml index 29211a4fe4f..eb34cfafc6c 100644 --- a/playbooks/roles/common/tasks/main.yml +++ b/playbooks/roles/common/tasks/main.yml @@ -2,7 +2,10 @@ - include: create_users.yml - name: Create application root sudo: True - action: file path=/opt/wwc state=directory owner=root group=root + file: path=/opt/wwc state=directory owner=root group=root - name: Create log directory sudo: True - action: file path=/mnt/logs state=directory + file: path=/mnt/logs state=directory +- name: Update apt cache + sudo: True + apt: update_cache=yes diff --git a/playbooks/roles/lms/tasks/main.yml b/playbooks/roles/lms/tasks/main.yml index 59755794e95..a24e67cf14f 100644 --- a/playbooks/roles/lms/tasks/main.yml +++ b/playbooks/roles/lms/tasks/main.yml @@ -1,7 +1,12 @@ +# requires: +# - common/tasks/main.yml +# - nginx/tasks/main.yml --- - name: create lms application config - action: template src=env.json.j2 dest=/opt/wwc/lms-env.json + template: src=env.json.j2 dest=/opt/wwc/lms-env.json sudo: True - name: create lms auth file - action: template src=auth.json.j2 dest=/opt/wwc/lms-auth.json + template: src=auth.json.j2 dest=/opt/wwc/lms-auth.json sudo: True +- include: ../../nginx/tasks/nginx_site.yml state=link site_name=lms +- include: ../../nginx/tasks/nginx_site.yml state=link site_name=lms-backend diff --git a/playbooks/roles/nginx/README.md b/playbooks/roles/nginx/README.md new file mode 100644 index 00000000000..736860e7036 --- /dev/null +++ b/playbooks/roles/nginx/README.md @@ -0,0 +1 @@ +* main.yml: installs nginx and will enable the basic nginx configuration for version introspection diff --git a/playbooks/roles/nginx/handlers/main.yml b/playbooks/roles/nginx/handlers/main.yml new file mode 100644 index 00000000000..a15d80b42ba --- /dev/null +++ b/playbooks/roles/nginx/handlers/main.yml @@ -0,0 +1,4 @@ +--- +- name: restart nginx + service: name=nginx state=restarted + sudo: True diff --git a/playbooks/roles/nginx/tasks/main.yml b/playbooks/roles/nginx/tasks/main.yml new file mode 100644 index 00000000000..0f4bfe7a8d1 --- /dev/null +++ b/playbooks/roles/nginx/tasks/main.yml @@ -0,0 +1,22 @@ +# requires: +# - common/tasks/main.yml +--- +- name: Install nginx + sudo: True + apt: pkg=nginx state={{ pkgs.nginx.state }} + notify: restart nginx +# removing default link +- name: Removing default nginx config + sudo: True + file: path=/etc/nginx/sites-available/default state=absent + notify: restart nginx +# Standard configuration that is common across all roles +# Default values for these variables are set in group_vars/all +- include: nginx_site.yml state="{{ nginx_cfg.sites_enabled.edx_release }}" site_name=edx-release +- include: nginx_site.yml state="{{ nginx_cfg.sites_enabled.basic_auth }}" site_name=basic-auth +# Default htpassword file, required for basic auth +- copy: content={{ nginx_cfg.htpasswd }} dest=/etc/nginx/nginx.htpasswd + sudo: True +- name: Ensuring that nginx is running + sudo: True + service: name=nginx state=started diff --git a/playbooks/roles/nginx/tasks/nginx_site.yml b/playbooks/roles/nginx/tasks/nginx_site.yml new file mode 100644 index 00000000000..0c469d6b12c --- /dev/null +++ b/playbooks/roles/nginx/tasks/nginx_site.yml @@ -0,0 +1,11 @@ +# Requires nginx package +--- +- name: Copying nginx config + sudo: True + template: src={{ site_name }}.j2 dest=/etc/nginx/sites-available/{{ site_name }} + notify: restart nginx + +- name: Creating nginx config link + sudo: True + file: src=/etc/nginx/sites-available/{{ site_name }} dest=/etc/nginx/sites-enabled/{{ site_name }} state={{ state }} owner=root group=root + notify: restart nginx diff --git a/playbooks/roles/nginx/templates/basic-auth.j2 b/playbooks/roles/nginx/templates/basic-auth.j2 new file mode 100644 index 00000000000..398a1c0342d --- /dev/null +++ b/playbooks/roles/nginx/templates/basic-auth.j2 @@ -0,0 +1,10 @@ +server { + listen 80; + location / { + auth_basic "Restricted"; + auth_basic_user_file /etc/nginx/nginx.htpasswd; + root /opt/wwc/main_static; + index index.html + proxy_set_header X-Forwarded-Proto https; + } +} diff --git a/playbooks/roles/nginx/templates/edx-release.j2 b/playbooks/roles/nginx/templates/edx-release.j2 new file mode 100644 index 00000000000..03f509a02ab --- /dev/null +++ b/playbooks/roles/nginx/templates/edx-release.j2 @@ -0,0 +1,13 @@ +server { + listen 8099 default_server; + + server_name mitx_release.*; + + location = /versions.html { + alias {{ nginx_cfg.version_html }}; + } + + location = /versions.json { + alias {{ nginx_cfg.version_json }}; + } +} diff --git a/playbooks/roles/nginx/templates/lms-backend.j2 b/playbooks/roles/nginx/templates/lms-backend.j2 new file mode 100644 index 00000000000..be6999093a2 --- /dev/null +++ b/playbooks/roles/nginx/templates/lms-backend.j2 @@ -0,0 +1,4 @@ +upstream lms-backend { + # For a TCP configuration: + server 127.0.0.1:8000 fail_timeout=0; +} diff --git a/playbooks/roles/nginx/templates/lms.j2 b/playbooks/roles/nginx/templates/lms.j2 new file mode 100644 index 00000000000..ee0f8901e2b --- /dev/null +++ b/playbooks/roles/nginx/templates/lms.j2 @@ -0,0 +1,105 @@ +server { + + listen 80; + + server_name *.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. + # CMS requires larger value for course assest, values provided + # via hiera. + client_max_body_size 4M; + + 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; + proxy_set_header X-Forwarded-Port $http_x_forwarded_port; + proxy_set_header X-Forwarded-For $http_x_forwarded_for; + proxy_set_header Host $http_host; + + proxy_redirect off; + proxy_pass http://lms-backend; + } + + location / { + try_files $uri @proxy_to_lms_app; + } + + # No basic auth security on the github_service_hook url, so that github can use it for cms + location /github_service_hook { + try_files $uri @proxy_to_lms_app; + } + + # No basic auth security on the heartbeat url, so that ELB can use it + location /heartbeat { + try_files $uri @proxy_to_lms_app; + } + + # Check security on this + location ~ /static/(?P.*) { + auth_basic "Restricted"; + auth_basic_user_file /etc/nginx/lms.htpasswd; + root /opt/wwc; + try_files /staticfiles/$file /course_static/$file =404; + + # return a 403 for static files that shouldn't be + # in the staticfiles directory + location ~ ^/static/(?:.*)(?:\.xml|\.json|README.TXT) { + return 403; + } + # Set django-pipelined files to maximum cache time + location ~ "/static/(?P.*\.[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; + } + + # Expire other static files immediately (there should be very few / none of these) + expires epoch; + } + + # Forward to HTTPS if we're an HTTP request... + if ($http_x_forwarded_proto = "http") { + set $do_redirect "true"; + } + + # Run our actual redirect... + 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; + } +}