# n8n-nodes-ssh-command-dynamic-host

A custom n8n node that enables SSH command execution on **dynamic hosts**, which can be provided as part of input data. This is particularly useful when working with lists of remote servers and automating tasks such as monitoring, maintenance, or orchestration.

## ✨ Features

- Connect to SSH servers using dynamic hostnames from input data (`item.json`)
- Execute any command remotely
- Full support for multiple items (parallel/batch execution)
- Handles SSH fingerprint verification (non-interactively)
- Compatible with n8n’s native “Continue on error” feature

## 📦 Installation

### Manual (for self-hosted n8n)

1. Clone or download this repository to your n8n custom nodes folder.

2. Inside your n8n user folder (`~/.n8n/` or `/home/user/.n8n/`):

```bash
mkdir -p ~/.n8n/nodes
cd ~/.n8n/nodes
git clone https://github.com/madcatmining/n8n-nodes-ssh-command-dynamic-host.git
cd n8n-nodes-ssh-command-dynamic-host
npm install
npm run build

    Add this to your environment (if not already enabled):

N8N_CUSTOM_EXTENSIONS=/home/user/.n8n/nodes

    Restart your n8n server:

pm2 restart n8n
# or
docker restart n8n

⚙️ Node Configuration
Field	Description
Host Field	The name of the JSON key in each item that contains the target hostname, OR a literal hostname string.
Port	SSH port (default is 22). Accepts a single port, or a comma-separated list (e.g. `22,2222,2022`). Ports are tried in order; the node moves to the next port if one fails or is not established within 10 seconds, and fails only if none succeed. Useful when the same key connects to multiple servers that listen on different ports.
Username	SSH username to connect with.
Password	Password used for authentication. Leave empty when using a private key.
Private Key	Private key for authentication. Paste the full key (including header/footer lines). Any format supported by ssh2 (OpenSSH, PEM/PKCS#1, PKCS#8, RFC4716) is accepted, including encrypted keys.
Private Key Passphrase	Passphrase protecting the private key. Leave empty if the key is not encrypted.
Command	The command to run on the remote host. Can use expressions like {{ $json.something }}.

When a Private Key is provided it is used for authentication (with the passphrase if the key is encrypted); otherwise the Password is used.
🧠 How It Works

    If Host Field value is a string like host, and each item has { "host": "my.server.com" }, the node will extract it dynamically.

    If it’s a full hostname (e.g. my.server.com), that static hostname will be used for all items.

    The node loops through each input item and connects to the respective server over SSH, running the same command on each.

🔐 SSH Known Hosts Behavior

This node automatically accepts and caches unknown SSH fingerprints (like typing "yes" when manually connecting for the first time).

⚠️ Use caution in production environments! This disables SSH strict host key checking for automation convenience.
✅ Example Use Case

Input:

[
  {
    "host": "server1.example.com"
  },
  {
    "host": "server2.example.com"
  }
]

Set Host Field to host, and your command to something like:

uptime

Output:

[
  {
    "host": "server1.example.com",
    "output": "15:23:45 up 10 days,  2:34,  1 user,  load average: 0.00, 0.01, 0.05"
  },
  {
    "host": "server2.example.com",
    "output": "15:23:45 up 2 days,  4:12,  3 users,  load average: 0.30, 0.25, 0.40"
  }
]

🛠 Development
Build

npm install
npm run build

File Structure

    nodes/SSHCommandDynamicHost.node.ts – Main node definition and logic.

    package.json – Node package setup and metadata.

    dist/ – Compiled output folder after running npm run build.

🧪 Testing

    Use test SSH servers or local VMs.

    Toggle the "Continue On Error" setting in the n8n UI to ensure workflows continue even if one SSH connection fails.

    Use SplitInBatches and Wait nodes to rate-limit requests if needed.

🆕 Changelog

1.2.1

    Docs: corrected the GitHub repository URL in the README.

1.2.0

    Multiple SSH ports: the Port field now accepts a comma-separated list (e.g. 22,2222,2022). Ports are tried in order; the node moves to the next port if one fails or is not established within 10 seconds, and fails only if every port is exhausted. The successful port is included in the output. Useful when the same key connects to servers listening on different ports.

1.1.0

    SSH key authentication: added Private Key and Private Key Passphrase fields. Any key format supported by ssh2 (OpenSSH, PEM/PKCS#1, PKCS#8, RFC4716) is accepted, including encrypted keys. When a key is provided it takes priority, with the password used as a fallback.
    Packaging fixes: added n8nNodesApiVersion (fixes intermittent node load failures), removed the unused node-ssh dependency, and dropped n8n-core/n8n-workflow from runtime dependencies (now build-time only) to eliminate their vulnerable transitive tree.
    Robustness: host values are now coerced to strings, output items carry pairedItem linkage, and empty credentials are no longer sent during connection.

📄 License

MIT © 2025 Robertas Z (aka @MadCatMining)
