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.
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.
sudo apt-get install -y gnome-keyring libsecret-tools dbus-x11# 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_passNote on the newline: The newline is included for two reasons:
- Standard Unix convention (text files end with newline)
- Matches the working configuration from other nodes
- 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 \nBoth Login and Default keyrings must use the same password as in ~/.keyring_pass.
# Open Passwords and Keys GUI
seahorse &Then:
-
Login keyring:
- Right-click "Login" → "Change Password"
- Enter current password
- Set new password to match
~/.keyring_pass(8 characters, no newline when typing)
-
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.
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.shmkdir -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
EOFsystemctl --user daemon-reload
systemctl --user enable unlock-keyring.service
systemctl --user start unlock-keyring.service # Test itCreate 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.shTest it:
bash ~/.config/check-keyring-status.shExpected output:
✓✓✓ SUCCESS: All keyrings are unlocked!
sudo rebootAfter reboot:
bash ~/.config/check-keyring-status.shsystemctl --user status unlock-keyring.servicejournalctl --user -u unlock-keyring.service --no-pager~/.config/unlock-keyring.shwc -c ~/.keyring_pass # Should be 9 bytes
od -c ~/.keyring_pass # Should show password + \nService 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_passdoesn'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- Autologin starts your session
- Systemd user service runs
unlock-keyring.shafter graphical session starts - Script reads password from
~/.keyring_pass - gnome-keyring-daemon --unlock unlocks the Login keyring with that password
- Both keyrings become accessible (since they share the same password)
- Startup scripts can now access credentials stored in the keyrings
~/.keyring_passhas 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
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
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:
- Update both Login and Default keyrings to the same new password
- Update
~/.keyring_passto match - Reboot and verify
- Man page:
man gnome-keyring-daemon - Secret Service API: https://specifications.freedesktop.org/secret-service/
- Ubuntu Keyring Documentation: https://help.ubuntu.com/community/Gnome-keyring
@jdonohoo thanks for the gist
Why is there a requirement on the password length?