Ansible First Steps

Why Ansible?

In the past I would always look up how to configure users, groups, admin privledges and SSH key authentication every time I setup a new server. So I started looking for a solution.

With some experince at work using Puppet I knew about DevOps systems that allowed you to define the state of your server simalarly to the source code used to write applications. I would have used Puppet again but it seemed like overkill for configuring a single personal server.

This lead me to Ansible. It allows you to write out the steps it takes to configure a Unix or Linux server and automate the process. Unlike other similar tools, Ansible needs no specialized server or client installed. It simply uses a suite of utilites that only need to be installed locally and operate over the SSH login shell to your remote server. No need to install any specialized tools on the target server.

Getting Started

Install

You can install Ansible like any other python package or you can install it using your OS's package management system. Personally, I used Homebrew to install it on my MacBook with brew install ansible.

Inventory

Once Asnbile was installed it was time to write an inventory file. While it can be used to create different groups of servers for complex instalations I only use a single host so this step was really simple. I just created a file named inventory and added ericseyden.com to the contents of the file. This will let me point the Ansbile playbooks to my webserver. For this to work I had already configured my DNS entries to point to the newly created Digital Ocean Droplet Fedora 38 instance.

Granting Access

For Ansible to work you must have SSH admin access to the server. I setup this in the usual manner, generate a local SSH key pair, login via the admin panel of my hosing provider and add the public key string of my local key pair, usally in ~/.ssh/id_rsa.pub to the authorized_keys file of the root user.

The Rest Is Automatic

Now sit back and relax, it is time to run the playbook.

ansible-playbook -i inventory create-user.yml

Here is the content of that create user playbook:

- name: Configure User
  hosts: ericseyden.com
  remote_user: root
  tasks:
    - name: Add admins group
      ansible.builtin.group:
        name: admins
        state: present

    - name: Add webmasters group
      ansible.builtin.group:
        name: webmasters
        state: present

    - name: Add eseyden user
      ansible.builtin.user:
        name: eseyden
        groups: admins, wheel, webmasters

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

    - name: Grant passwordless sudo access
      lineinfile:
        dest: /etc/sudoers
        line: "%admins ALL=(ALL) NOPASSWD: ALL"
        validate: visudo -cf %s
        insertafter: EOF
        state: present

    - name: Install Required Packages
      package:
        name:
          - vim
          - tmux
          - git
        state: present

This file does all the heavy lifting for the tasks I do every time I get a new server running.

  • Creates admins and webmasters groups
  • Creates my user on the system
  • Adds my user to the two new groups
  • Installs my SSH public key to the authorized_keys file
    • Just like we did manually for the root user
  • Sets up passwordless SUDO privledges for the admins group
  • Installs the basic tools needed to get things done

Breaking Down Playbook Components

Lets take a look at the structure of the Ansible playbook. The format of the file is YAML. YAML uses whitespace as control so its importat to pay attention to how things are indented.

The - name: portion of a playbook is for description of each set of things. It will echo this out as the playbook runs so you know what it is trying to do.

hosts: refrences entries in your inventory file, this tells the playbook what server to run on.

remote_user: tells the playbook to run as this user instead of the user running the playbook. On subsequent playbooks, now that SUDO access is configured, I can just run them as eseyden, the user name that I'm logged onto my laptop with. If a playbook needs admin access for the whole thing or a single step you can just use become: yes to tell Ansbile to use SUDO.

The main part of a playbook is the - tasks: section. If you are not familiar with YAML files, the - denotes an array or key value map follows. So - tasks: contains all the steps you want your playbook to acomplish. The options here are limitless, as you can see in my example I use several different types of tasks. From ansible.builtin.group to ansible.posix.authorized_key Ansible provides a wealth of built in tasks that can acomplish most of what you might want to do with a server.