Compare commits

...

144 Commits

Author SHA1 Message Date
380d8f8e48 get cloud-init working consistently
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 55s
2025-11-26 13:54:01 -05:00
07a297f818 Add better intro to README
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 59s
2025-11-21 13:43:23 -05:00
d7224b038b switch to custom caddy with route53 dns support
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 2m21s
2025-11-20 17:58:53 -05:00
fc62219db7 update jellyfin to 10.11.3 2025-11-20 07:24:26 -05:00
2ebd97c345 update gitea to 2.5.1 2025-11-20 07:06:18 -05:00
270e86bfd0 clean up templates 2025-11-20 06:57:11 -05:00
7305e3a35b add cloud-init notes for amazon linux on qemu 2025-11-20 06:56:56 -05:00
aabbd8286f update immich to 2.3.1 2025-11-20 06:56:27 -05:00
37f7d442a1 add missing return 2025-11-20 06:56:09 -05:00
3ff805fa39 clamav don't alert on max size
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 1m33s
2025-11-18 10:24:53 -05:00
1ae62e70ed move systemd prefixes to software prefixes 2025-11-18 10:01:18 -05:00
91f4687c07 add esphome display notes 2025-11-18 09:57:49 -05:00
dc2df62d04 add borg repo update notes 2025-11-18 09:57:14 -05:00
b75aac76c2 add firewalld inspection notes 2025-11-18 09:57:00 -05:00
5161dced6e add clamav ignore signatures notes 2025-11-18 09:56:44 -05:00
d9ed144578 add lvfs-testing framework 16 update notes 2025-11-18 09:56:08 -05:00
5516f9530b add virsh networking notes
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 1m50s
2025-11-13 17:05:06 -05:00
621be95870 add fedora43 and default credentials to osbuild 2025-11-13 16:53:39 -05:00
b526901546 add clamav docs 2025-11-13 16:53:02 -05:00
b328081b59 upgrade immich 2025-11-13 16:52:45 -05:00
113b859927 Clarify docker integration with podman on fedora 2025-11-13 16:51:36 -05:00
57ff005186 add selinux files to gitignore 2025-11-13 16:51:13 -05:00
7ccedb9768 move selinux, firewalld, k3s 2025-11-13 16:51:02 -05:00
ef527abef4 expand yubikey docs to include gpg 2025-11-13 16:49:39 -05:00
75f4aaebf1 add clamav docs
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 39s
2025-11-07 13:29:02 -05:00
1396e09227 add gitea demo values compatible with metallb
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 55s
2025-11-03 09:54:40 -05:00
cbe8c4a369 add l2advertisement to metallb address pool k0s config 2025-11-03 09:54:21 -05:00
2f88c75655 Fix super old version of metallb in k0s 2025-11-03 09:42:09 -05:00
0f4b73720c Update metallb configmap to custom resource 2025-11-03 09:24:15 -05:00
b97f41eb70 fedora updates and systemd renames
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 58s
2025-10-30 22:51:53 -04:00
6df02e8dff k0s updates 2025-10-30 22:51:17 -04:00
57ae6b7e72 update dd command for bootable arch installer
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 56s
2025-10-23 10:41:11 -04:00
e3ba1759c4 init software_steam 2025-10-23 10:40:56 -04:00
af70d1d396 add secure boot note to systemd_qemu 2025-10-23 10:40:47 -04:00
5b474c7190 init software_k0s 2025-10-23 10:40:20 -04:00
d94cd01008 init software_virsh 2025-10-23 10:40:10 -04:00
afb27c512c add composer-cli list image command 2025-10-23 10:40:00 -04:00
a500c8a572 add yubikey gpg notes 2025-10-23 10:39:34 -04:00
c5748d81da add tagline to image builder docs
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 3m58s
2025-10-22 16:58:59 -04:00
b38390029f update README ssh notes 2025-10-22 16:57:53 -04:00
b116ea73ec add gpg change key password 2025-10-22 16:57:38 -04:00
920aeef7f3 update key names and add ssh public keys 2025-10-22 16:57:19 -04:00
9038962f29 add image builder notes 2025-10-22 16:57:05 -04:00
3fed164193 add gpg import keys, delete keys, sign, and encrypt files
Some checks failed
Podman DDNS Image / build-and-push-ddns (push) Failing after 2s
2025-10-20 17:25:26 -04:00
487e03c0bd update codium extension list 2025-10-20 12:23:23 -04:00
cf0a7373d4 move pgp to gpg and add export and expiration notes 2025-10-20 12:18:49 -04:00
e0adee5362 add gpg notes and gpg public keys 2025-10-19 21:36:09 -04:00
8f3e624925 Add gpg commit signing to README 2025-10-19 21:01:17 -04:00
e1e551c5cc add inputrc, find, and tmux notes to README
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 1m55s
2025-10-14 12:38:59 -04:00
23d3949421 improve podman template with checkboxes and better descriptions 2025-10-14 12:38:42 -04:00
714dd32ff6 convert README ssh key gen to script 2025-10-14 12:38:22 -04:00
8035fa38dc update freeipa smart card notes 2025-10-14 12:38:13 -04:00
b91cc1adc3 add install wakeword notes to wyoming 2025-10-14 12:37:55 -04:00
4fe56de990 update pytorch versions required by stable diffusion webui forge 2025-10-14 12:37:33 -04:00
9ef631b266 clarify difference between server and laptop in borg notes 2025-10-14 12:37:14 -04:00
8c39f749c7 add yt-dlp notes 2025-10-14 12:36:56 -04:00
1361c726d9 add bluetooth wireshark notes 2025-10-14 12:36:50 -04:00
1879158b6c add system monitor template backups 2025-10-14 12:36:41 -04:00
7b9968762a add ffpmeg notes 2025-10-14 12:36:29 -04:00
250ffeb266 add pgp notes 2025-10-14 12:36:22 -04:00
de6c1941c5 add firewall rules notes to podman ollama 2025-10-14 12:36:13 -04:00
9bc09a4b98 fix nextcloud deploy user 2025-10-14 12:36:01 -04:00
79377b3653 simplify podman minecraft deploy 2025-10-14 12:35:35 -04:00
d44bca3f2b add podman matrix 2025-10-14 12:35:23 -04:00
660735f0ae simplify podman jellyfin deploy 2025-10-14 12:35:10 -04:00
6dfd30e175 Upgrade podman immich to v2 2025-10-14 12:34:59 -04:00
0e5250d84d fix podman gitea volume permissions 2025-10-14 12:34:32 -04:00
556149c583 remove ansible podman ddns record 2025-10-14 12:34:17 -04:00
72e13f53aa fix caddy ansible playbook link 2025-10-14 12:33:55 -04:00
e9c68abeb9 updates to creating podman bricktracker user 2025-10-14 12:33:44 -04:00
69e8e89e72 truenas iscsi log notes 2025-10-14 12:33:29 -04:00
85e74541c2 rhel initialization with smart card notes 2025-10-14 12:33:11 -04:00
cb66fb6195 fedora snapper, tuned, and selinux policies 2025-10-14 12:32:57 -04:00
8d98cd06fa fix title conflict in arch docs 2025-10-14 12:32:37 -04:00
a85627b3b2 init truenas server device notes 2025-10-14 12:32:12 -04:00
f046e6edc2 add shelly bthome notes and more detailed instructions for existing devices 2025-10-14 12:32:01 -04:00
a32f055ede add home assistant unifi cameras, datetimes, and voice notes 2025-10-14 12:31:35 -04:00
0c6509cc17 add esphome notes 2025-10-14 12:31:14 -04:00
82b60c086c add alicia's printer 2025-10-14 12:31:05 -04:00
999869cab6 add 3dserver device 2025-10-14 12:30:55 -04:00
548cdc8b87 immich init 2025-10-01 22:37:49 -04:00
4832b283bb update podman rootless gitea docs
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 53s
2025-09-07 15:15:28 -04:00
9e83048248 fix gitea ssh key change on every reboot
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 1m3s
2025-07-30 22:40:20 -04:00
f2d684fa7c add scrubbing time to important dates and times 2025-07-25 20:42:31 -04:00
7980bfb381 add example json aws route53 record for minecraft 2025-07-25 20:42:18 -04:00
20690c48e5 add section on decrypting and scrubbing pools 2025-07-25 20:42:04 -04:00
ca582333f1 move some fedora software from server to software md 2025-07-25 20:41:51 -04:00
dae4063f25 fix keep-userns for systemd service generation
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 36s
2025-07-22 19:30:40 -04:00
5184c84d50 overhauls of most service docs
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 33s
2025-07-22 18:29:07 -04:00
3f3a03ee05 retire distoolbox
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 1m4s
2025-07-15 17:10:48 -04:00
22c1d635c6 upgrade gitea to 1.24
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 18m34s
Podman DDNS Image / build-and-push-ddns (push) Successful in 1m42s
2025-07-02 15:51:52 -04:00
5512c266eb fixes and updates to podman_gitea 2025-07-02 15:50:35 -04:00
de8b827cfb major vscode config overhauls. Getting python working as expected
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 21m26s
Podman DDNS Image / build-and-push-ddns (push) Successful in 34s
2025-05-26 12:04:53 -04:00
7b93f740ec wyoming updates, borg manual, fedora kscreen, bambu wifi, vscode pylance, stable diffusion
Some checks failed
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Failing after 2m40s
Podman DDNS Image / build-and-push-ddns (push) Failing after 5s
2025-05-23 13:49:03 -04:00
b3e4a45996 make ollama-* actions user-independent
Some checks failed
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Failing after 3m13s
Podman DDNS Image / build-and-push-ddns (push) Successful in 50s
2025-05-04 23:59:00 -04:00
ab2b033c54 wyoming, borg, grayjay, oh my
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 9m54s
2025-05-04 02:34:10 -04:00
ducoterra
c2fa408c1e Update README.md
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 26m40s
Podman DDNS Image / build-and-push-ddns (push) Successful in 32s
2025-04-22 11:46:24 -04:00
ducoterra
a469444811 Update README.md 2025-04-22 11:38:31 -04:00
ed2088d0dc remove bump.txt as not needed
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 25m40s
Podman DDNS Image / build-and-push-ddns (push) Successful in 25s
2025-04-20 11:12:50 -04:00
7099e72d6f fix distoolbox gitea watch dir
Some checks failed
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Has been cancelled
2025-04-19 21:35:38 -04:00
d44773389e add AUR vscode to arch toolbox 2025-04-19 20:58:18 -04:00
03e959c215 fix badge 2025-04-19 19:31:45 -04:00
b45bcd802e add cron config to gitea setup 2025-04-19 19:29:37 -04:00
38b81fda9a fix COPY for ddns service not working in Docker
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 42s
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 28m2s
2025-04-19 19:07:53 -04:00
960e91f911 gitea workers only watch their build file
Some checks failed
Podman DDNS Image / build-and-push-ddns (push) Failing after 8s
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 11s
2025-04-19 18:59:25 -04:00
4723ffb13d add ddns container build pipeline
Some checks failed
Podman DDNS Image / build-and-push-ddns (push) Failing after 25s
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 11s
2025-04-19 18:57:34 -04:00
ef9104c796 moving everything to active or retired vs incubating and graduated
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 14s
2025-04-19 18:52:33 -04:00
6e393d90ee moving closer to podman systemd services for everything 2025-04-19 12:52:56 -04:00
9acff25d43 update fedora server virtualization instructions
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 12s
2025-04-11 11:28:59 -04:00
3752f9da61 use cache when building arch distoolbox
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 12s
2025-04-08 14:57:55 -04:00
9417e711a9 the great migration from truenas to fedora and all its collatoral
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 24m47s
2025-04-08 12:40:42 -04:00
9a3382862d clean up nextcloud-aio 2025-03-25 12:27:32 -04:00
237a906b68 add zfs rename
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 26m30s
2025-03-24 15:39:01 -04:00
85de8a54d9 init grapheneos 2025-03-24 15:38:55 -04:00
e30db947b0 rootless nextcloud aio install working 2025-03-24 15:38:48 -04:00
3865e64b19 remove wolf, use vm instead 2025-03-24 15:37:48 -04:00
7a2589d01f list of new apps for fedora
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 44m51s
2025-03-20 00:43:20 -04:00
e57bb30ccb add code-oss compatibility notes and roku tv remote control template
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 45m1s
2025-03-16 17:41:01 -04:00
2fbdde303a add volumes to graphite podman
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 45m21s
2025-03-12 16:41:56 -04:00
7479bcd493 add reptyr and netcat to arch distoolbox 2025-03-12 16:41:40 -04:00
34fad5846f add tpm2 luks decryption instructions for fedora kinoite 2025-03-12 16:41:19 -04:00
ecf66a5fb2 add grafana and graphite to podman incubating
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 44m47s
2025-03-09 19:27:22 -04:00
74d1f7364a add ups monitoring and data size monitoring to truenas docs 2025-03-09 19:27:02 -04:00
b9386f32b6 use targets for arch toolbox build to keep things in one containerfile
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 43m57s
2025-03-09 15:08:02 -04:00
fb5ac88686 add debugpy snippet to vscode
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 42m11s
2025-03-07 11:40:26 -05:00
2a421392b1 remove discord bot stub
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 36m5s
2025-03-06 17:39:33 -05:00
b3fb0f1dd8 add tmux to graduated software 2025-03-06 17:39:23 -05:00
90db511077 rename gitea readme in accordance with standard 2025-03-06 17:39:13 -05:00
c70d992221 update Truenas zfs docs 2025-03-06 17:38:56 -05:00
559febeaea clarify docker compose fedora kinoite section title 2025-03-06 17:38:34 -05:00
10599fae23 switch to docker-based build script with the assumption the user will use podman as backend if needed 2025-03-06 17:38:15 -05:00
5844fa224f add vscode tmux instructions 2025-03-06 17:37:37 -05:00
ae0e17c66f initialize software incubating, including magick and ffmpeg 2025-03-04 09:33:14 -05:00
3c7c1ce60a clarify localai deploy instructions 2025-03-04 09:32:57 -05:00
d53d95df1a add snapshot instructions to truenas 2025-03-04 09:31:23 -05:00
d7bb612677 switch to steam flatpak for gaming server 2025-03-04 09:31:15 -05:00
495d2bb159 add make, gcc, base-devel, and fonts to arch distoolbox 2025-03-04 09:30:57 -05:00
3c1e5540af docker-compose with fedora kinoite using podman and buildx 2025-03-04 09:30:40 -05:00
00b6ea4058 initial gaming server with manjaro 2025-03-03 14:50:59 -05:00
c1c82f8f04 fix zsh history in distoolbox
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 39m55s
2025-02-25 07:48:17 -05:00
f27e9548c8 Fix markdown lint issues
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 40m16s
2025-02-22 13:51:02 -05:00
7472dce736 Change arch gaming build to use flatpak sunshine for package dep purposes
All checks were successful
Reese's Arch Toolbox / build-and-push-arch-toolbox (push) Successful in 39m33s
2025-02-22 13:46:42 -05:00
3a8dc44bbd update qmk notes with basic setup 2025-02-22 13:46:21 -05:00
f9d50950ab add make and gcc to arch distoolbox 2025-02-22 13:46:11 -05:00
369 changed files with 19472 additions and 2288 deletions

View File

@@ -0,0 +1,30 @@
name: Podman DDNS Image
run-name: Build and Push the Custom Caddy Image with Route53 DNS Certbot
on:
push:
paths:
- active/podman_caddy/**
- .gitea/workflows/caddy.yaml
schedule:
- cron: '@daily'
jobs:
build-and-push-ddns:
runs-on: ubuntu-latest
if: gitea.ref == 'refs/heads/main'
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: Login to Gitea Registry
uses: docker/login-action@v2
with:
registry: gitea.reeseapps.com
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Build and push Docker image
uses: https://github.com/docker/build-push-action@v5
with:
context: ${{ gitea.workspace }}/active/podman_caddy
file: ${{ gitea.workspace }}/active/podman_caddy/Containerfile
push: true
tags: "gitea.reeseapps.com/services/caddy:latest,gitea.reeseapps.com/services/caddy:${{gitea.sha}}"
no-cache: true

View File

@@ -0,0 +1,30 @@
name: Podman DDNS Image
run-name: Build and Push the Podman DDNS Image
on:
push:
paths:
- active/podman_ddns/**
- .gitea/workflows/ddns.yaml
schedule:
- cron: '@daily'
jobs:
build-and-push-ddns:
runs-on: ubuntu-latest
if: gitea.ref == 'refs/heads/main'
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: Login to Gitea Registry
uses: docker/login-action@v2
with:
registry: gitea.reeseapps.com
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Build and push Docker image
uses: https://github.com/docker/build-push-action@v5
with:
context: ${{ gitea.workspace }}/active/podman_ddns
file: ${{ gitea.workspace }}/active/podman_ddns/Containerfile
push: true
tags: "gitea.reeseapps.com/services/ddns:latest,gitea.reeseapps.com/services/ddns:${{gitea.sha}}"
no-cache: true

10
.gitignore vendored
View File

@@ -2,4 +2,12 @@ secrets/
venv/
tmp/
Unsorted/
volumes/
volumes/
__pycache__/
.pytest_cache/
.venv/
.mypy_cache
TODO.md
eicar.com
*.pp
*.mod

17
.vscode/code_oss_extensions.txt vendored Normal file
View File

@@ -0,0 +1,17 @@
charliermarsh.ruff
eamodio.gitlens
franneck94.vscode-python-config
franneck94.vscode-python-dev-extension-pack
ms-pyright.pyright
ms-python.debugpy
ms-python.mypy-type-checker
ms-python.python
ms-python.vscode-python-envs
njpwerner.autodocstring
njqdev.vscode-python-typehint
redhat.vscode-yaml
stkb.rewrap
streetsidesoftware.code-spell-checker
tamasfe.even-better-toml
vue.volar
yzhang.markdown-all-in-one

86
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,86 @@
{
"[css]": {
"editor.suggest.insertMode": "replace",
"editor.tabSize": 2
},
"[django-html]": {
"editor.insertSpaces": true,
"editor.quickSuggestions": {
"comments": true,
"other": true,
"strings": true
},
"editor.suggest.insertMode": "replace",
"editor.tabSize": 2
},
"[dockercompose]": {
"breadcrumbs.showConstants": true,
"editor.quickSuggestions": {
"comments": false,
"other": true,
"strings": true
},
"editor.tabSize": 2
},
"[helm]": {
"editor.insertSpaces": true,
"editor.tabSize": 2,
"rewrap.autoWrap.enabled": true,
"rewrap.wholeComment": true,
"rewrap.wrappingColumn": 73
},
"[html]": {
"editor.insertSpaces": true,
"editor.suggest.insertMode": "replace",
"editor.tabSize": 2
},
"[javascript]": {
"editor.maxTokenizationLineLength": 2500,
"editor.tabSize": 2
},
"[markdown]": {
"editor.defaultFormatter": "yzhang.markdown-all-in-one",
"editor.quickSuggestions": {
"comments": "off",
"other": "off",
"strings": "off"
},
"editor.tabSize": 4,
"editor.wordWrap": "off"
},
"[python]": {
"editor.codeActionsOnSave": {
"source.organizeImports": "always"
},
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.formatOnSave": true,
"editor.formatOnType": true
},
"[shellscript]": {
"editor.tabSize": 2,
"files.eol": "\n"
},
"[terraform]": {
"editor.insertSpaces": true,
"editor.tabSize": 2
},
"[typescript]": {
"editor.maxTokenizationLineLength": 2500,
"editor.tabSize": 2
},
"[vue]": {
"editor.insertSpaces": true,
"editor.tabSize": 2,
"gitlens.codeLens.scopes": [
"document"
]
},
"[yaml]": {
"editor.tabSize": 2
},
"cSpell.userWords": [
"Kubernetes",
"clamd",
"rtype"
],
}

2
.vscode/tasks.json vendored
View File

@@ -6,7 +6,7 @@
{
"label": "Build arch-toolbox",
"type": "shell",
"command": "./infrastructure/graduated/distoolbox/arch-build.sh",
"command": "./active/software_distoolbox/arch-build.sh",
"problemMatcher": [],
"group": {
"kind": "build",

58
.vscode/vscode.md vendored
View File

@@ -1,12 +1,32 @@
# VSCODE Configuration
- [VSCODE Configuration](#vscode-configuration)
- [Debugpy Snippet](#debugpy-snippet)
- [Fix Paste (if ctrl+v not working)](#fix-paste-if-ctrlv-not-working)
- [Shell](#shell)
- [Fonts](#fonts)
- [Navigation](#navigation)
- [Extensions](#extensions)
- [Continue](#continue)
- [Continue](#continue)
- [Pylance Type Checking](#pylance-type-checking)
## Debugpy Snippet
Use this to add debugging to any project
```python
# Listens on 5678
# Only runs if ACTIVATE_DEBUGPY=true is set
if os.getenv("ACTIVATE_DEBUGPY", "").lower() == "true":
try:
import debugpy
debugpy.listen(("0.0.0.0", 5678))
print("Waiting for client on 5678...")
debugpy.wait_for_client()
print("Client connected")
except Exception as e:
print("DEBUG ERROR: " + str(e))
```
## Fix Paste (if ctrl+v not working)
@@ -21,11 +41,23 @@ Add to user keyboard settings (json)
## Shell
Edit settings.json
I would recommend using tmux as your default shell. VSCode automatically creates new
sessions when adding or splitting windows. The only small problem is closing out of
vscode and reopening it won't reattach the previous sessions. You'll need to run
`tmux switch-client -t #` to get back to each session you lost.
```json
"terminal.integrated.profiles.osx": {
//...existing profiles...
"tmux-shell": {
"path": "tmux",
}
}
```
```bash
{
"terminal.integrated.defaultProfile.linux": "zsh",
"terminal.integrated.defaultProfile.linux": "tmux",
}
```
@@ -86,18 +118,10 @@ To install that list of extensions run:
cat vscode_extensions.txt | xargs -L 1 code --install-extension
```
## Continue
### Continue
```json
{
"models": [
{
"title": "qwen2.5-coder:32b",
"provider": "ollama",
"apiBase": "https://ollama.example.com",
"apiKey": "...",
"model": "qwen2.5-coder:32b"
}
],
...
```
Continue -> Settings -> Help -> Quickstart
### Pylance Type Checking
Settings -> `python.analysis.typeChecking`

308
README.md
View File

@@ -1,81 +1,272 @@
# Homelab
A project to store homelab stuff.
Welcome to my homelab!
Just here for the Arch distoolbox?
This repo is an in-flux collection of my personal notes, docs, and tutorials of
things I find interesting and self-host.
[Arch Distoolbox](infrastructure/graduated/distoolbox/distoolbox.md)
Take a look around!
![Arch Toolbox Status](https://gitea.reeseapps.com/services/homelab/actions/workflows/build.yaml/badge.svg?branch=main)
- "Active" projects (/active) are in use today and generally fall into these
categories:
- `aws_` is for aws notes
- `device_` is for hardware
- `kubernetes_` is for helm charts or other kubernetes hosted software
- `os_` is for operating system setup guides and notes
- `podman_` is for containerized projects
- `software_` is for cli tools, projects without a specific way to host them,
or other misfits
All active projects will have a markdown file named after the project. This is
for quick access via shortcuts like `ctrl + p` in vscode. For example, I want
to check my notes for `virsh` so I would type `ctrl + p` "virsh" to open
"virsh.md".
"Retired" projects (/retired) is a graveyard of things I didn't want to delete.
"Template" projects (/templates) are quick templates for creating new active
projects with sane defaults.
I keep my GPG and SSH keys in `keys` if you want to add those to your keyring
or give me access to your servers.
## Table of Contents
- [Homelab](#homelab)
- [Table of Contents](#table-of-contents)
- [Fun Facts](#fun-facts)
- [Keyboard Shortcuts](#keyboard-shortcuts)
- [inputrc](#inputrc)
- ["find ." shortcuts](#find--shortcuts)
- [tmux](#tmux)
- [bash](#bash)
- [SSH Setup](#ssh-setup)
- [Git GPG Commit Signing](#git-gpg-commit-signing)
- [Important Dates and Times](#important-dates-and-times)
- [Project Lifecycle](#project-lifecycle)
- [Supported Projects](#supported-projects)
- [Graduation Requirements](#graduation-requirements)
- [Project Types](#project-types)
- [Active Project Requirements](#active-project-requirements)
- [Retirement Requirements](#retirement-requirements)
- [Project Structure](#project-structure)
- [Creating a Project](#creating-a-project)
- [Order of Operations](#order-of-operations)
## Fun Facts
### Keyboard Shortcuts
On linux, <kbd>ctrl</kbd>+<kbd>shift</kbd>+<kbd>u</kbd>, then, while holding
<kbd>ctrl</kbd>+<kbd>shift</kbd>, typing <kbd>b</kbd>+<kbd>0</kbd> will type a ° (degree) symbol. Also you
can enter any unicode symbol this way.
<kbd>ctrl</kbd>+<kbd>shift</kbd>, typing <kbd>b</kbd>+<kbd>0</kbd> will type a
° (degree) symbol. Also you can enter any unicode symbol this way.
In vim: `esc + o` will take you to the end of a file and insert a new line.
### inputrc
Add this to your `~/.inputrc` to allow ctrl + backspace to delete whole words.
```bash
"\C-h": backward-kill-word
```
### "find ." shortcuts
```bash
# Change file mode for a bunch of directories
find . -type d -exec chmod 755 {} \;
```
### tmux
- Vertical: ctrl + b + "
- Horizontal: ctrl + b + %
- Event Horizontal Distribution: ctrl + b + alt + 1
- Even Vertical Distribution: ctrl + b + alt + 2
- Swap pane order: ctrl + b + : -> swap-pane -t 0
### bash
<https://tecadmin.net/bash-special-variables/>
Here are some handy references for default bash variables
```text
$0 The name of the script being executed.
$1-$9 The first nine command-line arguments.
$# The number of command-line arguments.
$* All command-line arguments as a single string.
$@ All command-line arguments as an array.
$? The exit status of the last executed command.
$$ The process ID of the current shell.
$! The process ID of the last background command.
$- Shows the current shell options or flags.
```
And here are the meanings of the shell options
```text
h Remember the location of commands as they are looked up
i Interactive shell
m Job control is enabled
B Brace expansion is enabled
H History substitution is enabled
```
So to check if you are in an interactive shell:
```bash
[ $- == *i* ]] && Some command here
```
## SSH Setup
Generate a key (password protect it!)
```bash
# Pick one of the below key types
# ed25519
ssh-keygen -C ssh@ducoterra.net -t ed25519
# rsa 4096
ssh-keygen -C ssh@ducoterra.net -t rsa -b 4096
# Inspect a key
ssh-keygen -l -f ~/.ssh/id_rsa
# Change the password
ssh-keygen -p -f ~/.ssh/id_rsa
```
In your ~/.ssh/config, add the following line to set the default key
```conf
IdentityFile ~/.foo/identity
```
Then add a host to your local computer
```bash
Host <hostname>
Hostname <host.something.com or IP address>
User <remote user>
Port <remote port>
```
And copy the key to a remote computer
```bash
# Copy the generated key to the server using password auth. Assumes password auth enabled.
ssh-copy-id -f -i ~/.ssh/id_ed25519 ${REMOTE_USER}@${REMOTE_HOST}
# Log into the server with your key
ssh -i ${KEY_NAME} ${REMOTE_HOST}
# Copy authorized_keys to root
sudo mkdir -p /root/.ssh
sudo cp ~/.ssh/authorized_keys /root/.ssh/authorized_keys
exit
# login and disable password auth
ssh ${REMOTE_HOST}
mkdir -p /etc/ssh/sshd_config.d
echo "PasswordAuthentication no" > /etc/ssh/sshd_config.d/01-prohibit-password.conf
systemctl restart sshd
# OPTIONAL: Disable sudo password
echo '%wheel ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/01-nopasswd-wheel
exit
# Test if you can SSH with a password
ssh -o PubkeyAuthentication=no ducoterra@${SSH_HOST}.reeselink.com
# Test that you can log into the server with ssh config
ssh $SSH_HOST
```
## Git GPG Commit Signing
1. Use `gpg --list-key 'git@ducoterra.net'` to find your key
2. Use `git config --global user.signingkey 0A46826A...` to set the signing key
3. Use `gpg --export -a 'git@ducoterra.net'` to export the key to copy into Gitea/Github/Gitlab
Now you can sign commits with `git commit -S`.
Alternatively, you can sign every commit by default with `git config --global commit.gpgsign true`.
You can verify a commit with `git verify-commit e1e551c`. If the commit is
signed you'll see an output. If not, nothing will show.
## Important Dates and Times
| Time | Day | Description |
| ----- | -------- | ---------------------------------- |
| 00:00 | All | Automated builds |
| 00:00 | All | NAS Snapshots |
| 02:00 | All | Backups |
| 04:00 | All | Bare Metal Server Security Updates |
| 05:00 | All | VM Server Security Updates |
| 05:00 | All | Unifi Protect Firmware Updates |
| 06:00 | All | Unifi Network Firmware Updates |
| 06:00 | Saturday | Truenas Disk Scrub |
## Project Lifecycle
Projects will fall into one of the three following categories:
Projects will either be `active` or `retired`.
1. Incubating
2. Graduated
3. Retired
Active projects are being actively developed. They are in-use, stable, and
production ready. Active projects should meet and track the [active project
requirements](#active-project-requirements)
Incubating projects are experimental or prototypal. They're being actively developed and aren't
ready for production deployment. These projects may appear and disappear without warning and are not
stable. There is no minimum requirement for a project to be in incubation.
Retired projects are no longer in use or recommended. They are kept for
reference. Retired projects must meet the [retirement
requirements](#retirement-requirements)
Graduated projects are in-use, stable, and production ready. They met the [graduation
requirements](#graduation-requirements) and are actively maintained.
You'll notice that most of the active projects have scripts or examples that
use the `active` path as part of their install process. When moved outside the
`active` directory their scripts and examples break. This is intentional. If
you want a retired project to work again, bring it back to the active
directory.
Retired projects are no longer in use or recommended. They are kept for reference. Retired projects
must meet the [retirement requirements](#retirement-requirements)
## Project Types
## Supported Projects
All projects will be prefixed with one of the following categories:
All projects will fall into one of the following categories:
- `device_`
- `os_`
- `software_`
- `podman_`
- `docker_`
- `kubernetes_`
- hardware
- infrastructure
- cloud
- systemd
- podman
- docker
- kubernetes
Note, some projects will be named with just the prefix. These are projects for
configuring the underlying technology. The `podman` project, for example, will
tell you how to configure and install podman so it works correctly.
Hardware will contain projects that relate to specific machines or equipment. 3D printers, Raspberry
Pis, and other IOT devices qualify as specialized hardware that needs documentation and
configuration. This is not limited to computer equipment. The furnace is an important part of the
home lab. the Air Conditioner is integral to the homelab's function. These projects will also be documented.
`device_` will prefix projects that relate to specific machines or equipment.
3D printers, Raspberry Pis, and other IOT devices qualify as specialized
hardware that needs documentation and configuration. This is not limited to
computer equipment. The furnace is an important part of the homelab. the Air
Conditioner is integral to the homelab's function. These projects will also be
documented.
Infrastructure will contain projects that set up the environments for the remaining listed project
types. For example, infrastructure will contain "how to set up a linux box with docker" or "how to
set up a k3s cluster for kubernetes".
`os_` will contain projects that set up operating systems. These include best
practices, backups, updates, default software, etc.
Cloud projects are for specific cloud providers.
`cloud_` projects are for specific cloud providers. This will contain
documentation and errata for things like AWS IAM, Route53, etc. Note these will
be prefixed with the cloud's name, not the word "cloud". So AWS services will
be prefixed with `aws_` and azure would be `azure_`. This should make them more
searchable.
Systemd projects are designed to be installed with ansible and run via systemd on a linux VM or
other linux hardware.
`software_` projects record configuration for common software agnostic to
operating system or linux flavor.
Podman projects are either designed to be run as quadlets or as podman containers outright.
`podman_` projects are either designed to be run as quadlets or as podman
containers outright.
Docker projects are either docker-compose or some form of docker run command.
`kubernetes_` projects are helm, kustomize, kubectl, or some other kubernetes
compliant deployment.
Kubernetes projects are helm, kustomize, kubectl, or some other kubernetes compliant deployment.
## Graduation Requirements
## Active Project Requirements
- [ ] Installation is documented
- [ ] Installation configuration examples are provided
@@ -91,11 +282,30 @@ Kubernetes projects are helm, kustomize, kubectl, or some other kubernetes compl
- [ ] If applicable, a replacement has been identified and documented
- [ ] If applicable, backup data locations are documented
## Project Structure
All projects will have, at minimum.
1. A README named `project-name.md`
2. A directory called `secrets` which will be gitignored.
## Creating a Project
Assuming your project name is `my-project` and it runs on `podman`
1. Create a new directory called `podman_my-project` under the `active`
directory
2. Copy the readme template: `cp project_readme_template.md
active/podman_my-project/my-project.md`
3. Populate `my-project.md` as you work through the install process
4. Create a directory called `secrets` in `podman_my-project`. This will be
automatically gitignored. Put all secrets here.
5. Push the changes when you have a working product
## Order of Operations
1. Install cloud projects. These usually have no dependencies and typically provide critical services
to other projects (DNS, email notifications, etc.)
2. Install infrastructure projects. Usually these only have dependencies on cloud services.
3. Install systemd services. These are usually low-level programs that require a dedicated machine
and perform semi-critical functions (ipv4 proxy, ddns, etc.).
4. Install kubernetes, docker, podman, and other services.
1. Configure cloud providers. These usually have no dependencies and typically
provide critical services to other projects (DNS, email notifications, etc.)
2. Install infrastructure projects. Usually these only have dependencies on
cloud services.
3. Install systemd, kubernetes, docker, podman, and other services.

12
active/aws_cli/aws_cli.md Normal file
View File

@@ -0,0 +1,12 @@
# AWS CLI
## Install
```bash
# Run as root
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \
unzip awscliv2.zip && \
./aws/install && \
rm -f ./awscliv2.zip && \
rm -rf ./aws
```

View File

@@ -1,24 +1,33 @@
# AWS Credentials
## Credential Generation
Note: this requires the AWS CLI. See [AWS CLI](/active/aws_cli/aws_cli.md)
- [AWS Credentials](#aws-credentials)
- [Route53 Credential Generation](#route53-credential-generation)
- [AWS Certbot Route53 Policies](#aws-certbot-route53-policies)
- [Email Credentials](#email-credentials)
## Route53 Credential Generation
```bash
export AWS_USERNAME=
aws iam create-user --user-name $AWS_USERNAME
aws iam create-access-key --user-name $AWS_USERNAME
# Allow updating reeseapps
aws iam attach-user-policy --user-name $AWS_USERNAME --policy-arn $(cat cloud/graduated/aws_iam/secrets/update-reeseapps-iam-policy-arn)
aws iam attach-user-policy --user-name $AWS_USERNAME --policy-arn $(cat active/aws_iam/secrets/update-reeseapps-iam-policy-arn)
# Allow updating reeselink
aws iam attach-user-policy --user-name $AWS_USERNAME --policy-arn $(cat cloud/graduated/aws_iam/secrets/update-reeselink-iam-policy-arn)
aws iam attach-user-policy --user-name $AWS_USERNAME --policy-arn $(cat active/aws_iam/secrets/update-reeselink-iam-policy-arn)
# Create credentials (run aws configure on the machine that needs these to input them manually)
aws iam create-access-key --user-name $AWS_USERNAME
```
## AWS Certbot Route53 Policies
Example Policy:
cloud/graduated/aws_iam/secrets/policies/route53_reeselink.json
active/aws_iam/secrets/route53_reeselink.json
```json
{
@@ -50,8 +59,21 @@ cloud/graduated/aws_iam/secrets/policies/route53_reeselink.json
```bash
# Allow updating route53 records for reeselink.com
aws iam create-policy --policy-name update-reeselink --policy-document file://cloud/graduated/aws_iam/secrets/route53_reeselink_policy.json
aws iam create-policy --policy-name update-reeselink --policy-document file://active/aws_iam/secrets/route53_reeselink_policy.json
# Allow updating route53 records for reeseapps.com
aws iam create-policy --policy-name update-reeseapps --policy-document file://cloud/graduated/aws_iam/secrets/route53_reeseapps_policy.json
aws iam create-policy --policy-name update-reeseapps --policy-document file://active/aws_iam/secrets/route53_reeseapps_policy.json
```
## Email Credentials
<https://docs.aws.amazon.com/ses/latest/dg/smtp-credentials.html>
You can technically do this through the CLI, see above link.
1. Log into the AWS console
2. Navigate to SES
3. Click "SMTP Settings"
4. Click "Create SMTP Credentials"
5. Name it "ses-smtp-user.something"
6. Copy the username and password

View File

@@ -17,14 +17,14 @@ convenience.
## Reeselink Addresses
See `example-record-file.json` for example contents of `file://cloud/graduated/aws_route53/secrets/aws/reeselink.json`.
See `example-record-file.json` for example contents of `file://active/aws_route53/secrets/aws/reeselink.json`.
```bash
aws route53 change-resource-record-sets --hosted-zone-id $(cat cloud/graduated/aws_route53/secrets/reeselink-zoneid) --change-batch file://cloud/graduated/aws_route53/secrets/reeselink.json
aws route53 change-resource-record-sets --hosted-zone-id $(cat active/aws_route53/secrets/reeselink-zoneid) --change-batch file://active/aws_route53/secrets/reeselink.json
```
## Reeseapps Addresses
```bash
aws route53 change-resource-record-sets --hosted-zone-id $(cat cloud/graduated/aws_route53/secrets/reeseapps-zoneid) --change-batch file://cloud/graduated/aws_route53/secrets/reeseapps.json
aws route53 change-resource-record-sets --hosted-zone-id $(cat active/aws_route53/secrets/reeseapps-zoneid) --change-batch file://active/aws_route53/secrets/reeseapps.json
```

View File

@@ -0,0 +1,3 @@
# AWS SES
AWS Simple Email Service

View File

@@ -0,0 +1,14 @@
# 3D Server Hardware
## Motherboard
B650 GAMING X AX rev 1.5
<https://www.gigabyte.com/Motherboard/B650-GAMING-X-AX-rev-15/support#dl>
- Enable PBO
- Enable XMP
- Enable SVM
- Enable PCIe x4x4x4x4 bifurcation
- Enable Power always back on
- Fans to full speed

View File

@@ -8,6 +8,16 @@ If you want to set up WiFi without logging in follow this:
<https://wiki.bambulab.com/en/p1/manual/p1-sd-card-network-configuration-guide>
1. Create a new file on the printer's SD card named `user_wifi.cfg`
2. Add the following contents to `user_wifi.cfg`:
```text
ssid:FruitTest08
password:wikitest12
```
3. Put the SD card back in the printer. It should connect automatically.
### Connecting via LAN mode
- Make sure you open 1990 and 2021 (tcp + udp) in your firewall application.

View File

@@ -0,0 +1,11 @@
# Epson ET 2800
## Printer Setup
1. Download and install the drivers at <https://support.epson.net/linux/Printer/LSB_distribution_pages/en/escpr.php>
2. Settings -> Printers -> Add
3. Select LPD/LPR Host or Printer
4. Enter the address: `lpd://<ip_address>`
5. Select Epson, then select Epson ET-2800 Series
6. Save
7. Print

5
active/device_esphome/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
# Gitignore settings for ESPHome
# This is an example and may include too much for your use-case.
# You can modify this file to suit your needs.
/.esphome/
/secrets.yaml

View File

@@ -0,0 +1,370 @@
substitutions:
name: m5stack-atom-echo
friendly_name: M5Stack Atom Echo
esphome:
name: ${name}
name_add_mac_suffix: true
friendly_name: ${friendly_name}
min_version: 2025.5.0
esp32:
board: m5stack-atom
cpu_frequency: 240MHz
framework:
type: esp-idf
logger:
api:
ota:
- platform: esphome
id: ota_esphome
wifi:
ap:
captive_portal:
button:
- platform: factory_reset
id: factory_reset_btn
name: Factory reset
i2s_audio:
- id: i2s_audio_bus
i2s_lrclk_pin: GPIO33
i2s_bclk_pin: GPIO19
microphone:
- platform: i2s_audio
id: echo_microphone
i2s_din_pin: GPIO23
adc_type: external
pdm: true
sample_rate: 16000
correct_dc_offset: true
speaker:
- platform: i2s_audio
id: echo_speaker
i2s_dout_pin: GPIO22
dac_type: external
bits_per_sample: 16bit
sample_rate: 16000
channel: stereo # The Echo has poor playback audio quality when using mon audio
buffer_duration: 60ms
media_player:
- platform: speaker
name: None
id: echo_media_player
announcement_pipeline:
speaker: echo_speaker
format: WAV
codec_support_enabled: false
buffer_size: 6000
volume_min: 0.4
files:
- id: timer_finished_wave_file
file: https://github.com/esphome/wake-word-voice-assistants/raw/main/sounds/timer_finished.wav
on_announcement:
- if:
condition:
- microphone.is_capturing:
then:
- script.execute: stop_wake_word
- light.turn_on:
id: led
blue: 100%
red: 0%
green: 0%
brightness: 100%
effect: none
on_idle:
- script.execute: start_wake_word
- script.execute: reset_led
voice_assistant:
id: va
micro_wake_word:
microphone:
microphone: echo_microphone
channels: 0
gain_factor: 4
media_player: echo_media_player
noise_suppression_level: 2
auto_gain: 31dBFS
on_listening:
- light.turn_on:
id: led
blue: 100%
red: 0%
green: 0%
effect: "Slow Pulse"
on_stt_vad_end:
- light.turn_on:
id: led
blue: 100%
red: 0%
green: 0%
effect: "Fast Pulse"
on_tts_start:
- light.turn_on:
id: led
blue: 100%
red: 0%
green: 0%
brightness: 100%
effect: none
on_end:
# Handle the "nevermind" case where there is no announcement
- wait_until:
condition:
- media_player.is_announcing:
timeout: 0.5s
# Restart only mWW if enabled; streaming wake words automatically restart
- if:
condition:
- lambda: return id(wake_word_engine_location).state == "On device";
then:
- wait_until:
- and:
- not:
voice_assistant.is_running:
- not:
speaker.is_playing:
- lambda: id(va).set_use_wake_word(false);
- micro_wake_word.start:
- script.execute: reset_led
on_error:
- light.turn_on:
id: led
red: 100%
green: 0%
blue: 0%
brightness: 100%
effect: none
- delay: 2s
- script.execute: reset_led
on_client_connected:
- delay: 2s # Give the api server time to settle
- script.execute: start_wake_word
on_client_disconnected:
- script.execute: stop_wake_word
on_timer_finished:
- script.execute: stop_wake_word
- wait_until:
not:
microphone.is_capturing:
- switch.turn_on: timer_ringing
- light.turn_on:
id: led
red: 0%
green: 100%
blue: 0%
brightness: 100%
effect: "Fast Pulse"
- wait_until:
- switch.is_off: timer_ringing
- light.turn_off: led
- switch.turn_off: timer_ringing
binary_sensor:
# button does the following:
# short click - stop a timer
# if no timer then restart either microwakeword or voice assistant continuous
- platform: gpio
pin:
number: GPIO39
inverted: true
name: Button
disabled_by_default: true
entity_category: diagnostic
id: echo_button
on_multi_click:
- timing:
- ON for at least 50ms
- OFF for at least 50ms
then:
- if:
condition:
switch.is_on: timer_ringing
then:
- switch.turn_off: timer_ringing
else:
- script.execute: start_wake_word
- timing:
- ON for at least 10s
then:
- button.press: factory_reset_btn
light:
- platform: esp32_rmt_led_strip
id: led
name: None
disabled_by_default: true
entity_category: config
pin: GPIO27
default_transition_length: 0s
chipset: SK6812
num_leds: 1
rgb_order: grb
effects:
- pulse:
name: "Slow Pulse"
transition_length: 250ms
update_interval: 250ms
min_brightness: 50%
max_brightness: 100%
- pulse:
name: "Fast Pulse"
transition_length: 100ms
update_interval: 100ms
min_brightness: 50%
max_brightness: 100%
script:
- id: reset_led
then:
- if:
condition:
- lambda: return id(wake_word_engine_location).state == "On device";
- switch.is_on: use_listen_light
then:
- light.turn_on:
id: led
red: 100%
green: 89%
blue: 71%
brightness: 60%
effect: none
else:
- if:
condition:
- lambda: return id(wake_word_engine_location).state != "On device";
- switch.is_on: use_listen_light
then:
- light.turn_on:
id: led
red: 0%
green: 100%
blue: 100%
brightness: 60%
effect: none
else:
- light.turn_off: led
- id: start_wake_word
then:
- if:
condition:
and:
- not:
- voice_assistant.is_running:
- lambda: return id(wake_word_engine_location).state == "On device";
then:
- lambda: id(va).set_use_wake_word(false);
- micro_wake_word.start:
- if:
condition:
and:
- not:
- voice_assistant.is_running:
- lambda: return id(wake_word_engine_location).state == "In Home Assistant";
then:
- lambda: id(va).set_use_wake_word(true);
- voice_assistant.start_continuous:
- id: stop_wake_word
then:
- if:
condition:
lambda: return id(wake_word_engine_location).state == "In Home Assistant";
then:
- lambda: id(va).set_use_wake_word(false);
- voice_assistant.stop:
- if:
condition:
lambda: return id(wake_word_engine_location).state == "On device";
then:
- micro_wake_word.stop:
switch:
- platform: template
name: Use listen light
id: use_listen_light
optimistic: true
restore_mode: RESTORE_DEFAULT_ON
entity_category: config
on_turn_on:
- script.execute: reset_led
on_turn_off:
- script.execute: reset_led
- platform: template
id: timer_ringing
optimistic: true
restore_mode: ALWAYS_OFF
on_turn_off:
# Turn off the repeat mode and disable the pause between playlist items
- lambda: |-
id(echo_media_player)
->make_call()
.set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_OFF)
.set_announcement(true)
.perform();
id(echo_media_player)->set_playlist_delay_ms(speaker::AudioPipelineType::ANNOUNCEMENT, 0);
# Stop playing the alarm
- media_player.stop:
announcement: true
on_turn_on:
# Turn on the repeat mode and pause for 1000 ms between playlist items/repeats
- lambda: |-
id(echo_media_player)
->make_call()
.set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_ONE)
.set_announcement(true)
.perform();
id(echo_media_player)->set_playlist_delay_ms(speaker::AudioPipelineType::ANNOUNCEMENT, 1000);
- media_player.speaker.play_on_device_media_file:
media_file: timer_finished_wave_file
announcement: true
- delay: 15min
- switch.turn_off: timer_ringing
select:
- platform: template
entity_category: config
name: Wake word engine location
id: wake_word_engine_location
optimistic: true
restore_value: true
options:
- In Home Assistant
- On device
initial_option: On device
on_value:
- if:
condition:
lambda: return x == "In Home Assistant";
then:
- micro_wake_word.stop:
- delay: 500ms
- lambda: id(va).set_use_wake_word(true);
- voice_assistant.start_continuous:
- if:
condition:
lambda: return x == "On device";
then:
- lambda: id(va).set_use_wake_word(false);
- voice_assistant.stop:
- delay: 500ms
- micro_wake_word.start:
micro_wake_word:
on_wake_word_detected:
- voice_assistant.start:
wake_word: !lambda return wake_word;
vad:
models:
- model: okay_nabu
- model: hey_mycroft
- model: hey_jarvis

View File

@@ -0,0 +1,249 @@
# ESP32
- [ESP32](#esp32)
- [Install](#install)
- [Devices](#devices)
- [Lilygo tdongle](#lilygo-tdongle)
- [Local Flashing](#local-flashing)
- [Adding a New Device](#adding-a-new-device)
- [Controlling Home Assistant](#controlling-home-assistant)
- [Configuration Sections](#configuration-sections)
- [esphome](#esphome)
- [esp32](#esp32-1)
- [logger](#logger)
- [api](#api)
- [wifi](#wifi)
- [ota](#ota)
- [captive portal](#captive-portal)
- [button](#button)
- [i2s audio](#i2s-audio)
- [microphone](#microphone)
- [speaker](#speaker)
- [media player](#media-player)
- [voice assistant](#voice-assistant)
- [micro wake word](#micro-wake-word)
- [light](#light)
- [binary sensor](#binary-sensor)
- [lambda](#lambda)
- [Display](#display)
## Install
```bash
# Check that you have python 3.11 installed
uv python list --only-installed
# Create the venv (python 3.11 is recommended in the docs)
uv venv --python 3.11
# Install esphome
uv pip install esphome wheel pip
source .venv/bin/activate
```
## Devices
### Lilygo tdongle
Display: 80 X 160
## Local Flashing
Make sure your permissions are set correctly
```bash
sudo usermod -a -G dialout ducoterra
```
Then "run" your config file
```bash
cd active/device_esp32
uv venv
uv pip install esphome
source .venv/bin/activate
esphome run m5stack-atom-echo.yaml
```
## Adding a New Device
1. Create a new yaml configuration file called "my-device-device-type.yaml"
## Controlling Home Assistant
<https://esphome.io/components/api/#api-actions>
## Configuration Sections
<https://esphome.io/components/>
### esphome
### esp32
<https://esphome.io/components/esp32/#configuration-variables>
### logger
<https://esphome.io/components/logger/>
### api
<https://esphome.io/components/api/>
### wifi
<https://esphome.io/components/wifi/>
### ota
<https://esphome.io/components/ota/>
<https://esphome.io/components/ota/esphome/>
### captive portal
<https://esphome.io/components/captive_portal/>
### button
<https://esphome.io/components/button/>
### i2s audio
<https://esphome.io/components/i2s_audio/>
### microphone
<https://esphome.io/components/microphone/>
<https://esphome.io/components/microphone/i2s_audio/>
### speaker
<https://esphome.io/components/speaker/i2s_audio/>
### media player
<https://esphome.io/components/media_player/speaker/>
Sometimes you'll need to convert media files to supported encoders.
```bash
ffmpeg -i input.flac output.wav
```
To play media on other devices from home assistant, put the
```yaml
action: media_player.play_media
target:
entity_id: media_player.kitchen_google_home
data:
media_content_type: "audio/wav"
media_content_id: "media-source://media_source/local/wake_word_triggered.wav"
```
### voice assistant
<https://esphome.io/components/voice_assistant/>
In Home Assistant's configuration.yaml, add the following to listen to
audio recordings of your voice request:
```bash
assist_pipeline:
debug_recording_dir: /share/assist_pipeline
```
### micro wake word
<https://esphome.io/components/micro_wake_word/>
### light
<https://esphome.io/components/light/#light-effects>
### binary sensor
<https://esphome.io/components/binary_sensor/>
### lambda
<https://esphome.io/automations/templates/#config-lambda>
> id(...) is a helper function that makes ESPHome fetch an object with the
> supplied ID (which you defined somewhere else, like top_end_stop ) and lets
> you call any of ESPHomes many APIs directly. For example, here were
> retrieving the current state of the end stop using .state and using it to
> construct our cover state.
### Display
Display pages
```yaml
display:
- platform: st7735
spi_id: spi_lcd
model: "INITR_MINI160X80"
reset_pin: GPIO1
cs_pin: GPIO4
dc_pin: GPIO2
rotation: 270
device_width: 82
device_height: 161
col_start: 0
row_start: 0
eight_bit_color: true
invert_colors: true
use_bgr: true
auto_clear_enabled: true
id: my_display
pages:
- id: page1
lambda: |-
it.print(0, 10, id(font_roboto), "Connecting to");
it.print(0, 30, id(font_roboto), "Home Assistant...");
- id: page2
lambda: |-
it.print(0, 10, id(font_roboto), "Configuring");
it.print(0, 30, id(font_roboto), "sensors...");
- id: page3
lambda: |-
it.print(0, 10, id(font_roboto), "Loading");
it.print(0, 30, id(font_roboto), "important");
it.print(0, 50, id(font_roboto), "update...");
- id: page4
lambda: |-
it.image(0, 0, id(my_image), COLOR_OFF, COLOR_ON);
```
Switch pages
```yaml
interval:
- interval: 5s
then:
- display.page.show_next: my_display
- component.update: my_display
```
Show an image
```yaml
image:
- file: "test_tdongle_image.png"
type: RGB
id: my_image
```
Specify a font
```yaml
font:
- file: "gfonts://Roboto"
id: font_roboto
size: 20
```

View File

@@ -0,0 +1,386 @@
esphome:
name: great-room-atom-echo
friendly_name: Great Room Atom Echo
esp32:
board: m5stack-atom
framework:
type: esp-idf
# Enable logging
logger:
level: debug
# Enable Home Assistant API
api:
encryption:
key: !secret great_room_atom_echo_key
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
domain: .reeselink.com
fast_connect: true
enable_btm: true
on_disconnect:
- light.turn_on:
id: led
blue: 0%
red: 100%
green: 0%
effect: "Slow Pulse"
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Great-Room-Atom-Echo"
password: !secret hotspot_password
ota:
- platform: esphome
password: !secret ota_password
captive_portal:
button:
- platform: factory_reset
id: factory_reset_btn
name: Factory reset
i2s_audio:
- id: i2s_audio_bus
i2s_lrclk_pin: GPIO33
i2s_bclk_pin: GPIO19
microphone:
- platform: i2s_audio
id: echo_microphone
i2s_din_pin: GPIO23
adc_type: external
pdm: true
sample_rate: 16000
correct_dc_offset: true
speaker:
- platform: i2s_audio
id: echo_speaker
i2s_dout_pin: GPIO22
dac_type: external
bits_per_sample: 16bit
sample_rate: 16000
channel: stereo # The Echo has poor playback audio quality when using mon audio
buffer_duration: 60ms
media_player:
- platform: speaker
name: None
id: echo_media_player
announcement_pipeline:
speaker: echo_speaker
format: WAV
codec_support_enabled: false
buffer_size: 6000
volume_min: 1
volume_max: 1
volume_initial: 1
files:
- id: timer_finished_wave_file
file: https://github.com/esphome/wake-word-voice-assistants/raw/main/sounds/timer_finished.wav
on_announcement:
- if:
condition:
- microphone.is_capturing:
then:
- script.execute: stop_wake_word
- light.turn_on:
id: led
blue: 100%
red: 0%
green: 0%
brightness: 100%
effect: none
on_idle:
- script.execute: start_wake_word
- script.execute: reset_led
voice_assistant:
id: va
micro_wake_word:
microphone:
microphone: echo_microphone
channels: 0
gain_factor: 64
media_player: echo_media_player
noise_suppression_level: 2
auto_gain: 31dBFS
on_listening:
- light.turn_on:
id: led
blue: 100%
red: 0%
green: 0%
effect: "Slow Pulse"
on_stt_vad_end:
- light.turn_on:
id: led
blue: 100%
red: 0%
green: 0%
effect: "Fast Pulse"
on_tts_start:
- light.turn_on:
id: led
blue: 100%
red: 0%
green: 0%
brightness: 100%
effect: none
on_end:
# Handle the "nevermind" case where there is no announcement
- wait_until:
condition:
- media_player.is_announcing:
timeout: 0.5s
# Restart only mWW if enabled; streaming wake words automatically restart
- if:
condition:
- lambda: return id(wake_word_engine_location).state == "On device";
then:
- wait_until:
- and:
- not:
voice_assistant.is_running:
- not:
speaker.is_playing:
- lambda: id(va).set_use_wake_word(false);
- micro_wake_word.start:
- script.execute: reset_led
on_error:
- light.turn_on:
id: led
red: 100%
green: 0%
blue: 0%
brightness: 100%
effect: none
- delay: 2s
- script.execute: reset_led
on_client_connected:
- delay: 2s # Give the api server time to settle
- script.execute: start_wake_word
on_client_disconnected:
- script.execute: stop_wake_word
on_timer_finished:
- script.execute: stop_wake_word
- wait_until:
not:
microphone.is_capturing:
- switch.turn_on: timer_ringing
- light.turn_on:
id: led
red: 0%
green: 100%
blue: 0%
brightness: 100%
effect: "Fast Pulse"
- wait_until:
- switch.is_off: timer_ringing
- light.turn_off: led
- switch.turn_off: timer_ringing
binary_sensor:
# button does the following:
# short click - stop a timer
# if no timer then restart either microwakeword or voice assistant continuous
- platform: gpio
pin:
number: GPIO39
inverted: true
name: Button
disabled_by_default: true
entity_category: diagnostic
id: echo_button
on_multi_click:
- timing:
- ON for at least 50ms
- OFF for at least 50ms
then:
- if:
condition:
switch.is_on: timer_ringing
then:
- switch.turn_off: timer_ringing
else:
- script.execute: start_wake_word
- timing:
- ON for at least 10s
then:
- button.press: factory_reset_btn
light:
- platform: esp32_rmt_led_strip
id: led
name: None
disabled_by_default: true
entity_category: config
pin: GPIO27
default_transition_length: 0s
chipset: SK6812
num_leds: 1
rgb_order: grb
effects:
- pulse:
name: "Slow Pulse"
transition_length: 250ms
update_interval: 250ms
min_brightness: 50%
max_brightness: 100%
- pulse:
name: "Fast Pulse"
transition_length: 100ms
update_interval: 100ms
min_brightness: 50%
max_brightness: 100%
script:
- id: reset_led
then:
- if:
condition:
- lambda: return id(wake_word_engine_location).state == "On device";
- switch.is_on: use_listen_light
then:
- light.turn_on:
id: led
red: 100%
green: 89%
blue: 71%
brightness: 60%
effect: none
else:
- if:
condition:
- lambda: return id(wake_word_engine_location).state != "On device";
- switch.is_on: use_listen_light
then:
- light.turn_on:
id: led
red: 0%
green: 100%
blue: 100%
brightness: 60%
effect: none
else:
- light.turn_off: led
- id: start_wake_word
then:
- if:
condition:
and:
- not:
- voice_assistant.is_running:
- lambda: return id(wake_word_engine_location).state == "On device";
then:
- lambda: id(va).set_use_wake_word(false);
- micro_wake_word.start:
- if:
condition:
and:
- not:
- voice_assistant.is_running:
- lambda: return id(wake_word_engine_location).state == "In Home Assistant";
then:
- lambda: id(va).set_use_wake_word(true);
- voice_assistant.start_continuous:
- id: stop_wake_word
then:
- if:
condition:
lambda: return id(wake_word_engine_location).state == "In Home Assistant";
then:
- lambda: id(va).set_use_wake_word(false);
- voice_assistant.stop:
- if:
condition:
lambda: return id(wake_word_engine_location).state == "On device";
then:
- micro_wake_word.stop:
switch:
- platform: template
name: Use listen light
id: use_listen_light
optimistic: true
restore_mode: RESTORE_DEFAULT_ON
entity_category: config
on_turn_on:
- script.execute: reset_led
on_turn_off:
- script.execute: reset_led
- platform: template
id: timer_ringing
optimistic: true
restore_mode: ALWAYS_OFF
on_turn_off:
# Turn off the repeat mode and disable the pause between playlist items
- lambda: |-
id(echo_media_player)
->make_call()
.set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_OFF)
.set_announcement(true)
.perform();
id(echo_media_player)->set_playlist_delay_ms(speaker::AudioPipelineType::ANNOUNCEMENT, 0);
# Stop playing the alarm
- media_player.stop:
announcement: true
on_turn_on:
# Turn on the repeat mode and pause for 1000 ms between playlist items/repeats
- lambda: |-
id(echo_media_player)
->make_call()
.set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_ONE)
.set_announcement(true)
.perform();
id(echo_media_player)->set_playlist_delay_ms(speaker::AudioPipelineType::ANNOUNCEMENT, 1000);
- media_player.speaker.play_on_device_media_file:
media_file: timer_finished_wave_file
announcement: true
- delay: 15min
- switch.turn_off: timer_ringing
select:
- platform: template
entity_category: config
name: Wake word engine location
id: wake_word_engine_location
optimistic: true
restore_value: true
options:
- In Home Assistant
- On device
initial_option: On device
on_value:
- if:
condition:
lambda: return x == "In Home Assistant";
then:
- micro_wake_word.stop:
- delay: 500ms
- lambda: id(va).set_use_wake_word(true);
- voice_assistant.start_continuous:
- if:
condition:
lambda: return x == "On device";
then:
- lambda: id(va).set_use_wake_word(false);
- voice_assistant.stop:
- delay: 500ms
- micro_wake_word.start:
micro_wake_word:
on_wake_word_detected:
- voice_assistant.start:
wake_word: !lambda return wake_word;
vad:
models:
- model: okay_nabu
- model: hey_mycroft
- model: hey_jarvis

View File

@@ -0,0 +1,118 @@
esphome:
name: tdongle
friendly_name: tdongle
esp32:
board: esp32-s3-devkitc-1
framework:
type: esp-idf
flash_size: 16MB
logger:
# Enable Home Assistant API
api:
encryption:
key: !secret lilygo_tdongle_key
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
domain: .reeselink.com
fast_connect: true
enable_btm: true
id: wifithing
# on_connect:
# - component.update: my_online_image
ota:
- platform: esphome
password: !secret ota_password
captive_portal:
binary_sensor:
- platform: gpio
pin: GPIO0
name: Button
spi:
- id: spi_led
clk_pin: GPIO39
mosi_pin: GPIO40
- id: spi_lcd
clk_pin: GPIO5
mosi_pin: GPIO3
output:
- platform: ledc
frequency: 2000
pin: GPIO38
inverted: True
id: backlight_output
light:
- platform: monochromatic
output: backlight_output
name: "LCD Backlight"
id: lcd_backlight
restore_mode: ALWAYS_ON
# RGB Led, APA102 on GPIO39/GPIO40
- platform: spi_led_strip
spi_id: spi_led
num_leds: 1
name: "FastLED SPI Light"
data_rate: 1MHz # Adjust as needed, APA102 supports up to 20MHz, 1MHz is a safe starting point
display:
- platform: st7735
spi_id: spi_lcd
model: "INITR_MINI160X80"
reset_pin: GPIO1
cs_pin: GPIO4
dc_pin: GPIO2
rotation: 270
device_width: 82
device_height: 161
col_start: 0
row_start: 0
eight_bit_color: true
invert_colors: true
use_bgr: true
auto_clear_enabled: true
id: my_display
pages:
- id: page1
lambda: |-
it.print(0, 10, id(font_roboto), "Connecting to");
it.print(0, 30, id(font_roboto), "Home Assistant...");
- id: page2
lambda: |-
it.print(0, 10, id(font_roboto), "Configuring");
it.print(0, 30, id(font_roboto), "sensors...");
- id: page3
lambda: |-
it.print(0, 10, id(font_roboto), "Loading");
it.print(0, 30, id(font_roboto), "important");
it.print(0, 50, id(font_roboto), "update...");
- id: page4
lambda: |-
it.image(0, 0, id(my_image), COLOR_OFF, COLOR_ON);
image:
- file: "test_tdongle_image.png"
type: RGB
id: my_image
http_request:
font:
- file: "gfonts://Roboto"
id: font_roboto
size: 20
interval:
- interval: 5s
then:
- display.page.show_next: my_display
- component.update: my_display

View File

@@ -0,0 +1,387 @@
esphome:
name: loft-atom-echo
friendly_name: Loft Atom Echo
esp32:
board: m5stack-atom
cpu_frequency: 240MHz
framework:
type: esp-idf
# Enable logging
logger:
level: debug
# Enable Home Assistant API
api:
encryption:
key: !secret loft_atom_echo_key
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
domain: .reeselink.com
fast_connect: true
enable_btm: true
on_disconnect:
- light.turn_on:
id: led
blue: 0%
red: 100%
green: 0%
effect: "Slow Pulse"
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Loft-Atom-Echo"
password: !secret hotspot_password
ota:
- platform: esphome
password: !secret ota_password
captive_portal:
button:
- platform: factory_reset
id: factory_reset_btn
name: Factory reset
i2s_audio:
- id: i2s_audio_bus
i2s_lrclk_pin: GPIO33
i2s_bclk_pin: GPIO19
microphone:
- platform: i2s_audio
id: echo_microphone
i2s_din_pin: GPIO23
adc_type: external
pdm: true
sample_rate: 16000
correct_dc_offset: true
speaker:
- platform: i2s_audio
id: echo_speaker
i2s_dout_pin: GPIO22
dac_type: external
bits_per_sample: 16bit
sample_rate: 16000
channel: stereo # The Echo has poor playback audio quality when using mon audio
buffer_duration: 60ms
media_player:
- platform: speaker
name: None
id: echo_media_player
announcement_pipeline:
speaker: echo_speaker
format: WAV
codec_support_enabled: false
buffer_size: 6000
volume_min: 1
volume_max: 1
volume_initial: 1
files:
- id: timer_finished_wave_file
file: https://github.com/esphome/wake-word-voice-assistants/raw/main/sounds/timer_finished.wav
on_announcement:
- if:
condition:
- microphone.is_capturing:
then:
- script.execute: stop_wake_word
- light.turn_on:
id: led
blue: 100%
red: 0%
green: 0%
brightness: 100%
effect: none
on_idle:
- script.execute: start_wake_word
- script.execute: reset_led
voice_assistant:
id: va
micro_wake_word:
microphone:
microphone: echo_microphone
channels: 0
gain_factor: 64
media_player: echo_media_player
noise_suppression_level: 2
auto_gain: 31dBFS
on_listening:
- light.turn_on:
id: led
blue: 100%
red: 0%
green: 0%
effect: "Slow Pulse"
on_stt_vad_end:
- light.turn_on:
id: led
blue: 100%
red: 0%
green: 0%
effect: "Fast Pulse"
on_tts_start:
- light.turn_on:
id: led
blue: 100%
red: 0%
green: 0%
brightness: 100%
effect: none
on_end:
# Handle the "nevermind" case where there is no announcement
- wait_until:
condition:
- media_player.is_announcing:
timeout: 0.5s
# Restart only mWW if enabled; streaming wake words automatically restart
- if:
condition:
- lambda: return id(wake_word_engine_location).state == "On device";
then:
- wait_until:
- and:
- not:
voice_assistant.is_running:
- not:
speaker.is_playing:
- lambda: id(va).set_use_wake_word(false);
- micro_wake_word.start:
- script.execute: reset_led
on_error:
- light.turn_on:
id: led
red: 100%
green: 0%
blue: 0%
brightness: 100%
effect: none
- delay: 2s
- script.execute: reset_led
on_client_connected:
- delay: 2s # Give the api server time to settle
- script.execute: start_wake_word
on_client_disconnected:
- script.execute: stop_wake_word
on_timer_finished:
- script.execute: stop_wake_word
- wait_until:
not:
microphone.is_capturing:
- switch.turn_on: timer_ringing
- light.turn_on:
id: led
red: 0%
green: 100%
blue: 0%
brightness: 100%
effect: "Fast Pulse"
- wait_until:
- switch.is_off: timer_ringing
- light.turn_off: led
- switch.turn_off: timer_ringing
binary_sensor:
# button does the following:
# short click - stop a timer
# if no timer then restart either microwakeword or voice assistant continuous
- platform: gpio
pin:
number: GPIO39
inverted: true
name: Button
disabled_by_default: true
entity_category: diagnostic
id: echo_button
on_multi_click:
- timing:
- ON for at least 50ms
- OFF for at least 50ms
then:
- if:
condition:
switch.is_on: timer_ringing
then:
- switch.turn_off: timer_ringing
else:
- script.execute: start_wake_word
- timing:
- ON for at least 10s
then:
- button.press: factory_reset_btn
light:
- platform: esp32_rmt_led_strip
id: led
name: None
disabled_by_default: true
entity_category: config
pin: GPIO27
default_transition_length: 0s
chipset: SK6812
num_leds: 1
rgb_order: grb
effects:
- pulse:
name: "Slow Pulse"
transition_length: 250ms
update_interval: 250ms
min_brightness: 50%
max_brightness: 100%
- pulse:
name: "Fast Pulse"
transition_length: 100ms
update_interval: 100ms
min_brightness: 50%
max_brightness: 100%
script:
- id: reset_led
then:
- if:
condition:
- lambda: return id(wake_word_engine_location).state == "On device";
- switch.is_on: use_listen_light
then:
- light.turn_on:
id: led
red: 100%
green: 89%
blue: 71%
brightness: 60%
effect: none
else:
- if:
condition:
- lambda: return id(wake_word_engine_location).state != "On device";
- switch.is_on: use_listen_light
then:
- light.turn_on:
id: led
red: 0%
green: 100%
blue: 100%
brightness: 60%
effect: none
else:
- light.turn_off: led
- id: start_wake_word
then:
- if:
condition:
and:
- not:
- voice_assistant.is_running:
- lambda: return id(wake_word_engine_location).state == "On device";
then:
- lambda: id(va).set_use_wake_word(false);
- micro_wake_word.start:
- if:
condition:
and:
- not:
- voice_assistant.is_running:
- lambda: return id(wake_word_engine_location).state == "In Home Assistant";
then:
- lambda: id(va).set_use_wake_word(true);
- voice_assistant.start_continuous:
- id: stop_wake_word
then:
- if:
condition:
lambda: return id(wake_word_engine_location).state == "In Home Assistant";
then:
- lambda: id(va).set_use_wake_word(false);
- voice_assistant.stop:
- if:
condition:
lambda: return id(wake_word_engine_location).state == "On device";
then:
- micro_wake_word.stop:
switch:
- platform: template
name: Use listen light
id: use_listen_light
optimistic: true
restore_mode: RESTORE_DEFAULT_ON
entity_category: config
on_turn_on:
- script.execute: reset_led
on_turn_off:
- script.execute: reset_led
- platform: template
id: timer_ringing
optimistic: true
restore_mode: ALWAYS_OFF
on_turn_off:
# Turn off the repeat mode and disable the pause between playlist items
- lambda: |-
id(echo_media_player)
->make_call()
.set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_OFF)
.set_announcement(true)
.perform();
id(echo_media_player)->set_playlist_delay_ms(speaker::AudioPipelineType::ANNOUNCEMENT, 0);
# Stop playing the alarm
- media_player.stop:
announcement: true
on_turn_on:
# Turn on the repeat mode and pause for 1000 ms between playlist items/repeats
- lambda: |-
id(echo_media_player)
->make_call()
.set_command(media_player::MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_ONE)
.set_announcement(true)
.perform();
id(echo_media_player)->set_playlist_delay_ms(speaker::AudioPipelineType::ANNOUNCEMENT, 1000);
- media_player.speaker.play_on_device_media_file:
media_file: timer_finished_wave_file
announcement: true
- delay: 15min
- switch.turn_off: timer_ringing
select:
- platform: template
entity_category: config
name: Wake word engine location
id: wake_word_engine_location
optimistic: true
restore_value: true
options:
- In Home Assistant
- On device
initial_option: On device
on_value:
- if:
condition:
lambda: return x == "In Home Assistant";
then:
- micro_wake_word.stop:
- delay: 500ms
- lambda: id(va).set_use_wake_word(true);
- voice_assistant.start_continuous:
- if:
condition:
lambda: return x == "On device";
then:
- lambda: id(va).set_use_wake_word(false);
- voice_assistant.stop:
- delay: 500ms
- micro_wake_word.start:
micro_wake_word:
on_wake_word_detected:
- voice_assistant.start:
wake_word: !lambda return wake_word;
vad:
models:
- model: okay_nabu
- model: hey_mycroft
- model: hey_jarvis

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,240 @@
## Laptop Specs
Operating System: Fedora Linux 41
KDE Plasma Version: 6.3.4
KDE Frameworks Version: 6.12.0
Qt Version: 6.8.2
Kernel Version: 6.13.9-200.fc41.x86_64 (64-bit)
Graphics Platform: Wayland
Processors: 16 × AMD Ryzen 9 7940HS w/ Radeon 780M Graphics
Memory: 98.9 GB of RAM
Graphics Processor: AMD Radeon 780M
Manufacturer: Framework
Product Name: Laptop 16 (AMD Ryzen 7040 Series)
System Version: AJ
## The Problem
Hey everyone, I've had no luck searching for this issue online. I might be looking in the wrong places so please point me to existing posts if there's already a topic in flight on this, or another, forum.
My Framework 16's dGPU disconnects after waking from sleep. It won't show up in monitoring software (Mission Center from Flatpak) or MangoHud in games. It's also not being detected by steam games or ollama - both will only detect and use the internal gpu. I'm pretty sure it shows up in `lscpi` (shown below in dGPU disconnected state).
No bios settings have made a difference. This happens both on-battery and charging with the framework charger and a 240 watt Delta charger. Power profiles don't make a difference either.
I have secure boot on. I don't use hibernate. I have a couple custom udev rules that prevent usb devices from waking the laptop in sleep (shown below).
Looking for anything to try, thanks for the help!
## Details
### lspci
```bash
00:00.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Phoenix Root Complex
00:00.2 IOMMU: Advanced Micro Devices, Inc. [AMD] Phoenix IOMMU
00:01.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Phoenix Dummy Host Bridge
00:01.1 PCI bridge: Advanced Micro Devices, Inc. [AMD] Phoenix GPP Bridge
00:02.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Phoenix Dummy Host Bridge
00:02.2 PCI bridge: Advanced Micro Devices, Inc. [AMD] Phoenix GPP Bridge
00:02.4 PCI bridge: Advanced Micro Devices, Inc. [AMD] Phoenix GPP Bridge
00:03.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Phoenix Dummy Host Bridge
00:03.1 PCI bridge: Advanced Micro Devices, Inc. [AMD] Family 19h USB4/Thunderbolt PCIe tunnel
00:04.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Phoenix Dummy Host Bridge
00:04.1 PCI bridge: Advanced Micro Devices, Inc. [AMD] Family 19h USB4/Thunderbolt PCIe tunnel
00:08.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Phoenix Dummy Host Bridge
00:08.1 PCI bridge: Advanced Micro Devices, Inc. [AMD] Phoenix Internal GPP Bridge to Bus [C:A]
00:08.2 PCI bridge: Advanced Micro Devices, Inc. [AMD] Phoenix Internal GPP Bridge to Bus [C:A]
00:08.3 PCI bridge: Advanced Micro Devices, Inc. [AMD] Phoenix Internal GPP Bridge to Bus [C:A]
00:14.0 SMBus: Advanced Micro Devices, Inc. [AMD] FCH SMBus Controller (rev 71)
00:14.3 ISA bridge: Advanced Micro Devices, Inc. [AMD] FCH LPC Bridge (rev 51)
00:18.0 Host bridge: Advanced Micro Devices, Inc. [AMD] Phoenix Data Fabric; Function 0
00:18.1 Host bridge: Advanced Micro Devices, Inc. [AMD] Phoenix Data Fabric; Function 1
00:18.2 Host bridge: Advanced Micro Devices, Inc. [AMD] Phoenix Data Fabric; Function 2
00:18.3 Host bridge: Advanced Micro Devices, Inc. [AMD] Phoenix Data Fabric; Function 3
00:18.4 Host bridge: Advanced Micro Devices, Inc. [AMD] Phoenix Data Fabric; Function 4
00:18.5 Host bridge: Advanced Micro Devices, Inc. [AMD] Phoenix Data Fabric; Function 5
00:18.6 Host bridge: Advanced Micro Devices, Inc. [AMD] Phoenix Data Fabric; Function 6
00:18.7 Host bridge: Advanced Micro Devices, Inc. [AMD] Phoenix Data Fabric; Function 7
01:00.0 PCI bridge: Advanced Micro Devices, Inc. [AMD/ATI] Navi 10 XL Upstream Port of PCI Express Switch (rev 12)
02:00.0 PCI bridge: Advanced Micro Devices, Inc. [AMD/ATI] Navi 10 XL Downstream Port of PCI Express Switch (rev 12)
03:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Navi 33 [Radeon RX 7600/7600 XT/7600M XT/7600S/7700S / PRO W7600] (rev c1)
03:00.1 Audio device: Advanced Micro Devices, Inc. [AMD/ATI] Navi 31 HDMI/DP Audio
04:00.0 Network controller: Intel Corporation Wi-Fi 6E(802.11ax) AX210/AX1675* 2x2 [Typhoon Peak] (rev 1a)
05:00.0 Non-Volatile memory controller: Seagate Technology PLC E18 PCIe SSD (rev 01)
c4:00.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Phoenix1 (rev c1)
c4:00.1 Audio device: Advanced Micro Devices, Inc. [AMD/ATI] Rembrandt Radeon High Definition Audio Controller
c4:00.2 Encryption controller: Advanced Micro Devices, Inc. [AMD] Phoenix CCP/PSP 3.0 Device
c4:00.3 USB controller: Advanced Micro Devices, Inc. [AMD] Device 15b9
c4:00.4 USB controller: Advanced Micro Devices, Inc. [AMD] Device 15ba
c4:00.5 Multimedia controller: Advanced Micro Devices, Inc. [AMD] ACP/ACP3X/ACP6x Audio Coprocessor (rev 63)
c4:00.6 Audio device: Advanced Micro Devices, Inc. [AMD] Family 17h/19h/1ah HD Audio Controller
c5:00.0 Non-Essential Instrumentation [1300]: Advanced Micro Devices, Inc. [AMD] Phoenix Dummy Function
c5:00.1 Signal processing controller: Advanced Micro Devices, Inc. [AMD] AMD IPU Device
c6:00.0 Non-Essential Instrumentation [1300]: Advanced Micro Devices, Inc. [AMD] Phoenix Dummy Function
c6:00.3 USB controller: Advanced Micro Devices, Inc. [AMD] Device 15c0
c6:00.4 USB controller: Advanced Micro Devices, Inc. [AMD] Device 15c1
c6:00.5 USB controller: Advanced Micro Devices, Inc. [AMD] Pink Sardine USB4/Thunderbolt NHI controller #1
c6:00.6 USB controller: Advanced Micro Devices, Inc. [AMD] Pink Sardine USB4/Thunderbolt NHI controller #2
```
### UDev Rules
```conf
ACTION=="add", SUBSYSTEM=="acpi", DRIVERS=="button", ATTRS{hid}=="PNP0C0D", ATTR{power/wakeup}="disabled"
ACTION=="add", SUBSYSTEM=="serio", DRIVERS=="atkbd", ATTR{power/wakeup}="disabled"
ACTION=="add", SUBSYSTEM=="i2c", DRIVERS=="i2c_hid_acpi", ATTRS{name}=="PIXA3854:00", ATTR{power/wakeup}="disabled"
ACTION=="add", SUBSYSTEM=="usb", DRIVERS=="usb", ATTR{power/wakeup}="disabled"
```
### Dmesg
```bash
[27962.377892] CPU: 11 UID: 0 PID: 187288 Comm: kworker/11:6 Tainted: G W 6.13.9-200.fc41.x86_64 #1
[27962.377896] Tainted: [W]=WARN
[27962.377898] Hardware name: Framework Laptop 16 (AMD Ryzen 7040 Series)/FRANMZCP09, BIOS 03.05 11/13/2024
[27962.377901] Workqueue: pm pm_runtime_work
[27962.377906] RIP: 0010:amdgpu_irq_put+0x46/0x70 [amdgpu]
[27962.378233] Code: c0 74 33 48 8b 4e 10 48 83 39 00 74 29 89 d1 48 8d 04 88 8b 08 85 c9 74 11 f0 ff 08 74 07 31 c0 e9 0a a3 c6 fa e9 1a fd ff ff <0f> 0b b8 ea ff ff ff e9 f9 a2 c6 fa b8 ea ff ff ff e9 ef a2 c6 fa
[27962.378237] RSP: 0018:ffffb598a9667c98 EFLAGS: 00010246
[27962.378241] RAX: ffff9a9fe45a0ea8 RBX: ffff9a9fdb880000 RCX: 0000000000000000
[27962.378244] RDX: 0000000000000000 RSI: ffff9a9fdb8a5560 RDI: ffff9a9fdb880000
[27962.378246] RBP: ffff9a9fdb8c55d0 R08: 0000000000000000 R09: 0000000001195b5a
[27962.378249] R10: ffffb598a9667c48 R11: 0000000000000000 R12: 0000000000000006
[27962.378251] R13: ffff9a9fdb880000 R14: 0000000000000001 R15: ffff9aa5dcb2b040
[27962.378254] FS: 0000000000000000(0000) GS:ffff9ab67ff80000(0000) knlGS:0000000000000000
[27962.378257] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[27962.378260] CR2: 00001f4402539014 CR3: 000000161c82c000 CR4: 0000000000f50ef0
[27962.378263] PKRU: 55555554
[27962.378265] Call Trace:
[27962.378268] <TASK>
[27962.378270] ? srso_alias_return_thunk+0x5/0xfbef5
[27962.378274] ? show_trace_log_lvl+0x255/0x2f0
[27962.378280] ? show_trace_log_lvl+0x255/0x2f0
[27962.378289] ? gfx_v11_0_hw_fini+0x41/0xf0 [amdgpu]
[27962.378597] ? amdgpu_irq_put+0x46/0x70 [amdgpu]
[27962.378906] ? __warn.cold+0x93/0xfa
[27962.378912] ? amdgpu_irq_put+0x46/0x70 [amdgpu]
[27962.379216] ? report_bug+0xff/0x140
[27962.379222] ? handle_bug+0x58/0x90
[27962.379226] ? exc_invalid_op+0x17/0x70
[27962.379230] ? asm_exc_invalid_op+0x1a/0x20
[27962.379239] ? amdgpu_irq_put+0x46/0x70 [amdgpu]
[27962.379549] ? srso_alias_return_thunk+0x5/0xfbef5
[27962.379553] gfx_v11_0_hw_fini+0x41/0xf0 [amdgpu]
[27962.379879] gfx_v11_0_suspend+0xe/0x20 [amdgpu]
[27962.380210] amdgpu_ip_block_suspend+0x24/0x40 [amdgpu]
[27962.380523] amdgpu_device_ip_suspend_phase2+0x125/0x340 [amdgpu]
[27962.380830] amdgpu_device_suspend+0xcf/0x170 [amdgpu]
[27962.381154] amdgpu_pmops_runtime_suspend+0xb9/0x1a0 [amdgpu]
[27962.381488] pci_pm_runtime_suspend+0x67/0x1a0
[27962.381494] ? __pfx_pci_pm_runtime_suspend+0x10/0x10
[27962.381499] __rpm_callback+0x41/0x170
[27962.381503] ? __pfx_pci_pm_runtime_suspend+0x10/0x10
[27962.381508] rpm_callback+0x55/0x60
[27962.381512] ? __pfx_pci_pm_runtime_suspend+0x10/0x10
[27962.381516] rpm_suspend+0xe6/0x5f0
[27962.381520] ? srso_alias_return_thunk+0x5/0xfbef5
[27962.381523] ? finish_task_switch.isra.0+0x99/0x2c0
[27962.381531] pm_runtime_work+0x98/0xb0
[27962.381535] process_one_work+0x176/0x330
[27962.381541] worker_thread+0x252/0x390
[27962.381547] ? __pfx_worker_thread+0x10/0x10
[27962.381551] kthread+0xcf/0x100
[27962.381557] ? __pfx_kthread+0x10/0x10
[27962.381562] ret_from_fork+0x31/0x50
[27962.381568] ? __pfx_kthread+0x10/0x10
[27962.381573] ret_from_fork_asm+0x1a/0x30
[27962.381583] </TASK>
[27962.381587] ---[ end trace 0000000000000000 ]---
[27965.093916] amdgpu 0000:03:00.0: amdgpu: MES failed to respond to msg=REMOVE_QUEUE
[27965.093923] [drm:amdgpu_mes_unmap_legacy_queue [amdgpu]] *ERROR* failed to unmap legacy queue
[27967.860541] amdgpu 0000:03:00.0: amdgpu: MES failed to respond to msg=REMOVE_QUEUE
[27967.860554] [drm:amdgpu_mes_unmap_legacy_queue [amdgpu]] *ERROR* failed to unmap legacy queue
[27970.792292] amdgpu 0000:03:00.0: amdgpu: MES failed to respond to msg=REMOVE_QUEUE
[27970.792306] [drm:amdgpu_mes_unmap_legacy_queue [amdgpu]] *ERROR* failed to unmap legacy queue
[27973.717776] amdgpu 0000:03:00.0: amdgpu: MES failed to respond to msg=REMOVE_QUEUE
[27973.717790] [drm:amdgpu_mes_unmap_legacy_queue [amdgpu]] *ERROR* failed to unmap legacy queue
[27976.642661] amdgpu 0000:03:00.0: amdgpu: MES failed to respond to msg=REMOVE_QUEUE
[27976.642670] [drm:amdgpu_mes_unmap_legacy_queue [amdgpu]] *ERROR* failed to unmap legacy queue
[27979.503724] amdgpu 0000:03:00.0: amdgpu: MES failed to respond to msg=REMOVE_QUEUE
[27979.503737] [drm:amdgpu_mes_unmap_legacy_queue [amdgpu]] *ERROR* failed to unmap legacy queue
[27982.355092] amdgpu 0000:03:00.0: amdgpu: MES failed to respond to msg=REMOVE_QUEUE
[27982.355102] [drm:amdgpu_mes_unmap_legacy_queue [amdgpu]] *ERROR* failed to unmap legacy queue
[27985.020353] amdgpu 0000:03:00.0: amdgpu: MES failed to respond to msg=REMOVE_QUEUE
[27985.020365] [drm:amdgpu_mes_unmap_legacy_queue [amdgpu]] *ERROR* failed to unmap legacy queue
[27987.689301] amdgpu 0000:03:00.0: amdgpu: MES failed to respond to msg=REMOVE_QUEUE
[27987.689308] [drm:amdgpu_mes_unmap_legacy_queue [amdgpu]] *ERROR* failed to unmap legacy queue
[27987.916382] [drm:gfx_v11_0_hw_fini [amdgpu]] *ERROR* failed to halt cp gfx
[27987.916872] ------------[ cut here ]------------
[27987.916873] WARNING: CPU: 11 PID: 187288 at drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c:631 amdgpu_irq_put+0x46/0x70 [amdgpu]
[27987.917063] Modules linked in: ib_core uinput overlay rfcomm snd_seq_dummy snd_hrtimer nft_reject_ipv6 nft_masq nft_reject_ipv4 act_csum cls_u32 sch_htb nf_nat_tftp nf_conntrack_tftp bridge stp llc nf_conntrack_netbios_ns nf_conntrack_broadcast nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ip_set nf_tables qrtr uhid bnep snd_hda_codec_realtek snd_hda_codec_generic snd_hda_scodec_component snd_hda_codec_hdmi sunrpc binfmt_misc vfat fat snd_sof_amd_acp70 snd_sof_amd_acp63 snd_sof_amd_vangogh snd_sof_amd_rembrandt snd_sof_amd_renoir snd_sof_amd_acp snd_sof_pci iwlmvm snd_sof_xtensa_dsp snd_sof cdc_mbim cdc_wdm cdc_ncm cdc_ether usbnet snd_sof_utils mac80211 snd_pci_ps snd_soc_acpi_amd_match snd_amd_sdw_acpi soundwire_amd soundwire_generic_allocation soundwire_bus snd_soc_sdca amd_atl intel_rapl_msr intel_rapl_common snd_soc_core libarc4 snd_hda_intel edac_mce_amd snd_intel_dspcfg snd_compress
[27987.917127] cros_usbpd_charger leds_cros_ec gpio_cros_ec cros_charge_control led_class_multicolor cros_ec_chardev ac97_bus cros_ec_hwmon cros_ec_sysfs cros_usbpd_logger cros_usbpd_notify snd_intel_sdw_acpi snd_pcm_dmaengine snd_hda_codec kvm_amd hid_sensor_als snd_rpl_pci_acp6x snd_acp_pci hid_sensor_trigger cros_ec_dev snd_hda_core hid_sensor_iio_common snd_acp_legacy_common kvm btusb iwlwifi industrialio_triggered_buffer snd_pci_acp6x btrtl btintel snd_hwdep kfifo_buf btbcm snd_seq btmtk cros_ec_lpcs spd5118 cros_ec snd_seq_device industrialio rapl cfg80211 wmi_bmof bluetooth snd_pcm snd_pci_acp5x pcspkr snd_rn_pci_acp3x snd_timer r8152 snd_acp_config thunderbolt mii k10temp snd_soc_acpi i2c_piix4 snd rfkill i2c_smbus snd_pci_acp3x amd_pmf soundcore amdtee joydev amd_sfh tee platform_profile amd_pmc loop nfnetlink zram lz4hc_compress lz4_compress dm_crypt hid_logitech_hidpp hid_logitech_dj typec_displayport amdgpu amdxcp drm_exec gpu_sched drm_panel_backlight_quirks drm_buddy drm_ttm_helper ttm nvme i2c_algo_bit
[27987.917196] drm_suballoc_helper crct10dif_pclmul crc32_pclmul drm_display_helper crc32c_intel nvme_core polyval_clmulni polyval_generic ghash_clmulni_intel video hid_multitouch sha512_ssse3 ucsi_acpi hid_sensor_hub typec_ucsi sha256_ssse3 sha1_ssse3 cec sp5100_tco typec nvme_auth wmi i2c_hid_acpi i2c_hid fuse i2c_dev
[27987.917222] CPU: 11 UID: 0 PID: 187288 Comm: kworker/11:6 Tainted: G W 6.13.9-200.fc41.x86_64 #1
[27987.917226] Tainted: [W]=WARN
[27987.917227] Hardware name: Framework Laptop 16 (AMD Ryzen 7040 Series)/FRANMZCP09, BIOS 03.05 11/13/2024
[27987.917229] Workqueue: pm pm_runtime_work
[27987.917235] RIP: 0010:amdgpu_irq_put+0x46/0x70 [amdgpu]
[27987.917403] Code: c0 74 33 48 8b 4e 10 48 83 39 00 74 29 89 d1 48 8d 04 88 8b 08 85 c9 74 11 f0 ff 08 74 07 31 c0 e9 0a a3 c6 fa e9 1a fd ff ff <0f> 0b b8 ea ff ff ff e9 f9 a2 c6 fa b8 ea ff ff ff e9 ef a2 c6 fa
[27987.917405] RSP: 0018:ffffb598a9667c68 EFLAGS: 00010246
[27987.917408] RAX: ffff9a9fe45a0508 RBX: ffff9a9fc7c27000 RCX: 0000000000000000
[27987.917410] RDX: 0000000000000000 RSI: ffff9a9fc7c27008 RDI: ffff9a9fdb880000
[27987.917411] RBP: ffff9a9fdb880000 R08: ffffffffbc873d28 R09: ffff9a9fc04020e8
[27987.917412] R10: ffffffffffffffff R11: 0000000000000000 R12: 0000000000000004
[27987.917413] R13: ffff9a9fdb880000 R14: 0000000000000001 R15: ffff9aa5dcb2b040
[27987.917415] FS: 0000000000000000(0000) GS:ffff9ab67ff80000(0000) knlGS:0000000000000000
[27987.917416] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[27987.917418] CR2: 00001f4402539014 CR3: 000000161c82c000 CR4: 0000000000f50ef0
[27987.917419] PKRU: 55555554
[27987.917420] Call Trace:
[27987.917423] <TASK>
[27987.917425] ? srso_alias_return_thunk+0x5/0xfbef5
[27987.917429] ? show_trace_log_lvl+0x255/0x2f0
[27987.917435] ? show_trace_log_lvl+0x255/0x2f0
[27987.917439] ? smu_smc_hw_cleanup+0x68/0xa0 [amdgpu]
[27987.917633] ? amdgpu_irq_put+0x46/0x70 [amdgpu]
[27987.917785] ? __warn.cold+0x93/0xfa
[27987.917789] ? amdgpu_irq_put+0x46/0x70 [amdgpu]
[27987.917930] ? report_bug+0xff/0x140
[27987.917934] ? handle_bug+0x58/0x90
[27987.917937] ? exc_invalid_op+0x17/0x70
[27987.917939] ? asm_exc_invalid_op+0x1a/0x20
[27987.917945] ? amdgpu_irq_put+0x46/0x70 [amdgpu]
[27987.918084] ? srso_alias_return_thunk+0x5/0xfbef5
[27987.918087] smu_smc_hw_cleanup+0x68/0xa0 [amdgpu]
[27987.918231] smu_suspend+0x77/0xe0 [amdgpu]
[27987.918344] amdgpu_ip_block_suspend+0x24/0x40 [amdgpu]
[27987.918461] amdgpu_device_ip_suspend_phase2+0x125/0x340 [amdgpu]
[27987.918568] amdgpu_device_suspend+0xcf/0x170 [amdgpu]
[27987.918674] amdgpu_pmops_runtime_suspend+0xb9/0x1a0 [amdgpu]
[27987.918778] pci_pm_runtime_suspend+0x67/0x1a0
[27987.918782] ? __pfx_pci_pm_runtime_suspend+0x10/0x10
[27987.918784] __rpm_callback+0x41/0x170
[27987.918787] ? __pfx_pci_pm_runtime_suspend+0x10/0x10
[27987.918790] rpm_callback+0x55/0x60
[27987.918792] ? __pfx_pci_pm_runtime_suspend+0x10/0x10
[27987.918794] rpm_suspend+0xe6/0x5f0
[27987.918795] ? srso_alias_return_thunk+0x5/0xfbef5
[27987.918797] ? finish_task_switch.isra.0+0x99/0x2c0
[27987.918802] pm_runtime_work+0x98/0xb0
[27987.918805] process_one_work+0x176/0x330
[27987.918808] worker_thread+0x252/0x390
[27987.918811] ? __pfx_worker_thread+0x10/0x10
[27987.918813] kthread+0xcf/0x100
[27987.918816] ? __pfx_kthread+0x10/0x10
[27987.918818] ret_from_fork+0x31/0x50
[27987.918821] ? __pfx_kthread+0x10/0x10
[27987.918823] ret_from_fork_asm+0x1a/0x30
[27987.918828] </TASK>
[27987.918829] ---[ end trace 0000000000000000 ]---
[27987.918833] amdgpu 0000:03:00.0: amdgpu: Fail to disable thermal alert!
[27987.918836] amdgpu 0000:03:00.0: amdgpu: suspend of IP block <smu> failed -22
[27987.918851] amdgpu 0000:03:00.0: amdgpu: SMU: response:0xFFFFFFFF for index:46 param:0x00000000 message:PrepareMp1ForUnload?
[27987.918853] amdgpu 0000:03:00.0: amdgpu: [PrepareMp1] Failed!
[27987.918855] [drm:amdgpu_device_ip_suspend_phase2 [amdgpu]] *ERROR* SMC failed to set mp1 state 2, -121
[28270.864511] amdgpu 0000:03:00.0: amdgpu: PSP is resuming...
[28271.140289] amdgpu 0000:03:00.0: amdgpu: PSP create ring failed!
[28271.140299] amdgpu 0000:03:00.0: amdgpu: PSP resume failed
[28271.140303] amdgpu 0000:03:00.0: amdgpu: resume of IP block <psp> failed -62
[28271.140309] amdgpu 0000:03:00.0: amdgpu: amdgpu_device_ip_resume failed (-62).
```

View File

@@ -0,0 +1,23 @@
# Framework Laptop 16
## Keyboard VIA
Access keyboard configuration at <https://keyboard.frame.work/>
You might need to add the qmk udev rules for the browser to access your keyboard. Follow below:
```bash
sudo curl -o /etc/udev/rules.d/50-qmk.rules https://raw.githubusercontent.com/qmk/qmk_firmware/refs/heads/master/util/udev/50-qmk.rules
sudo udevadm control --reload-rules
sudo udevadm trigger
```
## Beta Bios Updates
```bash
# With charger attached
sudo fwupdmgr enable-remote lvfs-testing
sudo fwupdmgr refresh --force
sudo fwupdmgr get-updates
sudo fwupdmgr update
```

Binary file not shown.

View File

@@ -0,0 +1,710 @@
# Home Assistant
- [Home Assistant](#home-assistant)
- [Certificates](#certificates)
- [Setup and Configuration](#setup-and-configuration)
- [Schlage Door Lock](#schlage-door-lock)
- [Philips Hue Lights](#philips-hue-lights)
- [Shelly](#shelly)
- [Barometer](#barometer)
- [Relative Humidity Calculator](#relative-humidity-calculator)
- [Font Colors](#font-colors)
- [Light Indicator for Voice Assistant](#light-indicator-for-voice-assistant)
- [Blank Button (Spacer)](#blank-button-spacer)
- [Roku Remote](#roku-remote)
- [Flair Vent Battery](#flair-vent-battery)
- [Voice](#voice)
- [Changing the Voice of TTS](#changing-the-voice-of-tts)
- [Custom Sentences](#custom-sentences)
- [Overriding Default Sentences](#overriding-default-sentences)
- [Notifications](#notifications)
- [Unifi Cameras](#unifi-cameras)
- [Multiple Entity Triggers with Custom Names](#multiple-entity-triggers-with-custom-names)
- [Philips Hue Switches](#philips-hue-switches)
- [Datetimes](#datetimes)
- [LG TV Switch](#lg-tv-switch)
## Certificates
Note, self signed certs won't work on the hass android app.
```bash
# Generate the key/cert
# Note, 36159 days == 99 years
openssl req \
-sha256 \
-addext "subjectAltName = IP:10.2.0.230" \
-newkey rsa:4096 \
-nodes \
-keyout privkey.pem \
-x509 \
-days 36159 \
-out fullchain.pem
http:
server_port: 8123
ssl_certificate: /ssl/fullchain.pem
ssl_key: /ssl/privkey.pem
```
## Setup and Configuration
### Schlage Door Lock
1. Install Z-wave
2. Install z-wave JS module
3. Add device -> How do you want to add your device -> Legacy Secure
4. Disconnect and Reconnect the battery on the lock
5. Press and hold the zwave button until the light turns solid red, release and it should flash red
1. (OR) Enter programming pin on lock -> 0 (this may take a few attempts, don't click the pair button)
If the lock ever disconnects you can safely delete it from home assistant and re-interview. It will
set back up with the correct entity IDs and automations/dashboards will work just fine.
### Philips Hue Lights
1. I configure all philips hue lights through zigbee directly connected to HA
hue lights support color_temp in mireds, here are some mired-kelvin conversions:
| Kelvin | Mired |
| ------ | ----- |
| 6000 | 167 |
| 4000 | 250 |
| 2600 | 385 |
### Shelly
1. Outbound Websocket `wss://homeassistant.reeseapps.com/api/shelly/ws`
Shelly devices can act as "passive" or "active" bluetooth scanners. Both of these configurations
allow home assistant to proxy bluetooth connections through shelly devices, significantly extending
the range of your home assistant's bluetooth capabilities. Active scanning uses more power but
is quicker to pick up and transmit device information. Note that "gateway mode" is not required,
just enable bluetooth and rpc or select "active" from the configuration menu for the shelly
device.
#### Barometer
<https://www.thoughtco.com/how-to-read-a-barometer-3444043>
A barometric reading over 30.20 inHg is generally considered high, and high pressure is associated with clear skies and calm weather.
If the reading is over 30.20 inHg (102268.9 Pa or 1022.689 mb):
- Rising or steady pressure means continued fair weather.
- Slowly falling pressure means fair weather.
- Rapidly falling pressure means cloudy and warmer conditions.
A barometric reading in the range of 29.80 and 30.20 inHg can be considered normal, and normal pressure is associated with steady weather.
If the reading falls between 29.80 and 30.20 inHg (100914.4102268.9 Pa or 1022.6891009.144 mb):
- Rising or steady pressure means present conditions will continue.
- Slowly falling pressure means little change in the weather.
- Rapidly falling pressure means that rain is likely, or snow if it is cold enough.
A barometric reading below 29.80 inHg is generally considered low, and low pressure is associated with warm air and rainstorms.
If the reading is under 29.80 inHg (100914.4 Pa or 1009.144 mb):
- Rising or steady pressure indicates clearing and cooler weather.
- Slowly falling pressure indicates rain.
- Rapidly falling pressure indicates a storm is coming.
A basic automation would look like
```yaml
It's {{ int(states("sensor.grouse_temp")) }} degrees and {{ states("weather.grouse_weather") }}. The relative humidity is {{ states("sensor.grouse_humidity") }}%. I'm seeing {{ int(states("sensor.grouse_wind_speed")) }}mph wind with gusts up to {{ int(states("sensor.grouse_wind_gust")) }}mph.
{% set pressure = float(states("sensor.grouse_rel_pressure")) %}
The barometer reads {{ pressure }}inHg.
{% if pressure > 30.20 %}
Fair weather is expected
{% elif pressure > 29.80 %}
Rain is possible
{% else %}
Rain is coming.
{% endif %}
```
#### Relative Humidity Calculator
<https://www.wikihow.com/Calculate-Humidity>
You can calculate the relative humidity of the outdoor air if warmed to indoor temperatures like so:
```jinja
{% set dew_point = state_attr("weather.forecast_home", "dew_point") %}
{% set air_temp_f = state_attr("climate.ecobee_thermostat", "current_temperature") %}
{% set air_temp = (5/9)*(air_temp_f-32) %}
{% set sat_vap_press = 6.11 * 10**((7.5*air_temp) / (237.3+air_temp)) %}
{% set act_vap_press = 6.11 * 10**((7.5*dew_point) / (237.3+dew_point)) %}
{% set rel_hum = 100*(act_vap_press / sat_vap_press) %}
{{ dew_point }}
{{ air_temp }}
{{ sat_vap_press }}
{{ act_vap_press }}
{{ rel_hum }}
```
### Font Colors
```html
<font color = {{ "green" if state_attr("climate.ecobee_thermostat", "current_humidity") > low_humidity and state_attr("climate.ecobee_thermostat", "current_humidity") < high_humidity else "red" }}>
HVAC Humidity: {{ state_attr("climate.ecobee_thermostat", "current_humidity") }}%
</font>
```
### Light Indicator for Voice Assistant
```yaml
alias: Flash Lights on Bedroom Voice Assistant Start
description: ""
triggers:
- type: turned_on
device_id: d50fa1ae499e88bf37225c7e82ed189b
entity_id: 7ab2896ca3a55efd2e0ee9bba91fdf68
domain: binary_sensor
metadata:
secondary: false
trigger: device
conditions: []
actions:
- action: scene.create
metadata: {}
data:
scene_id: bedroombeforescene
snapshot_entities:
- light.main_bedroom_lamps
- action: light.turn_on
metadata: {}
data:
transition: 0.25
brightness_step_pct: 5
target:
entity_id: light.main_bedroom_lamps
- delay:
hours: 0
minutes: 0
seconds: 0
milliseconds: 250
- action: scene.turn_on
data:
entity_id: scene.bedroombeforescene
transition: 0.25
mode: single
```
### Blank Button (Spacer)
```yaml
- type: button
tap_action:
action: none
show_state: false
show_name: false
show_icon: false
hold_action:
action: none
```
### Roku Remote
```yaml
type: vertical-stack
cards:
- type: entity
entity: select.left_living_room_application
- square: true
type: grid
cards:
- show_name: true
show_icon: true
type: button
tap_action:
action: perform-action
perform_action: remote.send_command
target:
entity_id: remote.left_living_room
data:
command: power
entity: remote.left_living_room
icon: mdi:power
name: power
show_state: false
hold_action:
action: none
- show_name: true
show_icon: true
type: button
tap_action:
action: perform-action
perform_action: remote.send_command
target:
entity_id: remote.left_living_room
data:
command: volume_down
entity: remote.left_living_room
icon: mdi:volume-minus
name: volume down / hold mute
show_state: false
hold_action:
action: perform-action
perform_action: remote.send_command
target:
entity_id: remote.left_living_room
data:
command: volume_mute
- show_name: true
show_icon: true
type: button
tap_action:
action: perform-action
perform_action: remote.send_command
target:
entity_id: remote.left_living_room
data:
command: volume_up
entity: remote.left_living_room
icon: mdi:volume-plus
name: volume up / hold mute
show_state: false
"hold_action:":
action: perform-action
perform_action: remote.send_command
target:
entity_id: remote.left_living_room
data:
command: volume_mute
- show_name: true
show_icon: true
type: button
tap_action:
action: perform-action
perform_action: remote.send_command
target:
entity_id: remote.left_living_room
data:
command: back
entity: remote.left_living_room
icon: mdi:undo
name: back
show_state: false
hold_action:
action: none
- show_name: true
show_icon: true
type: button
tap_action:
action: perform-action
perform_action: remote.send_command
target:
entity_id: remote.left_living_room
data:
command: up
entity: remote.left_living_room
icon: mdi:arrow-up-bold
name: up
hold_action:
action: none
- show_name: true
show_icon: true
type: button
tap_action:
action: perform-action
perform_action: remote.send_command
target:
entity_id: remote.left_living_room
data:
command: home
entity: remote.left_living_room
icon: mdi:home
name: home
hold_action:
action: none
- show_name: true
show_icon: true
type: button
tap_action:
action: perform-action
perform_action: remote.send_command
target:
entity_id: remote.left_living_room
data:
command: left
entity: remote.left_living_room
icon: mdi:arrow-left-bold
name: left
hold_action:
action: none
- show_name: true
show_icon: true
type: button
tap_action:
action: perform-action
perform_action: remote.send_command
target:
entity_id: remote.left_living_room
data:
command: select
entity: remote.left_living_room
icon: mdi:select-all
name: select
hold_action:
action: none
- show_name: true
show_icon: true
type: button
tap_action:
action: perform-action
perform_action: remote.send_command
target:
entity_id: remote.left_living_room
data:
command: right
entity: remote.left_living_room
icon: mdi:arrow-right-bold
name: right
hold_action:
action: none
- show_name: true
show_icon: true
type: button
tap_action:
action: perform-action
perform_action: remote.send_command
target:
entity_id: remote.left_living_room
data:
command: play
entity: remote.left_living_room
icon: mdi:play-pause
name: play/pause
hold_action:
action: none
- show_name: true
show_icon: true
type: button
tap_action:
action: perform-action
perform_action: remote.send_command
target:
entity_id: remote.left_living_room
data:
command: down
entity: remote.left_living_room
icon: mdi:arrow-down-bold
name: down
hold_action:
action: none
- show_name: true
show_icon: true
type: button
tap_action:
action: perform-action
perform_action: remote.send_command
target:
entity_id: remote.left_living_room
data:
command: info
entity: remote.left_living_room
icon: mdi:wrench
name: settings
hold_action:
action: none
title: Left Living Room TV
```
### Flair Vent Battery
Flair vents report low battery at 2.4v. 3v is nominal/full.
```yaml
{% set volt_min=2.4 %}
{% set volt_max=3.0 %}
{% set volt_diff_max=0.6 %}
{{ (min(float(states("sensor.main_bedroom_29bf_voltage")) - volt_min, volt_diff_max) / volt_diff_max) * 100 }}
```
## Voice
### Changing the Voice of TTS
Select a media player -> play TTS -> select voice -> copy voice ID.
```yaml
options:
voice: DavisNeural||chat
```
### Custom Sentences
<https://developers.home-assistant.io/docs/voice/intent-recognition/template-sentence-syntax/#sentence-templates-syntax>
### Overriding Default Sentences
1. Identify if your sentence conflicts with [Home Assistant's default
sentences](https://github.com/OHF-Voice/intents/tree/main/sentences/en)
2. Create a new file at `/config/custom_sentences/en/overrides.yaml`
3. As an example, to override the `HassGetWeather` sentence:
1. Copy the contents of `weather_HassGetWeather.yaml` into `overrides.yaml`
2. Rename `HassGetWeather` to `HassGetWeather_Custom`
3. Delete the required context `weather`
4. Now in `configuration.yaml`, under a section called `intent_script`, add the following
```yaml
HassGetWeather_Custom:
speech:
text: >-
It's {{ int(states("sensor.backyard_weather_station_temp")) }} degrees
with {{ states("sensor.backyard_weather_station_humidity") }}% humidity.
I'm seeing {{ int(states("sensor.backyard_weather_station_wind_speed"))
}}mph wind. It's rained {{
int(states("sensor.backyard_weather_station_hourly_rain_rate")) }} inches
in the last hour.
```
5. Restart Home Assistant
6. Navigate to Settings -> Voice Assistants -> Click the 3 dots next to
your voice assistant -> Debug -> Click the icon in the top right -> Run
text pipeline -> "What's the weather"
## Notifications
Notification Information:
<https://www.home-assistant.io/docs/automation/templating/>
```yaml
Triggered by {{ trigger.entity_id }}, Date: {{ now().strftime('%Y-%m-%d') }}, Time: {{ now().strftime('%H:%M') }}
```
## Unifi Cameras
Create image/video previews of events with the following automation:
```yaml
alias: Vehicle Driveway Notification
description: Sends a notification with video upon motion detection.
triggers:
- entity_id:
- binary_sensor.driveway_camera_vehicle_detected
trigger: state
from: "on"
to: "off"
actions:
- data:
message: Vehicle detected on Driveway Camera
data:
image: >-
/api/unifiprotect/thumbnail/{{ config_entry_id(trigger.entity_id)
}}/{{ trigger.from_state.attributes.event_id }}
video: >-
/api/unifiprotect/video/{{ config_entry_id(trigger.entity_id) }}/{{
trigger.from_state.attributes.event_id }}
action: notify.notify
mode: single
max_exceeded: silent
```
## Multiple Entity Triggers with Custom Names
You can set an "id" for a trigger that can be used as a human readable name.
```yaml
alias: Notify when a Door Opened
description: ""
triggers:
- trigger: state
entity_id:
- binary_sensor.my_front_door
from: "off"
to: "on"
id: Front Door
- trigger: state
entity_id:
- binary_sensor.my_back_door
from: "off"
to: "on"
id: Back Door
- trigger: state
entity_id:
- binary_sensor.super_secret_door
from: "off"
to: "on"
id: Trap Door
conditions: []
actions:
- action: notify.notify
metadata: {}
data:
message: "{{ trigger.id }} Opened"
mode: single
```
## Philips Hue Switches
Philips Hue Switches don't expose entities, but rather trigger "zha_event" events.
To see events fired by these devices: Developer tools -> Events -> Listen to events `zha_event`
You can use this in automations like so:
```yaml
alias: Some Switch
description: ""
triggers:
- device_id: bb54b111ec77fb7d5356bb600789098f
domain: zha
type: remote_button_short_press
subtype: turn_on
trigger: device
id: "on"
- device_id: bb54b111ec77fb7d5356bb600789098f
domain: zha
type: remote_button_long_press
subtype: turn_on
trigger: device
id: on-con
conditions: []
actions:
- action: scene.turn_on
metadata: {}
data: {}
target:
entity_id: scene.some_scene
mode: single
```
## Datetimes
Stolen from Reddit
```yaml
## Set placeholder templates for reference in this template
## 'dt' substitutes 'now()'
## eg. if currently 5 March 2024 at 09:08:07 (AM)
eg_now = {% set eg_now = "2024-03-05 09:08:07.123456+00:00" %}{{ eg_now }}
dt = {% set dt = eg_now | as_datetime %}{{ dt }}
ts = {% set ts = eg_now | as_timestamp %}{{ ts }}
## Basic Time & Date Functions
time_now: {{ now() }}
time_local: {{ now() | as_local }}
time_timestamp: {{ now() | as_timestamp }}
## Time Conversions
seconds_per_min : {% set spm = 60 | int %}{{ spm }}
seconds_per_hour: {% set sph = ( spm * 60 ) | int %}{{ sph }}
seconds_per_day : {% set spd = 86400 | int %}{{ spd }}
seconds_per_week: {% set spw = ( spd * 7 ) | int %}{{ spw }}
minutes_per_day : {% set mpd = ( spd / 60 ) | int %}{{ mpd }}
minutes_per_week: {% set mpw = ( mpd * 7 ) | int %}{{ mpw }}
hours_per_week : {% set hpw = ( 24 * 7 ) | int %}{{ hpw }}
## Time Calculations
## with DATETIME use timedelta:
* CURRENT TIME : {{ dt }}
+ 1 YEAR : {{ dt + timedelta(days=365) }}
- 1 DAY (24H) : {{ dt - timedelta(days=1) }}
+ 3 DAYS (72H) : {{ dt + timedelta(days=3) }}
- 3 HOURS : {{ dt - timedelta(hours=3) }}
+ 1 HR 26 MIN : {{ dt + timedelta(hours=1, minutes=26) }}
+ 1D 2H 3M 4S : {{ dt + timedelta(days=1, hours=2, minutes=3, seconds=4) }}
## with TIMESTAMP use maths and then convert:
## Referencing earlier calculations for ease
* TIMESTAMP : {{ ts }}
* CURRENT TIME : {{ ts | as_datetime }}
+ 1 YEAR : {{ ( ts + (spd * 365) ) | as_datetime }}
- 1 DAY (24H) : {{ ( ts - spd ) | as_datetime }}
+ 3 DAYS (72H) : {{ ( ts + (spd * 3) ) | as_datetime }}
- 3 HOURS : {{ ( ts - (sph * 3) ) | as_datetime }}
+ 1 HR 26 MIN : {{ ( ts + sph + (spm * 26) ) | as_datetime }}
+ 1D 2H 3M 4S : {{ ( ts + spd + (sph * 2) + (spm * 3) + 4 ) | as_datetime }}
## Adjusting Time & Date For Calculations
Start Of Today: {% set start_today = dt.replace(hour=0, minute=0, second=0, microsecond=0) %}{{ start_today }}
End Of Today : {% set start_tomorrow = start_today + timedelta(days=1) %}{{ start_tomorrow }}
## Use Relative Time For DATETIME in the PAST
relative_time: {{ relative_time( start_today ) }} ago
## For time in the FUTURE you can use:
{% set current_time = dt %}{% set future_time = as_local(dt) %}{% set time_distance = future_time - current_time %}
relative_future: In {{ relative_time(current_time - time_distance) }}
## Use Time Templates combined with History Stats Sensor:
sensor:
- platform: history_stats
name: Lamp ON today
entity_id: light.my_lamp
state: "on"
```
Stolen from <https://www.fabriziomusacchio.com/blog/2021-08-15-strftime_Cheat_Sheet/>
| Format | Example | Description |
| ------ | ------------------------ | -------------------------------------------------------------------------------------------------- |
| %c | Thu Jan 28 12:32:01 2014 | locales appropriate date and time representation |
| %D | 23/05/12 | formats the date |
| %F | 2002-01-30 | date in ISO 8601 format YYYY-MM-DD |
| %x | 02/10/11 | locales appropriate date representation |
| %X | 14:22:01 | locales appropriate time representation |
| %r | 3:44:12 AM | 12-hour time |
| %R | 15:21 | 24-hour time HH:MM |
| %T | 15:21:59 | time in ISO 8601 format HH:MM:SS |
| %A | Monday | full weekday name |
| %a | Mon | abbreviated weekday name |
| %w | 0-6 | day of the week with Sunday as 0 |
| %d | 01-31 | day of the month (with a leading zero) |
| %e | 1-31 | day of the month (without a leading zero) |
| %B | April | full month name |
| %b | Apr | abbreviated month name |
| %m | 01-12 | month of the year (with a leading zero) |
| %-m | 1-12 | month of the year (without a leading zero) |
| %Y | 2003 | year |
| %y | 00-99 | year without a century (last two digits, with a leading zero) |
| %-y | 0-99 | year without a century (last two digits, without a leading zero) |
| %H | 00-23 | hour of the day, 24-hour time (with a leading zero) |
| %k | 0-23 | hour of the day, 24-hour time (without a leading zero) |
| %I | 01-11 | hour of the day, 12-hour time (with a leading zero) |
| %-I | 1-11 | hour of the day, 12-hour time (without a leading zero) |
| %P | am, pm | am or pm designation |
| %p | AM, PM | AM or PM designation |
| %M | 00-59 | minute of the hour (with a leading zero) |
| %-M | 0-59 | minute of the hour (without a leading zero) |
| %S | 00-60 | second of the minute (with a leading zero) |
| %-S | 0-60 | second of the minute (without a leading zero) |
| %f | 000000-999999 | microsecond of the second (with a leading zero) |
| %Z | UTC | timezone name or abbreviation |
| %z | +0000 | UTC offset in the form +HHMM or -HHMM |
| %s | | amount of seconds since 1970-01-01 00:00:00 UTC |
| %% | | % sign |
| %j | 001-366 | day of the year (with a leading zeroes) |
| %U | 00-53 | week number with the first Sunday as the first day of week one |
| %W | 00-53 | week number of the current year, starting with the first Monday as the first day of the first week |
| %V | 01-53 | week number in ISO 8601 format |
## LG TV Switch
```yaml
- platform: wake_on_lan
mac: b4:b2:91:8e:ce:20
name: loft_lg_tv_wol
turn_off:
service: media_player.turn_off
target:
device_id: "{{device_id('media_player.loft_lg_tv')}}"
- platform: wake_on_lan
mac: 60:8d:26:2c:4d:45
name: living_room_lg_tv_wol
turn_off:
service: media_player.turn_off
target:
device_id: "{{device_id('media_player.living_room_lg_tv')}}"
```

View File

@@ -0,0 +1,88 @@
# Shelly Devices
- [Shelly Devices](#shelly-devices)
- [1PM Mini Gen4](#1pm-mini-gen4)
- [Setup 1PM Mini Gen4](#setup-1pm-mini-gen4)
- [Install 1PM Mini Gen4](#install-1pm-mini-gen4)
- [Shelly Plug US](#shelly-plug-us)
- [Shelly BLU Motion](#shelly-blu-motion)
- [Shelly BLU Door/Window](#shelly-blu-doorwindow)
- [Reset](#reset)
- [Shelly Flood](#shelly-flood)
## 1PM Mini Gen4
### Setup 1PM Mini Gen4
1. Cut 1 white and 3 black pieces of 14 gauge wire to 3" long.
2. Strip 1/4" from one side of each wire.
3. Strip 1/2" from the other side of each wire.
4. Connect the 1/4" side to the shelly. Tighten the screws until you can't turn them.
5. Push line and neutral into a standard outlet. The wider receptacle is neutral.
6. Press and hold the button for 10 seconds to factory reset. Light will flash on/off every 1/4 second.
7. Press and hold the button for 5 seconds to turn on AP mode. Light will flash on/off every 1/2 second.
8. Connect to shelly network.
9. Navigate to <http://192.168.33.1>.
10. Connect to wifi. The light should turn solid.
11. Update firmware.
12. Set a password for AP mode.
13. Turn off the AP.
14. In Unifi: Name the device, give it a fixed IP, set the icon.
15. Navigate to the Shelly website via its IP address.
16. Set a password for http access: Settings -> Authentication.
17. Name the device: Settings -> Device name.
18. Set Restore last known state of output/relay: Home -> Output -> Input/Output Settings.
19. Enable Zigbee: Zigbee -> Enable.
20. Connect Shelly to Home Assistant via Zigbee.
21. Change switch type: Click on switch control -> Settings -> Show as.
### Install 1PM Mini Gen4
1. Cut 1 3" white wire for neutral bridge.
2. Cut 2 3" black wires for line bridge and light switch input.
3. Prepare 4 14 gauge wire connectors.
## Shelly Plug US
1. Connect to WiFi
2. Set password for AP
3. Disable AP
4. Set password for device authentication
5. Set Restore last known state of output/relay
6. Set Device Name
7. Enable Bluetooth Gateway
8. Update Firmware
## Shelly BLU Motion
1. Download and install the Shelly Debug app
2. Follow the instructions in the app to connect the device
3. Update the firmware
4. Enable encryption (generate a 6 digit code)
5. "Read" from the device and copy the encryption key for home assistant
## Shelly BLU Door/Window
1. Download and install the Shelly Debug app
2. Follow the instructions in the app to connect the device
3. Update the firmware
4. Create a new "login" in Bitwarden called "Shelly BLU DW " + name of device
1. Password will be the encryption key
2. Website should be the MAC address of the Shelly
5. Generate a 6 digit code, send it to your phone then throw it away
6. In the Shelly Debug app, enable encryption using the 6 digit code
7. Copy the encryption and store in the password field
8. Add to Home Assistant
9. Unpair from Phone
### Reset
Resetting is super finnicky. You'll need to plug it in, press and hold the power button until the
red light flashes quickly (not slowly, that's a reboot). You'll probably have to do it multiple
times because they seem to reboot halfway through the reset process.
## Shelly Flood
1. In the web interface, ensure "CoIoT" is enabled and pointing to `<home assistant ip>:5683`.
Allow 5683/udp from shelly flood to home assistant. If you don't do this Shelly Flood will
not report its status correctly!

View File

@@ -0,0 +1,99 @@
# Yubikey
- [Yubikey](#yubikey)
- [Configuration](#configuration)
- [Software](#software)
- [GPG](#gpg)
- [Saving GPG key to card](#saving-gpg-key-to-card)
- [Using the GPG key on a Yubikey](#using-the-gpg-key-on-a-yubikey)
- [Factory Reset](#factory-reset)
## Configuration
1. You will likely need the [udev
rules](https://support.yubico.com/hc/en-us/articles/360013708900-Using-Your-YubiKey-with-Linux)
to use the AppImage configuration tool on linux even if your udev version is above 244.
## Software
The [Yubikey Manager](https://www.yubico.com/support/download/yubikey-manager/) is deprecated.
Use the [Yubikey Authenticator](https://www.yubico.com/products/yubico-authenticator/) for GUI.
## GPG
### Saving GPG key to card
<https://support.yubico.com/hc/en-us/articles/360013790259-Using-Your-YubiKey-with-OpenPGP>
On Fedora you'll need to add the following polkit rules to access your smart card.
```bash
export MY_USER=ducoterra
echo <<EOF > /etc/polkit-1/rules.d/10-pcsc-custom.rules
polkit.addRule(function(action, subject) {
if (action.id == "org.debian.pcsc-lite.access_pcsc" &&
subject.user == "${MY_USER}") {
return polkit.Result.YES;
}
});
polkit.addRule(function(action, subject) {
if (action.id == "org.debian.pcsc-lite.access_card" &&
action.lookup("reader") == 'Yubico YubiKey OTP+FIDO+CCID 00 00' &&
subject.user == "${MY_USER}") {
return polkit.Result.YES;
}
});
EOF
```
Now you can add your key to your card.
```bash
gpg --edit-key 1234ABC
# Save both the signature and authentication keys
> keytocard
# Do not save or your key will be deleted locally
> quit
```
Check the keys on the yubikey with
```bash
gpg --card-status
```
Once your keys have been loaded, change the pin.
```bash
gpg --change-pin
```
### Using the GPG key on a Yubikey
<https://github.com/drduh/YubiKey-Guide?tab=readme-ov-file#notes>
```bash
export GPG_EMAIL='myemail@example.com'
# Import the public key. Without this the key won't show up.
gpg --auto-key-locate hkps://keys.openpgp.org --locate-keys ${GPG_EMAIL}
# Trust the key
gpg --quick-set-ownertrust ${GPG_EMAIL} full
# Yubikey should now show up
gpg --list-secret-keys
```
### Factory Reset
```bash
gpg --edit-card
> admin
> factory-reset
```

View File

@@ -0,0 +1,13 @@
# Kubernetes
## CLI Tools
kubectl: <https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/>
helm: <https://helm.sh/docs/intro/install/>
## Install a Kubernetes Server
For k3s, see [k3s](/active/systemd_k3s/k3s.md)
For k0s, see [k0s](/active/systemd_k0s/k0s.md)

View File

@@ -12,7 +12,7 @@ helm repo add bitwarden https://charts.bitwarden.com/
helm repo update
kubectl create namespace bitwarden
helm show values bitwarden/self-host > kubernetes/incubating/bitwarden/values.yaml
helm show values bitwarden/self-host > active/kubernetes_bitwarden/values.yaml
# Installation ID: https://bitwarden.com/host/
# Optional argument for Have I Been Pwned: --from-literal=globalSettings__hibpApiKey="REPLACE" \
@@ -25,5 +25,5 @@ kubectl create secret generic custom-secret -n bitwarden \
--from-file=globalSettings__yubico__key=./secrets/bitwarden/yubico_secret \
--from-file=SA_PASSWORD=./secrets/bitwarden/sa_password
helm upgrade bitwarden bitwarden/self-host --install --namespace bitwarden --values kubernetes/incubating/bitwarden/values.yaml
helm upgrade bitwarden bitwarden/self-host --install --namespace bitwarden --values active/kubernetes_bitwarden/values.yaml
```

View File

@@ -0,0 +1,15 @@
provider:
name: aws
env:
- name: AWS_SHARED_CREDENTIALS_FILE
value: /etc/aws/credentials/externaldns-credentials
- name: AWS_DEFAULT_REGION
value: us-east-1 # change to region where EKS is installed
extraVolumes:
- name: aws-credentials
secret:
secretName: external-dns # In this example, the secret will have the data stored in a key named `my_credentials`
extraVolumeMounts:
- name: aws-credentials
mountPath: /etc/aws/credentials
readOnly: true

View File

@@ -0,0 +1,11 @@
service:
http:
type: LoadBalancer
externalTrafficPolicy: Cluster
annotations:
metallb.io/allow-shared-ip: gitea
ssh:
type: LoadBalancer
externalTrafficPolicy: Cluster
annotations:
metallb.io/allow-shared-ip: gitea

View File

@@ -21,14 +21,10 @@ ingress:
persistence:
enabled: true
create: true
storageClass: zfs-iscsi-enc0
claimName: data-gitea-staging-0
annotations:
"helm.sh/resource-policy": keep
global:
storageClass: zfs-iscsi-enc1
postgresql:
enabled: true
image:
@@ -36,7 +32,6 @@ postgresql:
primary:
persistence:
enabled: true
storageClass: zfs-iscsi-enc1
annotations:
"helm.sh/resource-policy": keep

View File

@@ -1,10 +1,13 @@
# Gitea
- [Gitea](#gitea)
- [Demo](#demo)
- [Staging](#staging)
- [Install](#install)
- [Backup and Restore](#backup-and-restore)
- [Gitea Runners](#gitea-runners)
- [Install](#install-1)
- [Cache Cleanup](#cache-cleanup)
Gitea provides a helm chart [here](https://gitea.com/gitea/helm-chart/). We're not
going to modify much, but we are going to solidify some of the default values in case
@@ -12,6 +15,17 @@ they decide to change things. This is the first chart (besides ingress-nginx) wh
we need to pay attention to the MetalLB annotation. This has been set in the values.yaml
file.
## Demo
```bash
helm upgrade --install \
gitea \
gitea-charts/gitea \
--values active/kubernetes_gitea/gitea-demo-values.yaml \
--namespace gitea \
--create-namespace
```
## Staging
There is a `gitea-staging.yaml` file with staging values. This should be installed in
@@ -38,7 +52,7 @@ helm repo update
helm upgrade --install \
gitea \
gitea-charts/gitea \
--values kubernetes/graduated/gitea/gitea-values.yaml \
--values active/kubernetes_gitea/gitea-values.yaml \
--namespace gitea \
--create-namespace
```
@@ -78,6 +92,8 @@ kubectl scale statefulset gitea --replicas 1
<https://docs.gitea.com/next/usage/actions/act-runner/#install-with-the-docker-image>
### Install
```bash
touch config.yaml
@@ -95,3 +111,30 @@ docker run \
--name kube_runner \
-d gitea/act_runner:latest
```
### Cache Cleanup
Each org or project with a package registry will have its own cleanup rules. For example,
services -> settings -> Packages -> Add Cleanup Rule will allow you to create a cleanup
rule for packages stored under the "services" org. These cleanup rules should run automatically.
On the other hand, the docker builder cache will balloon out of control over time. The gitea
docker runner is handled outside of Gitea's context, so you'll need to clean it up yourself.
```bash
# Check used system resources
docker system df
```
You should run something like this on a schedule:
```bash
# Prune the builder cache
docker builder prune -a
```
To run it every day at midnight: `crontab -e`
```bash
0 0 * * * yes | docker builder prune -a
```

View File

@@ -8,7 +8,7 @@ helm repo update
helm upgrade --install my-grafana grafana/grafana \
--namespace monitoring \
--create-namespace \
--values kubernetes/incubating/grafana/values.yaml
--values active/kubernetes_grafana/values.yaml
kubectl get secret --namespace monitoring my-grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
```
@@ -25,5 +25,5 @@ helm upgrade --install \
kube-prometheus-stack \
prometheus-community/kube-prometheus-stack \
--namespace kube-system \
--values kubernetes/incubating/grafana/helm-prom-stack-values.yaml
--values active/kubernetes_grafana/helm-prom-stack-values.yaml
```

View File

@@ -7,7 +7,7 @@ This creates a basic iperf3 server.
```bash
helm upgrade --install \
iperf3 \
./kubernetes/graduated/iperf3 \
./active/kubernetes_iperf3/iperf3 \
--namespace iperf3 \
--create-namespace
```
```

View File

@@ -5,7 +5,7 @@
```bash
helm upgrade --install \
jellyfin \
./kubernetes/graduated/jellyfin \
./active/kubernetes_jellyfin \
--namespace jellyfin \
--create-namespace
```

View File

@@ -59,16 +59,16 @@ spec:
claimName: {{ .Release.Name }}-cache
- name: movies
nfs:
server: driveripper.reeselink.com
path: /mnt/enc0/media/Movies
server: driveripper-lab.reeselink.com
path: /mnt/enc0/smb/media/Movies
readOnly: true
- name: shows
nfs:
server: driveripper.reeselink.com
path: /mnt/enc0/media/Shows
server: driveripper-lab.reeselink.com
path: /mnt/enc0/smb/media/Shows
readOnly: true
- name: videos
nfs:
server: driveripper.reeselink.com
path: /mnt/enc0/media/Videos
server: driveripper-lab.reeselink.com
path: /mnt/enc0/smb/media/Videos
readOnly: true

View File

@@ -0,0 +1,10 @@
- op: replace # action
path: /data/config.json # resource we want to change
value: |-
{
"storageClassConfigs": {
"local-path": {
"sharedFileSystemPath": "/opt/local-path-provisioner"
}
}
}

View File

@@ -1,15 +1,10 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# Creates local path storage and a storage class
# Patched by ConfigMap-patch.yaml and namespace-patch.yaml
resources:
- local-path-storage.yaml
- ssd-storage.yaml
patches:
- target:
group: storage.k8s.io
version: v1
kind: StorageClass
name: local-path
path: StorageClass-hdd-patch.yaml
- target:
group: ""
version: v1

View File

@@ -0,0 +1,23 @@
# Local Path Provisioner Install
1. `mkdir /var/lib/rancher/k3s/storage`
2. Edit fstab to mount your drive to `/var/lib/rancher/k3s/storage`
3. `systemctl daemon-reload`
4. `mount -a`
<https://github.com/rancher/local-path-provisioner/tree/master/deploy/chart/local-path-provisioner>
```bash
# Download the updated template from github
kubectl kustomize "github.com/rancher/local-path-provisioner/deploy?ref=v0.0.32" > active/kubernetes_local-path-provisioner/local-path-storage.yaml
# Apply customizations (ssd/hdd storage, read write many support)
kubectl kustomize active/kubernetes_local-path-provisioner | kubectl apply -f -
```
Mark the class as default
```bash
kubectl patch storageclass local-path -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
```

View File

@@ -176,7 +176,7 @@ spec:
fieldPath: metadata.namespace
- name: CONFIG_MOUNT_PATH
value: /etc/config/
image: rancher/local-path-provisioner:v0.0.28
image: rancher/local-path-provisioner:v0.0.32
imagePullPolicy: IfNotPresent
name: local-path-provisioner
volumeMounts:

View File

@@ -0,0 +1,19 @@
---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: unifi-pool
namespace: kube-system
spec:
addresses:
- 2603:6013:3140:105:10:5:0:10-2603:6013:3140:105:10:5:0:210
- 10.5.0.10-10.5.0.210
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: l2advertisement
namespace: kube-system
spec:
ipAddressPools:
- unifi-pool

View File

@@ -5,12 +5,21 @@ below installs nimcraft. For each installation you'll want to create your own va
with a new port. The server-downloader is called "minecraft_get_server" and is available on
[Github](https://github.com/ducoterra/minecraft_get_server).
After installing, you can run admin commands (like whitelisting players) by
attaching to the container:
```bash
kubectl attach -it <pod>
> /whitelist add ducoterra
```
## Testing
```bash
helm upgrade --install \
testcraft \
./kubernetes/graduated/minecraft \
./active/kubernetes_minecraft \
--namespace minecraft \
--create-namespace
```
@@ -20,7 +29,7 @@ helm upgrade --install \
```bash
helm upgrade --install \
nimcraft \
./kubernetes/graduated/minecraft \
./active/kubernetes_minecraft \
--namespace minecraft \
--create-namespace
```
@@ -30,7 +39,7 @@ helm upgrade --install \
```bash
helm upgrade --install \
courtniecraft \
./kubernetes/graduated/minecraft \
./active/kubernetes_minecraft \
--namespace minecraft \
--create-namespace
```
@@ -40,7 +49,7 @@ helm upgrade --install \
```bash
helm upgrade --install \
camcraft1 \
./kubernetes/graduated/minecraft \
./active/kubernetes_minecraft \
--namespace minecraft \
--create-namespace
```

View File

@@ -56,10 +56,10 @@ spec:
value: "1"
resources:
requests:
memory: {{ div .Values.max_ram 2 }}Gi
memory: "{{ div .Values.max_ram 2 }}Gi"
cpu: 1m
limits:
memory: {{ add 1 .Values.max_ram }}Gi
memory: "{{ add 1 .Values.max_ram }}Gi"
cpu: {{ .Values.max_cpu | quote }}
volumes:
- name: data

View File

@@ -5,7 +5,6 @@ metadata:
annotations:
"helm.sh/resource-policy": keep
spec:
storageClassName: ssd
accessModes:
- ReadWriteOnce
resources:

View File

@@ -2,11 +2,7 @@ apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}
annotations:
metallb.universe.tf/address-pool: "external"
external-dns.alpha.kubernetes.io/hostname: {{ .Release.Name }}.reeseapps.com
spec:
ipFamilies: ["IPv6"]
externalTrafficPolicy: Cluster
selector:
app: {{ .Release.Name }}

View File

@@ -7,7 +7,7 @@ Snapdrop is a file sharing app that allows airdrop-like functionality over the w
```bash
helm upgrade --install \
snapdrop \
./kubernetes/graduated/snapdrop \
./active/kubernetes_snapdrop \
--namespace snapdrop \
--create-namespace
```

View File

@@ -17,7 +17,7 @@ spec:
- name: snapdrop
image: {{ .Values.snapdrop.image }}
ports:
- containerPort: 80
- containerPort: 3000
name: http
envFrom:
- configMapRef:

View File

@@ -1,3 +1,3 @@
snapdrop:
image: linuxserver/snapdrop:latest
image: linuxserver/pairdrop:latest
domain: snapdrop.reeseapps.com

Some files were not shown because too many files have changed in this diff Show More