[ STATUS: LOG UPDATED FOR 2026 RUNTIME ENVIRONMENT ]
I wrote this post in 2016 as a quick reference for getting pwgen installed and running. It still works, the tool is still available, and the flags haven’t changed in any meaningful way. But a short snippet on installing a password generator undersells what’s actually useful here. This update expands it into something more practical: what pwgen is good for, where other tools do it better, and how I use secret generation inside automation workflows.
Pwgen generates pronounceable passwords by default, which sounds like a liability but is actually a deliberate design choice. The idea is that a human might actually need to type or remember the output. For machine-generated secrets going straight into a config file or secret store, that’s irrelevant — you want entropy, not pronounceability. The -s flag gets you there by generating completely random output rather than the phonetic default.
Installation
On Arch Linux:
pacman -S pwgen
On Debian and Ubuntu:
apt install pwgen
On macOS with Homebrew:
brew install pwgen
Basic usage
The argument order is pwgen [options] [length] [count]. A few flags worth knowing:
-c include at least one capital letter
-n include at least one number
-y include at least one symbol
-s generate completely random output (not pronounceable)
-B exclude ambiguous characters like 0, O, l, 1
-1 one password per line
Generate a single 64-character random password:
pwgen -s -c -n -y 64 1
Generate ten of them:
pwgen -s -c -n -y 64 10
The -s flag is the important one. Without it pwgen optimizes for memorability, which produces weaker output for use cases where the password is never typed by a human.
Where openssl does it better
For generating secrets in scripts and automation, openssl rand is often more practical than pwgen because it’s available on virtually every system without installing anything. The -base64 and -hex flags give you clean output that’s safe to drop directly into config files:
# 32 bytes of base64-encoded random data
openssl rand -base64 32
# 32 bytes as hex — useful for keys that need hex format
openssl rand -hex 32
The base64 output will occasionally include +, /, and = characters. If you need URL-safe output or something going into a field with character restrictions, pipe it through tr to clean it up:
openssl rand -base64 32 | tr -d '/+=' | cut -c1-32
For quick one-liners on any Linux system, /dev/urandom through tr works without any tools at all:
tr -dc 'A-Za-z0-9!@#$%^&*' < /dev/urandom | head -c 32; echo
Inside Ansible
Where secret generation gets genuinely useful is inside Ansible playbooks. Rather than pre-generating secrets and storing them somewhere, you can generate them at provisioning time and write them directly into your vault or config. The lookup('password', ...) plugin handles this natively:
vars:
db_password: "{{ lookup('password', '/dev/null length=32 chars=ascii_letters,digits') }}"
That generates a 32-character alphanumeric secret at run time. If you want the secret to persist across runs rather than regenerate every time, write it to a file and reference that file in subsequent runs:
vars:
db_password: "{{ lookup('password', 'credentials/db_password length=32 chars=ascii_letters,digits') }}"
Ansible reads the file if it exists and creates it if it doesn’t, so the secret is stable after the first run. Combine this with Ansible Vault to encrypt the credentials directory and you have a lightweight secrets workflow that doesn’t require a separate secrets manager for smaller deployments.
For larger infrastructure where you’re managing secrets across multiple systems and teams, dedicated tools like HashiCorp Vault, Infisical, or even Bitwarden Secrets Manager make more sense. But for a homelab or a small VPS stack where you’re the only operator, the Ansible lookup pattern covers most needs without adding another service to maintain.
Pwgen is still a perfectly good tool. For quick interactive use or dropping into a shell script where you want readable output, it’s fine. But knowing when to reach for openssl rand instead, and how to wire secret generation into your automation, is where the real value is in 2026.
Comments
Questions, corrections, and follow-ups live in GitHub Discussions.