Skip to content

Instantly share code, notes, and snippets.

@jdonohoo
Last active May 27, 2026 17:10
Show Gist options
  • Select an option

  • Save jdonohoo/ccd8c462736fd95a32bbbd92005d3d58 to your computer and use it in GitHub Desktop.

Select an option

Save jdonohoo/ccd8c462736fd95a32bbbd92005d3d58 to your computer and use it in GitHub Desktop.
unlock keyring with passphrase on ubuntu 22.04 autologin

GNOME Keyring Auto-Unlock for Autologin Systems

This guide sets up automatic keyring unlocking on Ubuntu/Zorin systems with autologin enabled. This allows startup scripts and services (like RDP) to access stored credentials without manual intervention.

Why Use Passwords on Keyrings?

While empty passwords are simpler for autologin, recent Ubuntu versions have a bug where keyrings with empty passwords can get randomly reset/corrupted after updates. Using a password prevents this data loss.

Prerequisites

sudo apt-get install -y gnome-keyring libsecret-tools dbus-x11

Setup Instructions

1. Create Keyring Password File

# Create password file (replace 'YourPassword' with your actual password)
# Using printf ensures exact format: 8 characters + newline
printf "YourPassword\n" > ~/.keyring_pass
chmod 600 ~/.keyring_pass

Note on the newline: The newline is included for two reasons:

  1. Standard Unix convention (text files end with newline)
  2. Matches the working configuration from other nodes
  3. Both with and without newline work, but this is more consistent

Verify:

wc -c ~/.keyring_pass  # Should show: 9 (8 chars + newline)
od -c ~/.keyring_pass  # Should show your password followed by \n

2. Set Keyring Passwords

Both Login and Default keyrings must use the same password as in ~/.keyring_pass.

# Open Passwords and Keys GUI
seahorse &

Then:

  1. Login keyring:

    • Right-click "Login" → "Change Password"
    • Enter current password
    • Set new password to match ~/.keyring_pass (8 characters, no newline when typing)
  2. Default keyring:

    • Right-click "Default keyring" → "Change Password"
    • Enter current password
    • Set new password to the same as Login keyring

Why both need the same password: gnome-keyring-daemon --unlock only unlocks the Login keyring directly, but if both keyrings share the same password, both become accessible.

3. Create Unlock Script

cat > ~/.config/unlock-keyring.sh << 'EOF'
#!/bin/bash

export DISPLAY=:0
export XDG_RUNTIME_DIR=/run/user/$(id -u)

password=$(<"$HOME/.keyring_pass")
/usr/bin/gnome-keyring-daemon --unlock <<< "$password"
EOF

chmod +x ~/.config/unlock-keyring.sh

4. Create Systemd Service

mkdir -p ~/.config/systemd/user

cat > ~/.config/systemd/user/unlock-keyring.service << 'EOF'
[Unit]
Description=Unlock GNOME Keyring
After=graphical-session.target

[Service]
Type=oneshot
ExecStart=%h/.config/unlock-keyring.sh
RemainAfterExit=true
Environment=DISPLAY=:0
Environment=XDG_RUNTIME_DIR=/run/user/%U

[Install]
WantedBy=default.target
EOF

5. Enable Service

systemctl --user daemon-reload
systemctl --user enable unlock-keyring.service
systemctl --user start unlock-keyring.service  # Test it

6. Verify Setup

Create a verification script:

cat > ~/.config/check-keyring-status.sh << 'EOF'
#!/bin/bash

echo "========================================"
echo "  GNOME Keyring Status Check"
echo "========================================"
echo ""

# Check if gnome-keyring-daemon is running
if pgrep -x gnome-keyring-d > /dev/null; then
    echo "✓ gnome-keyring-daemon is running"
else
    echo "✗ gnome-keyring-daemon is NOT running"
    exit 1
fi

echo ""

# Check keyring status using Python
python3 << 'PYEOF'
import dbus
import sys

try:
    bus = dbus.SessionBus()
    service = bus.get_object('org.freedesktop.secrets', '/org/freedesktop/secrets')
    collections = service.Get('org.freedesktop.Secret.Service', 'Collections',
                             dbus_interface='org.freedesktop.DBus.Properties')

    print("Keyring Status:")
    print("-" * 40)

    all_unlocked = True
    important_unlocked = True

    for coll_path in collections:
        coll = bus.get_object('org.freedesktop.secrets', coll_path)
        label = coll.Get('org.freedesktop.Secret.Collection', 'Label',
                        dbus_interface='org.freedesktop.DBus.Properties')
        locked = coll.Get('org.freedesktop.Secret.Collection', 'Locked',
                         dbus_interface='org.freedesktop.DBus.Properties')

        try:
            items = coll.Get('org.freedesktop.Secret.Collection', 'Items',
                            dbus_interface='org.freedesktop.DBus.Properties')
            item_count = len(items)
        except:
            item_count = "?"

        status_symbol = "✗ LOCKED  " if locked else "✓ UNLOCKED"
        print(f"{status_symbol} | {label:20s} | {item_count} items")

        # Track if important keyrings are unlocked
        if label in ['Default keyring', 'Default', 'Login']:
            if locked:
                important_unlocked = False

        if locked:
            all_unlocked = False

    print("-" * 40)
    print("")

    # Overall status
    if all_unlocked:
        print("✓✓✓ SUCCESS: All keyrings are unlocked!")
        sys.exit(0)
    elif important_unlocked:
        print("✓ PARTIAL: Login and Default keyrings are unlocked")
        print("  (Some other keyrings may be locked, but that's OK)")
        sys.exit(0)
    else:
        print("✗✗✗ FAILURE: Important keyrings are still locked!")
        print("")
        print("Troubleshooting:")
        print("1. Check that Login and Default keyrings have the same password")
        print("2. Verify password in ~/.keyring_pass matches keyring passwords")
        print("3. Check service status: systemctl --user status unlock-keyring.service")
        print("4. Check logs: journalctl --user -u unlock-keyring.service")
        sys.exit(1)

except Exception as e:
    print(f"ERROR: {e}")
    import traceback
    traceback.print_exc()
    sys.exit(1)
PYEOF

echo ""
echo "========================================"
echo "  Service Status"
echo "========================================"
systemctl --user status unlock-keyring.service --no-pager | head -10
EOF

chmod +x ~/.config/check-keyring-status.sh

Test it:

bash ~/.config/check-keyring-status.sh

Expected output:

✓✓✓ SUCCESS: All keyrings are unlocked!

7. Reboot and Verify

sudo reboot

After reboot:

bash ~/.config/check-keyring-status.sh

Troubleshooting

Check service status

systemctl --user status unlock-keyring.service

Check service logs

journalctl --user -u unlock-keyring.service --no-pager

Manually test unlock

~/.config/unlock-keyring.sh

Verify password file

wc -c ~/.keyring_pass      # Should be 9 bytes
od -c ~/.keyring_pass      # Should show password + \n

Common Issues

Service fails with "Exec format error" (203/EXEC):

  • Script isn't executable: chmod +x ~/.config/unlock-keyring.sh

Keyrings stay locked after reboot:

  • Login and Default keyrings don't have the same password
  • Password in ~/.keyring_pass doesn't match the keyring passwords
  • Verify with seahorse: seahorse &

Password file wrong size:

# Recreate with exact format (8 chars + newline = 9 bytes)
printf "YourPass\n" > ~/.keyring_pass
chmod 600 ~/.keyring_pass

How It Works

  1. Autologin starts your session
  2. Systemd user service runs unlock-keyring.sh after graphical session starts
  3. Script reads password from ~/.keyring_pass
  4. gnome-keyring-daemon --unlock unlocks the Login keyring with that password
  5. Both keyrings become accessible (since they share the same password)
  6. Startup scripts can now access credentials stored in the keyrings

Security Notes

  • ~/.keyring_pass has 600 permissions (only you can read it)
  • Physical access to machine is already required (autologin)
  • Using a password prevents keyring corruption from Ubuntu bugs
  • The session keyring (empty name) is temporary and always unlocked - this is normal

About the Session Keyring

You may see a keyring with an empty name in the status - this is the session keyring. It's:

  • Automatically created each login
  • Always unlocked (no password)
  • Temporary (destroyed on logout)
  • Used for SSH agent keys and temporary credentials
  • Completely normal - you can ignore it

Additional Notes

For RDP access: If you're using GNOME Remote Desktop, ensure your RDP credentials are stored in either the Login or Default keyring (both will be unlocked with this setup).

For other services: Any service that needs keyring access on startup will now work, as both Login and Default keyrings are unlocked automatically.

Updating the password: If you change your keyring passwords:

  1. Update both Login and Default keyrings to the same new password
  2. Update ~/.keyring_pass to match
  3. Reboot and verify

References

@josselinonduty
Copy link
Copy Markdown

josselinonduty commented Feb 8, 2026

@jdonohoo thanks for the gist
Why is there a requirement on the password length?

@jdonohoo
Copy link
Copy Markdown
Author

@josselinonduty you can change it this was just a script I was using on an ubuntu fleet that had that character limit, so the check was added for that use case, then when I went and sanitized it to make it a public gist it was a relic of that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment