{"id":21605997,"url":"https://github.com/archf/ansible-accounts","last_synced_at":"2026-05-18T01:37:29.362Z","repository":{"id":89974997,"uuid":"42890899","full_name":"archf/ansible-accounts","owner":"archf","description":"Ansible role to install and configure accounts on a host","archived":false,"fork":false,"pushed_at":"2020-07-21T18:32:33.000Z","size":129,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-18T14:49:06.272Z","etag":null,"topics":["accounts","ansible","role","system"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/archf.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-09-21T20:08:35.000Z","updated_at":"2020-08-02T15:44:10.000Z","dependencies_parsed_at":"2023-05-30T18:00:38.906Z","dependency_job_id":null,"html_url":"https://github.com/archf/ansible-accounts","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/archf/ansible-accounts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archf%2Fansible-accounts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archf%2Fansible-accounts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archf%2Fansible-accounts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archf%2Fansible-accounts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/archf","download_url":"https://codeload.github.com/archf/ansible-accounts/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/archf%2Fansible-accounts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33161940,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-17T22:39:12.733Z","status":"ssl_error","status_checked_at":"2026-05-17T22:39:10.741Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["accounts","ansible","role","system"],"created_at":"2024-11-24T20:18:30.291Z","updated_at":"2026-05-18T01:37:29.350Z","avatar_url":"https://github.com/archf.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ansible-accounts\n\nA role to create and configure user accounts and groups on a host.\n\n## Ansible requirements\n\n### Ansible version\n\nMinimum required ansible version is 2.5.\n\n### Ansible role dependencies\n\nNone.\n\n## Installation\n\n### Install with Ansible Galaxy\n\n```shell\nansible-galaxy install archf.accounts\n```\n\nBasic usage is:\n\n```yaml\n- hosts: all\n  roles:\n    - role: archf.accounts\n```\n\n### Install with git\n\nIf you do not want a global installation, clone it into your `roles_path`.\n\n```shell\ngit clone git@github.com:archf/ansible-accounts.git /path/to/roles_path\n```\n\nBut I often add it as a submdule in a given `playbook_dir` repository.\n\n```shell\ngit submodule add git@github.com:archf/ansible-accounts.git \u003cplaybook_dir\u003e/roles/accounts\n```\n\nAs the role is not managed by Ansible Galaxy, you do not have to specify the\ngithub user account.\n\nBasic usage is:\n\n```yaml\n- hosts: all\n  roles:\n  - role: accounts\n```\n## User guide\n\n### Requirements\n\n  This roles contains tasks relying on the `synchronize` module (rsync) and\n  therefore it requires the `openssh` daemon to be running.\n\n  However, if no underlying connection is not `ssh`, it will fall back to the\n  copy module.\n\n### Introduction\n\n**Usergroups**\n\nThis role works in a usergroups paradigm. As your coworkers also needs to\nlogin on the same servers, user accounts are configured by adding one or\nmultiple usergroups composed of one or more individual users that will end up\nattached to the unix group named after the usergroup name. Phew!\n\nThere is also `noadmin` mode for when you have no control over the remote\nmachine. You can use this on the restricted machines to deploy your public\nssh keys and your dotfiles. You will be touching **only your account**\n\n**SSH keys management**\n\nPrivate ssh keys are **only managed on specified hosts**. Agent-fowarding should be\nconsidered when using a `jumphost` or hopping through a bastion host. To make\nthings manageable and flexible, following logic is used to allow a user to\nhave have multiple ssh keys.\n\n  * default keyname id_rsa and id_rsa.pub are not use for complexity reasons\n  * default keys give access to an internal domain (i.e. company domain)\n  * other keys might optionaly exist and give access to other external domains\n  * keynames follow a `\u003cuser\u003e.\u003cdomain\u003e`\n\nThe `domain` part is important as it hints you what it gives access to. As\nsuch, this is the role behavior regarding your keyring management.\n\n  * default keys are deployed as \u003cuser\u003e.\u003cdomain\u003e and \u003cuser\u003e.\u003cdomain\u003e.pub on workstations\n  * public keys will be deployed exclusively on target where ansible_fqdn == \u003cuser\u003e.\u003cdomain\u003e\n  * ssh keys can be rotated, this behavior is disabled by default\n  * keypairs are created on specified hosts at user account creations\n  * all public keys of configured keypairs are fetched back to usergroup keyring\n  * private keys are never fetched to the usergroup keyring\n  * other keys can be requested to be generated at user account creation\n  * every public key is deployed in an exclusive fashion\n  * other keys are not deployed in the internal domain (keys are exclusive)\n  * to make use of other keys, the user must configure his `ssh_config` properly\n\n### Usage\n\n**Usergroup directory scaffolding**\n\nTo add users, you need to configure usergroups inside `group_vars` or `host_vars`.\n\n```yaml\nusergroups:\n  - name: vendorgroup\n    # gid is optional\n    gid: 1001\n    # create vendorgroup sudoers file inside /etc/sudoers.d\n    sudos:\n      - ALL=(ALL) ALL\n\n  - name: customergroup\n```\n\nYou can also tweak the behavior on a per group or per machine basis. See\nvariables in 'Default vars' .\n\nThen at the path defined by `groups_dir` variable (`{{ playbook_dir }}/private/groups`)\ncreate a folder by the `usergroup name` with content such as\n\n```bash\n$ \u003e tree\n.\n├── customergroup\n│   └── users.yml\n└── vendorgroup\n     └── users.yml\n```\n\nfor each of the groups you declared in `usergroups`. Other missing\ndirectories inside the group directory will be created by the play.\n\n**Usergroup members configuration**\n\nIn each group you will have a file where you define and configure the unix\ngroup members. See the Role Variables` section for more information on ways\nto personalise a user account. Most settings in `users_defaults` can be\noverridden.\n\n```shell\n$ \u003e cat vendorgroup/users.yml\n---\n\nusers:\n\n  - name: foo\n    comments: 'foo account'\n    groups:\n      - adm\n      - lp\n      - users\n    shell: \"/bin/zsh\"\n\n    # optional\n    ssh_domains:\n      - company.domain\n\n    # optional\n    dotfiles_dir: dotfiles\n    vim_dir: .vim\n\n    # optional\n    dotfiles_symlinks:\n      - vimrc\n      - bashrc\n      - zshrc\n      - gitconfig\n      - git_template\n      - profile\n      - zprofile\n      - tmux.conf\n      - ansible.cfg\n      - ctags\n      - pypirc\n\n  - name: bar\n    comments: 'bar user'\n    ssh_domains:\n      - lan\n      - example.com\n\n  - name: baz\n    comments: 'baz user'\n    groups:\n      - users\n    ssh_domains:\n      - lan\n      - example.org\n```\n\n**When remote_user is different than local_user **\n\nsee `users_usermap` in `defaults/main.yml`\n\n**User ssh_configuration**\n\nEach user can optionaly manage their `ssh_config` with ansible. For that to happen,\nyou have to create a `\u003cusername\u003e_ssh_config.yml file inside the group directory.\n\nFor example for the *foo* user above, the statements below will be transmuted into a\n`~/.ssh/config` Parameters from `users_defaults['ssh_config']` are also\nconsidered. This file is *totaly optional*. The playbook will not fail if it\nis missing for any given user.\n\n```bash\n$ \u003e cat vendorgroup/foo_ssh_config.yml\n---\n\nssh_config:\n  - Host: bitbucket.org\n    User: git\n    ForwardX11: no\n    PreferredAuthentications: publickey\n    ControlMaster: no\n\n  - Host: github.com\n    User: git\n    ForwardX11: no\n    PreferredAuthentications: publickey\n    ControlMaster: no\n\n  - Host: \"*lb-*\"\n    User: archambf\n    Hostname: \"%h.lb.labfqdn\"\n    ForwardAgent: yes\n    StrictHostKeyChecking: yes\n    ProxyCommand: ssh -W %h:%p jumphost\n```\n\nAs you might notice,\n\n* Every key must be a valid `ssh_config` option.\n* `Match` statements are supported.\n* Quote strings with special chars else yaml parsing will fail\n\n**Using the 'noadmin' mode**\n\nFor this restricted mode, just set the `users_noadmin' boolean to yes|True\neither on the cli (`-e users_noadmin=True`) or in your playbook variables.\n\n\n## Role Variables\n\nVariables are divided in three types.\n\nThe [default vars](#default-vars) section shows you which variables you may\noverride in your ansible inventory. As a matter of fact, all variables should\nbe defined there for explicitness, ease of documentation as well as overall\nrole manageability.\n\nThe [mandatory variables](#mandatory-variables) section contains variables that\nfor several reasons do not fit into the default variables. As name implies,\nthey must absolutely be defined in the inventory or else the role will\nfail. It is a good thing to avoid reach for these as much as possible and/or\ndesign the role with clear behavior when they're undefined.\n\nThe [context variables](#context-variables) are shown in section below hint you\non how runtime context may affects role execution.\n\n### Default vars\n\nRole default variables from `defaults/main.yml`.\n\n```yaml\n# Debug output.\ndebug: false\n\n# An external directory containing sensitive data (group profiles, public ssh\n# keys, users's ssh_config, ...etc.\ngroups_dir: \"{{inventory_dir}}/extra_vars/usergroups\"\n\nusers_usergroups: []\n\n# Avoid trying to install packages. Useful if you know you don't have access to\n# repositories.\nusers_nopkgs: no\n\n# Ignore erros when using users modules on LDAP controlled server.\nusers_usermod_ignore_errors: false\n\n# Force expiration of new user's so they are prompted to change it on first\n# login.\nusers_expire_passwords: no\n\n# Don't generate private ssh key in user accounts on every machine, consider\n# agent forwarding instead. Use this in group_vars to toggle ssh_key creation\n# in a group of hosts.\nusers_generate_ssh_keys: no\n\n# SSH key rotation is disabled by default. Enabling this implicitly enables\n# users_generate_ssh_keys.\nusers_rotate_ssh_keys: no\n\n# Exclusive ssh keys on remote accounts. This is fed to the authorized_key\n# module.\nusers_exclusive_ssh_keys: no\n\n# Max age of keys for ssh_rotation. This is a time specification that must be\n# compatbile with the find module.\nusers_ssh_key_max_age: 60d\n\n# Default ssh key domain. Default key name is the concatenation of the username\n# and this value. For public key to be propagated to the right machines, it\n# should match the 'ansible_domain' fact and thus hint wich realm the key gives\n# access to.\nusers_default_domain: null\n\n# Configure '/etc/skel' facility. Useful prior accounts creation. Doing it on\n# lot of user home directory after they created is costly. This will add\n# directories as defined in users_defaults['skel'].\nusers_gen_skel: no\n\n# Enable this to ensure already created home matches de /etc/skel structure.\n# This task can be somewhat slow when managing lots of users on a large\n# inventory. This behavior is rather invasive and probably more suitable for\n# personal usage and/or when you have no control over /etc/skel.\nusers_skel_homedir: no\n\n# If yes, 'usergroups' are exclusive. That means that all unstated unix\n# usergroups in play variable will be deleted along with all it's members at\n# the exception of group `nogroup`.\nusers_exclusive_usergroups: no\n\n# List of 'usergroups' that will never be removed.\nusers_exclusive_usergroups_exceptions:\n  - vagrant\n  - nogroup\n\n# If yes, group members are exclusive. That means that all unstated group\n# members in play variables will deleted at the exception of user `nobody`.\nusers_exclusive_groupmembers: no\n\n# Default args for the user module and sensible defaults for other role\n# features on a per user accounts basis. Override these on a per user basis\n# inside the 'users.yml' file of the usergroup.\nusers_defaults:\n  state: present\n  # FIXME: task should generate something random per user, register it, and send to user by mail.\n  shell: \"/bin/bash\"\n  system: no\n\n  groups: omit\n  append: yes         # Append to group\n\n  # Default to 'on_create' (will change passwd if they differ). Could also be\n  # set to 'always'.\n  update_password: 'on_create'\n\n  # Path prefix to the directory that will contain a user account. If you work\n  # on Solaris you could set this to '/export/home'. Not to be confused with\n  # 'homedir'\n  homedir_root: '/home'\n\n  # Module defaults\n  createhome: yes     # Defaults to yes\n  move_home: no       # Defaults to no\n  non_unique: no      # Defaults to no\n\n  # Set the amount of days a password can remain inactive after expiration.\n  # This is passed to the 'inactive' options of 'passwd' command.\n  inactive: 365\n\n  # SSH configuration defaults.\n  # fixme: task should generate something random, register it, and send to user by mail.\n  ssh_key_passphrase: q1w2e3\n  ssh_key_type: rsa\n  ssh_key_bits: 2048\n\n  # Homedir skeleton.\n  skel:\n    - '.ssh/controlmasters'\n    - 'bin'\n    - 'tmp'\n\n  # Values for ~/.ssh/config. Those are for a \"Host *\" clause at the top and\n  # will be applied to every users. This doesn't prevent you from having\n  # multiple \"Host *\" statements under it that will supersede this one. I think\n  # those are acceptable sane defaults.\n\n  ssh_config:\n    ServerAliveInterval: 41\n    ControlPersist: 120s\n    ControlMaster: auto\n    ControlPath: '~/.ssh/controlmasters/%r@%h:%p'\n\n  # This is the list of files in your dotfiles_dir you do not want to rsync\n  # to the remote host.\n  dotfiles_rsync_exclude:\n    - americano\n    - i3\n    - zsh-autosuggestion\n    - debug-refs\n    - gnupg\n    - hexchat\n    - win*\n    - wireshark\n    - _vimrc\n\n    # directories for building tmux, vim, openssh from source\n    - tmux/tmux-?.?\n    - vim.d/vim\n    - openssh\n\n# Sometimes, remote user account doesn't match the local one. That happens for\n# instance when host is 'mostly' controlled by your customer. Fill this dict\n# with keys such as { '\u003cremote_username\u003e' : '\u003clocal userneame\u003e'}.\nusers_usermap: {}\n\n# Disabling this for now.\n# # You can have shared by multiple users. Define this variable in `users.yml`\n# # to have usergroup defaults different than `users_defaults`.\n# usergroup_defaults:\n#   passwd: ''\n\n### omited parameters\n\n# By default, the first make target is ran but you way want to override. Could\n# be useful to if hosts have no www access. This is fed to the make module\n# target argument.\n# users_dotfiles_makefile_target:\n\n# Include debugging tasks that prints variable information when adding and\n# removing unix groups.\ngroupadd_debug: no\ngroupdel_debug: no\n\n```\n\n### Mandatory variables\n\nNone.\n\n### Context variables\n\nNone.\n\n\n## Todo\n\nYou want to contribute? Here's a wishlist:\n\n  * generate random passwords using passlib and mail'em to user\n\nConsider opening an issue to share your intent and avoid work duplication!\n\n## License\n\nBSD.\n\n## Author Information\n\nFelix Archambault.\n\n---\nPlease do not edit this file. This role `README.md` was generated using the\n'ansidoc' python tool available on pypi!\n\n*Installation:*\n\n```shell\npip3 install ansidoc\n```\n\n*Basic usage:*\n\nValidate output by running a dry-run (will output result to stdout)\n```shell\nansidoc --dry-run \u003crolepath\u003e\n```\n\nGenerate you role readme file. Will write a `README.md` file under\n`\u003crolepath\u003e/README.md`.\n```shell\nansidoc \u003crolepath\u003e\n```\n\nAlso usable programatically from Sphinx.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farchf%2Fansible-accounts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farchf%2Fansible-accounts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farchf%2Fansible-accounts/lists"}