The SSH integration provides native remote execution capabilities for Pabawi, enabling direct command execution, package management, and inventory management on remote hosts via SSH without requiring external automation tools like Ansible or Bolt.
- Features
- Prerequisites
- Configuration
- SSH Config File
- Security Best Practices
- Usage Examples
- Troubleshooting
- Remote Command Execution: Execute shell commands on remote hosts via SSH
- Connection Pooling: Efficient connection reuse for improved performance
- Package Management: Install, remove, and update packages across multiple Linux distributions (apt, yum, dnf, zypper, pacman)
- Concurrent Execution: Execute commands on multiple hosts in parallel with configurable limits
- SSH Config Support: Use standard OpenSSH config files for host definitions
- Privilege Escalation: Execute commands with sudo support
- Inventory Management: Integrate with Pabawi's unified inventory system
- Health Monitoring: Built-in health checks for connection verification
- SSH access to target hosts
- SSH keys configured for authentication (recommended) or password authentication
- Target hosts' public keys in
known_hosts(if host key checking is enabled) - Appropriate user permissions on target hosts
The SSH integration is configured entirely through environment variables in backend/.env. You can also use the SSH Setup Guide in the Pabawi web UI to generate this snippet — it walks you through the settings and lets you copy the result to your clipboard.
# Enable SSH integration
SSH_ENABLED=true
# Path to SSH config file (OpenSSH format)
SSH_CONFIG_PATH=/etc/pabawi/ssh_config
# Default SSH username (required when enabled)
SSH_DEFAULT_USER=deploy
# Default SSH port (1-65535)
SSH_DEFAULT_PORT=22
# Default private key path
SSH_DEFAULT_KEY=/path/to/private_key# Verify SSH host keys against known_hosts
SSH_HOST_KEY_CHECK=true
# Connection timeout in seconds (5-300)
SSH_CONNECTION_TIMEOUT=30
# Command execution timeout in seconds (10-3600)
SSH_COMMAND_TIMEOUT=300
# Maximum total connections in pool (1-1000)
SSH_MAX_CONNECTIONS=50
# Maximum connections per host (1-100)
SSH_MAX_CONNECTIONS_PER_HOST=5
# Idle connection timeout in seconds (10-3600)
SSH_IDLE_TIMEOUT=300
# Maximum concurrent command executions (1-100)
SSH_CONCURRENCY_LIMIT=10# Enable sudo for privilege escalation
SSH_SUDO_ENABLED=true
# Sudo command prefix
SSH_SUDO_COMMAND=sudo
# Whether sudo is passwordless
SSH_SUDO_PASSWORDLESS=true
# Sudo password (if not passwordless)
SSH_SUDO_PASSWORD=
# User to run commands as with sudo
SSH_SUDO_USER=root# Plugin priority for inventory deduplication (0-100)
SSH_PRIORITY=50version: '3.8'
services:
pabawi:
image: pabawi:latest
environment:
# SSH Integration
SSH_ENABLED: "true"
SSH_CONFIG_PATH: "/config/ssh_config"
SSH_DEFAULT_USER: "deploy"
SSH_DEFAULT_KEY: "/keys/deploy_key"
SSH_HOST_KEY_CHECK: "true"
SSH_CONNECTION_TIMEOUT: "30"
SSH_COMMAND_TIMEOUT: "300"
SSH_MAX_CONNECTIONS: "50"
SSH_CONCURRENCY_LIMIT: "10"
# Sudo Configuration
SSH_SUDO_ENABLED: "true"
SSH_SUDO_PASSWORDLESS: "true"
SSH_SUDO_USER: "root"
volumes:
- ./ssh_config:/config/ssh_config:ro
- ./keys:/keys:ro
- ~/.ssh/known_hosts:/root/.ssh/known_hosts:roapiVersion: v1
kind: ConfigMap
metadata:
name: pabawi-ssh-config
data:
SSH_ENABLED: "true"
SSH_CONFIG_PATH: "/config/ssh_config"
SSH_DEFAULT_USER: "deploy"
SSH_DEFAULT_PORT: "22"
SSH_HOST_KEY_CHECK: "true"
SSH_CONNECTION_TIMEOUT: "30"
SSH_COMMAND_TIMEOUT: "300"
SSH_MAX_CONNECTIONS: "50"
SSH_MAX_CONNECTIONS_PER_HOST: "5"
SSH_IDLE_TIMEOUT: "300"
SSH_CONCURRENCY_LIMIT: "10"
SSH_SUDO_ENABLED: "true"
SSH_SUDO_PASSWORDLESS: "true"
SSH_SUDO_USER: "root"
SSH_PRIORITY: "50"
---
apiVersion: v1
kind: Secret
metadata:
name: pabawi-ssh-keys
type: Opaque
data:
deploy_key: <base64-encoded-private-key>The SSH integration uses the standard OpenSSH client configuration file format (~/.ssh/config syntax). This provides compatibility with existing SSH configurations.
# Web servers
Host web-server-01 web01
HostName 192.168.1.10
User deploy
Port 22
IdentityFile ~/.ssh/deploy_key
# Groups: webservers,production
Host db-server-01 db01
HostName 192.168.1.20
User dbadmin
Port 2222
IdentityFile ~/.ssh/db_key
# Groups: databases,production
# Development servers
Host dev-*.example.com
User developer
Port 22
IdentityFile ~/.ssh/dev_key
# Groups: development
# Default settings for all hosts
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
StrictHostKeyChecking yesHost- Host pattern/alias (first value used as node name)HostName- Target hostname or IP addressUser- SSH usernamePort- SSH port (default: 22)IdentityFile- Path to private key file
Use comments to add custom metadata for Pabawi:
# Groups: group1,group2,group3This allows organizing hosts into logical groups for inventory management.
Ensure private keys have restrictive permissions:
chmod 600 ~/.ssh/pabawi_key- Use encrypted volumes in Docker
- Use Kubernetes Secrets for key storage
- Never commit keys to version control
Regularly rotate SSH keys:
# Generate new key pair
ssh-keygen -t ed25519 -f ~/.ssh/pabawi_key_new -C "pabawi@example.com"
# Deploy new public key to hosts
ssh-copy-id -i ~/.ssh/pabawi_key_new.pub user@host
# Update SSH_DEFAULT_KEY configuration
export SSH_DEFAULT_KEY=~/.ssh/pabawi_key_newAlways verify host keys in production:
SSH_HOST_KEY_CHECK=trueKeep known_hosts file up to date:
# Add host key manually
ssh-keyscan -H 192.168.1.10 >> ~/.ssh/known_hosts
# Or connect once to accept key
ssh user@192.168.1.10Only disable host key checking in isolated test environments:
# NOT recommended for production
SSH_HOST_KEY_CHECK=falseConfigure NOPASSWD in sudoers:
# /etc/sudoers.d/pabawi
deploy ALL=(ALL) NOPASSWD: ALLRestrict sudo to specific commands:
# /etc/sudoers.d/pabawi
deploy ALL=(ALL) NOPASSWD: /usr/bin/apt, /usr/bin/systemctlNever store sudo passwords in plain text:
- Use passwordless sudo when possible
- Use secure secret management if passwords are required
Disable password authentication:
# /etc/ssh/sshd_config
PasswordAuthentication no
PubkeyAuthentication yesLimit SSH access by IP:
# Using firewall rules
ufw allow from 10.0.0.0/8 to any port 22Consider using non-standard SSH ports:
Host production-*
Port 2222Set appropriate limits based on infrastructure size:
# For small deployments (< 50 hosts)
SSH_MAX_CONNECTIONS=50
SSH_MAX_CONNECTIONS_PER_HOST=5
# For large deployments (> 100 hosts)
SSH_MAX_CONNECTIONS=200
SSH_MAX_CONNECTIONS_PER_HOST=10Balance responsiveness with reliability:
# Quick operations
SSH_CONNECTION_TIMEOUT=10
SSH_COMMAND_TIMEOUT=60
# Long-running operations
SSH_CONNECTION_TIMEOUT=30
SSH_COMMAND_TIMEOUT=1800Execute a command on a single host through the Pabawi UI or API:
# Via API
curl -X POST http://pabawi:3000/api/execute \
-H "Content-Type: application/json" \
-d '{
"integration": "ssh",
"target": "web-server-01",
"command": "uptime"
}'Execute a command on multiple hosts:
curl -X POST http://pabawi:3000/api/execute \
-H "Content-Type: application/json" \
-d '{
"integration": "ssh",
"target": ["web-server-01", "web-server-02"],
"command": "systemctl status nginx"
}'Install a package on a host:
curl -X POST http://pabawi:3000/api/package \
-H "Content-Type: application/json" \
-d '{
"integration": "ssh",
"target": "web-server-01",
"operation": "install",
"package": "nginx"
}'Execute a command with sudo:
curl -X POST http://pabawi:3000/api/execute \
-H "Content-Type: application/json" \
-d '{
"integration": "ssh",
"target": "web-server-01",
"command": "systemctl restart nginx",
"sudo": true
}'Error: Connection timeout after 30 seconds
Solutions:
- Verify host is reachable:
ping <hostname> - Check SSH service is running:
systemctl status sshd - Verify firewall rules allow SSH
- Increase connection timeout:
SSH_CONNECTION_TIMEOUT=60
Error: Authentication failed for user@host
Solutions:
- Verify private key path is correct
- Check private key permissions:
ls -l ~/.ssh/key - Ensure public key is in
~/.ssh/authorized_keyson target - Check SSH logs on target:
journalctl -u sshd
Error: Host key verification failed
Solutions:
- Add host key to known_hosts:
ssh-keyscan -H <host> >> ~/.ssh/known_hosts - Remove old host key:
ssh-keygen -R <host> - Temporarily disable checking (testing only):
SSH_HOST_KEY_CHECK=false
Error: Command timeout after 300 seconds
Solutions:
- Increase command timeout:
SSH_COMMAND_TIMEOUT=600 - Optimize command to run faster
- Check if command is hanging on target
Error: Permission denied (publickey)
Solutions:
- Verify user has permission to execute command
- Enable sudo if needed:
SSH_SUDO_ENABLED=true - Check sudo configuration on target
Error: SSH_DEFAULT_USER is required when SSH_ENABLED is true
Solutions:
- Set SSH_DEFAULT_USER:
export SSH_DEFAULT_USER=deploy - Or disable SSH:
export SSH_ENABLED=false
Error: SSH_CONNECTION_TIMEOUT must be between 5 and 300, got: 3
Solutions:
- Use value within valid range:
export SSH_CONNECTION_TIMEOUT=30 - Check documentation for valid ranges
Solutions:
- Enable connection pooling (enabled by default)
- Increase max connections:
SSH_MAX_CONNECTIONS=100 - Increase concurrency:
SSH_CONCURRENCY_LIMIT=20 - Reduce idle timeout to free connections faster:
SSH_IDLE_TIMEOUT=120
Error: POOL_EXHAUSTED - Maximum connections reached
Solutions:
- Increase max connections:
SSH_MAX_CONNECTIONS=100 - Increase max connections per host:
SSH_MAX_CONNECTIONS_PER_HOST=10 - Reduce concurrency limit:
SSH_CONCURRENCY_LIMIT=5 - Check for connection leaks in logs
Status: Degraded - Some hosts unreachable
Solutions:
- Check which hosts are failing in health check details
- Verify network connectivity to failed hosts
- Check SSH service status on failed hosts
- Review SSH logs for connection errors
Status: Unhealthy - No hosts reachable
Solutions:
- Verify SSH_CONFIG_PATH is correct
- Check SSH config file exists and is readable
- Verify at least one host is defined in SSH config
- Test manual SSH connection to hosts
- Check network connectivity and firewall rules
Adjust based on infrastructure size:
# Small deployments (< 50 hosts)
SSH_MAX_CONNECTIONS=50
SSH_MAX_CONNECTIONS_PER_HOST=5
# Medium deployments (50-200 hosts)
SSH_MAX_CONNECTIONS=100
SSH_MAX_CONNECTIONS_PER_HOST=10
# Large deployments (> 200 hosts)
SSH_MAX_CONNECTIONS=200
SSH_MAX_CONNECTIONS_PER_HOST=15Balance parallelism with resource usage:
# Conservative (low resource usage)
SSH_CONCURRENCY_LIMIT=5
# Balanced (default)
SSH_CONCURRENCY_LIMIT=10
# Aggressive (high throughput)
SSH_CONCURRENCY_LIMIT=20Adjust timeouts based on network conditions:
# Fast, reliable networks
SSH_CONNECTION_TIMEOUT=10
SSH_COMMAND_TIMEOUT=60
SSH_IDLE_TIMEOUT=120
# Slow or unreliable networks
SSH_CONNECTION_TIMEOUT=60
SSH_COMMAND_TIMEOUT=1800
SSH_IDLE_TIMEOUT=600When multiple integrations provide the same node, priority determines which source is used:
# SSH has lower priority than PuppetDB by default
SSH_PRIORITY=50
PUPPETDB_PRIORITY=100All SSH command executions are stored in Pabawi's execution history and can be re-executed from the UI.
SSH integration health status is displayed in the Pabawi dashboard alongside other integrations.
- Start with restrictive settings: Begin with conservative connection limits and timeouts, then adjust based on actual usage
- Use SSH config files: Leverage standard SSH config format for easier management and compatibility
- Enable host key checking: Always verify host keys in production environments
- Prefer key-based authentication: Use SSH keys instead of passwords for better security
- Configure passwordless sudo: Set up NOPASSWD in sudoers for smoother operations
- Monitor connection pool usage: Watch for pool exhaustion and adjust limits accordingly
- Regular key rotation: Rotate SSH keys periodically for security
- Test in development first: Validate configuration in a test environment before production deployment
- Use appropriate timeouts: Set timeouts based on expected command execution times
- Document your SSH config: Keep comments in SSH config file explaining host purposes and groups
- Bolt Integration - Alternative execution tool integration
- Ansible Integration - Alternative automation tool integration
- Configuration Guide - General Pabawi configuration
- Troubleshooting Guide - General troubleshooting information