Provisioning a Raspberry Pi using ansible

These are my notes on how to get started provisioning Raspbian with ansible.

Before using ansible

We have to get a working Raspbian installation before using ansible on the device.

Installing Raspbian

The first step is downloading and installing Raspbian in the SD card you're going to use in the Pi. You can find the Raspbian image here: https://www.raspberrypi.org/downloads/raspbian/. Prefer the "lite" image, as it allows you to start from a cleaner point.

To install the image, use an adapter to plug the SD card into a computer. You can figure out the /dev/ device that got assigned by using lsblk before and after plugging the card. Let's assume it got assigned to /dev/sdc, for the sake of illustration. The next step is writting the Raspbian image to it:

  unzip -p *-raspbian-stretch-lite.zip | sudo dd of=/dev/sdc bs=4M oflag=dsync status=progress

You can now insert the card into the Raspberry Pi board.

Initial Raspbian setup

Raspbian comes with a initial user pi, password raspberry, that can use sudo freely. ssh is installed, but disabled. Changing the password and enabling ssh are the next steps, in a console session that should look like the following:

  > raspberrypi login: pi
  > Password:
  passwd
  > Changing password for pi.
  > (current) UNIX password:
  > Enter new UNIX password:
  > Retype new UNIX password:
  > passwd: password updated successfully
  sudo systemctl enable ssh.service
  (...)

Alternative initial setup

Another way to do the initial image setup is by mounting in your system and changing the required files before writting it in the SD card. To mount the image:

Using ansible

You can now use ansible from any computer to provision the Pi. I'd recommend, though, using python3 as the interpreter on the Pi, as it has more modules available - *apt_repository*, for instance, is not directly usable with the default python2 interpreter.

A basic playbook that runs tasks as root looks like the following (save it as playbook-sudo-rpi.yml):

  ---
  - hosts: all
    become: yes
    become_user: root
    vars:
      ansible_python_interpreter: /usr/bin/python3
    tasks:
      - debug: msg="Ansible running in {{ansible_lsb.id}}!"

Assuming that the playbook as available as playbook.yml, and that raspberrypi is a name that can be resolved to the device, you can run the playbook with the following command:

  ansible-playbook -i raspberrypi, -u pi playbook-sudo-rpi.yml -K

(you can also replace raspberrypi with the actual IP address of the device)

Setting up Debian repositories

Because Raspbian is based on Debian and upstream Debian has support for the architecture of the Raspberry Pi B+, you can configure and use upstream Debian repositories and packages in the Pi. To do that, use the follwing snippet:

  (...)
    tasks:
      - name: install apt pinning config
        copy: src=apt-pinning dest=/etc/apt/preferences.d/99pinning owner=root group=root mode=0644
      - name: install Debian apt key
        apt_key: url='https://ftp-master.debian.org/keys/archive-key-9.asc' id='E1CF20DDFFE4B89E802658F1E0B11894F66AEC98' state=present
        notify: apt-update
      - name: install Debian apt repositories
        apt_repository: repo='deb http://ftp.debian.org/debian {{item}} main contrib non-free' state=present
        with_items:
          - stable
          - testing
          - unstable
          - experimental
        notify: apt-update
    handlers:
      - name: apt-update
        apt: update-cache=yes

The apt-pinning file should contain something like the following:

  Package: *
  Pin: release o=Raspberry Pi Foundation
  Pin-Priority: 600

  Package: *
  Pin: release o=Raspbian
  Pin-Priority: 600

  Package: *
  Pin: release a=stable
  Pin-Priority: 510

  Package: *
  Pin: release a=testing
  Pin-Priority: 520

  Package: *
  Pin: release a=unstable
  Pin-Priority: 150

  Package: *
  Pin: release a=experimental
  Pin-Priority: 120