What the server process needs
Foundry's dedicated-server figures are small because a headless server runs no client: the rendering happens in each player's browser. The requirements article lists these minimums for a dedicated host:
| Resource | Knowledge base figure |
|---|---|
| Operating system | Any OS with glibc 2.28 or newer |
| Node.js | 22 for V13 and below, 24 for V14 and above |
| CPU | At least 1 vCPU, 2 recommended |
| Memory | 4 GB recommended, 2 GB at the least |
| Storage | At least 1 GB |
| Network | Firewall open on the port Foundry is served on |
The same article says memory use grows with the game system and the modules active in a world, so a heavy system with content modules needs more than the floor. Disk is the other variable: every map, token and music file you upload lives in the user data folder, and the server sends it to every player's browser. For a home host the knowledge base recommends at least 12 Mbps of upload for exactly that reason.
Licensing: one key, one server
A Foundry licence is bought once by the host and covers one game server for any number of players, who need no licence of their own. The EULA lets a key be actively used in one location. You may run a second instance on the same key only if nobody but the licence owner can use it, such as a private world-building copy. A home copy and a dedicated server both open to players at the same time need two keys.
Activation needs the server to reach Foundry's licence server once, when you paste the key and sign the EULA. After that, the knowledge base says, nothing would block you if Foundry's own site were offline.
Which machine to run it on
The dedicated server range runs from Moonshot cartridges to four-socket machines, and the service page itself suggests a cartridge for one service per machine, a game server included. The smallest cartridge carries 8 GB of ECC memory and an SSD, double the knowledge base's recommended 4 GB. If the campaign carries large map and audio libraries, size the disk first: the Xeon D-1587 line ships with a 1.92 TB NVMe drive.
- Ports are unmetered on every line (the speed, 500 Mbps or a gigabit, is in each row), so asset downloads at session start cost nothing extra.
- Racked single-, dual- and quad-socket servers carry a full out-of-band console (iLO on HPE machines, iDRAC on Dell, a BMC on Supermicro), as do the m510 and m710x cartridges. Elsewhere in the cartridge range there is power control alone, so an SSH lockout from a firewall mistake can leave a reinstall from the control panel as the way back.
- Five cities: New York, Miami, San Francisco, Amsterdam and Bucharest. Pick the one nearest your table from the locations page.
- IPv6 is a free option at checkout; the firewall below therefore covers both address families.
- A racked machine is handed over in about 30 minutes once payment is approved; Linux images cost nothing.
Running several game servers for the same group? The game server hosting page covers the wider range, and voice for the table can live on the same box with TeamSpeak.
Install: firewall, Node.js, service user
On a fresh Ubuntu dedicated server, close everything but SSH before Foundry ever starts. The ufw steps are ours, not the knowledge base's; ufw applies its rules to IPv6 as well when /etc/default/ufw reads IPV6=yes, which is the default. The knowledge base installs Node from NodeSource; its example script names setup_20.x, below its own minimum, so the version is raised to 24 here for V14. For a V13 install use setup_22.x instead: V13 does not run on Node 24. That script runs as root: download and read it first if you prefer. The non-root foundry user is our addition too; Foundry's guide does not cover it.
grep IPV6 /etc/default/ufw # expect IPV6=yes
sudo ufw default deny incoming
sudo ufw allow OpenSSH
sudo ufw enable
sudo apt install -y libssl-dev unzip
curl -sL https://deb.nodesource.com/setup_24.x | sudo bash -
sudo apt install -y nodejs
node --version # v24.x
sudo useradd --system --create-home --home-dir /opt/foundry \
--shell /usr/sbin/nologin foundry
sudo -u foundry mkdir -p /opt/foundry/app /opt/foundry/data
# Paste the Timed URL from your Foundry account (valid 5 minutes)
read -rp 'Timed URL: ' URL
sudo -u foundry wget -O /opt/foundry/app/foundryvtt.zip "$URL"
sudo -u foundry unzip /opt/foundry/app/foundryvtt.zip -d /opt/foundry/app
Choose the Node.js build type in the download menu: it is the one meant for a headless server. Reading the timed link with read -rp, our addition, keeps it out of shell history; it is still briefly visible in the process list while wget runs, and it expires after five minutes.
Run it under systemd
The knowledge base recommends systemd for a standalone server but gives no unit file; the one below is ours, Restart=always and --noupnp included. Write the unit to /etc/systemd/system/foundry.service. After a daemon-reload, systemctl enable --now foundry starts it at once and on every boot.
[Unit]
Description=Foundry Virtual Tabletop
After=network-online.target
Wants=network-online.target
[Service]
User=foundry
Group=foundry
WorkingDirectory=/opt/foundry/app
ExecStart=/usr/bin/node /opt/foundry/app/main.js --dataPath=/opt/foundry/data --noupnp
Restart=always
RestartSec=5
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
Restart=always, not on-failure: saving the Configuration tab writes options.json and shuts Foundry down cleanly, and systemd must bring it back. There is an --adminPassword flag, but leave it out: a unit file is world-readable and the argument would show in ps to every local user.
Set the admin access key before going public
Foundry is now listening on port 30000, which ufw blocks from outside. Reach it through your own SSH login and finish the first-run steps privately.
- From your workstation:
ssh -L 30000:127.0.0.1:30000 you@your-server, then browse tohttp://localhost:30000. - Paste your licence key and accept the EULA.
- On the Setup screen's Configuration tab, set the Administrator Password, the access key that guards the Setup screen. Foundry stores it encrypted in
Config/admin.txtunder the user data path. - Save Changes. Foundry exits and systemd restarts it; reconnect and confirm the Setup screen now asks for the key.
Each player account inside a world has its own access key as well. Set those before you send invitation links.
nginx in front, with TLS
TLS is what lets browsers grant camera and microphone to Foundry's audio/video integration, and it keeps access keys off the wire in clear. Install nginx and save the knowledge base's proxy block as /etc/nginx/sites-available/vtt.example.com, with an IPv6 listener (listen [::]:80, our addition) added:
server {
server_name vtt.example.com;
listen 80;
listen [::]:80;
client_max_body_size 300M;
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSockets
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://localhost:30000;
}
}
- Symlink the file into
/etc/nginx/sites-enabled/;sudo nginx -tmust report a valid syntax before you reload the nginx service. - Open the proxy ports for both address families with our ufw rule:
sudo ufw allow 'Nginx Full'(80 and 443). Port 30000 stays closed. - Point the domain's A and AAAA records at the server, then get a certificate with Certbot, which the knowledge base recommends. The commands are ours, in place of the article's hand-written SSL block:
sudo apt install certbot python3-certbot-nginx, thensudo certbot --nginx -d vtt.example.com --redirectadds the 443 listener and the HTTP redirect. - Stop Foundry, back up
/opt/foundry/data/Config/options.json, and set"hostname": "vtt.example.com","proxyPort": 443and"proxySSL": truein it, so invitation links carry the right address. Start Foundry again.
Updates and backups
Foundry never forces an update. Run live games on Stable releases only, and before moving to a new generation, such as V13 to V14, check that your game system and modules are marked compatible and take a full Snapshot from Manage Backups on the Setup screen. V13 and V14 need mutually exclusive Node versions: V13 does not run on Node 24, and V14 requires it. Moving a V13 server to V14 is therefore one sequence (ours, not the knowledge base's): take the Snapshot, sudo systemctl stop foundry, switch NodeSource to setup_24.x and install nodejs, move the old build aside with sudo mv /opt/foundry/app /opt/foundry/app-v13 && sudo -u foundry mkdir /opt/foundry/app, fetch the V14 Node.js build with a new timed URL (the same read -rp and wget lines as the install, into /opt/foundry/app/foundryvtt.zip), run sudo -u foundry unzip /opt/foundry/app/foundryvtt.zip -d /opt/foundry/app, and start the service. The app-v13 folder, the Snapshot and your archive are the way back, with Node returned to 22 first (sudo apt remove nodejs, NodeSource's setup_22.x, sudo apt install nodejs): V13 will not start on Node 24. Within one generation, sudo apt upgrade keeps Node current on its NodeSource major line.
Snapshots and package backups are written to the Backups folder inside the user data path, on the same disk, and they skip any assets stored outside the worlds, systems and modules folders. Keep a second copy elsewhere. The knowledge base's manual method for Linux is to stop the server and pack Data and Config with tar; where the archive is kept and how it leaves the machine are our additions:
sudo systemctl stop foundrysudo tar -czf /root/foundry-$(date +%F).tar.gz -C /opt/foundry/data Data Config(Config holds secured settings, so the archive stays in root's private home).sudo systemctl start foundry.sudo install -o $USER -m 600 /root/foundry-$(date +%F).tar.gz ~/hands a copy to your login, since/rootis mode 700. Fetch it from your computer withscp you@your-server:foundry-*.tar.gz ., then delete the copy in your home folder.
Never point a sync client such as Dropbox at a running user data folder: the knowledge base warns it can copy world databases mid-write and corrupt them.
When this is the wrong setup
If your group meets once a week and your home connection has the upload, the desktop app on your own PC with a forwarded port is the knowledge base's self-hosted option and costs nothing more. A dedicated server earns its keep when the world should stay up between sessions so players can edit characters, when your home connection is behind carrier-grade NAT, or when you want the box to yourself with root.
Questions
Do my players need their own Foundry licence?
No. The host buys one licence, and everyone else joins from a web browser with an invitation link and the access key for their user. The key belongs to whoever runs the server.
Which Node.js version does the current Foundry release need?
The requirements article says Node 22 for V13 and below and Node 24 for V14 and above. Foundry's knowledge base also notes that odd-numbered Node majors are not considered stable, so stay on an even line.
Where does Foundry keep worlds and settings on Linux?
In the user data folder, which the systemd unit above pins with --dataPath=/opt/foundry/data. Without that flag, the environment variable or a setting, Linux defaults to ~/.local/share/FoundryVTT. Inside it, Data holds worlds, systems, modules and uploads, and Config holds options.json.
Can I use the same licence key at home and on the server?
Only if one of them is private to you. The FAQ allows a second instance that no player can reach, for example a build server for preparing worlds. Two servers open to players at once need two keys.
Do I need HTTPS for a Foundry server?
For audio and video chat, yes: browsers only expose the camera and microphone on secure pages. It also protects the access keys players type. The nginx and Certbot steps above provide it without touching Foundry's own SSL options.