NodeJS Extension for SSH & SFTP

That’s an early version that allows you to run commands on a remote server via SSH.
I’m planning to extend this over time but I’ll package it in releases on GitHub so that you can decide for yourself when you upgrade.

Current functionality:

Use an ssh private key stored in your Wappler project directory to connect to a remote host via ssh and run commands.

Example:

You can currently only see the server output (stdout) in the console.

Further plans/roadmap:

  • Make stdout available as output inside Wappler
  • Allow ssh keys with passphrases
  • Add SFT functionality

I’m sure I’ll add more than the above over time but these are my next priorities.

I’ve released two other extensions in the last few days NodeJS Extension to Create/Write/Append Files & NodeJS Extension to Change File & Folder Permissions which can be used in conjunction with this one.

I’m using them for example to generate a config on my Wappler server, SCP it over to a remote server, and run a script there, the script runs a curl in the end to another Wappler endpoint.

There are lots of possibilities when it comes to being able to connect to a remote server directly inside Wappler so I hope that I can extend this extension a lot over time. Feedback and ideas are more than welcome.

You can get the module here:

6 Likes

@Apple that’s the first version

1 Like

The package you’re using for SSH might not facilitate doing this:

  • Make stdout available as output inside Wappler

It seems to use a callback instead of the more modern promise or async/await syntax, modern example here:

await ssh.connect();
let output = await ssh.exec("whoami");
console.log(output); // Log to console as currently doing
return {output: output} // Returns object to Wappler, with element "output"
/*
{
    "output": "root"
}
*/

In addition to the output string, the object may contain the exit code of the command - this is why I’m not returning a string directly, but instead wrapping it in an object. An exit code of 0 indicates the command was successful

I highly recommend the usage of the async/await syntax, see here to convert your .js extension code for usage with async/await:

You’d then need to swap the NPM package you’re using for one with first-hand support for promises/async-await, like the one linked above. Anything that supports Promises supports Async/Await.

1 Like

Thanks @Apple!

Im aware of that and should have mentioned it. The current package indeed doesn’t support promises.

ssh2promise isn’t maintained anymore and I’m thinking about building my own wrapper or forking it and building based on it. The community around ssh2promise is quiet strong but I’m always a little careful when the core dev isn’t around anymore.

I mentioned GH releases because there will be breaking changes. So the longterm plan is to go either with ssh2 directly or ssh2promise which would wrap everything for me but isn’t 100% reliable. That’s why I went with synchronous for the first version.

Here we go @Apple. I rebuilt the extension with ssh2-promise. It’s async and returns the data from stdout and an error message if an error occurs.

CleanShot 2022-09-03 at 21.12.24

There is one new input called Define Export. You can set that to any unique string in your workflow.

CleanShot 2022-09-03 at 21.21.24

Then you can use that string in the data picker to access the stdout data and the error message.

CleanShot 2022-09-03 at 21.22.18

It’s tagged as V1.0.0 on GitHub and you can get it here:

2 Likes

I also found this one that uses promises:

It also returns stderr and (exit) code in addition to stdout. Perhaps that would be a better option?

I would also suggest replacing “exportstdout” to “stdout” for more standardized naming, as well as renaming the extension option “Define Export” to “Name” and putting it as the 1st option - it’s kind of a standard on Wappler extensions :slight_smile:

Output schema:

{
    stdout: "hello"
    stderr: ""
    code: 0, // or exit_code 
    error: ""
}

As a minor feature suggestion, I would add a checkbox option for “Throw error”, so the extension can throw an error instead of returning the error as a string in the return object. This would allow one to use the Try/Catch steps within Wappler for handling errors.

I’m very happy with it regardless, thanks for sharing!

1 Like

Thanks @Apple

New release is out (V1.1.0)

  • Switched from ssh2-promise to node-ssh
  • Added SFTP support for pulling and putting files

  • Added SSH key passphrase support and restructured the panel & finally added the right icons and colors

  • Added stderr, stdout, code to output for ssh actions

All actions (ssh, put file, pull file) will throw an error so you can add them to a try -> catch workflow.
The ssh action will throw an error if the initial connection fails.
If the connection is successful but the command you run on the server errors out then you can check the code output and stderr.
The code output will be 0 if everything went well and stderr will contain the error as a string. stdout will contain the terminal output if there was no error.

3 Likes

I currently have another private repo of the extension which has another action that allows to move an entire directory via sftp including all files in the directory. It supports defining the concurrency aka how many sftp stream to run simultaneously , the option to handle everything recursive and the option to exclude things like .files. It’s currently not dynamic but if it would be useful to anybody then I can make it dynamic and add it to the public repo as well.