towbar.yml and recursively discovers .towbar/apps/**/*.app.yml
and .towbar/resources/**/*.resource.yml. Each file declares one entity.
Branch mappings are configured in Repository → Environments, not in YAML.
Download the root example and
app example. Editor schemas are available for
the root, apps, and
resources. Sync validates the effective configuration
after merging defaults and environment overrides.
Minimal app
towbar.yml
.towbar/apps/web.app.yml
main and staging to develop
when connecting the repository.
Stable identity
An entity’sid is stable across file moves and display-name changes. IDs must
be unique within the app or resource namespace in a repository. Each environment
gets a separate instance with its own deployment history, secrets, server,
volumes, and operations. A resource cannot change its type under the same ID.
The environments map explicitly selects where an entity exists. Common fields
are merged with that environment’s overrides: objects merge recursively and
arrays replace the entire common array. id, name, resource type, secrets,
and preview belong at entity level and cannot be overridden.
Removing an entity or its environment membership archives that instance after a
successful sync of the affected environment. A failed sync preserves the prior
configuration and secret values. Declaring a new environment in Git does not
connect it automatically; connect and map its branch in Towbar.
Automatic deployments
SetautoDeploy: true to deploy on changes from the environment’s mapped branch.
Apps can restrict relevant repository paths with autoDeploy.inputs:
Managed secrets
Declare required key names under top-levelsecrets.build, secrets.runtime,
secrets.preDeploy, and secrets.postDeploy in each entity file. Values are
entered in Towbar. New keys appear unset after sync, existing values and
references are preserved, and removed declarations delete their stored values
in the synced environment. Missing values block deployment, not sync.
An explicitly saved empty string counts as a value. Resources accept only
secrets.runtime; build and hook stages are rejected. See Secrets
for reference syntax and reveal controls.
Apps and Resources
Apps declare an explicitdeployment.type: dockerfile, static, image,
railpack, nixpacks, or buildpack. Compose projects use their own manifest
kind. Resource files declare type: image, postgres, mysql, mariadb,
mongodb, redis, dragonfly, keydb, or clickhouse. Image deployments
require an explicit non-latest tag or digest. See Deployment modes,
Resources, and Backups.
Private networks and operator access
Setcontainer.network to join a Docker network and container.networkAlias
for private discovery. Resource aliases default to their entity ID; use distinct
aliases or networks when environments share a server. Optional
access.sshTunnel.hostPort exposes a resource port on server loopback for SSH
tunnels. Alias and port conflicts are rejected during validation or deployment.
Preview deployments
Enable previews on a target environment intowbar.yml and opt an app in with
preview.enabled, preview.domain, and an optional preview.ttlHours. Same-repository
PRs targeting that environment’s mapped branch use the immutable PR head.
Preview secrets are isolated as preview:<environment> and never fall back to
persistent environment values. Resources do not create PR previews.
See Previews.
Domains and TLS
Set domains per environment so production and staging do not claim the same hostname. Domain ownership is checked across the workspace. See Domains and TLS.Field reference
Root fields
version: 2 and a nonempty environments map are required. Each environment can
set previews.enabled. Branch names, server settings, and entity directory
paths are not root configuration fields.
App fields
id, name, and environments identify the entity. The effective configuration
requires server, dockerfile, and container.port. It can also configure
context, health, domains, TLS, container resources, hooks, automatic deployment,
and vulnerability scanning.
Resource fields
id, name, type, and environments identify the entity. The effective
configuration requires a registered server IP and settings appropriate to its
type.
Backup destinations and schedules are supported for all eight managed engines.
Validate locally
Associate the matching JSON Schema with each file in your editor. Schemas check file structure; Towbar sync also checks merged configuration, server ownership, entity identity, and cross-entity conflicts at an immutable Git commit. Version 1 single-file manifests are not supported.Persistent app storage
Declare Docker-managed named volumes undercontainer.volumes in an app file:
RUN mkdir /app/uploads && chown node:node /app/uploads before
USER node. A new volume is initialized from the image directory once. Later
images never overwrite existing files. See examples/persistent-files in the
repository for a runnable upload example.
When adding storage to an already deployed app, explicitly choose where the
initial data comes from:
previous-container imports that directory from the previous container while
it is stopped, preserving file ownership and permissions. image initializes
from the image instead. Without an explicit choice, attaching a new volume to
an existing app is blocked. The setting only applies when initializing a new
volume; existing volumes are reused. New PR previews initialize from their own image even when the base app declares
previous-container; production files are never copied to previews.
An interrupted import never becomes a ready volume. A retry discards only the
verified, uncommitted initializer and restarts the import from the previous
container. Unrecognized volumes are retained and block initialization. A missing previously initialized volume blocks deployment
rather than silently creating empty storage.
For apps with persistent storage, Towbar builds the candidate first, stops the
previous container, initializes storage, runs pre-deploy hooks, and starts the
candidate. This prevents concurrent writers and creates a brief interruption.
Pre- and post-deploy hooks see the same volumes. If candidate startup or its
health check fails, Towbar attempts to restart the previous container. Data
changes made by hooks or the candidate are retained; app rollback is not a data
restore. The self-managed Towbar worker cannot use this stop/start strategy.
The app’s Storage page lists configured and retained volumes. Mount status
comes from the latest server check, which also detects missing or incorrect
mounts. Removing a declaration, expiring a preview, or archiving an app does not
remove its volumes. Explicit, confirmed server orphan cleanup can delete volumes
belonging to removed apps; ordinary deployment cleanup does not delete data.
Storage is local to its server. Repository sync and deployment execution block
reassigning an app with storage history to another server. Cross-server transfer
requires a separate, deliberate migration; Towbar does not copy files between
servers automatically. Local persistence does not protect against disk or server
loss. Back up persistent application files with storage or infrastructure tooling
appropriate for the server; Towbar does not back up or restore app volumes.
Scheduled application jobs
Apps accept an optionaljobs list with at most 20 unique names. Each job has
name, command, and schedule.cron; optional fields are description,
schedule.timezone (only UTC), enabled (default true), and timeoutSeconds
(default 300, range 5–3600). Names contain lowercase letters, digits and hyphens,
start with a letter, and are limited to 63 characters.
Jobs inherit the deployed app image, runtime secret values, container resources,
network and persistent volumes. The manifest contains no credential values.
Environment overrides replace the entire jobs list. See
Scheduled jobs for timing, concurrency, interruption,
preview and manual-run behavior.
Log forwarding
Apps and resources accept alogDrains list of team integration names:
newrelic, axiom, betterstack, datadog, otlp, and loki. Environment
overrides replace the list; use [] to disable it for an environment. Credentials
stay in Towbar. Forwarding changes take effect after deployment. See
Log forwarding for provider setup and delivery
limits.