The settings file, tanzahost.json
Every field of tanzahost.json - language, version, commands, system packages, folders to keep, the health address and PHP's settings - with examples.
Updated 17 Oct 20263 min read
Most apps need no settings file: we read your code and work out how to build and start it. When you want something else, add tanzahost.json to the top folder of your code. It's read on every build, and anything you set in the app's Build and run settings in the dashboard wins over it.
An example
Asha's Laravel shop pins PHP 8.4, adds two extensions, raises the upload size, and gets visitors only once /up answers:
{
"language": "php",
"version": "8.4",
"health": "/up",
"release": "php artisan migrate --force",
"php": {
"extensions": ["intl", "gd"],
"ini": {
"upload_max_filesize": "64M",
"post_max_size": "64M"
}
}
}Every field
| Field | What it sets | Example |
|---|---|---|
language | The language, when we shouldn't guess: php, nodejs, python, go, ruby, java, rust or static | "nodejs" |
version | An exact version we offer | "22" |
root | The folder inside your repository that holds the app | "apps/api" |
install | The install command, instead of ours | "npm ci" |
build | The build command, instead of ours | "npm run build:prod" |
start | How the web process starts | "npm run serve" |
release | The command run before going live | "python manage.py migrate" |
health | The path a new version must answer before it gets visitors | "/up" |
permanent | Folders of your code kept between deploys | ["storage"] |
packages | System packages to install, up to 30 | ["ffmpeg"] |
php | PHP's extensions and ini settings | See below |
The file must be valid JSON, at most 64 KB. A field we don't know is an error: the build stops and says which one, so a typo never goes unnoticed.
Language and version
The version must be one we offer, or the build stops and lists the ones we do. What we offer today: PHP 8.0 to 8.5, Node.js 22 and 24, Python 3.10 to 3.14, Go 1.26 and 1.27, Ruby 3.3, 3.4 and 4.0, Java 21 and 25, and Rust 1.98. Without a version, we use what your code asks for (like require.php in composer.json or .nvmrc for Node.js).
Commands
install, build and start replace ours; leave one out to keep ours. Each may be up to 4,000 characters. release must be on one line: join several commands with &&.
The web process must listen on the port in PORT, which is 8080:
{
"start": "gunicorn shop.wsgi:application --bind 0.0.0.0:${PORT} --workers 2"
}Permanent folders
Each deploy starts with fresh files from your code, which can't be changed while the app runs. The folders in permanent are kept instead: the first deploy fills them from your code, and later deploys keep what's there. Up to 10 folders, each a folder of your code like storage or public/uploads.
For Laravel, storage is permanent without asking, and bootstrap/cache is a small scratch folder made fresh at each start. Setting permanent replaces the list, so a Laravel app that adds a folder keeps storage in it:
{
"permanent": ["storage", "public/uploads"]
}Your app's home folder is kept too.
System packages
packages installs system packages by name before your build, like ffmpeg or imagemagick. Up to 30, with names of lowercase letters, digits and +.-.
PHP settings
php.extensions adds extensions from this list: bcmath, bz2, calendar, exif, gd, gmp, imagick, intl, mysqli, opcache, pcntl, pdo_mysql, pdo_pgsql, pgsql, redis, soap, sockets, xsl, zip. The common ones (mbstring, curl, openssl, pdo and others) are always there.
php.ini changes these settings, and no others:
| Setting | Allowed |
|---|---|
upload_max_filesize, post_max_size | A size up to 2G, like 64M |
memory_limit | A size up to your app's memory limit |
max_execution_time, max_input_time | 0 to 600 seconds |
max_input_vars | 0 to 100000 |
display_errors, opcache.enable | On or Off |
date.timezone | A time zone, like Europe/London or UTC |
session.gc_maxlifetime | Up to 2592000 seconds (30 days) |
For an app that isn't PHP, the php field is ignored, and the build says so.
An app in a folder
With root, we read your app from that folder of the repository. A tanzahost.json inside that folder counts too, and wins over the one at the top.
{
"root": "apps/api",
"language": "nodejs"
}Where each setting comes from
What we find in your code.
Then
tanzahost.json.Then Build and run in the dashboard. An empty field there uses the file, or what we found.