Prompt for a System Password Safely with systemd-ask-password
You will finish with a repeatable way to ask for a system-wide password or passphrase, capture it for one command, and choose whether the request stays on the current terminal or goes through systemd's password-agent mechanism. The examples are based on systemd 255.4-1ubuntu8.17, installed here as systemd 255.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes. You need a shell and a terminal for the interactive examples. This command deals with secrets, so do not paste a real password into a shell history, a ticket, or a shared terminal. The examples use obvious test values only where a terminal smoke test needs input.
1. Check the installed command
Start with read-only checks. They do not need elevated privileges:
$ command -v systemd-ask-password
/usr/bin/systemd-ask-password
$ systemd-ask-password --version
systemd 255 (255.4-1ubuntu8.17)
$ systemd-ask-password --help
The help text confirms the local option spelling. The command accepts one question message after its options. It asks for a system password, meaning a secret used by a service or system operation rather than a password belonging to one login account.
Checkpoint: if command -v finds nothing, stop here and install or enable the systemd package supplied by your distribution. Do not copy a different binary into /usr/bin to work around a path problem.
2. Use the current TTY for a one-off prompt
With a usable TTY, the normal mode asks on that terminal and writes the acquired password to standard output. A minimal example is:
$ systemd-ask-password 'Passphrase for the test operation:'
Passphrase for the test operation: ********
test-value
Replace test-value with the secret only when you are testing interactively. The command's output is the password, followed by a newline by default. That makes command substitution convenient, but it also makes careless logging easy:
$ password=$(systemd-ask-password 'Passphrase: ')
$ some-command --password "$password"
$ unset password
The variable is not a secure vault. It can be exposed by debugging, crash reporting, process inspection of a poorly designed child, or accidental shell tracing. Keep the lifetime short, never enable set -x around this code, and unset it as soon as the child no longer needs it.
When the masked prompt is shown, pressing Tab hides the asterisks. Pressing Backspace before entering text does the same. This changes only visual feedback; it does not make the secret safer if the terminal or shell is already compromised.
3. Make output safer for a real script
If the password is needed by a program, keep it out of standard output and pass it through a short-lived variable or a file descriptor supported by that program. Use --no-output when you want the query to populate a kernel keyring cache without printing the collected value:
$ sudo systemd-ask-password \
--keyname=cryptsetup \
--no-output \
'Passphrase for the encrypted device:'
This is a security-sensitive example. It can place the password in the root user's kernel keyring, so use it only when the consuming workflow expects that cache. sudo is needed here because the manpage describes the cache as belonging to root. The command does not unlock a disk by itself and does not change persistent system configuration.
For ordinary output, use -n when a trailing newline would be harmful:
$ systemd-ask-password -n 'Token for the test operation:' > /run/user/1000/token.txt
Do not use a world-readable path for a secret. The example path is only illustrative, and redirecting to a file creates state that must be removed. If you created a test file, remove it with the narrow, explicit command below after checking its path:
$ ls -l /run/user/1000/token.txt
$ rm -- /run/user/1000/token.txt
That removal is irreversible. Never replace the path with a broad directory or a variable you have not inspected.
4. Choose TTY or password agents deliberately
Use --no-tty when a terminal must never receive the prompt:
$ systemd-ask-password --no-tty --timeout=30 \
'Passphrase required by the service:'
Without a TTY, or with --no-tty, systemd uses its system-wide query mechanism. Active password agents may ask through Plymouth, the console service, a wall message, or another registered agent. A headless machine may have no agent able to answer, which is a normal failure rather than a reason to print the secret in a log.
The default timeout is 90 seconds. A timeout of zero waits indefinitely, which is usually a poor choice in a service because it can leave a job stuck forever. Set a finite value that fits the operation's maintenance window and handle a non-zero exit status.
Checkpoint: test the agent path without entering a real secret:
$ systemd-ask-password --no-tty --timeout=1 'Agent-path smoke test'
Failed to query password: Permission denied
$ printf 'exit status: %s\n' "$?"
exit status: 1
The exact diagnostic depends on the available agents and permissions. The useful contract is that success returns zero and a failed or expired query returns non-zero. Do not build automation around the wording of the diagnostic.
5. Make repeated unlocks less disruptive
--accept-cached allows a previously entered password to satisfy the query. It is useful when several objects may be unlocked with the same secret:
$ sudo systemd-ask-password \
--keyname=cryptsetup \
--accept-cached \
--timeout=30 \
'Passphrase for the next encrypted device:'
A keyring cache is not permanent. With --keyname, systemd gives the cached key a 2.5 minute timeout, and more than one password can be stored under the same key name as a NUL-separated list. Treat the key name as part of your security design, not as a convenient place to leave secrets indefinitely. If you need to inspect or clear such a cache, use the keyring tooling and the exact key name defined by your system's workflow.
The --multiple option only has meaning with --accept-cached. It asks for multiple cached values and writes one password per line. Do not use line-oriented output if a password itself could contain a newline or if your consumer cannot distinguish records safely.
6. Keep prompts identifiable
Set an identifier when several services may ask questions at once:
$ systemd-ask-password \
--id=cryptsetup:/dev/mapper/data \
--timeout=30 \
'Passphrase for /dev/mapper/data:'
The identifier is freely chosen, but include the subsystem and object it refers to. Agents can use it to recognise related requests. Do not put the password in the identifier, question, unit name, or any other metadata that may be logged or displayed.
--icon=NAME supplies an XDG icon name to agents that support graphical display. --echo=yes is intended for non-protected input such as a username, not for passwords. The default --echo=masked shows asterisks, while --echo=no gives no typing feedback. The command's --emoji=auto default may add a lock and key symbol when the TTY permits it; do not use that visual detail as a machine-readable signal.
7. Handle failures without weakening the boundary
A non-zero exit status means the query did not complete successfully. Check the status immediately, preserve only a safe diagnostic, and decide whether the caller should retry:
if ! password=$(systemd-ask-password --timeout=30 'Passphrase: '); then
printf '%s\n' 'Password query failed or timed out' >&2
exit 1
fi
if ! some-command --password "$password"; then
unset password
exit 1
fi
unset password
Do not solve an agent failure by adding the password to a command line, writing it to a predictable temporary file, or turning on visible echo. If a service needs a password at boot, investigate its configured password agent and unit ordering. If a TTY query works but --no-tty fails, that is evidence about agent availability, not about the password itself.
Done means
- You confirmed the installed systemd version and local option syntax.
- You know whether the caller should use the current TTY or a password agent.
- You set a finite timeout and check the exit status.
- You keep passwords out of logs, identifiers, command-line arguments and shell tracing.
- You use
--no-outputand--keynameonly when a root keyring cache is genuinely required. - You understand that cached passwords expire and that test files or caches need deliberate cleanup.