Ansible: Gotchas deploying to ubuntu
Ansible (http://www.ansible.com/home) is a pretty cool new system for deploying systems. While using it i pulled out the gotchas that took up some of my time. Many are just unix admin details but some are ansible specific.
Gotcha #1: Shell Types and environment setup
Depending on what kind of shell you are using you might be surprised to learn that some of the files you expect to be sourced aren’t and your environment is messed up. Ansible has taken the stance that you should declare your environment requirements in the playbook rather than sourced shell files. However there are cases where that just isn’t possible and in that case its very important to know what gets sourced when and how to trigger different shell types.
In bash you can:
- enable a login shell with “-l” (ell)
- enable a interactive shell with “-i”
- with sudo you can enable an interactive login shell for a user with “sudo -iu username”
What scripts get read with what shell type can be found here: https://github.com/sstephenson/rbenv/wiki/Unix-shell-initialization
Gotcha #2: Command and shell are different
Ansible offers up two modules for executing arbitrary commands. The “command” module is well documented and states that it can’t handle piping, shell operators or much else. Its pretty much only good for a single non complex command. The shell command defaults to “sh” which is a POSIX standard. However for different *nix you may have different shells symlinked to that executable:
On ubuntu > 6 you have “dash” which is not “bash”. See https://wiki.ubuntu.com/DashAsBinSh
More on this here: http://stackoverflow.com/questions/5725296/difference-between-sh-and-bash
Gotcha #3: RVM
RVM is a pretty nice ruby version manager but it has some subtle issues regarding the first two gotchas.
- RVM works best in bash or zsh which isn’t what ansible guarantees when you run a shell.
- RVM needs its initialization script normally ~/.rvm/scripts/rvm.sh to be sourced for RVM to be added to the path
- RVM functions like “rvm use” will not work by default on noniteractive shells even if you source the initialization script. Instead you can source a particular ruby OR use the RVM binary option
source $(rvm 2.1.2 do rvm env --path)
rvm 2.12 do rvm gemset create my_gemset
More on this here: https://rvm.io/rvm/basics#post-install-configuration and here https://rvm.io/workflow/scripting
Gotcha #4: .bashrc files that return quickly for non interactive shells
Watch out for pregenerated bashrc files that automatically return when the shell isn’t interactive. Often there is a small line at the top that reads
[ -z "$PS1" ] && return
that will automatically return if you aren’t in an interactive shell. This will bite you if you add necessary sourced files to the bottom of your bashrc hastily.
More on this here: https://rvm.io/rvm/basics#post-install-configuration
Gotcha #5: sudoers file isn’t setup correctly
This one is pretty obvious but you should know that when you sudo anything everything from what environment is inherited to what programs you can access is determined by your /etc/sudoers file. Beyond not setting it up correctly you can also have add a type to it. If modifying it with ansible its recommended to validate it with lineinfile
More on this here: http://docs.ansible.com/lineinfile_module.html
More gotchas as i hit them will arrive here