Making users in Linux isn't necessarily as simple as making a username, and giving it a password. There are a few considerations you need to know about! Knowing these will make creating new users in Ansible easier.
First, some Linux distributions have the
adduser command, wihch is a shortcut (with sensible defaults) to the
adduser command will create a new user that is able to login and has a home directory. The
useradd command needs to be told to do all of these things. The way Ansible creates a user is more like
useradd than the easier
Here are a few things to know about creating a new user on Linux systems:
System vs Regular Users
By convention, users can be "system" users or "normal" users. System users often have a user id (UID) below 1000 and cannot be used to login. They are usually used to run programs. For example, users
apache are often used to run web servers. Conversely, "regular" users typically have UID's at 1000 or higher and are allowed to log into the server.
If you're curious about how UID's are assigned, you can see the file
/etc/login.defs to find variables like UID_MIN and UID_MAX set for system vs regular users:
# # Min/max values for automatic uid selection in useradd # UID_MIN 1000 UID_MAX 60000 # System accounts #SYS_UID_MIN 100 #SYS_UID_MAX 999 # # Min/max values for automatic gid selection in groupadd # GID_MIN 1000 GID_MAX 60000 # System accounts #SYS_GID_MIN 100 #SYS_GID_MAX 999
Ability to Login
Users cannot login (over SSH or otherwise) unless they are assigned a shell, usually
/bin/bash. This shell is the program run when you login - it's why you can interact with the server.
The ability to login usually coincides with assigning the user a home directory. By convention (and default), this is created at
/home/<username>, but can be any location.
Users have a primary group, which is usually the same name as their username. However, users can be assigned one or more secondary groups.
Creating a User in Ansible
Knowing the above, we can create a user in Ansible.
We'll create a user who is able to login with the following attributes:
- User: fideloper
- Password: secret
- Home Directory: /home/fideloper
- Shell: /bin/bash
We can see we're creating a "regular" user, one that can login. That user will likely be assigned a UID of 1000 or greater.
Here's a Ansible task file with a user definition for the above. It uses the user module to create a user:
--- - name: Create a login user user: name: fideloper password: '???' groups: # Empty by default, here we give it some groups - docker - sudo state: present shell: /bin/bash # Defaults to /bin/bash system: no # Defaults to no createhome: yes # Defaults to yes home: /home/fideloper # Defaults to /home/<username>
Let's cover that task definition:
name: Set the username (the primary group they belong to will be the same).
password: Set their password, we'll cover how this works in a minute.
groups: Assign secondary groups. Here we add this user to groups "docker" and "sudo" (group
sudoallows the user to run sudo commands on Ubuntu and Debian linux).
state: Tell ansible we want the user to exist.
shell: You can define any shell. The default is
/bin/bash. I just re-iterate the default here.
system: Set this to "yes" to make it a system user. No shell or home directory will be made unless specified otherwise.
createhome: Yes to create a home directory, no to not create one
home: If you don't want to use the default location, set it here
Note that we have a few ways we can create users. Using the "system" setting we essentially flip a few defaults. A system user will have a lower UID, no shell, and no home directory. A "regular" user (
system: no) will have these things assigned, and likely a UID at 1000 or over.
Generating Password Strings
The one thing I left off here is how to make a valid password string. You can't put a plaintext password into Ansible. Instead you need to generate one!
The easiest way to do this is with the
This will prompt you for the plaintext password and will give you a hashed password string you can paste into the task definition. For password
secret, I get hash
That would make my Yaml look like this:
--- - name: Create a login user user: name: fideloper password: '$6$F4NWXRFtSdCi8$DsB5vvMJYusQhSbvGXrYDXL6Xj37MUuqFCd4dGXdKd6NyxT3lpdELN07/Kpo7EjjWnm9zusFg/LLFv6oc.ynu/' groups: docker, sudo # Empty by default. state: present shell: /bin/bash # Defaults to /bin/bash system: no # Defaults to no createhome: yes # Defaults to yes home: /home/fideloper # Defaults to /home/<username>
- On Debian/Ubuntu systems,
mkpasswdlikely exists, but if not, it's part of the
sudo apt-get install -y whois.
- On CentOS, I believe the
expectpackage has it:
sudo yum install expect. However, you can check to see if
grub-cryptis available too and use it just like
- On Macintosh, you can install the
gem install mkpasswd. Source code here.