SSH Configuration
Secure shell configuration and advanced usage.
SSH Key Management
# Generate Ed25519 key (recommended)
ssh-keygen -t ed25519 -C "user@host" # Interactive
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_vault -N "" -C "vault-ssh-ca" # Non-interactive
# Generate RSA key (for legacy systems)
ssh-keygen -t rsa -b 4096 -C "user@host"
# Generate key for specific purpose
ssh-keygen -t ed25519 -f ~/.ssh/id_github -C "github-personal"
ssh-keygen -t ed25519 -f ~/.ssh/id_work -C "work-servers"
# Hardware security keys (FIDO2/YubiKey)
ssh-keygen -t ed25519-sk -C "yubikey-resident" # Requires touch
ssh-keygen -t ecdsa-sk -O resident -C "yubikey" # Resident key (stored on device)
ssh-keygen -t ed25519-sk -O verify-required -C "key" # PIN required
# View key fingerprint
ssh-keygen -l -f ~/.ssh/id_ed25519.pub # SHA256 fingerprint
ssh-keygen -l -f ~/.ssh/id_ed25519.pub -E md5 # MD5 fingerprint (legacy)
ssh-keygen -lv -f ~/.ssh/id_ed25519.pub # With randomart
# Change key passphrase
ssh-keygen -p -f ~/.ssh/id_ed25519
# Convert key formats
ssh-keygen -e -f ~/.ssh/id_ed25519.pub > key.pem # OpenSSH to PEM
ssh-keygen -i -f key.pem > key.pub # PEM to OpenSSH
# Extract public key from private
ssh-keygen -y -f ~/.ssh/id_ed25519 > ~/.ssh/id_ed25519.pub
SSH Agent
# Start agent (if not running)
eval $(ssh-agent -s)
# Add key to agent
ssh-add ~/.ssh/id_ed25519
ssh-add # Add default keys
ssh-add -t 3600 ~/.ssh/id_ed25519 # 1 hour timeout
# List loaded keys
ssh-add -l # Fingerprints
ssh-add -L # Full public keys
# Remove keys
ssh-add -d ~/.ssh/id_ed25519 # Remove specific
ssh-add -D # Remove all
# Agent forwarding (use carefully!)
ssh -A user@jumphost # Forward agent to remote
# Then from jumphost: ssh user@internal-server (uses forwarded key)
# Check agent socket
echo $SSH_AUTH_SOCK
# Systemd user agent (persistent)
systemctl --user enable --now ssh-agent
# Add to ~/.bashrc or ~/.zshrc:
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"
# Forward agent with specific socket
SSH_AUTH_SOCK=/run/user/1000/ssh-agent.socket ssh user@host
# YubiKey agent integration
# Keys are in hardware, no ssh-add needed
# Just configure ~/.ssh/config with IdentityFile
SSH Certificates (Vault SSH CA)
# SSH certificates provide:
# - No need to distribute authorized_keys to every host
# - Automatic expiration (no stale keys)
# - Centralized revocation
# - Audit trail of who signed what
# Generate signing key pair (CA)
ssh-keygen -t ed25519 -f /etc/ssh/ca_user_key -C "user-ca"
# Sign a user key (manual)
ssh-keygen -s /etc/ssh/ca_user_key \
-I "user-cert-20260227" \
-n "ansible,evanusmodestus,root" \
-V +8h \
~/.ssh/id_ed25519.pub
# View certificate details
ssh-keygen -L -f ~/.ssh/id_ed25519-cert.pub
# Output shows:
# Type: ssh-ed25519-cert-v01@openssh.com user certificate
# Public key: ED25519-CERT SHA256:...
# Signing CA: ED25519 SHA256:... (using ed25519-sk)
# Key ID: "user-cert-20260227"
# Valid: from 2026-02-27T10:00:00 to 2026-02-27T18:00:00
# Principals:
# ansible
# evanusmodestus
# root
# Extensions:
# permit-pty
# permit-user-rc
# Host trusts CA (add to sshd_config or sshd_config.d/)
# TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pub
# The CA public key goes in /etc/ssh/trusted-user-ca-keys.pub
# NOT in authorized_keys
Vault SSH CA Integration
# Vault provides automatic SSH certificate signing
# No manual CA key management needed
# Prerequisites
export VAULT_ADDR="https://vault-01.inside.domusdigitalis.dev:8200"
export VAULT_TOKEN="$(cat ~/.vault-token)"
# Sign public key via Vault CLI
vault write -field=signed_key ssh/sign/domus-client \
public_key=@$HOME/.ssh/id_ed25519_vault.pub \
valid_principals="ansible,evanusmodestus,root,adminerosado" \
>| ~/.ssh/id_ed25519_vault-cert.pub
# Sign via curl (API)
curl -sk -X POST -H "X-Vault-Token: $VAULT_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"public_key\": \"$(cat ~/.ssh/id_ed25519_vault.pub)\",
\"valid_principals\": \"ansible,evanusmodestus,root\"
}" \
"$VAULT_ADDR/v1/ssh/sign/domus-client" | jq -r '.data.signed_key' \
> ~/.ssh/id_ed25519_vault-cert.pub
# Automated signing script (vault-ssh-sign)
#!/bin/bash
set -euo pipefail
KEY_PATH="${1:-$HOME/.ssh/id_ed25519_vault}"
PRINCIPALS="ansible,evanusmodestus,root,adminerosado,admin"
vault write -field=signed_key ssh/sign/domus-client \
public_key=@"${KEY_PATH}.pub" \
valid_principals="$PRINCIPALS" \
>| "${KEY_PATH}-cert.pub"
# Reload SSH agent
ssh-add -d "${KEY_PATH}" 2>/dev/null || true
ssh-add "${KEY_PATH}"
echo "Certificate valid until:"
ssh-keygen -L -f "${KEY_PATH}-cert.pub" | grep Valid
# Host configuration (on each server)
# /etc/ssh/sshd_config.d/vault-ca.conf:
# TrustedUserCAKeys /etc/ssh/vault-ca.pub
# Get CA public key from Vault
curl -sk "$VAULT_ADDR/v1/ssh/public_key" | sudo tee /etc/ssh/vault-ca.pub
sudo systemctl reload sshd
SSH Config Patterns
# ~/.ssh/config
# Defaults for all hosts
Host *
# Security settings
AddKeysToAgent yes
IdentitiesOnly yes
# Connection settings
ServerAliveInterval 60
ServerAliveCountMax 3
TCPKeepAlive yes
# Compression (good for slow links)
Compression yes
# Vault SSH CA hosts (use certificate)
Host vault-* ise-* bind-* kvm-* nas-* k3s-* home-dc01
HostName %h.inside.domusdigitalis.dev
User evanusmodestus
IdentityFile ~/.ssh/id_ed25519_vault
CertificateFile ~/.ssh/id_ed25519_vault-cert.pub
# FIDO2 fallback (if cert expired)
Host vault-* ise-* bind-* kvm-* nas-*
IdentityFile ~/.ssh/id_ed25519_sk
IdentityFile ~/.ssh/id_ecdsa_sk
# Specific host overrides
Host nas-01
HostName nas-01.inside.domusdigitalis.dev
User admin
IdentityFile ~/.ssh/id_ed25519_vault
Host home-dc01
HostName home-dc01.inside.domusdigitalis.dev
User administrator@inside.domusdigitalis.dev
# Jump host (bastion)
Host internal-*
ProxyJump bastion.example.com
User admin
# GitHub
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_github
# Wildcards
Host *.dev
User developer
IdentityFile ~/.ssh/id_dev
# Pattern matching
Host 10.50.1.*
User admin
IdentityFile ~/.ssh/id_ed25519_vault
SSH Tunneling
# Local port forward (access remote service locally)
# -L localport:remotehost:remoteport
ssh -L 8080:localhost:80 user@server
# Access server's port 80 via localhost:8080
ssh -L 9060:ise-01.inside.domusdigitalis.dev:9060 user@jumphost
# Access ISE ERS via localhost:9060
# Multiple forwards
ssh -L 8080:localhost:80 -L 8443:localhost:443 user@server
# Remote port forward (expose local service to remote)
# -R remoteport:localhost:localport
ssh -R 8080:localhost:3000 user@server
# Server can access your local port 3000 via its localhost:8080
# Dynamic port forward (SOCKS proxy)
ssh -D 1080 user@server
# Configure browser/apps to use SOCKS5 proxy localhost:1080
# All traffic goes through server
# Background tunnel (no shell)
ssh -fN -L 8080:localhost:80 user@server
# -f = background
# -N = no command (tunnel only)
# Keep tunnel alive
ssh -fN -o ServerAliveInterval=60 -L 8080:localhost:80 user@server
# Tunnel with autossh (auto-reconnect)
autossh -M 0 -fN -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" \
-L 8080:localhost:80 user@server
# Jump/proxy through bastion
ssh -J bastion.example.com user@internal-server
# Multi-hop: ssh -J hop1,hop2 user@target
# Tunnel through bastion
ssh -L 8080:internal-server:80 user@bastion
# Or with ProxyJump:
ssh -J bastion -L 8080:localhost:80 user@internal-server
File Transfer (SCP/Rsync)
# SCP - Secure Copy
scp file.txt user@host:/path/ # Upload
scp user@host:/path/file.txt ./ # Download
scp -r directory/ user@host:/path/ # Recursive
scp -P 2222 file.txt user@host:/path/ # Custom port
scp -i ~/.ssh/id_special file.txt user@host:/path/ # Specific key
# SCP through jump host
scp -o ProxyJump=bastion file.txt user@internal:/path/
# SCP preserve attributes
scp -p file.txt user@host:/path/ # Preserve times/modes
# Rsync (preferred for large transfers)
rsync -av /local/path/ user@host:/remote/path/ # Archive + verbose
rsync -avz /local/path/ user@host:/remote/path/ # With compression
rsync -avz --delete /local/ user@host:/remote/ # Mirror (delete extra files)
rsync -avz --progress /local/ user@host:/remote/ # Show progress
rsync -avz --dry-run /local/ user@host:/remote/ # Preview changes
# Rsync with SSH options
rsync -avz -e "ssh -p 2222" /local/ user@host:/remote/
rsync -avz -e "ssh -i ~/.ssh/id_special" /local/ user@host:/remote/
# Rsync through jump host
rsync -avz -e "ssh -J bastion" /local/ user@internal:/remote/
# Rsync exclude patterns
rsync -avz --exclude='*.log' --exclude='.git' /local/ user@host:/remote/
rsync -avz --exclude-from=exclude.txt /local/ user@host:/remote/
# Rsync resume partial transfer
rsync -avz --partial --progress /local/bigfile user@host:/remote/
# Bandwidth limit
rsync -avz --bwlimit=1000 /local/ user@host:/remote/ # 1000 KB/s
SSHD Server Configuration
# /etc/ssh/sshd_config key settings
# Authentication
PasswordAuthentication no # Disable passwords
PubkeyAuthentication yes # Enable keys
PermitRootLogin prohibit-password # Root with keys only
ChallengeResponseAuthentication no # Disable keyboard-interactive
# SSH Certificates (Vault CA)
TrustedUserCAKeys /etc/ssh/vault-ca.pub # Trust Vault CA
# Restrict users/groups
AllowUsers admin ansible deploy
AllowGroups wheel ssh-users
DenyUsers root guest
DenyGroups nogroup
# Security hardening
Protocol 2 # SSH v2 only
MaxAuthTries 3 # Limit auth attempts
MaxSessions 10 # Limit sessions
LoginGraceTime 30 # Timeout for auth
ClientAliveInterval 300 # Check client every 5min
ClientAliveCountMax 2 # Disconnect after 2 missed
PermitEmptyPasswords no # No empty passwords
# Network settings
Port 22 # Or custom port
ListenAddress 0.0.0.0 # All interfaces
ListenAddress 10.50.1.99 # Specific IP only
# Forwarding
AllowTcpForwarding yes
GatewayPorts no
X11Forwarding no
PermitTunnel no
# Subsystems
Subsystem sftp /usr/lib/openssh/sftp-server
# Match blocks (per-user/group/address)
Match User deploy
PasswordAuthentication no
AllowTcpForwarding no
ForceCommand /usr/local/bin/deploy-script
Match Address 10.50.1.0/24
PasswordAuthentication no
PubkeyAuthentication yes
Match Group sftp-only
ChrootDirectory /home/%u
ForceCommand internal-sftp
AllowTcpForwarding no
# Test config before restart
sshd -t
# Apply changes
systemctl reload sshd
Authorized Keys Options
# ~/.ssh/authorized_keys format:
# [options] keytype base64key comment
# Basic key
ssh-ed25519 AAAA... user@host
# Restrict to specific command
command="/usr/local/bin/backup-script" ssh-ed25519 AAAA... backup-key
# Restrict source IP
from="10.50.1.0/24" ssh-ed25519 AAAA... admin-key
from="10.50.1.20,10.50.1.60" ssh-ed25519 AAAA... multi-source
# Disable forwarding
no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-ed25519 AAAA... restricted
# Read-only SFTP
command="internal-sftp",no-port-forwarding,no-X11-forwarding ssh-ed25519 AAAA... sftp-key
# Environment variables
environment="GIT_AUTHOR_NAME=Deploy Bot" ssh-ed25519 AAAA... deploy-key
# Certificate principals (not in authorized_keys)
# Instead, TrustedUserCAKeys in sshd_config
# CA signs certs with principals: -n "ansible,deploy"
# sshd accepts if user matches a principal
# Combine options
from="10.50.1.0/24",command="/usr/bin/rsync --server",no-pty ssh-ed25519 AAAA... rsync-key
# Expiry (OpenSSH 8.2+)
expiry-time="20261231" ssh-ed25519 AAAA... temp-key
# Multiple keys per line (NO, one per line)
# Each key on its own line
# Authorized keys with Vault CA
# Don't use authorized_keys for cert users!
# Add CA to: TrustedUserCAKeys /etc/ssh/vault-ca.pub
# Users with valid certs can log in as any matching principal
SSH Troubleshooting
# Verbose connection (client-side)
ssh -v user@host # Verbose
ssh -vv user@host # More verbose
ssh -vvv user@host # Maximum verbosity
# Check what key is being offered
ssh -v user@host 2>&1 | grep "Offering"
# Check certificate validity
ssh-keygen -L -f ~/.ssh/id_ed25519_vault-cert.pub
# Look for:
# - Valid: dates (not expired?)
# - Principals: (includes target user?)
# - Extensions: (includes permit-pty?)
# Common cert errors:
# "no matching key found" - principals don't include target user
# "certificate invalid: not yet valid" - clock skew (check NTP)
# "certificate has expired" - re-sign with vault
# Server-side debugging
sudo /usr/sbin/sshd -d -p 2222 # Debug mode on alt port
# Connect: ssh -p 2222 -v user@host
# Check sshd logs
journalctl -u sshd -f
journalctl -u sshd --since "5 minutes ago"
# Permission problems
ls -la ~/.ssh/ # Should be 700
ls -la ~/.ssh/authorized_keys # Should be 600
ls -la ~/.ssh/id_* # Private: 600, Public: 644
# Fix permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_*
chmod 644 ~/.ssh/*.pub
chmod 600 ~/.ssh/authorized_keys
# Check SELinux (RHEL/Rocky)
ls -Z ~/.ssh/
restorecon -Rv ~/.ssh/ # Fix SELinux labels
# Test specific key
ssh -i ~/.ssh/id_specific -v user@host
# Test certificate
ssh -i ~/.ssh/id_ed25519_vault \
-o "CertificateFile=~/.ssh/id_ed25519_vault-cert.pub" \
-v user@host
# Verify server accepts CA
ssh -v user@host 2>&1 | grep -i "certificate"
# Look for: "Server accepts key: ... cert"
# Check host key changed
ssh-keygen -R hostname # Remove old key
ssh-keyscan hostname >> ~/.ssh/known_hosts # Add new key
# Connection timeouts
ssh -o ConnectTimeout=5 user@host # 5 second timeout
ssh -o BatchMode=yes user@host # No prompts (for scripts)
Infrastructure SSH Patterns
# Multi-host command execution
HOSTS="vault-01 ise-01 bind-01 kvm-01 nas-01"
for host in $HOSTS; do
echo "=== $host ==="
ssh "$host.inside.domusdigitalis.dev" "hostname; uptime"
done
# Parallel execution (with GNU parallel)
echo "vault-01 ise-01 bind-01" | tr ' ' '\n' | \
parallel -j3 ssh {}.inside.domusdigitalis.dev 'hostname; uptime'
# SSH connectivity matrix
echo "=== SSH Connectivity ==="
printf "%-15s %-8s %-8s\n" "HOST" "SSH" "CERT"
for host in vault-01 ise-01 bind-01 kvm-01 nas-01; do
fqdn="$host.inside.domusdigitalis.dev"
ssh_ok=$(timeout 5 ssh -o BatchMode=yes "$fqdn" "exit" 2>/dev/null && echo "✓" || echo "✗")
cert_valid="✓"
if ssh -v "$fqdn" exit 2>&1 | grep -q "certificate"; then
cert_valid="✓ cert"
else
cert_valid="✗ key"
fi
printf "%-15s %-8s %-8s\n" "$host" "$ssh_ok" "$cert_valid"
done
# Vault SSH cert renewal for all hosts
vault-ssh-sign # Signs key with all principals
# Test SSH to all infrastructure
~/.local/bin/vault-ssh-test
# Deploy SSH CA to new host
deploy_ssh_ca() {
local host=$1
echo "=== Deploying CA to $host ==="
curl -sk "https://vault-01.inside.domusdigitalis.dev:8200/v1/ssh/public_key" | \
ssh "$host" "sudo tee /etc/ssh/vault-ca.pub"
ssh "$host" "echo 'TrustedUserCAKeys /etc/ssh/vault-ca.pub' | sudo tee /etc/ssh/sshd_config.d/vault-ca.conf"
ssh "$host" "sudo systemctl reload sshd"
}
# Batch file distribution
for host in vault-01 ise-01 bind-01; do
scp /etc/resolv.conf "$host.inside.domusdigitalis.dev":/tmp/
ssh "$host.inside.domusdigitalis.dev" "sudo cp /tmp/resolv.conf /etc/"
done
# Run command and log output
infra_cmd() {
local host=$1
shift
local cmd="$*"
echo "[$(date +%H:%M:%S)] $host: $cmd"
ssh "$host.inside.domusdigitalis.dev" "$cmd" 2>&1 | sed "s/^/ /"
}
infra_cmd vault-01 "vault status"
infra_cmd ise-01 "show application status ise"
SSH Hardening
# Generate new host keys (after install)
rm -f /etc/ssh/ssh_host_*
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N ""
# Restrict ciphers/MACs/KexAlgorithms
# /etc/ssh/sshd_config.d/hardening.conf
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
# Host key algorithms
HostKeyAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256
# Remove weak moduli (for DH)
awk '$5 >= 3071' /etc/ssh/moduli > /tmp/moduli.safe
mv /tmp/moduli.safe /etc/ssh/moduli
# Audit SSH configuration
sshd -T | grep -E '^(password|permit|allow|deny|pubkey)'
# fail2ban for SSH
cat > /etc/fail2ban/jail.d/sshd.local <<'EOF'
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600
EOF
systemctl restart fail2ban
# Rate limit SSH with firewalld
firewall-cmd --add-rich-rule='rule family="ipv4" service name="ssh" limit value="10/m" accept' --permanent
firewall-cmd --reload
# Port knocking (advanced)
# Requires knockd daemon
# User must "knock" on ports 7000, 8000, 9000 before SSH opens
# Two-factor with Google Authenticator
sudo yum install google-authenticator-libpam
google-authenticator # As user, setup TOTP
# Edit /etc/pam.d/sshd:
# auth required pam_google_authenticator.so
# Edit sshd_config:
# ChallengeResponseAuthentication yes
# AuthenticationMethods publickey,keyboard-interactive
Common Gotchas
# WRONG: Certificate signed but not loaded in agent
vault write ssh/sign/domus-client ... > ~/.ssh/id_ed25519-cert.pub
ssh host # Uses old key without cert!
# CORRECT: Reload agent after signing
ssh-add -d ~/.ssh/id_ed25519 2>/dev/null || true
ssh-add ~/.ssh/id_ed25519 # Adds key + finds cert automatically
# WRONG: TrustedUserCAKeys in wrong location (Match block)
# sshd_config:
Match Address 10.50.1.0/24
TrustedUserCAKeys /etc/ssh/vault-ca.pub # Inside Match = only for matches!
# CORRECT: TrustedUserCAKeys BEFORE Match blocks (global)
TrustedUserCAKeys /etc/ssh/vault-ca.pub
Match Address 10.50.1.0/24
PasswordAuthentication no
# WRONG: Principals don't include target user
# Signed with: valid_principals="ansible"
# But logging in as: ssh evanusmodestus@host # FAIL!
# CORRECT: Include all usernames you'll SSH as
vault write ssh/sign/domus-client \
valid_principals="ansible,evanusmodestus,root,admin"
# WRONG: Clock skew causes "not yet valid"
# Your machine is ahead of Vault server
# CORRECT: Enable NTP on all hosts
timedatectl set-ntp true
timedatectl status | grep synchronized
# WRONG: Using IdentityFile without IdentitiesOnly
Host server
IdentityFile ~/.ssh/id_specific
# Agent still tries ALL loaded keys first!
# CORRECT: Use IdentitiesOnly to try only specified keys
Host server
IdentityFile ~/.ssh/id_specific
IdentitiesOnly yes
# WRONG: scp to Synology NAS fails
scp file nas-01:/path/ # Blocked by DSM security
# CORRECT: Use cat pipe
cat file | ssh nas-01 "cat > /path/file"
# WRONG: Permission denied after key copy
ssh-copy-id user@host
ssh user@host # Still asks for password!
# CORRECT: Check permissions on remote
ssh user@host "chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"
# Also check SELinux: restorecon -Rv ~/.ssh/
Quick Reference
# Keys
ssh-keygen -t ed25519 # Generate key
ssh-keygen -l -f key.pub # Show fingerprint
ssh-keygen -L -f cert.pub # Show certificate
# Agent
ssh-add ~/.ssh/id_ed25519 # Add key
ssh-add -l # List keys
ssh-add -D # Remove all
# Connection
ssh user@host # Basic connect
ssh -p 2222 user@host # Custom port
ssh -i ~/.ssh/key user@host # Specific key
ssh -J bastion user@internal # Jump host
# Tunnels
ssh -L 8080:localhost:80 host # Local forward
ssh -R 8080:localhost:80 host # Remote forward
ssh -D 1080 host # SOCKS proxy
ssh -fN -L 8080:localhost:80 host # Background tunnel
# File transfer
scp file user@host:/path/ # Upload
scp user@host:/path/file ./ # Download
rsync -avz /local/ user@host:/rem/ # Sync
# Vault SSH CA
vault write ssh/sign/domus-client public_key=@~/.ssh/id.pub valid_principals="user"
ssh-keygen -L -f ~/.ssh/id-cert.pub # Verify cert
# Troubleshooting
ssh -v user@host # Verbose
sshd -t # Test config
journalctl -u sshd -f # Watch logs
chmod 700 ~/.ssh # Fix permissions
chmod 600 ~/.ssh/id_* # Private keys
chmod 644 ~/.ssh/*.pub # Public keys
# Common ports
# 22 SSH (default)
# 2222 Common alternate
# Config files
# ~/.ssh/config - Client config
# /etc/ssh/sshd_config - Server config
# ~/.ssh/authorized_keys - Allowed keys
# ~/.ssh/known_hosts - Trusted hosts
# /etc/ssh/vault-ca.pub - Trusted CA (Vault)