Skip to content

Instantly share code, notes, and snippets.

@xsleonard
Last active March 14, 2024 02:01
Show Gist options
  • Save xsleonard/b1c1cd5e46cbd3fb13ea559eec6068f7 to your computer and use it in GitHub Desktop.
Save xsleonard/b1c1cd5e46cbd3fb13ea559eec6068f7 to your computer and use it in GitHub Desktop.
Ansible role to create a new user and disable root
playbook
├── roles
│   ├── createuser
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── templates
│   │   └── sudoers.j2
│   └── maybecreateuser
│   └── tasks
│   └── main.yml
└── site.yml
# roles/maybecreateuser/tasks/main.yml
# `gather_facts: no` must be set when using this role
# Uses a variable `initial_user` which defaults to "root".
# Set this if the initial user is not "root".
---
# To bootstrap from root to $ansible_user, we need to swap in the
# $initial_user var into $initial_user, yet still retain the value
# of $ansible_user so that we know what user to create.
- name: "Register username var"
set_fact:
username: "{{ ansible_user }}"
# Test if the original ansible_user can SSH in or not.
# If not, assume we can SSH in with the initial_user
# and setup the ansible_user.
- name: Create new user if not exists
vars:
- ansible_user: "{{ initial_user | default('root') }}"
block:
- name: Check if new user already exists
command: 'ssh -q -o BatchMode=yes -o ConnectTimeout=3 {{ username }}@{{ inventory_hostname }} "echo OK"'
delegate_to: localhost
changed_when: false
failed_when: false
register: check_new_user
- name: Create new user
import_role:
name: createuser
when: not "OK" in check_new_user.stdout
# roles/createuser/tasks/main.yml
# This creates a new user, copies the root .ssh/authorized_keys to its home
# and gives it nopasswd sudo.
# This assumes that the server is already configured to have root login by
# SSH pubkey, which can be done on DigitalOcean.
---
# When using this role from the maybecreateuser role, gather_facts must be
# disabled at the playbook level to avoid initialization problems.
# Ensure the facts are gathered now, since we need them.
- name: "gather facts"
setup:
# We'll give the user nopasswd sudo later, so it doesn't need to set a password
- name: "create new user without a password"
register: newuser
user:
name: "{{ username }}"
create_home: yes
groups: sudo
state: present
shell: /bin/bash
- name: "create .ssh for the new user"
file:
mode: 0700
owner: "{{ username }}"
group: "{{ username }}"
path: "{{ newuser.home }}/.ssh"
state: directory
- name: "copy authorized_keys to new user's .ssh folder"
copy:
remote_src: yes
src: "{{ ansible_env.HOME }}/.ssh/authorized_keys"
dest: "{{ newuser.home }}/.ssh/authorized_keys"
# remote_src requires mode: preserve; update the owner and perms later
mode: preserve
- name: "change mode of authorized_keys file"
file:
mode: 0644
path: "{{ newuser.home }}/.ssh/authorized_keys"
owner: "{{ username }}"
group: "{{ username }}"
- name: "sudo nopasswd for the new user"
template:
src: sudoers.j2
dest: "/etc/sudoers.d/{{ username }}"
owner: root
group: root
mode: 0440
validate: /usr/sbin/visudo -cf %s
# roles/createuser/templates/sudoers.j2
%{{ username }} ALL = (ALL) NOPASSWD: ALL
# site.yml (playbook)
---
- name: Maybe create user
hosts: all
# gather_facts must be disabled here to use this role
gather_facts: no
roles:
- maybecreateuser
- name: Configure server as the new user
hosts: all
become: yes
roles:
- myconfiguration # example
[all]
a.b.c.d
# optional: set initial_user (default "root")
w.x.y.z initial_user=fedora
[all:vars]
# optional: set the ansible ssh user.
# This is the user that will be created by the maybecreateuser.
# Defaults to the ansible operator's username
ansible_user=ansible
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment