APNIC 56 Network Automation tutorial
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Setup LibreNMS without touching server manually

Idea here is to setup LibreNMS (via docker) on a fresh Ubuntu 20.04 LTS server via Ansible + Configure VyOS with SNMP v3 + Use REST API of LibreNMS via Ansible to add devices

Warning: This is to put live working configuration for attendee reference. This is NOT a comprehensive “how to guide”. Some of the best practise have been omitted to make demo easy to follow. When running this in production consider using Ansible vault to store credentials.


Break overall job in three parts and work on each sequentially

Part 1 - Get the Docker engine ready & deploy LibreNMS on a fresh server

host.yml code:

---
  - hosts: nms.apnic56.anuragbhatia.com 
    gather_facts: no 


    tasks: 
      - name: Ensure all packages are latest 
        ansible.builtin.apt:
          name: "{{ item }}"
          update_cache: yes 
          # upgrade: yes 
        loop: 
          - ca-certificates
          - curl
          - gnupg
          - lsb-release  

      - name: Ensure docker key is present 
        ansible.builtin.apt_key:
          url: https://download.docker.com/linux/ubuntu/gpg
          state: present 
        # tags: now  
  
      - name: Ensure ansible repo is present 
        ansible.builtin.apt_repository:
          repo: deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable
          state: present
        # tags: now     

      - name: Ensure docker engine is installed 
        ansible.builtin.apt:
          name: "{{ item }}"
          state: latest 
          update_cache: yes 
        loop: 
          - docker-ce 
          - docker-ce-cli 
          - containerd.io 
          - docker-compose
          - docker-compose-plugin
        # tags: now   
         
      - name: Update network config for loopback        
        copy: 
          src: ./50-cloud-init.yaml
          dest: /etc/netplan/50-cloud-init.yaml
        tags: netplan   

      - name: Apply the netplan config 
        command: netplan apply 
        tags: netplan

      - name: Ensure user account for anurag exists 
        user: 
          name: anurag 
          generate_ssh_key: yes
          ssh_key_bits: 2048
          ssh_key_file: .ssh/id_rsa
          shell: /usr/bin/bash
          groups: "sudo"
          append: yes          
          state: present  
        tags: user    

      - name: Upload all SSH keys for attendees
        ansible.posix.authorized_key:
          user: anurag 
          key: '{{ item }}'
          state: present
        with_file:
          - "/Users/anurag/.ssh/id_rsa.pub"
        tags: user          

      - name: Allow passwordless sudo for attendees
        lineinfile:
            path: /etc/sudoers
            state: present
            line: 'anurag ALL=(ALL) NOPASSWD: ALL'
            validate: 'visudo -cf %s'
        tags: user         

      - name: Ensure anurag is part of docker group 
        user: 
            name: anurag
            group: docker
            append: yes
        tags: user

inventory sample:

[servers]
nms.apnic56.anuragbhatia.com ansible_user=root

[routers]
R01
R02
R03

[routers:vars]
ansible_connection=ansible.netcommon.network_cli 
ansible_network_os=vyos.vyos.vyos 
ansible_user=anurag

Next, we get LibreNMS files as given in their official sample repo over here modify it a bit to ensure things like binding LibreNMS on 10.10.10.10:8000 instead of having it to bind on public IP.

We deploy this container using

---
  - hosts: nms.apnic56.anuragbhatia.com
    gather_facts: no

    vars: 
      docker_dir: /home/anurag/docker
      app_name: nms.apnic56.anuragbhatia.com 
      stack_name: librenms
      docker_compose_loc: ./docker-compose.yml


    tasks: 
      - name: Ensure directory for {{ app_name }} is present
        file: 
          path: "{{ docker_dir }}/{{ app_name }}"
          state: directory

      - name: Ensure docker-compose.yml is uploaded
        copy:
          src: "{{ docker_compose_loc }}"
          dest: "{{ docker_dir }}/{{ app_name }}"     
        tags: now    

      - name: Ensure required files are uploaded 
        copy: 
          src: "./{{ item }}"
          dest: "{{ docker_dir }}/{{ app_name }}"  
        loop: 
          - .env 
          - librenms.env
          - msmtpd.env
       
      - name: Spin up the container for {{ app_name }}
        docker_compose: 
          project_name: "{{ stack_name }}"
          project_src: "{{ docker_dir}}/{{ app_name }}"     
          pull: yes
          state: present
        tags: control  

Until this part we have docker engine setup & running, we have librenms containers running. We cannot access them yet because they are bind on loopback IP of the server.

Next, we setup Caddy server for reverse proxy. Because we are relying on Letsencrypt for SSL here, the DNS must point to this server. One can run critical server on private IP with SSL but in that case prefer using NGINX Proxy Manager and get SSL certificate using DNS method.

Caddy Config

Caddyfile

nms.apnic56.anuragbhatia.com {
    reverse_proxy 10.10.10.10:8000
}    

docker-compose.yml

version: '3'
services:
  app:
    image: 'caddy:latest'
    restart: unless-stopped
    ports:
      - '80:80'
      - '443:443'      
    volumes:
      - /home/anurag/docker/caddy/Caddyfile:/etc/caddy/Caddyfile
      - data:/data
      - config:/config

volumes:
  data:
  config:      

This gets us Caddy running and doing reverse proxy. This traffic from internet can now hit on nms.apnic56.anuragbhatia.com (HTTP port 80 and 443) and Caddy will get the librenms via 10.10.10.10:8000 running locally on the same server.


Part 2 - Configure SNMP on VyOS routers

Warning: This is broad idea with one time ad-hoc like demo. In production when you create account either provide passwords via variable or make use of Ansible Vault.

vyos-configure-snmp.yml

---
  - hosts: routers 
    gather_facts: no 


    tasks: 
      - name: Configure SNMP on the router 
        vyos.vyos.vyos_config:
          lines:
            - set service snmp contact 'Anurag Bhatia'
            - set service snmp location 'US'
            - set service snmp v3 engineid '080001f8810b61f9921b417a48b00000'
            - set service snmp v3 group group1 mode 'ro'
            - set service snmp v3 group group1 seclevel 'priv'
            - set service snmp v3 group group1 view 'snmpview1'
            - set service snmp v3 user librenms auth plaintext-password yXZTaLg32TYCZJb
            - set service snmp v3 user librenms auth type 'sha'
            - set service snmp v3 user librenms group 'group1'
            - set service snmp v3 user librenms privacy plaintext-password yXZTaLg32TYCZJb
            - set service snmp v3 user librenms privacy type 'aes'
            - set service snmp v3 view snmpview1 oid 1.2.3.4.5.6.7
            

Part 3 - Make use of REST API of LibreNMS and add all routers

Enable REST API by going to https://nms.apnic56.anuragbhatia.com/api-access and create API token.

(Warning: Do not store this critical data in Git but provide via variable during run time or use Ansible vault. Treat this like one time run job to get the devices ready.)

add-device.yml

--- 
  - hosts: localhost  
    gather_facts: no 


    tasks: 

      - name: Add my device in librenms 
        ansible.builtin.uri:
            url: https://nms.apnic56.anuragbhatia.com/api/v0/devices
            method: POST
            body_format: json
            body:
              hostname: "{{ item }}"
              version: v3
              authlevel: authPriv
              authname: librenms
              authpass: yXZTaLg32TYCZJb
              authalgo: SHA
              cryptopass: yXZTaLg32TYCZJb
              cryptoalgo: AES
            headers:
              X-Auth-Token: 96dcbd4eb5e3892f34a1fc54720a3240       
        loop: 
          - R01
          - R02
          - R03