Using Ansible To Bootstrap Ubuntu

After creating a new VPS Ubuntu instance, one of the first things I do is lock down root access and create an administrator account.

I was using Fabric to push out these modifications. Recently, however, I decided to switch to Ansible instead.

Tasks

Here are the tasks this playbook needs to perform:

  1. Install ansible requirements.
  2. Create administrator user account.
  3. Add administrator account to sudo group.
  4. Add public keys from GitHub to authorized keys.
  5. Add firewall with SSH hole
  6. Secure SSH:
    • Fail2Ban
    • Disable password auth
    • Disable root login

Playbook

This is the resulting playbook:

Running it

An example of a playbook run:

$ git clone https://gist.github.com/efed5a81b1622acfebf9.git
Cloning into 'efed5a81b1622acfebf9'...
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
Checking connectivity... done.

$ cd efed5a81b1622acfebf9/

$ ansible-playbook -i 'amelia.belm.info,' -e 'admin_user=admin' -e 'github_user=belminf' bootstrap.yaml

PLAY [all] ********************************************************************

TASK: [verify python installed] ***********************************************
The authenticity of host 'amelia.belm.info (192.168.55.12)' can't be established.
ECDSA key fingerprint is SHA256:Ih25OXlSJzQFkkug+2zzAP/IInaU0txqdhamMi7l2iM.
Are you sure you want to continue connecting (yes/no)? yes
failed: [amelia.belm.info] => {"rc": 1}
...ignoring

TASK: [install python] ********************************************************
ok: [amelia.belm.info]

TASK: [sudoers for authkey-only auth] *****************************************
changed: [amelia.belm.info]

TASK: [add admin user accounts] ***********************************************
changed: [amelia.belm.info]

TASK: [add pubkeys from GitHub] ***********************************************
changed: [amelia.belm.info]

TASK: [install fail2ban] ******************************************************
changed: [amelia.belm.info]

TASK: [ensure fail2ban enabled] ***********************************************
ok: [amelia.belm.info]

TASK: [add SSH ufw rule] ******************************************************
ok: [amelia.belm.info]

TASK: [set default ufw policy] ************************************************
changed: [amelia.belm.info]

TASK: [disable SSH password auth] *********************************************
changed: [amelia.belm.info]

TASK: [disable SSH root logins] ***********************************************
changed: [amelia.belm.info]

NOTIFIED: [restart fail2ban] **************************************************
changed: [amelia.belm.info]

NOTIFIED: [restart SSH] *******************************************************
changed: [amelia.belm.info]

PLAY RECAP ********************************************************************
amelia.belm.info         : ok=13   changed=9    unreachable=0    failed=0

Conclusion

I kept this to the absolute minimuim required to lock down the root account and create an administrator account. Everything else I do with a more comprehensive playbook.

Tested successfully on Ubuntu 14.04 and 15.10 with Ansible 1.9.4.