-
Notifications
You must be signed in to change notification settings - Fork 0
/
playbook.yaml
406 lines (370 loc) · 12.7 KB
/
playbook.yaml
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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
- name: System setup
hosts: all
tags: system
gather_facts: False # Not using facts
vars:
user: 'debian'
tasks:
# Accept some user preferences through SSH
- name: Configure SSH AcceptEnv
lineinfile:
dest: "/etc/ssh/sshd_config"
regexp: "^AcceptEnv.*$"
line: "AcceptEnv LANG LC_* GIT_* EDITOR"
insertafter: "EOF"
state: present
notify:
- Restart sshd
# Allow using git through sudo
- name: Configure sudo env_keep
ansible.builtin.copy:
dest: '/etc/sudoers.d/env_keep'
src: './files/sudoers_env_keep'
- name: Set timezone
community.general.timezone:
name: Europe/Amsterdam
# Timesync is needed for apt to verify signatures. Timesync only
# works if systemd-networkd does not have offline status (so does
# not work if adding a manual route).
- name: Enable NTP timesync
# Only needed on bbb, Armbian uses chrony instead of timesyncd and
# has it enabled by default.
when: board == "beagleboneblack"
# Normally you would use timedatectl set-ntp yes, but this enables
# a service underwater, so do that directly so ansible can see if
# it is already done or not. The service name is taken from
# /usr/lib/systemd/ntp-units.d/*.list normally, see the
# systemd-timedated.service manpage.
ansible.builtin.service:
name: systemd-timesyncd
enabled: true
state: started
- name: Update apt cache if old
ansible.builtin.apt:
update_cache: true
cache_valid_time: 3600
- name: Install useful packages
ansible.builtin.apt:
pkg:
- vim
- tig
- git
- avahi-daemon
- name: Install resolved packages
# Beaglebone uses Google DNS by default, installing resolved
# ensures local DNS is used. Armbian uses NetworkManager by
# default, which uses local DNS by default already.
when: board == "beagleboneblack"
ansible.builtin.apt:
pkg:
- systemd-resolved
# Ensure that git pushes always use SSH instead of HTTPS (to be used
# along with SSH agent forwarding)
- name: Configure git SSH push
community.general.git_config:
name: '[email protected]:.pushInsteadOf'
value: 'https://github.com/'
- name: Configure user authorized keys
ansible.builtin.copy:
dest: '/home/{{ user }}/.ssh/'
src: './files/authorized_keys'
- name: Configure root authorized keys
ansible.builtin.copy:
dest: '/root/.ssh/'
src: './files/authorized_keys'
- name: Allow passwordless sudo
community.general.sudoers:
name: passwordless
state: present
user: "{{ user }}"
commands: ALL
nopassword: true
- name: Disable user password
ansible.builtin.user:
name: "{{ user }}"
password_lock: true
- name: Disable root password
ansible.builtin.user:
name: "{{ user }}"
password_lock: true
- name: Set the hostname
ansible.builtin.hostname:
name: "{{ inventory_hostname }}"
- name: Replace localhost entry ipv4
ansible.builtin.lineinfile:
path: /etc/hosts
regexp: '^127\.0\.0\.1\s'
line: "127.0.0.1 {{ inventory_hostname }}"
- name: Replace localhost entry ipv6
ansible.builtin.lineinfile:
path: /etc/hosts
regexp: '^::1 '
line: "::1 {{ inventory_hostname }}"
handlers:
- name: Restart sshd
ansible.builtin.service:
name: sshd
state: restarted
- name: Set up doorlockd-client
hosts: locks:testing
tags: client
gather_facts: False # Not using facts
vars:
client_dir: /opt/doorlockd-client
run_dir: '{{ client_dir }}/run'
cert: '{{ client_dir }}/client.pem'
user: 'debian'
group: 'debian'
backend_url: 'https://lock-backend.lan'
server_ssl_fingerprint: 'bbecbb85dd6b5e55ed69eab39147c3572d4f43a8f6c9e32dc46d836a00a07a45'
tasks:
- name: Checkout doorlockd-client
ansible.builtin.git:
repo: https://github.com/doorlockd/doorlockd-client.git
version: b42e0a88eebeab88db223666aa08806093897bfb
dest: '{{ client_dir }}'
- name: Configure UART devicetree
when: board == "beagleboneblack"
lineinfile:
dest: "/boot/uEnv.txt"
regexp: "^#?dtb_overlay=.*$"
line: "dtb_overlay=BB-UART2-00A0.dtbo"
insertafter: "EOF"
state: present
- name: Copy UART devicetree
when: board == "rockpi-s"
ansible.builtin.copy:
dest: '/root/'
src: './files/rockpi-s-enable-uart2.dts'
register: copy_uart_dt
- name: Install UART devicetree
when: (board == "rockpi-s") and copy_uart_dt.changed
command: "armbian-add-overlay {{ copy_uart_dt.dest }}"
# This allows gpiod control of pullup and pulldown for selected pins
# Needed until a more general fix is applied in the beaglebone
# image, see https://openbeagle.org/beagleboard/BeagleBoard-DeviceTrees/-/merge_requests/71
- name: Copy GPIO bias fix devicetree
when: board == "beagleboneblack"
ansible.builtin.copy:
dest: '/root/'
src: './files/bbb-gpio-bias-fix.dts'
register: copy_gpio_bias_dt
- name: Compile GPIO bias fix devicetree
when: (board == "beagleboneblack") and copy_gpio_bias_dt.changed
# This hardcodes the kernel dirname, but if it does not exist this
# fails, which is good enough for now
command: dtc -@ -Hepapr -I dts -O dtb -o /boot/dtbs/5.10.168-ti-r72/overlays/bbb-gpio-bias-fix.dtbo /root/bbb-gpio-bias-fix.dts
- name: Enable GPIO bias fix devicetree
when: board == "beagleboneblack"
lineinfile:
dest: "/boot/uEnv.txt"
regexp: "^#?uboot_overlay_addr4=.*$"
line: "uboot_overlay_addr4=bbb-gpio-bias-fix.dtbo"
insertafter: "EOF"
state: present
- name: Setup GPIO permissions
when: board == "rockpi-s"
ansible.builtin.copy:
dest: /etc/udev/rules.d/99-gpio-permissions.rules
content: SUBSYSTEM=="gpio", ACTION=="add", GROUP="plugdev", MODE="0660"
- name: Install apt dependencies
ansible.builtin.apt:
pkg:
- python3-poetry
- python3-dev
notify:
- Restart doorlockd-client
- name: Install python dependendencies
become: true
become_user: '{{ user }}'
ansible.builtin.command:
cmd: poetry install --only=main --no-root --extras "gpiod nfcpy"
chdir: '{{ client_dir }}'
register: poetry_result
changed_when: ("No dependencies to install or update" not in poetry_result.stdout)
notify:
- Restart doorlockd-client
- name: Create run dir
ansible.builtin.file:
state: 'directory'
path: '{{ run_dir }}'
owner: '{{ user }}'
group: '{{ group }}'
mode: 'u=rwx,g=,o='
- name: Generate certificate
ansible.builtin.command:
creates: '{{ cert }}'
cmd: '{{ client_dir }}/tools/gencert.sh "{{ cert }}"'
- name: Certificate permissions
ansible.builtin.file:
path: '{{ cert }}'
owner: root
group: '{{ group }}'
mode: 'u=rw,g=r'
- name: Copy config
vars:
src_file: './files/client-config/{{ inventory_hostname }}.ini'
# Skip this step if no config file is available (e.g. for test hosts)
when: src_file is file
ansible.builtin.template:
dest: '{{ client_dir }}/config.ini'
src: '{{ src_file }}'
notify:
- Restart doorlockd-client
- name: Install systemd service
ansible.builtin.template:
dest: '/etc/systemd/system/'
src: './files/doorlockd-client.service'
notify:
- Reload systemd
- name: Enable service
ansible.builtin.service:
name: doorlockd-client.service
enabled: true
handlers:
- name: Reload systemd
command: /usr/bin/systemctl daemon-reload
- name: Restart doorlockd-client
ansible.builtin.service:
name: doorlockd-client
state: restarted
- name: Set up backend
hosts: backends:testing
tags: backend
gather_facts: False # Not using facts
vars:
django_dir: /opt/doorlockd-backend
run_dir: '{{ django_dir }}/run'
user: 'debian'
group: 'debian'
tasks:
- name: Checkout doorlockd-backend
ansible.builtin.git:
repo: https://github.com/doorlockd/doorlockd-backend.git
version: 5dc555f85adcc054b38c0fba28e11f7c314a2d80
dest: '{{ django_dir }}'
- name: Install apt dependencies
ansible.builtin.apt:
pkg:
- python3-poetry
- nginx
- ssl-cert # Autogenerates a self-signed certificate (called "snakeoil")
- name: Install python dependendencies
become: true
become_user: '{{ user }}'
ansible.builtin.command:
cmd: poetry install --only=main
chdir: '{{ django_dir }}'
register: poetry_result
changed_when: ("No dependencies to install or update" not in poetry_result.stdout)
- name: Install systemd socket
ansible.builtin.copy:
dest: '/etc/systemd/system/'
src: './files/doorlockd-backend.socket'
notify:
- Reload systemd
- name: Install systemd service
ansible.builtin.template:
dest: '/etc/systemd/system/'
src: './files/doorlockd-backend.service'
notify:
- Reload systemd
- name: Enable socket
ansible.builtin.service:
name: doorlockd-backend.socket
enabled: true
state: started
# The socket will ensure django is auto-started, but start it
# automatically to prevent a big startup delay on the first request
- name: Enable service
ansible.builtin.service:
name: doorlockd-backend.service
enabled: true
state: started
- name: Create run dir
ansible.builtin.file:
state: 'directory'
path: '{{ run_dir }}'
# Restrict datadir, so we can put root-owned world-readable
# files (e.g. client.pem) inside that will be read-only for the
# lock-client
owner: '{{ user }}'
group: '{{ group }}'
mode: 'u=rwx'
- name: Run migrations
# Run as unprivileged user to ensure db access happens correctly
become: true
become_user: '{{ user }}'
ansible.builtin.command:
cmd: poetry run ./manage.py migrate
chdir: '{{ django_dir }}'
register: migrations_result
changed_when: ("No migrations to apply" not in migrations_result.stdout)
notify:
- Restart gunicorn
- name: Collect static files
become: true
become_user: '{{ user }}'
ansible.builtin.command:
cmd: poetry run ./manage.py collectstatic --no-input
chdir: '{{ django_dir }}'
register: collect_static_result
changed_when: ("0 static files copied to" not in collect_static_result.stdout)
notify:
- Restart gunicorn
- name: Install nginx config
ansible.builtin.template:
dest: '/etc/nginx/sites-available/default'
src: './files/nginx-vhost'
notify:
- Reload nginx
handlers:
- name: Reload systemd
command: /usr/bin/systemctl daemon-reload
- name: Reload nginx
ansible.builtin.service:
name: nginx
state: reloaded
- name: Restart gunicorn
ansible.builtin.service:
name: doorlockd-backend
state: restarted
# Run these based on tags, e.g.: ansible-playbook -i inventory.yaml playbook.yaml --tags enable_emmc --limit hostname
- name: Utilities
hosts: all
gather_facts: False # Not using facts
tasks:
- name: Enable default route over usb0 network (until reboot)
ansible.builtin.copy:
dest: "/run/systemd/network/usb0.network.d/"
src: "./files/usb0-outward-route.network.conf"
when: board == "beagleboneblack"
tags: [never, usb_route]
notify:
- Reload networkd
- name: Reboot system
tags: [never, reboot]
command: /usr/sbin/shutdown -r now
handlers:
- name: Reload networkd
command: /usr/bin/networkctl reload
- name: Flash to EMMC
hosts: all
tags: [never, flash_emmc]
gather_facts: False # Not using facts
vars:
flasher_script: /usr/sbin/init-beagle-flasher
tasks:
- name: Check flasher script exists
ansible.builtin.file:
state: file
path: "{{ flasher_script }}"
when: board == "beagleboneblack"
- name: Configure flasher as init
ansible.builtin.lineinfile:
path: /boot/uEnv.txt
line: "cmdline=init={{ flasher_script }}"
- name: Disable SSH host key regeneration
ansible.builtin.lineinfile:
path: /boot/SOC.sh
line: disable_ssh_regeneration=true