Using Ansible to Bootstrap My Work Environment Part 3

In my previous post I dove into crouton specific role items. These were just little bits unique to a Chromebook chroot environment. The bulk of items I can automate with ansible are common to any linux install I might do. I’m focused on Ubuntu for desktop work but given the way ansible works, I can customize this to use with any distribution perhaps segregating an OS-distribution specific role down the road. For now, the vast majority of items are wrapped up in ~/source/ansible-mystuff/roles/common/tasks/main.yml

This is a larger file so let me break it down a bit

- name: install git
  become: yes
  apt:
    name: git
    state: present

- name: send ssh id
  copy:
    src: /home/sharney/.ssh/id_rsa
    dest: /home/sharney/.ssh/id_rsa
    mode: 0600

- name: git configfiles
  become: no
  copy: src={{ item.src }} dest={{ item.dest }}
  with_items:
     - { src: 'dot_gitignore', dest: '/home/sharney/.gitignore' }
     - { src: 'dot_gitignore', dest: '/home/sharney/.gitignore' }
     - { src: 'dot_git', dest: '/home/sharney/.git' }

- name: bitbucket  key to known_hosts
  known_hosts:
    key: "{{ lookup('pipe', 'ssh-keyscan -t rsa bitbucket.org')}}"
    name: bitbucket.org
    state: present

This is the sequential start of everything. git drives so much of this so it’s installed before any other packages. I also have ssh keys which here are just copied but they in fact reside in a private git repository.

The next item uses Ansible’s with_items looping capability to copy some additional git configuration files which will become relevant momentarily. The last item grabs bitbucket.org’s public ssh key piping the STDOUT from ssh-keyscan so I can hit my bitbucket private ‘configfiles’ repo over ssh using the previously imported ssh keys and ssh configuration files:

- name: do configfiles repo
  become: no
  script: /home/sharney/source/ansible-mystuff/configfiles_setup.sh  creates=/home/sharney/configfiles/.configfiles_done

- name: ssh id permissions fix 
  become: no
  file: path=/home/sharney/.ssh/id_rsa mode=0600

Setting up the private configuration files is a bit more involved than a typical git clone so I have a script that I can use to take care of it:

#!/bin/sh

# do the bits to setup configflies repo
if [ ! -d $HOME/configfiles ]; then
    mkdir $HOME/configfiles 
    cd $HOME
    git clone --no-checkout git@bitbucket.org:scott_harney/configfiles.git
    git reset --hard origin/master
fi


if [ ! -e $HOME/Dropbox/.tmux.conf ]; then 
    ln -s $HOME/Dropbox/.tmux.conf
fi
if [ ! -e $HOME/Dropbox/.dir_colors ]; then
    ln -s $HOME/Dropbox/.dir_colors
fi

touch $HOME/configfiles/.configfiles_done

This is straight from the digital ocean article describing how to create and use a git repo for private configuration files. I’ve used this for a while to selectively manage my $HOME dot config files. The .git,.gitconfig, and .gitignore files copied in the earlier Ansible play are set up per that article for managing the configfiles repo. I selectively add files to the repo in my $HOME.

The two Dropbox links are files that I originally managed via symlinks from dropbox but ultimately found it was better to manage with git. I just left the links in place so this is a vestige of an earlier approach I tried for managing configuration file data. I could probably fix it with a git mv to put the files in their right place but this is fine. Even if I’m not using Dropbox on a utility host I deploy, it’s not hurting anything.

The next items grab a github ssh key as well, which will be handy for some public repos I clone and then loop over a list of the apt dpkg items I like to have installed.

- name: github key to known_hosts
  known_hosts:
    key: "{{ lookup('pipe', 'ssh-keyscan -t rsa github.com') }}"
    name: github.com
    state: present
    
- name: install packages for emacs and more
  action: apt pkg={{ item }} state=installed install_recommends=yes
  become: yes
  with_items:
    - emacs24
    - emacs24-el
    - pandoc
    - tmux
    - zsh
    - ispell
    - vpnc
    - fonts-hack-ttf
    - ruby
    - ruby-aws-sdk
    - python-pip
    - python-pip-whl
    - virtualenv
    - curl
    - openjdk-8-jre
    - fonts-crosextra-caladea
    - fonts-crosextra-carlito # substituion fonts for ms office. probably need a GUI role

One thing I note here is that there are some packages that are really only relevant in a GUI context. On on an EC2 instance they don’t take up much space and I typically will have the x11 libraries present so I don’t really have that much GUI dependency driven bloat.

As you can see I use emacs but in reality you’ll see below I layer over that with spacemacs. I have the vpnc package I use for Cisco compatible IPSEC VPNs. I have some aws related libraries and python items for python2 support in Xenial. The last two fonts are useful on a full blown linux install where I am using LibreOffice and editing Word docs. They are google produced metric equivalents for Microsoft’s proprietary Calibri and Calisto fonts. I substitute them within LibreOffice as described in this Debian Wiki article

The Java item is kind of annoying as it’s required for s3_website which I use to push this statically generated website to s3. That’s another separate git repo and associated dependencies that I’ll probably break out into another role at some point.

- name: python pip install items
  become: yes
  pip: name={{ item }} state=present
  with_items:
    - powerline-status
    - awscli
    - saws

- name: aws sdk v1 for ruby for awscli
  become: yes
  gem: name=aws-sdk-v1 state=present

These just some python pip and ruby items related to managing AWS. I like the saws enhancement for the standard aws cli. The powerline-status item is related to tmux

- name: check for spacemacs already imported
  stat: path=/home/sharney/.emacs.d/spacemacs.mk
  register: spacemacs_import

- name: mv .emacs.d out of the way for spacemacs if spacemacs not yet deployed
  command: mv /home/sharney/.emacs.d /tmp
  when: spacemacs_import.stat.exists == False

- name: spacemacs
  git: repo=https://github.com/syl20bnr/spacemacs dest=/home/sharney/.emacs.d 
  when: spacemacs_import.stat.exists == False

- name: for spacemacs org-protocol-capture-html
  git: repo=https://github.com/alphapapa/org-protocol-capture-html.git dest=/home/sharney/source/org-protocol-capture-html

- name: fix .emacs.d/private via source copy
  copy: src=/home/sharney/.emacs.d/private/private dest=/home/sharney/.emacs.d/private
  when: spacemacs_import.stat.exists == False
  # note: relying on the fact that the host running ansible has checked out private git repo

This is for spacemacs which I really like. Spacemacs is most often picked up by vi/vim users who want to use the power and extensibility of Emacs but with the vi/vim keymap and modal method of operation they are used to.

I was a heavy user of Emacs for a number of years until I took a job as a Solaris Unix admin. You’d spend a lot of time in single user mode or on servers configured for production use so you didn’t have Emacs installed but typically always had vi. Emacs tramp mode for remote access doesn’t help when you’re on a serial console in single user mode. So I got very comfortable with vi. Eventually, though, I discovered Spacemacs which adds a vi like personality and a whole lot of other features and really like it. It allowed me to rediscover Emacs' org-mode which I use for nearly all of my note taking and documentation.

- name: gen en_US.UTF-8 locale
  become: yes
  locale_gen: name=en_US.UTF-8 state=present

- name: set default locale to en_US.UTF-8
  become: yes
  command: /usr/sbin/update-locale LANG=en_US.UTF-8

- name: symlink for dir_colors
  file: src=/home/sharney/Dropbox/.dir_colors path=/home/sharney/.dir_colors state=link

- name: symlink for .tmux.conf
  file: src=/home/sharney/Dropbox/.tmux.conf path=/home/sharney/.tmux.conf state=link

Here I set the locale so I have a proper timezone. I also set up the symlinks for the two config files that I previously held in Dropbox. Since Ansible is idempotent, repeating this pair of plays that was called in the earlier crouton playbook (actually within a script) is fine.

- name: copy vpnc config
  become: yes
  copy:
    src: vpnc
    dest: /etc
    owner: root
    group: yes
    mode: 0700 

This recursively copies from roles/common/files/vpnc to /etc/vpnc so my vpn client configurations are passed through.

- name: git clone scottharney.com
  git: repo=git@bitbucket.org:scott_harney/scottharney.com.git dest=/home/sharney/scottharney.com

This is also for this website and as I noted earlier probably needs to be split into its own role since s3_website has it’s own requirements and dependencies along with all the jekyll components. Not every host I need a utility config on would need this particular repo and set of tools

- name: install ohmyzsh via git
  git: repo=https://github.com/robbyrussell/oh-my-zsh.git  dest=/home/sharney/.oh-my-zsh depth=1 

- name: fix .zshrc
  copy: src=/home/sharney/.zshrc dest=/home/sharney/.zshrc

This is the last bit of customization for zsh. It copies oh-my-zsh and then copies over my theme. The .zshrc is in my configuration files repo but the zsh install overwrites it. This is equivalent to doing a git checkout ~/.zshrc to reset it.

So those are the common configuration bits. Bootstrapping an AWS EC2 instance and deploying it involves several more steps. That’s covered in part 4

 Share!

 
comments powered by Disqus