From 1505e39da7db64111d41196a6d939c443150c618 Mon Sep 17 00:00:00 2001 From: Ray Lyon Date: Sun, 16 Oct 2022 18:54:37 -0400 Subject: [PATCH] initial working commit --- group_vars/all | 13 ++ hosts | 1 + roles/common/files/keys-default | 1 + roles/common/files/keys-mothershipbu | 2 + roles/common/handlers/main.yml | 10 + roles/common/tasks/main.yml | 61 +++++++ roles/librenms-client/handlers/main.yml | 23 +++ roles/librenms-client/tasks/main.yml | 171 ++++++++++++++++++ .../librenms-client/templates/rsyslog.conf.j2 | 5 + roles/librenms-client/templates/snmpd.conf.j2 | 47 +++++ roles/librenms-client/templates/sudoers.j2 | 9 + roles/tailscale/tasks/main.yml | 43 +++++ site.yml | 10 + 13 files changed, 396 insertions(+) create mode 100644 group_vars/all create mode 100644 hosts create mode 100644 roles/common/files/keys-default create mode 100644 roles/common/files/keys-mothershipbu create mode 100644 roles/common/handlers/main.yml create mode 100644 roles/common/tasks/main.yml create mode 100644 roles/librenms-client/handlers/main.yml create mode 100644 roles/librenms-client/tasks/main.yml create mode 100644 roles/librenms-client/templates/rsyslog.conf.j2 create mode 100644 roles/librenms-client/templates/snmpd.conf.j2 create mode 100644 roles/librenms-client/templates/sudoers.j2 create mode 100644 roles/tailscale/tasks/main.yml create mode 100644 site.yml diff --git a/group_vars/all b/group_vars/all new file mode 100644 index 0000000..ebd42cf --- /dev/null +++ b/group_vars/all @@ -0,0 +1,13 @@ +--- +# common +remote_user: +ssh_keyfile: + +# librenms-client +pihole01_key: "" +pihole02_key: "" +snmp_community: "" +librenms_ip: + +# tailscale +tailscale_key: "" diff --git a/hosts b/hosts new file mode 100644 index 0000000..e1bbadf --- /dev/null +++ b/hosts @@ -0,0 +1 @@ +# Hostnames or IPs here. \ No newline at end of file diff --git a/roles/common/files/keys-default b/roles/common/files/keys-default new file mode 100644 index 0000000..7a91322 --- /dev/null +++ b/roles/common/files/keys-default @@ -0,0 +1 @@ +# SSH public keys for all devices that will access the server. \ No newline at end of file diff --git a/roles/common/files/keys-mothershipbu b/roles/common/files/keys-mothershipbu new file mode 100644 index 0000000..85fcf00 --- /dev/null +++ b/roles/common/files/keys-mothershipbu @@ -0,0 +1,2 @@ +# SSH public keys for all devices that will access the server. +# Backup server needs to grant access to my primary VM host for ZFS snapshot replication, so this additional file is needed. \ No newline at end of file diff --git a/roles/common/handlers/main.yml b/roles/common/handlers/main.yml new file mode 100644 index 0000000..be2ce28 --- /dev/null +++ b/roles/common/handlers/main.yml @@ -0,0 +1,10 @@ +--- +- name: restart ssh service - Debian + ansible.builtin.systemd: + state: restarted + name: ssh + +- name: restart ssh service - RedHat + ansible.builtin.systemd: + state: restarted + name: sshd \ No newline at end of file diff --git a/roles/common/tasks/main.yml b/roles/common/tasks/main.yml new file mode 100644 index 0000000..044258e --- /dev/null +++ b/roles/common/tasks/main.yml @@ -0,0 +1,61 @@ +--- +- name: get package facts + ansible.builtin.package_facts: + +- name: get service facts + service_facts: + +- name: add default ssh keys + authorized_key: + key: "{{ lookup('file', '{{ ssh_keyfile }}') }}" + user: "{{ remote_user }}" + state: present + exclusive: True + when: "'mothershipbu.lyon' not in inventory_hostname" + +- name: add default ssh keys - mothershipbu + authorized_key: + key: "{{ lookup('file', 'keys-mothershipbu') }}" + user: "{{ remote_user }}" + state: present + exclusive: True + when: "'mothershipbu.lyon' in inventory_hostname" + +- name: disable password ssh auth + ansible.builtin.lineinfile: + path: "/etc/ssh/sshd_config" + regexp: '^PasswordAuthentication' + line: 'PasswordAuthentication no' + backrefs: yes + notify: restart ssh service - {{ ansible_distribution_file_variety }} + +- name: automatic security updates - debian + package: name=unattended-upgrades state=latest + when: ansible_distribution_file_variety == "Debian" + +- name: automatic security updates - redhat + package: name=dnf-automatic state=latest + when: ansible_distribution_file_variety == "RedHat" + +- name: configure automatic security updates step 01 - redhat + ansible.builtin.lineinfile: + path: "/etc/dnf/automatic.conf" + regexp: '^upgrade_type =' + line: 'upgrade_type = security' + backrefs: yes + when: ansible_distribution_file_variety == "RedHat" + +- name: configure automatic security updates step 02 - redhat + ansible.builtin.lineinfile: + path: "/etc/dnf/automatic.conf" + regexp: '^apply_updates =' + line: 'apply_updates = yes' + backrefs: yes + when: ansible_distribution_file_variety == "RedHat" + +- name: enable and start dnf-automatic.timer - redhat + ansible.builtin.systemd: + state: started + enabled: yes + name: dnf-automatic.timer + when: ansible_distribution_file_variety == "RedHat" diff --git a/roles/librenms-client/handlers/main.yml b/roles/librenms-client/handlers/main.yml new file mode 100644 index 0000000..23771b7 --- /dev/null +++ b/roles/librenms-client/handlers/main.yml @@ -0,0 +1,23 @@ +--- +- name: reload systemd configs + ansible.builtin.systemd: + daemon_reload: yes + +- name: enable and restart snmpd.service + ansible.builtin.systemd: + state: restarted + enabled: yes + name: snmpd + listen: enable and restart snmpd.service + +- name: enable and restart the rsyslog service + ansible.builtin.systemd: + state: restarted + enabled: yes + name: rsyslog + +- name: restart syslog-ng for LibreNMS + ansible.builtin.systemd: + state: restarted + name: syslog-ng + delegate_to: nms.lyon \ No newline at end of file diff --git a/roles/librenms-client/tasks/main.yml b/roles/librenms-client/tasks/main.yml new file mode 100644 index 0000000..201e9d1 --- /dev/null +++ b/roles/librenms-client/tasks/main.yml @@ -0,0 +1,171 @@ +--- +- name: check for pihole + ansible.builtin.stat: + path: "/usr/local/bin/pihole" + register: pihole + +- name: install latest snmpd - debian + package: name=snmpd state=latest + when: ansible_os_family == "Debian" + +- name: install latest snmpd - centos + package: name=net-snmp state=latest + when: ansible_distribution_file_variety == "RedHat" + +- name: install latest jq + package: name=jq state=latest + +- name: fix extend serial permissions + ansible.builtin.file: + path: "/sys/devices/virtual/dmi/id/product_serial" + mode: '444' + when: ansible_architecture == "x86_64" and ansible_virtualization_role != "guest" + +- name: cron job for extend serial permissions + ansible.builtin.lineinfile: + path: /etc/crontab + line: "@reboot chmod 444 /sys/devices/virtual/dmi/id/product_serial" + when: ansible_architecture == "x86_64" + +- name: download script for extend distro + ansible.builtin.get_url: + url: "https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/distro" + dest: "/usr/bin/distro" + mode: '755' + +- name: download script for extend osupdates + ansible.builtin.get_url: + url: "https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/osupdate" + dest: "/etc/snmp/osupdate" + mode: '755' + +- name: download script for extend zfs + ansible.builtin.get_url: + url: "https://github.com/librenms/librenms-agent/raw/master/snmp/zfs-linux" + dest: "/etc/snmp/zfs-linux" + mode: '755' + when: "'zfs-zed' in ansible_facts.packages" + +- name: download script for extend docker + ansible.builtin.get_url: + url: "https://github.com/librenms/librenms-agent/raw/master/snmp/docker-stats.sh" + dest: "/etc/snmp/docker-stats.sh" + mode: '755' + when: "'docker' in services" + +- name: download script for extend pihole + ansible.builtin.get_url: + url: "https://github.com/librenms/librenms-agent/raw/master/snmp/pi-hole" + dest: "/etc/snmp/pi-hole" + mode: '755' + when: pihole.stat.exists + +- name: download script for extend raspberrypi + ansible.builtin.get_url: + url: "https://raw.githubusercontent.com/librenms/librenms-agent/master/snmp/raspberry.sh" + dest: "/etc/snmp/raspberry.sh" + mode: '755' + when: ansible_os_family == "Debian" and ansible_lsb.id == 'Raspbian' + +- name: add api key to pihole script for pihole01 + ansible.builtin.lineinfile: + path: "/etc/snmp/pi-hole" + regexp: '^API_AUTH_KEY=' + line: 'API_AUTH_KEY="{{ pihole01_key }}"' + backrefs: yes + when: ansible_hostname == "pihole01" + +- name: add api key to pihole script for pihole02 + ansible.builtin.lineinfile: + path: "/etc/snmp/pi-hole" + regexp: '^API_AUTH_KEY=' + line: 'API_AUTH_KEY="{{ pihole02_key }}"' + backrefs: yes + when: ansible_hostname == "pihole02" + +- name: set ExecStart options in service file - ubuntu + ansible.builtin.lineinfile: + path: "/lib/systemd/system/snmpd.service" + regexp: '^ExecStart=' + line: "ExecStart=/usr/sbin/snmpd -LS4d -Lf /dev/null -u Debian-snmp -g Debian-snmp -I -smux,mteTrigger,mteTriggerConf -f" + backrefs: yes + when: ansible_os_family == "Debian" + notify: reload systemd configs + +- name: set snmpdopts - centos + ansible.builtin.lineinfile: + path: "/etc/sysconfig/snmpd" + regexp: '^# OPTIONS=|^OPTIONS=' + line: 'OPTIONS="-LS4-6d"' + when: ansible_distribution_file_variety == "RedHat" + +- name: copy snmpd.conf from template + register: snmpd_config + ansible.builtin.template: + src: snmpd.conf.j2 + dest: "/etc/snmp/snmpd.conf" + owner: root + group: root + mode: '0644' + notify: + - enable and restart snmpd.service + +- name: add host to librenms + # when: snmpd_config.changed + block: + - name: Try adding by hostname + command: + cmd: "/usr/bin/lnms device:add --v2c -c {{ snmp_community }} {{ inventory_hostname }}" + become: yes + become_user: librenms + delegate_to: nms.lyon + register: lnms_add_by_hostname + rescue: + - name: Add by IP when hostname fails + command: + cmd: "/opt/librenms/snmp-scan.py -v -r {{ ansible_default_ipv4.address }}/32" + become: yes + become_user: librenms + delegate_to: nms.lyon + register: lnms_add_by_ip + +- name: check librenms add by hostname status + when: lnms_add_by_hostname.changed + ansible.builtin.debug: + msg: "{{ lnms_add_by_hostname.stdout }}" + +- name: check librenms add by ip status + when: lnms_add_by_ip.changed + ansible.builtin.debug: + msg: "{{ lnms_add_by_ip.stdout }}" + +- name: copy sudoers from template + ansible.builtin.template: + src: sudoers.j2 + dest: "/etc/sudoers.d/80-snmp" + owner: root + group: root + mode: '0440' + +- name: copy rsyslog config from template + ansible.builtin.template: + src: rsyslog.conf.j2 + dest: "/etc/rsyslog.d/librenms.conf" + owner: root + group: root + mode: '0644' + notify: + - enable and restart the rsyslog service + - restart syslog-ng for LibreNMS + +- name: verify the rsyslog service is running + ansible.builtin.systemd: + state: started + name: rsyslog + +- name: verify the snmpd service is running + ansible.builtin.systemd: + state: started + name: snmpd + + diff --git a/roles/librenms-client/templates/rsyslog.conf.j2 b/roles/librenms-client/templates/rsyslog.conf.j2 new file mode 100644 index 0000000..667a562 --- /dev/null +++ b/roles/librenms-client/templates/rsyslog.conf.j2 @@ -0,0 +1,5 @@ +*.* @{{ librenms_ip }}:514 + +if $programname == 'snmpd' and $msg contains 'statfs' then { + stop + } \ No newline at end of file diff --git a/roles/librenms-client/templates/snmpd.conf.j2 b/roles/librenms-client/templates/snmpd.conf.j2 new file mode 100644 index 0000000..d7c466e --- /dev/null +++ b/roles/librenms-client/templates/snmpd.conf.j2 @@ -0,0 +1,47 @@ +# Change RANDOMSTRINGGOESHERE to your preferred SNMP community string +com2sec readonly default {{ snmp_community }} + +group MyROGroup v2c readonly +view all included .1 80 +access MyROGroup "" any noauth exact all none none + +syslocation Home +syscontact Ray Lyon + +agentAddress udp:161,udp6:[::1]:161 +rocommunity {{ snmp_community }} + +#OS Distribution Detection +extend distro /usr/bin/distro + +#OS Updates +extend osupdate /etc/snmp/osupdate + +#Hardware Detection +{% if ansible_architecture == "x86_64" %} +extend manufacturer '/bin/cat /sys/devices/virtual/dmi/id/sys_vendor' +extend hardware '/bin/cat /sys/devices/virtual/dmi/id/product_name' +extend serial '/bin/cat /sys/devices/virtual/dmi/id/product_serial' +{% endif %} + +{% if ansible_architecture == "armv6l" %} +extend hardware '/bin/cat /sys/firmware/devicetree/base/model' +extend serial '/bin/cat /sys/firmware/devicetree/base/serial-number' +{% endif %} + +#Extended scripts +{% if "nfs-kernel-server" in ansible_facts.services %} +extend nfs-server /bin/cat /proc/net/rpc/nfsd +{% endif %} +{% if "zfs-zed" in ansible_facts.packages %} +extend zfs '/usr/bin/sudo /etc/snmp/zfs-linux' +{% endif %} +{% if "docker" in ansible_facts.services %} +extend docker /usr/bin/sudo /etc/snmp/docker-stats.sh +{% endif %} +{% if pihole.stat.exists %} +extend pi-hole /etc/snmp/pi-hole +{% endif %} +{% if ansible_os_family == "Debian" and ansible_lsb.id == 'Raspbian' %} +extend raspberry /usr/bin/sudo /bin/sh /etc/snmp/raspberry.sh +{% endif %} \ No newline at end of file diff --git a/roles/librenms-client/templates/sudoers.j2 b/roles/librenms-client/templates/sudoers.j2 new file mode 100644 index 0000000..4156043 --- /dev/null +++ b/roles/librenms-client/templates/sudoers.j2 @@ -0,0 +1,9 @@ +{% if "zfs-zed" in ansible_facts.packages %} +Debian-snmp ALL=(ALL) NOPASSWD: /etc/snmp/zfs-linux +{% endif %} +{% if "docker" in ansible_facts.services %} +Debian-snmp ALL=(ALL) NOPASSWD: /etc/snmp/docker-stats.sh +{% endif %} +{% if pihole.stat.exists %} +Debian-snmp ALL=(ALL) NOPASSWD: /bin/sh /etc/snmp/raspberry.sh +{% endif %} \ No newline at end of file diff --git a/roles/tailscale/tasks/main.yml b/roles/tailscale/tasks/main.yml new file mode 100644 index 0000000..96d2e32 --- /dev/null +++ b/roles/tailscale/tasks/main.yml @@ -0,0 +1,43 @@ +--- +- name: check for tailscale install + command: + cmd: tailscale status + register: tailscale_status + ignore_errors: yes + +- name: check tailscale_status + ansible.builtin.debug: + msg: "{{ tailscale_status }}" + +- name: Download Tailscale install script + get_url: + url: https://tailscale.com/install.sh + dest: /tmp/tailscale_install.sh + mode: '0555' + when: tailscale_status.failed + +- name: Run Tailscale install script + command: + cmd: /tmp/tailscale_install.sh + when: tailscale_status.failed + +- name: Prompt to authorize device + debug: + msg: "Device requires authorization in the TailScale admin panel. Task will wait 60s for you to do so." + when: + - tailscale_status.failed == false + - '"not yet authorized" in tailscale_status.stdout' + +- name: Start Tailscale + command: + cmd: /usr/bin/tailscale up --authkey "{{ tailscale_key }}" + async: 60 + when: tailscale_status.failed + register: tailscale_start_status + +- name: Machine added confirmation + debug: + msg: "Device successfully added to TailScale." + when: + - tailscale_start_status.changed + - '"Success" in tailscale_start_status.stderr' \ No newline at end of file diff --git a/site.yml b/site.yml new file mode 100644 index 0000000..1195c10 --- /dev/null +++ b/site.yml @@ -0,0 +1,10 @@ +--- +- name: Configure servers for use on my home network + hosts: all + remote_user: "{{ remote_user }}" + become: yes + + roles: + - common + - librenms-client + - tailscale \ No newline at end of file