# VPS Hosting for FoundryVTT: A Beginner's Guide

## Prerequisite Checks

Before you begin, ensure you have:

**Required:**

* A valid FoundryVTT license (purchase at [https://foundryvtt.com](https://foundryvtt.com))
    
* Basic command-line familiarity
    
* VPS hosting ($5-15/month)
    
* SSH client installed:
    
    * **Windows:** Built into Windows 10/11, or download PuTTY
        
    * **Mac/Linux:** Built-in Terminal
        

**Optional but Recommended:**

* A domain name ($10-15/year from Namecheap, Cloudflare, etc.)
    
* SFTP client for file uploads (FileZilla, Cyberduck, WinSCP)
    

**Time Estimate:** 30-60 minutes for complete setup

---

## Step 1: Get a VPS

Choose a provider like OVHcloud, DigitalOcean, Hetzner, or Linode.

**Recommended specs:**

* 2GB RAM minimum (4GB recommended)
    
* 2 CPU cores
    
* 20GB+ SSD storage
    
* Ubuntu 24.04 LTS or Newer
    

You will need SSH access, most hosts have guides for this

## Step 2: Initial Setup

SSH into your server. On Windows, use PuTTY, Windows Terminal, or WSL. On Mac/Linux, open a Terminal and run:

```bash
ssh username@your_server_ip
```

Replace `your_server_ip` with your VPS IP address and `username` with your provider's default user:

* **OVHcloud:** Usually `ubuntu` or `debian` (depending on OS)
    
* **DigitalOcean:** `root` for some images, `ubuntu` for Ubuntu droplets
    
* **Hetzner:** `root`
    
* **Linode:** `root`
    

Check your provider's setup email or documentation for the correct username. Accept the host key when prompted.

**Authentication:**

* **Password:** If your VPS uses password authentication, you'll be prompted to enter the password (usually emailed to you by your hosting provider)
    
* **SSH Key:** If you set up SSH keys during VPS creation, the key will be used automatically. No password prompt will appear.
    
    * For PuTTY users: Load your private key (.ppk file) in Connection &gt; SSH &gt; Auth
        
    * For OpenSSH users: Specify the key with `ssh -i /path/to/private_key username@your_server_ip`
        

Once connected, update packages:

```bash
sudo apt update
sudo apt upgrade -y
sudo apt install unzip -y
```

## Step 3: Create a Dedicated User

```bash
sudo useradd -r -m -d /opt/foundry -s /bin/bash foundry
sudo passwd foundry  # Set a password for SFTP access
```

## Step 4: Install Node.js via fnm (as foundry user)

```bash
sudo -u foundry -i  # Switch to foundry user

curl -fsSL https://fnm.vercel.app/install | bash
source ~/.bashrc
fnm install --lts --corepack-enabled
fnm default lts-latest
fnm use lts-latest

node --version  # Verify installation
```

## Step 5: Install PM2

```bash
npm install -g pm2
pm2 --version  # Verify installation
```

## Step 6: Download and Install FoundryVTT

Still as the foundry user:

```bash
# Get your timed URL from https://foundryvtt.com/me/licenses
# (Requires a Foundry license)
cd ~
mkdir -p app
curl -L -o foundry.zip "YOUR_TIMED_URL_HERE"
unzip foundry.zip -d ~/app
rm foundry.zip

# Create data directory
mkdir -p data
```

## Step 7: Configure Foundry Options

Create the Foundry configuration file at `~/data/Config/options.json`:

**Option A: With Domain & HTTPS (Strongly Recommended)**

```bash
mkdir -p ~/data/Config
cat > ~/data/Config/options.json <<'EOF'
{
  "hostname": "foundry.yourdomain.com",
  "routePrefix": null,
  "sslCert": null,
  "sslKey": null,
  "port": 30000,
  "proxyPort": 443,
  "proxySSL": true,
   "upnp": false
}
EOF
```

**Important:** Replace [`foundry.yourdomain.com`](http://foundry.yourdomain.com) with your actual domain name.

This configuration tells Foundry:

* It's accessible at your domain name
    
* To run on port 30000 (internal)
    
* That it's behind a reverse proxy (Caddy) on port 443
    
* That the proxy handles SSL/TLS
    

**Option B: Without Domain/HTTPS (Not Recommended)**

If you want to skip DNS and HTTPS setup, you can use:

```bash
mkdir -p ~/data/Config
cat > ~/data/Config/options.json <<'EOF'
{
  "port": 30000,
  "upnp": false
}
EOF
```

Then open port 30000 in your firewall (`sudo ufw allow 30000/tcp`) and access via [`http://your_server_ip:30000`](http://your_server_ip:30000).

**⚠️ Warning:** This is insecure as traffic is unencrypted. Only use for testing or if using a VPN.

## Step 8: Configure PM2

Create `~/ecosystem.config.js`:

```bash
cat > ~/ecosystem.config.js <<'EOF'
module.exports = {
  apps: [{
    name: 'foundry',
    script: '/opt/foundry/app/main.js',
    cwd: '/opt/foundry/app',
    env: {
      NODE_ENV: 'production',
      FOUNDRY_VTT_DATA_PATH: '/opt/foundry/data'
    },
    instances: 1,
    autorestart: true,
    watch: false,
    max_memory_restart: '1G'
  }]
};
EOF
```

Start Foundry:

```bash
pm2 start ecosystem.config.js
pm2 save
pm2 startup  # Copy and run the command it outputs as your regular user
```

Exit back to your regular user:

```bash
exit
```

## Step 9: Install Caddy (Optional but Strongly Recommended)

**Why use Caddy?**

* Automatic HTTPS with free SSL certificates from Let's Encrypt
    
* Secure encrypted connections (required for many web features)
    
* Professional setup with custom domain
    
* Better security for passwords and game data
    

**⚠️ If you skip Caddy:** You'll need to use [`http://your_server_ip:30000`](http://your_server_ip:30000) and manually open port 30000. Traffic will be unencrypted.

```bash
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install -y caddy
```

## Step 10: Configure Caddy

Replace [`foundry.yourdomain.com`](http://foundry.yourdomain.com) with your actual domain and [`your-email@example.com`](mailto:your-email@example.com) with your email:

```bash
sudo tee /etc/caddy/Caddyfile > /dev/null <<'EOF'
{
    email email@example.com
}

foundry.example.com {
    reverse_proxy localhost:30000

    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "SAMEORIGIN"
        Referrer-Policy "same-origin"
    }

    request_body {
        max_size 500MB
    }
}
EOF
```

Validate and start Caddy:

```bash
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl enable caddy
sudo systemctl restart caddy
```

## Step 11: Configure SFTP for File Uploads

Edit SSH config:

```bash
sudo tee -a /etc/ssh/sshd_config > /dev/null <<'EOF'

# Foundry SFTP configuration
Match User foundry
    ForceCommand internal-sftp
    PasswordAuthentication yes
    ChrootDirectory /opt/foundry
    PermitTunnel no
    AllowAgentForwarding no
    AllowTcpForwarding no
    X11Forwarding no
EOF
```

Fix permissions for chroot:

```bash
sudo chown root:root /opt/foundry
sudo chmod 755 /opt/foundry
sudo chown -R foundry:foundry /opt/foundry/data
```

Restart SSH:

```bash
sudo systemctl restart sshd
```

## Step 12: Configure Firewall (if using ufw)

```bash
sudo ufw allow 22/tcp   # SSH/SFTP
sudo ufw allow 80/tcp   # HTTP
sudo ufw allow 443/tcp  # HTTPS
sudo ufw enable
```

## Step 13: Setup DNS (Optional but Strongly Recommended)

**Why use a custom domain?**

* Easy to remember address instead of IP:port
    
* Required for automatic HTTPS/SSL certificates
    
* Professional appearance
    
* Easier to share with players
    

**⚠️ If you skip DNS:** You can access Foundry via [`http://your_server_ip:30000`](http://your_server_ip:30000) (requires opening port 30000 in firewall and skipping Caddy setup).

**To set up DNS:**

1. Go to your domain registrar or DNS provider
    
2. Add an A record pointing [`foundry.yourdomain.com`](http://foundry.yourdomain.com) to your VPS IP address
    
3. Wait for DNS propagation (can take up to 24 hours, usually much faster)
    

## Step 14: Access Your Foundry Instance

1. Visit [`https://foundry.yourdomain.com`](https://foundry.yourdomain.com)
    
2. Complete the Foundry setup wizard
    
3. Enter your license key
    

## Uploading Files via SFTP

Use any SFTP client (FileZilla, Cyberduck, WinSCP):

* **Host:** Your domain or server IP
    
* **Port:** 22
    
* **Username:** foundry
    
* **Password:** The password you set in Step 3
    
* **Remote path:** `/data`
    

Upload worlds, modules, and assets to the appropriate subdirectories.

## Useful Commands

**Check Foundry status:**

```bash
sudo -u foundry pm2 status
```

**View Foundry logs:**

```bash
sudo -u foundry pm2 logs foundry
```

**Restart Foundry:**

```bash
sudo -u foundry pm2 restart foundry
```

**Check Caddy status:**

```bash
sudo systemctl status caddy
```

**Reload Caddy config:**

```bash
sudo systemctl reload caddy
```

**View Caddy logs:**

```bash
sudo journalctl -u caddy -f
```

## Updating Foundry

1. Download new version as foundry user
    
2. Stop PM2: `pm2 stop foundry`
    
3. Backup: `cp -r resources resources.backup`
    
4. Extract new version over existing files
    
5. Start PM2: `pm2 start foundry`
    

## Troubleshooting

**Foundry not accessible:**

* Check PM2 is running: `sudo -u foundry pm2 status`
    
* Check Caddy is running: `sudo systemctl status caddy`
    
* Verify DNS points to your server IP
    
* Check firewall allows ports 80 and 443
    

**Can't connect via SFTP:**

* Verify SSH is running: `sudo systemctl status sshd`
    
* Check firewall allows port 22
    
* Verify foundry user password is correct
    

**SSL certificate issues:**

* Check DNS is properly configured
    
* View Caddy logs: `sudo journalctl -u caddy -f`
    
* Ensure ports 80 and 443 are accessible from the internet
