Wait for SSH to become available, then connect.
$ sshuntil root 10
[INFO] Subnet: 192.168.28.0/24 (via auto-detection)
[INFO] Expanded IP: 10 -> 192.168.28.10
[INFO] Waiting for SSH (192.168.28.10:22) ...... [OK]
[INFO] Fetching SSH host key ...
[INFO] Host key already known and valid
[INFO] Connecting to root@192.168.28.10 ...
root@grml ~ #
Perfect for freshly booted systems, rebooting servers, or deployment workflows.
- ⏱️ Waits for SSH: Polls until port 22 is ready – ideal after reboot or fresh deployment
- 🌐 Flexible IP notation: Just type
15instead of192.168.28.15 - 👤 Quick username:
sshuntil root 15– no-lflag needed - 🔑 Smart host keys: Only updates on mismatch, no manual
known_hostscleanup - 🔍 Subnet auto-detection: Works without config on most setups
- ⚙️ Configurable: Timeouts, default user, passwords via config files
# Download the script
curl -o sshuntil https://raw.githubusercontent.com/efnats/sshuntil/main/sshuntil
chmod +x sshuntil
# Optional: Move to PATH
sudo mv sshuntil /usr/local/bin/
# Check version
sshuntil --versionbash(4.0+)sshandssh-keyscannc(netcat)sshpass(optional, only for password authentication)
# Full IP address
sshuntil 192.168.28.194
# Host number only (uses SUBNET from config or auto-detection)
sshuntil 194
# → connects to 192.168.28.194
# Two octets (replaces last two octets of SUBNET)
sshuntil 21.11
# → connects to 192.168.21.11
# Three octets (replaces last three octets of SUBNET)
sshuntil 10.0.50
# → connects to 192.10.0.50# These are equivalent:
sshuntil root 15
sshuntil -l root 15
# → connects as root@192.168.28.15
# With partial IPs
sshuntil admin 21.11
# → connects as admin@192.168.21.11
# Without username: uses SSH_USER from config (default: root)
sshuntil 15# Execute command on remote host
sshuntil 194 "uptime"
sshuntil root 15 "df -h"
sshuntil admin 21.11 "systemctl status nginx"Given a configured or auto-detected SUBNET of 192.168.28.0/24:
| Input | Expands to | Explanation |
|---|---|---|
194 |
192.168.28.194 |
Uses full SUBNET prefix + host number |
21.11 |
192.168.21.11 |
Uses first two octets from SUBNET |
10.0.50 |
192.10.0.50 |
Uses first octet from SUBNET |
10.0.5.100 |
10.0.5.100 |
Full IP, used as-is |
Create a config file at /etc/sshuntil.conf (system-wide) or ~/.config/sshuntil.conf (user-specific):
# Subnet for partial IP expansion (auto-detected if not set)
SUBNET="192.168.28.0/24"
# SSH username (default: root)
SSH_USER="root"
# SSH password (empty = key-based auth)
PASSWORD=""
# Custom known_hosts file location
KNOWN_HOSTS="${HOME}/.ssh/known_hosts"
# Port check interval in seconds
CHECK_INTERVAL=3
# Maximum wait time in seconds
MAX_WAIT=180If SUBNET is not configured, sshuntil automatically detects your current subnet using:
ip route(Linux)ifconfig(macOS/BSD)hostname -I(fallback)
The detected subnet is displayed:
[INFO] Subnet: 192.168.1.0/24 (via auto-detection)
sshuntil intelligently manages SSH host keys:
- New host: Key is added to
known_hosts - Known host with matching key: No changes, connection proceeds
- Known host with different key: Old key is removed, new key is added (with warning)
This prevents unnecessary key removals while still handling host key changes (e.g., reinstalled systems).
| Code | Meaning |
|---|---|
0 |
Success |
2 |
Invalid input (bad IP format, missing config) |
69 |
Could not fetch SSH host key |
111 |
SSH connection failed |
124 |
Timeout waiting for SSH port |
Set SUBNET manually in ~/.config/sshuntil.conf:
echo 'SUBNET="192.168.1.0/24"' > ~/.config/sshuntil.confIncrease MAX_WAIT in config or check if:
- Target host is powered on
- Network connectivity is working
- Firewall allows SSH (port 22)
Install sshpass:
# Debian/Ubuntu
sudo apt install sshpass
# macOS
brew install hudochenkov/sshpass/sshpass- Store passwords in config files only in secure environments
- Config files should have restricted permissions (
chmod 600) - Consider using SSH keys instead of passwords
- Host key verification is always enabled (
StrictHostKeyChecking=yes)
Contributions are welcome! Please feel free to submit issues or pull requests.
MIT License - see repository for details