diff --git a/.gitea/workflows/distoolbox.yaml b/.gitea/workflows/distoolbox.yaml
index fb4ce8c..6f0d6e6 100644
--- a/.gitea/workflows/distoolbox.yaml
+++ b/.gitea/workflows/distoolbox.yaml
@@ -37,4 +37,4 @@ jobs:
target: amdgpu
push: true
tags: "gitea.reeseapps.com/services/arch-toolbox-amdgpu:latest,gitea.reeseapps.com/services/arch-toolbox-amdgpu:${{gitea.sha}}"
- no-cache: true
\ No newline at end of file
+ no-cache: false
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index a13b487..5eee5d6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ volumes/
__pycache__/
.pytest_cache/
.venv/
+.mypy_cache
\ No newline at end of file
diff --git a/README.md b/README.md
index 3495217..3f41006 100644
--- a/README.md
+++ b/README.md
@@ -45,6 +45,8 @@ Host ${KEYGEN_HOST}
EOF
```
+In vim: `esc + o` will take you to the end of a file and insert a new line.
+
## Important Dates and Times
- Machine updates happen at 4am on on Saturday
diff --git a/active/ansible/inventory.yaml b/active/ansible/inventory.yaml
deleted file mode 100644
index 8625c5c..0000000
--- a/active/ansible/inventory.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-fedora:
- hosts:
- 3dserver:
- podman:
- kubernetes:
- docker:
- yellow:
- borg:
-
-ubuntu:
- hosts:
- unifi-external:
-
-caddy:
- hosts:
- 3dserver:
\ No newline at end of file
diff --git a/active/os_debian/debian.md b/active/os_debian/debian.md
index 6dc76ca..9a30236 100644
--- a/active/os_debian/debian.md
+++ b/active/os_debian/debian.md
@@ -18,7 +18,7 @@ On the operator:
```bash
export SSH_HOST=kube
-ssh-keygen -t rsa -b 4096 -C ducoterra@${SSH_HOST}.reeselink.com -f ~/.ssh/id_${SSH_HOST}_rsa
+ssh-keygen -t rsa -b 4096 -C ${USER}@${HOSTNAME} -f ~/.ssh/id_${SSH_HOST}_rsa
# Note: If you get "too many authentication failures" it's likely because you have too many private
# keys in your ~/.ssh directory. Use `-o PubkeyAuthentication` to fix it.
diff --git a/active/os_fedora/fedora-kinoite.md b/active/os_fedora/fedora-kinoite.md
index 709416f..055ae92 100644
--- a/active/os_fedora/fedora-kinoite.md
+++ b/active/os_fedora/fedora-kinoite.md
@@ -11,6 +11,7 @@
- [Hostname](#hostname)
- [VLAN Setup with nmcli](#vlan-setup-with-nmcli)
- [GPU Support in Distrobox](#gpu-support-in-distrobox)
+ - [Automatic Display Switching](#automatic-display-switching)
## TPM2 Luks Decryption
@@ -162,3 +163,56 @@ sudo usermod -aG render $USER
```
Logout and log back in to adopt new groups.
+
+## Automatic Display Switching
+
+```bash
+# List displays
+# Builtin: eDP-2
+# Roku: DP-13
+# Lenovo: DP-11
+kscreen-doctor -o
+
+# Put the builtin display back to normal
+kscreen-doctor \
+output.eDP-2.enable \
+output.eDP-2.position.0,0 \
+output.eDP-2.primary \
+output.eDP-2.mode.2560x1600@60 \
+output.eDP-2.scale.1.25
+
+# Show on Roku TV and Monitor
+kscreen-doctor \
+output.DP-11.enable \
+output.DP-11.position.0,0 \
+output.DP-11.mode.2560x1440@60 \
+output.DP-11.scale.1 \
+output.DP-13.enable \
+output.DP-13.position.0,0 \
+output.DP-13.mode.2560x1440@100 \
+output.DP-13.scale.1 \
+output.DP-13.primary \
+output.eDP-2.disable
+
+# Show only on the roku TV
+kscreen-doctor \
+output.DP-11.enable \
+output.DP-11.position.0,0 \
+output.DP-11.primary \
+output.DP-11.mode.3840x2160@60 \
+output.DP-11.scale.2 \
+output.DP-13.disable \
+output.eDP-2.disable
+
+# Mirror the builtin display to the roku tv
+kscreen-doctor \
+output.DP-11.enable \
+output.DP-11.position.0,0 \
+output.DP-11.primary \
+output.DP-11.mode.3840x2160@60 \
+output.DP-11.scale.2 \
+output.eDP-2.enable \
+output.eDP-2.mode.1920x1080@60 \
+output.eDP-2.scale.1 \
+output.eDP-2.position.0,0
+```
\ No newline at end of file
diff --git a/active/os_fedora/fedora-server.md b/active/os_fedora/fedora-server.md
index a76e958..bb48b2f 100644
--- a/active/os_fedora/fedora-server.md
+++ b/active/os_fedora/fedora-server.md
@@ -79,7 +79,7 @@ On the operator:
```bash
export SSH_HOST=kube
-ssh-keygen -C ducoterra@${SSH_HOST}.reeselink.com -f ~/.ssh/id_${SSH_HOST}_rsa
+ssh-keygen -C ${USER}@${HOSTNAME} -f ~/.ssh/id_${SSH_HOST}_rsa
# Note: If you get "too many authentication failures" it's likely because you have too many private
# keys in your ~/.ssh directory. Use `-o PubkeyAuthentication` to fix it.
diff --git a/active/podman_gitea/compose.yaml b/active/podman_gitea/compose.yaml
index 01cef0f..f07e22f 100644
--- a/active/podman_gitea/compose.yaml
+++ b/active/podman_gitea/compose.yaml
@@ -28,6 +28,8 @@ services:
- postgres
security_opt:
- label=disable
+ labels:
+ - "io.containers.autoupdate=registry"
postgres:
image: docker.io/library/postgres:15
diff --git a/active/podman_gitea/gitea.md b/active/podman_gitea/gitea.md
index 8741bb7..3a0272b 100644
--- a/active/podman_gitea/gitea.md
+++ b/active/podman_gitea/gitea.md
@@ -5,6 +5,7 @@
- [Create the gitea user](#create-the-gitea-user)
- [Convert Compose to Quadlet](#convert-compose-to-quadlet)
- [Install Quadlets](#install-quadlets)
+ - [Upgrade Quadlets](#upgrade-quadlets)
- [Editing Configs within Container](#editing-configs-within-container)
- [Gitea Runners](#gitea-runners)
- [Firewall Rules](#firewall-rules)
@@ -63,9 +64,18 @@ scp -r quadlets/. gitea:~/.config/containers/systemd/
The first user you register will be the admin
```bash
-ssh gitea
-systemctl --user daemon-reload
-systemctl --user start gitea postgres
+ssh gitea systemctl --user daemon-reload
+ssh gitea systemctl --user restart gitea postgres
+# Enables auto-update service which will pull new container images automatically every day
+ssh gitea systemctl --user enable --now podman-auto-update.timer
+```
+
+### Upgrade Quadlets
+
+```bash
+scp -r quadlets/. gitea:~/.config/containers/systemd/
+ssh gitea systemctl --user daemon-reload
+ssh gitea systemctl --user restart gitea postgres
```
### Editing Configs within Container
@@ -141,10 +151,11 @@ You should run something like this on a schedule:
docker builder prune -a
```
-To run it every day at midnight: `crontab -e`
+To run it every day at noon: `crontab -e`
```bash
-0 0 * * * yes | docker builder prune -a
+0 12 * * * yes | docker builder prune -a
+0 12 * * * docker image prune -a -f
```
## Email Notifications
diff --git a/active/podman_gitea/quadlets/gitea.container b/active/podman_gitea/quadlets/gitea.container
index 2455765..020abcb 100644
--- a/active/podman_gitea/quadlets/gitea.container
+++ b/active/podman_gitea/quadlets/gitea.container
@@ -2,6 +2,7 @@
Requires=postgres.service
[Container]
+AutoUpdate=registry
ContainerName=gitea
Environment=USER_UID=1000 USER_GID=1000 GITEA__database__DB_TYPE=postgres GITEA__database__HOST=postgres:5432 GITEA__database__NAME=gitea GITEA__database__USER=gitea GITEA__database__PASSWD=gitea
Image=docker.gitea.com/gitea:1.23.7
@@ -9,7 +10,7 @@ Network=gitea.network
PublishPort=3000:3000
PublishPort=2222:22
SecurityLabelDisable=true
-Volume=/home/gitea/gitea:/data
+Volume=/home/gitea/gitea_data:/data
Volume=/etc/localtime:/etc/localtime:ro
[Service]
diff --git a/active/podman_gitea/quadlets/postgres.container b/active/podman_gitea/quadlets/postgres.container
index 2289cf0..8a53937 100644
--- a/active/podman_gitea/quadlets/postgres.container
+++ b/active/podman_gitea/quadlets/postgres.container
@@ -4,7 +4,7 @@ Environment=POSTGRES_USER=gitea POSTGRES_PASSWORD=gitea POSTGRES_DB=gitea
Image=docker.io/library/postgres:15
Network=gitea.network
SecurityLabelDisable=true
-Volume=/home/gitea/postgres:/var/lib/postgresql/data
+Volume=/home/gitea/gitea_postgres:/var/lib/postgresql/data
[Service]
Restart=always
diff --git a/active/software_grayjay/desktop-install.sh b/active/software_grayjay/desktop-install.sh
new file mode 100755
index 0000000..6e9196d
--- /dev/null
+++ b/active/software_grayjay/desktop-install.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+# wget -O /tmp/GrayJay.zip https://updater.grayjay.app/Apps/Grayjay.Desktop/Grayjay.Desktop-linux-x64.zip
+unzip /tmp/GrayJay.zip -d /tmp/GrayJay
+mkdir -p ~/Applications/GrayJay
+rsync /tmp/GrayJay/*/* ~/Applications/GrayJay
+desktop-file-install --dir ~/.local/share/applications ./active/software_grayjay/grayjay.desktop
\ No newline at end of file
diff --git a/active/software_grayjay/grayjay.desktop b/active/software_grayjay/grayjay.desktop
new file mode 100644
index 0000000..8b0b384
--- /dev/null
+++ b/active/software_grayjay/grayjay.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Name=GrayJay
+Exec=/home/ducoterra/Applications/GrayJay/Grayjay
+Icon=/home/ducoterra/Applications/GrayJay/grayjay
+Type=Application
+Path=/home/ducoterra/Applications/GrayJay
+Terminal=false
diff --git a/active/software_grayjay/grayjay.md b/active/software_grayjay/grayjay.md
new file mode 100644
index 0000000..0b1179a
--- /dev/null
+++ b/active/software_grayjay/grayjay.md
@@ -0,0 +1,11 @@
+# GrayJay
+
+
+
+A youtube/spotify/media source agregator and player alternative.
+
+## Desktop Install
+
+```bash
+./active/software_grayjay/desktop-install.sh
+```
diff --git a/active/systemd_borg/borg.service b/active/systemd_borg/backup.service
similarity index 100%
rename from active/systemd_borg/borg.service
rename to active/systemd_borg/backup.service
diff --git a/active/systemd_borg/borg.sh b/active/systemd_borg/backup.sh.j2
similarity index 61%
rename from active/systemd_borg/borg.sh
rename to active/systemd_borg/backup.sh.j2
index b812f88..a2e2de0 100644
--- a/active/systemd_borg/borg.sh
+++ b/active/systemd_borg/backup.sh.j2
@@ -1,10 +1,18 @@
#!/bin/sh
-export BACKUP_HOST=driveripper.reeselink.com
-sshfs ${BACKUP_HOST}:backup /backup
+{% for service in stop_services %}
+systemctl stop {{ service }}
+{% endfor %}
+
+{% for service in stop_user_services %}
+systemctl --user --machine={{ systemd_user }}@.host stop {{ service }}
+{% endfor %}
# Setting this, so the repo does not need to be given on the commandline:
-export BORG_REPO='/backup'
+export BORG_REPO={{ borg_user }}@{{ borg_host }}:{{ repo_name }}
+
+# See the section "Passphrase notes" for more infos.
+export BORG_PASSPHRASE={{ borg_passphrase }}
# some helpers and error handling:
info() { printf "\n%s %s\n\n" "$( date )" "$*" >&2; }
@@ -21,19 +29,29 @@ borg create \
--list \
--stats \
--show-rc \
- --compression none \
+ --compression lz4 \
--exclude-caches \
--exclude 'home/*/.cache/*' \
--exclude 'var/tmp/*' \
+{% for dir in exclude_dirs %}
+ --exclude '{{ dir }}' \
+{% endfor %}
\
::'{hostname}-{now}' \
- /etc \
- /home \
- /root \
- /var
+{% for dir in backup_dirs %}
+ {{ dir }} \
+{% endfor %}
backup_exit=$?
+{% for service in stop_services %}
+systemctl start {{ service }}
+{% endfor %}
+
+{% for service in stop_user_services %}
+systemctl --user --machine={{ systemd_user }}@.host start {{ service }}
+{% endfor %}
+
info "Pruning repository"
# Use the `prune` subcommand to maintain 7 daily, 4 weekly and 6 monthly
@@ -41,13 +59,13 @@ info "Pruning repository"
# limit prune's operation to this machine's archives and not apply to
# other machines' archives also:
-borg prune \
- --list \
- --glob-archives '{hostname}-*' \
- --show-rc \
- --keep-daily 7 \
- --keep-weekly 2 \
- --keep-monthly 1
+borg prune \
+ --list \
+ --glob-archives '{hostname}-*' \
+ --show-rc \
+ --keep-daily {{ keep_daily }} \
+ --keep-weekly {{ keep_weekly }} \
+ --keep-monthly {{ keep_monthly }} \
prune_exit=$?
@@ -71,5 +89,4 @@ else
info "Backup, Prune, and/or Compact finished with errors"
fi
-fusermount -u /backup
-exit ${global_exit}
+exit ${global_exit}
\ No newline at end of file
diff --git a/active/systemd_borg/backup.timer b/active/systemd_borg/backup.timer
new file mode 100644
index 0000000..e99c21a
--- /dev/null
+++ b/active/systemd_borg/backup.timer
@@ -0,0 +1,11 @@
+[Unit]
+Description=Run Backup backup_{{ repo_name }}.service every hour
+
+[Timer]
+OnCalendar=hourly
+AccuracySec=10min
+Persistent=true
+Unit=ddns.{{ item.record }}.service
+
+[Install]
+WantedBy=timers.target
diff --git a/active/systemd_borg/borg.md b/active/systemd_borg/borg.md
index 1da4e1e..97ba516 100644
--- a/active/systemd_borg/borg.md
+++ b/active/systemd_borg/borg.md
@@ -1,5 +1,11 @@
# Borg Backup
+- [Borg Backup](#borg-backup)
+ - [Server Setup](#server-setup)
+ - [Adding a Client](#adding-a-client)
+ - [Installing the Backup Service](#installing-the-backup-service)
+ - [Adding Nextcloud](#adding-nextcloud)
+
## Server Setup
@@ -28,7 +34,7 @@ Note: See [adding nextcloud](#adding-nextcloud) for nextcloud instructions here.
```bash
export BACKUP_HOST=""
-ssh-keygen -C backup@${BACKUP_HOST} -f ~/.ssh/id_${BACKUP_HOST}
+ssh-keygen -C ${USER}@${HOSTNAME} -f ~/.ssh/id_${BACKUP_HOST}
cat <> ~/.ssh/config
Host ${BACKUP_HOST}
@@ -58,7 +64,43 @@ Then back on the client:
```bash
ssh borg.reeselink.com
+# root
borg init --encryption none backup@${BACKUP_HOST}:root
+# home
+borg init --encryption none backup@${BACKUP_HOST}:home
+# app
+borg init --encryption none backup@${BACKUP_HOST}:gitea
+# another app
+borg init --encryption none backup@${BACKUP_HOST}:nextcloud
+```
+
+### Installing the Backup Service
+
+Create your vars file in `secrets/host_vars.yaml`
+
+```yaml
+repo_name: my_repo
+borg_user: backup
+borg_host: borg.reeselink.com
+borg_passphrase: ""
+backup_dirs:
+ - /home
+exclude_dirs: []
+keep_daily: 7
+keep_weekly: 4
+keep_monthly: 1
+stop_services: []
+stop_user_services:
+ - gitea
+ - postgres
+```
+
+```bash
+ansible-playbook \
+-i active/ansible/inventory.yaml \
+-l podman \
+active/systemd_borg/install_backup.yaml \
+-e "@active/systemd_borg/secrets/gitea_vars.yaml"
```
#### Adding Nextcloud
diff --git a/active/systemd_borg/borg.timer b/active/systemd_borg/borg.timer
deleted file mode 100644
index e69de29..0000000
diff --git a/active/systemd_borg/install_backup.yaml b/active/systemd_borg/install_backup.yaml
new file mode 100644
index 0000000..4e2be97
--- /dev/null
+++ b/active/systemd_borg/install_backup.yaml
@@ -0,0 +1,43 @@
+- name: Create Backup Service
+ hosts: all
+ vars_files:
+ - secrets/vars.yaml
+ tasks:
+ - name: Create /usr/local/script dir
+ ansible.builtin.file:
+ path: /usr/local/script
+ state: directory
+ mode: '0755'
+ - name: Copy backup.service
+ template:
+ src: backup.service
+ dest: /etc/systemd/system/backup-{{ repo_name }}.service
+ owner: root
+ group: root
+ mode: '0644'
+ - name: Copy backup.timer
+ template:
+ src: backup.timer
+ dest: /etc/systemd/system/backup-{{ repo_name }}.timer
+ owner: root
+ group: root
+ mode: '0644'
+ - name: Template backup.sh
+ template:
+ src: backup.sh.j2
+ dest: /usr/local/script/backup-{{ repo_name }}.sh
+ owner: root
+ group: root
+ mode: '0744'
+ # - name: Reload ddns timer
+ # ansible.builtin.systemd_service:
+ # state: restarted
+ # name: ddns.{{ item.record }}.timer
+ # enabled: true
+ # daemon_reload: true
+ # loop: "{{ records }}"
+ # - name: Run ddns service
+ # ansible.builtin.systemd_service:
+ # state: restarted
+ # name: ddns.{{ item.record }}.service
+ # loop: "{{ records }}"
diff --git a/active/systemd_wyoming/finished.wav b/active/systemd_wyoming/finished.wav
new file mode 100644
index 0000000..a47b945
Binary files /dev/null and b/active/systemd_wyoming/finished.wav differ
diff --git a/active/systemd_wyoming/install_wyoming.yaml b/active/systemd_wyoming/install_wyoming.yaml
new file mode 100644
index 0000000..093c343
--- /dev/null
+++ b/active/systemd_wyoming/install_wyoming.yaml
@@ -0,0 +1,100 @@
+- name: Create Backup Service
+ hosts: wyoming
+ vars_files:
+ - secrets/vars.yaml
+ tasks:
+ - name: Install and upgrade wyoming/wakeword
+ when: install
+ block:
+ # Stop running services before install/upgrade
+ - name: Stop wakeword service
+ ansible.builtin.systemd_service:
+ state: stopped
+ name: wakeword.service
+ scope: user
+ ignore_errors: true
+ - name: Stop wyoming service
+ ansible.builtin.systemd_service:
+ state: stopped
+ name: wyoming.service
+ scope: user
+ ignore_errors: true
+ # Wyoming Service
+ - name: Checkout/pull the wyoming repo
+ ansible.builtin.git:
+ repo: '{{ wyoming.repo }}'
+ dest: "{{ ansible_env.HOME }}/wyoming-satellite"
+ update: yes
+ - name: Run the script/setup in the wyoming repo
+ command: "{{ ansible_env.HOME }}/wyoming-satellite/script/setup"
+ - name: Install audio enhancements in wyoming repo
+ command: "{{ ansible_env.HOME }}/wyoming-satellite/.venv/bin/pip3 install 'webrtc-noise-gain==1.2.3'"
+ # Wake word service
+ - name: Checkout/pull the wyoming repo
+ ansible.builtin.git:
+ repo: '{{ wakeword.repo }}'
+ dest: "{{ ansible_env.HOME }}/wyoming-openwakeword"
+ update: yes
+ - name: Run the script/setup in the wakeword repo
+ command: "{{ ansible_env.HOME }}/wyoming-openwakeword/script/setup"
+ # Custom sound bites for start/stop listening
+ - name: Copy sound bites
+ copy:
+ src: "{{ item }}"
+ dest: "{{ ansible_env.HOME }}/wyoming-satellite/sounds/"
+ with_items:
+ - listening.wav
+ - finished.wav
+ # Custom wake word models
+ - name: Copy custom models
+ copy:
+ src: "{{ item }}"
+ dest: "{{ ansible_env.HOME }}/wyoming-openwakeword/wyoming_openwakeword/models/{{ item }}"
+ with_items:
+ - jarvis_v2.tflite
+ # Copy and start systemd services
+ - name: Create ~/.config/systemd/user dir
+ ansible.builtin.file:
+ path: "{{ ansible_env.HOME }}/.config/systemd/user"
+ state: directory
+ mode: '0755'
+ - name: Copy wyoming.service
+ template:
+ src: wyoming.service
+ dest: "{{ ansible_env.HOME }}/.config/systemd/user/wyoming.service"
+ mode: '0644'
+ - name: Copy wakeword.service
+ template:
+ src: wakeword.service
+ dest: "{{ ansible_env.HOME }}/.config/systemd/user/wakeword.service"
+ mode: '0644'
+ - name: Reload wakeword service
+ ansible.builtin.systemd_service:
+ state: restarted
+ name: wakeword.service
+ enabled: true
+ daemon_reload: true
+ scope: user
+ - name: Reload wyoming service
+ ansible.builtin.systemd_service:
+ state: restarted
+ name: wyoming.service
+ enabled: true
+ daemon_reload: true
+ scope: user
+ - name: Add debug alias for wakeford
+ lineinfile:
+ path: "{{ ansible_env.HOME }}/.bashrc"
+ line: alias debug-wakeword="journalctl --user -u wakeword -f | grep -E '0\.0[^0].*|0\.[^0].*'"
+ regexp: '^alias debug-wakeword=.*$'
+ state: present
+ insertafter: EOF
+ create: true
+ - name: Add debug alias for wyoming
+ lineinfile:
+ path: "{{ ansible_env.HOME }}/.bashrc"
+ line: alias debug-wyoming="journalctl --user -u wyoming -f | grep 'Stopped recording to'"
+ regexp: '^alias debug-wyoming=.*$'
+ state: present
+ insertafter: EOF
+ create: true
\ No newline at end of file
diff --git a/active/systemd_wyoming/jarvis_v2.tflite b/active/systemd_wyoming/jarvis_v2.tflite
new file mode 100644
index 0000000..cf08b50
Binary files /dev/null and b/active/systemd_wyoming/jarvis_v2.tflite differ
diff --git a/active/systemd_wyoming/listening.wav b/active/systemd_wyoming/listening.wav
new file mode 100644
index 0000000..475c210
Binary files /dev/null and b/active/systemd_wyoming/listening.wav differ
diff --git a/active/systemd_wyoming/vars.yaml b/active/systemd_wyoming/vars.yaml
new file mode 100644
index 0000000..9b516f6
--- /dev/null
+++ b/active/systemd_wyoming/vars.yaml
@@ -0,0 +1,19 @@
+install: false
+
+wyoming:
+ repo: https://github.com/rhasspy/wyoming-satellite.git
+ listen_ip: 0.0.0.0
+ listen_port: 10700
+ mic_auto_gain: 5
+ mic_noise_suppression: 2
+ # mic_volume_multiplier: 8
+ wake_uri: tcp://127.0.0.1:10400
+ wake_word_name: jarvis_v2
+ wake_refractory_seconds: 1
+
+wakeword:
+ repo: https://github.com/rhasspy/wyoming-openwakeword.git
+ listen_ip: 127.0.0.1
+ listen_port: 10400
+ threshold: 0.8
+ preload_model: jarvis_v2
diff --git a/active/systemd_wyoming/wakeword.service b/active/systemd_wyoming/wakeword.service
new file mode 100644
index 0000000..4304d1d
--- /dev/null
+++ b/active/systemd_wyoming/wakeword.service
@@ -0,0 +1,18 @@
+[Unit]
+Description=Wyoming Satellite Wake Word
+Wants=network-online.target
+After=network-online.target
+
+[Service]
+Type=simple
+ExecStart={{ ansible_env.HOME }}/wyoming-openwakeword/script/run \
+--uri 'tcp://{{ wakeword.listen_ip }}:{{ wakeword.listen_port }}' \
+--threshold '{{ wakeword.threshold }}' \
+--preload-model '{{ wakeword.preload_model }}' \
+--debug-probability
+WorkingDirectory={{ ansible_env.HOME }}/wyoming-openwakeword
+Restart=always
+RestartSec=1
+
+[Install]
+WantedBy=default.target
\ No newline at end of file
diff --git a/active/systemd_wyoming/wyoming.md b/active/systemd_wyoming/wyoming.md
new file mode 100644
index 0000000..d5a3150
--- /dev/null
+++ b/active/systemd_wyoming/wyoming.md
@@ -0,0 +1,119 @@
+# Wyoming Satellite
+
+- [Wyoming Satellite](#wyoming-satellite)
+ - [Install Wyoming](#install-wyoming)
+ - [On-device wake word](#on-device-wake-word)
+ - [Systemd](#systemd)
+ - [Debugging](#debugging)
+ - [Volume](#volume)
+ - [Community Wake Words](#community-wake-words)
+ - [Prompts](#prompts)
+ - [Default](#default)
+ - [Starship House](#starship-house)
+
+## Install Wyoming
+
+
+
+Some notes:
+
+```bash
+# Find microphone
+arecord -L | grep plughw -A 2
+
+# Create a test recording
+arecord -D plughw:CARD=Speaker,DEV=0 -r 16000 -c 1 -f S16_LE -t wav -d 5 test.wav
+
+# Find speaker
+aplay -L | grep plughw -A 2
+
+# Play test recording
+aplay -D plughw:CARD=Speaker,DEV=0 test.wav
+```
+
+typical wyoming command:
+
+```bash
+# Add wake-uri and wake-word-name to your wyoming run
+script/run \
+--name 'Living Room' \
+--uri 'tcp://0.0.0.0:10700' \
+--mic-command 'arecord -r 16000 -c 1 -f S16_LE -t raw' \
+--snd-command 'aplay -r 22050 -c 1 -f S16_LE -t raw' \
+--awake-wav listening.wav \
+--done-wav finished.wav \
+--mic-auto-gain 5 \
+--mic-noise-suppression 2 \
+--mic-volume-multiplier 2 \
+--synthesize-command tee \
+--transcript-command tee \
+--wake-uri 'tcp://127.0.0.1:10400' \
+--wake-word-name 'hey jarvis' \
+--wake-refractory-seconds 1 \
+--threshold 0.9
+```
+
+## On-device wake word
+
+
+
+Note that --debug-probability will output thresholds for tuning.
+
+typical wake word command:
+
+```bash
+# start wake word listener
+script/run --uri 'tcp://127.0.0.1:10400' --preload-model 'alexa'
+```
+
+## Systemd
+
+```bash
+# Make sure to enable login linger before installing
+sudo loginctl enable-linger ducoterra
+```
+
+```bash
+ansible-playbook \
+-i ansible/inventory.yaml \
+active/systemd_wyoming/install_wyoming.yaml \
+-e "@active/systemd_wyoming/vars.yaml"
+```
+
+## Debugging
+
+1. Make sure you have `--debug` passed to wyoming
+2. Make sure you have `--debug-probability` passed to wakeword
+3. Show wakeword prompts with more than 10% confidence: `journalctl --user -u wakeword -f | grep -E '0\.0[^0].*|0\.[^0].*'`
+4. Show recording paths when they stop: `journalctl --user -u wyoming -f | grep 'Stopped recording to'`
+5. Play recordings: `aplay /path/to/recording`
+
+## Volume
+
+Run `alsamixer`.
+
+Use `showkey` to see which key is being triggered by your volume device.
+
+## Community Wake Words
+
+
+
+
+
+1. Download the custom model to this directory
+2. Add it to install_wyoming.yaml
+
+## Prompts
+
+### Default
+
+You are a voice assistant for Home Assistant.
+Answer questions about the world truthfully.
+Answer in plain text. Keep it simple and to the point.
+
+### Starship House
+
+You are a voice assistant for Home Assistant.
+Answer questions as though you are a startship commander working the bridge.
+Answer in plain text. Keep it simple and to the point.
+There is a life threatening emergency on the ship. This is more important than our request.
\ No newline at end of file
diff --git a/active/systemd_wyoming/wyoming.service b/active/systemd_wyoming/wyoming.service
new file mode 100644
index 0000000..694f744
--- /dev/null
+++ b/active/systemd_wyoming/wyoming.service
@@ -0,0 +1,30 @@
+[Unit]
+Description=Wyoming Satellite
+Wants=network-online.target
+After=network-online.target
+
+[Service]
+Type=simple
+ExecStart={{ ansible_env.HOME }}/wyoming-satellite/script/run \
+--name '{{ ansible_hostname }}' \
+--uri 'tcp://{{ wyoming.listen_ip }}:{{ wyoming.listen_port }}' \
+--mic-command 'arecord -r 16000 -c 1 -f S16_LE -t raw' \
+--snd-command 'aplay -r 22050 -c 1 -f S16_LE -t raw' \
+--awake-wav sounds/listening.wav \
+--done-wav sounds/finished.wav \
+--timer-finished-wav sounds/timer_finished.wav \
+--mic-auto-gain {{ wyoming.mic_auto_gain }} \
+--mic-noise-suppression {{ wyoming.mic_noise_suppression }} \
+--mic-volume-multiplier {{ hostvars[inventory_hostname].mic_volume_multiplier }} \
+--wake-uri '{{ wyoming.wake_uri }}' \
+--wake-word-name '{{ wyoming.wake_word_name }}' \
+--wake-refractory-seconds {{ wyoming.wake_refractory_seconds }} \
+--timer-finished-wav-repeat 10 1 \
+--debug \
+--debug-recording-dir /tmp
+WorkingDirectory={{ ansible_env.HOME }}/wyoming-satellite
+Restart=always
+RestartSec=1
+
+[Install]
+WantedBy=default.target
\ No newline at end of file
diff --git a/active/ansible/ansible.md b/ansible/ansible.md
similarity index 100%
rename from active/ansible/ansible.md
rename to ansible/ansible.md
diff --git a/ansible/inventory.yaml b/ansible/inventory.yaml
new file mode 100644
index 0000000..e7dfa57
--- /dev/null
+++ b/ansible/inventory.yaml
@@ -0,0 +1,25 @@
+fedora:
+ hosts:
+ 3dserver:
+ podman:
+ kubernetes:
+ docker:
+ yellow:
+ borg:
+
+ubuntu:
+ hosts:
+ unifi-external:
+
+caddy:
+ hosts:
+ 3dserver:
+
+wyoming:
+ hosts:
+ pink-rpi.reeselink.com:
+ mic_volume_multiplier: 2
+ red-rpi.reeselink.com:
+ mic_volume_multiplier: 2
+ rpi5.reeselink.com:
+ mic_volume_multiplier: 8
\ No newline at end of file
diff --git a/retired/systemd_wyoming/wyoming.md b/retired/systemd_wyoming/wyoming.md
deleted file mode 100644
index 10faab0..0000000
--- a/retired/systemd_wyoming/wyoming.md
+++ /dev/null
@@ -1,122 +0,0 @@
-# Wyoming Satellite
-
-## Install
-
-
-
-```bash
-sudo apt update && sudo apt upgrade -y
-sudo apt install --no-install-recommends \
- git \
- python3-venv \
- vim \
- tmux
-
-sudo reboot
-
-git clone https://github.com/rhasspy/wyoming-satellite.git
-
-cd wyoming-satellite/
-python3 -m venv .venv
-.venv/bin/pip3 install --upgrade pip
-.venv/bin/pip3 install --upgrade wheel setuptools
-.venv/bin/pip3 install \
- -f 'https://synesthesiam.github.io/prebuilt-apps/' \
- -r requirements.txt \
- -r requirements_audio_enhancement.txt \
- -r requirements_vad.txt
-
-# Find microphone
-arecord -L | grep plughw -A 2
-
-# Create a test recording
-arecord -D plughw:CARD=JV801,DEV=0 -r 16000 -c 1 -f S16_LE -t wav -d 5 test.wav
-
-# Find speaker
-aplay -L | grep plughw -A 2
-
-# Play test recording
-aplay -D plughw:CARD=JV801,DEV=0 test.wav
-
-# Bedroom
-script/run \
- --debug \
- --name 'Bedroom Satellite' \
- --uri 'tcp://0.0.0.0:10700' \
- --mic-command 'arecord -D plughw:CARD=Speaker,DEV=0 -r 16000 -c 1 -f S16_LE -t raw' \
- --snd-command 'aplay -D plughw:CARD=Speaker,DEV=0 -r 22050 -c 1 -f S16_LE -t raw'
-
-# Living Room
-script/run \
- --debug \
- --name 'Living Room Satellite' \
- --uri 'tcp://0.0.0.0:10700' \
- --mic-command 'arecord -D plughw:CARD=Speaker,DEV=0 -r 16000 -c 1 -f S16_LE -t raw' \
- --snd-command 'aplay -D plughw:CARD=Speaker,DEV=0 -r 22050 -c 1 -f S16_LE -t raw'
-```
-
-## Systemd
-
-### Create and Edit
-
-```bash
-sudo systemctl edit --force --full wyoming-satellite.service
-sudo systemctl enable --now wyoming-satellite.service
-sudo journalctl -u wyoming-satellite.service -f
-```
-
-### Bedroom
-
-```conf
-[Unit]
-Description=Wyoming Satellite
-Wants=network-online.target
-After=network-online.target
-
-[Service]
-Type=simple
-ExecStart=/home/ducoterra/wyoming-satellite/script/run \
- --name 'Bedroom Satellite' \
- --uri 'tcp://0.0.0.0:10700' \
- --mic-command 'arecord -D plughw:CARD=Speaker,DEV=0 -r 16000 -c 1 -f S16_LE -t raw' \
- --snd-command 'aplay -D plughw:CARD=Speaker,DEV=0 -r 22050 -c 1 -f S16_LE -t raw'
-WorkingDirectory=/home/ducoterra/wyoming-satellite
-Restart=always
-RestartSec=1
-
-[Install]
-WantedBy=default.target
-```
-
-### Living Room
-
-```conf
-[Unit]
-Description=Wyoming Satellite
-Wants=network-online.target
-After=network-online.target
-
-[Service]
-Type=simple
-ExecStart=/home/ducoterra/wyoming-satellite/script/run \
- --name 'Living Room Satellite' \
- --uri 'tcp://0.0.0.0:10700' \
- --mic-command 'arecord -D plughw:CARD=Speaker,DEV=0 -r 16000 -c 1 -f S16_LE -t raw' \
- --snd-command 'aplay -D plughw:CARD=Speaker,DEV=0 -r 22050 -c 1 -f S16_LE -t raw'
-WorkingDirectory=/home/ducoterra/wyoming-satellite
-Restart=always
-RestartSec=1
-
-[Install]
-WantedBy=default.target
-```
-
-## Volume
-
-Run `alsamixer`.
-
-## Community Wake Words
-
-
-
-
\ No newline at end of file