Copying files to a volume on Fly.io
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