Foundry VTT is a standalone application for tabletop multiplayer RPGs. It is comparable to Roll20, but with a large number of community-driven modules and more modern features. In this guide, I will explain how to self-host Foundry VTT using LightSail and S3 (other hosting services will work), with HTTPS and automated backups.

Create and Connect to a LightSail Instance

  1. Create an AWS account if you do not have one
  2. Create a LightSail instance. Select:
    • Your region. I picked us-west-2 because my players and myself are located on the West coast.
    • Select OS Only and Ubuntu 20.04 LTS
    • Download/change your SSH key if you have not already (under optional)
    • Choose your instance price. If this is your first-time using AWS, you will get 3 months free. I picked the $5.00 tier, and it has been ample for my usage.
    • Name your instance and click create
  3. Once the instance is running, click on it and go to Networking and add a Static IP and add a Firewall rule for HTTPS (port 443).

When the instance is created, log in using ssh -i <KEY_NAME>.pem [email protected]<IP_ADDRESS>

Starting the FoundryVTT Service

First let us install the packages you will need:

$ sudo apt update
$ sudo apt upgrade
$ sudo apt install nginx
$ sudo apt install certbot
$ sudo apt install unzip
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
$ sudo apt-get install -y nodejs

It is good practice to create an accout with limited access to run your service.

$ sudo adduser foundryvtt
$ sudo passwd -d foundryvtt

passwd -d removes password login from the account. Next log into the account and create two folders: foundrycore and foundrydata.

$ sudo su foundryvtt
$ cd $HOME
$ mkdir foundrycore foundrydata

foundrycore will hold FoundryVTT’s application, foundrydata will be your data.

If you have purchased FoundryVTT you will be able to generate a temporary download link from your account secion on their website. Copy that link.

$ cd $HOME/foundrycore
$ wget <YOUR_DOWNLOAD_LINK> -o foundryvtt.zip
$ unzip foundryvtt.zip
$ rm foundryvtt.zip

Test to make sure the service is up and running:

$ node resources/app/main.js --dataPath=$HOME/foundrydata

The easiest way to get the service up-and-running is to use pm2.

$ npm install [email protected] -g
$ pm2 start "node /home/foundryvtt/foundrycore/resources/app/main.js --dataPath=/home/foundryvtt/foundrydata"

The server is now running! If you want to view it, go to your LightSail instance > Networking and create a new rule to allow traffic to port 30000. Then you should be able to access it at `<IP_ADDRESS>:30000.

After you finish assessing it, remove that rule. We will setup nginx as a HTTP/HTTPS proxy later.

I placed this in a script /home/foundryvtt/start.sh:

#!/bin/bash
# only run if there is no other instance running
if [ "$(pm2 id foundrydata)" == "[]" ]; then
        pm2 start "node /home/foundryvtt/foundrycore/resources/app/main.js --dataPath=/home/foundryvtt/foundrydata"
fi

Run on Reboot

To make it automatically start on reboot, stop the instance:

$ pm2 stop 0

Then run:

$ pm2 startup
[PM2] You have to run this command as root. Execute the following command:
      sudo su -c "env PATH=$PATH:/home/unitech/.nvm/versions/node/v14.3/bin pm2 startup <distribution> -u <user> --hp <home-path>"

$ sudo su -c "env PATH=$PATH:/home/unitech/.nvm/versions/node/v14.3/bin pm2 startup <distribution> -u <user> --hp <home-path>"
$ $HOME/start.sh
$ pm2 save

Adding Additional Storage Space Using S3

If you would like FoundryVTT to use S3 as an additional storage space (which I highly recommend), follow the official guide.

Create an Automatic Backup

I use rclone to manage my backups and S3 as storage. You will have to go through the rclone setup process specified here.

Still as user foundryvtt, create a script called backup.sh and add the following:

#!/bin/bash

echo "Backup starting. Stopping server"

#Stop the Foundry server to ensure no files change during the backup
pm2 stop foundrydata  &> /dev/null

# the folder containing foundrydata
FOUNDRY_HOME=/home/foundryvtt
# rclone's config file
RCLONE_CONFIG=${FOUNDRY_HOME}/.config/rclone/rclone.conf
# max age in days you want to keep the backups
MAX_AGE=30
# the bucket's name
BUCKET=<YOUR_BUCKET_NAME>
# date to append to the tarball
DATE_TIME=$(date +"%Y-%m-%d_%H-%M")

# make a temporary directory to hold the backup and add the compressed data
TEMP=$(mktemp -d /tmp/foundry-backup.XXX)
echo "Created temporary folder at $TEMP. Compressing and sending to bucket $BUCKET"
tar czf ${TEMP}/foundrydata-${DATE_TIME}.tar.gz ${FOUNDRY_HOME}/foundrydata  &> /dev/null

# start the Foundry server
pm2 start foundrydata  &> /dev/null

# copy to cloud storage
rclone copy ${TEMP} remote:${BUCKET} --config="${RCLONE_CONFIG}"  &> /dev/null

# delete backups that are older than 30 days
rclone delete remote:${BUCKET} --min-age ${MAX_AGE}d --config="${RCLONE_CONFIG}"  &> /dev/null

# cleanup
echo "Removing temporary folder $TEMP"
rm -rf $TEMP
echo "Backup complete. Restarted server"

Next, create a cronjob to call the script:

$ crontab -e
# Add the following
0 4 * * 0 /home/foundryvtt/backup.sh

This will call the script every Sunday at 4:00 AM.

Use Certbot and Nginx to Proxy to Server

First, make sure nginx is not running:

$ sudo systemctl stop nginx.service

Use certbot to create certifications for your domain. Your domain will have to be pointing at your IP address for this to work. Sometimes it takes a while for DNS to propagate, so be patient and keep retrying.

$ sudo certbot certonly --nginx

Then change /etc/nginx/sites-available/default to the following:

server {
        server_name _; # managed by Certbot

        listen [::]:443 ssl ipv6only=on; # managed by Certbot
        listen 443 ssl; # managed by Certbot
        ssl_certificate /etc/letsencrypt/live/<FILE_NAME>/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/<FILE_NAME>/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

        # The default max body size is 1MB, which is too small for transfering files
        client_max_body_size 500M;

        # Proxy Requests to Foundry VTT
        location / {

            # Set proxy headers
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            # These are important to support WebSockets
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";

            # Make sure to set your Foundry VTT port number
            proxy_pass http://localhost:30000;
    }

}
server {
    listen 80 default_server;
    server_name _;
    return 301 https://$host$request_uri;
}

And start nginx up again:

$ sudo systemctl start nginx.service

Done! You should be able to visit your instance of FoundryVTT at your domain with HTTPS.