Ledger Nano S Setup Guide
Goal: Secure SSH authentication, GPG signing, and SOPS secret management using your Ledger Nano S, all integrated with your Nix flake.
Stack:
- Hardware: Ledger Nano S
- SSH/GPG:
ledger-agent
(from trezor-agent package) - Secrets: SOPS + GPG
- Platform: macOS with Nix/nix-darwin
Table of Contents
Section titled “Table of Contents”- Prerequisites
- Step 1: Install Software via Nix
- Step 2: Initialize Your Ledger Device
- Step 3: Install SSH/GPG App on Ledger
- Step 4: Configure GPG with Ledger
- Step 5: Configure SSH with Ledger
- Step 6: Configure SOPS with Ledger GPG
- Quick Reference
- Troubleshooting
- Security Notes
- Next Steps
Prerequisites
Section titled “Prerequisites”- Ledger Nano S device
- USB cable
- macOS system with Nix installed
- This Nix configuration cloned locally
Step 1: Install Software via Nix
Section titled “Step 1: Install Software via Nix”The hardware security profile includes all required software. It’s already configured in your setup via the hardware-security.nix
profile.
What’s Included
Section titled “What’s Included”Nix packages (from nix/profiles/hardware-security.nix
):
ledger-agent
- Ledger SSH/GPG agent from trezor-agentledger-ssh-agent
- Standalone SSH agent for Ledgergnupg
- GPG for encryption/signingsops
- Secrets management (fromnix/modules/secrets/sops.nix
)
Homebrew casks (from nix/modules/darwin/homebrew.nix
):
ledger-live
- GUI app for Ledger device management
Apply Configuration
Section titled “Apply Configuration”If not already activated, apply your Nix configuration:
cd /Users/wikigen/Configdarwin-rebuild switch --flake .#wikigen-mac
Verify Installation
Section titled “Verify Installation”# CLI tools (from Nix)which ledger-agentwhich ledger-gpg-agentwhich sops
# GUI app (from Homebrew)open -a "Ledger Live"
Status: ✅ Already configured in your Nix flake
Step 2: Initialize Your Ledger Device
Section titled “Step 2: Initialize Your Ledger Device”Launch Ledger Live
Section titled “Launch Ledger Live”open -a "Ledger Live"
Connect and Initialize
Section titled “Connect and Initialize”- Connect your Ledger Nano S via USB
- Follow the on-screen setup:
- Choose “Set up as new device”
- CRITICAL: Write down your 24-word recovery phrase on paper
- Store it in a safe place (NOT on your computer)
- Set a PIN code (6-8 digits recommended)
- Confirm your recovery phrase by entering words when prompted
Update Firmware
Section titled “Update Firmware”Ledger Live will check for firmware updates. Install any available updates to ensure compatibility with latest apps.
Status: ✅ Complete when device is initialized
Step 3: Install SSH/GPG App on Ledger
Section titled “Step 3: Install SSH/GPG App on Ledger”The SSH/PGP Agent app enables your Ledger to handle SSH authentication and GPG operations.
Enable Developer Mode
Section titled “Enable Developer Mode”- Open Ledger Live
- Click the gear icon (⚙️) in the top right for Settings
- Navigate to “Experimental features” tab
- Toggle “Developer mode” to ON
This reveals developer apps including SSH/PGP Agent.
Install SSH/PGP Agent
Section titled “Install SSH/PGP Agent”- Navigate to “Manager” (left sidebar)
- Connect and unlock your Ledger device (enter PIN)
- Search for “SSH/PGP Agent”
- Click “Install” button
- Confirm on your Ledger device (press both buttons)
- Wait for installation to complete
Verify Installation
Section titled “Verify Installation”On your Ledger device:
- Scroll through apps
- You should see “SSH/PGP Agent”
- Open it (press both buttons)
- Screen should show “SSH/PGP Agent is ready”
Status: ✅ Complete when app is installed
Step 4: Configure GPG with Ledger
Section titled “Step 4: Configure GPG with Ledger”Your Nix configuration automatically sets up GPG to use your Ledger for signing and encryption.
Initialize Ledger GPG Agent
Section titled “Initialize Ledger GPG Agent”The hardware-security profile includes a launchd service that automatically starts ledger-gpg-agent
on login. To start it manually:
ledger-gpg-agent --homedir ~/.gnupg-ledger --server --verbose &
Generate/Import GPG Key on Ledger
Section titled “Generate/Import GPG Key on Ledger”The Ledger SSH/PGP Agent app generates keys based on your device’s seed (24-word phrase). To get your GPG public key:
# Set GPG home directoryexport GNUPGHOME=~/.gnupg-ledger
# Start agent if not runningledger-gpg-agent --homedir ~/.gnupg-ledger --server --verbose &sleep 2
# Get your public keyledger-gpg-agent --homedir ~/.gnupg-ledger -v
The output will show your GPG key fingerprint. In this configuration, it’s:
D2A7EC63E350CC488197CB2ED369B07E00FB233E
Import Public Key to System
Section titled “Import Public Key to System”# Export public keygpg --homedir ~/.gnupg-ledger --export --armor > ~/ledger-gpg-public.asc
# Import to system keyring (optional, for verification)gpg --import ~/ledger-gpg-public.asc
Test GPG Signing
Section titled “Test GPG Signing”# Ensure Ledger is unlocked and SSH/GPG Agent app is openecho "test" | gpg --homedir ~/.gnupg-ledger --clearsign
The Ledger will display “Sign message” - press the button to confirm.
Status: ✅ Configured via nix/profiles/hardware-security.nix
Step 5: Configure SSH with Ledger
Section titled “Step 5: Configure SSH with Ledger”Your Nix configuration includes two SSH agent options:
Option 1: GPG Agent for SSH (Recommended)
Section titled “Option 1: GPG Agent for SSH (Recommended)”Uses gpg-agent
with SSH support (already configured):
# The hardware-security profile sets this automatically:export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
Get your SSH public key:
ssh-add -L
Option 2: Ledger SSH Agent (Alternative)
Section titled “Option 2: Ledger SSH Agent (Alternative)”Uses ledger-agent
directly:
# The launchd service starts this automatically# Or run manually:ledger-agent -d ssh://ledger@localhost
Get your SSH public key:
ssh-add -L
Add to GitHub/Servers
Section titled “Add to GitHub/Servers”- Copy your SSH public key:
ssh-add -L | pbcopy
- GitHub: Settings → SSH Keys → New SSH key
- Servers: Add to
~/.ssh/authorized_keys
Test SSH Authentication
Section titled “Test SSH Authentication”# Test GitHubssh -T git@github.com
# The Ledger will prompt for confirmation - press button
Status: ✅ Configured via nix/profiles/hardware-security.nix
Step 6: Configure SOPS with Ledger GPG
Section titled “Step 6: Configure SOPS with Ledger GPG”SOPS (Secrets OPerationS) uses your Ledger GPG key for encrypting/decrypting secrets.
SOPS Configuration
Section titled “SOPS Configuration”Your configuration includes (from nix/modules/secrets/sops.nix
):
sops = { gnupg.home = "~/.gnupg-ledger"; defaultSopsFile = ./nix/secrets/secrets.yaml;};
environment.variables = { GNUPGHOME = "/Users/wikigen/.gnupg-ledger";};
SOPS Rules
Section titled “SOPS Rules”The .sops.yaml
file specifies your GPG key for encryption:
creation_rules: - path_regex: .*\.(yaml|json|env|ini)$ pgp: >- D2A7EC63E350CC488197CB2ED369B07E00FB233E
Create Your First Secret
Section titled “Create Your First Secret”# Set GPG homeexport GNUPGHOME=~/.gnupg-ledger
# Ensure ledger-gpg-agent is runningpgrep -f ledger-gpg-agent || \ ledger-gpg-agent --homedir ~/.gnupg-ledger --server --verbose &
# Create/edit encrypted secretsops nix/secrets/secrets.yaml
What happens:
- SOPS contacts Ledger via
ledger-gpg-agent
- Ledger displays “Sign message”
- Press button to confirm
- Editor opens with decrypted content
- Make changes and save
- SOPS re-encrypts on save
Use Secret in Nix
Section titled “Use Secret in Nix”In your host configuration:
{ # Declare a secret sops.secrets."example/api_key" = {};
# Secret available at runtime: # /run/secrets/example/api_key}
Rebuild your system:
darwin-rebuild switch --flake .#wikigen-mac
Status: ✅ Configured via nix/modules/secrets/sops.nix
Quick Reference
Section titled “Quick Reference”Environment Setup
Section titled “Environment Setup”# Add to ~/.zshrc for persistent configexport GNUPGHOME=~/.gnupg-ledgerexport SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)export GPG_TTY=$(tty)
Common Commands
Section titled “Common Commands”# GPGecho "test" | gpg --clearsign # Test GPG signinggpg --list-keys # List GPG keys
# SSHssh-add -L # Show SSH public keyssh -T git@github.com # Test GitHub SSH
# SOPSsops nix/secrets/secrets.yaml # Edit secretssops -d nix/secrets/secrets.yaml # View secretssops -d --extract '["key"]' secrets.yaml # Extract specific value
# Agentspgrep -f ledger-gpg-agent # Check GPG agentpgrep -f ledger-agent # Check SSH agentledger-gpg-agent --homedir ~/.gnupg-ledger -v # Get GPG fingerprint
File Locations
Section titled “File Locations”- GPG keyring:
~/.gnupg-ledger/
- GPG agent log:
~/.local/share/ledger-gpg-agent.log
- SSH agent log:
~/.local/share/ledger-ssh-agent.log
- SOPS config:
.sops.yaml
- Secrets:
nix/secrets/
- Decrypted secrets (runtime):
/run/secrets/
Key Information
Section titled “Key Information”- GPG Fingerprint:
D2A7EC63E350CC488197CB2ED369B07E00FB233E
- Identity: Luc Chartier luc@distorted.media
- Algorithm: ECDSA (NIST P-256)
- Storage: Ledger Nano S hardware wallet
Troubleshooting
Section titled “Troubleshooting”Ledger Not Responding
Section titled “Ledger Not Responding”Checklist:
- Ledger connected via USB
- Ledger unlocked (PIN entered)
- SSH/GPG Agent app is open on device
- Screen shows “SSH/GPG Agent is ready”
- Agent process is running
Test:
# Check agent is runningpgrep -f ledger-gpg-agent
# If not, start itledger-gpg-agent --homedir ~/.gnupg-ledger --server --verbose &sleep 2
# Test GPG operationecho "test" | gpg --homedir ~/.gnupg-ledger --clearsign
“No GPG key found”
Section titled ““No GPG key found””Solution:
# Ensure GNUPGHOME is setexport GNUPGHOME=~/.gnupg-ledger
# Verify key is visiblegpg --list-keys
# Should show: D2A7EC63E350CC488197CB2ED369B07E00FB233E
“Failed to get data key” (SOPS)
Section titled ““Failed to get data key” (SOPS)”Solution:
# Check .sops.yaml has correct fingerprintcat .sops.yaml
# Verify fingerprint matchesgpg --list-keys --fingerprint
# Ensure agent is runningpgrep -f ledger-gpg-agent || \ ledger-gpg-agent --homedir ~/.gnupg-ledger --server --verbose &
SSH Authentication Fails
Section titled “SSH Authentication Fails”Solution:
# Check SSH agent socketecho $SSH_AUTH_SOCK
# Or set it manually:export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
# Verify key is loadedssh-add -L
# Test with verbose outputssh -vT git@github.com
Agent Crashes on Operation
Section titled “Agent Crashes on Operation”Solution:
# Kill existing agentskillall ledger-gpg-agentkillall ledger-agent
# Check Ledger is ready# 1. Ledger unlocked# 2. SSH/GPG Agent app open# 3. Screen shows "ready"
# Restart agentledger-gpg-agent --homedir ~/.gnupg-ledger --server --verbose &sleep 2
# Check logstail -f ~/.local/share/ledger-gpg-agent.error.log
SOPS Opens Wrong Editor
Section titled “SOPS Opens Wrong Editor”Solution:
# Set editor in ~/.zshrcexport EDITOR="nano" # or "code --wait", "vim", etc.
# Or for single commandEDITOR=nano sops secrets.yaml
Security Notes
Section titled “Security Notes”Hardware Security
Section titled “Hardware Security”- Private keys never leave Ledger: Only signs/decrypts on device
- Physical confirmation required: Must press button for every operation
- No remote exploitation: Can’t decrypt without physical device
- Recovery: Keys derived from 24-word seed (keep secure!)
Threat Model
Section titled “Threat Model”What Ledger protects against:
- ✅ Key extraction from computer
- ✅ Malware stealing keys from disk
- ✅ Remote attacks on SSH/GPG keys
- ✅ Unauthorized signing/decryption
What Ledger doesn’t protect against:
- ❌ Malware intercepting decrypted data in memory
- ❌ Physical theft of device (PIN provides basic protection)
- ❌ Compromise of device if seed phrase is leaked
- ❌ Side-channel attacks on device itself
Operational Security
Section titled “Operational Security”- Lock screen when away from computer
- Remove Ledger when not actively using it
- Never share your 24-word recovery phrase
- Store seed phrase in secure physical location
- Use unique PIN - not shared with other devices
- Audit operations via Git history (SOPS commits)
- Rotate secrets if device is lost or compromised
Backup Strategy
Section titled “Backup Strategy”Your keys are derived from your 24-word recovery phrase:
- Primary backup: Recovery phrase written on paper, stored securely
- Alternative access: Consider a second Ledger restored from same seed
- Test recovery: Periodically verify you can restore from seed
- SOPS multi-key: Add additional GPG keys to
.sops.yaml
for team access
Next Steps
Section titled “Next Steps”Now that your Ledger is configured:
SSH Authentication
Section titled “SSH Authentication”- Add SSH public key to GitHub
- Add SSH public key to servers
- Test authentication:
ssh -T git@github.com
GPG Signing
Section titled “GPG Signing”- Configure git signing (already done in
hardware-security.nix
) - Make a test commit to verify signing
- Add GPG public key to GitHub for verified commits
SOPS Secrets
Section titled “SOPS Secrets”- Create first secret:
sops nix/secrets/secrets.yaml
- Use secret in config:
sops.secrets."my-app/api-key" = {};
- Rebuild system:
darwin-rebuild switch --flake .#wikigen-mac
- Verify secret:
ls -l /run/secrets/
Advanced Usage
Section titled “Advanced Usage”- Set up multi-user SOPS access
- Configure secret rotation procedures
- Add secrets for cloud deployments
- Integrate with CI/CD pipelines
Related Documentation
Section titled “Related Documentation”- Ledger Deep Dive - Comprehensive hardware security guide
- GPG Signing - GPG configuration and commit signing
- SSH Authentication - SSH with hardware wallet
- SOPS Guide - Complete SOPS documentation
- Design Doc - Overall Nix configuration architecture
External References
Section titled “External References”- Ledger SSH/GPG Agent - Official Ledger app
- Trezor Agent - Agent software (supports Ledger)
- SOPS - Secrets management
- GPG Documentation - GPG reference
Happy hardware security! 🔐