Setting Up SSL/HTTPS with nginx
How to configure an nginx reverse proxy with Let's Encrypt SSL for Foundry VTT, required for voice and video features.
Overview
HTTPS is required for Foundry VTT voice and video features. Browsers enforce a "secure context" policy that blocks access to microphones and cameras on non-HTTPS pages, regardless of Foundry's own settings. If your players use audio or video at the table, HTTPS is not optional.
The recommended approach is an nginx reverse proxy on port 443 that forwards requests to Foundry on port 30000. This keeps Foundry's configuration simple and lets nginx handle certificate management.
Prerequisites
- A domain name pointing to your server's IP (e.g.,
foundry.example.com) - nginx installed on the server
- Foundry already running on port 30000
Install Certbot and Obtain a Certificate
# Debian/Ubuntu
apt install certbot python3-certbot-nginx
# Obtain a certificate (certbot modifies nginx config automatically)
certbot certonly --nginx -d foundry.example.com
Certificates are placed at:
/etc/letsencrypt/live/foundry.example.com/fullchain.pem
/etc/letsencrypt/live/foundry.example.com/privkey.pem
nginx Configuration
Create a new site configuration at /etc/nginx/sites-available/foundry:
# Redirect HTTP to HTTPS
server {
listen 80;
server_name foundry.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name foundry.example.com;
ssl_certificate /etc/letsencrypt/live/foundry.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/foundry.example.com/privkey.pem;
# WebSocket support — required for Foundry
location / {
proxy_pass http://localhost:30000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 90;
}
}
The Upgrade and Connection headers are mandatory. Foundry uses WebSockets for real-time communication; without these headers, the connection will fail.
Enable the site and reload nginx:
ln -s /etc/nginx/sites-available/foundry /etc/nginx/sites-enabled/foundry
nginx -t
systemctl reload nginx
Configure Foundry for the Reverse Proxy
Stop the Foundry server, then update /foundry-data/Config/options.json:
{
"port": 30000,
"proxySSL": true,
"proxyPort": 443
}
These two fields are critical:
proxySSL: true— tells Foundry to generatehttps://links in invitation URLs and asset pathsproxyPort: 443— tells Foundry what external port clients are reaching
Without these settings, invitation links will point to http:// on port 30000 even though clients are connecting on port 443.
Restart Foundry after editing the config.
Cloudflare Alternative
If you proxy your domain through Cloudflare, SSL is handled at Cloudflare's edge. Set Cloudflare SSL/TLS mode to "Full" or "Full (Strict)". You still need to configure proxySSL: true and proxyPort: 443 in options.json. Note that Cloudflare's free WebSocket support may have limitations on high-traffic servers.
Certificate Renewal
Certbot installs a systemd timer that renews certificates automatically. Verify it is active:
systemctl status certbot.timer
Test renewal without actually renewing:
certbot renew --dry-run
Verifying HTTPS Works
- Navigate to
https://foundry.example.comin a browser - Confirm no certificate warning appears
- Start a world and verify the browser URL shows
https:// - Test audio/video — browser should prompt for microphone/camera permission rather than silently blocking