Daily Archives: May 13, 2015

DevOps Automation – Ansible+Semaphore is Indispensable!

Semaphore 2.x is in current release and much of the information regarding the install process below is no longer relevant as the package has been significantly refactored. The developers have made it much easier to install: See the install directions here: https://github.com/ansible-semaphore/semaphore/wiki/Installation

I deviated a bit, but got it up and running in less than 5 minutes. Here’s how:

As root:

#cd /usr/bin
#wget https://github.com/ansible-semaphore/semaphore/releases/download/v2.0.2/semaphore_linux_amd64
#mv semaphore_linux_amd64 semaphore
#chmod a+x semaphore
#semaphore -setup


Note that I already had mysqld running on the server.

As Spire Digital delves deeper in DevOps, I have had the opportunity to test drive a number of automation technologies – Puppet and Chef, of course.  But the open-source, python-based ansible project is far and away my preferred technology for automating server configuration and initial web app deployments and configuration.  It even handles could-based instance provisioning!  One of it’s best features is that it needs no client agent running on the target server – everything is done through ssh using key-based authentication.  We run redhat-flavored VMs (amazon-linux-ami) so installing ansible goes like this:

#sudo yum install epel-release
#sudo yum-config-manager --enable epel
#sudo yum install ansible

And then you have all of ansible’s cli tools available to issue ad-hoc commands via ansible or run playbooks using ansible-playbook.  It gets even better with a GUI.  And while I think that the ansible tower GUI is reasonably priced (especially when compared to puppet’s GUI), I found the semaphore project on github to be lean and very useful – it’s not yet well documented, so you do have to deal with some guesswork or hope the developers will answer questions on the github board for the project, but once you get everything configured and understand how it works, it’s great!

The semaphore application is a node.js app that normally runs under vagrant or docker – I skipped the vagrant/docker, and just set it up as a node.js app directly on a fresh dedicated server.  Two gotchas:

1. need to npm install some modules for dependencies:
async body-parser connect-redis express jade logtrail morgan passport.socketio socket.io bcrypt bugsnag cookie-parser express-session less-middleware mongoose passport serve-static validator

2. need to copy lib/credentials.default.json to lib/credentials.json

Then spin it up running node bin/semaphore.js  -  it will bind to port 80 by default, but you can change that in lib/config.js by changing the exports.port variable.  Point a browser at your install and log in!

What does semaphore do?  So basically it runs playbooks for you.  And here’s how:  Put your playbooks in a git repository (we use bitbucket)  There are only 2 top-level navigation items in semaphore:  Playbooks (which point to the git project)  and Identities (which are private/public ssh keypairs)  You enter keys for the git repository as an identity, then you enter the URL to your repo containing your playbooks and associate it with the right identity.


Semaphore does not use ansible’s default hosts file, so you’ll need to enter hosts and host groups directly into semaphore.

Now you need to enter a Job.  A job is a playbook in your repo – for example if you want to run a playbook from your repository that lives in a subdirectory of the project called “project-deploy” you would enter project-deploy/software-deploy.yaml  as the “Play” (“Name” can be whatever.)



When you click on run for that job, semaphore pulls down the repo into a temp folder and runs ansible-playbook on the .yaml file that you specified – you can monitor the output of the job by going to tasks > see outputtasksCapture

*Protip – semaphore will use the same ssh keypair for fetching the git repo as it will for connecting to the remote host, so you need to be sure that the public key for your git account is also in the authorized_keys file on your target host. You may also need to add an ssh config file to /root/.ssh/config that looks like this:

Host *
  StrictHostKeyChecking no
  CheckHostIp no
  PasswordAuthentication no
  PreferredAuthentications publickey

*Protip2 – semaphore downloads git repos into /root/ as configured in vagrant or docker that works fine, but if you’re working on an install outside of a VM, you need to run semaphore as root.

Here’s an example playbook that ensures a server has everything we need to run our app:

- hosts: testservers
# set the php version that needs to run on the server here
# and ansible will pull in the relevant vars file for that version
# it does not matter if php is currently on the image as this playbook
# completely uninstalls any version and replaces it with the version
# specified here.
# [email protected] - 05/13/15
phpversion: 55
- software-vars-php{{ phpversion }}.yaml
gather_facts: true
remote_user: ec2-user
become: yes

- name: Install EPEL repo.
yum: name={{ repo_package }} state=latest

- name: enable EPEL.
shell: yum-config-manager --enable {{ repo_name }}

- name: clean up any existing php.
yum: name=php* state=absent

- name: clean up any existing php54.
yum: name=php54* state=absent

- name: clean up any existing php55.
yum: name=php55* state=absent

- name: clean up any existing php56.
yum: name=php56* state=absent

- name: Next - update all core packages
yum: name=* state=latest

- name: Then, install required system packages.
yum: name={{ item }} state=latest
with_items: "{{ system_packages }}"

- name: Now, install required npm packages.
npm: name={{ item }} global=yes
with_items: "{{ npm_packages }}"

- name: Install apache security configuration file.
copy: src=conf/x-secure.conf dest=/etc/httpd/conf.d/x-secure.conf

- name: And, restart httpd services.
service: name=httpd state=restarted

- name: Almost done - now enable httpd service at boot.
shell: chkconfig httpd on

- name: Finally, enable mysqld service at boot.
shell: chkconfig mysqld on

And here is the associated variables file:

repo_package: epel-release
repo_name: epel
- git
- httpd24
- httpd24-tools
- httpd24-devel
- mod24_ssl
- php55
- php55-bcmath
- php55-cli
- php55-common
- php55-dba
- php55-devel
- php55-gd
- php55-imap
- php55-intl
- php55-ldap
- php55-mbstring
- php55-mcrypt
- php55-mysqlnd
- php55-odbc
- php55-pdo
- php55-pecl-jsonc
- php55-pecl-jsonc-devel
- php55-pecl-memcached
- php55-pecl-oauth
- php55-pecl-redis
- php55-pecl-ssh2
- php55-pgsql
- php55-pspell
- php55-soap
- php55-tidy
- php55-xml
- php55-xmlrpc
- mysql55-server
- redis
- npm
- nodejs
- mongodb
- bower
- npmlog
- node-uuid


Git yourself some semaphore here: https://github.com/ansible-semaphore/semaphore