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
|
target: amdgpu
|
||||||
push: true
|
push: true
|
||||||
tags: "gitea.reeseapps.com/services/arch-toolbox-amdgpu:latest,gitea.reeseapps.com/services/arch-toolbox-amdgpu:${{gitea.sha}}"
|
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__/
|
__pycache__/
|
||||||
.pytest_cache/
|
.pytest_cache/
|
||||||
.venv/
|
.venv/
|
||||||
|
.mypy_cache
|
||||||
@@ -45,6 +45,8 @@ Host ${KEYGEN_HOST}
|
|||||||
EOF
|
EOF
|
||||||
```
|
```
|
||||||
|
|
||||||
|
In vim: `esc + o` will take you to the end of a file and insert a new line.
|
||||||
|
|
||||||
## Important Dates and Times
|
## Important Dates and Times
|
||||||
|
|
||||||
- Machine updates happen at 4am on on Saturday
|
- 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
|
```bash
|
||||||
export SSH_HOST=kube
|
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
|
# 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.
|
# keys in your ~/.ssh directory. Use `-o PubkeyAuthentication` to fix it.
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
- [Hostname](#hostname)
|
- [Hostname](#hostname)
|
||||||
- [VLAN Setup with nmcli](#vlan-setup-with-nmcli)
|
- [VLAN Setup with nmcli](#vlan-setup-with-nmcli)
|
||||||
- [GPU Support in Distrobox](#gpu-support-in-distrobox)
|
- [GPU Support in Distrobox](#gpu-support-in-distrobox)
|
||||||
|
- [Automatic Display Switching](#automatic-display-switching)
|
||||||
|
|
||||||
## TPM2 Luks Decryption
|
## TPM2 Luks Decryption
|
||||||
|
|
||||||
@@ -162,3 +163,56 @@ sudo usermod -aG render $USER
|
|||||||
```
|
```
|
||||||
|
|
||||||
Logout and log back in to adopt new groups.
|
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
|
```bash
|
||||||
export SSH_HOST=kube
|
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
|
# 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.
|
# keys in your ~/.ssh directory. Use `-o PubkeyAuthentication` to fix it.
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ services:
|
|||||||
- postgres
|
- postgres
|
||||||
security_opt:
|
security_opt:
|
||||||
- label=disable
|
- label=disable
|
||||||
|
labels:
|
||||||
|
- "io.containers.autoupdate=registry"
|
||||||
|
|
||||||
postgres:
|
postgres:
|
||||||
image: docker.io/library/postgres:15
|
image: docker.io/library/postgres:15
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
- [Create the gitea user](#create-the-gitea-user)
|
- [Create the gitea user](#create-the-gitea-user)
|
||||||
- [Convert Compose to Quadlet](#convert-compose-to-quadlet)
|
- [Convert Compose to Quadlet](#convert-compose-to-quadlet)
|
||||||
- [Install Quadlets](#install-quadlets)
|
- [Install Quadlets](#install-quadlets)
|
||||||
|
- [Upgrade Quadlets](#upgrade-quadlets)
|
||||||
- [Editing Configs within Container](#editing-configs-within-container)
|
- [Editing Configs within Container](#editing-configs-within-container)
|
||||||
- [Gitea Runners](#gitea-runners)
|
- [Gitea Runners](#gitea-runners)
|
||||||
- [Firewall Rules](#firewall-rules)
|
- [Firewall Rules](#firewall-rules)
|
||||||
@@ -63,9 +64,18 @@ scp -r quadlets/. gitea:~/.config/containers/systemd/
|
|||||||
The first user you register will be the admin
|
The first user you register will be the admin
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ssh gitea
|
ssh gitea systemctl --user daemon-reload
|
||||||
systemctl --user daemon-reload
|
ssh gitea systemctl --user restart gitea postgres
|
||||||
systemctl --user start 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
|
### Editing Configs within Container
|
||||||
@@ -141,10 +151,11 @@ You should run something like this on a schedule:
|
|||||||
docker builder prune -a
|
docker builder prune -a
|
||||||
```
|
```
|
||||||
|
|
||||||
To run it every day at midnight: `crontab -e`
|
To run it every day at noon: `crontab -e`
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
0 0 * * * yes | docker builder prune -a
|
0 12 * * * yes | docker builder prune -a
|
||||||
|
0 12 * * * docker image prune -a -f
|
||||||
```
|
```
|
||||||
|
|
||||||
## Email Notifications
|
## Email Notifications
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
Requires=postgres.service
|
Requires=postgres.service
|
||||||
|
|
||||||
[Container]
|
[Container]
|
||||||
|
AutoUpdate=registry
|
||||||
ContainerName=gitea
|
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
|
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
|
Image=docker.gitea.com/gitea:1.23.7
|
||||||
@@ -9,7 +10,7 @@ Network=gitea.network
|
|||||||
PublishPort=3000:3000
|
PublishPort=3000:3000
|
||||||
PublishPort=2222:22
|
PublishPort=2222:22
|
||||||
SecurityLabelDisable=true
|
SecurityLabelDisable=true
|
||||||
Volume=/home/gitea/gitea:/data
|
Volume=/home/gitea/gitea_data:/data
|
||||||
Volume=/etc/localtime:/etc/localtime:ro
|
Volume=/etc/localtime:/etc/localtime:ro
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Environment=POSTGRES_USER=gitea POSTGRES_PASSWORD=gitea POSTGRES_DB=gitea
|
|||||||
Image=docker.io/library/postgres:15
|
Image=docker.io/library/postgres:15
|
||||||
Network=gitea.network
|
Network=gitea.network
|
||||||
SecurityLabelDisable=true
|
SecurityLabelDisable=true
|
||||||
Volume=/home/gitea/postgres:/var/lib/postgresql/data
|
Volume=/home/gitea/gitea_postgres:/var/lib/postgresql/data
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Restart=always
|
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
|
#!/bin/sh
|
||||||
|
|
||||||
export BACKUP_HOST=driveripper.reeselink.com
|
{% for service in stop_services %}
|
||||||
sshfs ${BACKUP_HOST}:backup /backup
|
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:
|
# 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:
|
# some helpers and error handling:
|
||||||
info() { printf "\n%s %s\n\n" "$( date )" "$*" >&2; }
|
info() { printf "\n%s %s\n\n" "$( date )" "$*" >&2; }
|
||||||
@@ -21,19 +29,29 @@ borg create \
|
|||||||
--list \
|
--list \
|
||||||
--stats \
|
--stats \
|
||||||
--show-rc \
|
--show-rc \
|
||||||
--compression none \
|
--compression lz4 \
|
||||||
--exclude-caches \
|
--exclude-caches \
|
||||||
--exclude 'home/*/.cache/*' \
|
--exclude 'home/*/.cache/*' \
|
||||||
--exclude 'var/tmp/*' \
|
--exclude 'var/tmp/*' \
|
||||||
|
{% for dir in exclude_dirs %}
|
||||||
|
--exclude '{{ dir }}' \
|
||||||
|
{% endfor %}
|
||||||
\
|
\
|
||||||
::'{hostname}-{now}' \
|
::'{hostname}-{now}' \
|
||||||
/etc \
|
{% for dir in backup_dirs %}
|
||||||
/home \
|
{{ dir }} \
|
||||||
/root \
|
{% endfor %}
|
||||||
/var
|
|
||||||
|
|
||||||
backup_exit=$?
|
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"
|
info "Pruning repository"
|
||||||
|
|
||||||
# Use the `prune` subcommand to maintain 7 daily, 4 weekly and 6 monthly
|
# Use the `prune` subcommand to maintain 7 daily, 4 weekly and 6 monthly
|
||||||
@@ -45,9 +63,9 @@ borg prune \
|
|||||||
--list \
|
--list \
|
||||||
--glob-archives '{hostname}-*' \
|
--glob-archives '{hostname}-*' \
|
||||||
--show-rc \
|
--show-rc \
|
||||||
--keep-daily 7 \
|
--keep-daily {{ keep_daily }} \
|
||||||
--keep-weekly 2 \
|
--keep-weekly {{ keep_weekly }} \
|
||||||
--keep-monthly 1
|
--keep-monthly {{ keep_monthly }} \
|
||||||
|
|
||||||
prune_exit=$?
|
prune_exit=$?
|
||||||
|
|
||||||
@@ -71,5 +89,4 @@ else
|
|||||||
info "Backup, Prune, and/or Compact finished with errors"
|
info "Backup, Prune, and/or Compact finished with errors"
|
||||||
fi
|
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](#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
|
## Server Setup
|
||||||
|
|
||||||
<https://borgbackup.readthedocs.io/en/stable/deployment/central-backup-server.html#user-and-group>
|
<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
|
```bash
|
||||||
export BACKUP_HOST=""
|
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
|
cat <<EOF >> ~/.ssh/config
|
||||||
Host ${BACKUP_HOST}
|
Host ${BACKUP_HOST}
|
||||||
@@ -58,7 +64,43 @@ Then back on the client:
|
|||||||
```bash
|
```bash
|
||||||
ssh borg.reeselink.com
|
ssh borg.reeselink.com
|
||||||
|
|
||||||
|
# root
|
||||||
borg init --encryption none backup@${BACKUP_HOST}: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
|
#### 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