├── .gitignore ├── root-playbook.yml ├── roles ├── django │ ├── handlers │ │ └── main.yml │ ├── templates │ │ ├── uwsgi.j2 │ │ └── local_settings.py │ └── tasks │ │ └── main.yml └── system │ ├── handlers │ └── main.yml │ ├── templates │ ├── supervisor.conf.j2 │ └── nginx.j2 │ └── tasks │ └── main.yml ├── hosts ├── Makefile ├── user-playbook.yml ├── group_vars └── project-hosts └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | roles/django/templates/id_rsa 3 | roles/django/templates/id_rsa.pub 4 | -------------------------------------------------------------------------------- /root-playbook.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: root-hosts 3 | sudo: true 4 | roles: 5 | - system 6 | -------------------------------------------------------------------------------- /roles/django/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart django 3 | supervisorctl: name={{ project_url }} state=restarted 4 | sudo: true 5 | -------------------------------------------------------------------------------- /roles/system/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: restart site 4 | supervisorctl: name={{ project_url }} state=restarted 5 | 6 | - name: restart mysql 7 | service: name=mysql state=restarted enabled=yes 8 | 9 | - name: restart nginx 10 | service: name=nginx state=restarted enabled=yes 11 | -------------------------------------------------------------------------------- /hosts: -------------------------------------------------------------------------------- 1 | [project-hosts] 2 | root ansible_ssh_host= ansible_ssh_user= ansible_ssh_pass= ansible_sudo_pass= 3 | user ansible_ssh_host= ansible_ssh_user= ansible_ssh_pass= 4 | 5 | [user-hosts] 6 | user 7 | 8 | [user-group:children] 9 | user-hosts 10 | 11 | [root-hosts] 12 | root 13 | 14 | [root-group:children] 15 | root-hosts 16 | 17 | 18 | -------------------------------------------------------------------------------- /roles/django/templates/uwsgi.j2: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | chdir = {{ project_homedir }} 3 | env = DJANGO_SETTINGS_MODULE={{ project_slug }}.settings 4 | socket = 127.0.0.1:{{ uwsgi_port }} 5 | module = {{ project_slug }}.wsgi:application 6 | master = True 7 | pidfile = {{ project_slug }}.pid 8 | home = {{ env }} 9 | vacuum = True 10 | plugins = python27 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ARCHIVE:="django_deploy.tar" 2 | CURRENT_DIR:=$(CURDIR) 3 | 4 | release: start deploy 5 | 6 | start: 7 | ansible-playbook -i ansible-django-deploy/hosts ansible-django-deploy/root-playbook.yml 8 | 9 | deploy: 10 | tar -cf /tmp/$(ARCHIVE) * 11 | ansible-playbook -i ansible-django-deploy/hosts ansible-django-deploy/user-playbook.yml 12 | rm -rf /tmp/$(ARCHIVE) 13 | -------------------------------------------------------------------------------- /user-playbook.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: user-hosts 3 | sudo: false 4 | roles: 5 | - django 6 | 7 | - hosts: root-hosts 8 | sudo: true 9 | tasks: 10 | - name: restart site in supervisor 11 | supervisorctl: name={{ project_url }} state=restarted 12 | 13 | - name: restart mysql 14 | service: name=mysql state=restarted enabled=yes 15 | 16 | - name: restart nginx 17 | service: name=nginx state=restarted enabled=yes 18 | -------------------------------------------------------------------------------- /roles/system/templates/supervisor.conf.j2: -------------------------------------------------------------------------------- 1 | [program:{{ project_url }}] 2 | user = {{ username }} 3 | command = /usr/bin/uwsgi --ini {{ project_dir }}/{{ project_slug }}/uwsgi.{{ project_slug }}.ini 4 | stdout_logfile = {{ project_dir }}/logs/supervisor.log 5 | stderr_logfile = {{ project_dir }}/logs/supervisor.log 6 | directory = {{ project_dir }}/{{ project_slug }} 7 | autostart = true 8 | autorestart = true 9 | redirect_stderr = true 10 | numprocs=1 11 | stopsignal = QUIT 12 | -------------------------------------------------------------------------------- /roles/django/templates/local_settings.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | import os 3 | 4 | DATABASES = { 5 | 'default': { 6 | 'ENGINE': 'django.db.backends.mysql', 7 | 'NAME': '{{ mysql_database }}', 8 | 'USER': '{{ mysql_user }}', 9 | 'PASSWORD': '{{ mysql_user_password }}', 10 | 'TEST': { 11 | 'CHARSET': 'utf8', 12 | 'COLLATION': 'utf8_unicode_ci', 13 | } 14 | } 15 | } 16 | 17 | DEBUG = {{ debug }} 18 | TEMPLATE_DEBUG = DEBUG 19 | 20 | STATIC_ROOT = os.path.abspath(os.path.join("{{ project_dir }}", "static")) 21 | MEDIA_ROOT = os.path.abspath(os.path.join("{{ project_dir }}", "media")) -------------------------------------------------------------------------------- /roles/system/templates/nginx.j2: -------------------------------------------------------------------------------- 1 | server { 2 | 3 | root {{ project_dir }}/{{ project_slug }}; 4 | 5 | access_log {{ project_dir }}/logs/nginx-access.log; 6 | error_log {{ project_dir }}/logs/nginx-errors.log; 7 | 8 | server_name {{ project_url }}; 9 | 10 | gzip on; 11 | gzip_min_length 1000; 12 | gzip_proxied expired no-cache no-store private auth; 13 | gzip_types text/plain application/xml; 14 | 15 | location / { 16 | include uwsgi_params; 17 | uwsgi_pass 127.0.0.1:{{ uwsgi_port }}; 18 | } 19 | 20 | location /static { 21 | root {{ project_dir }}; 22 | } 23 | 24 | location /media { 25 | root {{ project_dir }}; 26 | } 27 | 28 | location /robots.txt { 29 | root {{ project_dir }}; 30 | } 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /group_vars/project-hosts: -------------------------------------------------------------------------------- 1 | # 2 | # system options 3 | # 4 | 5 | # linux username 6 | username: 7 | 8 | # about password crypt 9 | # http://docs.ansible.com/faq.html#how-do-i-generate-crypted-passwords-for-the-user-module 10 | # or run `mkpasswd --method=SHA-512` 11 | # here crypted 12 | user_crypt_password: 13 | 14 | # really password 15 | user_password: z 16 | 17 | user_homedir: "/home/{{ username }}" 18 | 19 | mysql_root_user: root # root mysql user 20 | mysql_root_password: "" 21 | 22 | 23 | # 24 | # project options 25 | # 26 | 27 | # project slug ( if u have `example/manage.py` and example/example/settings.py` - `example` is project_slug) 28 | project_slug: 29 | 30 | # url or list urls for nginx 31 | project_url: 32 | 33 | project_dir: "{{ user_homedir }}/projects/{{ project_slug }}" 34 | 35 | project_homedir: "{{ user_homedir }}/projects/{{ project_slug }}/{{ project_slug }}" 36 | 37 | # virtualenv name 38 | env: "{{ project_dir }}/env" 39 | 40 | # port for uwsgi, must be unique for each project 41 | uwsgi_port: 9000 42 | 43 | # mysql database for current project 44 | mysql_database: "{{ project_slug }}" 45 | 46 | # mysql user for current project 47 | mysql_user: 48 | 49 | # mysql user password for current project 50 | mysql_user_password: 51 | 52 | # 53 | # django settings 54 | # 55 | 56 | debug: True 57 | local_settings: 'local_settings.py' 58 | 59 | # set empty string if not used 60 | requirements: 'requirements.txt' -------------------------------------------------------------------------------- /roles/django/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: create project directory 3 | file: path={{ project_dir }} state=directory 4 | 5 | - name: create logs directory 6 | file: path={{ project_dir }}/logs state=directory 7 | 8 | - name: create project home directory 9 | file: path={{ project_homedir }} state=directory 10 | 11 | - name: unarchive project archive 12 | unarchive: src=/tmp/django_deploy.tar dest={{ project_homedir }} 13 | 14 | - name: create virtualenv 15 | pip: virtualenv={{ env }} virtualenv_site_packages=yes {% if requirements %}requirements={{ project_homedir }}/{{ requirements }}{% endif %} 16 | 17 | - name: copy uwsg file 18 | template: src=uwsgi.j2 dest={{ project_homedir }}/uwsgi.{{ project_slug }}.ini 19 | 20 | - name: copy local_settings.py 21 | template: src=local_settings.py dest={{ project_homedir }}/{{ project_slug }}/{{ local_settings }} 22 | 23 | - name: syncdb (for django<1.7) 24 | django_manage: command=syncdb virtualenv={{ env }} app_path={{ project_homedir }} 25 | 26 | - name: migrate database 27 | django_manage: command=migrate virtualenv={{ env }} app_path={{ project_homedir }} 28 | 29 | - name: collectstatic 30 | django_manage: command=collectstatic virtualenv={{ env }} app_path={{ project_homedir }} 31 | 32 | - name: create media directory 33 | file: path={{ project_dir }}/media state=directory 34 | 35 | - name: create `uploads` directory 36 | file: path={{ project_dir }}/media/uploads state=directory -------------------------------------------------------------------------------- /roles/system/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: updating the system 4 | apt: update_cache=yes cache_valid_time=86400 5 | notify: 6 | - restart server 7 | 8 | - name: Add mariadb apt repository key 9 | apt_key: id=0xcbcb082a1bb943db keyserver=hkp://keyserver.ubuntu.com:80 state=present 10 | 11 | - name: Add mariadb apt repository 12 | apt_repository: repo='deb http://mirror.timeweb.ru/mariadb/repo/10.1/debian wheezy main' state=present 13 | 14 | - name: install packages 15 | apt: pkg={{ item.name }} state=present 16 | with_items: 17 | - name: python-mysqldb 18 | - name: python-virtualenv 19 | - name: python-pip 20 | - name: supervisor 21 | - name: mariadb-server 22 | - name: nginx 23 | - name: uwsgi 24 | - name: uwsgi-plugin-python 25 | 26 | - name: copy supervisor config 27 | template: src=supervisor.conf.j2 dest=/etc/supervisor/conf.d/{{ project_url }}.conf 28 | notify: 29 | - restart site 30 | 31 | - name: create linux user 32 | user: name={{ username }} shell=/bin/bash home={{ user_homedir }} password={{ user_crypt_password }} 33 | 34 | - name: Create MySQL user 35 | mysql_user: > 36 | name={{ mysql_user }} 37 | host=% 38 | password={{ mysql_user_password }} 39 | priv={{ mysql_database }}.*:ALL 40 | login_user={{ mysql_root_user }} 41 | login_password={{ mysql_root_password }} 42 | state=present 43 | notify: 44 | - restart mysql 45 | 46 | # create database 47 | - name: Create MySQL database 48 | mysql_db: > 49 | name={{ mysql_database }} 50 | collation=utf8_general_ci 51 | encoding=utf8 52 | login_user={{ mysql_root_user }} 53 | login_password={{ mysql_root_password }} 54 | state=present 55 | notify: 56 | - restart mysql 57 | 58 | - name: copy nginx config 59 | template: src=nginx.j2 dest=/etc/nginx/sites-available/{{ project_url }} 60 | notify: 61 | - restart nginx 62 | 63 | - name: create symlink nginx config 64 | file: src=/etc/nginx/sites-available/{{ project_url }} dest=/etc/nginx/sites-enabled/{{ project_url }} state=link -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Django deploying scripts 2 | ======================== 3 | 4 | Library or simple deploying django-projects 5 | 6 | What we have: 7 | django project at local machine with structure: 8 | 9 | example/ 10 | manage.py 11 | example/ 12 | settings.py 13 | # etc 14 | # etc 15 | 16 | And we need to deploy this project for remote host 192.168.0.100 17 | with creating new user `hostuser` (optionally) at ubuntu 14.04 (not tested at another versions) 18 | 19 | Usage 20 | ----- 21 | 22 | 1. install [ansible](http://docs.ansible.com/intro_installation.html) 23 | 2. clone repository to your django `example` project: 24 | ``` 25 | git clone git@github.com:freylis/ansible-django-deploy.git 26 | ``` 27 | 28 | 3. Copy `Makefile` to you root project directory 29 | ``` 30 | cp django-deploy/Makefile . 31 | ``` 32 | 33 | 4. configure `django-deploy/hosts` file: 34 | ``` 35 | # usually YOU_USER_PASSWORD = YOU_SUDO_USER_PASSWORD 36 | root ansible_ssh_host=192.168.0.100 ansible_ssh_user=YOUR_SUDO_USERNAME ansible_ssh_pass=YOU_USER_PASSWORD ansible_sudo_pass=YOU_SUDO_USER_PASSWORD 37 | user ansible_ssh_host=192.168.0.100 ansible_ssh_user=YOU_USER_FOR_PROJECT ansible_ssh_pass=USER_FOR_PROJECT_PASSWORD 38 | ``` 39 | 40 | 5. configure `django-deploy/group_vars/project-hosts` file 41 | ``` 42 | # 43 | # system options 44 | # 45 | 46 | # linux username 47 | username: 48 | 49 | # how to crypt your password: 50 | # http://docs.ansible.com/faq.html#how-do-i-generate-crypted-passwords-for-the-user-module 51 | # or run `mkpasswd --method=SHA-512` 52 | # here crypted password 53 | user_crypt_password: 54 | 55 | # really password 56 | user_password: z 57 | 58 | user_homedir: "/home/{{ username }}" 59 | 60 | mysql_root_user: root # root mysql user 61 | mysql_root_password: "" 62 | 63 | 64 | # 65 | # project options 66 | # 67 | 68 | # project slug ( if u have `example/manage.py` and example/example/settings.py` - `example` is project_slug) 69 | project_slug: 70 | 71 | # url or list urls for nginx 72 | project_url: 73 | 74 | project_dir: "{{ user_homedir }}/projects/{{ project_slug }}" 75 | 76 | project_homedir: "{{ user_homedir }}/projects/{{ project_slug }}/{{ project_slug }}" 77 | 78 | # virtualenv name 79 | env: "{{ project_dir }}/env" 80 | 81 | # port for uwsgi, must be unique for each project 82 | uwsgi_port: 9000 83 | 84 | # mysql database for current project 85 | mysql_database: "{{ project_slug }}" 86 | 87 | # mysql user for current project 88 | mysql_user: 89 | 90 | # mysql user password for current project 91 | mysql_user_password: 92 | 93 | # 94 | # django settings 95 | # 96 | 97 | debug: True 98 | local_settings: 'local_settings.py' 99 | 100 | # set empty string if not used 101 | requirements: 'requirements.txt' 102 | ``` 103 | 104 | 6. By SSH go to remote host. In this step you need only press `yes` when system ask you about known_hosts file 105 | 106 | 7. run deployment script: 107 | ``` 108 | # if you system is empty, and you need to install all system packages (can run only first time) 109 | make release 110 | 111 | # if all packages already installed and you need only deploying project changes to host machine 112 | make deploy 113 | ``` 114 | 115 | Its all! 116 | go to you `project_url` and smile :] 117 | 118 | If domain not ready - add record about domain to your `/etc/hosts` file 119 | --------------------------------------------------------------------------------