Forge Home


Puppet module to easily manage local users and their authorized keys


556 latest version

5.0 quality score

We run a couple of automated
scans to help you access a
module's quality. Each module is
given a score based on how well
the author has formatted their
code and documentation and
modules are also checked for
malware using VirusTotal.

Please note, the information below
is for guidance only and neither of
these methods should be considered
an endorsement by Puppet.

Version information

  • 1.4.3 (latest)
  • 1.4.2
  • 1.4.1
  • 1.4.0
  • 1.3.2
  • 1.3.0
  • 1.2.0
  • 1.1.0
  • 1.0.3
  • 1.0.2
  • 1.0.1
released Apr 13th 2022
This version is compatible with:
  • Puppet Enterprise 2023.2.x, 2023.1.x, 2023.0.x, 2021.7.x, 2021.6.x, 2021.5.x, 2021.4.x, 2021.3.x, 2021.2.x, 2021.1.x, 2021.0.x, 2019.8.x, 2019.7.x, 2019.5.x, 2019.4.x, 2019.3.x, 2019.2.x, 2019.1.x, 2019.0.x, 2018.1.x, 2017.3.x, 2017.2.x, 2017.1.x, 2016.5.x, 2016.4.x
  • Puppet >= 4.7.0 < 8.0.0
  • , , ,
  • clear_auth_keys

Start using this module

  • r10k or Code Manager
  • Bolt
  • Manual installation
  • Direct download

Add this module to your Puppetfile:

mod 'qtechnologies-local_users', '1.4.3'
Learn more about managing modules with a Puppetfile

Add this module to your Bolt project:

bolt module add qtechnologies-local_users
Learn more about using this module with an existing project

Manually install this module globally with Puppet module tool:

puppet module install qtechnologies-local_users --version 1.4.3

Direct download is not typically how you would use a Puppet module to manage your infrastructure, but you may want to download the module in order to inspect the code.



qtechnologies/local_users — version 1.4.3 Apr 13th 2022



Puppet module to easily manage local users and their authorized keys. It also manages local groups. It's an abstraction layer over the user and group resources to make it easier to add/remove users/groups across different systems using just hiera and calling this class.


  • maps keys into accounts according to the SSH key comment
  • sets the password aging for non expiring accounts
  • generates a series of accounts (e.g. for testing purposes)

It makes some assumptions to simplify the creation of local users:

  • the GID is the same as the UID unless it is explicitly specified
  • if GID is not specified, the system will choose one
  • the home directory location is the convention for the OS - it will be created if it doesn't exist

It will fail, if:

  • there is no user comment (GECOS) (unless the user is root)

It is designed to be driven by hiera, not so much through code.


What local_users affects

  • /etc/passwd, /etc/shadow and /etc/group mostly through the Puppet user and group resources, but does use the low level commands in certain circumstances.
  • user home directories
  • users' authorized keys
  • permissions of files in users' home directories may be updated to match a new UID and/or GID (but only if explicity enabled)

Setup Requirements

  • The stdlib module
  • It does presume there is a basic system perl installed on systems being managed

Beginning with local_users

Include the class in your code:

  class { 'local_users': }

Create a list of SSH keys that will be referenced later (i.e. consumed) when setting up local users:

  - comment: 'jblogs@imac.local'
    type: ssh-rsa 
    key: 'AAAAB3NzaC1yc2EAAAABIwAAAQEArqFOapIoElAmJBlKq74MdlXQjPZ2xqOZ7xo2UZ4sRD4fRh+kgkfOP0+wius71pIJ2N2n7cgP1QWMP1i7xsvFJBnb+up9P0y93WTnf+wjKMNx3b9Xt43AffXAADegkWnaImIY+nVrqC1fOiq8xyDjT+kq5ItdE+QHaBNlsuP/FCSGQB8hhxOQyqwKsALdhedhZZ9MsCuVqf62Zti+V3CujyKwRuyeZa3f8zMLjjRFXXldxMVFMJv3/PbJNvMSGe38ikI6Dz/1ESJbNHJFcN+3sM6yzHWS1MROfW6jdxDEtvNgccirDDKUzmeA6wzGnHiDAqf/iJn/x4DUBdijROxE1Q=='
  - comment: 'root@prd009'
    type: ssh-rsa
    key: 'AAAAB3NzaC1yc2EAAAAdaqabaaabaqcHyTOwUqmD5evjpDdqyOaR7DISjHa4hu5vwIjg1IecduOZ9Mx00St6emeGwIjMWIapLwaWmTds3DnrON+lFCmMXYPhgIZJpJ4JrxJevMNFXZObS+TdSRwsCo9nuehA9Y1+NPMEPFdtcwdBRSjxDwCbuHzgTYo+hS2Wzwz4B2KjGFvFKx6IlK9qKx7B31n5O4bJMSJLsw+BPe/4xqzDUHjBpcXPPOP+4TWZzhXqZCdXalQZkhxLEC4jHTVycPvpyd3fHr3LOGThpc2ldnh8JAJz71sA01AquErQXa1/pFRl6dGbCZLRuHU8flMj8dA4ZZWCU06cboAkCgxYifTwB8Dd'
    options: 'from="10.X.X.X"'
  - comment: ''
    type: ssh-rsa
    key: 'AAAAB3NzaC1yc2EAAAADAQABAAABAQDFcGZD9nyS34Q4olunx2UgN3XKmZqQT2CeKNiuA2/KJkscty9tWP4cG4syEGY21ws3YL11KLYlI1oH4r2qiBk/AdyKhqpo10sCdCuOVAA+kXK7UQGyAjjwlkCLMYkofjEc5iauz1E6d9UOyrtSMnWZ+B59tq5Kd5zPMXAG1MrzWRO4bB2LwT82HaxXKdoon3VCB7jnXKMYQkj1o890HFp/RA1r4B+EBMDf6Op6iSsQsZGG4607Qvhrf8mfeJbSJiK3FezbO7i2hbIyqfzTNaDgzAexJNpsO/67nlytLs9w2Sx7npdp8faMECPQU0DW31e2UckXgDN43edYpYlNNV/N'

Define any groups that will be required for the users. Also delete some unnecessary groups or ignore some groups (i.e. don't remove them even if they are specified for removal in a more general scope, but they also don't need to be fully defined through the 'add' data).

  admin: {}
    gid: 15002

  - thesmiths
  - builders

  - ftp
  - root

Define some users, consuming both the SSH keys and groups previously specifed. Also, delete some redundant users or ignore others (i.e. don't remove them even if they are specified for removal in a more general scope, but they also don't need to be fully defined through the 'add' data).

    uid: 1000
    comment: Joe Blogs
    expiry: none
    groups: ['a','b','c']
      - 'jblogs@imac.local'
    uid: 1051
    comment: Bill Smith
    expiry: none
    mode: '0700'
      - ''
    uid: 1052
    comment: Bill Smith 0
    mode: '0700'
    generate: 10
    expiry: none
      - 'jblogs@imac.local'
      - 'root@prd009'

  - jsmith
  - bob

  - games
  - shutdown

  - ftp
  - root


The local_users::remove::sysusers collection will not try to remove the home directory regardless of the global managehome setting. If a system user is specified for removal in local_users::remove::users and managehome is also set to true then the home directory will be removed (or attempted at least) - e.g. /root, /sbin, etc. - which will corrupt your systems! (i.e. delete critical binaries).


Adding SSH Keys

Add an array of keys to hiera. The comment field will be used to match against when being consumed by users.

    comment: 'jblogs@imac.local'
    type: ssh-rsa 
    key: 'AAAAB3NzaC1yc2EAAAABIwAAAQEArqFOapIoElAmJBlKq74MdlXQjPZ2xqOZ7xo2UZ4sRD4fRh+kgkfOP0+wius71pIJ2N2n7cgP1QWMP1i7xsvFJBnb+up9P0y93WTnf+wjKMNx3b9Xt43AffXAADegkWnaImIY+nVrqC1fOiq8xyDjT+kq5ItdE+QHaBNlsuP/FCSGQB8hhxOQyqwKsALdhedhZZ9MsCuVqf62Zti+V3CujyKwRuyeZa3f8zMLjjRFXXldxMVFMJv3/PbJNvMSGe38ikI6Dz/1ESJbNHJFcN+3sM6yzHWS1MROfW6jdxDEtvNgccirDDKUzmeA6wzGnHiDAqf/iJn/x4DUBdijROxE1Q=='

Adding Users

Add users by defining hashes/Data in the hiera data:

    uid: 1000
    comment: Joe Blogs
    expiry: none
      - 'jblogs@imac.local'

Adding Groups

Add groups by defining hashes/Data in the hiera data. If the group hash is empty, then the system will decide the GID, otherwise it can be specified.

  admin: {}
    gid: 15002

Removing Users

Simply provide a list of groups to the hiera key:

local_users::remove::users: []

Removing Groups

Simply provide a list of groups to the hiera key:

local_users::remove::groups: []

Defining named sets of users

You can define named sets of users in your hiera data and refer to those sets when adding users to nodes. This way, you do not need to update hiera or manifest files in many locations when people or responsibilities change.

Here's some example hiera data that defines a database of users and their properties under the key local_users::staff. Then, it makes named sets under the keys local_users::department::developers and local_users::department::sysadmins. Note that these keys have no particular meaning to the local_users module on their own, so at this point, we've simply defined some data:

# common.yaml or similar
    uid: 100
    gid: 13779
    comment: Mike Baynton
    uid: 1234
    gid: 13779
    comment: Another user
    uid: 4567
    gid: 13779
    comment: A third user

  mbaynton: '%{alias("local_users::staff.mbaynton")}'
  user2: '%{alias("local_users::staff.user2")}'
  thirdUser: '%{alias("local_users::staff.thirdUser")}'

Now we can apply our named sets to nodes as desired by assigning them to the local_users::add::users key (which does have special meaning to the local_users module):

# or similar
  - '%{alias("local_users::department::developers")}'
  - '%{alias("local_users::department::sysadmins")}'

This concept can even be extended to create named sets that contain nested named sets.


Adding SSH Keys


Requires an array of hashses.

Each hash must have 3 fields:

  • comment - the name of the key, used to link entry to authorised_keys entries
  • type - the type of key, e.g. ssh-rsa
  • key - the actual public key

Adding Users


Requires a hash of user definition hashes.

Each user definition hash must have a comment field (except root), otherwise system defaults will prevail.
All Puppet user resource fields are supported, plus these additional ones:

  • auth_keys - a list of keys that will be added to the authorized_keys file, these must be defined with local_users::add::keys
  • mode - the mode of the home directory
  • base_dir - the directory where the user's home directory with be created within
  • generate - the number of similar users to create. I.e. 10 wil create 10 users. Each user will be numbered sequentially and if the UID is specified, it will also be incremented.

If the GID of the user does not correspond to an existing group, a new one will be created named after the user.

If an existing group has the same name but a different GID then Puppet will throw an error saying it is unable to match the group. This can be fixed by setting local_users::add::force_group_gid_fix to true - this will change the GID of the group matching the name with the required GID. This is not enabled by default.

Updating file permssions

When local_users::add::fix_file_perms is set to true and the UID/GID of the user is changing, any files in the home directory of the user matching the old UID/GID will be updated to the new UID/GID. This is not enabled by default.

If the GID of the user has been specified as a name rather than ID and the GID of that group is being changed by Puppet, the GID of the files in the home directory will not be changed as it is impossible to capture this scenario without re-doing the built-in user resource.

Password expiry

Setting an account expiry to none will tune the expiry and password_max_age for each OS nuance to give expected behaviour. This doesn't always work as expected out of the box with Puppet.

Adding Groups

Groups behave the same as the Puppet group resource.

Removing Users

All users specified for removal will be forcefully removed - i.e. all running processes belonging to that user will be killed before the removal is attempted.

Removing Groups

Groups being removed will simply be removed with the Puppet group resource.


Only tested on UNIX/Linux type systems. It does require a working perl 5, but only the core modules. I don't always have access to AIX, so sometimes it breaks.

Since version 1.0.1 of this module duplicate GIDs will not be forced through. This will create an issue if you have previously relied on this behaviour.

Since version 1.1.0 it requires Puppet 4 and above (hiera functions were replaced with lookup) and internal hiera was converted to version 5