Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

SSH Temporal Keys - User Guide

Quick Start

Generate and Connect with Temporary Key

The fastest way to use temporal SSH keys:

# Auto-generate, deploy, and connect (key auto-revoked after disconnect)
ssh connect server.example.com

# Connect with custom user and TTL
ssh connect server.example.com --user deploy --ttl 30min

# Keep key active after disconnect
ssh connect server.example.com --keep

Manual Key Management

For more control over the key lifecycle:

# 1. Generate key
ssh generate-key server.example.com --user root --ttl 1hr

# Output:
# ✓ SSH key generated successfully
#   Key ID: abc-123-def-456
#   Type: dynamickeypair
#   User: root
#   Server: server.example.com
#   Expires: 2024-01-01T13:00:00Z
#   Fingerprint: SHA256:...
#
# Private Key (save securely):
# -----BEGIN OPENSSH PRIVATE KEY-----
# ...
# -----END OPENSSH PRIVATE KEY-----

# 2. Deploy key to server
ssh deploy-key abc-123-def-456

# 3. Use the private key to connect
ssh -i /path/to/private/key root@server.example.com

# 4. Revoke when done
ssh revoke-key abc-123-def-456

Key Features

Automatic Expiration

All keys expire automatically after their TTL:

  • Default TTL: 1 hour
  • Configurable: From 5 minutes to 24 hours
  • Background Cleanup: Automatic removal from servers every 5 minutes

Multiple Key Types

Choose the right key type for your use case:

TypeDescriptionUse Case
dynamic (default)Generated Ed25519 keysQuick SSH access
caVault CA-signed certificateEnterprise with SSH CA
otpVault one-time passwordSingle-use access

Security Benefits

✅ No static SSH keys to manage ✅ Short-lived credentials (1 hour default) ✅ Automatic cleanup on expiration ✅ Audit trail for all operations ✅ Private keys never stored on disk

Common Usage Patterns

Development Workflow

# Quick SSH for debugging
ssh connect dev-server.local --ttl 30min

# Execute commands
ssh root@dev-server.local "systemctl status nginx"

# Connection closes, key auto-revokes

Production Deployment

# Generate key with longer TTL for deployment
ssh generate-key prod-server.example.com --ttl 2hr

# Deploy to server
ssh deploy-key <key-id>

# Run deployment script
ssh -i /tmp/deploy-key root@prod-server.example.com < deploy.sh

# Manual revoke when done
ssh revoke-key <key-id>

Multi-Server Access

# Generate one key
ssh generate-key server01.example.com --ttl 1hr

# Use the same private key for multiple servers (if you have provisioning access)
# Note: Currently each key is server-specific, multi-server support coming soon

Command Reference

ssh generate-key

Generate a new temporal SSH key.

Syntax:

ssh generate-key <server> [options]

Options:

  • --user <name>: SSH user (default: root)
  • --ttl <duration>: Key lifetime (default: 1hr)
  • --type <ca|otp|dynamic>: Key type (default: dynamic)
  • --ip <address>: Allowed IP (OTP mode only)
  • --principal <name>: Principal (CA mode only)

Examples:

# Basic usage
ssh generate-key server.example.com

# Custom user and TTL
ssh generate-key server.example.com --user deploy --ttl 30min

# Vault CA mode
ssh generate-key server.example.com --type ca --principal admin

ssh deploy-key

Deploy a generated key to the target server.

Syntax:

ssh deploy-key <key-id>

Example:

ssh deploy-key abc-123-def-456

ssh list-keys

List all active SSH keys.

Syntax:

ssh list-keys [--expired]

Examples:

# List active keys
ssh list-keys

# Show only deployed keys
ssh list-keys | where deployed == true

# Include expired keys
ssh list-keys --expired

ssh get-key

Get detailed information about a specific key.

Syntax:

ssh get-key <key-id>

Example:

ssh get-key abc-123-def-456

ssh revoke-key

Immediately revoke a key (removes from server and tracking).

Syntax:

ssh revoke-key <key-id>

Example:

ssh revoke-key abc-123-def-456

ssh connect

Auto-generate, deploy, connect, and revoke (all-in-one).

Syntax:

ssh connect <server> [options]

Options:

  • --user <name>: SSH user (default: root)
  • --ttl <duration>: Key lifetime (default: 1hr)
  • --type <ca|otp|dynamic>: Key type (default: dynamic)
  • --keep: Don’t revoke after disconnect

Examples:

# Quick connection
ssh connect server.example.com

# Custom user
ssh connect server.example.com --user deploy

# Keep key active after disconnect
ssh connect server.example.com --keep

ssh stats

Show SSH key statistics.

Syntax:

ssh stats

Example Output:

SSH Key Statistics:
  Total generated: 42
  Active keys: 10
  Expired keys: 32

Keys by type:
  dynamic: 35
  otp: 5
  certificate: 2

Last cleanup: 2024-01-01T12:00:00Z
  Cleaned keys: 5

ssh cleanup

Manually trigger cleanup of expired keys.

Syntax:

ssh cleanup

ssh test

Run a quick test of the SSH key system.

Syntax:

ssh test <server> [--user <name>]

Example:

ssh test server.example.com --user root

ssh help

Show help information.

Syntax:

ssh help

Duration Formats

The --ttl option accepts various duration formats:

FormatExampleMeaning
Minutes30min30 minutes
Hours2hr2 hours
Mixed1hr 30min1.5 hours
Seconds3600sec1 hour

Working with Private Keys

Saving Private Keys

When you generate a key, save the private key immediately:

# Generate and save to file
ssh generate-key server.example.com | get private_key | save -f ~/.ssh/temp_key
chmod 600 ~/.ssh/temp_key

# Use the key
ssh -i ~/.ssh/temp_key root@server.example.com

# Cleanup
rm ~/.ssh/temp_key

Using SSH Agent

Add the temporary key to your SSH agent:

# Generate key and extract private key
ssh generate-key server.example.com | get private_key | save -f /tmp/temp_key
chmod 600 /tmp/temp_key

# Add to agent
ssh-add /tmp/temp_key

# Connect (agent provides the key automatically)
ssh root@server.example.com

# Remove from agent
ssh-add -d /tmp/temp_key
rm /tmp/temp_key

Troubleshooting

Key Deployment Fails

Problem: ssh deploy-key returns error

Solutions:

  1. Check SSH connectivity to server:

    ssh root@server.example.com
    
  2. Verify provisioning key is configured:

    echo $PROVISIONING_SSH_KEY
    
  3. Check server SSH daemon:

    ssh root@server.example.com "systemctl status sshd"
    

Private Key Not Working

Problem: SSH connection fails with “Permission denied (publickey)”

Solutions:

  1. Verify key was deployed:

    ssh list-keys | where id == "<key-id>"
    
  2. Check key hasn’t expired:

    ssh get-key <key-id> | get expires_at
    
  3. Verify private key permissions:

    chmod 600 /path/to/private/key
    

Cleanup Not Running

Problem: Expired keys not being removed

Solutions:

  1. Check orchestrator is running:

    curl http://localhost:9090/health
    
  2. Trigger manual cleanup:

    ssh cleanup
    
  3. Check orchestrator logs:

    tail -f ./data/orchestrator.log | grep SSH
    

Best Practices

Security

  1. Short TTLs: Use the shortest TTL that works for your task

    ssh connect server.example.com --ttl 30min
    
  2. Immediate Revocation: Revoke keys when you’re done

    ssh revoke-key <key-id>
    
  3. Private Key Handling: Never share or commit private keys

    # Save to temp location, delete after use
    ssh generate-key server.example.com | get private_key | save -f /tmp/key
    # ... use key ...
    rm /tmp/key
    

Workflow Integration

  1. Automated Deployments: Generate key in CI/CD

    #!/bin/bash
    KEY_ID=$(ssh generate-key prod.example.com --ttl 1hr | get id)
    ssh deploy-key $KEY_ID
    # Run deployment
    ansible-playbook deploy.yml
    ssh revoke-key $KEY_ID
    
  2. Interactive Use: Use ssh connect for quick access

    ssh connect dev.example.com
    
  3. Monitoring: Check statistics regularly

    ssh stats
    

Advanced Usage

Vault Integration

If your organization uses HashiCorp Vault:

# Generate CA-signed certificate
ssh generate-key server.example.com --type ca --principal admin --ttl 1hr

# Vault signs your public key
# Server must trust Vault CA certificate

Setup (one-time):

# On servers, add to /etc/ssh/sshd_config:
TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem

# Get Vault CA public key:
vault read -field=public_key ssh/config/ca | \
  sudo tee /etc/ssh/trusted-user-ca-keys.pem

# Restart SSH:
sudo systemctl restart sshd

OTP Mode

# Generate one-time password
ssh generate-key server.example.com --type otp --ip 192.168.1.100

# Use the OTP to connect (single use only)

Scripting

Use in scripts for automated operations:

# deploy.nu
def deploy [target: string] {
    let key = (ssh generate-key $target --ttl 1hr)
    ssh deploy-key $key.id

    # Run deployment
    try {
        ssh $"root@($target)" "bash /path/to/deploy.sh"
    } catch {
        print "Deployment failed"
    }

    # Always cleanup
    ssh revoke-key $key.id
}

API Integration

For programmatic access, use the REST API:

# Generate key
curl -X POST http://localhost:9090/api/v1/ssh/generate \
  -H "Content-Type: application/json" \
  -d '{
    "key_type": "dynamickeypair",
    "user": "root",
    "target_server": "server.example.com",
    "ttl_seconds": 3600
  }'

# Deploy key
curl -X POST http://localhost:9090/api/v1/ssh/{key_id}/deploy

# List keys
curl http://localhost:9090/api/v1/ssh/keys

# Get stats
curl http://localhost:9090/api/v1/ssh/stats

FAQ

Q: Can I use the same key for multiple servers? A: Currently, each key is tied to a specific server. Multi-server support is planned.

Q: What happens if the orchestrator crashes? A: Keys in memory are lost, but keys already deployed to servers remain until their expiration time.

Q: Can I extend the TTL of an existing key? A: No, you must generate a new key. This is by design for security.

Q: What’s the maximum TTL? A: Configurable by admin, default maximum is 24 hours.

Q: Are private keys stored anywhere? A: Private keys exist only in memory during generation and are shown once to the user. They are never written to disk by the system.

Q: What happens if cleanup fails? A: The key remains in authorized_keys until the next cleanup run. You can trigger manual cleanup with ssh cleanup.

Q: Can I use this with non-root users? A: Yes, use --user <username> when generating the key.

Q: How do I know when my key will expire? A: Use ssh get-key <key-id> to see the exact expiration timestamp.

Support

For issues or questions:

  1. Check orchestrator logs: tail -f ./data/orchestrator.log
  2. Run diagnostics: ssh stats
  3. Test connectivity: ssh test server.example.com
  4. Review documentation: SSH_KEY_MANAGEMENT.md

See Also

  • Architecture: SSH_KEY_MANAGEMENT.md
  • Implementation: SSH_IMPLEMENTATION_SUMMARY.md
  • Configuration: config/ssh-config.toml.example