“Best” depends on your requirements. Large files vs small files, many all the time or occasional, do the receivers want their contents as values in the VMs or not?
rsync and os:cmd would be a good start, unless the requirements clearly say otherwise.
And what about sendfile for point-to-point transfers or, if having a network of nodes, peer-to-peer protocols? (for example apparently several Erlang BitTorrent clients can be found)
Just one anecdotal warning - we’ve seen issues on the receiving end of such a file transfer (using file:sendfile). At high concurrency and rate of operations we’ve seen the binary allocator struggle with deallocating all the binaries received from socket. A stop-gap solution of a simple NIF for receiving and writing to a file with a pool of buffers worked well for us.
Shared filesystem where the file implicitly exists on all nodes?
Shared S3-like where the file exists elsewhere, but is accessible from all nodes?
Outbox, inbox pattern: you write to local filesystem, something else picks it up and writes it to the remote filesystem? Remote end polls for newly-arrived files.
Like @mikpe says: “best” depends on your requirements.