In my projects (including Spine Hero) I like to use Ansible. It's a great tool for deploying your code and for setup of whole enviroment on server.
With one command you can transform a plain linux server into server that has installed newest nginx, gunicorn, postgresql etc. and your application is running on it.
When you want all of that, you have to write playbooks. Ansible's playbooks are YAML files which contain tasks. These tasks will setup your server. But when you have tens of tasks you need to put them into seperates files to maintain readability and modularity. Because sometimes you want just to deploy your code not to setup whole server, right? How to do that?
Structure of project
This is how I organize files inside the root of my project that use Ansible:
. ├── ansible/ ├── src/ ├── .ansible-vault-password.txt ├── ansible.cfg └── README.md
Source code is in
src/ directory and all Ansible related files are placed inside
There are also two Ansible files in the root. First,
.ansible-vault-password.txt store password
for Vault files. Vault enables Ansible to use variables from encrypted files. This is great
because you can safely push your encrypted files to git repository
(this also means you can't push .ansible-vault-password.txt to git). Second file,
is config file for Ansible. In my case it mostly says to Ansible to use
for decrypting files.
Structure of Ansible files
ansible/ directory looks like this:
ansible/ ├── group_vars │ ├── all.yml │ ├── production │ │ ├── vars.yml │ │ └── vault.yml │ └── staging │ ├── vars.yml │ └── vault.yml ├── roles │ ├── base │ │ └── tasks │ ├── server │ │ ├── handlers │ │ ├── tasks │ │ │ ├── main.yml │ │ │ ├── setup_db.yml │ │ │ ├── setup_gunicorn.yml │ │ │ └── setup_nginx.yml │ │ └── templates │ │ ├── gunicorn_start.j2 │ │ └── nginx_site_config.j2 │ └── web │ ├── tasks │ └── templates ├── hosts_production ├── hosts_vagrant ├── production.yml └── vagrant.yml
hosts_production, hosts_vagrant - addresses of servers (can be IP) with login information
production.yml, vagrant.yml - contain main task and variables
This directory contains variables that are used in tasks.
all.yml - General variables that are same on production and also staging - like application name, server name
production/vars.yml - Variables that are specific for the enviroment - different paths, enable/disable debug mode, ssl
production/vault.yml - encrypted file with variables like passwords to database and etc
roles/ directory are placed playbooks with tasks. They are grouped together into directories
by purpose of task they contain.
base/ - Installation of general packages that are need to monitor and work on the server.
server/ - Every task you need to setup a web server. Installation of nginx, postgresql, memcached, etc.
Configurations for this tools are in
templates/ directory. Templates use variables from
web - Tasks focused on deploying a new version of your app, running migrations and things you need
to achieve zero downtime.
Provisioning with one command
Now, when you have all of this you can deploy your app to a new server with one command:
ansible-playbook -i ansible/hosts_production ansible/production.yml
Do you have any questions? Write them in comments belove.