├── .github_token.sample ├── .gitignore ├── README.md ├── ansible.cfg ├── hosts.example ├── roles ├── access │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── authorized_keys.sample ├── celery │ └── tasks │ │ └── main.yml ├── common-python │ └── tasks │ │ └── main.yml ├── common │ └── tasks │ │ └── main.yml ├── customize │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── local_settings.py.j2 ├── django │ └── tasks │ │ └── main.yml ├── letsencrypt │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── nginx.conf ├── nginx │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── nginx.conf ├── postgres │ └── tasks │ │ └── main.yml ├── prerequisites │ └── tasks │ │ └── main.yml ├── rabbitmq │ └── tasks │ │ └── main.yml ├── supervisor │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── supervisord.conf ├── uwsgi │ ├── tasks │ │ └── main.yml │ └── templates │ │ └── uwsgi.ini └── virtualenv │ └── tasks │ └── main.yml ├── server.yml └── vars └── external_vars.yml.sample /.github_token.sample: -------------------------------------------------------------------------------- 1 | YOUR_GITHUB_ACCESS_TOKEN 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | hosts 2 | vars/external_vars.yml 3 | vars/backups/ 4 | roles/prerequisites/templates/authorized_keys 5 | .github_token 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ansible Playbook for Django on Ubuntu 2 | 3 | ## Overview 4 | 5 | This is an Ansible playbook that sets up a Ubuntu 14.04 machine as a server for a Django project. It is primarily built for a typical AWS or Digital Ocean server. 6 | 7 | * PostgreSQL as the database 8 | * nginx & uWSGI to serve the Django site 9 | * Supervisor to daemonize uWSGI 10 | 11 | ## Prerequisites 12 | 13 | * Set up a AWS or Digital Ocean server 14 | * Add all needed SSH keys to the server 15 | * Add the server IP address to 16 | * the ansible hosts file `hosts` 17 | * and the variables: file `vars/external_var.yaml` 18 | 19 | #### Let's Encrypt 20 | 21 | You'll have to change the A-records of your domain before running the letsencrypt roles. Otherwise letsencrypt is not able to verify your site. 22 | 23 | #### Github 24 | 25 | If you're cloning a Github repository, make sure to add your access token to the ``.github_token`` file. 26 | 27 | ## Usage 28 | 29 | Install Ansible: http://docs.ansible.com/ansible/intro_installation.html#installation 30 | 31 | Create your `vars/external_vars.yml` file and generate all necessary passwords and variables. 32 | 33 | Run the ansible-playbook script: 34 | 35 | ansible-playbook -i hosts server.yml 36 | 37 | If you want to start over beginning at another task, use: 38 | 39 | ansible-playbook -i hosts server.yml --start-at-task="task name" 40 | -------------------------------------------------------------------------------- /ansible.cfg: -------------------------------------------------------------------------------- 1 | [ssh_connection] 2 | control_path = %(directory)s/%%h-%%r 3 | 4 | -------------------------------------------------------------------------------- /hosts.example: -------------------------------------------------------------------------------- 1 | [ubuntu-server] 2 | 123.123.123.123 or ssh alias 3 | -------------------------------------------------------------------------------- /roles/access/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: prerequisites - add authorized_keys 3 | template: src=authorized_keys dest=~/.ssh/ 4 | 5 | - name: prerequisites - chmod authorized_keys 6 | raw: chmod 600 ~/.ssh/authorized_keys && chmod 700 ~/.ssh 7 | -------------------------------------------------------------------------------- /roles/access/templates/authorized_keys.sample: -------------------------------------------------------------------------------- 1 | ssh-rsa YOURKEY yourname@example.com 2 | -------------------------------------------------------------------------------- /roles/celery/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: celery - install 3 | sudo: yes 4 | pip: name=celery 5 | -------------------------------------------------------------------------------- /roles/common-python/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: common-python - link python 2 3 | sudo: yes 4 | file: 5 | src: /usr/bin/python2.7 6 | dest: /usr/bin/python 7 | state: link 8 | 9 | - name: common-python - install global packages 10 | sudo: yes 11 | pip: name={{ item.name }} 12 | with_items: 13 | - { name: ipython, version: 5.3.0 } 14 | - { name: psycopg2 } 15 | - { name: python-memcached } 16 | 17 | - name: common-python - update distutils 18 | sudo: yes 19 | raw: easy_install distribute 20 | -------------------------------------------------------------------------------- /roles/common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: common - install packages 3 | sudo: yes 4 | apt: pkg={{ item }} update_cache=yes state=latest cache_valid_time=4320 5 | with_items: 6 | - curl 7 | - g++ 8 | - gettext 9 | - git-core 10 | - libsqlite3-dev 11 | - build-essential 12 | - libssl-dev 13 | - libffi-dev 14 | - make 15 | - mercurial 16 | - python-dev 17 | - sqlite3 18 | - vim 19 | - libjpeg-dev 20 | -------------------------------------------------------------------------------- /roles/customize/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: customize - add local settings 3 | template: 4 | src: local_settings.py.j2 5 | dest: "{{ server_project_local_settings }}" 6 | -------------------------------------------------------------------------------- /roles/customize/templates/local_settings.py.j2: -------------------------------------------------------------------------------- 1 | """ 2 | Local settings for the project {{ django_project_name }}. 3 | Taken from: https://github.com/bitlabstudio/django-project-template/ 4 | 5 | """ 6 | import os 7 | 8 | from .base_settings import DJANGO_PROJECT_ROOT 9 | 10 | 11 | DEBUG = True 12 | SANDBOX = True 13 | DEFAULT_HTTP_PROTOCOL = 'http' 14 | DISABLED_APPS = [] 15 | 16 | # Set this to false on PROD / works with `grunt watch` on local development. 17 | LIVERELOAD = True 18 | 19 | # Enable/disable django compressor 20 | LOCAL_COMPRESS_ENABLED = False 21 | 22 | # For local development 23 | ADMIN_URL = 'admin/' 24 | 25 | # For your server 26 | # ADMIN_URL = 'admin-XXXX/' 27 | 28 | # Used for fabfile 29 | # PEM_KEY_DIR = '~/.ssh/{{ django_project_name }}.pem' 30 | 31 | # Needed by debug_toolbar. Set it to None to disable the toolbar. 32 | INTERNAL_IPS = None 33 | # INTERNAL_IPS = ('127.0.0.1',) 34 | 35 | ADMINS = ( 36 | ('{{ django_project_name }}', 'info@{{ domain }}'), 37 | ) 38 | 39 | MANAGERS = ADMINS 40 | 41 | # First create your DB role like so: 42 | # > psql (connect as superuser) 43 | # > create database {{ django_project_name }}; 44 | # > create user {{ django_project_name }} with password '{{ django_project_name }}'; 45 | # > grant all privileges on database {{ django_project_name }} to {{ django_project_name }}; 46 | 47 | # if you want to use geodjango: 48 | # > \connect {{ django_project_name }}; 49 | # > create extension postgis; 50 | DATABASES = { 51 | 'default': { 52 | 'ENGINE': 'django.db.backends.postgresql_psycopg2', 53 | 'NAME': '{{ postgres_db_name }}', 54 | 'USER': '{{ postgres_user }}', 55 | 'PASSWORD': '{{ postgres_pw }}', 56 | 'HOST': '{{ postgres_host }}', 57 | 'PORT': '{{ postgres_port }}', 58 | } 59 | } 60 | 61 | # Set this to your OS username if you are working with Postgres.app on OSX 62 | # LOCAL_PG_ADMIN_ROLE = 'username' 63 | 64 | # Hosts/domain names that are valid for this site; required if DEBUG is False 65 | # See https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts 66 | 67 | # On your server, it should look like this: 68 | ALLOWED_HOSTS = ['{{ ip }}', '{{ domain }}', 'www.{{ domain }}'] 69 | 70 | # Absolute filesystem path to the directory that will hold user-uploaded files. 71 | # Example: "/var/www/example.com/media/" 72 | MEDIA_ROOT = '/home/{{ user }}/project_assets/media/' 73 | 74 | # Absolute path to the directory static files should be collected to. 75 | # Don't put anything in this directory yourself; store your static files 76 | # in apps' "static/" subdirectories and in STATICFILES_DIRS. 77 | # Example: "/var/www/example.com/static/" 78 | STATIC_ROOT = '/home/{{ user }}/project_assets/static/' 79 | 80 | # Make this unique, and don't share it with anybody. 81 | SECRET_KEY = 'http://www.miniwebtool.com/django-secret-key-generator/' 82 | 83 | 84 | EMAIL_BACKEND = 'mailer.backend.DbBackend' 85 | # ================================ 86 | # Local Development Email Settings 87 | # ================================ 88 | # MAILER_EMAIL_BACKEND = 'django_libs.test_email_backend.EmailBackend' 89 | # TEST_EMAIL_BACKEND_RECIPIENTS = ADMINS 90 | 91 | # FROM_EMAIL = ADMINS[0][1] 92 | # EMAIL_SUBJECT_PREFIX = '[dev {{ django_project_name }}] ' 93 | 94 | # EMAIL_HOST = 'smtp.gmail.com' 95 | # EMAIL_HOST_USER = FROM_EMAIL 96 | # EMAIL_HOST_PASSWORD = "yourpassword" 97 | # EMAIL_PORT = 587 98 | 99 | 100 | # ========================== 101 | # Email Server Settings 102 | # ========================== 103 | FROM_EMAIL = "noreply@{{ domain }}" 104 | EMAIL_SUBJECT_PREFIX = '[{{ django_project_name }}] ' 105 | 106 | EMAIL_HOST = 'smtp.example.com' 107 | EMAIL_HOST_USER = "{{ django_project_name }}" 108 | EMAIL_HOST_PASSWORD = "yourpassword" 109 | EMAIL_PORT = 25 110 | 111 | 112 | # =========================== 113 | # More general email settings 114 | # =========================== 115 | DEFAULT_FROM_EMAIL = FROM_EMAIL 116 | SERVER_EMAIL = FROM_EMAIL 117 | EMAIL_USE_TLS = True 118 | -------------------------------------------------------------------------------- /roles/django/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: django - create folders 3 | shell: mkdir -p backups etc log project project_assets/media project_assets/static src 4 | 5 | - name: django - clone project 6 | git: repo={{ git_repo }} 7 | dest=/home/{{ user }}/src/{{ django_project_name }} 8 | accept_hostkey=yes 9 | 10 | - name: django - update submodules 11 | shell: git submodule init && git submodule update 12 | args: 13 | chdir: "{{ server_git_repo }}" 14 | 15 | - name: django - create project venv 16 | shell: source ~/.bash_profile && mkvirtualenv {{ venv_name }} 17 | args: 18 | executable: /bin/bash 19 | 20 | - name: django - install project venv 21 | shell: source ~/.bash_profile && workon {{ venv_name }} && pip install -r {{ server_requirements_txt }} 22 | args: 23 | executable: /bin/bash 24 | 25 | - name: django - rsync cloned repo into destination 26 | shell: rsync -avz --stats --delete {{ server_git_project_root }}/ {{ server_project_folder }} 27 | -------------------------------------------------------------------------------- /roles/letsencrypt/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: letsencrypt - prepare 3 | sudo: yes 4 | apt: 5 | name: software-properties-common 6 | update_cache: yes 7 | 8 | - name: letsencrypt - add certbot repository 9 | sudo: yes 10 | raw: add-apt-repository ppa:certbot/certbot 11 | 12 | - name: letsencrypt - install certbot 13 | sudo: yes 14 | apt: 15 | name: python-certbot-nginx 16 | update_cache: yes 17 | 18 | - name: letsencrypt - create folders 19 | shell: mkdir -p /home/{{ user }}/letsencrypt 20 | 21 | - name: letsencrypt - get cert 22 | shell: certbot --nginx certonly -w /home/{{ user }}/letsencrypt --agree-tos -n -d {{ domain }} -d www.{{ domain }} --email={{ email }} 23 | sudo: yes 24 | 25 | - name: letsencrypt - create DH group 26 | shell: openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048 27 | sudo: yes 28 | 29 | - name: letsencrypt - cron cert renewal 30 | cron: 31 | name: "renew cert" 32 | minute: "30" 33 | hour: "2" 34 | weekday: "1" 35 | job: "certbot renew >> /var/log/le-renew.log" 36 | 37 | - name: letsencrypt - update nginx conf 38 | sudo: yes 39 | template: src=nginx.conf dest=/etc/nginx/sites-enabled/{{ django_project_name }} 40 | 41 | 42 | - name: letsencrypt - nginx restart 43 | sudo: yes 44 | shell: service nginx restart 45 | -------------------------------------------------------------------------------- /roles/letsencrypt/templates/nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name {{ domain }} {{ domain }}; 4 | root /home/{{ user }}/letsencrypt; 5 | 6 | location / { 7 | rewrite ^ https://{{ domain }}$request_uri? permanent; 8 | } 9 | 10 | location ~ /.well-known { 11 | allow all; 12 | } 13 | } 14 | 15 | server { 16 | listen 443 ssl; 17 | server_name {{ ip }} {{ domain }} {{ domain }}; 18 | root /home/{{ user }}/project_assets; 19 | 20 | ssl on; 21 | ssl_certificate_key /etc/letsencrypt/live/{{ domain }}/privkey.pem; 22 | ssl_certificate /etc/letsencrypt/live/{{ domain }}/fullchain.pem; 23 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 24 | ssl_prefer_server_ciphers on; 25 | ssl_dhparam /etc/ssl/certs/dhparam.pem; 26 | ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; 27 | ssl_session_timeout 1d; 28 | ssl_session_cache shared:SSL:50m; 29 | ssl_stapling on; 30 | ssl_stapling_verify on; 31 | add_header Strict-Transport-Security max-age=15768000; 32 | 33 | error_log /var/log/nginx/{{ django_project_name }}.error.log; 34 | access_log /var/log/nginx/{{ django_project_name }}.access.log; 35 | 36 | gzip on; 37 | gzip_static on; 38 | gzip_disable 'msie6'; 39 | gzip_types text/plain text/css text/javascript; 40 | client_max_body_size 150M; 41 | 42 | 43 | location /static/ { 44 | expires 1y; 45 | add_header Cache-Control public; 46 | add_header ETag ""; 47 | break; 48 | } 49 | 50 | location /media/ { 51 | expires 1y; 52 | add_header Cache-Control public; 53 | add_header ETag ""; 54 | break; 55 | } 56 | 57 | location / { 58 | uwsgi_read_timeout 6000; 59 | uwsgi_send_timeout 6000; 60 | include uwsgi_params; 61 | uwsgi_pass 127.0.0.1:8889; 62 | } 63 | error_page 500 502 503 504 /static/50x.html; 64 | } 65 | -------------------------------------------------------------------------------- /roles/nginx/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: nginx - install 3 | sudo: yes 4 | apt: name=nginx 5 | 6 | - name: nginx - upload nginx conf 7 | sudo: yes 8 | template: src=nginx.conf dest=/etc/nginx/sites-enabled/{{ django_project_name }} 9 | 10 | - name: nginx - restart 11 | sudo: yes 12 | shell: service nginx restart 13 | -------------------------------------------------------------------------------- /roles/nginx/templates/nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name {{ domain }} www.{{ domain }}; 4 | root /home/{{ user }}/letsencrypt; 5 | 6 | location / { 7 | rewrite ^ https://{{ domain }}$request_uri? permanent; 8 | } 9 | 10 | location ~ /.well-known { 11 | allow all; 12 | } 13 | } 14 | 15 | server { 16 | listen 443 ssl; 17 | server_name {{ ip }} {{ domain }} www.{{ domain }}; 18 | root /home/{{ user }}/project_assets; 19 | 20 | error_log /var/log/nginx/{{ django_project_name }}.error.log; 21 | access_log /var/log/nginx/{{ django_project_name }}.access.log; 22 | 23 | gzip on; 24 | gzip_static on; 25 | gzip_disable 'msie6'; 26 | gzip_types text/plain text/css text/javascript; 27 | client_max_body_size 150M; 28 | 29 | 30 | location /static/ { 31 | expires 1y; 32 | add_header Cache-Control public; 33 | add_header ETag ""; 34 | break; 35 | } 36 | 37 | location /media/ { 38 | expires 1y; 39 | add_header Cache-Control public; 40 | add_header ETag ""; 41 | break; 42 | } 43 | 44 | location / { 45 | uwsgi_read_timeout 6000; 46 | uwsgi_send_timeout 6000; 47 | include uwsgi_params; 48 | uwsgi_pass 127.0.0.1:8889; 49 | } 50 | error_page 500 502 503 504 /static/50x.html; 51 | } 52 | -------------------------------------------------------------------------------- /roles/postgres/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: postgres - create folders 3 | shell: mkdir -p backups/{{ django_project_name }}/postgres 4 | 5 | - name: postgres - add postgres to sources.list 6 | sudo: yes 7 | lineinfile: create=yes dest=/etc/apt/sources.list.d/pgdg.list line='deb http://apt.postgresql.org/pub/repos/apt trusty-pgdg main' 8 | 9 | - name: postgres - add postgres repository key 10 | sudo: yes 11 | raw: wget --quiet -O - http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc | sudo apt-key add - 12 | 13 | - name: postgres - install packages 14 | sudo: yes 15 | apt: pkg={{ item }} update_cache=yes state=latest 16 | with_items: 17 | - postgresql-client-common 18 | - postgresql-client-9.5 19 | - python-psycopg2 20 | - libpq-dev 21 | 22 | - name: postgres - install server packages 23 | sudo: yes 24 | apt: pkg={{ item }} update_cache=yes state=latest 25 | with_items: 26 | - postgresql-9.4 27 | - postgresql-contrib 28 | - postgresql-server-dev-9.4 29 | - postgresql-9.4-postgis-2.1 30 | - pgadmin3 31 | when: postgres_local == "yes" 32 | 33 | - name: postgres - change admin password 34 | sudo: yes 35 | raw: sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD '{{ postgres_pw }}';" 36 | when: postgres_local == "yes" 37 | 38 | - name: postgres - create postgres user 39 | sudo_user: postgres 40 | sudo: yes 41 | postgresql_user: name={{ postgres_user }} 42 | role_attr_flags=SUPERUSER 43 | password={{ postgres_pw }} 44 | when: postgres_local == "yes" 45 | 46 | - name: postgres - create project db 47 | sudo_user: postgres 48 | sudo: yes 49 | postgresql_db: name={{ postgres_db_name }} 50 | encoding='UTF-8' 51 | owner='{{ postgres_user }}' 52 | when: postgres_local == "yes" 53 | 54 | - name: postgres - create pgpass 55 | lineinfile: create=yes dest=~/.pgpass line="{{ postgres_host }}:*:{{ postgres_db_name }}:{{ postgres_user }}:{{ postgres_pw }}" 56 | 57 | - name: postgres - create chmod .pgpass 58 | raw: chmod 600 ~/.pgpass 59 | 60 | - name: postgres - create postgis extension 61 | raw: psql -U {{ postgres_user }} -d {{ postgres_db_name }} -c "CREATE EXTENSION postgis" -h localhost 62 | when: (postgres_local == "yes" and postgres_postgis == "yes") 63 | -------------------------------------------------------------------------------- /roles/prerequisites/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: prerequisites - update locale 3 | sudo: yes 4 | raw: locale-gen en_US.UTF-8 && update-locale LANG=en_US.UTF-8 5 | 6 | - name: prerequisites - make ssh folder 7 | raw: mkdir -p ~/.ssh 8 | 9 | - name: prerequisites - create ssh key 10 | user: 11 | name: "{{ user }}" 12 | generate_ssh_key: yes 13 | 14 | - name: prerequisites - register ssh key 15 | shell: cat ~/.ssh/id_rsa.pub 16 | register: ssh_key 17 | 18 | - name: prerequisites - add deploy key 19 | shell: "curl -u {{ github_user }}:{{ lookup('file', '.github_token') }} -d '{\"title\": \"ubuntu\", \"key\": \"{{ item }}\", \"read_only\": true}' https://api.github.com/repos/{{ github_repo_owner }}/{{ github_repo_name }}/keys" 20 | with_items: 21 | - "{{ ssh_key.stdout }}" 22 | -------------------------------------------------------------------------------- /roles/rabbitmq/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: rabbitmq - install 3 | sudo: yes 4 | apt: name=rabbitmq-server 5 | -------------------------------------------------------------------------------- /roles/supervisor/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: supervisor - create folders 3 | shell: mkdir -p etc /home/{{ user }}/log/supervisor /home/{{ user }}/tmp 4 | 5 | - name: supervisor - install 6 | sudo: yes 7 | pip: name="git+https://github.com/Supervisor/supervisor@946d9cf3be4db398f5c2474140e0b92880863bb2#egg=supervisor" 8 | 9 | - name: supervisor - upload supervisord.conf 10 | template: src=supervisord.conf dest=/etc/supervisord.conf 11 | 12 | - name: supervisor - add sock file 13 | file: 14 | path: /home/{{ user }}/tmp/supervisor.sock 15 | state: touch 16 | 17 | - name: supervisor - add crontab 18 | cron: 19 | name: "start supervisor" 20 | minute: "*/5" 21 | job: "PATH=/usr/local/bin /usr/local/bin/supervisord -c /home/{{ user }}/etc/supervisord.conf > /home/{{ user }}/log/supervisor/crontab.log 2>&1" 22 | 23 | - name: supervisor - start supervisor 24 | sudo: yes 25 | shell: supervisord -c /etc/supervisord.conf 26 | 27 | - name: supervisor - restart 28 | shell: source ~/.bash_profile && supervisorctl restart all 29 | args: 30 | chdir: ~/etc/ 31 | executable: /bin/bash 32 | -------------------------------------------------------------------------------- /roles/supervisor/templates/supervisord.conf: -------------------------------------------------------------------------------- 1 | [unix_http_server] 2 | file=/home/{{ user }}/tmp/supervisor.sock 3 | 4 | [supervisord] 5 | logfile=/home/{{ user }}/log/supervisor/supervisord.log 6 | logfile_maxbytes=50MB 7 | logfile_backups=10 8 | loglevel=info 9 | pidfile=/home/{{ user }}/tmp/supervisord.pid 10 | 11 | [rpcinterface:supervisor] 12 | supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface 13 | 14 | [supervisorctl] 15 | serverurl=unix:///home/{{ user }}/tmp/supervisor.sock 16 | 17 | [program:uwsgi] 18 | command=uwsgi --ini /home/{{ user }}/etc/uwsgi.ini 19 | autorestart=true 20 | stopsignal=QUIT 21 | stopasgroup=true 22 | stderr_logfile=/home/{{ user }}/log/uwsgi/err.log 23 | stdout_logfile=/home/{{ user }}/log/uwsgi/out.log 24 | -------------------------------------------------------------------------------- /roles/uwsgi/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: uwsgi - create folders 3 | shell: mkdir -p /home/{{ user }}/etc /home/{{ user }}/log/uwsgi 4 | 5 | - name: uwsgi - install 6 | sudo: yes 7 | pip: name=uwsgi 8 | 9 | - name: uwsgi upload uwsgi.ini 10 | template: src=uwsgi.ini dest=/home/{{ user }}/etc/uwsgi.ini 11 | -------------------------------------------------------------------------------- /roles/uwsgi/templates/uwsgi.ini: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | socket=127.0.0.1:8889 3 | chdir={{ server_project_folder }}/{{ django_folder }} 4 | wsgi-file={{ wsgi_folder }} 5 | touch-reload={{ wsgi_folder }} 6 | virtualenv=/home/{{ user }}/Envs/{{ django_project_name }} 7 | processes=2 8 | harakiri=20 9 | die-on-term=true 10 | -------------------------------------------------------------------------------- /roles/virtualenv/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: virtualenv - create folders 3 | raw: mkdir -p ~/tmp 4 | 5 | - name: virtualenv - install setuptools 6 | sudo: yes 7 | apt: name=python-setuptools 8 | 9 | - name: virtualenv - install pip 10 | sudo: yes 11 | easy_install: name=pip 12 | when: python_main_version == 2 13 | 14 | - name: virtualenv - install pip3 15 | sudo: yes 16 | apt: name=python3-pip 17 | when: python_main_version == 3 18 | 19 | - name: virtualenv - install 20 | sudo: yes 21 | pip: name=virtualenv 22 | 23 | - name: virtualenv - install virtualenvwrapper 24 | sudo: yes 25 | pip: name=virtualenvwrapper 26 | 27 | - name: virtualenv - add virtualenvwrapper exports to .bash_profile 28 | lineinfile: 'dest=~/.bash_profile line="{{ item }}" create=yes' 29 | with_items: 30 | - export PATH=$PATH:$HOME/bin 31 | - export TMPDIR=$HOME/tmp 32 | - export WORKON_HOME=/home/{{ user }}/Envs 33 | - export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python{{ python_main_version}}.{{ python_sub_version }} 34 | - export PIP_VIRTUALENV_BASE=$WORKON_HOME 35 | - export PIP_RESPECT_VIRTUALENV=true 36 | - source /usr/local/bin/virtualenvwrapper.sh 37 | 38 | - name: virtualenv - source the new .bashrc 39 | raw: source .bashrc 40 | -------------------------------------------------------------------------------- /server.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Main task 3 | hosts: ubuntu-server 4 | vars: 5 | ansible_python_interpreter: "/usr/bin/python3.5" 6 | vars_files: 7 | - vars/external_vars.yml 8 | user: "{{ user }}" 9 | 10 | roles: 11 | - { role: prerequisites, tags: [ 'prerequisites' ] } 12 | - { role: access, when: upload_authorized_keys == 'yes' } 13 | - { role: common, tags: [ 'common' ] } 14 | - { role: virtualenv, tags: [ 'virtualenv' ] } 15 | - { role: postgres, tags: [ 'postgres' ] } 16 | - { role: common-python, tags: [ 'common-python' ] } 17 | - { role: django, tags: [ 'django' ] } 18 | - { role: nginx, tags: [ 'nginx' ] } 19 | - { role: uwsgi, tags: [ 'uwsgi' ] } 20 | - { role: supervisor, tags: [ 'supervisor' ] } 21 | - { role: customize, tags: [ 'customize' ] } 22 | - { role: letsencrypt, tags: [ 'letsencrypt' ] } 23 | - { role: rabbitmq, tags: [ 'rabbitmq' ] } 24 | - { role: celery, tags: [ 'celery' ] } 25 | -------------------------------------------------------------------------------- /vars/external_vars.yml.sample: -------------------------------------------------------------------------------- 1 | --- 2 | # Ubuntu user name 3 | # Use `ubuntu` for AWS and `root` for Digital Ocean 4 | user: ubuntu 5 | 6 | # Python version (2 or 3) 7 | # Also change the `ansible_python_interpreter` in server.yml 8 | python_main_version: 3 9 | python_sub_version: 5 10 | 11 | # Activate ("yes") this setting to upload your authorized_keys to the server 12 | upload_authorized_keys: "no" 13 | 14 | # The db password will be set by the script. Make something up! 15 | postgres_host: localhost 16 | postgres_user: django 17 | postgres_db_name: django 18 | postgres_pw: YOUR_ROLE_PASSWORD 19 | postgres_port: 5432 20 | 21 | # Use this settings, if you want to create a local database 22 | postgres_local: "no" 23 | postgres_postgis: "yes" 24 | 25 | # Your git repo, django project and venv should be called the same: 26 | django_project_name: YOUR_DJANGO_PROJECT_NAME 27 | 28 | # If you're using a custom django folder, use something like `django/` 29 | django_folder: 30 | 31 | # From where can we clone the django project? 32 | # Don't forget to add your access token to ``.github_token`` 33 | git_repo: YOUR_GIT_REPO_URL 34 | # github_user: YOUR_GITHUB_USERNAME 35 | # github_repo_owner: USER_OR_ORG_NAME 36 | # github_repo_name: REPO_NAME 37 | 38 | # Your website URLs: 39 | ip: your.server.IP 40 | domain: your-domain.com 41 | 42 | # Certificate settings 43 | email: info@bitmazk.com 44 | 45 | # ============================================================================= 46 | # The things here should not be changed when using a default server layout 47 | # ============================================================================= 48 | venv_name: "{{ django_project_name }}" 49 | server_git_repo: "/home/{{ user }}/src/{{ django_project_name }}" 50 | server_git_project_root: "{{ server_git_repo }}/" 51 | server_requirements_txt: "{{ server_git_project_root }}{{ django_folder }}requirements.txt" 52 | server_project_folder: "/home/{{ user }}/project" 53 | server_project_local_settings: "{{ server_project_folder }}/{{ django_folder }}{{ django_project_name }}/settings/local_settings.py" 54 | wsgi_folder: "{{ server_project_folder }}/{{ django_folder }}{{ django_project_name }}/{{ django_project_name }}/wsgi.py" 55 | server_assets_folder: "/home/{{ user }}/project_assets" 56 | --------------------------------------------------------------------------------