Lightweight SSH orchestration for multi-server environments.
- Individual server access via named symlinks (
srv1,dev,backup) - Cluster-wide commands with sequential or parallel execution
- Configuration-driven server management via
hosts.conf - Host connectivity testing with reachability checks
- Ad-hoc launchers without config file editing
- Local-only restrictions for host-specific access control
# 1. Install
curl -sSL https://raw.githubusercontent.com/OkusiAssociates/oknav/main/install.sh | sudo bash
# 2. Configure servers
sudo nano /etc/oknav/hosts.conf
# server1.example.com srv1 (oknav)
# server2.example.com srv2 (oknav)
# 3. Create symlinks
sudo oknav install
# 4. Use
srv1 uptime # Individual server
oknav uptime # All cluster servers
oknav -p df -h # Parallel executioncurl -sSL https://raw.githubusercontent.com/OkusiAssociates/oknav/main/install.sh | sudo bashInstalls to:
| Location | Contents |
|---|---|
/usr/local/share/oknav/ |
Package files |
/usr/local/bin/ |
Executable symlinks |
/etc/oknav/hosts.conf |
Server configuration |
/usr/local/share/man/man1/oknav.1 |
Manual page |
/etc/bash_completion.d/oknav |
Bash completion |
git clone https://github.com/OkusiAssociates/oknav.git
cd oknav
sudo ./install.shsudo /usr/local/share/oknav/install.sh --uninstallServer definitions live in /etc/oknav/hosts.conf:
# Format: FQDN primary-alias [alias2...] [(options)]
# Production cluster
server1.example.com srv1 server1 (oknav)
server2.example.com srv2 server2 (oknav)
server3.example.com srv3 server3 (oknav)
# Development (restricted to workstation)
devbox.local dev devbox (oknav,local-only:workstation)
# Backup (excluded from normal cluster operations)
backup.local bak backup (oknav,exclude)
# Direct access only (not in cluster)
adhoc.example.com adhoc
| Option | Description |
|---|---|
oknav |
Include in cluster operations (primary alias only) |
exclude |
Exclude from cluster operations (still accessible directly) |
local-only:HOST |
Restrict access to specified hostname |
- Primary alias: First alias listed is used for cluster operations
- Combined options: Separate with commas:
(oknav,local-only:myhost) - Ad-hoc entries: Servers without
(oknav)are accessible but not in cluster - Config priority:
/etc/oknav/hosts.conf>$SCRIPT_DIR/hosts.conf
Connect to servers via symlinks that resolve through hosts.conf:
srv1 [OPTIONS] [command]| Option | Description |
|---|---|
-r, --root |
Connect as root |
-u, --user USER |
Connect as specified user |
-d, --dir |
Preserve current working directory |
-D, --debug |
Show connection parameters |
-V, --version |
Show version |
-h, --help |
Show help |
Examples:
srv1 # Interactive shell
srv1 uptime # Execute command
srv1 -r # Root shell
srv1 -rd # Root shell, current directory
srv1 -u deploy git pull # Run as specific user
srv1 "df -h | grep data" # Complex commands (quote them)Execute commands across all servers marked with (oknav):
oknav [OPTIONS] <command>
oknav [OPTIONS] -- <command> # Force command mode| Option | Description |
|---|---|
-p, --parallel |
Execute simultaneously |
-d, --dir |
Preserve current working directory |
-t, --timeout SECS |
Connection timeout (default: 30) |
-x, --exclude-host HOST |
Exclude server (repeatable) |
-D, --debug |
Show server discovery details |
-- |
Force command mode (bypass subcommand detection) |
-V, --version |
Show version |
-h, --help |
Show help |
Examples:
oknav uptime # Sequential execution
oknav -p df -h # Parallel execution
oknav -d ls # Run in current directory
oknav -pd pwd # Parallel, preserve directory
oknav -pt 10 uptime # Parallel + 10s timeout
oknav -x srv1 -x srv2 uptime # Exclude multiple servers
oknav -D hostname # Debug: show discovered servers
oknav -- list /tmp # Run 'list /tmp' (not subcommand)| Subcommand | Purpose |
|---|---|
install |
Manage symlinks from hosts.conf |
add |
Create ad-hoc launcher |
remove |
Remove launcher |
list |
List installed host symlinks |
Create symlinks in /usr/local/bin for all hosts.conf aliases:
sudo oknav install # Create/update symlinks
oknav install --dry-run # Preview changes
sudo oknav install --remove-stale # Remove symlinks not in hosts.conf
sudo oknav install --clean-local # Remove dev symlinks from script dir| Option | Description |
|---|---|
-n, --dry-run |
Preview changes |
--remove-stale |
Remove symlinks not in hosts.conf |
--clean-local |
Remove symlinks from script directory |
-h, --help |
Show help |
Create ad-hoc launchers without editing hosts.conf:
# Add launcher (hostname used as alias)
sudo oknav add ai.okusi.id
# Add with custom aliases
sudo oknav add ai.okusi.id ai ok-ai
# Remove launchers
sudo oknav remove ai ok-ai| Option | Description |
|---|---|
-n, --dry-run |
Preview changes |
-h, --help |
Show help |
Notes:
- Hostname must be resolvable (DNS or
/etc/hosts) - Ad-hoc hosts are NOT included in cluster operations
- Use
hosts.conffor cluster membership
Show all host symlinks in /usr/local/bin pointing to ok_master:
oknav list # List all hosts
oknav list -R # Test SSH connectivity
oknav list -R -p # Parallel connectivity testing| Option | Description |
|---|---|
-R, --reachable |
Test SSH connectivity (5s timeout) |
-p, --parallel |
Test hosts in parallel (use with -R) |
-h, --help |
Show help |
Output format:
srv1 hosts.conf
srv2 hosts.conf
ai ad-hoc
With -R (reachability testing):
srv1 hosts.conf ✓
srv2 hosts.conf ✓
ai ad-hoc ✗
Direct output without prefixes:
$ srv1 uptime
09:15:23 up 45 days, 3:22, 2 users, load average: 0.15, 0.12, 0.10
Prefixed output showing server origin:
$ oknav uptime
+++srv1:
09:15:23 up 45 days, 3:22, 2 users, load average: 0.15, 0.12, 0.10
+++srv2:
09:15:24 up 32 days, 14:55, 0 users, load average: 0.08, 0.03, 0.01
In parallel mode (-p), output is collected and displayed in server order after all complete.
shellcheck -x oknav ok_master common.inc.sh install.sh# Run all tests
bats tests/
# Run specific test file
bats tests/oknav.bats
# Filter by test name
bats tests/oknav.bats --filter "parallel"bash -n oknav && bash -n ok_master && bash -n common.inc.sh| Tool | Option | Description |
|---|---|---|
ok_master |
-r |
Root user |
ok_master |
-u USER |
Specific user |
ok_master |
-d |
Preserve directory |
ok_master |
-D |
Debug mode |
oknav |
-p |
Parallel execution |
oknav |
-d |
Preserve directory |
oknav |
-t SECS |
Timeout (default: 30) |
oknav |
-x HOST |
Exclude host (repeatable) |
oknav |
-D |
Debug mode |
oknav |
-- |
Force command mode |
install |
-n |
Dry run |
install |
--remove-stale |
Remove stale symlinks |
install |
--clean-local |
Remove local symlinks |
add |
-n |
Dry run |
remove |
-n |
Dry run |
list |
-R |
Test reachability |
list |
-p |
Parallel testing |
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error |
| 2 | Local-only constraint violated |
| 22 | Invalid option (EINVAL) |
| 42 | Direct ok_master execution (must use symlink) |
| 124 | Timeout reached |
| 125 | Timeout command error |
| 126 | Command not found |
| Variable | Description |
|---|---|
OKNAV_HOSTS_CONF |
Override hosts.conf location |
OKNAV_TARGET_DIR |
Override target directory (for testing) |
XDG_RUNTIME_DIR |
Temp file location (falls back to /tmp) |
Installed:
/usr/local/share/oknav/
├── oknav # Cluster orchestrator
├── ok_master # Individual server handler
├── common.inc.sh # Shared functions
└── install.sh # Installer
/etc/oknav/
└── hosts.conf # Server configuration
/usr/local/bin/
├── oknav # → /usr/local/share/oknav/oknav
├── ok_master # → /usr/local/share/oknav/ok_master
└── srv1, srv2... # → /usr/local/share/oknav/ok_master
Source:
oknav/
├── oknav # Cluster orchestrator
├── ok_master # Individual server handler
├── common.inc.sh # Shared functions
├── install.sh # Installer
├── hosts.conf.example # Configuration template
├── oknav.1 # Man page
├── oknav.bash_completion
└── tests/ # BATS test suite
- Commands execute via sudo with SSH key authentication
- Parallel operations affect multiple servers simultaneously
- Local-only restrictions prevent access from unauthorized hosts
- Test first: Run commands on individual servers before cluster-wide
- Quote carefully: Use quotes for commands with pipes or special characters
- Review changes: Use
-Ddebug mode to verify server discovery - Limit blast radius: Use
-xto exclude servers when testing - Secure keys: Protect SSH keys and rotate regularly
- Restrict access: Use
local-only:HOSTfor sensitive servers
"Command not found"
- Ensure symlinks exist:
ls -la /usr/local/bin/srv* - Run
sudo oknav installto create symlinks
SSH connection failures
- Verify SSH key authentication:
ssh user@server echo OK - Check hostname resolution:
getent hosts server1.example.com - Use
-Dfor debug output
Timeout errors
- Default timeout is 30 seconds
- Use
-t SECSfor slow networks - Check network connectivity
"No servers found"
- Verify
hosts.confhas entries with(oknav)option - Check
(local-only:HOST)restrictions match current hostname - Use
oknav -Dto see server discovery
Local-only restrictions
- Servers with
(local-only:HOST)only work from that specific host - Check current hostname:
hostname
# Show discovered servers and settings
oknav -D hostname
# Verify individual server resolution
srv1 -D whoami
# Test connectivity with short timeout
oknav -t 5 echo OK
# List hosts with reachability check
oknav list -RGPL-3. See LICENSE file for details.