Compare commits

...

19 Commits

Author SHA1 Message Date
Tuan-Dat Tran
a905b25190 fix(raspberry_pi): switch zigbee2mqtt adapter from ezsp to ember 2026-06-03 20:06:21 +02:00
Tuan-Dat Tran
25cc5ac271 fix(inventory): remove undefined k3s_storage group 2026-06-03 19:53:43 +02:00
Tuan-Dat Tran
2b857903a7 fix(raspberry_pi): use /dev/ttyUSB0 and set ezsp adapter for SONOFF MG21 2026-06-03 19:50:30 +02:00
Tuan-Dat Tran
eb4e8445fc fix(raspberry_pi): isolate z2m to own compose dir, fix port conflict 2026-06-03 19:43:35 +02:00
Tuan-Dat Tran
3799dc16d9 fix(raspberry_pi): install docker-compose-plugin before starting stack 2026-06-03 08:31:21 +02:00
Tuan-Dat Tran
585c01ca62 feat(raspberry_pi): wire up role tasks 2026-06-03 08:27:16 +02:00
Tuan-Dat Tran
14b93bf4f5 feat(raspberry_pi): add zigbee2mqtt deploy task 2026-06-03 08:26:04 +02:00
Tuan-Dat Tran
42e790656d feat(raspberry_pi): add zigbee2mqtt and mosquitto templates 2026-06-03 03:12:20 +02:00
Tuan-Dat Tran
da92fb0ccc feat(raspberry_pi): add directory setup task 2026-06-03 03:11:17 +02:00
Tuan-Dat Tran
d655cc54e2 fix(raspberry_pi): remove host condition from handler 2026-06-03 03:03:20 +02:00
Tuan-Dat Tran
9115d30c59 feat(raspberry_pi): add defaults, handlers, and secrets placeholder 2026-06-03 03:01:20 +02:00
Tuan-Dat Tran
8dcb429573 docs: add zigbee2mqtt implementation plan for naruto 2026-06-03 02:57:22 +02:00
Tuan-Dat Tran
29cc38872c docs: add zigbee2mqtt design spec for naruto 2026-06-03 02:54:18 +02:00
Tuan-Dat Tran
f6e2ce8c1a fix(common): replace deprecated apt_repository with deb822_repository 2026-06-03 02:31:33 +02:00
Tuan-Dat Tran
956836dc67 fix(common): replace deprecated ansible_ fact references with ansible_facts[] 2026-06-03 02:17:08 +02:00
Tuan-Dat Tran
aa8b591afd feat(raspberry_pi): add playbook 2026-06-03 01:23:48 +02:00
Tuan-Dat Tran
935389dc6d feat(raspberry_pi): add empty role scaffold 2026-06-03 01:23:48 +02:00
Tuan-Dat Tran
c4327a7596 fix(common): support aarch64 in extra_packages 2026-05-31 23:41:39 +02:00
Tuan-Dat Tran
b190022ff0 feat(raspberry_pi): add inventory and group vars 2026-05-31 23:29:07 +02:00
22 changed files with 650 additions and 32 deletions

View File

@@ -0,0 +1,356 @@
# Zigbee2MQTT + Mosquitto on naruto — Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Deploy Zigbee2MQTT and Mosquitto as Docker containers on naruto, fully managed by the `raspberry_pi` Ansible role.
**Architecture:** The `raspberry_pi` role gains a defaults file, a handlers file, and two task files (directories + zigbee2mqtt). Three Jinja2 templates cover the compose file, Mosquitto config, and Zigbee2MQTT config. All Zigbee2MQTT tasks are guarded with `when: inventory_hostname == 'naruto'` since the USB dongle only exists there. Secrets live in a new `vars/group_vars/raspberry_pi/secrets.yaml`.
**Tech Stack:** Ansible, Docker Compose, Mosquitto, Zigbee2MQTT, Debian 11 (aarch64)
---
## File Map
| Action | Path | Responsibility |
|--------|------|----------------|
| Modify | `roles/raspberry_pi/tasks/main.yaml` | Include 10_ and 20_ task files |
| Create | `roles/raspberry_pi/tasks/10_directories.yaml` | Create `/opt/docker/` tree on naruto |
| Create | `roles/raspberry_pi/tasks/20_zigbee2mqtt.yaml` | Template configs, start compose |
| Create | `roles/raspberry_pi/defaults/main.yaml` | Image versions and path vars |
| Create | `roles/raspberry_pi/handlers/main.yaml` | Restart zigbee2mqtt handler |
| Create | `roles/raspberry_pi/templates/zigbee2mqtt/docker-compose.yml.j2` | Compose file |
| Create | `roles/raspberry_pi/templates/zigbee2mqtt/mosquitto.conf.j2` | Mosquitto config |
| Create | `roles/raspberry_pi/templates/zigbee2mqtt/z2m-configuration.yaml.j2` | Zigbee2MQTT config |
| Create | `vars/group_vars/raspberry_pi/secrets.yaml` | Zigbee network key placeholder |
---
### Task 1: Add defaults, handlers, and secrets placeholder
**Files:**
- Create: `roles/raspberry_pi/defaults/main.yaml`
- Create: `roles/raspberry_pi/handlers/main.yaml`
- Create: `vars/group_vars/raspberry_pi/secrets.yaml`
- [ ] **Create defaults file**
```yaml
---
raspberry_pi_docker_base: /opt/docker
raspberry_pi_mosquitto_config_dir: "{{ raspberry_pi_docker_base }}/config/mosquitto"
raspberry_pi_z2m_config_dir: "{{ raspberry_pi_docker_base }}/config/zigbee2mqtt"
raspberry_pi_compose_dir: "{{ raspberry_pi_docker_base }}/compose"
raspberry_pi_mosquitto_version: "2"
raspberry_pi_z2m_version: "2"
```
Save to `roles/raspberry_pi/defaults/main.yaml`.
- [ ] **Create handlers file**
```yaml
---
- name: Restart zigbee2mqtt
ansible.builtin.command:
cmd: docker compose restart zigbee2mqtt
chdir: "{{ raspberry_pi_compose_dir }}"
listen: restart zigbee2mqtt
when: inventory_hostname == 'naruto'
```
Save to `roles/raspberry_pi/handlers/main.yaml`.
- [ ] **Create secrets placeholder**
```yaml
vault_raspberry_pi:
zigbee2mqtt:
network_key: "GENERATE"
```
Note: `GENERATE` tells Zigbee2MQTT to auto-generate a network key on first run and persist it to data. Replace with a fixed 16-integer array (e.g. `[1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 13]`) if you need a stable key across reinstalls.
Save to `vars/group_vars/raspberry_pi/secrets.yaml`.
- [ ] **Commit**
```bash
git add roles/raspberry_pi/defaults/main.yaml roles/raspberry_pi/handlers/main.yaml vars/group_vars/raspberry_pi/secrets.yaml
git commit -m "feat(raspberry_pi): add defaults, handlers, and secrets placeholder"
```
---
### Task 2: Create directory task
**Files:**
- Create: `roles/raspberry_pi/tasks/10_directories.yaml`
- [ ] **Create directory task file**
```yaml
---
- name: Create docker base directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: "0755"
become: true
loop:
- "{{ raspberry_pi_docker_base }}"
- "{{ raspberry_pi_compose_dir }}"
when: inventory_hostname == 'naruto'
- name: Create Mosquitto directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: "0755"
become: true
loop:
- "{{ raspberry_pi_mosquitto_config_dir }}"
- "{{ raspberry_pi_mosquitto_config_dir }}/data"
- "{{ raspberry_pi_mosquitto_config_dir }}/log"
when: inventory_hostname == 'naruto'
- name: Create Zigbee2MQTT directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: "0755"
become: true
loop:
- "{{ raspberry_pi_z2m_config_dir }}"
- "{{ raspberry_pi_z2m_config_dir }}/data"
when: inventory_hostname == 'naruto'
```
Save to `roles/raspberry_pi/tasks/10_directories.yaml`.
- [ ] **Commit**
```bash
git add roles/raspberry_pi/tasks/10_directories.yaml
git commit -m "feat(raspberry_pi): add directory setup task"
```
---
### Task 3: Create templates
**Files:**
- Create: `roles/raspberry_pi/templates/zigbee2mqtt/mosquitto.conf.j2`
- Create: `roles/raspberry_pi/templates/zigbee2mqtt/z2m-configuration.yaml.j2`
- Create: `roles/raspberry_pi/templates/zigbee2mqtt/docker-compose.yml.j2`
- [ ] **Create Mosquitto config template**
```
listener 1883
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
allow_anonymous true
```
Save to `roles/raspberry_pi/templates/zigbee2mqtt/mosquitto.conf.j2`.
- [ ] **Create Zigbee2MQTT config template**
```yaml
homeassistant:
enabled: true
mqtt:
server: mqtt://mosquitto:1883
serial:
port: /dev/serial/by-id/usb-SONOFF_SONOFF_Dongle_Lite_MG21_0263f93f46a2ef11b078926661ce3355-if00-port0
advanced:
network_key: {{ vault_raspberry_pi.zigbee2mqtt.network_key }}
log_level: info
frontend:
enabled: true
port: 8080
```
Save to `roles/raspberry_pi/templates/zigbee2mqtt/z2m-configuration.yaml.j2`.
- [ ] **Create Docker Compose template**
```yaml
name: zigbee2mqtt
services:
mosquitto:
image: eclipse-mosquitto:{{ raspberry_pi_mosquitto_version }}
container_name: mosquitto
restart: unless-stopped
ports:
- 1883:1883
volumes:
- {{ raspberry_pi_mosquitto_config_dir }}/mosquitto.conf:/mosquitto/config/mosquitto.conf:ro
- {{ raspberry_pi_mosquitto_config_dir }}/data:/mosquitto/data
- {{ raspberry_pi_mosquitto_config_dir }}/log:/mosquitto/log
zigbee2mqtt:
image: koenkk/zigbee2mqtt:{{ raspberry_pi_z2m_version }}
container_name: zigbee2mqtt
restart: unless-stopped
depends_on:
- mosquitto
ports:
- 8080:8080
volumes:
- {{ raspberry_pi_z2m_config_dir }}/data:/app/data
- {{ raspberry_pi_z2m_config_dir }}/configuration.yaml:/app/data/configuration.yaml
- /run/udev:/run/udev:ro
devices:
- /dev/ttyUSB0:/dev/ttyUSB0
environment:
- TZ=Europe/Berlin
group_add:
- dialout
networks:
default:
driver: bridge
name: zigbee2mqtt
```
Save to `roles/raspberry_pi/templates/zigbee2mqtt/docker-compose.yml.j2`.
- [ ] **Commit**
```bash
git add roles/raspberry_pi/templates/
git commit -m "feat(raspberry_pi): add zigbee2mqtt and mosquitto templates"
```
---
### Task 4: Create Zigbee2MQTT deploy task
**Files:**
- Create: `roles/raspberry_pi/tasks/20_zigbee2mqtt.yaml`
- [ ] **Create deploy task file**
```yaml
---
- name: Deploy Mosquitto config
ansible.builtin.template:
src: zigbee2mqtt/mosquitto.conf.j2
dest: "{{ raspberry_pi_mosquitto_config_dir }}/mosquitto.conf"
mode: "0644"
become: true
when: inventory_hostname == 'naruto'
- name: Deploy Zigbee2MQTT config
ansible.builtin.template:
src: zigbee2mqtt/z2m-configuration.yaml.j2
dest: "{{ raspberry_pi_z2m_config_dir }}/configuration.yaml"
mode: "0644"
become: true
notify: restart zigbee2mqtt
when: inventory_hostname == 'naruto'
- name: Deploy docker-compose
ansible.builtin.template:
src: zigbee2mqtt/docker-compose.yml.j2
dest: "{{ raspberry_pi_compose_dir }}/docker-compose.yml"
mode: "0644"
become: true
when: inventory_hostname == 'naruto'
- name: Start Zigbee2MQTT stack
ansible.builtin.command:
cmd: docker compose up -d
chdir: "{{ raspberry_pi_compose_dir }}"
become: true
changed_when: false
when: inventory_hostname == 'naruto'
```
Save to `roles/raspberry_pi/tasks/20_zigbee2mqtt.yaml`.
- [ ] **Commit**
```bash
git add roles/raspberry_pi/tasks/20_zigbee2mqtt.yaml
git commit -m "feat(raspberry_pi): add zigbee2mqtt deploy task"
```
---
### Task 5: Wire up role main.yaml
**Files:**
- Modify: `roles/raspberry_pi/tasks/main.yaml`
- [ ] **Update main.yaml to include task files**
Replace the current contents (`---`) with:
```yaml
---
- name: Setup directories
ansible.builtin.include_tasks: 10_directories.yaml
- name: Setup Zigbee2MQTT
ansible.builtin.include_tasks: 20_zigbee2mqtt.yaml
```
- [ ] **Commit**
```bash
git add roles/raspberry_pi/tasks/main.yaml
git commit -m "feat(raspberry_pi): wire up role tasks"
```
---
### Task 6: Run and verify
- [ ] **Run the playbook**
```bash
ansible-playbook playbooks/raspberry-pi.yaml
```
Expected: all tasks `ok` or `changed` on naruto, no failures. On pi, directory and zigbee2mqtt tasks should be skipped.
- [ ] **Verify containers are running on naruto**
```bash
ansible naruto -a "docker ps --format 'table {{.Names}}\t{{.Status}}'" -b
```
Expected:
```
NAMES STATUS
zigbee2mqtt Up X seconds
mosquitto Up X seconds
```
- [ ] **Check Zigbee2MQTT logs for successful startup**
```bash
ssh naruto "sudo docker logs zigbee2mqtt 2>&1 | tail -20"
```
Expected: lines like `Zigbee2MQTT started!`, no errors about serial port or MQTT connection.
- [ ] **Verify Mosquitto is reachable from the LAN**
```bash
ssh naruto "docker exec mosquitto mosquitto_pub -h localhost -t test -m hello && echo 'OK'"
```
Expected: `OK`
- [ ] **Verify pi tasks were skipped**
Check playbook output shows `skipping: [pi]` for all directory and zigbee2mqtt tasks.

View File

@@ -0,0 +1,82 @@
# Zigbee2MQTT + Mosquitto on naruto — Design Spec
**Date:** 2026-06-03
## Goal
Run Zigbee2MQTT and Mosquitto as Docker containers on naruto, managed by the `raspberry_pi` Ansible role. Home Assistant (running in k3s) connects to Mosquitto over the LAN.
## Hardware
- Host: naruto (Pi 4, 192.168.20.13)
- Zigbee coordinator: SONOFF Dongle Lite MG21 on `/dev/ttyUSB0`
- Stable by-id path: `/dev/serial/by-id/usb-SONOFF_SONOFF_Dongle_Lite_MG21_0263f93f46a2ef11b078926661ce3355-if00-port0`
## Architecture
Two containers via Docker Compose on naruto. Ansible templates all configs and manages the stack. Home Assistant adds the MQTT integration pointing at `192.168.20.13:1883`.
```
[SONOFF Dongle /dev/ttyUSB0]
|
[zigbee2mqtt container]
| MQTT (internal docker network)
[mosquitto container] :1883
|
[Home Assistant in k3s] — via LAN 192.168.20.13:1883
```
## Directory Layout on naruto
```
/opt/docker/
config/
mosquitto/
mosquitto.conf
data/
log/
zigbee2mqtt/
configuration.yaml
data/
compose/
docker-compose.yml
```
## Mosquitto Config
- Listens on port 1883
- No authentication (internal LAN only)
- Persistence enabled, logs to `/opt/docker/config/mosquitto/log/`
## Zigbee2MQTT Config
- Serial port: `/dev/serial/by-id/usb-SONOFF_SONOFF_Dongle_Lite_MG21_0263f93f46a2ef11b078926661ce3355-if00-port0`
- MQTT broker: `mqtt://mosquitto:1883` (internal docker network)
- Network key: stored in `vars/group_vars/raspberry_pi/secrets.yaml` as `vault_raspberry_pi.zigbee2mqtt.network_key`
- Frontend enabled on port 8080 for local device management
## Secrets
`vars/group_vars/raspberry_pi/secrets.yaml` (vault-encrypted, placeholder for now):
```yaml
vault_raspberry_pi:
zigbee2mqtt:
network_key: "YOUR_ZIGBEE_NETWORK_KEY"
```
## Ansible Changes
| Action | Path | Responsibility |
|--------|------|----------------|
| Modify | `roles/raspberry_pi/tasks/main.yaml` | Include numbered task files |
| Create | `roles/raspberry_pi/tasks/10_directories.yaml` | Create `/opt/docker/` tree |
| Create | `roles/raspberry_pi/tasks/20_zigbee2mqtt.yaml` | Template configs, start compose |
| Create | `roles/raspberry_pi/templates/zigbee2mqtt/docker-compose.yml.j2` | Compose file |
| Create | `roles/raspberry_pi/templates/zigbee2mqtt/mosquitto.conf.j2` | Mosquitto config |
| Create | `roles/raspberry_pi/templates/zigbee2mqtt/z2m-configuration.yaml.j2` | Zigbee2MQTT config |
| Create | `vars/group_vars/raspberry_pi/secrets.yaml` | Network key placeholder |
## Host Constraint
The `raspberry_pi` role applies to both naruto and pi. The Zigbee2MQTT tasks must be guarded with `when: inventory_hostname == 'naruto'` since the USB dongle is only on naruto.

View File

@@ -0,0 +1,11 @@
---
- name: Set up Raspberry Pis
hosts: raspberry_pi
gather_facts: true
roles:
- role: common
tags:
- common
- role: raspberry_pi
tags:
- raspberry_pi

View File

@@ -1,4 +1,9 @@
--- ---
- name: Update apt cache
ansible.builtin.apt:
update_cache: true
become: true
- name: Restart sshd - name: Restart sshd
service: service:
name: sshd name: sshd

View File

@@ -2,9 +2,9 @@
- name: Copy bash-configs - name: Copy bash-configs
ansible.builtin.template: ansible.builtin.template:
src: "files/bash/{{ item }}" src: "files/bash/{{ item }}"
dest: "{{ ansible_env.HOME }}/.{{ item }}" dest: "{{ ansible_facts['env']['HOME'] }}/.{{ item }}"
owner: "{{ ansible_user_id }}" owner: "{{ ansible_facts['user_id'] }}"
group: "{{ ansible_user_id }}" group: "{{ ansible_facts['user_id'] }}"
mode: "644" mode: "644"
loop: loop:
- bashrc - bashrc
@@ -13,25 +13,25 @@
- name: Copy ghostty infocmp - name: Copy ghostty infocmp
ansible.builtin.copy: ansible.builtin.copy:
src: files/ghostty/infocmp src: files/ghostty/infocmp
dest: "{{ ansible_env.HOME }}/ghostty" dest: "{{ ansible_facts['env']['HOME'] }}/ghostty"
owner: "{{ ansible_user_id }}" owner: "{{ ansible_facts['user_id'] }}"
group: "{{ ansible_user_id }}" group: "{{ ansible_facts['user_id'] }}"
mode: "0644" mode: "0644"
register: ghostty_terminfo register: ghostty_terminfo
- name: Compile ghostty terminalinfo - name: Compile ghostty terminalinfo
ansible.builtin.command: "tic -x {{ ansible_env.HOME }}/ghostty" ansible.builtin.command: "tic -x {{ ansible_facts['env']['HOME'] }}/ghostty"
when: ghostty_terminfo.changed when: ghostty_terminfo.changed
- name: Copy kitty infocmp - name: Copy kitty infocmp
ansible.builtin.copy: ansible.builtin.copy:
src: files/kitty/infocmp src: files/kitty/infocmp
dest: "{{ ansible_env.HOME }}/kitty" dest: "{{ ansible_facts['env']['HOME'] }}/kitty"
owner: "{{ ansible_user_id }}" owner: "{{ ansible_facts['user_id'] }}"
group: "{{ ansible_user_id }}" group: "{{ ansible_facts['user_id'] }}"
mode: "0644" mode: "0644"
register: kitty_terminfo register: kitty_terminfo
- name: Compile kitty terminalinfo - name: Compile kitty terminalinfo
ansible.builtin.command: "tic -x {{ ansible_env.HOME }}/kitty" ansible.builtin.command: "tic -x {{ ansible_facts['env']['HOME'] }}/kitty"
when: kitty_terminfo.changed when: kitty_terminfo.changed

View File

@@ -14,11 +14,17 @@
become: true become: true
- name: Add Gierens repository to apt sources - name: Add Gierens repository to apt sources
ansible.builtin.apt_repository: ansible.builtin.deb822_repository:
repo: "deb [signed-by=/etc/apt/keyrings/gierens.asc] http://deb.gierens.de stable main" name: gierens
types: deb
uris: http://deb.gierens.de
suites: stable
components: main
signed_by: /etc/apt/keyrings/gierens.asc
state: present state: present
update_cache: true install_python_debian: true
become: true become: true
notify: Update apt cache
- name: Install eza package - name: Install eza package
ansible.builtin.apt: ansible.builtin.apt:
@@ -28,7 +34,7 @@
- name: Install bottom package - name: Install bottom package
ansible.builtin.apt: ansible.builtin.apt:
deb: https://github.com/ClementTsang/bottom/releases/download/0.9.6/bottom_0.9.6_amd64.deb deb: https://github.com/ClementTsang/bottom/releases/download/0.9.6/bottom_0.9.6_{{ arch }}.deb
state: present state: present
become: true become: true
@@ -37,20 +43,21 @@
register: neovim_installed register: neovim_installed
changed_when: false changed_when: false
ignore_errors: true ignore_errors: true
when: ansible_facts['architecture'] != 'aarch64'
- name: Download Neovim AppImage - name: Download Neovim AppImage
ansible.builtin.get_url: ansible.builtin.get_url:
url: https://github.com/neovim/neovim/releases/download/v0.10.0/nvim.appimage url: https://github.com/neovim/neovim/releases/download/v0.10.0/nvim.appimage
dest: /tmp/nvim.appimage dest: /tmp/nvim.appimage
mode: "0755" mode: "0755"
when: neovim_installed.rc != 0 when: ansible_facts['architecture'] != 'aarch64' and neovim_installed.rc != 0
register: download_result register: download_result
- name: Extract Neovim AppImage - name: Extract Neovim AppImage
ansible.builtin.command: ansible.builtin.command:
cmd: "./nvim.appimage --appimage-extract" cmd: "./nvim.appimage --appimage-extract"
chdir: /tmp chdir: /tmp
when: download_result.changed when: ansible_facts['architecture'] != 'aarch64' and download_result.changed
register: extract_result register: extract_result
- name: Copy extracted Neovim files to /usr - name: Copy extracted Neovim files to /usr
@@ -60,19 +67,19 @@
remote_src: true remote_src: true
mode: "0755" mode: "0755"
become: true become: true
when: extract_result.changed when: ansible_facts['architecture'] != 'aarch64' and extract_result.changed
- name: Clean up extracted Neovim files - name: Clean up extracted Neovim files
ansible.builtin.file: ansible.builtin.file:
path: /tmp/squashfs-root path: /tmp/squashfs-root
state: absent state: absent
when: extract_result.changed when: ansible_facts['architecture'] != 'aarch64' and extract_result.changed
- name: Remove Neovim AppImage - name: Remove Neovim AppImage
ansible.builtin.file: ansible.builtin.file:
path: /tmp/nvim.appimage path: /tmp/nvim.appimage
state: absent state: absent
when: download_result.changed when: ansible_facts['architecture'] != 'aarch64' and download_result.changed
- name: Check if Neovim config directory already exists - name: Check if Neovim config directory already exists
ansible.builtin.stat: ansible.builtin.stat:

View File

@@ -5,24 +5,24 @@
upgrade: true upgrade: true
autoremove: true autoremove: true
become: true become: true
when: ansible_user_id != "root" when: ansible_facts['user_id'] != "root"
- name: Install base packages - name: Install base packages
ansible.builtin.apt: ansible.builtin.apt:
name: "{{ common_packages }}" name: "{{ common_packages }}"
state: present state: present
become: true become: true
when: ansible_user_id != "root" when: ansible_facts['user_id'] != "root"
- name: Update and upgrade packages - name: Update and upgrade packages
ansible.builtin.apt: ansible.builtin.apt:
update_cache: true update_cache: true
upgrade: true upgrade: true
autoremove: true autoremove: true
when: ansible_user_id == "root" when: ansible_facts['user_id'] == "root"
- name: Install base packages - name: Install base packages
ansible.builtin.apt: ansible.builtin.apt:
name: "{{ common_packages }}" name: "{{ common_packages }}"
state: present state: present
when: ansible_user_id == "root" when: ansible_facts['user_id'] == "root"

View File

@@ -8,7 +8,7 @@
notify: notify:
- Restart sshd - Restart sshd
become: true become: true
when: ansible_user_id != "root" when: ansible_facts['user_id'] != "root"
- name: Copy root sshd_config - name: Copy root sshd_config
ansible.builtin.template: ansible.builtin.template:
@@ -18,7 +18,7 @@
backup: true backup: true
notify: notify:
- Restart sshd - Restart sshd
when: ansible_user_id == "root" when: ansible_facts['user_id'] == "root"
- name: Copy pubkey - name: Copy pubkey
ansible.builtin.copy: ansible.builtin.copy:

View File

@@ -3,12 +3,12 @@
community.general.timezone: community.general.timezone:
name: "{{ timezone }}" name: "{{ timezone }}"
become: true become: true
when: ansible_user_id != "root" when: ansible_facts['user_id'] != "root"
- name: Set timezone - name: Set timezone
community.general.timezone: community.general.timezone:
name: "{{ timezone }}" name: "{{ timezone }}"
when: ansible_user_id == "root" when: ansible_facts['user_id'] == "root"
- name: Configure NTP servers for systemd-timesyncd - name: Configure NTP servers for systemd-timesyncd
ansible.builtin.lineinfile: ansible.builtin.lineinfile:
@@ -24,11 +24,11 @@
enabled: true enabled: true
state: started state: started
become: true become: true
when: ansible_user_id != "root" when: ansible_facts['user_id'] != "root"
- name: Enable and start systemd-timesyncd - name: Enable and start systemd-timesyncd
ansible.builtin.systemd: ansible.builtin.systemd:
name: systemd-timesyncd name: systemd-timesyncd
enabled: true enabled: true
state: started state: started
when: ansible_user_id == "root" when: ansible_facts['user_id'] == "root"

View File

@@ -0,0 +1,7 @@
---
raspberry_pi_docker_base: /opt/docker
raspberry_pi_mosquitto_config_dir: "{{ raspberry_pi_docker_base }}/config/mosquitto"
raspberry_pi_z2m_config_dir: "{{ raspberry_pi_docker_base }}/config/zigbee2mqtt"
raspberry_pi_compose_dir: "{{ raspberry_pi_docker_base }}/compose/zigbee2mqtt"
raspberry_pi_mosquitto_version: "2"
raspberry_pi_z2m_version: "2"

View File

@@ -0,0 +1,6 @@
---
- name: Restart zigbee2mqtt
ansible.builtin.command:
cmd: docker compose restart zigbee2mqtt
chdir: "{{ raspberry_pi_compose_dir }}"
listen: restart zigbee2mqtt

View File

@@ -0,0 +1,34 @@
---
- name: Create docker base directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: "0755"
become: true
loop:
- "{{ raspberry_pi_docker_base }}"
- "{{ raspberry_pi_compose_dir }}"
when: inventory_hostname == 'naruto'
- name: Create Mosquitto directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: "0755"
become: true
loop:
- "{{ raspberry_pi_mosquitto_config_dir }}"
- "{{ raspberry_pi_mosquitto_config_dir }}/data"
- "{{ raspberry_pi_mosquitto_config_dir }}/log"
when: inventory_hostname == 'naruto'
- name: Create Zigbee2MQTT directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: "0755"
become: true
loop:
- "{{ raspberry_pi_z2m_config_dir }}"
- "{{ raspberry_pi_z2m_config_dir }}/data"
when: inventory_hostname == 'naruto'

View File

@@ -0,0 +1,40 @@
---
- name: Install docker-compose-plugin
ansible.builtin.apt:
name: docker-compose-plugin
state: present
become: true
when: inventory_hostname == 'naruto'
- name: Deploy Mosquitto config
ansible.builtin.template:
src: zigbee2mqtt/mosquitto.conf.j2
dest: "{{ raspberry_pi_mosquitto_config_dir }}/mosquitto.conf"
mode: "0644"
become: true
when: inventory_hostname == 'naruto'
- name: Deploy Zigbee2MQTT config
ansible.builtin.template:
src: zigbee2mqtt/z2m-configuration.yaml.j2
dest: "{{ raspberry_pi_z2m_config_dir }}/configuration.yaml"
mode: "0644"
become: true
notify: restart zigbee2mqtt
when: inventory_hostname == 'naruto'
- name: Deploy docker-compose
ansible.builtin.template:
src: zigbee2mqtt/docker-compose.yml.j2
dest: "{{ raspberry_pi_compose_dir }}/docker-compose.yml"
mode: "0644"
become: true
when: inventory_hostname == 'naruto'
- name: Start Zigbee2MQTT stack
ansible.builtin.command:
cmd: docker compose up -d
chdir: "{{ raspberry_pi_compose_dir }}"
become: true
changed_when: false
when: inventory_hostname == 'naruto'

View File

@@ -0,0 +1,6 @@
---
- name: Setup directories
ansible.builtin.include_tasks: 10_directories.yaml
- name: Setup Zigbee2MQTT
ansible.builtin.include_tasks: 20_zigbee2mqtt.yaml

View File

@@ -0,0 +1,36 @@
name: zigbee2mqtt
services:
mosquitto:
image: eclipse-mosquitto:{{ raspberry_pi_mosquitto_version }}
container_name: mosquitto
restart: unless-stopped
ports:
- 1883:1883
volumes:
- {{ raspberry_pi_mosquitto_config_dir }}/mosquitto.conf:/mosquitto/config/mosquitto.conf:ro
- {{ raspberry_pi_mosquitto_config_dir }}/data:/mosquitto/data
- {{ raspberry_pi_mosquitto_config_dir }}/log:/mosquitto/log
zigbee2mqtt:
image: koenkk/zigbee2mqtt:{{ raspberry_pi_z2m_version }}
container_name: zigbee2mqtt
restart: unless-stopped
depends_on:
- mosquitto
ports:
- 8081:8080
volumes:
- {{ raspberry_pi_z2m_config_dir }}/data:/app/data
- {{ raspberry_pi_z2m_config_dir }}/configuration.yaml:/app/data/configuration.yaml
- /run/udev:/run/udev:ro
devices:
- /dev/ttyUSB0:/dev/ttyUSB0
environment:
- TZ=Europe/Berlin
group_add:
- dialout
networks:
default:
driver: bridge
name: zigbee2mqtt

View File

@@ -0,0 +1,5 @@
listener 1883
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
allow_anonymous true

View File

@@ -0,0 +1,17 @@
homeassistant:
enabled: true
mqtt:
server: mqtt://mosquitto:1883
serial:
port: /dev/ttyUSB0
adapter: ember
advanced:
network_key: {{ vault_raspberry_pi.zigbee2mqtt.network_key }}
log_level: info
frontend:
enabled: true
port: 8080

View File

@@ -19,7 +19,7 @@ nfs_server: 192.168.20.12
# Packages # Packages
# #
arch: "{{ 'arm64' if ansible_architecture == 'aarch64' else 'amd64' }}" arch: "{{ 'arm64' if ansible_facts['architecture'] == 'aarch64' else 'amd64' }}"
netcup_api_key: "{{ vault_netcup.api_key }}" netcup_api_key: "{{ vault_netcup.api_key }}"
netcup_api_password: "{{ vault_netcup.api_password }}" netcup_api_password: "{{ vault_netcup.api_password }}"

View File

@@ -0,0 +1,3 @@
vault_raspberry_pi:
zigbee2mqtt:
network_key: "GENERATE"

View File

@@ -0,0 +1 @@
---

View File

@@ -3,7 +3,6 @@
[k3s:children] [k3s:children]
k3s_server k3s_server
k3s_agent k3s_agent
k3s_storage
k3s_loadbalancer k3s_loadbalancer
[k3s_server] [k3s_server]

3
vars/raspberry_pi.ini Normal file
View File

@@ -0,0 +1,3 @@
[raspberry_pi]
naruto
pi