search by tags

for the user

adventures into the land of the command line

ansible - like puppet but not frustrating

i have this webapp i host on amazon’s free tier (cos im cheap) that i use to show my photos to friends and family. every year, when the free tier expires, i migrate to a new amazon account to keep getting the free tier (cos im cheap). so it’s about that time of year and i had to migrate again, but i didnt want to do everything manually. i wanted to learn how to use ansible to do it. i didn’t know how much effort would be required or anything at all for that matter, so i just jumped in.

now bear in mind, i started from scratch like 3 hours ago and i’ve finished migrating and am writing this post about it now. that’s how easy it was to learn to use ansible. i’m so happy. thank you ansible.

here’s what i did

install ansible on my computer (i installed it in a vagrant vm)

$ sudo pip install ansible

create a deploy user on my computer with some ssh keys

$ sudo useradd -m deploy
$ sudo passwd deploy
$ su - deploy
$ ssh-keygen -t rsa

create a deploy user on the amazon host and copy the public key over to it

$ sudo useradd -m deploy
$ sudo passwd deploy
$ su - deploy
$ mkdir .ssh
$ chmod 700 .ssh
$ vim .ssh/authorized_keys
-- paste the contents of ~/.ssh/id_rsa.pub into here --
$ chmod 600 .ssh/authorized_keys

tell ansible what my host(s) is/are in an ‘inventory’ file

$ sudo mkdir /etc/ansible
$ sudo vim /etc/ansible/hosts

[webserver]
ec2-12-34-56-789.ap-southeast-2.compute.amazonaws.com

test connectivity to the host with ansible

$ ansible all -m ping

ec2-12-34-56-789.ap-southeast-2.compute.amazonaws.com | success >> {
    "changed": false,
    "ping": "pong"
}

create a playbook which contains steps for ansible to install all the things and create directories or files and set permissions and do all the other things you want it to do

$ sudo vim /path/to/playbook.yaml

---
- hosts: webserver
  remote_user: deploy
  sudo: yes
  # install stuff
  tasks:
  - name: install pip
    yum:
      name: python-pip
      state: latest
  - name: install python-devel
    yum:
      name: python-devel
      state: latest
  - name: install gcc
    yum:
      name: gcc
      state: latest
  - name: install nginx
    yum:
      name: nginx
      state: latest
  - name: install Flask
    pip:
      name: Flask
      version: 0.10.1
  - name: install gunicorn
    pip:
      name: gunicorn
      version: 19.3.0
  - name: install supervisor
    pip:
      name: supervisor
      version: 3.1.3
  # create directories and copy config files over
  - name: create www directory
    file:
      path: /var/www
      state: directory
      owner: root
      group: root
      mode: 0775
  - name: create gunicorn log directory
    file:
      path: /var/log/gunicorn
      state: directory
      owner: root
      group: root
      mode: 0775
  - name: ensure flask log file exists
    file:
      path: /var/log/gunicorn/flask.log
      state: touch
      owner: root
      group: root
      mode: 0644
  - name: add the supervisord.conf file
    template:
      src: /path/to/supervisord.conf
      dest: /etc/supervisord.conf
      owner: root
      group: root
      mode: 0644
  - name: add the supervisord startup script
    template:
      src: /path/to/supervisord
      dest: /etc/init.d/supervisord
      owner: root
      group: root
      mode: 0755
  - name: replace the nginx config file
    template:
      src: /path/to/nginx.conf
      dest: /etc/nginx/nginx.conf
      owner: root
      group: root
      mode: 0644
  - name: add the nginx myapp config file
    template:
      src: /path/to/myapp.conf
      dest: /etc/nginx/conf.d/myapp.conf
      owner: root
      group: root
      mode: 0644
  # one hack
  - name: comment out meld3 dependancy in supervisors requires.txt file
    shell: "sudo sed -i 's/meld3/#meld3/' /usr/lib/python2.6/site-packages/supervisor-3.1.3-py2.6.egg-info/requires.txt"
  # pull the code from git
  - git:
      repo: https://github.com/myapp/myapp.git
      dest: /var/www/myapp
  # start the webserver
  - name: ensure supervisor is running (and enable it at boot)
    service:
      name: supervisord
      state: started
      enabled: yes
  # start nginx reverse proxy
  - name: ensure nginx is running (and enable it at boot)
    service:
      name: nginx
      state: started
      enabled: yes

run the play with one fork (number of parallel processes to use, default is 5)

$ ansible-playbook /path/to/playbook.yaml -f 1

PLAY [webserver]