Backup your Bluehost server remotely with Ansible description

Posted on May 1, 2014
tl;dr: I created a simple Ansible playbook to dump databases and folders from a Bluehost shared hosting, ideal for automating backups using a cron job, you can get the source code for this playbook in https://github.com/jcalonso/ansible-bluehost-backup.

After all the incidents with the Heartbleed bug and security issues, I decided to audit my servers to spot security flaws, some days ago I started redirecting all the system and application logs to papertrailapp.com a simple service to centralise all your logs and create alerts, search, store them, etc. After that I started thinking in a better way to secure my information and automate backups of multiple sites and databases I have a across multiple hosting providers.

One of those providers is Bluehost, a very popular shared hosting service. If you have some experience with shared hosting you will know there are things that simply are not possible to do in contrast with a VPS or dedicated server. Nevertheless, there is a lot you can do if your provider let you access via ssh. In this post I’ll be showing you how to automate backups using Ansible a simple but powerful tool for managing and automate infrastructure. If you don’t have or don’t know how to access Bluehost via ssh, read this guide.

The Bash way

The first thing that came to my mind before Ansible was a bash script a simple script that would be triggered by a cron job in my home server and use mysql-dump via SCP to dump and copy databases backups into my home server and then rsync to maintain files and folders synced.

The method was fairly simple, but after being working with Ansible for some months I really wanted to create something simpler and cleaner, so after translating that bash script into Ansible I ended up with this playbook:

---
- name: Bluehost backups
  hosts: bluehost
  sudo: False
  vars_files:
    - vars.yml

  tasks:

    - name: Create Backups folder
      file: path={{ remote_bk_dir }} state=directory
      tags:
        - folders
        - databases

    - name: Dump databases
      mysql_db: login_user={{ db_user }} login_host={{ db_host }} login_password={{ db_pass }} name={{ item }} state=dump target={{ remote_bk_dir }}{{ item }}Db.sql.gz
      with_items: databases
      tags:
        - databases

    - name: Compress sites folders
      command: tar -zcvf {{ remote_bk_dir }}{{ item }}.tar {{ item }}
      with_items: folders
      tags:
        - folders

    - name: Fetch databases backups
      fetch: src={{ remote_bk_dir }}{{ item }}Db.sql.gz dest={{ local_bk_dir }} owner={{ fileOwner }} group={{ fileGroup }}
      with_items: databases
      tags:
        - databases

    - name: Fetch folders backups
      fetch: src={{ remote_bk_dir }}{{ item }}.tar dest={{ local_bk_dir }} owner={{ fileOwner }} group={{ fileGroup }}
      with_items: folders
      tags:
        - folders

    - name: Delete temp backup folder from server
      file: path={{ remote_bk_dir }} state=absent
      tags:
        - folders
        - databases

    - name: Send email notification
      local_action: mail msg='System {{ ansible_hostname }} has been successfully backed up.'
                    subject="Ansible-report"
                    body="This databases has been backed up {{ databases }}"
                    from="server@email.com (Bluehost)"
                    to="Your Name <your@email.com>"
      ignore_errors: true
      tags:
        - folders
        - databases
        - notification

If you are curious about the bash script, here is it (it doesn’t have the rsync part for folders, just mysql dump): https://gist.github.com/jcalonso/120f12270535e146226b

Finally, if you want to schedule your backups, you can easily trigger this playbook from a cron job like this (put this in the server that will store the backups):

00 1 * * 0    cd /path/to/playbook; ansible-playbook -i hosts bluehostBackup.yml --tags databases folders

Here you can find the full repository

Let me know what you think in the comments below, and if you have a better ideas to improve it.