Skip to content

Commit 2ca36fe

Browse files
committed
Moving deployment and configuration scripts over to ansible, and general updates
1 parent c274235 commit 2ca36fe

File tree

19 files changed

+300
-78
lines changed

19 files changed

+300
-78
lines changed

README.textile

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
This is just the skeleton that I use for easilly starting a new project.
3+

buildout.cfg

+4-10
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,16 @@ eggs =
2121
# The versions below are as example only, please change these to use
2222
# latest versions of packages you require
2323
[versions]
24-
pillow = 1.7.5
25-
django = 1.4.3
26-
gunicorn = 0.16.1
24+
pillow = 2.6.1
25+
django = 1.7.1
26+
gunicorn = 19.1.1
27+
psycopg2 = 2.5.4
2728

2829

2930
[sources]
3031
# Sources from repos here. See mr.developer documentation
3132

3233

33-
[logs]
34-
access_log = ${buildout:directory}/log/access.log
35-
instance_log = ${buildout:directory}/log/instance.log
36-
error_log = ${buildout:directory}/log/error.log
37-
supervisor_log = ${buildout:directory/log/supervisor.log
38-
39-
4034
[python]
4135
recipe = zc.recipe.egg
4236
interpreter = python

fabfile/__init__.py

-2
This file was deleted.

fabfile/production.py

-38
This file was deleted.

playbooks/production

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[local]
2+
localhost ansible_connection=local
3+
4+
[webservers]
5+
# Webservers here
6+
7+
[webservers:vars]
8+
git_branch = production
9+
server_name = www.example.com
10+
listen_port =
11+
user_home = /home/{{ ansible_ssh_user }}
12+
webapp_name = <your_django_app_name>
13+
webapp_user = <app_username>
14+
webapp_dir = {{ user_home }}/webapps/{{ webapp_name }}
15+
webapp_socketfile = {{ webapp_dir }}/bin/{{ webapp_name }}.sock
16+
webapp_logs = {{ webapp_dir }}/log
17+
webapp_media = {{ webapp_dir }}/cdn

playbooks/roles/python/tasks/main.yml

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# A clean webfaction server wont have pip installed. This role will take care
2+
# of this. currently I'm using python 2.7, but I may in future use 3.x
3+
---
4+
- name: Ensure the local python packages dir exists
5+
file: path=~/lib/python2.7 state=directory
6+
7+
- name: Install pip
8+
easy_install: executable=easy_install-2.7 name=pip
+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Set up supervisor on the webfaction server and prepares the default
2+
# configuration.
3+
---
4+
- name: Check that required supervisor directories exist
5+
file: path={{ item }} state=directory
6+
with_items:
7+
- ~/local/etc/supervisord
8+
- ~/log/supervisord
9+
10+
# Supervisor expects config to be located in ~/etc,
11+
# but we will keep it in ~/local/etc, for this reason we will symlink to the
12+
# correct place
13+
- name: Create symlink to correct config location
14+
file: path=~/etc
15+
src=~/local/etc
16+
state=link
17+
18+
- name: Install supervisor
19+
pip: name=supervisor state=present
20+
executable={{ user_home }}/bin/pip2.7
21+
extra_args="--user"
22+
23+
- name: Create shell script that checks that supervisord is running
24+
template: src=check_supervisord.sh.j2
25+
dest={{ user_home }}/bin/check_supervisord.sh
26+
mode=0744
27+
28+
- name: Create base superivord config
29+
template: src=supervisord.conf.j2
30+
dest=~/local/etc/supervisord.conf
31+
mode=0644
32+
33+
# Set up supervisor cron jobs
34+
- name: Cron to check if supervisor is running at reboot
35+
cron: name="start supervisor at boot" special_time=reboot
36+
job="/home/{{ username }}/bin/check_supervisor.sh"
37+
38+
- name: Cron to check that supervisor is running every minute
39+
cron: name="is supervisor running"
40+
job="/home/{{ username }}/bin/check_supervisor.sh"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/sh
2+
3+
if ps -u {{ ansible_ssh_user }} | grep -E 'supervisord$' > /dev/null; then
4+
echo "supervisord is running."
5+
else
6+
echo "starting supervisord."
7+
{{ user_home }}/bin/supervisord
8+
{{ user_home }}/bin/supervisorctl start all
9+
fi
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[unix_http_server]
2+
file={{ user_home }}/tmp/supervisor.sock
3+
4+
[supervisord]
5+
logfile={{ user_home }}/log/supervisord/supervisord.log
6+
logfile_maxbytes=50MB
7+
logfile_backups=10
8+
loglevel=info
9+
pidfile={{ user_home }}/tmp/supervisord.pid
10+
11+
[rpcinterface:supervisor]
12+
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
13+
14+
[supervisorctl]
15+
serverurl=unix://{{ user_home }}/tmp/supervisor.sock
16+
17+
[include]
18+
files = {{ user_home }}/local/etc/supervisord/*.ini
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
- name: Reload supervisord
3+
supervisorctl: name={{ item }}
4+
state=present
5+
supervisorctl_path={{ user_dir }}/bin/supervisorctl
6+
with_items:
7+
- "{{ app_name }}"
8+
- nginx
9+
10+
- name: Restart webapp
11+
supervisorctl: name={{ app_name }} state=restarted
12+
supervisorctl_path={{ user_dir }}/bin/supervisorctl
13+
tags: restart_webapp
14+
15+
- name: Restart nginx
16+
supervisorctl: name=nginx state=restarted
17+
supervisorctl_path={{ user_dir }}/bin/supervisorctl
18+
tags: restart_nginx
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Our webfaction tasks are mainly used to set up some final links between
2+
# supervisor, nginx, and our future webapp.
3+
# As a side note; I'm not convinced these tasks belong here, and will
4+
# probably move them sometime in the future.
5+
---
6+
- name: Make sure log directory exists
7+
file: path=~/log state="directory"
8+
9+
- name: Create the nginx supervisor config
10+
template: src=nginx_supervisor.ini.j2
11+
dest=~/local/etc/supervisord/nginx.ini
12+
notify:
13+
- Reload supervisord
14+
- Restart nginx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[program:nginx]
2+
command = {{ user_home }}/local/sbin/nginx
3+
user = {{ username }}
4+
stdout_logfile = {{ user_home }}/log/nginx_out.log
5+
stderr_logfile = {{ user_home }}/log/nginx_err.log
6+
autostart = true
7+
autorestart = true
8+
redirect_stderr = true
9+
exitcodes = 0
+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
---
2+
# I prefer that my hosts are unaware of the code repo, and for that reason
3+
# I don't pull code from a remote git repo, but rather archive it, and
4+
# extract the archive on the remote.
5+
- name: Create latest code archive
6+
local_action: shell cd "../" &&
7+
git archive --format=tar {{ git_branch }} | gzip >{{ webapp_name }}-{{ git_branch }}.tar.gz
8+
9+
10+
- name: Extract archive on remote
11+
unarchive: src=../{{ webapp_name }}-{{ git_branch }}.tar.gz dest={{ webapp_dir }}/
12+
13+
14+
# We may not always want to run bootstrap, but the method below with never
15+
# run again after it was first bootstrapped. We may do something about this
16+
# in future. Maybe a variable or flag to force bootstrap to run?
17+
- name: Bootstrap webapp
18+
command: python2.7 -S bootstrap.py
19+
args:
20+
chdir: "{{ webapp_dir }}"
21+
creates: "{{ webapp_dir }}/bin/buildout"
22+
23+
24+
- name: Run buildout and install dependencies
25+
command: bin/buildout
26+
args:
27+
chdir: "{{ webapp_dir }}"
28+
tags: run_buildout
29+
30+
31+
- name: Collect django app static media
32+
command: bin/{{ webapp_name }} collectstatic --noinput
33+
args:
34+
chdir: "{{ webapp_dir }}"
35+
36+
37+
- name: Create database tables
38+
command: bin/{{ webapp_name }} syncdb --noinput
39+
args:
40+
chdir: "{{ webapp_dir }}"
41+
42+
43+
- name: Migrate database
44+
command: bin/{{ webapp_name }} migrate
45+
args:
46+
chdir: "{{ webapp_dir }}"
47+
notify:
48+
- Restart webapp
49+
50+
51+
- name: Create webapp nginx config
52+
template: src=nginx.conf.j2
53+
dest=~/local/nginx/sites-enabled/{{ webapp_name }}.conf
54+
mode=0644
55+
notify:
56+
- Restart nginx
57+
58+
59+
- name: Create supervisor config for our webapp
60+
template: src=webapp_supervisor.ini.j2
61+
dest=~/local/etc/supervisord/{{ webapp_name }}.ini
62+
mode=0644
63+
notify:
64+
- Reload supervisord
65+
- Restart webapp
66+
67+
68+
## Set up our cron jobs
69+
# The examples here is because I normally use django mailer as a simple
70+
# mail Queue
71+
# - name: <your_app_name> - Send mail cron job
72+
# cron: name="send mail"
73+
# job="{{ webapp_dir }}/bin/{{ webapp_name }} send_mail >> {{ webapp_logs }}/cron_mail.log 2>&1"
74+
75+
# - name: <your_app_name> - Retry mail cron job
76+
# cron: name="retry deferred mail" minute="0,20,40"
77+
# job="{{ webapp_dir }}/bin/{{ webapp_name }} retry_deferred >> {{ webapp_logs }}/cron_mail_deferred.log 2>&1"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
2+
server {
3+
server_name {{ server_name }};
4+
listen {{ listen_port }};
5+
access_log {{ webapp_logs }}/access.log;
6+
error_log {{ webapp_logs }}/error.log;
7+
8+
location ^~ /media/ {
9+
root {{ webapp_media }};
10+
expires 31d;
11+
}
12+
13+
location ^~ /static/ {
14+
root {{ webapp_media }};
15+
expires 31d;
16+
}
17+
18+
# Enable if you want to use Gunicorn
19+
location / {
20+
proxy_pass http://unix:{{ webapp_socketfile }}:;
21+
proxy_pass_header Server;
22+
proxy_set_header Host $http_host;
23+
proxy_redirect off;
24+
25+
proxy_connect_timeout 600;
26+
proxy_send_timeout 600;
27+
proxy_read_timeout 600;
28+
send_timeout 600;
29+
30+
proxy_set_header X-Scheme $scheme;
31+
proxy_set_header X-Real-IP $remote_addr;
32+
proxy_set_header X-Forwarded-For $remote_addr;
33+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
34+
proxy_set_header X-Forwarded-Protocol ssl;
35+
set_real_ip_from 127.0.0.1;
36+
real_ip_header X-Forwarded-For;
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[program:{{ webapp_name }}]
2+
command = {{ webapp_dir }}/bin/{{ webapp_name }} run_gunicorn
3+
-u {{ webapp_user }}
4+
-w 4
5+
-b unix:{{ webapp_socketfile }}
6+
--log-file={{ webapp_logs }}/{{ webapp_name }}.instance.log
7+
user = {{ webapp_user }}
8+
stdout_logfile = {{ webapp_logs }}/supervisor.log
9+
autostart = true
10+
autorestart = true
11+
redirect_stderr = true

playbooks/server.yml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
# This playbook only sets up a new webfaction server with specific dependencies
3+
# which is used in other playbooks, and any other requirements for my django
4+
# apps to run.
5+
- hosts: webservers
6+
gather_facts: False
7+
roles:
8+
- python
9+
- supervisor
10+
- nginx

playbooks/site.yml

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# This playbook will manage the website on the webfaction
2+
---
3+
- hosts: webservers
4+
gather_facts: False
5+
roles:
6+
- webfaction
7+
- website

playbooks/staging

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[local]
2+
localhost ansible_connection=local
3+
4+
[webservers]
5+
# Webservers here
6+
7+
[webservers:vars]
8+
git_branch = staging
9+
server_name = www.example.com
10+
listen_port =
11+
user_home = /home/{{ ansible_ssh_user }}
12+
webapp_name = <your_django_app_name>
13+
webapp_user = <app_username>
14+
webapp_dir = {{ user_home }}/webapps/{{ webapp_name }}
15+
webapp_socketfile = {{ webapp_dir }}/bin/{{ webapp_name }}.sock
16+
webapp_logs = {{ webapp_dir }}/log
17+
webapp_media = {{ webapp_dir }}/cdn

0 commit comments

Comments
 (0)