Fusion - run Elixir code on remote servers via SSH, no deployment needed

Ten years ago I got curious: what would a Chef/Ansible-like tool look like built entirely in Elixir? One that uses Erlang distribution instead of agents installed on remote machines.

I got most of it working — SSH tunnels, remote BEAM bootstrap, transparent clustering. But in the last piece, full code loading I run out of time. Life happened. The project sat.

A few weeks ago I picked it back up. Finished the bytecode pushing and dependency resolution with some AI assist, cleaned it up to newer utilities and shipped it in a day.

What it does

Connect to a remote server over SSH, push your modules, run them. No deployment. No pre-installed app on the remote. Just SSH access and Elixir.

target = %Fusion.Target{
  host: "10.0.1.5",
  port: 22,
  username: "deploy",
  auth: {:key, "~/.ssh/id_ed25519"}
}

{:ok, manager} = Fusion.NodeManager.start_link(target)
{:ok, remote_node} = Fusion.NodeManager.connect(manager)

# Run your own modules remotely — dependencies are pushed automatically
{:ok, result} = Fusion.run(remote_node, MyApp.Worker, :process, [data])

When you call MyApp.Worker remotely, Fusion reads the BEAM bytecode, walks the dependency tree, and pushes everything the module needs. No manual tracking.

Why build this

Back then it was mainly for curiosity. The idea was that instead of python or ruby, you can run Elixir on remote machines without a full deployment pipeline. Ad-hoc tasks across a fleet. Provisioning. One-off diagnostics. Interactive remote exploration.

Fusion gives you that without leaving Elixir.

How it works (the short version)

  • 3 SSH tunnels bridge Erlang distribution through firewalls — two reverse, one forward
  • Remote BEAM bootstrap starts Elixir on the remote with flags that route all traffic through the tunnels
  • Bytecode pushing transfers compiled .beam binaries (not source) with automatic dependency resolution

Zero runtime dependencies. ~700 lines of Elixir.

Deep dive articles

I wrote a three-part series covering the internals:

  1. Running Elixir on Remote Servers with Fusion — hands-on tutorial
  2. How Fusion Works: Tunnels and Distribution — SSH tunnel architecture
  3. How Fusion Works: Bytecode Pushing — dependency resolution and code loading

Links

Feedback welcome

This is a POC. I do not plan using it in prod anytime soon. If someone find this interesting I’d love to hear your thoughts. API design, use cases I haven’t considered, rough edges. Maybe someone will find this useful.

25 Likes

This looks great!

I rewrote one of my older applications just recently which is an IaaS platform similar to Linode/DO/etc. I originally had it as Ruby orchestrator + a Go sidecar deployed to each hypervisor, but when I brought it over to Elixir/Phoenix I ended up using SSH as the transport for simplicity, with nothing running on the hypervisor.

I looked at doing something similar to Fusion but I couldn’t completely crack the problem. I wanted to keep things simple, but I definitely made a few compromises in the journey.

I’m going to check this out in depth once I get a free moment.

1 Like

I dislike Ansible but have not been able to find a better replacement. So I’m rooting for you!

For design inspiration, you might like to review the work done on JetPorch, a deploy tool by Michael DeHaan, the original Ansible developer. DeHaan worked on this project for a year-ish, then abandoned the project. But IMO his design was very good! You can find the archived JetPorch repo here: ~mpdehaan/jetporch - the Jet Enterprise Professional Orchestrator - sourcehut git

3 Likes