Docker Compose is the simplest way to run a single Foundry Virtual Tabletop
instance on one host. A compose.yaml file captures the image, configuration,
storage, and ports in one place, so the server is easy to start, stop, and
reproduce.
This guide covers a complete single-host deployment. For the full catalog of settings, see the environment variables and secrets sections of the project README.
- Docker Engine with the Compose plugin (the
docker composecommand). Any runtime that understands Compose files works too; Podman users should read the Podman guide. - A foundryvtt.com account with a purchased software license.
Note
These examples use the docker command line, which also drives other
drop-in backends such as Colima or Rancher Desktop. Use whichever you
prefer; the commands are the same.
-
Create a
compose.yamlfile. Supply your credentials as the values of the environment variables:--- services: foundry: image: ghcr.io/felddy/foundryvtt:14 hostname: my_foundry_host environment: - FOUNDRY_USERNAME=<your_username> - FOUNDRY_PASSWORD=<your_password> - FOUNDRY_ADMIN_KEY=<your_admin_key> - FOUNDRY_TELEMETRY=true volumes: - type: bind source: ./data target: /data ports: - target: 30000 published: 30000 protocol: tcp restart: unless-stopped
-
Start the server and detach:
docker compose up --detach -
Open http://localhost:30000. You should be prompted to accept the license agreement, then for the admin access key you set in
FOUNDRY_ADMIN_KEY.
Important
Always set a stable hostname. Foundry binds its software license to the
container hostname. Without one, the runtime assigns a random container ID on
each start and license verification fails after every restart.
Configuration options are supplied as environment variables. Each time the
container starts, it regenerates Foundry's configuration files from those
variables. This means changes made in the in-application configuration GUI do
not persist across restarts — manage configuration through compose.yaml
instead. To preserve hand-edited configuration files, set
CONTAINER_PRESERVE_CONFIG to true.
Sensitive values can be passed as a secret file instead of environment
variables. The file may have any name, but it must be mounted to config.json
inside the container. See the secrets reference for every supported key.
-
Create a
secrets.jsonfile with the values you want to set:{ "foundry_admin_key": "<your_admin_key>", "foundry_password": "<your_password>", "foundry_username": "<your_username>" } -
Reference it from
compose.yamland drop the matching environment variables:--- secrets: config_json: file: secrets.json services: foundry: image: ghcr.io/felddy/foundryvtt:14 hostname: my_foundry_host environment: - FOUNDRY_TELEMETRY=true volumes: - type: bind source: ./data target: /data ports: - target: 30000 published: 30000 protocol: tcp secrets: - source: config_json target: config.json restart: unless-stopped
The in-application "Update Software" tab is disabled in this image. To move to a newer release, pull a fresh image and recreate the container:
docker compose pull
docker compose up --detachBecause the image is pinned to the major tag :14, pull
fetches the newest release that is compatible with your existing data. To move
to a new major version, change the tag in compose.yaml first, then pull.
- Add automatic HTTPS with the Caddy reverse proxy recipe.
- Publish the server without port forwarding using the Cloudflare Tunnel recipe.