Copying files to a volume on Fly.io

/ Reading time: 5 minute/s

Today, I finally did something I've been meaning to do since last year: I migrated my Vaultwarden installation from Amazon ECS to Fly.io.

The migration really was very simple and mostly painless to do — the only part that slowed me down was figuring out how to copy files up to a (disk) volume I've set up on the Fly.io platform. Vaultwarden uses SQLite, so all of its data was on the file system. For a complete migration, I will need to copy the files from my old installation to the new one.


Given a Fly.io app:

app = "my-sample-app"

[build]
  dockerfile = "Dockerfile"

[mount]
  source = "my_volume"
  destination = "/data"

We have a single volume my_volume mounted to our app at /data. We might be able to scp into the app but Fly.io apps now don't automatically come with a static IPv4 address. You still can get an IPv4 address, but this will cost USD 2.00/month.

I wanted to look for a way to do this with just default resources. Unfortunately, it also gets a bit complicated.

So, how?

First, we grab a Wireguard config file:

$  fly wireguard create

This creates a config file on your machine which you can then import into Wireguard. Doing so gives you network visibility to your app via a private VPN connection. While connected to the VPN, your app will be available at <app-name>.internal. (For example, the app above will be at my-sample-app.internal).

Next, we create a (temporary) SSH key:

$  fly ssh issue

This creates a pair of SSH keys on your machine that you can use to connect to your app. For example, my-app-key and my-app-key-cert.pub. We're only interested in your private key here, not the one with a .pub extension.

To test connectivity, just run ssh root@<app-name>.internal -i <your-key-name>. For example:

$  ssh root@my-sample-app.internal -i my-app-key

If everything is OK, you should now be in a tunneled SSH session inside your app. Exit the session by typing exit.

Since we can now ssh into our app normally (i.e. without using fly ssh console), we can now also use the same credentials to run scp to copy files to/fro our app.

For example, to copy foo.txt from my machine's current directory to /data/foo.txt in the app (and therefore, into the volume):

$  scp foo.txt root@my-sample-app.internal:/data/foo.txt

Caveats

Something that you will have to make sure of is that the container that your app is running actually has scp available to it. Otherwise, the operation will fail.

If that's not the case, you can generally install it using something similar to this in your Dockerfile:

RUN apt-get update && \
    apt-get install -y openssh-client