-
Notifications
You must be signed in to change notification settings - Fork 19
/
main.yml
275 lines (229 loc) · 7.97 KB
/
main.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
---
- name: Expand "layout" variable
set_fact:
layout_n: "{{ layout_n|default([]) + _layout_n|list }}"
loop: "{{ layout | selectattr('device', 'defined') | list }}"
vars:
_layout_n: |-
{%- for _item in ([item.device] if item.device is string else item.device) -%}
{{ item | combine({'device': _item}) }},
{%- endfor -%}
- name: Update "layout" variable
when: layout_n | selectattr('device', 'defined') | list | length > 0
set_fact:
layout: "{{ layout_n }}"
- name: Get disks sizes, logical and physical sectors sizes
command: "lsblk -d -b -O --json {{ layout | selectattr('device', 'defined') | map(attribute='device') | list | join(' ') }}"
check_mode: no
register: _cmd_lsblk_result
- name: Calculate some disks attributes
when: _cmd_lsblk_result.rc is defined and _cmd_lsblk_result.rc | int == 0
set_fact:
device_attrs: "{{
device_attrs|default([])
| union([{'device': '/dev/' + item['name'],
'devsz_b': item['size'],
'lbsz_b': item['log-sec'],
'pbsz_b': item['phy-sec'],
'last_usable_sector_s': item['size']|int / item['log-sec']|int - _efi_label_size_s,
'offset_s': 2048 if item['phy-sec']|int == 512 else (4096 if item['phy-sec']|int == 4096 else 0)}
])
}}"
vars:
_efi_label_size_s: 34
loop: "{{ _cmd_lsblk_result.stdout | from_json | dict2items | selectattr('value','defined') | map(attribute='value') | flatten(levels=1) }}"
loop_control:
label: "{{ item.name }}"
- name: Combine disks layouts with disks attributes
when: item.0.device == item.1.device
set_fact:
layout_w_attrs: "{{ layout_w_attrs|default([]) | union([item.0 | combine(item.1)]) }}"
loop: "{{ layout|sort(attribute='device') | zip(device_attrs|sort(attribute='device')) | list }}"
- name: Check EFI system
when: use_efi
stat:
path: /sys/firmware/efi
register: _stat_efi
- name: Check EFI mount point
when: use_efi and _stat_efi.stat.exists
set_fact:
_efi_mountpoint: "{{ layout
| selectattr('partitions', 'defined')
| sum(attribute='partitions', start=[])
| selectattr('mount', 'defined')
| selectattr('mount', 'eq', '/boot/efi')
| map(attribute='mount')
| list
| first
| default(False) }}"
- name: Disable efi if there is no EFI partition
set_fact:
use_efi: False
when: use_efi and _efi_mountpoint|default(False) == False
- name: Cursory variable check
include_tasks: sanity.yml
- name: Check raw partition encryption
set_fact:
_encrypt: "{{ layout
| selectattr('partitions', 'defined')
| sum(attribute='partitions', start=[])
| selectattr('encrypt', 'defined')
| map(attribute='encrypt')
| list
| first
| default(False) }}"
- name: Check raid partition encryption
when: md is defined and not _encrypt
set_fact:
_encrypt: "{{ md
| selectattr('encrypt', 'defined')
| map(attribute='encrypt')
| list
| first
| default(False) }}"
- name: Install newest debootstrap from impish
apt:
deb: http://de.archive.ubuntu.com/ubuntu/pool/main/d/debootstrap/debootstrap_1.0.124_all.deb
when: ansible_distribution_release != "impish" and release == "impish"
- name: Install global dependencies
apt:
name: "{{ dependencies.global }}"
state: latest
update_cache: yes
cache_valid_time: "{{ debian_cache_valid_time|default(7200) }}"
- name: check if already bootstrapped
stat:
path: "{{ dbstrp_mountpoint }}/root/.bootstrap_complete"
register: _stat_mount
- set_fact:
bootstrapped: "{{ _stat_mount.stat.exists }}"
bootstrapped_in_chroot: "{{ _stat_mount.stat.exists }}"
- name: check if already bootstrapped
stat:
path: "/root/.bootstrap_complete"
register: _stat_local
- set_fact:
bootstrapped: "{{ _stat_local.stat.exists }}"
bootstrapped_in_chroot: "{{ _stat_local.stat.exists }}"
- block:
- name: print keys
command: ssh-add -L
delegate_to: localhost
become: no
changed_when: no
register: _local_keys
- fail:
msg: "No keys in ssh-agent, please add your keys to the agent"
when: _local_keys.stdout == ""
- name: copy keys
set_fact:
dbstrp_ssh_keys: "{{ _local_keys.stdout_lines }}"
delegate_to: localhost
become: no
when: dbstrp_ssh_keys is not defined
- block:
# This may fail when buster-backports isn't enabled as repository, however
# this is preferable to debootstrap failing later. This works on the Hetzner
# rescue system which is a common use case for this author
- name: Install debootstrap from buster-backports when on buster and eoan
apt:
name: debootstrap
state: latest
default_release: buster-backports
cache_valid_time: "{{ debian_cache_valid_time|default(7200) }}"
update_cache: yes
when: ansible_distribution_release == 'buster' and release == 'eoan'
- name: create list of target devices
set_fact:
_target_devices: "{{ _target_devices + [item.device] }}"
with_items: "{{ layout }}"
- name: wipe devices
include_tasks: wipe.yml
when: wipe|default('') == "ABSOLUTELY"
- name: create mountpoint
file:
state: directory
path: "{{ dbstrp_mountpoint }}"
- name: create debootstrap user
include_tasks: user.yml
vars:
_tgt_user: no
- name: chroot user via ssh
blockinfile:
path: "/etc/ssh/sshd_config"
state: present
block: >
Match user {{ dbstrp_user['name'] }}
ChrootDirectory {{ dbstrp_mountpoint }}
AuthorizedKeysFile {{ dbstrp_mountpoint }}/home/debootstrap/.ssh/authorized_keys
register: _ssh_config
- name: restart sshd
service:
name: ssh
state: restarted
when: _ssh_config.changed
- name: set mountpoint
set_fact:
_tgt_root: "{{ dbstrp_mountpoint }}"
_mktemp: None
- name: Partition Devices
include_tasks: partitions.yml
- name: Create MD Devices
include_tasks: md.yml
when: md is defined and md|count > 0
- name: encrypt devices
include_tasks: encryption.yml
when: _encrypt
- name: Create logical volumes
include_tasks: lvm.yml
when: lvm is defined and lvm|count > 0
- name: Create filesystems
include_tasks: fs.yml
- name: Create and mount ZFS pools
include_tasks: zfs.yml
when: zfs_pool is defined and zfs_fs is defined
- name: mount filesystems
include_tasks: mount.yml
- name: run bootstrap
include_tasks: bootstrap.yml
- name: configure system
include_tasks: configure.yml
- name: create debootstrap user on target
include_tasks: user.yml
vars:
_tgt_user: yes
- name: create ssh directory for bootstrap user
file:
state: directory
path: "{{ dbstrp_mountpoint }}/home/{{ dbstrp_user['name'] }}/.ssh"
owner: "{{ dbstrp_user['name'] }}"
- name: create ssh directory for bootstrap user on host
file:
state: directory
path: "/tmp/.debootstrap-ssh"
owner: "{{ dbstrp_user['name'] }}"
mode: 0700
- name: setup keys for bootstrap user
authorized_key:
key: "{{ item }}"
path: "{{ dbstrp_mountpoint }}/home/{{ dbstrp_user['name'] }}/.ssh/authorized_keys"
user: "{{ dbstrp_user['name'] }}"
with_items: "{{ dbstrp_ssh_keys }}"
- name: allow sudo for debootstrap user
copy:
dest: "{{ dbstrp_mountpoint }}/etc/sudoers.d/{{ dbstrp_user['name'] }}"
owner: root
group: root
mode: 0440
content: "{{ dbstrp_user['name'] }} ALL=(ALL) NOPASSWD:ALL"
- name: mark as bootstrapped
copy:
dest: "/root/.bootstrap_complete"
content: ""
owner: root
group: root
mode: 0600
- name: register bootstrapped fact
set_fact:
bootstrapped: yes
when: not bootstrapped or wipe|default('') == "ABSOLUTELY"