Hetzner Object Storage for Foundry VTT
Set up Hetzner Object Storage as asset storage for your Foundry VTT server
This guide walks you through configuring Hetzner Object Storage as external asset storage for Foundry VTT. Hetzner offers affordable S3-compatible storage that works seamlessly with Foundry.
Prerequisites
- A running Foundry VTT server (see Manual Server Setup)
- A Hetzner Cloud account
- SSH access to your Foundry server
Why Use Object Storage?
- Save disk space on your VPS
- Cost effective - Hetzner storage is very affordable
- Easier backups - worlds are small, assets are in the cloud
- Share assets across multiple Foundry instances
Step 1: Create a Bucket
- Log in to Hetzner Cloud Console
- Select your project (or create a new one)
- Go to Object Storage in the left sidebar
- Click Create Bucket
- Choose a region:
| Region | Location |
|---|---|
| fsn1 | Falkenstein, Germany |
| nbg1 | Nuremberg, Germany |
| hel1 | Helsinki, Finland |
- Enter a bucket name (e.g.,
foundry-assets) - Click Create Bucket
Bucket names must be unique within your Hetzner project. Choose something descriptive like foundry-assets or my-vtt-storage.
Step 2: Create Access Credentials
- In your project, go to Security → API Tokens
- Click Generate API Token
- Select Read & Write permissions
- Copy and save the token
Now create S3 credentials:
- Go to Object Storage → S3 Credentials
- Click Generate Credentials
- Save both the Access Key and Secret Key
Store your credentials securely. The secret key is only shown once during creation.
Step 3: Configure CORS
CORS (Cross-Origin Resource Sharing) allows your Foundry server to load assets from the bucket. You’ll need to use a tool like s3cmd or aws-cli.
Install s3cmd
apt-get install -y s3cmd
Configure s3cmd for Hetzner
s3cmd --configure
Enter the following when prompted:
- Access Key: your Hetzner S3 access key
- Secret Key: your Hetzner S3 secret key
- Default Region: your bucket region (e.g.,
fsn1) - S3 Endpoint:
{region}.your-objectstorage.com(e.g.,fsn1.your-objectstorage.com) - DNS-style bucket:
%(bucket)s.{region}.your-objectstorage.com
Option A: Single Domain CORS
Create a CORS configuration file for your specific Foundry domain:
cat > cors.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>https://your-foundry-domain.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
<MaxAgeSeconds>3600</MaxAgeSeconds>
</CORSRule>
</CORSConfiguration>
EOF
Apply the CORS configuration:
s3cmd setcors cors.xml s3://your-bucket-name
Option B: For Self-Hosted with Dynamic DNS
If your Foundry server uses a dynamic DNS name or you access it from multiple networks:
cat > cors.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
<MaxAgeSeconds>3600</MaxAgeSeconds>
</CORSRule>
</CORSConfiguration>
EOF
Using * as the allowed origin means any website can load your assets. This is fine for game assets but don’t store sensitive files in this bucket.
Option C: Multiple Specific Origins
For accessing Foundry from both local network and public internet:
cat > cors.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>https://foundry.yourdomain.com</AllowedOrigin>
<AllowedOrigin>http://192.168.1.100:30000</AllowedOrigin>
<AllowedOrigin>http://localhost:30000</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
<MaxAgeSeconds>3600</MaxAgeSeconds>
</CORSRule>
</CORSConfiguration>
EOF
Step 4: Configure Foundry
SSH into your Foundry server and create the aws.json configuration file:
cat > /home/foundry/foundrydata/Config/aws.json << 'EOF'
{
"buckets": ["your-bucket-name"],
"region": "fsn1",
"endpoint": "https://fsn1.your-objectstorage.com",
"credentials": {
"accessKeyId": "YOUR_ACCESS_KEY",
"secretAccessKey": "YOUR_SECRET_KEY"
}
}
EOF
Replace:
your-bucket-namewith your bucket namefsn1with your chosen region (both places)YOUR_ACCESS_KEYandYOUR_SECRET_KEYwith your S3 credentials
Set proper permissions:
chown foundry:foundry /home/foundry/foundrydata/Config/aws.json
chmod 600 /home/foundry/foundrydata/Config/aws.json
Step 5: Update Foundry Options
Edit your existing options.json to add the awsConfig property:
nano /home/foundry/foundrydata/Config/options.json
Add this line inside the JSON object:
"awsConfig": "aws.json"
Your options.json should look something like this (your other settings may vary):
{
"hostname": "your-foundry-domain.com",
"port": 30000,
"proxyPort": 443,
"proxySSL": true,
"awsConfig": "aws.json"
}
Step 6: Restart Foundry
sudo -u foundry pm2 restart foundry
Step 7: Verify the Setup
- Open Foundry VTT in your browser
- Go to Settings → Configure Game Settings
- You should see your S3 bucket listed under Asset Storage
- Try uploading an image - it should appear in your Hetzner bucket
Hetzner Endpoint Reference
| Region | Endpoint |
|---|---|
| fsn1 | https://fsn1.your-objectstorage.com |
| nbg1 | https://nbg1.your-objectstorage.com |
| hel1 | https://hel1.your-objectstorage.com |
Pricing
Hetzner Object Storage is billed based on:
- Storage: €0.00524/GB/month (~€5.24/TB)
- Egress: €1.00/TB (first 1TB free)
For most Foundry setups, costs are minimal - typically under €1/month.
Troubleshooting
Assets not loading (CORS errors)
Check browser console for CORS errors. Verify your CORS configuration:
s3cmd info s3://your-bucket-name
Re-apply CORS if needed:
s3cmd setcors cors.xml s3://your-bucket-name
“Access Denied” errors
- Verify your access key and secret are correct in
aws.json - Check the bucket name matches exactly (case-sensitive)
- Ensure the region and endpoint match your bucket’s location
- Verify your S3 credentials have read/write permissions
Foundry doesn’t show S3 option
- Verify
aws.jsonexists and has correct permissions - Check that
options.jsonincludes"awsConfig": "aws.json" - Check Foundry logs for configuration errors:
sudo -u foundry pm2 logs foundry
“Invalid endpoint” errors
Make sure the endpoint format is correct:
- Include
https:// - Use
.your-objectstorage.com(not.hetzner.com) - Match the region exactly (fsn1, nbg1, or hel1)
Your Foundry VTT server is now using Hetzner Object Storage for assets!
Migrating Existing Assets
If you have existing assets on your server, you can sync them to the bucket:
s3cmd sync /home/foundry/foundrydata/Data/ s3://your-bucket-name/
Then update your world’s asset paths to use the S3 storage. This is easiest done through Foundry’s file browser by re-linking assets.