-
Notifications
You must be signed in to change notification settings - Fork 5
/
rpi.yml
281 lines (256 loc) · 10.2 KB
/
rpi.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# Configures the Raspberry Pi that handles my home automation
#
# It assumes my user has already been created by rpi_provisioning.yml
- hosts: raspberrypi
remote_user: "{{ admin_user }}"
become: yes
vars:
admin_user: chesterbr
admin_email: [email protected]
external_hostname: chesterbr.duckdns.org
backup_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
32333432316339373564633937666663323762323834356135396163343361653732346637386365
3266636330393331636436393936633035383539616535390a306163346136353464636366373938
34626237613062626636653366346363653662393439613839363661376235363162643939346332
3265386661626665360a666662336663363265383066623439323061623737336439366335393032
37323364626232333262663065666430386436336161633565353963663263336537323863623361
34333136323362343562623338396537363531343530366236323666356536386363316638323038
66326134636339393761336337633731636631613030386438303230323965653333383239356339
63643530626335636561633238316630373665393438633861356563306434613462663665346666
61313535626434633164356430383135386533613231346566373536323934623364326166396364
37623030636230393637666636383839633461356235656462616132666264333663656435326334
376631333062666237336238303630623033
duckdns_token: !vault |
$ANSIBLE_VAULT;1.1;AES256
30626238633131363461363936396234316334306531623366393931663433313065396330343437
3635386336633039663232393165336334316665663533640a366564663366313662636532376530
35363032326132636432386434333831363733346363626436396361396261306265393030666238
6261613764323161320a623239396135663163306438613839326638626236336161323932373335
31653637393635376165653064336565306262303332303432376638633365626431663637636566
3464623366386333636231663736383932623865336663656531
handlers:
- name: restart ssh
service: name=ssh state=restarted
- name: restart dns
service: name=dnsmasq state=restarted
- name: restart unattended-upgrades
service: name=unattended-upgrades state=restarted
- name: reboot
reboot:
tasks:
- name: Add my user to all groups that pi normally belongs to
user:
name: "{{ admin_user }}"
groups: pi,adm,dialout,cdrom,sudo,audio,video,plugdev,games,users,input,netdev,gpio,i2c,spi
append: yes
- name: Update packages info (if older than a couple days)
apt: update_cache=yes cache_valid_time=7200
- name: Install general utilities
apt: name={{ packages }} state=present
tags: apt
vars:
packages:
- git # Required for Ansible git (and for life, IMHO).
- python-setuptools # Required for Ansible pip ¯\_(ツ)_/¯
- aptitude # I don't use it, but Ansible seems to.
- python3-gpiozero # Provides pinout (and I ❤️ pinout).
- libudev-dev # Not 100% sure, but Home Assistant +
- libopenzwave1.5-dev # ZWave seems to require these two.
- name: Install fail2ban.
tags: fail2ban
block:
- apt: name=fail2ban,sendmail state=present
- copy:
src: templates/jail.local.j2
dest: /etc/fail2ban/jail.local
owner: root
group: root
mode: 0644
- service: name=fail2ban state=started enabled=yes
- name: Update SSH configuration to be more secure (no password/root logins).
lineinfile:
dest: "/etc/ssh/sshd_config"
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
state: present
with_items:
- regexp: "^PasswordAuthentication"
line: "PasswordAuthentication no"
- regexp: "^PermitRootLogin"
line: "PermitRootLogin no"
notify: restart ssh
# Uncomment if you don't want the local pi user
# - name: Drop the pi user (we don't need it and can't even use it remotely at this point)
# user: name=pi state=absent remove=yes
- name: Install unattended upgrades package and dependencies.
apt: name={{ packages }} state=present
vars:
packages:
- unattended-upgrades
- apt-listchanges
- bsd-mailx
- name: Configure dnsmasq with a custom entry (so my phone can find the dynamic hostname)
tags: dns
block:
- apt: name={{ packages }} state=present
vars:
packages:
- dnsmasq
- dnsutils
- lineinfile:
dest: "/etc/dnsmasq.conf"
line: "address=/{{ external_hostname }}/{{ hostvars[inventory_hostname]['ansible_default_ipv4']['address'] }}"
state: present
notify: restart dns
- name: Updated unattended-upgrades config to reboot if needed,
auto-fix, reboot time, email, etc
lineinfile:
dest: "/etc/apt/apt.conf.d/50unattended-upgrades"
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
state: present
with_items:
- regexp: "(\/\/)? ?Unattended-Upgrade::AutoFixInterruptedDpkg \""
line: Unattended-Upgrade::AutoFixInterruptedDpkg "true";
- regexp: "(\/\/)? ?Unattended-Upgrade::MinimalSteps \""
line: Unattended-Upgrade::MinimalSteps "true";
- regexp: "(\/\/)? ?Unattended-Upgrade::Automatic-Reboot \""
line: Unattended-Upgrade::Automatic-Reboot "true";
- regexp: "(\/\/)? ?Unattended-Upgrade::Automatic-Reboot-Time \""
line: Unattended-Upgrade::Automatic-Reboot-Time "02:00";
- regexp: "(\/\/)? ?Unattended-Upgrade::Mail \""
line: Unattended-Upgrade::Mail "{{ admin_email }}";
- regexp: "(\/\/)? ?Unattended-Upgrade::MailOnlyOnError \""
line: Unattended-Upgrade::MailOnlyOnError "false";
- regexp: "(\/\/)? ?Unattended-Upgrade::Remove-Unused-Dependencies \""
line: Unattended-Upgrade::Remove-Unused-Dependencies "true";
notify: restart unattended-upgrades
- name: (Re)configure firewall (ufw)
tags: firewall
block:
- apt: name=ufw state=present
- ufw: rule=allow port={{ item }}
with_items:
- "22" # ssh
- "53" # dns (dnsmasq, see below)
- "80" # http (mostly to generate/renew certs)
- "443" # https (mostly to generate/renew certs)
- "1883" # mqtt
- "8883" # mqtt ssl (not sure whether mqtt is using ssl, let's open both)
- "8123" # Home Assistant
- ufw: state=enabled policy=reject direction=incoming
- name: Install certbot (so we can have letsencrypt ssl certificates)
apt: name=certbot state=present
- name: Create script that generates/renews/copies certificates as needed
template:
src: templates/update_and_copy_certificates.sh.j2
dest: /root/update_and_copy_certificates.sh
owner: root
mode: 0700
- name: Configure dynamic DNS provider (DuckDNS)
block:
- template:
src: templates/duck.sh.j2
dest: /root/duck.sh
mode: 0700
- cron:
name: Refresh DuckDNS address
minute: "*/5"
job: /root/duck.sh
- name: Run the script once (so we have certificates to play with)
command: bash -lc "/root/update_and_copy_certificates.sh"
args:
creates: /home/{{ admin_user }}/privkey.pem
- name: Schedule certbot to rebuild the certs when needed \
(and copy/fix perms so HomeAssistant can use them)
cron:
name: Update ssl certificates
minute: "0"
hour: "4"
job: /root/update_and_copy_certificates.sh
- name: Install packages required for Bluetooth
apt: name={{ packages }} state=present
vars:
packages:
- bluetooth
- bluez
- bluez-firmware
- libbluetooth-dev
- name: Install Mosquitto (MQTT broker used by RF/IR) and its clients
apt: name={{ packages }} state=present
vars:
packages:
- mosquitto
- mosquitto-clients
- name: Configure Home Assistant backups
block:
- copy:
content: "{{ backup_password }}"
dest: /home/{{ admin_user }}/.backup-password
become: no
- template:
src: templates/ha-backup.sh.j2
dest: /home/{{ admin_user }}/ha-backup.sh
mode: 0700
become: no
- cron:
name: Backup homeassistant configs
minute: "0"
hour: "3"
user: "{{ admin_user }}"
job: /home/{{ admin_user }}/ha-backup.sh
- name: Configure the Raspberry Pi camera
tags: camera
block:
# yes, 0=enabled for all things here ¯\_(ツ)_/¯
# see: https://github.com/BretStateham/headlesspi#enable-ssh--vnc
- command: bash -lc "raspi-config nonint do_camera 0"
notify: reboot
# This doesn't seem to work anymore. I'll let it here as
# a placeholder, in case I ever find a solution
# - lineinfile:
# dest: "/boot/config.txt"
# regexp: "^disable_camera_led="
# line: "disable_camera_led=0"
- name: Check if Home Assistant (config) is present...
stat:
path: /home/{{ admin_user }}/.homeassistant
register: homeassistant_config
- name: ...if not, restore config from backup and install Home Assistant \
(on a virtualenv, on my user, with configs from backup)
when: homeassistant_config.stat.exists == false
block:
- command: bash -lc "./ha-backup.sh restore"
args:
chdir: /home/{{ admin_user }}
creates: /home/{{ admin_user }}/.homeassistant
become: no
- apt: name={{ packages }} state=present
vars:
packages:
- python3-pip
- python3-venv
- build-essential
- libssl-dev
- libffi-dev
- python3-dev
- pip:
name: virtualenv
executable: pip3
- pip:
name:
- wheel
- homeassistant
virtualenv: /home/{{ admin_user }}/homeassistant
become: no
- template:
src: templates/homeassistant.service.j2
dest: /lib/systemd/system/homeassistant.service
mode: 0644
- systemd:
daemon_reload: yes
name: homeassistant.service
enabled: true
state: stopped
notify: reboot