FoundryVTT is a high quality virtual online tabletop platform. Unlike Roll20, however, there’s not a central server — once you buy a license, you have to run it someplace. There are a few services that will do this for you at a reasonable price, but I’m a geek, so if I start using FoundryVTT I want to host it myself.
Fly.io is a very cool new application hosting cloud. I experimented with it a month ago for hosting an NJPWWorld RSS feed generator and it was awesomely simple. They support persistent disk, so I couldn’t see any reason why it wouldn’t work for FoundryVTT. And it did! Details after the cut.
Setting up Fly.io is really easy. Start with their speedrun guide; do the first couple of steps until you’re logged in. Everything runs through their command line app,
flyctl. If that guide is too terse for you, use this one and stop when you get to “Creating an App on Fly.”
Fly.io uses Amazon’s FirecrackerVM technology, but to make life simple, you build a fly.io app using a Docker image. There are a bunch of preconfigured solutions to running FoundryVTT in Docker. I used the simplest one, mikysan’s simple dockerfile, because Fly.io handles all the reverse proxying that’s built into some of these more complex solutions.
That Dockerfile needs you to download FoundryVTT yourself. You want the linux version, as per this page. Download it and unzip it, and then download
Dockerfile from mikysan’s repo into the
To verify that everything was working, I wanted to get FoundryVTT up and running locally first. I already had Docker Desktop installed, but if you don’t, you can find it here. It’s a pretty easy install.
OK, so let’s build and run this sucker. Building:
docker build -t foundryvtt .
Lots of build status, and done. Hm; for the sake of testing, it’s going to need a data directory, so I made one:
Running the Docker container:
docker run --name fvtt \ -p 30000:30000 \ -v `pwd`/data:/home/foundry/data \ -d foundryvtt
Pulled up my Docker Desktop dashboard, and whoops, it exited. What do the logs say?
[ERROR] You are using Node.js version 12.22.4. Foundry Virtual Tabletop requires Node.js version 14.x or greater.
Easy fix. Edit the
Dockerfile. At the very top there’s a line that says
FROM node:12-alpine; edit that to read
FROM node:14-alpine. This means “use the node.js 14.x base image.” I actually guessed at the right image name here, but if I’d needed to look it up I could have done so here.
OK. Ran the Docker image again using the above command, and everything worked fine. I had a brief problem with being unable to enter the license key, but it turns out that’s a Safari issue and you can just use Chrome. You can also select Develop -> Experimental Features -> WebGL 2.0 in Safari if you like.
Great. Now let’s get it over to fly.io. This is really astoundingly simple. If you have a working Docker image, you just type:
You may need to select an organization; you can just use personal here. There’s some fun stuff you can do with organizations and buying credits in advance, which helps keep a lid on unexpected costs, but it’s out of scope for this post. You’ll also need to choose a region. The default choice is fine.
It’ll then ask you if you want to deploy. Say no, because we’ve got some config changes to make first.
fly.toml — the launch command just created it in the same directory you’re already working in. You need to make two changes.
First, find the line that reads
internal_port = 8080. Change that to read
internal_port = 30000. FoundryVTT runs on port 30000 by default, and fly.io needs to know where to forward incoming HTTP traffic.
Second, add a new block to the end of the file. It should look like this:
[[mounts]] source="foundryvtt_data" destination="/home/foundry/data"
This tells fly.io to mount the persistent volume named “foundryvtt_data” into the container at /home/foundry/data, which is where our FoundryVTT installation expects to save data. The end of the
Dockerfile looks like this:
CMD ["node", "./resources/app/main.js", "--headless", "--dataPath=/home/foundry/data" ]
dataPath at the end? If you don’t make sure that’s persistent storage, it’ll go away when the container restarts.
However, you haven’t created that persistent volume yet, so let’s do that now:
flyctl volumes create foundryvtt_data --region sea --size 10
This creates a 10 GB volume (the
--size parameter) in the Seattle region. If you used a different region when you ran
flyctl launch, use that region here. It’ll still work if you don’t but it’ll be slower.
foundryvtt_data is the name of the volume. You don’t really need 10 GB for this but that’s the minimum volume size fly.io supports.
By the by, this is the only thing that’s going to cost you any money. Your usage of FoundryVTT on fly.io will fit in the free tier easily, but persistent storage isn’t free. It costs $0.15/GB per month of provisioned capacity, which means this’ll cost you $1.50 a month. Still cheaper than the hosted options!
Now we’re done with configuration changes. Type:
It’ll churn a bit while building a new image, and eventually you should see something like:
==> Creating release Release v0 created You can detach the terminal anytime without stopping the deployment Monitoring Deployment 1 desired, 1 placed, 1 healthy, 0 unhealthy [health checks: 1 total, 1 passing] --> v0 deployed successfully
This will launch the Web site in your browser. Enter your license key and accept the license agreement. Then click on Configuration and enter an Administrator Password. Finally, click the Save Changes button. FoundryVTT will ask you if you’re sure. You are.
I don’t know of any way to preconfigure this password effectively; until you do this, someone else could in theory come along and take over your installation. It’s a minor risk but it’s still wise to close the hole as quickly as possible.
You now have a working FoundryVTT installation. If you’re curious, you can type
flyctl ssh console to get a shell on the container. Do
df -k and you’ll see
/home/foundry/data mounted from the persistent volume. Cool stuff.
Let me know if you have any questions!