From 6e94220d9570c3c8e770d427ed5e9bb508e96686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felipe=20Mart=C3=ADn?= Date: Mon, 15 Jun 2015 22:17:07 +0200 Subject: [PATCH] Finished provision --- Vagrantfile | 2 +- amiibofindr/settings/devel.py | 14 +++ deploy.py | 49 ++++++++ provision/defaults/main.yml | 4 - provision/group_vars/deploy.yml | 6 + provision/group_vars/development.yml | 2 + provision/host_vars/default | 4 - provision/host_vars/test.yml | 7 ++ provision/hosts | 6 +- provision/playbook.yml | 42 +++++-- .../roles/add_user_deploy/tasks/main.yml | 7 ++ provision/roles/app_deploy/defaults/main.yml | 5 + provision/roles/app_deploy/tasks/config.yml | 6 + provision/roles/app_deploy/tasks/django.yml | 14 +++ .../roles/app_deploy/tasks/django_initial.yml | 5 + provision/roles/app_deploy/tasks/folder.yml | 6 + provision/roles/app_deploy/tasks/git.yml | 14 +++ provision/roles/app_deploy/tasks/main.yml | 58 +++++++++ provision/roles/app_deploy/tasks/node.yml | 3 + .../roles/app_deploy/tasks/virtualenv.yml | 9 ++ .../roles/app_localdev/defaults/main.yml | 0 .../roles/app_localdev/tasks/aliases.yml | 9 -- provision/roles/app_localdev/tasks/deploy.yml | 12 +- provision/roles/app_localdev/tasks/main.yml | 4 +- .../roles/app_localdev/tasks/postgresql.yml | 14 +-- provision/roles/app_localdev/tasks/python.yml | 8 -- provision/roles/app_production/tasks/main.yml | 4 + provision/roles/deploy_user/defaults/main.yml | 13 ++ .../roles/deploy_user/files/initial_syncdb.sh | 9 ++ provision/roles/deploy_user/files/sudoerfile | 1 + provision/roles/deploy_user/tasks/folders.yml | 29 +++++ provision/roles/deploy_user/tasks/main.yml | 13 ++ provision/roles/deploy_user/tasks/sudoer.yml | 8 ++ provision/roles/nginx/defaults/main.yml | 6 + provision/roles/nginx/files/host.conf | 115 ++++++++++++++++++ provision/roles/nginx/tasks/main.yml | 21 ++++ provision/roles/nodejs/tasks/tools.yml | 3 +- provision/roles/postgresql/defaults/main.yml | 5 +- provision/roles/postgresql/files/hstore.sh | 13 ++ .../roles/postgresql/tasks/config_hstore.yml | 5 + .../roles/postgresql/tasks/create_db.yml | 2 +- .../roles/postgresql/tasks/create_user.yml | 4 +- provision/roles/postgresql/tasks/main.yml | 2 + provision/roles/python/tasks/tools.yml | 6 +- provision/roles/redis/defaults/main.yml | 2 + provision/roles/redis/handlers/main.yml | 4 + provision/roles/redis/tasks/main.yml | 2 + provision/roles/redis/tasks/redis.yml | 8 ++ provision/roles/supervisor/defaults/main.yml | 3 + provision/roles/supervisor/files/config.ini | 31 +++++ provision/roles/supervisor/tasks/main.yml | 14 +++ provision/roles/system/tasks/tools.yml | 4 + requirements/{local.txt => devel.txt} | 0 53 files changed, 577 insertions(+), 60 deletions(-) create mode 100644 amiibofindr/settings/devel.py create mode 100644 deploy.py delete mode 100644 provision/defaults/main.yml create mode 100644 provision/group_vars/deploy.yml create mode 100644 provision/group_vars/development.yml delete mode 100644 provision/host_vars/default create mode 100644 provision/host_vars/test.yml create mode 100644 provision/roles/add_user_deploy/tasks/main.yml create mode 100644 provision/roles/app_deploy/defaults/main.yml create mode 100644 provision/roles/app_deploy/tasks/config.yml create mode 100644 provision/roles/app_deploy/tasks/django.yml create mode 100644 provision/roles/app_deploy/tasks/django_initial.yml create mode 100644 provision/roles/app_deploy/tasks/folder.yml create mode 100644 provision/roles/app_deploy/tasks/git.yml create mode 100644 provision/roles/app_deploy/tasks/main.yml create mode 100644 provision/roles/app_deploy/tasks/node.yml create mode 100644 provision/roles/app_deploy/tasks/virtualenv.yml create mode 100644 provision/roles/app_localdev/defaults/main.yml delete mode 100644 provision/roles/app_localdev/tasks/aliases.yml create mode 100644 provision/roles/deploy_user/defaults/main.yml create mode 100644 provision/roles/deploy_user/files/initial_syncdb.sh create mode 100644 provision/roles/deploy_user/files/sudoerfile create mode 100644 provision/roles/deploy_user/tasks/folders.yml create mode 100644 provision/roles/deploy_user/tasks/main.yml create mode 100644 provision/roles/deploy_user/tasks/sudoer.yml create mode 100644 provision/roles/nginx/defaults/main.yml create mode 100644 provision/roles/nginx/files/host.conf create mode 100644 provision/roles/nginx/tasks/main.yml create mode 100644 provision/roles/postgresql/files/hstore.sh create mode 100644 provision/roles/postgresql/tasks/config_hstore.yml create mode 100644 provision/roles/redis/defaults/main.yml create mode 100644 provision/roles/redis/handlers/main.yml create mode 100644 provision/roles/redis/tasks/main.yml create mode 100644 provision/roles/redis/tasks/redis.yml create mode 100644 provision/roles/supervisor/defaults/main.yml create mode 100644 provision/roles/supervisor/files/config.ini create mode 100644 provision/roles/supervisor/tasks/main.yml rename requirements/{local.txt => devel.txt} (100%) diff --git a/Vagrantfile b/Vagrantfile index 3a1e85c..9c9443f 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -4,7 +4,7 @@ VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| - config.vm.define "globalwishlist-backend" do |web| + config.vm.define "amiibofindr-web" do |web| web.vm.box = "ubuntu/trusty64" #web.vm.network "private_network", type: "dhcp" diff --git a/amiibofindr/settings/devel.py b/amiibofindr/settings/devel.py new file mode 100644 index 0000000..4d9d2f9 --- /dev/null +++ b/amiibofindr/settings/devel.py @@ -0,0 +1,14 @@ +# coding: utf-8 + +from .base import * + + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': 'amiibofindr', + 'USER': 'vagrant', + 'PASS': 'vagrant', + 'HOST': '127.0.0.1', + } +} diff --git a/deploy.py b/deploy.py new file mode 100644 index 0000000..ba034d9 --- /dev/null +++ b/deploy.py @@ -0,0 +1,49 @@ +# coding: utf-8 + +# 3rd party +import click +from fabric.api import local + + +@click.command() +@click.option('--branch', '-b', default='stable', + help='Branch to git clone from') +@click.option('--inventory', '-i', default='hosts', + help='Inventory file for ansible to use') +@click.option('--host', '-h', default=None, + help='Host to deploy to') +@click.option('--tag', '-t', default='deploy', + help='Ansible tags to run') +@click.option('--tasks', count=True, + help='List tasks instead of executing them') +@click.option('--hosts', count=True, + help='List hosts instead of executing tasks') +@click.option('--verbose', count=True, + help='Appends -vvvv to ansible') +def deploy(branch, inventory, host, tag, tasks, hosts, verbose): + cmd = 'ansible-playbook -i provision/{}'.format(inventory) + + if host: + cmd += ' -l {}'.format(host) + + cmd += ' -t {}'.format(tag) + + if tasks: + cmd += ' --list-tasks' + + if hosts: + cmd += ' --list-hosts' + + cmd += ' -e git_branch={}'.format(branch) + + cmd += ' provision/playbook.yml' + + if verbose: + cmd += ' -vvvv' + + local(cmd) + + +# Let's do this +if __name__ == '__main__': + deploy() diff --git a/provision/defaults/main.yml b/provision/defaults/main.yml deleted file mode 100644 index 6703394..0000000 --- a/provision/defaults/main.yml +++ /dev/null @@ -1,4 +0,0 @@ -# PostgreSQL config -postgresql_version: 9.3 -postgresql_database_name: amiibofindr -postgresql_database_user: amiibofindr diff --git a/provision/group_vars/deploy.yml b/provision/group_vars/deploy.yml new file mode 100644 index 0000000..3d9730c --- /dev/null +++ b/provision/group_vars/deploy.yml @@ -0,0 +1,6 @@ +# Remote user that will execute the app +app_user: amiibofindr + +# Git repository +git_repository: git@github.org:fmartingr/amiibofindr.git +git_branch: master diff --git a/provision/group_vars/development.yml b/provision/group_vars/development.yml new file mode 100644 index 0000000..119e77d --- /dev/null +++ b/provision/group_vars/development.yml @@ -0,0 +1,2 @@ +# Nginx +enable_ssl: false diff --git a/provision/host_vars/default b/provision/host_vars/default deleted file mode 100644 index c8a9c20..0000000 --- a/provision/host_vars/default +++ /dev/null @@ -1,4 +0,0 @@ ---- -postgresql_version: 9.3 -postgresql_database_name: amiibofindr -postgresql_database_user: amiibofindr diff --git a/provision/host_vars/test.yml b/provision/host_vars/test.yml new file mode 100644 index 0000000..084514c --- /dev/null +++ b/provision/host_vars/test.yml @@ -0,0 +1,7 @@ +# Nginx +site_hostname: amiibofindr.com + +site_media_hostname: media.amiibofindr.com +site_static_hostname: static.amiibofindr.com + +enable_ssl: false diff --git a/provision/hosts b/provision/hosts index 57fb589..a8b3ab4 100644 --- a/provision/hosts +++ b/provision/hosts @@ -1,4 +1,8 @@ -default ansible_ssh_host=127.0.0.1 ansible_ssh_user=vagrant ansible_ssh_port=2201 +default ansible_ssh_host=127.0.0.1 ansible_ssh_user=vagrant ansible_ssh_port=2222 [localdev] default + +[development] + +[deploy] diff --git a/provision/playbook.yml b/provision/playbook.yml index e1e04cf..f81431b 100644 --- a/provision/playbook.yml +++ b/provision/playbook.yml @@ -2,18 +2,42 @@ - name: Common Tasks hosts: all roles: - - system - - base - - python - - nodejs - - postgresql + - role: system + tags: ["provision", "system"] + - role: base + tags: ["provision", "base"] + - role: python + tags: ["provision", "python"] + - role: nodejs + tags: ["provision", "nodejs"] + - role: redis + tags: ["provision", "redis"] + - role: postgresql + tags: ["provision", "postgresql"] + - role: nginx + tags: ["provision", "nginx"] + - role: supervisor + tags: ["provision", "supervisor"] + - role: deploy_user + tags: ["provision", "deploy_user"] - name: LocalDev Tasks hosts: localdev roles: - - app_localdev + - role: app_localdev + tags: ["app_localdev"] -- name: Production Tasks - hosts: production +- name: Deploy Tasks + hosts: + - deploy + vars: + - ansible_ssh_user: "{{ app_user }}" roles: - - app_production + - role: app_deploy + tags: ["deploy"] + +- name: Automation tasks + hosts: all + roles: + - role: add_user_deploy + tags: ["add_user_deploy"] diff --git a/provision/roles/add_user_deploy/tasks/main.yml b/provision/roles/add_user_deploy/tasks/main.yml new file mode 100644 index 0000000..2f5dd01 --- /dev/null +++ b/provision/roles/add_user_deploy/tasks/main.yml @@ -0,0 +1,7 @@ +--- +- name: Ensure deployers group is present + group: name=deployers state=present + sudo: true +- name: Ensure user is present and member of the deployers group + user: name={{ app_user }} generate_ssh_key=yes ssh_key_bits={{ app_user_key_bits }} ssh_key_file=.ssh/id_rsa group={{ app_deploy_group }} + sudo: true diff --git a/provision/roles/app_deploy/defaults/main.yml b/provision/roles/app_deploy/defaults/main.yml new file mode 100644 index 0000000..e957dde --- /dev/null +++ b/provision/roles/app_deploy/defaults/main.yml @@ -0,0 +1,5 @@ +deploy_backend: true + +deploy_migrate: true + +deploy_collecstatic: true diff --git a/provision/roles/app_deploy/tasks/config.yml b/provision/roles/app_deploy/tasks/config.yml new file mode 100644 index 0000000..0986995 --- /dev/null +++ b/provision/roles/app_deploy/tasks/config.yml @@ -0,0 +1,6 @@ +--- +- name: Ensure config is symlinked + file: src=/home/{{ app_user }}/conf/local.py + dest={{ deploy_path.stdout }}/git/src/backend/settings/local.py + state=link + force=true diff --git a/provision/roles/app_deploy/tasks/django.yml b/provision/roles/app_deploy/tasks/django.yml new file mode 100644 index 0000000..efdd890 --- /dev/null +++ b/provision/roles/app_deploy/tasks/django.yml @@ -0,0 +1,14 @@ +--- +- name: Performs manage.py syncdb + when: deploy_migrate + django_manage: > + command=syncdb + app_path={{ deploy_path.stdout }}/git/src/backend + virtualenv={{ deploy_path.stdout }}/.virtualenv + +- name: Performs manage.py migrate + when: deploy_migrate + django_manage: > + command=migrate + app_path={{ deploy_path.stdout }}/git/src/backend + virtualenv={{ deploy_path.stdout }}/.virtualenv diff --git a/provision/roles/app_deploy/tasks/django_initial.yml b/provision/roles/app_deploy/tasks/django_initial.yml new file mode 100644 index 0000000..5338c7d --- /dev/null +++ b/provision/roles/app_deploy/tasks/django_initial.yml @@ -0,0 +1,5 @@ +--- +- name: Performs initial syncdb + shell: "{{ app_scripts_folder }}/initial_syncdb.sh" + args: + chdir: /home/{{ app_user }}/builds/{{ deploy_date.stdout }} diff --git a/provision/roles/app_deploy/tasks/folder.yml b/provision/roles/app_deploy/tasks/folder.yml new file mode 100644 index 0000000..002b3ba --- /dev/null +++ b/provision/roles/app_deploy/tasks/folder.yml @@ -0,0 +1,6 @@ +--- +- name: Create deploy folder + file: path={{ app_builds_folder }}/{{ deploy_date.stdout }} state=directory + +- action: shell echo {{ app_builds_folder }}/{{ deploy_date.stdout }} + register: deploy_path diff --git a/provision/roles/app_deploy/tasks/git.yml b/provision/roles/app_deploy/tasks/git.yml new file mode 100644 index 0000000..99c86fb --- /dev/null +++ b/provision/roles/app_deploy/tasks/git.yml @@ -0,0 +1,14 @@ +--- +- name: Clone git repository + git: repo={{ git_repository }} + dest={{ app_git_folder }} + version={{ git_branch }} + accept_hostkey=true + +- name: Create build git directory + file: path={{ deploy_path.stdout }}/git state=directory + sudo: true + sudo_user: "{{ app_user }}" + +- name: Copy repository to build folder + command: cp -r {{ app_git_folder }} {{ deploy_path.stdout }} diff --git a/provision/roles/app_deploy/tasks/main.yml b/provision/roles/app_deploy/tasks/main.yml new file mode 100644 index 0000000..354ddbd --- /dev/null +++ b/provision/roles/app_deploy/tasks/main.yml @@ -0,0 +1,58 @@ +--- +- include_vars: ../../deploy_user/defaults/main.yml + +# Register date as variable to use it in deploy steps +- action: shell date '+%Y%m%d_%H%M%S' + register: deploy_date + remote_user: "{{ app_user }}" + +- stat: path=/home/{{ app_user }}/.initial_syncdb + register: initial_syncdb + ignore_errors: true + +- include: folder.yml + remote_user: "{{ app_user }}" + +- include: git.yml + remote_user: "{{ app_user }}" + +- include: virtualenv.yml + remote_user: "{{ app_user }}" + +#- include: node.yml +# remote_user: "{{ app_user }}" + +- include: config.yml + remote_user: "{{ app_user }}" + +- include: django_initial.yml + remote_user: "{{ app_user }}" + when: initial_syncdb.stat.exists == False + +- include: django.yml + remote_user: "{{ app_user }}" + when: initial_syncdb.stat.exists + +- name: Mark as finished + file: path=/home/{{ app_user }}/builds/{{ deploy_date.stdout }}/.finished + state=touch + remote_user: "{{ app_user }}" + +- name: Remove old current symlink + file: path=/home/{{ app_user }}/current + state=absent + remote_user: "{{ app_user }}" + +- name: Symlink new release + file: src={{ deploy_path.stdout }}/git/src + dest=/home/{{ app_user }}/current + state=link + force=true + remote_user: "{{ app_user }}" + +- name: Restart supervisor + sudo: true + command: supervisorctl restart {{ item }} + with_items: + - django + - celery diff --git a/provision/roles/app_deploy/tasks/node.yml b/provision/roles/app_deploy/tasks/node.yml new file mode 100644 index 0000000..6d379dc --- /dev/null +++ b/provision/roles/app_deploy/tasks/node.yml @@ -0,0 +1,3 @@ +#--- +#- name: Install node requirements +# npm: path={{ deploy_path.stdout }}/git/src/backend diff --git a/provision/roles/app_deploy/tasks/virtualenv.yml b/provision/roles/app_deploy/tasks/virtualenv.yml new file mode 100644 index 0000000..4a6b9c3 --- /dev/null +++ b/provision/roles/app_deploy/tasks/virtualenv.yml @@ -0,0 +1,9 @@ +--- +- name: Ensure virtualenv requirements installed + pip: requirements={{ deploy_path.stdout }}/git/src/backend/requirements-prod.txt + virtualenv={{ deploy_path.stdout }}/.virtualenv + +- name: Symlink virtualenv to git src folder + file: src={{ deploy_path.stdout }}/.virtualenv + dest=/home/{{ app_user }}/git/src/.virtualenv + state=link diff --git a/provision/roles/app_localdev/defaults/main.yml b/provision/roles/app_localdev/defaults/main.yml new file mode 100644 index 0000000..e69de29 diff --git a/provision/roles/app_localdev/tasks/aliases.yml b/provision/roles/app_localdev/tasks/aliases.yml deleted file mode 100644 index a26e7eb..0000000 --- a/provision/roles/app_localdev/tasks/aliases.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -- name: Ensure (runserver) alias - lineinfile: dest=~/.bash_profile state=present line='alias runserver="python /vagrant/manage.py runserver 0.0.0.0:8000"' -- name: Ensure (runserver_plus) alias - lineinfile: dest=~/.bash_profile state=present line='alias runserver_plus="python /vagrant/manage.py runserver_plus 0.0.0.0:8000"' -- name: Ensure (shell) alias - lineinfile: dest=~/.bash_profile state=present line='alias shell="python /vagrant/manage.py shell"' -- name: Ensure (shell_plus) alias - lineinfile: dest=~/.bash_profile state=present line='alias shell_plus="python /vagrant/manage.py shell_plus"' diff --git a/provision/roles/app_localdev/tasks/deploy.yml b/provision/roles/app_localdev/tasks/deploy.yml index e988bd1..e0f74f7 100644 --- a/provision/roles/app_localdev/tasks/deploy.yml +++ b/provision/roles/app_localdev/tasks/deploy.yml @@ -1,15 +1,13 @@ --- - name: Install requirements - pip: requirements=/vagrant/requirements/local.txt virtualenv=~/.virtualenv + pip: requirements=/vagrant/requirements/devel.txt virtualenv=/vagrant/.virtualenv sudo: yes sudo_user: vagrant -# - name: Install nodejs requirements -# npm: path=/vagrant -# sudo: yes -# sudo_user: vagrant - name: Ensure vagrant user have a .bash_profile file: path=~/.bash_profile state=touch - name: Ensure directory is changed on login lineinfile: dest=~/.bash_profile state=present line='cd /vagrant' -- name: Ensure DJANGO_SETTINGS_MODULE environment variable - lineinfile: dest=~/.bash_profile state=present line='export DJANGO_SETTINGS_MODULE="local_settings"' +- name: Performs manage.py migrate + django_manage: command=migrate + virtualenv=/vagrant/.virtualenv + app_path=/vagrant diff --git a/provision/roles/app_localdev/tasks/main.yml b/provision/roles/app_localdev/tasks/main.yml index e035b80..e7e73c0 100644 --- a/provision/roles/app_localdev/tasks/main.yml +++ b/provision/roles/app_localdev/tasks/main.yml @@ -1,5 +1,7 @@ --- +- include_vars: ../../postgresql/defaults/main.yml - include: python.yml - include: postgresql.yml - include: deploy.yml -- include: aliases.yml +- name: Ensure directory is changed on login + lineinfile: dest=~/.bash_profile state=present line='cd /vagrant' diff --git a/provision/roles/app_localdev/tasks/postgresql.yml b/provision/roles/app_localdev/tasks/postgresql.yml index 991d89b..a34fc5f 100644 --- a/provision/roles/app_localdev/tasks/postgresql.yml +++ b/provision/roles/app_localdev/tasks/postgresql.yml @@ -3,14 +3,14 @@ postgresql_user: name=vagrant role_attr_flags=SUPERUSER sudo_user: postgres sudo: true +- name: Ensure vagrant database user is created + postgresql_user: db={{ postgresql_database_name }} name=vagrant password=vagrant priv=ALL state=present + sudo_user: postgres + sudo: true +- name: Ensure vagrant user can access + lineinfile: dest=/etc/postgresql/9.3/main/pg_hba.conf state=present line='local all postgres trust' + sudo: true - name: Ensure database is present postgresql_db: name={{ postgresql_database_name }} owner=vagrant sudo: true sudo_user: postgres -- name: Ensure vagrant database user is created - postgresql_user: db={{ postgresql_database_name }} name=vagrant password=NULL priv=ALL state=present - sudo_user: postgres - sudo: true -- name: Ensure vagrant user can access - lineinfile: dest=/etc/postgresql/{{ postgresql_version }}/main/pg_hba.conf state=present line='local all postgres trust' - sudo: true diff --git a/provision/roles/app_localdev/tasks/python.yml b/provision/roles/app_localdev/tasks/python.yml index a1977a4..7c302ba 100644 --- a/provision/roles/app_localdev/tasks/python.yml +++ b/provision/roles/app_localdev/tasks/python.yml @@ -3,20 +3,12 @@ - shell: if [ -e .virtualenv ]; then echo yes; else echo no; fi; register: virtualenv_exists always_run: True - sudo: true - sudo_user: vagrant # Create virtualenv - name: Ensure virtualenv is created when: virtualenv_exists.stdout == 'no' command: 'virtualenv .virtualenv' - sudo: true - sudo_user: vagrant # Auto activate on ssh - name: Ensure vagrant user have a .bash_profile file: path=~/.bash_profile state=touch - sudo: true - sudo_user: vagrant - name: Ensure virtualenv is enabled on login lineinfile: dest=~/.bash_profile state=present line='. ~/.virtualenv/bin/activate' - sudo: true - sudo_user: vagrant diff --git a/provision/roles/app_production/tasks/main.yml b/provision/roles/app_production/tasks/main.yml index e69de29..1c45087 100644 --- a/provision/roles/app_production/tasks/main.yml +++ b/provision/roles/app_production/tasks/main.yml @@ -0,0 +1,4 @@ +--- +- name: Create user and generate shh-key file + user: name={{ app_user }} generate_ssh_key=yes ssh_key_bits={{ app_user_key_bits }} ssh_key_file=.ssh/id_rsa + sudo: true diff --git a/provision/roles/deploy_user/defaults/main.yml b/provision/roles/deploy_user/defaults/main.yml new file mode 100644 index 0000000..a44deba --- /dev/null +++ b/provision/roles/deploy_user/defaults/main.yml @@ -0,0 +1,13 @@ +app_user: amiibofindr +app_user_key_bits: 2048 + +app_deploy_group: deployers + +app_static_folder: /home/{{ app_user }}/files/static +app_media_folder: /home/{{ app_user }}/files/media +app_conf_folder: /home/{{ app_user }}/conf +app_builds_folder: /home/{{ app_user }}/builds +app_logs_folder: /home/{{ app_user }}/logs +app_public_files_folder: /home/{{ app_user }}/public_files +app_git_folder: /home/{{ app_user }}/git +app_scripts_folder: /home/{{ app_user }}/scripts diff --git a/provision/roles/deploy_user/files/initial_syncdb.sh b/provision/roles/deploy_user/files/initial_syncdb.sh new file mode 100644 index 0000000..4b34a9a --- /dev/null +++ b/provision/roles/deploy_user/files/initial_syncdb.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Assumes we are chdir'ed to last build dir... + +source .virtualenv/bin/activate + +python manage.py migrate --noinput + +touch $HOME/.initial_syncdb diff --git a/provision/roles/deploy_user/files/sudoerfile b/provision/roles/deploy_user/files/sudoerfile new file mode 100644 index 0000000..165c5e3 --- /dev/null +++ b/provision/roles/deploy_user/files/sudoerfile @@ -0,0 +1 @@ +{{ app_user }} ALL=NOPASSWD: {{ supervisorctl_path.stdout }} diff --git a/provision/roles/deploy_user/tasks/folders.yml b/provision/roles/deploy_user/tasks/folders.yml new file mode 100644 index 0000000..5b39ce3 --- /dev/null +++ b/provision/roles/deploy_user/tasks/folders.yml @@ -0,0 +1,29 @@ +--- +- name: Ensure folder - static + file: path={{ app_static_folder }} state=directory + sudo: true + sudo_user: "{{ app_user }}" +- name: Ensure folder - media + file: path={{ app_media_folder }} state=directory + sudo: true + sudo_user: "{{ app_user }}" +- name: Ensure folder - conf + file: path={{ app_conf_folder }} state=directory + sudo: true + sudo_user: "{{ app_user }}" +- name: Ensure builds folder + file: path={{ app_builds_folder }} state=directory + sudo: true + sudo_user: "{{ app_user }}" +- name: Ensure logs folder + file: path={{ app_logs_folder }} state=directory + sudo: true + sudo_user: "{{ app_user }}" +- name: Ensure git repo folder + file: path={{ app_git_folder }} state=directory + sudo: true + sudo_user: "{{ app_user }}" +- name: Ensure scripts folder + file: path={{ app_scripts_folder }} state=directory + sudo: true + sudo_user: "{{ app_user }}" diff --git a/provision/roles/deploy_user/tasks/main.yml b/provision/roles/deploy_user/tasks/main.yml new file mode 100644 index 0000000..ffe2efc --- /dev/null +++ b/provision/roles/deploy_user/tasks/main.yml @@ -0,0 +1,13 @@ +--- +- name: Create user and generate shh-key file + user: name={{ app_user }} generate_ssh_key=yes ssh_key_bits={{ app_user_key_bits }} ssh_key_file=.ssh/id_rsa shell=/bin/bash + sudo: true +- include: folders.yml +- include: sudoer.yml + +- name: Add initial_syncdb.sh script + template: src=roles/deploy_user/files/initial_syncdb.sh + dest={{ app_scripts_folder }}/initial_syncdb.sh + mode=0644 + sudo: true + sudo_user: "{{ app_user }}" diff --git a/provision/roles/deploy_user/tasks/sudoer.yml b/provision/roles/deploy_user/tasks/sudoer.yml new file mode 100644 index 0000000..59cf9a6 --- /dev/null +++ b/provision/roles/deploy_user/tasks/sudoer.yml @@ -0,0 +1,8 @@ +--- +- action: shell which supervisorctl + register: supervisorctl_path + +- name: Add sudoer file to allow supervisor without password + template: src=roles/deploy_user/files/sudoerfile + dest=/etc/sudoers.d/{{ app_user }} + sudo: true diff --git a/provision/roles/nginx/defaults/main.yml b/provision/roles/nginx/defaults/main.yml new file mode 100644 index 0000000..c828e67 --- /dev/null +++ b/provision/roles/nginx/defaults/main.yml @@ -0,0 +1,6 @@ +site_hostname: amiibofindr.com + +site_media_hostname: media.amiibofindr.com +site_static_hostname: static.amiibofindr.com + +enable_ssl: true diff --git a/provision/roles/nginx/files/host.conf b/provision/roles/nginx/files/host.conf new file mode 100644 index 0000000..a4267fa --- /dev/null +++ b/provision/roles/nginx/files/host.conf @@ -0,0 +1,115 @@ +# Redirect non-www to www +server { + listen 80; + {% if enable_ssl %}listen 443 ssl;{% endif %} + server_name www.{{ site_hostname }}; + return 301 $scheme://{{ site_hostname }}$request_uri; + {% if enable_ssl %} + ssl_certificate /etc/nginx/ssl/certificate.pem; + ssl_certificate_key /etc/nginx/ssl/privkey.pem; + {% endif %} +} + +# Main server +server { + listen 80 default_server; + {% if enable_ssl %}listen 443 ssl default_server;{% endif %} + server_name {{ site_hostname }}; + server_tokens off; + + client_max_body_size 50M; + charset utf-8; + + access_log {{ app_logs_folder }}/nginx-ecommerce.access.log; + error_log {{ app_logs_folder }}/nginx-ecommerce.error.log; + + {% if enable_ssl %} + ssl_certificate /etc/nginx/ssl/certificate.pem; + ssl_certificate_key /etc/nginx/ssl/privkey.pem; + + if ($scheme = "http") { + return 301 https://$host$request_uri; + } + {% endif %} + + location /archivos { + autoindex off; + alias {{ app_public_files_folder }}; + } + + location / { + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Scheme $scheme; + proxy_set_header X-Forwarded-Protocol $scheme; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_pass http://127.0.0.1:8000/; + proxy_redirect off; + expires -1; + } +} + +server { + listen 80; + {% if enable_ssl %}listen 443 ssl;{% endif %} + server_name {{ site_media_hostname }}; + + charset utf-8; + + access_log {{ app_logs_folder }}/nginx-media.access.log; + error_log {{ app_logs_folder }}/nginx-media.error.log; + + {% if enable_ssl %} + ssl_certificate /etc/nginx/ssl/certificate.pem; + ssl_certificate_key /etc/nginx/ssl/privkey.pem; + + if ($scheme = "http") { + return 301 https://$host$request_uri; + } + {% endif %} + + location / { + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Credentials' 'true'; + add_header 'Access-Control-Allow-Headers' 'Content-Type,Accept'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE'; + + root {{ app_media_folder }}; + autoindex off; + expires 1h; + } +} + +server { + listen 80; + + {% if enable_ssl %} + listen 443 ssl; + {% endif %} + server_name {{ site_static_hostname }}; + + charset utf-8; + + access_log {{ app_logs_folder }}/nginx-static.access.log; + error_log {{ app_logs_folder }}/nginx-static.error.log; + + {% if enable_ssl %} + ssl_certificate /etc/nginx/ssl/certificate.pem; + ssl_certificate_key /etc/nginx/ssl/privkey.pem; + + if ($scheme = "http") { + return 301 https://$host$request_uri; + } + {% endif %} + + location / { + add_header 'Access-Control-Allow-Origin' '*'; + add_header 'Access-Control-Allow-Credentials' 'true'; + add_header 'Access-Control-Allow-Headers' 'Content-Type,Accept'; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE'; + + root {{ app_static_folder }}; + autoindex off; + expires 1h; + } +} diff --git a/provision/roles/nginx/tasks/main.yml b/provision/roles/nginx/tasks/main.yml new file mode 100644 index 0000000..07832d6 --- /dev/null +++ b/provision/roles/nginx/tasks/main.yml @@ -0,0 +1,21 @@ +--- +- include_vars: ../../deploy_user/defaults/main.yml +- name: Ensure nginx installed + apt: pkg=nginx state=latest + sudo: true + +- name: Ensure default hostfile is deleted + file: path=/etc/nginx/sites-enabled/default state=absent + sudo: true + +- name: Ensure our hostfile is into sites-available + template: src=roles/nginx/files/host.conf dest=/etc/nginx/sites-available/{{ app_user }} + sudo: true + +- name: Ensure hostfile is linked into sites-enabled + file: src=/etc/nginx/sites-available/{{ app_user }} dest=/etc/nginx/sites-enabled/{{ app_user }} state=link + sudo: true + +- name: Restart nginx + service: name=nginx state=restarted + sudo: true diff --git a/provision/roles/nodejs/tasks/tools.yml b/provision/roles/nodejs/tasks/tools.yml index 7137217..0fc2e57 100644 --- a/provision/roles/nodejs/tasks/tools.yml +++ b/provision/roles/nodejs/tasks/tools.yml @@ -3,5 +3,4 @@ npm: name={{ item }} global=yes sudo: true with_items: - - grunt-cli - - bower + - gulp diff --git a/provision/roles/postgresql/defaults/main.yml b/provision/roles/postgresql/defaults/main.yml index 1dfeb98..33adc7d 100644 --- a/provision/roles/postgresql/defaults/main.yml +++ b/provision/roles/postgresql/defaults/main.yml @@ -1,3 +1,2 @@ -postgresql_database_name: amiibofindr -postgresql_database_user: amiibofindr -postgresql_database_port: 5432 +postgresql_user: djangoapp +postgresql_database_name: djangoapp diff --git a/provision/roles/postgresql/files/hstore.sh b/provision/roles/postgresql/files/hstore.sh new file mode 100644 index 0000000..4ff6fa1 --- /dev/null +++ b/provision/roles/postgresql/files/hstore.sh @@ -0,0 +1,13 @@ +#!/bin/bash +psql template1 << EOF + CREATE EXTENSION hstore; + CREATE OR REPLACE FUNCTION idx(anyarray, anyelement) + RETURNS int AS + $$ + SELECT i FROM ( + SELECT generate_series(array_lower($1,1),array_upper($1,1)) + ) g(i) + WHERE $1[i] = $2 + LIMIT 1; + $$ LANGUAGE sql IMMUTABLE; + EOF diff --git a/provision/roles/postgresql/tasks/config_hstore.yml b/provision/roles/postgresql/tasks/config_hstore.yml new file mode 100644 index 0000000..84a9d7a --- /dev/null +++ b/provision/roles/postgresql/tasks/config_hstore.yml @@ -0,0 +1,5 @@ +--- +- name: Config HSTORE into template1 + sudo: true + sudo_user: postgres + script: hstore.sh diff --git a/provision/roles/postgresql/tasks/create_db.yml b/provision/roles/postgresql/tasks/create_db.yml index e08002b..d90b184 100644 --- a/provision/roles/postgresql/tasks/create_db.yml +++ b/provision/roles/postgresql/tasks/create_db.yml @@ -3,5 +3,5 @@ postgresql_db: name={{ postgresql_database_name }} encoding='UTF-8' state=present - sudo_user: postgres sudo: true + sudo_user: postgres diff --git a/provision/roles/postgresql/tasks/create_user.yml b/provision/roles/postgresql/tasks/create_user.yml index 79a63e7..83f349e 100644 --- a/provision/roles/postgresql/tasks/create_user.yml +++ b/provision/roles/postgresql/tasks/create_user.yml @@ -1,9 +1,9 @@ --- - name: Ensure the database user is present - postgresql_user: db={{ postgresql_database_name }} name={{ postgresql_database_user }} password=NULL priv=ALL state=present + postgresql_user: db={{ postgresql_database_name }} name={{ app_user }} password=NULL priv=ALL state=present sudo_user: postgres sudo: true - name: Ensure user dont have unnecesary privileges - postgresql_user: name={{ postgresql_database_user }} role_attr_flags=NOSUPERUSER,CREATEDB + postgresql_user: name=={{ app_user }} role_attr_flags=NOSUPERUSER,CREATEDB sudo_user: postgres sudo: true diff --git a/provision/roles/postgresql/tasks/main.yml b/provision/roles/postgresql/tasks/main.yml index 3f9b306..ee198bd 100644 --- a/provision/roles/postgresql/tasks/main.yml +++ b/provision/roles/postgresql/tasks/main.yml @@ -1,5 +1,7 @@ --- +- include_vars: ../../deploy_user/defaults/main.yml - include: libs.yml - include: postgresql.yml +- include: config_hstore.yml - include: create_db.yml - include: create_user.yml diff --git a/provision/roles/python/tasks/tools.yml b/provision/roles/python/tasks/tools.yml index 392404c..a99859b 100644 --- a/provision/roles/python/tasks/tools.yml +++ b/provision/roles/python/tasks/tools.yml @@ -1,6 +1,10 @@ --- -- name: Ensure debug tools are installed +- name: Ensure pip tools pip: name={{ item }} sudo: true with_items: - ipdb + +- name: Upgrade pip to last version + pip: name=pip state=latest + sudo: true diff --git a/provision/roles/redis/defaults/main.yml b/provision/roles/redis/defaults/main.yml new file mode 100644 index 0000000..787b4ba --- /dev/null +++ b/provision/roles/redis/defaults/main.yml @@ -0,0 +1,2 @@ +redis_bind: 0.0.0.0 +redis_port: 6379 diff --git a/provision/roles/redis/handlers/main.yml b/provision/roles/redis/handlers/main.yml new file mode 100644 index 0000000..fc81b85 --- /dev/null +++ b/provision/roles/redis/handlers/main.yml @@ -0,0 +1,4 @@ +--- +- name: start redis + service: name=redis-server state=started + sudo: yes diff --git a/provision/roles/redis/tasks/main.yml b/provision/roles/redis/tasks/main.yml new file mode 100644 index 0000000..6701b4b --- /dev/null +++ b/provision/roles/redis/tasks/main.yml @@ -0,0 +1,2 @@ +--- +- include: redis.yml diff --git a/provision/roles/redis/tasks/redis.yml b/provision/roles/redis/tasks/redis.yml new file mode 100644 index 0000000..578b356 --- /dev/null +++ b/provision/roles/redis/tasks/redis.yml @@ -0,0 +1,8 @@ +--- +- name: Install redis + apt: pkg={{ item }} state=latest + with_items: + - redis-server + sudo: true + notify: + - start redis diff --git a/provision/roles/supervisor/defaults/main.yml b/provision/roles/supervisor/defaults/main.yml new file mode 100644 index 0000000..1a8f190 --- /dev/null +++ b/provision/roles/supervisor/defaults/main.yml @@ -0,0 +1,3 @@ +app_worker_num: 1 + +celery_worker_num: 1 diff --git a/provision/roles/supervisor/files/config.ini b/provision/roles/supervisor/files/config.ini new file mode 100644 index 0000000..dd9f9b7 --- /dev/null +++ b/provision/roles/supervisor/files/config.ini @@ -0,0 +1,31 @@ +[program:django] +command=/home/{{ app_user }}/current/.virtualenv/bin/gunicorn_django -w 3 -t 60 --settings=settings --pythonpath=. +directory=/home/{{ app_user }}/current/backend +numprocs={{ app_worker_num }} +autostart=true +autorestart=false +stopsignal=INT +stopwaitsecs=2 +startsecs=2 +redirect_stderr=true +stdout_logfile={{ app_logs_folder }}/gunicorn.log +stdout_logfile_backups=20 +stdout_logfile_maxbytes=20MB +user={{ app_user }} +environment=LANG="en_US.UTF-8",USER="{{ app_user }}",HOME="/home/{{ app_user }}" + +[program:celery] +command=/home/{{ app_user }}/current/.virtualenv/bin/python manage.py celery worker -l INFO -E +directory=/home/{{ app_user }}/current/backend +numprocs={{ celery_worker_num }} +autostart=true +autorestart=false +stopsignal=INT +stopwaitsecs=2 +startsecs=2 +redirect_stderr=true +stdout_logfile={{ app_logs_folder }}/celery.log +stdout_logfile_backups=20 +stdout_logfile_maxbytes=20MB +user={{ app_user }} +environment=LANG="en_US.UTF-8",USER="{{ app_user }}",HOME="/home/{{ app_user }}" diff --git a/provision/roles/supervisor/tasks/main.yml b/provision/roles/supervisor/tasks/main.yml new file mode 100644 index 0000000..158574a --- /dev/null +++ b/provision/roles/supervisor/tasks/main.yml @@ -0,0 +1,14 @@ +--- +- include_vars: ../../deploy_user/defaults/main.yml +- name: Ensure supervisor installed + apt: pkg=supervisor state=latest + sudo: true + +- name: Ensure our config file is enabled + template: src=roles/supervisor/files/config.ini dest=/etc/supervisor/conf.d/{{ app_user }}.conf + sudo: true + +- name: Restart supervisor + command: service supervisor restart + sudo: true + ignore_errors: true diff --git a/provision/roles/system/tasks/tools.yml b/provision/roles/system/tasks/tools.yml index f2d42ef..c7346d5 100644 --- a/provision/roles/system/tasks/tools.yml +++ b/provision/roles/system/tasks/tools.yml @@ -3,3 +3,7 @@ lineinfile: dest=/etc/environment line=LANG=en_US.utf-8 lineinfile: dest=/etc/environment line=LC_ALL=en_US.utf-8 sudo: true + +- name: Ensure git is installed + apt: pkg=git state=latest + sudo: true diff --git a/requirements/local.txt b/requirements/devel.txt similarity index 100% rename from requirements/local.txt rename to requirements/devel.txt