Load Balancing With Nginx


Nginx, the web server, is a fantastically simple and inexpensive front-end load balancer for web applications – large and small. Its ability to handle high loads of concurrency and simply forwarding settings make it an excellent choice.

Although it doesn’t have the bells and whistles of enterprise solutions from Citrix or F5, it is very capable of doing the job, and doing it very well. The biggest down fall, depending on your team’s skill set, is it won’t have a friendly GUI to guide you. The configurations will have to be done in the Nginx configuration files using a text editor.

Don’t let that stop you from deploying Nginx. Many start-ups and relatively large technology companies rely on Nginx for load balancing their web applications.


There are many alternatives, but what follows is my experience of:

  • Deploying an Nginx server on CentOS 6
  • Load balance 3 Apache web servers
  • Web server 1 and 2 are new, powerful servers and should receive most of the connections.
  • Web server 3 is old and should not receive too many connections.
  • Connections should be persistent. This is required to ensure users remain on the same server when they log in, as session information isn’t replicated to other servers.

Server Configuration

Internal Hostname OS Role IP Address
slloadbal01.example.com CentOS 6.5 Nginx Load Balancer
mywebapp01.example.com CentOS 6.5 Apache Web Server
mywebapp02.example.com CentOS 6.5 Apache Web Server
mywebapp03.example.com CentOS 6.5 Apache Web Server
TABLE1 – Frontend load balancers and backend web servers


Application Configuration

Each web application server’s IP address will be assigned the same public hostname, in addition to their real hostnames as listed above. They will each have WordPress installed, with exact same configuration and content.

Website Hostname Application Database Server
www.tctest.com WordPress webdb01.example.com
TABLE2 – DNS information for balanced web service and database

Listing the database isn’t really that relevant to this tutorial, other than to illustrate that the WordPress database is not hosted on any of the web servers.

Installing Nginx

  1. Create a YUM repo file for Nginx.

vi /etc/yum.repos.d/nginx.repo

  1. Add the following lines to it.


name=nginx repo




  1. Save the file and exit the text editor.
  2. Install Nginx.

yum install nginx

Configure Nginx

  1. Open the default site configuration file into a text editor.

vi /etc/nginx/conf.d/default.conf

  1. Add the upstream module to the top of the configuration file. The name back-endcan be replaced with a name of your choosing. All three back-end servers are defined by their internal DNS hostnames. You may use IP addresses instead.

upstream website1 {

server mywebapp01.example.com;

server mywebapp02.example.com;

server mywebapp03.example.com;


  1. Assign weight values to the servers. The lower the value, the more traffic the server will receive relative to the other servers. Both mywebapp01 and mywebapp02 will be assigned a weigh value of 1 to spread load evenly between them. Mywebapp03 will, however, be assigned a higher weight of 5 to minimize its load. It will receive every 7th (1+1+5) connection.

upstream website1 {

server mywebapp01.example.com weight=1;

server mywebapp02.example.com weight=1;

server mywebapp03.example.com weight=5;


  1. We need our users logged into the WordPress CMS to always connect to the same server. If they don’t, the will be shuffled around the servers and constantly having to log in. We use the hash directive to force users to always communicate with the same server.

upstream website1 {


server mywebapp01.example.com weight=1;

server mywebapp02.example.com weight=1;

server mywebapp03.example.com weight=5;


  1. Now we configure the server directive to listen for incoming connections, and then forward them to one of the backend servers. Below the upstream directive, configure the server directive.

server {

listen 80; # Listen on the external interface

server_name www.tctest.com;

location / {

proxy_pass http://website1;



  1. Save the configuration file and exit the text editor.
  2. Reload the default configuration into Nginx.

service nginx reload

Additional Options and Directives

Marking a Server as Down (offline)

You may need to bring one of the servers down for emergency maintenance. And you want to be able to do this without impacting your users. The Down directive will allow you to do this.

upstream website1 {


server mywebapp01.example.com weight=1 down;

server mywebapp02.example.com weight=1;

server mywebapp03.example.com weight=5;


Health Checks

Enable health checks to automatically check the health of each server in an upstream group. By default, each server is checked every 5 seconds by sending an http connection. If the server doesn’t return a 2XX or 3XX status, it is flagged as unhealthy and will no longer have connections forwarded to it.

upstream website1 {

server mywebapp01.example.com;

server mywebapp02.example.com;

server mywebapp03.example.com;




Upstream Server Ports

Unless a port is specified, all requests will be forwarded to port 80. If your back-end web servers are hosting the application on another port, you may specify it at the end of the server name/ip address.

upstream website1 {

server mywebapp01.example.com:8080;

server mywebapp02.example.com:8080;

server mywebapp03.example.com:9000;



Backup Servers

You have a requirement for having a server as a hot backup for when a node unexpectedly goes down. The backup server will only handle traffic when a node goes down, and will remain idle when all nodes are healthy.

upstream website1 {

server mywebapp01.example.com;

server mywebapp02.example.com;

server mywebapp03.example.com;


server mywebbkup01.example.com backup;



More Options and Directives

There are so many different directives to manage Nginx load balancers that it doesn’t make sense to list them all here. I’ve kept is short to highlight popular options. I do recommend that you read through the upstream documentation for a complete list of capabilities.


You now have a functional load balancer for your website, spreading load among three nodes. It may not have all of the bells and whistles of enterprise balancers, but it is very fast and very efficient, and it can balance connections with minimal hardware resources. It certain gives typical hardware load balancers a run for their money, which is why it is used by large Internet web sites all over the world.

If you do need a simple and lightning fast balancer for a web application, I would definitely recommend using Nginx.


Cynefin And Complexity Theory

Introduction To Complex Systems Theory

As an outspoken character, Dave Snowden usually provokes an opinion from most people with whom he comes into contact. Best known for his creation of the ‘known knowns’ to ‘unknown unknowns’ concept, fewer people have studied the official body of work from which this is derived – Cynefin.

However his theories on complex systems theory are undoubtedly provocative and noteworthy.

I’ve found his theories on complex adaptive systems to be of particular relevance to cloud computing, micro-service oriented, adaptive software development.

Below is a pithy but insightful summation of his opinion of traditional management/development practices.


For more, see his full talk on Agile development practices:

AWS VPC Design

Design Considerations for VPCs on AWS

Experiences of building VPCs

Few areas of cloud infrastructure are more important to get right from the start than the IP address layout of one’s Virtual Private Cloud (VPC). VPC design has far-reaching implications for scaling, fault-tolerance and security. It also directly affects the flexibility of your infrastructure: paint yourself into a corner, and you’ll spend ungodly amounts of time migrating instances across subnets to free up address space.

Fortunately, it’s easier to lay out a VPC the right way than the wrong way. You just have to keep a few principles in mind.


Proper subnet layout is the key to a well-functioning VPC. Subnets determine routing, Availability Zone (AZ) distribution, and Network Access Control Lists (NACLs).

The most common mistake I’ve observed around VPC subnetting is the treatment of a VPC like a data center network. VPC’s are not data centers. They are not switches. They are not routers. (Although they perform the jobs of all three.) A VPC is a software-defined network (SDN) optimized for moving massive amounts of packets into, out of and across AWS regions. Your packet is picked up at the front door and dropped off at its destination. It’s as simple as that.

Because of that simplicity, a number of data center and networking-gear issues are eliminated at the outset.

A bit of history: when I first started building data centers in the 90’s, we had 10 Mb/s ethernet switches. Ethernet uses Address Resolution Protocol (ARP) broadcasts to determine who’s where in the switch fabric. Because of that, network segments are chatty in direct proportion to the number of hosts on the broadcast domain. So anything beyond a couple hundred hosts would start to degrade performance. That, combined with the counter-intuitive nature of IPv4 subnet math, led to the practical effect of everyone using 24-bit subnets for different network segments. Three-octet addresses seemed to sit right in the sweet spot of all the constraints.

That thinking is no longer valid in a cloud environment. VPCs support neither broadcast nor multicast. What looks like ARP to the OS is actually the elegant function of the SDN. With that in mind, there is absolutely no reason to hack a VPC into 24-bit subnets. In fact, you have an important reason not to: waste. When you have a “middle-tier” subnet with 254 addresses available (or 128 or 64 or 32 or 16) and you only have 4 middle-tier hosts, the rest of those addresses are unavailable for the remainder of your workloads.

If instead you have a mixed-use subnet with 4,094 addresses, you can squeeze every last IP for autoscaling groups and more. Thus it behooves you to make your subnets as large as possible. Doing so gives you the freedom to dynamically allocate from an enormous pool of addresses.

Generally speaking, there are three primary reasons to create a new subnet:

  1. You need different hosts to route in different ways (for example, internal-only vs. public-facing hosts)
  2. You are distributing your workload across multiple AZs to achieve fault-tolerance. Always, ALWAYS do this.
  3. You have a security requirement that mandates NACLs on a specific address space (for example, the one in which the database with your customers’ personally identifiable information resides)

Let’s look at each of these factors in turn.


All hosts within a VPC can route to all other hosts within a VPC. Period. The only real question is what packets can route into and out of the VPC.

In fact, you could easily have a VPC that doesn’t allow packets to enter or leave at all. Just create a VPC without an Internet Gateway or Virtual Private Gateway. You’ve effectively black-holed it.

A VPC that can’t serve any network traffic would be of dubious value, so let’s just assume that you have an app that you’re making available to the Internet. You add an Internet Gateway and assign some Elastic IP addresses to your hosts. Does this mean they’re publicly accessible? No, it does not. You need to create a route table for whom the Internet Gateway is the default route. You then need to apply that table to one or more subnets. After that, all hosts within those subnets will inherit the routing table. Anything destined for an IP block outside the VPC will go through the Internet Gateway, thus giving your hosts the ability to respond to external traffic.

That said, almost no app wants all its hosts to be publicly accessible. In fact, good security dictates the principle of least privilege. So any host that doesn’t absolutely need to be reachable directly from the outside world shouldn’t be able to send traffic directly out the front door. These hosts will need a different route table from the ones above.

Subnets can have only one route table (though route tables can be applied to more than one subnet). If you want one set of hosts to route differently from another, you need to create a new subnet and apply a new route table to it.


AWS provides geographic distribution out of the box in the form of Availability Zones (AZs). Every region has at least two.

Subnets cannot span multiple AZs. So to achieve fault tolerance, you need to divide your address space among the AZs evenly and create subnets in each. The more AZs, the better: if you have three AZs available, split your address space into four parts and keep the fourth segment as spare capacity.

In case it’s not obvious, the reason you need to divide your address space up evenly is so the layout of each AZ is the same as the others. When you create resources like autoscaling groups, you want them to be evenly distributed. If you create disjointed address blocks, you’re creating a maintenance nightmare for yourself and you will regret it later.


The first layer of defense in a VPC is the tight control you have over what packets can enter and leave.

Above the routing layer are two levels of complementary controls: Security Groups and NACLs. Security Groups are dynamic, stateful and capable of spanning the entire VPC. NACLs are stateless (meaning you need to define inbound and outbound ports), static and subnet-specific.

Generally, you only need both if you want to distribute change control authority over multiple groups of admins. For instance, you might want your sys admin team to control the security groups and your networking team to control the NACL’s. That way, no one party can single-handedly defeat your network restrictions.

In practice, NACLs should be used sparingly and, once created, left alone. Given that they’re subnet-specific and punched down by IP addresses, the complexity of trying to manage traffic at this layer increases geometrically with each additional rule.

Security Groups are where the majority of work gets done. Unless you have a specific use-case like the ones described earlier, you’ll be better served by keeping your security as simple and straightforward as possible. That’s what Security Groups do best.

An Example

The above was meant as a set of abstract guidelines. I’d like to provide a concrete example to show how all this works together in practice.

The simplest way to lay out a VPC is to follow these steps:

  1. Evenly divide your address space across as many AZ’s as possible.
  2. Determine the different kinds of routing you’ll need and the relative number of hosts for each kind.
  3. Create identically-sized subnets in each AZ for each routing need. Give them the same route table.
  4. Leave yourself unallocated space in case you missed something. (Trust me on this one.)

So for our example, let’s create a standard n-tier app with web hosts that are addressable externally. We’ll use as our address space.

The easiest way to lay out a VPC’s address space is to forget about IP ranges and think in terms of subnet masks.

For example, take the address space above. Let’s assume you want to run across all three AZs available to you in us-west–2 so your Mongo cluster can achieve a reliable quorum. Doing this by address ranges would be obnoxious. Instead, you can simply say “I need four blocks—one for each of the three AZs and one spare.” Since subnet masks are binary, every bit you add to the mask divides your space in two. So if you need four blocks, you need two more bits. Your 16-bit becomes four 18-bits. — AZ A — AZ B — AZ C — Spare

Now within each AZ, you determine you want a public subnet, a private subnet and some spare capacity. Your publicly-accessible hosts will be far fewer in number than your internal-only ones, so you decide to give the public subnets half the space of the private ones. To create the separate address spaces, you just keep adding bits. To wit: — AZ A — Private
   — Public
   — Spare

Later on, if you want to add a “Protected” subnet with NACL’s, you just subdivide your Spare space: — AZ A — Private
     — Public
         — Protected
         — Spare

Just make sure whatever you do in one AZ, you duplicate in all the others: — AZ A — Private
      — Public
          — Protected
          — Spare — AZ B — Private
       — Public
           — Protected
           — Spare — AZ C — Private
       — Public
           — Protected
           — Spare — Spare

Your routing tables would look like this:

“Public” — Local  —  Internet Gateway
“Internal-only” (ie, Protected and Private) — Local

Create those two route-tables and then apply them to the correct subnets in each AZ. You’re done.

And in case anyone on your team gets worried about running out of space, show them this table:

    16-bit: 65534 addresses
    18-bit: 16382 addresses
    19-bit: 8190 addresses
    20-bit: 4094 addresses

Obviously, you’re not going to need 4,000 IP addresses for your web servers. That’s not the point. The point is that this VPC has only those routing requirements. There’s no reason to create new subnets in this VPC that don’t need to route differently within the same AZ.


Done properly, this method of planning goes a long way to ensuring you won’t get boxed in by an early decision. Everything that you’ll get into from here — Security Groups, Auto Scaling , Elastic Load Balancing , Amazon Relational Database Service, AWS Direct Connect, and more — will fit neatly into this model.



There are seven key best practices for cloud security that you should implement in order to protect yourself from the next vulnerability and/or wide scale attack:


Securing code is 100% your responsibility, and hackers are continually looking for ways to compromise your applications. Code that has not been thoroughly tested and secure makes it all the more easy for them to do harm. Make sure that security is part of your software development lifecycle: testing your libraries, scanning plugins etc.


Logins are the keys to your kingdom and should be treated as such. Make sure you have a solid access management policy in place, especially concerning those who are granted access on a temporary basis. Integration of all applications and cloud environments into your corporate AD or LDAP centralized authentication model will help with this process as will two factor authentication.


Unpatched software and systems can lead to major issues; keep your environment secure by outlining a process where you update your systems on a regular basis. Consider developing a checking of important procedures, test all updates to confirm that they do not damage or create vulnerabilities before implementation into your live environment.


Log reviews should be an essential component of your organizations security protocols. Logs are now useful for far more than compliance, they become a powerful security tool. You can use log data to monitor for malicious activity and forensic investigation.


No single piece of software is going to handle all of your security needs. You have to implement a defence-in-depth strategy that covers all your responsibilities in the stack. Implement IP tables, web application firewalls, antivirus, intrusion detection, encryption and log management.


Stay informed of the latest vulnerabilities that may affect you, the internet is a wealth of information. Use it to your advantage, search for the breaches and exploits that are happening in your industry.


Finally, as discussed get to know your provider and understand where the lines are drawn, and plan accordingly.

Cyber attacks are going to happen; vulnerabilities and exploits are going to be identified. By having a solid security in depth strategy, coupled with the right tools and people that understand how to respond you will out you into a position to minimise your exposure and risk.



In the public cloud, a key to being secure is a solid understanding of the shared security model that exists between you (the customer) and your cloud provider. Without this, you may make assumptions that your cloud provider is protecting you, when in fact you are actually responsible for particular security functions.

Your cloud provider is responsible for securing the foundational services, such as computer power, storage, database and networking services, but you will be responsible for the configuration of those services. At the network layer, your service provider is responsible for network segmentation, perimeter services, some DDOS and spoofing.

But you are responsible for network threat detection, reporting and any incident reporting. At the host layer, you are responsible for access management, patch management configuration hardening, security monitoring and log analysis. The application security components of your site are 100% your responsibility. The model below shows a breakdown of responsibilities between you and your service provider:

Shared Responsibility Model
Shared Responsibility Model


Understanding your role and the role of your cloud provider will not only help you make the best decision concerning your cloud infrastructure, it will also ensure that once implemented your cybersecurity strategy will efficiently and cost-effectively protect your data from threats to the cloud.

Next we’ll look at how you can protect your online assests with 7 Best Practices for Cloud Security


Although the public cloud comes with great financial and technical benefits, like any other infrastructure, it also has its share of threats. Over the years, we have seen a rise in both attack frequency and diversity of malicious software used. With increases in cloud incidents related to vulnerability scanning, web application attacks and brute force attacks, it is crucial for you to understand the types of threats potentially targeting you on the cloud so you can build a security-in-depth strategy to defend your environment from malicious attacks.

Cloud security reports for 2014 indicated that web application attacks, brute force attacks and vulnerability scans were the most pronounced attacks experienced in the Cloud Hosting Provider environments, each impacting over 40% of the cloud hosting base. Brute force attacks have surged, likely due to the increasing presence of valuable data in the cloud, with vulnerability scans typically coupled with brute force attacks in terms of attack style and process.

Real-time analysis across 2200 customers with 232,364 incidents. Source: Cloud Security Report 2014.
Real-time analysis across 2200 customers with 232,364 incidents. Source: Cloud Security Report 2014.

In the next post we’ll look further at understanding this shared security responsibility model and what you can do to secure your cloud deployments.

Amazon’s Docker service is linking into Apache Mesos for simpler clustering

Amazon’s Docker service is linking into Apache Mesos for simpler clustering

Summary:With cluster management a persistently big issue, recently-launched Amazon container service ECS is aiming to show how it can integrate with Apache Mesos and Marathon.

Amazon’s Docker-centric container service is working on ways to link into Apache Mesos and the popular Marathon services scheduler framework to widen users’ cluster-management options.

Launched last November, Amazon EC2 Container Service, or Amazon ECS, has just unveiled an Apache Mesos scheduler driver as a proof-of-concept integration with Marathon.

The open-source driver, which sends Mesos management commands direct to ECS, is designed to show how Marathon could schedule workloads on ECS.

It is also aimed at demonstrating the core design principles behind the Amazon service, which separates scheduling logic from state management, according to Deepak Singh, who founded and leads ECS.

“This allows you to use the ECS schedulers, write your own schedulers, or integrate with third-party schedulers,” Singh said in a blogpost.

Cluster management is becoming an important issue for developers who are building distributed applications in the cloud.

“A common example of developers interacting with a cluster management system is when you run a MapReduce job via Apache Hadoop or Apache Spark,” Singh said.

“Both these systems typically manage a coordinated cluster of machines working together to perform a large task. In the case of Hadoop or Spark, these tasks are most often data-analysis jobs or machine learning.”

Last week version 0.8.0 of Marathon was released. Mesosphere, a major contributor to the Mesos open-source project, describes it as the most popular framework on Mesos and as being used in large-scale production at a number major companies worldwide.

Singh said cluster management systems face two challenges. The first is the complexity of managing the state of the cluster.

“Software like Hadoop and Spark typically has a Leader, or a part of the software that runs in one place and is in charge of coordination. They’ll then have many, often hundreds or even thousands of Followers, or a part of the software that receives commands from the Leader, executes them, and reports state of their sub-task,” he said.

“When machines fail, the Leader must detect these failures, replace machines, and restart the Followers that receive commands. This can be a significant portion of code written for applications which need access to a large pool of resources.”

The second challenge for cluster management systems is that each application typically assumes full ownership of the machine where its tasks are running.

“You will often end up with multiple clusters of machines, each dedicated fully to the management system in use. This can lead to inefficient distribution of resources, and jobs taking longer to run than if a shared pool of resources could be used,” Singh said.

In the GitHub repository for the Marathon driver, Amazon points out that the software is for demonstration purposes and is “not recommended for production use”.

The company goes on to say: “We are working with the Mesos community to develop a more robust integration between Apache Mesos and Amazon ECS.”

More on Docker and containers

Forrester’s 2015 cloud predictions: Docker rises, storage pricing war claims lives

Forrester’s 2015 cloud predictions: Docker rises, storage pricing war claims lives

Summary:The market analysis company lays out what it sees as the top 10 major cloud developments that will shape the business landscape over the next year.


Cloud computing is a disruptive technology, and resistance to its power is futile.

This is the premise surrounding the latest set of 2015 predictions from Forrester Research, in which the market analysis company lays out what it sees as the top 10 major cloud developments that will shape the business landscape over the next year.

“The landscape for cloud computing changes quickly, so your business technology agenda must adapt just as rapidly,” the report states. “Your business will earn an early mover advantage by keeping ahead of these changes.”

Nadella’s cloud-first strategy, Microsoft could be set to generate more of its revenue from its cloud services than its traditional on-premises applications, Forrester says. For businesses, this means there’s an opportunity to have the upper hand when it comes time to negotiate contracts, as sales teams will want to push as much cloud as possible into each enterprise license agreement.

Back-office applications will need RESTful interfaces.Developers tasked with linking together apps via APIs are going to be on the lookout for services that communicate via REST interfaces, Forrester says. But rather than waiting for REST APIs via an upgrade, companies will look to replace their enterprise service with an API management solution.

Cloud data breaches are a sure thing. Forrester doesn’t mince words with this one, saying that CIOs should expect to encounter a breach in the cloud – and that it will be their fault, not the SaaS provider. “The culprits will likely be common process and governance failures such as poor key management or lack of training or perimeter-based thinking by your security department,” the report states. “A breach of some form is inevitable.”

Docker containers will cement their place. Companies ranging from Google to eBay have jumped on the Docker bandwagon, and Forrester recommends that others follow suit. “Docker is not a fad. It marks a new approach that delivers real benefits, and it is here to stay.”

Hybrid cloud management will finally mature. Forrester says that in 2015, enterprises will start to figure out how to use the tools that are available to expose private cloud resources to their developers, so long as they stop creating artificial boundaries between private and public clouds and their management tools.

Managed private clouds will face a death spiral. The on-premise, remotely managed private cloud is a doomed model, Forrester says. Not only does it offer enterprises no lasting value, it poses far more challenges than potential benefits. Forrester sees managed private clouds dwindling significantly over the next year.

Industry-specific SaaS will surge. For SaaS vendors, the coming year will be ripe with vertical expansions. The reason? To better appeal to enterprise customers, Forrester says. Expect to see Workday break out from education and government, and for Salesforce.com to throw their hat in, too.

SaaS vendors tiptoe toward hybrid. Forrester expects to see SaaS vendors that focus on public-only multi-tenant deployments to begin offering a more hybrid model that includes some on-premise implementations.

Cloud storage pricing wars will claim lives. Basic online backup is not a sustainable businesses when fronted on its own, Forrester says. The companies that realize this the fastest will obviously have a better shot at avoiding casualties. “In 2015, enterprise online backup providers must either make the leap to disaster-recovery-as-a-service (DRaaS) and provide workload availability in addition to data protection or prepare to suffer a similar fate to Symantec Backup Exec cloud.”

ChefDK Setup and Install on Mac

Download the Chef-DK package…

Go to: http://downloads.getchef.com/chef-dk/

Install the package…

Once its installed check it and make sure the install was successful with the following  command:

$ chef verify

– Set System Ruby

$ which ruby

You might see something like this: ~/.rvm/rubies/ruby-2.1.1/bin/ruby

If you want to use the version of ruby that came with ChefDK do the following…assuming you are using BASH…

$ echo ‘eval “$(chef shell-init bash)”‘ >> ~/.bash_profile

$ . ~/.bash_profile

$ which ruby

Install Git if you don’t already have it…

Setting up the chef-repo

You can do this two ways….download the starter kit from your Chef server OR manually. In this case we will do this manually because I already happen to have a hosted Chef account and will copy my keys over from another location. So…go to your designated chef directory and type:

$ git clone git://github.com/opscode/chef-repo.git

Then go to /Path/to/chef-repo/ and do:

mkdir .chef

Three files will need to be placed in this directory:

– knife.rb

– ORGANIZATION-validator.pem

– USER.pem

This directory will house your private keys and personal data. In order to not to commit your .chef directory to your git repository, add this directory to .gitignore as follows:

$ echo ‘.chef’ >> Path/to/chef-repo/.gitignore

Now you need to get the 3 files that go into your .chef directory. Either copy from another location or regenerate these files.

If you need to regenerate these files, follow the instructions below:

Log onto your Chef server. For me this is located at: https://manage.opscode.com

Once logged in click ADMINISTRATION at the top then the name of your organization.

Knife.rb – Click “Generate Knife Config” and download the file. Place it in your .chef directory

ORGANIZATION-validator.pem – can be downloaded by clicking “Reset Validation Key” in the Administration page.

USER.pem – can be downloaded by clicking Users on the left hand side and then choosing your username, and finally clicking “Reset Key“

Now test your chef setup:

$ cd /Path/to/chef-repo

$ knife client list

This will display any chef clients you currently have.

$ knife client list


Here we see only the security validator which will be responsible for managing future servers which we add to our organization.

Getopts Tutorial

−Table of Contents

Small getopts tutorial

When you want to parse commandline arguments in a professional way, getopts is the tool of choice. Unlike its older brother getopt (note the missing s!), it’s a shell builtin command. The advantage is

you don’t need to hand your positional parameters through to an external program
getopts can easily set shell variables you can use for parsing (impossible for an external process!)
you don’t have to argue with several getopt implementations which had buggy concepts in the past (whitespaces, …)
getopts is defined in POSIX®
Some other methods to parse positional parameters (without getopt(s)) are described in: How to handle positional parameters.

Note that getopts is not able to parse GNU-style long options (–myoption) or XF86-style long options (-myoption)!


It’s useful to know what we’re talking about here, so let’s see… Consider the following commandline:

mybackup -x -f /etc/mybackup.conf -r ./foo.txt ./bar.txt
All these are positional parameters, but you can divide them into some logical groups:
-x is an option, a flag, a switch: one character, indroduced by a dash (-)
-f is also an option, but this option has an additional argument (argument to the option -f): /etc/mybackup.conf. This argument is usually separated from its option (by a whitespace or any other splitting character) but that’s not a must, -f/etc/mybackup.conf is valid.
-r depends on the configuration. In this example, -r doesn’t take arguments, so it’s a standalone option, like -x
./foo.txt and ./bar.txt are remaining arguments without any option related. These often are used as mass-arguments (like for example the filenames you specify for cp(1)) or for arguments that don’t need an option to be recognized because of the intended behaviour of the program (like the filename argument you give your text-editor to open and display – why would one need an extra switch for that?). POSIX® calls them operands.
To give you an idea about why getopts is useful: The above commandline could also read like…

mybackup -xrf /etc/mybackup.conf ./foo.txt ./bar.txt
…which is very hard to parse by own code. getopts recognized all the common option formats.
The option flags can be upper- and lowercase characters, and of course digits. It may recognize other characters, but that’s not recommended (usability and maybe problems with special characters).

How it works

In general you need to call getopts several times. Each time it will use “the next” positional parameter (and a possible argument), if parsable, and provide it to you. getopts will not change the positional parameter set — if you want to shift it, you have to do it manually after processing:

shift $((OPTIND-1))
# now do something with $@
Since getopts will set an exit status of FALSE when there’s nothing left to parse, it’s easy to use it in a while-loop:

while getopts …; do

getopts will parse options and their possible arguments. It will stop parsing on the first non-option argument (a string that doesn’t begin with a hyphen (-) that isn’t an argument for any option infront of it). It will also stop parsing when it sees the — (double-hyphen), which means end of options.

Used variables

variable description
OPTIND Holds the index to the next argument to be processed. This is how getopts “remembers” its own status between invocations. Also usefull to shift the positional parameters after processing with getopts. OPTIND is initially set to 1, and needs to be re-set to 1 if you want to parse anything again with getopts
OPTARG This variable is set to any argument for an option found by getopts. It also contains the option flag of an unknown option.
OPTERR (Values 0 or 1) Indicates if Bash should display error messages generated by the getopts builtin. The value is initialized to 1 on every shell startup – so be sure to always set it to 0 if you don’t want to see annoying messages!
getopts also uses these variables for error reporting (they’re set to value-combinations which arent possible in normal operation).

Specify what you want

The base-syntax for getopts is:

OPTSTRING tells getopts which options to expect and where to expect arguments (see below)
VARNAME tells getopts which shell-variable to use for option reporting
ARGS tells getopts to parse these optional words instead of the positional parameters
The option-string

The option-string tells getopts which options to expect and which of them must have an argument. The syntax is very simple — every option character is simply named as is, this example-string would tell getopts to look for -f, -A and -x:

getopts fAx VARNAME
When you want getopts to expect an argument for an option, just place a : (colon) after the proper option flag. If you want -A to expect an argument (i.e. to become -A SOMETHING) just do:

getopts fA:x VARNAME
If the very first character of the option-string is a : (colon), which normally would be nonsense because there’s no option letter preceeding it, getopts switches to the mode “silent error reporting”. In productive scripts, this is usually what you want (handle errors yourself and don’t get disturbed by annoying messages).

Custom arguments to parse

The getopts utility parses the positional parameters of the current shell or function by default (which means it parses “$@”).

You can give your own set of arguments to the utility to parse. Whenever additional arguments are given after the VARNAME parameter, getopts doesn’t try to parse the positional parameters, but these given words.

This way, you are able to parse any option set you like, here for example from an array:

while getopts :f:h opt “${MY_OWN_SET[@]}”; do

A call to getopts without these additional arguments is equivalent to explicitly calling it with “$@”:

getopts … “$@”
Error Reporting

Regarding error-reporting, there are two modes getopts can run in:

verbose mode
silent mode
For productive scripts I recommend to use the silent mode, since everything looks more professional, when you don’t see annoying standard messages. Also it’s easier to handle, since the failure cases are indicated in an easier way.

Verbose Mode

invalid option VARNAME is set to ? (quersion-mark) and OPTARG is unset
required argument not found VARNAME is set to ? (quersion-mark), OPTARG is unset and an error message is printed
Silent Mode

invalid option VARNAME is set to ? (question-mark) and OPTARG is set to the (invalid) option character
required argument not found VARNAME is set to : (colon) and OPTARG contains the option-character in question
Using it

A first example

Enough said – action!

Let’s play with a very simple case: Only one option (-a) expected, without any arguments. Also we disable the verbose error handling by preceeding the whole option string with a colon (:):


while getopts “:a” opt; do
case $opt in
echo “-a was triggered!” >&2
echo “Invalid option: -$OPTARG” >&2
I put that into a file named go_test.sh, which is the name you’ll see below in the examples.
Let’s do some tests:

Calling it without any arguments

$ ./go_test.sh
Nothing happened? Right. getopts didn’t see any valid or invalid options (letters preceeded by a dash), so it wasn’t triggered.
Calling it with non-option arguments

$ ./go_test.sh /etc/passwd
Again — nothing happened. The very same case: getopts didn’t see any valid or invalid options (letters preceeded by a dash), so it wasn’t triggered.
The arguments given to your script are of course accessible as $1 – ${N}.

Calling it with option-arguments

Now let’s trigger getopts: Provide options.

First, an invalid one:

$ ./go_test.sh -b
Invalid option: -b
As expected, getopts didn’t accept this option and acted like told above: It placed ? into $opt and the invalid option character (b) into $OPTARG. With our case statement, we were able to detect this.
Now, a valid one (-a):

$ ./go_test.sh -a
-a was triggered!
You see, the detection works perfectly. The a was put into the variable $opt for our case statement.
Of course it’s possible to mix valid and invalid options when calling:

$ ./go_test.sh -a -x -b -c
-a was triggered!
Invalid option: -x
Invalid option: -b
Invalid option: -c
Finally, it’s of course possible, to give our option multiple times:

$ ./go_test.sh -a -a -a -a
-a was triggered!
-a was triggered!
-a was triggered!
-a was triggered!
The last examples lead us to some points you may consider:

invalid options don’t stop the processing: If you want to stop the script, you have to do it yourself (exit in the right place)
multiple identical options are possible: If you want to disallow these, you have to check manually (e.g. by setting a variable or so)
An option with argument

Let’s extend our example from above. Just a little bit:

-a now takes an argument
on an error, the parsing exits with exit 1

while getopts “:a:” opt; do
case $opt in
echo “-a was triggered, Parameter: $OPTARG” >&2
echo “Invalid option: -$OPTARG” >&2
exit 1
echo “Option -$OPTARG requires an argument.” >&2
exit 1
Let’s do the very same tests we did in the last example:

Calling it without any arguments

$ ./go_test.sh
As above, nothing happend. It wasn’t triggered.
Calling it with non-option arguments

$ ./go_test.sh /etc/passwd
The very same case: It wasn’t triggered.
Calling it with option-arguments

Invalid option:

$ ./go_test.sh -b
Invalid option: -b
As expected, as above, getopts didn’t accept this option and acted like programmed.
Valid option, but without the mandatory argument:

$ ./go_test.sh -a
Option -a requires an argument.
The option was okay, but there is an argument missing.
Let’s provide the argument:

$ ./go_test.sh -a /etc/passwd
-a was triggered, Parameter: /etc/passwd
See also


How do I get it so that with no arguments passed, it returns text saying “no arguments password, nothing triggered”?

I’d do it by checking $# before the while/getopts loop, if applicable:

if (($# == 0)); then

If you really need to check if getopts found something to process you could make up a variable for that check:


while getopts “:xyz” opt; do


if ((!options_found)); then
echo “no options found”

Another method of checking whether it found anything at all is to run a separate if statement right before the while getopts call.

if ( ! getopts “abc:deh” opt); then
echo “Usage: `basename $0` options (-ab) (-c value) (-d) (-e) -h for help”;

while etopts “abc:deh” opt; do
case $opt in
a) do something;;
b) do another;;
c) var=$OPTARG;;


try this trick. When you discover that OPTARG von -c is something beginning with a hyphen, then reset OPTIND and re-run getopts (continue the while loop).

The code is relatively small, but I hope you get the idea.

Oh, of course, this isn’t perfect and needs some more robustness. It’s just an example.


while getopts :abc: opt; do
case $opt in
echo “option a”
echo “option b”
echo “option c”

if [[ $OPTARG = -* ]]; then

echo “(c) argument $OPTARG”
echo “WTF!”
exit 1