wyoming, borg, grayjay, oh my
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 9m54s
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 9m54s
This commit is contained in:
@@ -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-cache: false
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,3 +6,4 @@ volumes/
|
||||
__pycache__/
|
||||
.pytest_cache/
|
||||
.venv/
|
||||
.mypy_cache
|
||||
@@ -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
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
fedora:
|
||||
hosts:
|
||||
3dserver:
|
||||
podman:
|
||||
kubernetes:
|
||||
docker:
|
||||
yellow:
|
||||
borg:
|
||||
|
||||
ubuntu:
|
||||
hosts:
|
||||
unifi-external:
|
||||
|
||||
caddy:
|
||||
hosts:
|
||||
3dserver:
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
```
|
||||
@@ -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.
|
||||
|
||||
@@ -28,6 +28,8 @@ services:
|
||||
- postgres
|
||||
security_opt:
|
||||
- label=disable
|
||||
labels:
|
||||
- "io.containers.autoupdate=registry"
|
||||
|
||||
postgres:
|
||||
image: docker.io/library/postgres:15
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
7
active/software_grayjay/desktop-install.sh
Executable file
7
active/software_grayjay/desktop-install.sh
Executable file
@@ -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
|
||||
7
active/software_grayjay/grayjay.desktop
Normal file
7
active/software_grayjay/grayjay.desktop
Normal file
@@ -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
|
||||
11
active/software_grayjay/grayjay.md
Normal file
11
active/software_grayjay/grayjay.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# GrayJay
|
||||
|
||||
<https://grayjay.app/>
|
||||
|
||||
A youtube/spotify/media source agregator and player alternative.
|
||||
|
||||
## Desktop Install
|
||||
|
||||
```bash
|
||||
./active/software_grayjay/desktop-install.sh
|
||||
```
|
||||
@@ -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}
|
||||
11
active/systemd_borg/backup.timer
Normal file
11
active/systemd_borg/backup.timer
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
<https://borgbackup.readthedocs.io/en/stable/deployment/central-backup-server.html#user-and-group>
|
||||
@@ -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 <<EOF >> ~/.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
|
||||
|
||||
43
active/systemd_borg/install_backup.yaml
Normal file
43
active/systemd_borg/install_backup.yaml
Normal file
@@ -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 }}"
|
||||
BIN
active/systemd_wyoming/finished.wav
Normal file
BIN
active/systemd_wyoming/finished.wav
Normal file
Binary file not shown.
100
active/systemd_wyoming/install_wyoming.yaml
Normal file
100
active/systemd_wyoming/install_wyoming.yaml
Normal file
@@ -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
|
||||
BIN
active/systemd_wyoming/jarvis_v2.tflite
Normal file
BIN
active/systemd_wyoming/jarvis_v2.tflite
Normal file
Binary file not shown.
BIN
active/systemd_wyoming/listening.wav
Normal file
BIN
active/systemd_wyoming/listening.wav
Normal file
Binary file not shown.
19
active/systemd_wyoming/vars.yaml
Normal file
19
active/systemd_wyoming/vars.yaml
Normal file
@@ -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
|
||||
18
active/systemd_wyoming/wakeword.service
Normal file
18
active/systemd_wyoming/wakeword.service
Normal file
@@ -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
|
||||
119
active/systemd_wyoming/wyoming.md
Normal file
119
active/systemd_wyoming/wyoming.md
Normal file
@@ -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
|
||||
|
||||
<https://github.com/rhasspy/wyoming-satellite>
|
||||
|
||||
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
|
||||
|
||||
<https://github.com/rhasspy/wyoming-openwakeword/>
|
||||
|
||||
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
|
||||
|
||||
<https://github.com/fwartner/home-assistant-wakewords-collection?tab=readme-ov-file>
|
||||
|
||||
<https://github.com/fwartner/ha-openwakeword-installer>
|
||||
|
||||
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.
|
||||
30
active/systemd_wyoming/wyoming.service
Normal file
30
active/systemd_wyoming/wyoming.service
Normal file
@@ -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
|
||||
25
ansible/inventory.yaml
Normal file
25
ansible/inventory.yaml
Normal file
@@ -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
|
||||
@@ -1,122 +0,0 @@
|
||||
# Wyoming Satellite
|
||||
|
||||
## Install
|
||||
|
||||
<https://github.com/rhasspy/wyoming-satellite/blob/master/docs/tutorial_2mic.md>
|
||||
|
||||
```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
|
||||
|
||||
<https://github.com/fwartner/home-assistant-wakewords-collection?tab=readme-ov-file>
|
||||
|
||||
<https://github.com/fwartner/ha-openwakeword-installer>
|
||||
Reference in New Issue
Block a user