Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


Minimalistic server configuration tool

Necktie is tool for running configuration tasks: setting up new servers and upgrading production servers. You can use it to manage services, mount volumes, change configuration, manage cronjobs, etc.

To install Necktie:

$ gem install necktie --source

To use Necktie:

  1. Write a Necktie file with configurtaion tasks

  2. Include any support files: config, scripts, binaries, etc

  3. git push && cap necktie

Introduction to Necktie:


Necktie is based on Rake, so if you know Rake you already know most of Necktie. This document will teach you the rest.

At the base of your Necktie project there's a file called Necktie (or necktie, or necktie.rb), with a list of tasks. For example:

file "/var/myapp" do
  append "/etc/fstab", "/mnt/myapp /var/myapp none bind\n" unless read("/etc/fstab")["/mnt/myapp"]
  mkdir_p "/var/myapp/"
  sh "mount /var/myapp"

desc "Install/update ruby gems"
task :rubygems do
  FileList["gems/*.gem"].each do |gem|
    install_gem gem
  sh "gem clean"

desc "Setup and start Nginx"
task :nginx do
  rm_rf "/etc/nginx/sites-enabled/*"
  cp "etc/nginx/unicorn.conf", "/etc/nginx/sites-available/"
  ln_sf "/etc/nginx/sites-available/unicorn.conf", "/etc/nginx/sites-enabled/"
  services.start "nginx"

desc "Setup and start Unicorn"
task :unicorn=>[:rubygems, "/var/myapp"] do
  cp "etc/init.d/unicorn", "/etc/init.d/"
  chmod 0750, "/etc/init.d/unicorn"

desc "Perform all tasks for the role app"
task :app=>["/var/myapp", :nginx, :unicorn]

When you run the app task, it runs the tasks that setup the application directory, install gems, configure Nginx and Unicorn. When it's done, you're ready to deploy.

Necktie deals with initial configuration, and also ongoing maintenance. Say you change a configuration file, or add another Gem to the gems directory. Push these changes into your Git repository and run Necktime again. That simple.

Note: In the example above, the nginx and unicorn tasks run each time, you can use them to push out new configurations. In contrast, the /var/myapp file task only runs once, before that directory exists.

cap necktie

I use Capistrano to setup new instances and upgrade existing ones.

You can store your Necktie files in a separate repository, or same repository as your application but in a separate branch.

If using a separate repository, set the variable necktie_url to the URL of the Necktie repository. You can also set necktie_branch to particular branch name, the default is master.

For example:

require "necktie/capistrano"
set :necktie_url, ""

If using the same repository and separate branch, do not set necktie_url. You can set necktie_branch to a particular branch name, the default in this case is necktie. You still need to require “necktie/capistrano”.

To create a new empty branch for Necktie that will live in the same repository as your application (note: make sure to commit all changes first, or you'll lose them):

$ git symbolic-ref HEAD refs/heads/necktie
$ rm .git/index
$ git clean -fdx
$ echo "# My Necktie file" > Necktie
$ git add .
$ git commit -a -m "First commit"
$ git push origin necktie

Rather than switching back and forth, you can clone this repository within your application's working directory:

$ cd myapp
$ git clone -b necktie git:myapp.git .necktie
$ ls necktie

Setting up a new EC2 instance:

cap necktie ROLES=app

Upgrading running instances with new configuration:

git push && cap necktie

Feel the rush

Necktie includes Rush, so you can write tasks like this:

task :memcached do
  unless processes.find { |p| p.cmdline[/memcached\s.*-l\s0.0.0.0/] }
    box["/etc/memcached.conf"].replace_contents! /^-l, "-l"
    services.start "memcached"

You can learn more about Rush here:

Of course, there's also FileUtils, system and sh (courtesy of Rake), so you can also:

# Update whenever we have a newer config file.
file "/etc/nginx/nginx.conf"=>"etc/nginx.conf" do
  cp "etc/nginx.conf", "/etc/nginx/nginx.conf"
  sh "service nginx restart"

The current directory (Dir.pwd and launch_dir) is the root directory of your Necktie repository. You can depend on relative paths when accessing files in your Necktie repository.

Role play

If you have different setups, split them into roles and give each role its own main task. Have that main task depend on all the specific setup tasks for this role. For example:

task :app=>[:rubygems, :nginx, :unicorn, "/var/myapp"]
task :db=>[:mount, :master, :backup]

You can then run Necktie with a list of roles. I recommend using the same roles with Necktie and Capistrano, that way you can:

cap necktie ROLES=app,db

This usage will pass the role names as task names to the necktie command.

If you have only one role, or work frequently with a given role, you can define the default task instead of setting ROLES each time. In your Necktie file add:

task :default=>:app

You may also want to take advantage of different environments, customizing your setup differently between production, staging, etc.

Check the example directory for ideas on how to split large configurations into smaller files and tasks.

Note: As with Rake, command line arguments are either options (see necktie -H), task names (executed in order), or name=value pairs that set environment variables (e.g. RAILS_ENV=production).

gem install

You can use install_gem in one of two ways. You can pass it a gem name and version requirement. For example:

install_gem "unicorn", "~= 0.93"

You can store the gem file in your Necktie repository and install it from there:

install_gem "gems/unicorn-0.93.3.gem"

I prefer the later, not depending on the Gem servers being online when I decide to upgrade.

Since install_gem will only install the same gem/version once, a run-always rubygems.rb task is all you need:

task :rubygems do
  Dir["gems/*.gem"].each do |gem|
    install_gem gem

One on one

You can also run Necktie from the command line directly on the server you're configuring. The first time you run Necktie, it clones the Git repository into the ~/.necktie directory. You'll need to give it the Git URL, like this:

necktie --source app

Subsequent runs use that repository. You can launch the necktie command from anywhere, it will always switch to the ~/.necktie directory, run the tasks and switch back to the previous working directory.

If you want to pull changes from the Git repository, use the -U option:

necktie -U app

If you have read/write access to the Git repository you use that to tweak and add new tasks, and test them out before using your setup in production.


Necktie, copyright (C) 2009 Assaf Arkin, released under the “Use for good, not evil” license (

Includes Rake, created by Jim Weirich and released under the MIT license

Includes Rush, created by Adam Wiggins and released under the MIT License

Includes Session, created by Ara T. Howard and released under the Ruby License

Atomic file write adapted from Rails.

ERB task adapted from Luke Bayes

Developed for managing EC2 instances for