TL;DR: If you're tired of setting up your infrastructure manually try Ansible. When you get tired of writing Ansible code - try our Cookiecutter Django Ansible. It generates Ansible code that fits the needs of every django project. A demo cookiecutted project can be found here.
More automation - more time for beer!
What is Ansible and why are we using it?
Django is a great framework when it comes to productivity. But what happens when it comes to deployment on a VPS? Who is going to setup the infrastructure and how? Do we really have to deal with all the postgres configuration, nginx files and upstart jobs that keep our gunicorns alive? :(
Of course we do! We are developers and we have to know all of those details but we don't really have to do them manually for every Django project that we maintain.
Ansible is an open source automation platform. It is the simplest solution out there and it is very powerful. You can use Ansible to manage your infrastructure, deploy your application and automate tasks. It is so simple that their motto is: "Automation for everyone!"
The main idea is that you can write a human readable code called Ansible role. After that you can run the role and Ansible is going to follow your instructions and setup your server or a group of servers.
Here is a peace of Ansible code that everyone can understand:
- name: Ensure nginx is installed apt: name=nginx state=installed - name: Ensure that the default site is disabled file: path=/etc/nginx/sites-enabled/default state=absent notify: reload nginx - name: Ensure Nginx service is started service: name=nginx state=started enabled=yes
The benefits of using Ansible are:
- It gives you the ability to keep your configuration in code and push it to a repository.
- That means configuration history and configuration state.
- An easy way to provision a couple of identical machines for horizontal scaling.
- You don't have to describe the setup in a documentation any more. Your code is your documentation.
- In theory it is distribution agnostic. You can run Ansible code no matter what the linux distribution of your VPS is.
Of course, you can host your Django app on a PaaS like Heroku, but it is not always worth it and it is a topic for another blog post.
What is Cookiecutter Django Ansible?
The first time you write Ansible code for your Django project it is fun but, when you have to support multiple Ansibles for multiple Django projects is more of a copy pasting then writing. This is where the Cookiecutter Django Ansible comes in place.
Cookiecutter Django Ansible is a code generator that generates production ready Ansible code. By asking you a series of questions for the most common Django cases, it generates Ansible code you can run afterwards and setup your infrastructure.
The generated Ansible code:
- Supports Staging and Production environment.
- Supports full ssl automation via letsencrypt.
- Support celery with rabbitmq.
- Handles deployment via ansistrano.
- Setups postgres and nginx.
- Handles your team's public keys storing.
- Comes with a README.md file with examples of how it works.
It is an open source project that uses cookiecutter as a code generation engine. It is inspired by the guys from cookiecutter-django that put their brains together to come with the best way to set up your django project. Our idea is the same but for generating Ansible code.
How to use it?
1. Launch a VPS
You can make the Ansible code work with you VPS provider's API to power on and off servers automatically but we are going to make this step manual today.
2. Redirect a domain to the new IP
Once again we can automate this step too. However our trusted VPS provider kyup.com provides an easy to use interface for that.
3. Cookiecut the Ansible code.
$ pip install cookiecutter $ cookiecutter gh:HackSoftware/cookiecutter-django-ansible
Here comes the interesting part. Cookiecutter Django Ansible asks you a series of questions in order to generate the Ansible code that fits your needs.
ansible_project_name [Name of the Ansible project]: hacksoft-ansible ansible_project_slug [hacksoft-ansible]: hacksoft-ansible application_name [Name of the project]: hacksoft application_slug [hacksoft]: application_user [hack]: hack application_root [/hack/hacksoft/]: /hack/hacksoft/ staging_server_domain [staging.example.com]: staging.hacksoft.io production_server_domain [example.com]: hacksoft.io add_your_pulic_key [y]: y add_celery_support [n]: n add_letsencrypt_certificate [y]: y letsencrypt_email [support@production_server_domain]: firstname.lastname@example.org project_git_remote [email@example.com:HackSoftware/cookiecutter-django-ansible.git]: firstname.lastname@example.org:HackSoftware/hacksoft.io.git
Done! Our Ansible code is generated in a directory named like the
ansible_project_slug value. In our case
4. Provision your VPS with the generated Ansible code.
The generated project provides a good README.md file that is going to answer most of your questions. It is a great idea to push the generated Ansible code in a private repository.
Let's install Ansible. Keep in mind that Ansible is stable only for python2 ATM. So run this commands in python2 virtual environment
$ pip install ansible
Now that we have Ansible installed on our machine we have to install all the required Ansible dependencies. ansible-galaxy is the package manager here.
$ ansible-galaxy install -r roles/requirements.yml
Now we have everything installed, generated and ready to run! Let's provision our server!
$ ansible-playbook -i production sites.yml
This is going to take a while (up to 5min) so grab a coffee while Ansible is doing everything that you were doing manually.
5. Deploy the project
Now that your VPS is fully provisioned It's ready for your code.
$ ansible-playbook -i production deploy.yml
Ansistrano gets the latest version from the master branch of your repository and paces it on the provisioned server. After that it does the normal post-deploy procedures for every Django project:
- Run Migrations
- Collect static files
- Restart the gunicorn workers
The best part about code generation.
You can use this Cookiecutter tool to save the first couple of hours writing Ansible.
Furthermore it is very flexible! If your Djagno project is more exotic and requires a custom setup you can just edit the generated code.
Why did we opensource it?
It really does the job for us! It saves a ton of time and it makes our setups almost identical. Our clients love to receive Ansible code instead of setup documentation. We think that it could fit your needs too.
The other benefit is that by opensourcing it we can receive some feedback and improve our Ansible code and our current setups.
The next steps
In the roadmap of the project:
- Add Redis support
- Add Daphne support for Django channels
- Add Celery beat scheduler support
- Write some Ansible tests
The long term idea is to collect feedback. So if you feel like you can contribute to the project, please raise a discussion in GitHub!