Andoni Rodríguez


Articulos

DigitalOcean tutorial as Ansible Playbook


Turning Ubuntu server DigitalOcean tutorial on ansible-playbook.

DigitalOcean Logo

DigitalOcean has, in my opinion, the best tutorials of the moment, I visit this one a lot Initial Server Setup with Ubuntu 16.04, where they explain how to mount Ubuntu server in one of its droplets.

DigitalOcean is a cloud infrastructure provider focused on simplifying web infrastructure for software developers.

DigitalOcean calls its virtual servers, Droplets; each Droplet that you spin up is a new virtual server for your personal use.

I've visited that tutorial many times, so many, I have decided to make it into an ansible-playbook to have it automated so that every time I want to launch a new droplet with Ubuntu I just have to run a command.

The command I throw is as follows:

$ ansible-playbook create_droplet.yml -vv

And this is the playbook I use:

# DigitalOcean Playbook
---
- name: DigitalOcean
  hosts: localhost
  connection: local
  gather_facts: False

  tasks:

  - name: Include the variables for droplet creation
    include_vars: group_vars/droplet

  - name: Create Droplet
    digital_ocean:
      state: present
      command: droplet
      name: "{{ droplet_name }}"
      api_token: "{{ digital_ocean_api_token }}"
      size_id: "{{ droplet_size }}"
      region_id: "{{ droplet_region }}"
      image_id: "{{ droplet_image }}"
      ssh_key_ids: "{{ droplet_ssh_key_id }}"
      wait_timeout: 500
    register: droplet_info


  - name: Add new instance to host group
    add_host: hostname={{ droplet_info.droplet.ip_address }} groupname=digital_ocean_droplet

  - name: Wait for SSH to come up
    wait_for: host={{ droplet_info.droplet.ip_address }} port=22 delay=10 timeout=60 state=started

- name: Configure Ubuntu Droplet for user directives
  hosts: digital_ocean_droplet
  remote_user: root
  gather_facts: False

  pre_tasks:

    - name: Install python2 necessary for Ansible
      raw: sudo apt-get -y install python-simplejson

  tasks:

    - name: Create a user with sudo privileges
      user:
        name: dropletuser
        state: present
        shell: /bin/bash
        groups: sudo

    - name: Set authorized key with id_rsa.pub home file
      authorized_key:
        user: dropletuser
        state: present
        key: "{{ lookup('file', lookup('env','HOME') + '/.ssh/id_rsa.pub') }}"

    - name: Allow run commands as root with dropletuser
      shell: "echo '%sudo ALL=NOPASSWD: ALL' >> /etc/sudoers"


- name: Configure Droplet
  hosts: digital_ocean_droplet
  remote_user: dropletuser
  gather_facts: True

  tasks:

    - name: Install Vim package
      sudo : yes
      apt:
        name: vim
        state: present
        update_cache: yes

    - name: Install htop
      sudo : yes
      apt:
        name: htop
        state: present
        update_cache: yes

    - name: Enable OpenSSH
      sudo: yes
      ufw:
        rule: allow
        name: OpenSSH

I'll explain each part of the playbook in detail:

  tasks:

  - name: Include the variables for droplet creation
    include_vars: group_vars/droplet

  - name: Create Droplet
    digital_ocean:
      state: present
      command: droplet
      name: "{{ droplet_name }}"
      api_token: "{{ digital_ocean_api_token }}"
      size_id: "{{ droplet_size }}"
      region_id: "{{ droplet_region }}"
      image_id: "{{ droplet_image }}"
      ssh_key_ids: "{{ droplet_ssh_key_id }}"
      wait_timeout: 500
    register: droplet_info


  - name: Add new instance to host group
    add_host: hostname={{ droplet_info.droplet.ip_address }} groupname=digital_ocean_droplet

  - name: Wait for SSH to come up
    wait_for: host={{ droplet_info.droplet.ip_address }} port=22 delay=10 timeout=60 state=started

In the first part of the playbook I read the variables that I will use from the external file 'group_vars/droplet', you'll have to see that it has:

droplet_region: ams2
digital_ocean_api_token: 
droplet_size: 512mb
droplet_image: ubuntu-16-04-x64
droplet_name: Ubuntu 16.04 Droplet
droplet_ssh_key_id: 

'droplet_region', is the region in which we want to deploy the droplet, in this case in ams2 (Amsterdam 2), the list of available regions is this:

"regions": ["ams1", "ams2", "ams3", "blr1", "fra1", "lon1", "nyc1", "nyc2", "nyc3", "sfo1", "sfo2", "sgp1", "tor1"]

'digital_ocean_api_token', is the Token API that we have to generate to be able to perform operations with DigitalOcean, if you don't have one you can generate it in this url: https://cloud.digitalocean.com/settings/api/tokens

'droplet_size', is the type of droplet that we want to deploy, in this case I have chosen the option '512mb' because it's the cheapest one, the following link is all available: https://www.digitalocean.com/pricing/#droplet

The list of options for 'droplet_size' is as follows:

"sizes": ["512mb", "1gb", "2gb", "4gb", "8gb", "16gb", "32gb", "48gb", "64gb"]

'droplet_image', refers to the base image that we are going to use for the droplet, because the DigitalOcean tutorial is from Ubuntu 16.04, we'll use that.

'droplet_name', is simply the name we want to give the droplet.

'droplet_ssh_key_id', this is an important option, since we don't use any type of passwords, we need to have a key ssh created in DigitalOcean (https://cloud.digitalocean.com/settings/security) and we also need to know its id. To know the id, I use this playbook:

# DigitalOcean Info Playbook
---
- name: DigitalOcean
  hosts: localhost
  connection: local
  gather_facts: False

  tasks:

  - name: Include variables
    include_vars: group_vars/droplet

  - name: Info ssh
    digital_ocean:
      state: present
      command: ssh
      name: .your name id here.
      ssh_pub_key: 'ssh-rsa ... .pub key here.'
      api_token: "{{ digital_ocean_api_token }}"

It is executed as follows:

$ ansible-playbook info.yml -vv

Later, with the module digital_ocean of ansible http://docs.ansible.com/ansible/digital_ocean_module.html, I create the doplet, register the information in a variable 'droplet_info', which I use later to connect to the host and to be able to configure it. I also check that the droplet is raised by checking if you have port 22 (SSH) listening.

What comes next is the own configuration of the droplet according to the tutorial of DigitalOcean, lets go with it:

- name: Configure Ubuntu Droplet for user directives
  hosts: digital_ocean_droplet
  remote_user: root
  gather_facts: False

  pre_tasks:

    - name: Install python2 necessary for Ansible
      raw: sudo apt-get -y install python-simplejson

  tasks:

    - name: Create a user with sudo privileges
      user:
        name: dropletuser
        state: present
        shell: /bin/bash
        groups: sudo

    - name: Set authorized key with id_rsa.pub home file
      authorized_key:
        user: dropletuser
        state: present
        key: "{{ lookup('file', lookup('env','HOME') + '/.ssh/id_rsa.pub') }}"

    - name: Allow run commands as root with dropletuser
      shell: "echo '%sudo ALL=NOPASSWD: ALL' >> /etc/sudoers"

In the 'pre_tasks' section, I installed pyhton2, since the Ansible version I use needs python2 and Ubuntu server 16.04 comes with python3 by default, I use the raw module for it http://docs.ansible.com/ansible/raw_module.html

The next thing the tutorial does is create a new user, generate a ssh key, upload it and give it privileges to execute commands as root. I do it through the modules user, authorized_key, and adding a line in the file 'sudoers' so that it does not ask me password when I do sudo.

The part of the tutorial where it disables password is not necessary because its already done by default when creating the droplet without any type of passwords.

The only thing left to do is to enable with the ufw module(http://docs.ansible.com/ansible/ufw_module.html), the OpenSSH protocol:

- name: Configure Droplet
  hosts: digital_ocean_droplet
  remote_user: dropletuser
  gather_facts: True

  tasks:

    - name: Install Vim package
      sudo : yes
      apt:
        name: vim
        state: present
        update_cache: yes

    - name: Install htop
      sudo : yes
      apt:
        name: htop
        state: present
        update_cache: yes

    - name: Enable OpenSSH
      sudo: yes
      ufw:
        rule: allow
        name: OpenSSH

I also installed a couple of packages on my own, vim and htop, which I always use on my servers.

With this the playbook is explained, after running it we can connect as follows:

$ ssh dropletuser@.ippublichere.

If everything went well we should see something like this:

⇒  ssh dropletuser@.ippublichere.
Warning: Permanently added 'xxx.xx.xx.xx' (RSA) to the list of known hosts.
Welcome to Ubuntu 16.04.2 LTS (GNU/Linux 4.4.0-72-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

10 packages can be updated.
10 updates are security updates.


dropletuser@ubuntu:~$ 

And that's it, I hope this little playbook can help someone, I'll leave the link to Github in case you want to take a look.

Regards.