diff --git a/README.md b/README.md
index 65d118a..7063d86 100644
--- a/README.md
+++ b/README.md
@@ -12,11 +12,10 @@ For now the goal of this code is to get a basic WireGuard deployment going for t
- Use ```deploy-software-updates.sh``` to update software on all frames
- Use ```deploy-wireguard.sh``` to deploy wireguard on the dispatcher + all frames
- Be sure to update frame IP address after running this so ansible uses the wireguard vpn instead of naked IP address
+ - Use ```setup-additional-wireguard-client.sh``` to create a wireguard config for a non-frame host (like your laptop/desktop used to manage a fleet of frames via the dispatcher)
+- Use ```deploy-dispatchers.sh``` to deploy dispatcher config (this is to fine-tune setup to include the frames)
- Use ```deploy-frames.sh``` to deploy frame configuration (this is a limited subset of config from the docs)
- - Monit
- - msmtprc / aliases
- - Scheduled hdmi on/off
-- See ```inventory.example``` for necessary config and layout of groups for the various ansible playbooks to work properly
+- See ```inventory.example``` and the ```host_vars``` directory for necessary config and layout of groups for the various ansible playbooks to work properly
# Licensing
diff --git a/host_vars/dispatcher.example b/host_vars/dispatcher.example
index 92701ad..9f46095 100644
--- a/host_vars/dispatcher.example
+++ b/host_vars/dispatcher.example
@@ -17,3 +17,4 @@ monit_web_user: "admin"
monit_web_pasword: "password"
rttys_http_username: "admin"
rttys_http_pass: "password"
+dispatcher_dashboard_ip: 192.168.254.1
diff --git a/host_vars/frame1.example b/host_vars/frame1.example
index 37eb047..4c16f5c 100644
--- a/host_vars/frame1.example
+++ b/host_vars/frame1.example
@@ -14,3 +14,5 @@ monit_filesystems:
- "/tank"
monit_web_user: "admin"
monit_web_pasword: "password"
+munin_address: 192.168.254.11
+dispatcher_dashboard_ip: 192.168.254.11
diff --git a/inventory.example b/inventory.example
index 0f181e5..52663ff 100644
--- a/inventory.example
+++ b/inventory.example
@@ -15,6 +15,8 @@ frames:
frame_timezone: UTC
monit_wireguard: true
monit_wireguard_ip: 192.168.254.1
+ rtty_server: 192.168.254.1
+ munin_server: 192.168.254.1
wg:
hosts:
frame1:
diff --git a/playbook-dispatchers.yml b/playbook-dispatchers.yml
index 4b8b603..ea676b4 100644
--- a/playbook-dispatchers.yml
+++ b/playbook-dispatchers.yml
@@ -6,3 +6,5 @@
- rttys
- monit
- monit-dashboard
+ - munin
+ - dispatcher-dashboard
diff --git a/playbook-frames.yml b/playbook-frames.yml
index 1a33577..6c5e609 100644
--- a/playbook-frames.yml
+++ b/playbook-frames.yml
@@ -5,6 +5,8 @@
- msmtp
- hdmi
- monit
+ - munin-node
+ - rtty
tasks:
- name: Setup timezone
timezone:
diff --git a/roles/dispatcher-dashboard/tasks/main.yml b/roles/dispatcher-dashboard/tasks/main.yml
new file mode 100644
index 0000000..a3aa376
--- /dev/null
+++ b/roles/dispatcher-dashboard/tasks/main.yml
@@ -0,0 +1,14 @@
+---
+ - name: Gather instance facts
+ setup:
+ - block:
+ - name: Setup dispatcher-dashboard
+ template:
+ src: index.html
+ dest: "/opt/dashboard/www/index.html"
+ owner: munin
+ group: munin
+ mode: 0600
+ with_items: groups['frames']
+ tags:
+ - dispatcher-dashboard-config
diff --git a/roles/dispatcher-dashboard/templates/index.html b/roles/dispatcher-dashboard/templates/index.html
new file mode 100644
index 0000000..b034bbd
--- /dev/null
+++ b/roles/dispatcher-dashboard/templates/index.html
@@ -0,0 +1,19 @@
+
+
+
+PiFrameFleet
+
+
+
+Command Line
+Monit Monitoring
+Munin Monitoring
+Picture File Browser
+Syncthing Admin Interfaces
+
+
+
diff --git a/roles/munin-node/defaults/main.yml b/roles/munin-node/defaults/main.yml
new file mode 100644
index 0000000..28c9165
--- /dev/null
+++ b/roles/munin-node/defaults/main.yml
@@ -0,0 +1,2 @@
+---
+munin_server: 192.168.254.1
\ No newline at end of file
diff --git a/roles/munin-node/handlers/main.yml b/roles/munin-node/handlers/main.yml
new file mode 100644
index 0000000..7d897fc
--- /dev/null
+++ b/roles/munin-node/handlers/main.yml
@@ -0,0 +1,6 @@
+---
+ - name: restart munin-node
+ systemd:
+ name: "munin-node"
+ state: "restarted"
+
\ No newline at end of file
diff --git a/roles/munin-node/tasks/main.yml b/roles/munin-node/tasks/main.yml
new file mode 100644
index 0000000..efc0d0f
--- /dev/null
+++ b/roles/munin-node/tasks/main.yml
@@ -0,0 +1,47 @@
+---
+ - name: Gather instance facts
+ setup:
+ - name: Update APT package cache
+ apt:
+ update_cache: "true"
+ cache_valid_time: "3600"
+ tags:
+ - munin-node-install
+ - name: Install dependencies
+ package:
+ name: "{{ packages }}"
+ state: present
+ vars:
+ packages:
+ - munin-node
+ tags:
+ - munin-node-install
+ - name: Remove main munin process
+ apt:
+ name: "{{ packages }}"
+ state: absent
+ purge: yes
+ vars:
+ packages:
+ - munin
+ tags:
+ - munin-node-install
+ - block:
+ - name: Allow dispatcher to connect to munin-node
+ lineinfile:
+ line: "cidr_allow {{ munin_server }}/32"
+ path: "/etc/munin/munin-node.conf"
+ state: present
+ notify: restart munin-node
+ tags:
+ - munin-node-config
+ - name: Setup firewall rule
+ firewalld:
+ port: 4949/tcp
+ zone: public
+ permanent: yes
+ state: enabled
+ immediate: yes
+ tags:
+ - munin-node-config
+
\ No newline at end of file
diff --git a/roles/munin/handlers/main.yml b/roles/munin/handlers/main.yml
new file mode 100644
index 0000000..68c38f3
--- /dev/null
+++ b/roles/munin/handlers/main.yml
@@ -0,0 +1,3 @@
+---
+- name: generate munin graphs
+ command: su - munin --shell=/bin/bash munin-cron
diff --git a/roles/munin/tasks/main.yml b/roles/munin/tasks/main.yml
new file mode 100644
index 0000000..0ea1fe4
--- /dev/null
+++ b/roles/munin/tasks/main.yml
@@ -0,0 +1,16 @@
+---
+- name: Gather instance facts
+ setup:
+- block:
+ - name: Setup munin
+ template:
+ src: munin.conf
+ dest: "/opt/munin/munin.conf"
+ owner: munin
+ group: munin
+ mode: 0600
+ with_items: groups['frames']
+ notify:
+ - generate munin graphs
+ tags:
+ - munin-config
diff --git a/roles/munin/templates/munin.conf b/roles/munin/templates/munin.conf
new file mode 100644
index 0000000..7af441a
--- /dev/null
+++ b/roles/munin/templates/munin.conf
@@ -0,0 +1,17 @@
+dbdir /opt/munin/db
+htmldir /opt/munin/www
+logdir /opt/munin/log
+rundir /opt/munin/run
+cgitmpdir /opt/munin/cgi-tmp
+
+graph_strategy cron
+html_strategy cron
+
+[dispatcher]
+ address 127.0.0.1
+ use_node_name yes
+{% for frame in groups['frames'] %}
+[frames;{{ hostvars[frame].inventory_hostname }}]
+ address {{ hostvars[frame].munin_address }}
+ use_node_name yes
+{% endfor %}
diff --git a/roles/rtty/defaults/main.yml b/roles/rtty/defaults/main.yml
new file mode 100644
index 0000000..afcd389
--- /dev/null
+++ b/roles/rtty/defaults/main.yml
@@ -0,0 +1,2 @@
+---
+rtty_server: 192.168.254.1
diff --git a/roles/rtty/handlers/main.yml b/roles/rtty/handlers/main.yml
new file mode 100644
index 0000000..c7e2357
--- /dev/null
+++ b/roles/rtty/handlers/main.yml
@@ -0,0 +1,5 @@
+---
+- name: restart rtty
+ systemd:
+ name: "rtty"
+ state: "restarted"
diff --git a/roles/rtty/tasks/main.yml b/roles/rtty/tasks/main.yml
new file mode 100644
index 0000000..90cb6e9
--- /dev/null
+++ b/roles/rtty/tasks/main.yml
@@ -0,0 +1,65 @@
+---
+ - name: Gather instance facts
+ setup:
+ - name: Update APT package cache
+ apt:
+ update_cache: "true"
+ cache_valid_time: "3600"
+ tags:
+ - rtty-install
+ - name: Install dependencies
+ package:
+ name: "{{ packages }}"
+ state: present
+ vars:
+ packages:
+ - libev4
+ - build-essential
+ - cmake
+ - libev-dev
+ - libssl-dev
+ tags:
+ - rtty-install
+ - block:
+ - name: Clone Sources
+ shell:
+ cmd: git clone --recursive https://github.com/zhaojh329/rtty.git /opt/rtty
+ creates: /opt/rtty/.git
+ tags:
+ - rtty-install
+ - name: Update sources
+ shell:
+ cmd: git pull
+ chdir: /opt/rtty
+ tags:
+ - rtty-install
+ - name: Prep sources
+ shell:
+ cmd: mkdir /opt/rtty/build
+ creates: /opt/rtty/build
+ tags:
+ - rtty-install
+ - name: Build sources
+ shell: |
+ cd /opt/rtty/build && \
+ cmake .. && \
+ make install
+ tags:
+ - rtty-install
+ - block:
+ - name: Setup rtty service
+ template:
+ src: rtty.service
+ dest: "/etc/systemd/system/rtty.service"
+ owner: root
+ group: root
+ mode: 0600
+ notify:
+ - restart rtty
+ tags:
+ - rtty-config
+ - name: restart rtty
+ systemd:
+ name: "rtty"
+ enabled: "true"
+ daemon_reload: yes
diff --git a/roles/rtty/templates/rtty.service b/roles/rtty/templates/rtty.service
new file mode 100644
index 0000000..87cb072
--- /dev/null
+++ b/roles/rtty/templates/rtty.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=rtty
+After=network.target
+
+[Service]
+PrivateTmp=true
+ExecStart=/usr/local/bin/rtty -I {{ inventory_hostname }} -h {{ rtty_server }} -a -f root
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/wireguard/templates/wg.conf.j2 b/roles/wireguard/templates/wg.conf.j2
index 3b2ade2..4addac6 100644
--- a/roles/wireguard/templates/wg.conf.j2
+++ b/roles/wireguard/templates/wg.conf.j2
@@ -68,3 +68,11 @@ Endpoint = {{host}}:{{wireguard_port}}
{% endif %}
{% endif %}
{% endfor %}
+
+{% for host in wg_additional_host_keys %}
+[Peer]
+# {{hostvars[host].name}}
+PublicKey = {{hostvars[host].public_key}}
+AllowedIPs = {{hostvars[host].wireguard_ip}}/32
+PersistentKeepalive = {{hostvars[host].wireguard_persistent_keepalive}}
+{% endfor %}
diff --git a/setup-additional-wireguard-client.sh b/setup-additional-wireguard-client.sh
new file mode 100755
index 0000000..a71ba12
--- /dev/null
+++ b/setup-additional-wireguard-client.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+WG_KEY_SERVER=$(wg showconf wg0 | grep PrivateKey | awk '{ print $3 }' | wg pubkey)
+WG_KEY_PRIVATE=$(wg genkey)
+WG_KEY_PUBLIC=$(echo $WG_KEY_PRIVATE | wg pubkey)
+
+echo "
+----------
+Update the name and ip below and then add to the 'host_vars/dispatcher' file
+wg_additional_host_keys:
+ - name: name
+ public_key: $WG_KEY_PUBLIC
+ wireguard_ip: 192.168.254.n
+ wireguard_persistent_keepalive: 30
+----------
+Use the following wireguard config on the new client
+Update the server endpoint IP in Peer and the Interface Address
+[Interface]
+PrivateKey = $WG_KEY_PRIVATE
+ListenPort = 51820
+Address = 192.168.254.n/32
+
+[Peer]
+PublicKey = $WG_KEY_SERVER
+AllowedIPs = 192.168.254.0/24
+Endpoint = ip:51821
+PersistentKeepalive = 30
+
+----------
+"