Two plays: bootstrap as the provider account (ubuntu, over bootstrap.pem), then everything else as the user that first play just created. The split is forced rather than stylistic -- the second play logs in as that user, so its authorized_keys entry and its NOPASSWD sudoers entry both have to exist before it starts. That is why the key tasks live in the 'user' role and 'wheel' runs in the first play: move either into play 2 and it fails with an auth error or "Missing sudo password". Both accounts and both keys are variables. The inventory sits beside the playbook and is read via ansible.cfg, which Ansible picks up from the current working directory rather than the playbook's, so it has to be run from this directory. bootstrap.pem is gitignored -- it is the provider key for the host.
38 lines
1.1 KiB
YAML
Executable File
38 lines
1.1 KiB
YAML
Executable File
#################################################
|
|
# Prepare the server
|
|
#################################################
|
|
---
|
|
# A freshly provisioned host only has the provider's bootstrap account
|
|
# ({{ bootstrap_user }}). That account is used once, to create the real user
|
|
# and make it reachable and able to escalate. Everything after this play runs
|
|
# as {{ user }} instead.
|
|
- name: Bootstrap the new user
|
|
hosts: all
|
|
become: true
|
|
remote_user: "{{ bootstrap_user }}"
|
|
vars:
|
|
ansible_ssh_private_key_file: "{{ bootstrap_key }}"
|
|
vars_files:
|
|
- vars/default.yml
|
|
|
|
roles:
|
|
# Creates {{ user }} and installs its authorized_keys, so that the next
|
|
# play can log in as it.
|
|
- user
|
|
# Has to happen in this play too: the next play runs as {{ user }} with
|
|
# become, which needs the NOPASSWD sudoers entry this role writes.
|
|
- wheel
|
|
|
|
- name: Configure the server as the new user
|
|
hosts: all
|
|
become: true
|
|
remote_user: "{{ user }}"
|
|
vars:
|
|
ansible_ssh_private_key_file: "{{ user_key }}"
|
|
vars_files:
|
|
- vars/default.yml
|
|
|
|
roles:
|
|
- common
|
|
- zsh
|