Deploying With Ansistrano

I have a major problem. I keep waaay too many open tabs on my phone. Every time I see something interesting – via Twitter, Hacker News, or Reddit – I open the link in a tab and promise myself I will check it out more thoroughly soon.

I currently have 47 open tabs 🙁

This is only amplified by the fact I do the same on desktop. Right now, across three desktops I have over a hundred open tabs.

It’s becoming an epidemic.

Anyway, once in a while, one of these tabs becomes useful.

Recently I hit on a problem whereby I needed to deploy a bunch of individual JavaScript files – node.js scripts – to a server to be used as Rabbit MQ workers.

I had a bunch of requirements for these workers:

  • start with specific flags (–harmony-async-await )
  • restart automatically if the server reboots
  • restart if the script crashes
  • can run multiple instances

And so on.

These turned out to be the superficial problems – and I say this because there’s a tool out there that already nails this problem – PM2.

Initially I thought these would be the hard problems.

What I hadn’t banked on was how much of a royal pain in the backside it might be to deploy my node.js scripts to dev / prod / wherever.


My requirements are fairly straightforward – they could be solved by using rsync. However, rsync becomes unmanageable as a project grows.

There’s the issue of remembering the right command, and then duplicating the command – altering slightly – for the prod deploy.

And what if it goes wrong? Well, you have to handle that yourself.

Call me spoiled, but having become accustomed to Deployer (Matt did a fantastic job on this course btw, you should check it out), I now use that as my baseline for deployments.

I have a similar tool I use on JavaScript projects called Flightplan. It offers a decent level of functionality, but with one major issue (from my p.o.v):

It is a pain to deploy more than one directory.

Flightplan works on the assumption – as best I can tell – that you will be running your project through some webpack-style setup first, producing a dist directory which contains everything you need to boot your single page app, or whatever.

This is cool, but I needed to run many different worker scripts – all ideally from one directory.

As best I understand it, webpack allows this via it’s multiple entry options, but I’m not using webpack. Actually, I tried to use webpack but it threw out a bunch of errors right away and I gave up.

I also tried Deployer. But that didn’t work much good either. JS mixed with PHP leads to mess.

Enter Ansistrano

Ok, so all that was a very long-winded precursor to the eventual solution.

However, I felt I needed to do justice to how much I have struggled to get this thing working. It’s taken 5 hours… ouch.

Needless to say I tried to give up on getting Ansistrano at numerous times (see how I ended up at Deployer, Flightplan, webpack etc).

In the end though, I cracked it. So here goes:

Firstly, my playbook:

- hosts: all

    ansistrano_deploy_to: "/var/www/your/remote/path" # server side path you want to deploy too
    ansistrano_keep_releases: 3

    ansistrano_deploy_via: "git"

    ansistrano_git_repo: "ssh://git@your.gitlab.server/your-gitlab-user/your-project.git"
    ansistrano_git_branch: "master"

    - { role: ansistrano.deploy }

Pay special attention to the ansistrano_git_repo entry, whereby I needed to add the prefix of ssh:// to make this work. If you don’t, you will find Ansible doesn’t understand the path you are providing, and blanks it out instead :/

I guess I wasn’t the only person to notice this.

Also, note that the typical git path given by gitlab will contains colons, which need to be replaced with spaces:

// becomes


Now note, this is an Ansible issue, not an Ansistrano issue.

This should be enough to get most of the way there.

However, I hit upon another issue.

No matter what I did, all the Ansistrano managed folders were being created as root .

Since the days of yore, I have been using the same set of flags on my runs of ansible-playbook, and today I was well and truly bitten on the backside:

ansible-playbook playbook/deploy.yml -i hosts -l -k -K  -vvvv

Ultimately this command sees me through. I’ve started using -vvvv on every playbook run as it saves me having to re-run when things inevitably go wrong. Also, for the love of God, use snapshots before running.

But yeah, my issue was I was running with the additional flag of -s which forced the playbook to run as root. Silly me.

Anyway, early signs are promising. It all works. I just wish it hadn’t taken me so much time to figure out these problems. Hopefully though, by sharing I can save someone some hassle in future.