Rsync over balena ssh tunnel?

Is it possible to run rsync over the balena ssh tunnel?

@jason10, I will take the liberty of answering a slightly different question:

“How can I use rsync to transfer files between my laptop and my devices?”

Well, glad you asked. :slight_smile: In the current state of play, it may require a few setting up steps, depending on exactly what needs to be achieved.

The standard ssh, scp and rsync tools can be used with balenaOS devices. It works with both development and production balenaOS images. In the case of a production image, a ssh key should be added to the config.json file – see sshKeys section of the meta-balena README file. In the case of a development image, no keys are required. (Development images allow root login without a password or ssh keys, so should never be directly exposed to the public internet.)

The ssh server on a device (host OS) listens on TCP port number 22222. This port is not blocked by the device host OS, not even in production. If this port is blocked by a firewall or router on the device’s local network, or if the device has a private IP address, the balena tunnel command can be used as in the examples below.

Example 1 (laptop and device are on the same local network, OR the device has a public / globally routable IPv4/v6 address and port 22222 is not blocked in the device’s local network)

# All these commands to be executed on your laptop/desktop
$ ssh -p 22222 root@<device_ip_address>
$ scp -P 22222 my_local_file root@<device_ip_address>:/mnt/data/
$ export RSYNC_RSH='ssh -p 22222'
$ rsync my_local_file root@<device_ip_address>:/mnt/data/

Example 2 (remote device with a private IP address, or port 22222 is blocked in the device’s local network)

# All these commands to be executed on your laptop/desktop
$ balena tunnel <deviceUUID> -p 22222:4321
$ ssh -p 4321 root@127.0.0.1
$ scp -P 4321 my_local_file root@127.0.0.1:/mnt/data/
$ export RSYNC_RSH='ssh -p 4321'
$ rsync my_local_file root@127.0.0.1:/mnt/data/

Note: use CLI v10.4.0 or later to benefit from fixes to the tunnel command.

The examples above all transfer files between your laptop/desktop and a folder accessible via the device’s host OS – e.g. /mnt/data/. You you may be able to rely on named volumes to transfer files to app containers in this way. But with a bit more setting up, it’s possible to use rsync to transfer files directly into the app container:

# All these commands to be executed on your laptop/desktop
$ balena tunnel <deviceUUID> -p 22222:4321
$ export RSYNC_RSH="/home/user/rsync-shell.sh" && chmod +x "$RSYNC_RSH"
$ rsync my_local_file main_1_1:destination_folder/

Where 'main_1_1' is the name of the app container (as listed by balena-engine ps on the host OS).

The export line above mentions an rsync-shell.sh script. Here’s a basic version of it, with hardcoded values for port numbers and container names:

rsync-shell.sh

#!/bin/bash
CONTAINER_NAME='main_1_1'
TUNNEL_OPTS='-p 4321 root@127.0.0.1'
new_args=()
for arg in "$@"; do
  if [ "$arg" = "$CONTAINER_NAME" ]; then
    new_args+=("$TUNNEL_OPTS" balena-engine exec -i "$CONTAINER_NAME")
  else
    new_args+=("$arg")
  fi
done
echo original command: ssh "$@" >&2
echo modified command: ssh ${new_args[@]} >&2
ssh ${new_args[@]}

Notes:

  • rsync needs to installed in the app container too. Typically it is a case of apt-get update; apt-get install rsync.
  • The rsync-shell.sh script can be improved to suit your use case. As given above, it prints its original and modified input arguments to stderr, so it’s easier to see what is going on when you run rsync.
3 Likes

Thanks Paulo!

Which config.json do you edit?
/mnt/boot/config.json
or
/resin-boot/config.json

It’s not recommended that you edit config.json whilst the device is running, so typically you would mount the resin-boot partition with the disk in another device and edit the config.json there. However if you’re adding SSH keys live on the device you would edit /mnt/boot/config.json (you’ll find /resin-boot/config.json to be read-only), but it’s important to stop the supervisor (systemctl stop resin-supervisor) before doing so and starting it again afterwards. If you’re adding SSH keys we also have a handy tool to do that: https://github.com/balena-io-playground/ssh-key-insert

Hi @chrisys, /mnt/boot/config.json is not read-only. /resin-boot/config.json is, though.

That’s correct, yup

I’m confused then, your post seems to say the opposite - never mind, the other one is read-only. Reading too fast

No worries - I edited my post to be more clear :+1:

I found that specifying my identity file with the -i flag helped me avoid a Bad packet length error.

scp -i ~/.ssh/id_ecdsa -P 4321 root@127.0.0.1:/path/to/file/I/want /where/to/put/file