Tutorial
This is an advanced tutorial for people who want to maintain larger installations.
It is recommended to have basic Linux administration skills.
The following tools are used for this task:
- Ansible, a lightweight state-of-the-art IT-automation tool
https://docs.ansible.com/ansible/latest/index.html - Remote openHAB Binding, a plugin for bidirectional between openHAB instances
https://www.openhab.org/addons/bindings/remoteopenhab/ - freeloader, a standalone bootstrapper tool providing a REST-API via HTTPS
https://github.com/nexus-unity/freeloader
All these tools are out of the box supported by our platform.
The quick guide
This chapter shows how easily it works without going into details.
Boot the freeloader image
On your NEXUS device run:
sudo freeloader_enable_boot --token THISISASECRET
sudo reboot
Upload the new image and configuration
freeloadercmd --reboot --image nexus.img --upload-file setup.yaml --token THISISASECRET 192.168.1.*
The device will now reboot into the new image and the setup.yaml instructions will be executed by Ansible.
Preparation
Ansible (in management mode) does only support Linux based operating systems!
If you want to use Windows for this guide we recommend running Ubuntu in VirtualBox (Tutorial)
Example requirements
- 2 or more NEXUS devices with Ethernet modules
Flashing the freeloader image
- Download the freeloader boot image from https://github.com/nexus-unity/freeloader
- Flash the image on each of the devices (Instructions)
- Start all devices
Installing Ansible
- Follow this guide how to install Ansible
- Download the freeloader ansible plugins TODO: Update
Flashing and configuring multiple devices
At this point you should have at least two NEXUS devices with Ethernet modules connected to the same network running.
You should have a (virtual) Ubuntu/Linux setup with Ansible installed.
Testing the configuration
This step will test if the setup is done correctly by scanning the network for devices.
- Open the directory where you have placed the freeloader ansible plugins. There should be the library/ and module_utils/ directory.
- Create a file called scan.yaml and open it using your favorite editor, we recommend Atom for this task.
- Copy the following text into the editor and save it. You need to change the ip address to match your network. (one wildcard is supported)
- hosts: localhost
tasks:
- name: Scan for devices
freeloader_scan:
ip: "192.168.1.*"
register: result
- debug: var=result
- Run ansible-playbook scan.yml
- If you have configured the setup correctly the “devices” should contain the booted devices.
PLAY [localhost] *******************************************************************************
TASK [Gathering Facts] *************************************************************************
ok: [localhost]
TASK [Scan for devices] ************************************************************************
ok: [localhost]
TASK [debug] ***********************************************************************************
ok: [localhost] => {
"result": {
"changed": false,
"devices": [
{
"disks": [
{
"disk_name": "mmcblk0",
"partition_json": {
"partitiontable": {
"device": "/dev/mmcblk0",
"id": "0x40f31316",
"label": "dos",
"partitions": [
{
"node": "/dev/mmcblk0p1",
"size": 204800,
"start": 2048,
"type": "b"
},
{
"node": "/dev/mmcblk0p2",
"size": 31215028,
"start": 206848,
"type": "fd"
}
],
"sectorsize": 512,
"unit": "sectors"
}
},
"size_bytes": 16088301568
}
],
"freeloader_version": "0.1.0",
"ip": "192.168.1.135",
"mac_address": "6a:fa:03:22:b0:cb",
"model": {
"hardware": "BCM2835",
"model": "Raspberry Pi Compute Module 3 Rev 1.0",
"revision": "a220a0",
"serial": "000000000d76573e"
},
"system_info": {
"hostname": "Freeloader",
"kernel_version": "5.4.105",
"os": "Linux 21.02-snapshot OpenWrt Freeloader",
"uptime": "41 seconds"
},
"url": "https://192.168.1.135:8443/freeloader/0.1"
}
],
"failed": false
}
}
PLAY RECAP ************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Preparing the configuration
This step will prepare the initial configuration uploaded to the device.
- Create a directory called files/
- Download the latest operation system image from TODO
- Place the image in the files/ directory and unpack it (.img file extension)
- Create a file called files/setup.yaml
- The setup.yaml will add the user account “remoteuser” to the system, install a public ssh key and enable root access
You must replace ssh-rsa AAAA…gX development@pc by your public ssh key
The configuration will be executed on first boot and setup the user.
- hosts: localhost
tasks:
- name: Add user
user:
name: remoteuser
comment: Remote User
groups: sudo
- name: Create ssh directory
file:
path: "/home/remoteuser/.ssh/"
state: directory
owner: remoteuser
group: remoteuser
mode: '0700'
- name: Copy pub key to authorized_keys file
copy:
owner: remoteuser
group: remoteuser
mode: '0600'
dest: "/home/remoteuser/.ssh/authorized_keys"
content: |
ssh-rsa AAAA...gX development@pc
- name: Add to sudoers
copy:
dest: "/etc/sudoers.d/99_remoteuser"
content: remoteuser ALL=(ALL:ALL) NOPASSWD:ALL
validate: 'visudo -cf %s'
mode: 0440
- Create a template/ directory and a file template/hosts-file.j2
nexushosts:
hosts:
{% for group in groups %}
{% if groups[group] and group == 'nexushosts' %}
{% for host in groups[group] %}
{{hostvars[host].inventory_hostname}}:
ansible_host: {{hostvars[host].ansible_host}}
mac_address: "{{ hostvars[host].mac_address }}"
serial_cm: "{{ hostvars[host].serial_cm }}"
{% endfor %}
{% endif %}
{% endfor %}
vars:
ansible_user: remoteuser
ansible_python_interpreter: auto
Executing the initial configuration
This step will upload the os image to the device and write it on the storage.
It will also place the setup.yaml file in the boot directory and reboot the system to start the os.
All successfully configured devices will be stored in the nexus-hosts.yaml file
- Create the file initial_setup.yaml and add the content (do not forget to change the ip address)
- hosts: localhost
tasks:
- name: Scan for devices
freeloader_scan:
ip: "192.168.1.*"
register: detected_devices
- debug: var=detected_devices
- name: Upload image
with_items:
- "{{detected_devices['devices']}}"
freeloader_image:
ip: "{{ item['ip'] }}"
file: "./files/nexus.img"
register: finished_devices
- debug: var=finished_devices
- name: Upload setup.yaml and reboot
with_items:
- "{{finished_devices.results}}"
freeloader_modify:
ip: "{{ item.item['ip'] }}"
redeploy_freeloader: True
upload_file_to_boot: "files/setup.yaml"
reboot: True
register: rebooted_devices
- debug: var=rebooted_devices
- name: Register device
with_items:
- "{{finished_devices.results}}"
add_host:
name: "{{ item.item['ip'] }}"
groups: [ nexushosts ]
ansible_host: "{{ item.item['ip'] }}"
mac_address: "{{ item.item['mac_address'] }}"
serial_cm: "{{ item.item['model']['serial'] }}"
- name: Write devices to hostfile
template:
src: templates/hosts-file.j2
dest: "./nexus-hosts.yaml"
- Run ansible-playbook initial_setup.yaml
This will execute the steps and upload the image and setup.yaml to the devices.
It may take several minutes (up to a hour) for all tasks to complete.
There is not much verbosity during the procedure so just wait for the process to finish.
Configuration after setup
Modifying the hosts file
After the initial setup all the devices should run the operating system and include the changes from setup.yaml .
It is assumed that the devices get the same ip addresses via dhcp after reboot (which is the typical behavior).
Otherwise it is necessary to adapt the ip addresses.
- You may want to edit the nexus-hosts.yaml to assign meaningful hostnames to the devices.
nexushosts:
hosts:
192.168.1.135:
ansible_host: 192.168.1.135
mac_address: "6a:fa:03:22:b0:cb"
serial_cm: "000000000d76573e"
192.168.1.136:
ansible_host: 192.168.1.136
mac_address: "6a:fa:0f:21:b1:cf"
serial_cm: "000000000d80574e"
vars:
ansible_user: remoteuser
ansible_python_interpreter: auto
Changed names:
nexushosts:
hosts:
nexus-first-floor:
ansible_host: 192.168.1.135
mac_address: "6a:fa:03:22:b0:cb"
serial_cm: "000000000d76573e"
nexus-second-floor:
ansible_host: 192.168.1.136
mac_address: "6a:fa:0f:21:b1:cf"
serial_cm: "000000000d80574e"
vars:
ansible_user: remoteuser
ansible_python_interpreter: auto
Hostname configuration
At this point all configured devices should be up and running.
The nexus-hosts.yaml file should have meaningful hostnames.
Now you can create and execute Ansible playbooks to configure the devices.
It is recommended to read the Ansible documentation to understand the concept.
For example we are changing the hostnames of all devices to match the names in our nexus-hosts.yaml
- Create a file called change_hostname.yaml and add the content
- hosts: nexushosts
become: true
become_user: root
tasks:
- name: Set hostname
ansible.builtin.hostname:
name: "{{ inventory_hostname }}"
- name: Updated /etc/hosts
ansible.builtin.lineinfile:
path: /etc/hosts
regexp: "^127\\.0\\.1\\.1.*{{ inventory_hostname }}"
line: "127.0.1.1 {{ inventory_hostname }}"
- Run ansible-playbook change_hostname.yaml -i nexus-hosts.yaml
- Now each device should have the hostname configured in the nexus-hosts.yaml file.
Updating
This examples shows how to update all devices
- Create a file called update.yaml and add the content
- hosts: nexushosts
become: true
become_user: root
tasks:
- name: Update packages
apt:
upgrade: 'dist'
update_cache: 'yes'
autoremove: true
autoclean: true
- Run ansible-playbook update.yaml -i nexus-hosts.yaml
- All devices should now have the latest updates installed
TODO
Install and configure packages.