Deploy SSH Keys
This role deploys SSH public keys to user accounts on target systems. It verifies user existence, creates necessary `.
Deploy SSH Keys Role
Overview
This role deploys SSH public keys to user accounts on target systems. It verifies user existence, creates necessary .ssh directories with proper permissions, adds public keys to authorized_keys files, and ensures correct ownership and permissions for SSH authentication to work properly.
Purpose
- Automated Access: Deploy SSH keys for automated Ansible access
- User Management: Configure SSH access for multiple users simultaneously
- Security: Ensure proper file permissions (0700 for .ssh, 0600 for authorized_keys)
- Idempotency: Safe to run multiple times without duplicating keys
- Flexibility: Skip users that don’t exist on target system
- Non-Exclusive: Adds keys without removing existing ones
Requirements
- Ansible 2.9 or higher
- SSH public key files stored in
roles/deploy_ssh_keys/files/directory - Target users must exist on the system (role checks and skips non-existent users)
- Proper sudo/root permissions to modify user home directories
Role Variables
Required Variables
This role has no required variables - it uses defaults that can be overridden.
Optional Variables
| Variable | Default | Description |
|---|---|---|
deploy_ssh_keys_users | See defaults | List of user configurations with SSH keys |
deploy_ssh_keys_ssh_dir_mode | 0700 | Permission mode for .ssh directory |
deploy_ssh_keys_authorized_keys_mode | 0600 | Permission mode for authorized_keys file |
Variable Details
deploy_ssh_keys_users
List of user configurations specifying which SSH keys to deploy to which users.
Structure:
deploy_ssh_keys_users:
- username: user_account_name
key_file: public_key_filename.pub
comment: "Description of this key"
Default configuration:
deploy_ssh_keys_users:
- username: ansibleuser
key_file: ansible_user.pub
comment: "Ansible automation key from mint-vm"
- username: bjoffrey
key_file: bjoffrey_user.pub
comment: "bjoffrey interactive SSH key (PuTTY)"
Example custom configuration:
deploy_ssh_keys_users:
- username: webadmin
key_file: webadmin_rsa.pub
comment: "Web server administrator key"
- username: deploy
key_file: deploy_ed25519.pub
comment: "CI/CD deployment key"
- username: backup
key_file: backup_rsa.pub
comment: "Backup automation key"
deploy_ssh_keys_ssh_dir_mode
Permission mode for the .ssh directory. Must be 0700 for SSH to accept it.
Example:
deploy_ssh_keys_ssh_dir_mode: '0700'
deploy_ssh_keys_authorized_keys_mode
Permission mode for the authorized_keys file. Must be 0600 or 0644 for SSH to accept it.
Example:
deploy_ssh_keys_authorized_keys_mode: '0600'
Dependencies
This role has no dependencies on other Ansible roles, but requires:
- SSH public key files placed in
roles/deploy_ssh_keys/files/directory - Target user accounts already created on the system
Example Playbook
Basic Usage
---
- name: Deploy SSH Keys to All Hosts
hosts: all
become: true
roles:
- deploy_ssh_keys
With Custom Users
---
- name: Deploy SSH Keys for Custom Users
hosts: webservers
become: true
vars:
deploy_ssh_keys_users:
- username: deploy
key_file: deploy_key.pub
comment: "Deployment automation key"
- username: monitoring
key_file: monitoring_key.pub
comment: "Monitoring agent key"
roles:
- deploy_ssh_keys
For Specific Host Group
---
- name: Deploy Admin SSH Keys to Critical Infrastructure
hosts: critical_infrastructure
become: true
vars:
deploy_ssh_keys_users:
- username: sysadmin
key_file: sysadmin_ed25519.pub
comment: "System administrator emergency access"
roles:
- deploy_ssh_keys
What This Role Does
- Checks user existence using
getentfor each configured user - Filters to existing users (skips users not on system)
- Displays found users for verification
- Creates
.sshdirectories for each user with mode 0700 - Sets directory ownership to user:user
- Deploys public keys to
authorized_keysusingauthorized_keymodule - Preserves existing keys (exclusive: false)
- Adds key comments for identification
- Verifies file permissions on
authorized_keys(mode 0600) - Sets file ownership to user:user
- Displays success message with hostname
SSH Key File Structure
Directory Layout
roles/deploy_ssh_keys/files/
├── ansible_user.pub
├── bjoffrey_user.pub
├── deploy_key.pub
└── monitoring_key.pub
Public Key Format
Public keys should be in standard OpenSSH format:
RSA Example:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC... user@hostname
Ed25519 Example:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... user@hostname
User Existence Checking
The role intelligently handles non-existent users:
- Checks all users in
deploy_ssh_keys_userslist - Uses
getent passwdto verify existence - Skips non-existent users without failing
- Processes only existing users
Example scenario:
deploy_ssh_keys_users:
- username: ansibleuser # Exists on all hosts
- username: webadmin # Only exists on webservers
- username: dbadmin # Only exists on databases
Result:
- Web servers: Deploys keys for
ansibleuserandwebadmin - Database servers: Deploys keys for
ansibleuseranddbadmin - Other servers: Deploys keys for
ansibleuseronly
Permissions and Ownership
Critical SSH Permissions
SSH is strict about file permissions. The role enforces:
| Path | Mode | Owner | Group |
|---|---|---|---|
~/.ssh/ | 0700 | user | user |
~/.ssh/authorized_keys | 0600 | user | user |
Why these permissions:
- 0700 on .ssh: Only owner can read/write/execute (SSH requirement)
- 0600 on authorized_keys: Only owner can read/write (SSH security)
- User ownership: SSH refuses to use files owned by wrong user
Permission Verification
The role explicitly verifies permissions after deployment using the file module to ensure SSH will accept the configuration.
Non-Exclusive Key Management
The role uses exclusive: false in the authorized_key module:
- Preserves existing keys: Does not remove manually added keys
- Adds new keys: Appends configured keys to file
- Idempotent: Running multiple times doesn’t duplicate keys
- Safe: Won’t lock out users with existing keys
Key Comments
Each deployed key includes a comment for identification:
- username: deploy
key_file: deploy_key.pub
comment: "CI/CD deployment key"
Result in authorized_keys:
ssh-rsa AAAAB3NzaC1... CI/CD deployment key
Benefits:
- Identify key purpose in
authorized_keysfile - Track which automation added the key
- Easier key audit and management
Security Considerations
- Public Keys Only: Role deploys public keys, private keys never leave secure storage
- No Password Auth: Deploying SSH keys enables passwordless authentication
- Proper Permissions: Enforces SSH security requirements
- User Isolation: Keys owned by target user, not root
- Non-Destructive: Doesn’t remove existing keys (preserves manual access)
- Audit Trail: Key comments identify source and purpose
Tags
This role does not define any tags. Use playbook-level tags if needed:
- hosts: all
roles:
- deploy_ssh_keys
tags:
- ssh
- access
- security
- users
Notes
- Public key files must exist in
roles/deploy_ssh_keys/files/directory - Role requires
become: true(root/sudo access) - SSH daemon must be running on target hosts
- Role does not create user accounts (users must pre-exist)
- Role does not modify SSH server configuration (
sshd_config) - Works with any SSH key type (RSA, Ed25519, ECDSA, etc.)
Troubleshooting
”User does not exist” warnings
Symptom: User skipped, key not deployed
Solution: This is normal behavior. The role only deploys to existing users. Either:
- Create the user account first (using
usermodule) - Remove the user from
deploy_ssh_keys_userslist - Use host-specific variables to target correct users per host
SSH still prompts for password
Check:
- Verify public key in
authorized_keys:cat ~/.ssh/authorized_keys - Check file permissions:
ls -la ~/.ssh/ - Verify SSH daemon allows key auth:
grep PubkeyAuthentication /etc/ssh/sshd_config - Check SSH logs:
tail -f /var/log/secure(RedHat) or/var/log/auth.log(Debian) - Test with verbose client:
ssh -vvv user@host
Permission denied (publickey)
Common causes:
- Wrong private key on client
- Public key not in
authorized_keys - Incorrect file permissions (fixed by role, but verify:
ls -la ~/.ssh/) - SELinux context (RedHat):
restorecon -R ~/.ssh/ - Home directory permissions too open (should be 755 or 700)
File not found error
Error: Could not find or access 'files/key_file.pub'
Solution:
# Verify file exists
ls roles/deploy_ssh_keys/files/
# Add missing key file
cp /path/to/key.pub roles/deploy_ssh_keys/files/
“FAILED: invalid permissions on authorized_keys”
This error comes from SSH daemon, not the role. The role explicitly sets correct permissions, but check:
# Verify permissions
ls -la ~/.ssh/authorized_keys
# Should show: -rw------- (0600)
# If not, manually fix:
chmod 600 ~/.ssh/authorized_keys
Key Generation
To generate new SSH keys for use with this role:
RSA (Traditional, widely compatible)
ssh-keygen -t rsa -b 4096 -C "automation@homelab" -f ~/.ssh/automation_rsa
cp ~/.ssh/automation_rsa.pub roles/deploy_ssh_keys/files/
Ed25519 (Modern, recommended)
ssh-keygen -t ed25519 -C "automation@homelab" -f ~/.ssh/automation_ed25519
cp ~/.ssh/automation_ed25519.pub roles/deploy_ssh_keys/files/
Key Generation Best Practices
- Use Ed25519 for modern systems (smaller, faster, more secure)
- Use RSA 4096-bit for compatibility with older systems
- Add meaningful comments with
-Cflag - Protect private keys (never commit to git, use ansible-vault if needed)
- Use passphrases for interactive keys (not automation keys)
Testing SSH Key Authentication
After deploying keys:
# Test connection (should not prompt for password)
ssh user@target-host
# Test with specific key
ssh -i ~/.ssh/automation_rsa user@target-host
# Verbose test (shows authentication process)
ssh -vvv user@target-host
Integration with Ansible Automation
ansible.cfg Configuration
[defaults]
remote_user = ansibleuser
private_key_file = ~/.ssh/ansible_user
[privilege_escalation]
become = true
become_method = sudo
become_user = root
Inventory Configuration
all:
vars:
ansible_user: ansibleuser
ansible_ssh_private_key_file: ~/.ssh/ansible_user
Best Practices
- Separate keys by purpose (interactive vs automation)
- Use descriptive filenames (e.g.,
ansible_automation.pub,admin_emergency.pub) - Add meaningful comments for each key
- Test on single host before deploying widely
- Keep private keys secure (never in git repository)
- Rotate keys periodically (update public key files and re-run role)
- Document key owners in comments
- Use Ed25519 for new deployments
- Backup private keys securely (encrypted backup)
- Audit authorized_keys regularly
Alternative: Manual Deployment
If you prefer manual deployment:
# Copy public key to target
ssh-copy-id -i ~/.ssh/key.pub user@target-host
# Or manually
cat ~/.ssh/key.pub | ssh user@target-host \
"mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"
Related Roles
This role is often used with:
- User management roles: Create user accounts before deploying keys
- Security hardening roles: Disable password auth, configure SSH daemon
- Sudo configuration roles: Grant sudo access to automated users
License
MIT
Author
Created for homelab infrastructure management.