Skip to content

Instantly share code, notes, and snippets.

@arfar-x
Last active February 26, 2026 13:55
Show Gist options
  • Select an option

  • Save arfar-x/a4c0a78d8618c57d90e3544d69cb57f3 to your computer and use it in GitHub Desktop.

Select an option

Save arfar-x/a4c0a78d8618c57d90e3544d69cb57f3 to your computer and use it in GitHub Desktop.
SSH password management + login in Linux Keyring

Secure Password SSH Using SSH_ASKPASS

This guide sets up secure password-based SSH using your OS keyring.
No plaintext passwords, no hardcoding, works for multiple servers and any tool that calls SSH.


How it works

  1. Any SSH call prompts for a password
  2. SSH_ASKPASS calls askpass.sh with the prompt
  3. The script retrieves the password from the keyring and prints it
  4. SSH receives the password and logs in
  5. No plaintext storage; minimal memory exposure

1. Store passwords in keyring

Use secret-tool (Linux) to store each server password:

secret-tool store --label="server-1" host 192.168.1.10 user demo_user
  • host: server IP or hostname
  • user: SSH login username

Check it:

secret-tool lookup host 192.168.1.10 user demo_user

It should print the password.


2. Create askpass script

Create ~/.ssh/askpass.sh:

#!/usr/bin/env bash

prompt="$1"
user=""
host=""

# Only handle password prompts
if [[ ! "$prompt" =~ [Pp]assword:\ *$ ]]; then
    echo "Unhandled prompt type" >&2
    echo "SSH_ASKPASS script `$0` received an unhandled prompt." >&2
    echo "The script is written to fetch passwords from OS Keyring, fallback to manual password prompting when not found." >&2
    echo "It does NOT handle other scenarios, since SSH_ASKPASS is a one-line pipeline; SSH Prompt IN, Password Out." >&2
    echo "To resolve this issue, you unset the following env variables TEMPORARILY:" >&2
    echo "SSH_ASKPASS, SSH_ASKPASS_REQUIRE, DISPLAY" >&2
    echo "Rerun the SSH command lead to unhandled scenario, then fix the problem." >&2
    echo "After that, SSH_ASKPASS can handle password prompting automatically." >&2
    exit 1
fi

# Parse user@host from prompt like "user@host's password: "
if [[ $prompt =~ ^([^@]+)@([^\'s]+) ]]; then
    user="${BASH_REMATCH[1]}"
    host="${BASH_REMATCH[2]}"
fi

# Fetch from keyring
password=$(secret-tool lookup host "$host" user "$user" 2>/dev/null)

if [[ -z "$password" ]]; then
    # Always read from /dev/tty, never from stdin
    echo "SSH_ASKPASS: Password not found in OS Keyring" >&2
    read -r -s -p "Enter SSH password for $user@$host: " password < /dev/tty > /dev/tty
    echo > /dev/tty
fi

echo "$password"

Make it executable:

chmod 700 ~/.ssh/askpass.sh

3. Configure environment variables

Add to your ~/.zshrc (or .bashrc):

export SSH_ASKPASS="$HOME/.ssh/askpass.sh"
export SSH_ASKPASS_REQUIRE=force
export DISPLAY=:0
# Set GIT_ASKPASS empty to prevent SSH_ASKPASS from interfering Git prompts
export GIT_ASKPASS=
  • SSH_ASKPASS: path to the script
  • SSH_ASKPASS_REQUIRE=force: forces usage even in terminal
  • DISPLAY: required for SSH_ASKPASS (any value works)

4. Test SSH manually

ssh demo_user@192.168.1.10
  • Should log in automatically using the password from the keyring

5. Add more servers

secret-tool store --label="server-2" host 192.168.1.11 user demo_user
  • The same askpass.sh script works for multiple servers
  • No changes needed in the script for additional hosts

⚠️ Considerations

  • The script works as long as SSH attempts the correct username. However, connecting to new hosts for the first time breaks this script because SSH may prompt you to type yes/no to add the key.
  • A workaound is to add the hosts to ~/.ssh/config as shown below:
    # Local LAN ranges - auto-accept new host keys
    Host 192.168.*
        StrictHostKeyChecking accept-new
    
    # Everything else - strict (default)
    Host *
        StrictHostKeyChecking yes
    

Security notes

  • Passwords are encrypted in the OS keyring
  • No plaintext files or hardcoded passwords
  • Works safely for multiple servers and multiple users
  • Fully compatible with terminal SSH calls or tools that invoke SSH under the hood
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment