Chef install apt packages when apt requires confirmation

I am writing a new chef recipe to upgrade rabbitmq-server packages to a newer version. The packages regularly installed were the ones provided by ubuntu but a newer version were requested from the dev team. Fortunately the nice folks at rabbitmq provide a very up to date apt repository which is the one I am using in the new recipe.

For specific reasons, the old recipe replaced rabbitmq init script using a chef template. When the new recipe was run to upgrade the package chef was not able to upgrade the package and stopped. The reason was that apt asked chef what to do with the modified init script and chef did not know what to do about it. Typically when you try to manually upgrade a package with a config file modified this is what you get:

After some googling I found help in an opscode forum post. The solution is very easy, you just need to add a dpkg option to the package resource specifying what you want to do (install, keep).

package "rabbitmq-server" do
action :upgrade
version "2.8.2-1"
options "-o Dpkg::Options::='--force-confnew'"

With the code above chef is able to pass apt the desired option and subsequently install the package.


I just wrote a simple ruby script that tracks audio file in the iTunes music folder and then searches its existence in iTunes library, cleaning files not present in iTunes. The reason is that sometimes iTunes does not ask to delete the files from disk when you are removing files from the library, or sometimes you press the wrong button when iTunes asks.

The script help me to free a couple of Gigabytes in my saturated hard disk. Check it out:

Chef management of shell users and groups

I just found another pearl in the chef mailing list.

If you want to manage shell users and groups so your uid and gid have the same number there’s an small hack to solve it. You don’t need to specify uid or gid but just be sure the user is included in the group.

See the example extracted from the post:

user "jboss"

group "jboss" do
  members [ 'jboss', 'adam', 'jesse' ]
Forcing a chef run on an specific attribute

After bootstraping some nodes on ec2 I found that knife registers the private EC2 address as the fqdn attribute on chef-server. When I tried to run something like this

knife ssh -x  therobot "ec2:*" "sudo chef-client"

knife miserably failed in resolving the ip addresses of the nodes. I contacted opscode support to clear things up and i got a knice tip. You can use the -a option in knife ssh to specify a certain attribute to look for in order to connect to the nodes:

knife ssh -x therobot -a ec2.public_hostname "ec2:*" "sudo chef-client"
Chef tip: set node value from script output.

I Just found this on chef mailing list,

If you need to set a node value with the output of a script you just need the following code:

node[:myattribute] = %x[/usr/bin/myscript]  
Using fog for attaching AWS elastic ip addresses to servers

Fog is the most promising way of interacting with ruby services, it supports lots of them but it lacks good documentation and examples. Many people find confortable to dive into the source if no documentation is available, but from us sysadmins coding more and more in this days good documentation is a boon.

I did not find any examples on how to do what this post title announces on google or fog doc, so I am explaining it here in hopes other will find it useful:

# Let's supose we have a hash with the following information: 
# aws-id, elastic_ip

elastic_ips = { 
"AWS-ID1" => "", 
"AWS-ID2" => ""  }

# First we get a connection object from amazon, region is 
# required if your instances are in other zone than the
# gem's default one (us-east-1).

c = Fog::Compute.new( 
    :provider => 'AWS',
    :aws_secret_access_key => $aws_secret_access_key,
    :aws_access_key_id => $aws_access_key_id,
    :region => $aws_region )

# Then we iterate over the nodes to associate each of them
# to an elastic ip address

c.servers.each do |server|
  c.associate_address server.id, elastic_ips[server.id]

And that’s it, simple and elegant.

Remove an ip banned by denyhosts

Denyhosts is a great tool to secure ssh accesses. Accidentally, from time to time an IP address from a valid user is banned (guys, use public key ssh authentication!). Removing an IP address from denyhosts ban lists is painful. You have to edit six files. So this small script comes to rescue and eliminates the pain.

Let me introduce you to unban-ip:

#!/usr/bin/env ruby

base_path = "/var/lib/denyhosts"
hosts_deny = "/etc/hosts.deny"
dh_files = %w(hosts hosts-restricted 
                    hosts-root hosts-valid users-hosts)

files = 
dh_files.map{|f| "#{base_path}/#{f}"}.push hosts_deny

denyhosts_stop = "/etc/init.d/denyhosts stop"
denyhosts_start = "/etc/init.d/denyhosts start"

if ARGV.length! = 1
  puts "Wrong number of arguments"
  puts "Usage: unban-ip"

  ip = ARGV[0]
  files.each do |file|
    text = File.read(file)
    buffer = file == hosts_deny ? 
                              text.gsub(/sshd: #{ip}\n/,"") 
                              : text.gsub(/#{ip}:(.*)\n/,"")
    File.open(file,"w") {|fw| fw.write buffer }

Easy piece.


I can’t find anything fancy and original to write in this first post, so I’d better lay down a music video.

Welcome to opsrobot.