Configuration
One YAML file defines the deployment graph.
TurboCI stores the deployment model in `.turboci/config.yaml`: provider selection, service shapes, runtime hooks, health checks, and balancer relationships all live in the same file.
1 config
holds the provider, service, runtime, and rollout model
Instances x clusters
determines total fleet size and rollout boundaries
- deployment_name: my_deployment
provider: hetzner
location: ash
description: My first deployment
services:
web:
instances: 2
clusters: 1
server_type: cpx21
dir_mappings:
- src: .
dst: /app
run:
start:
work_dir: /app
cmds:
- npm startDeployment fields
Top-level deployment properties
These fields shape the cloud target and define how a deployment relates to other deployments.
deployment_name
Unique identifier for the deployment. Use lowercase letters and underscores so the deployment can be referenced consistently by the CLI.
deployment_name: web_productionprovider
The target cloud provider. TurboCI accepts `hetzner`, `aws`, `gcp`, and `azure` and resolves the matching environment variables automatically.
provider: hetznerlocation
Provider-specific region or location. Use `turboci spec` to list the supported values before choosing one.
location: ashavailability_zone
For providers that support availability zones (e.g., AWS), specify the zone within the region.
availability_zone: us-east-1adescription
Optional human-readable context for operators who need to distinguish deployments quickly.
description: Production deployment on Hetznerduplicate_deployment_name
Clone the full configuration of another deployment and override only the fields that differ in the new target.
duplicate_deployment_name: web_productionrelay_server_options
Options for the relay server provisioned for this deployment. Use `server_type` to control the relay machine size.
relay_server_options:
server_type: cpx21pre_deployment
Commands to run on your local machine before the deployment starts — not on the remote server. Useful for local builds that must complete before code is synced.
pre_deployment:
work_dir: ./frontend
cmds:
- bun install
- bun run buildenv / env_file
Environment variables applied to all services in this deployment. Use `env` for inline key-value pairs or `env_file` to load from a file.
env:
NODE_ENV: production
DATABASE_URL: postgres://...
# or
env_file: ./secrets/prod.envService fields
Per-service controls
Each service inside a deployment can tune image choice, instance sizing, rollout shape, and inheritance.
type
Service type. Use `default`, `load_balancer`, or `docker`. If omitted, TurboCI treats the service as a standard VPS workload.
type: load_balanceros
Operating system image. On Hetzner this defaults to `debian_12`, with provider-appropriate equivalents on other clouds.
os: debian_12server_type
Instance size as defined by the provider. Use `turboci spec` to inspect the valid shapes.
server_type: cpx21enable_public_ip
Public IP addresses are disabled by default except on load balancer services. Set this explicitly when a service must be exposed.
enable_public_ip: trueinstances
The number of servers created inside each cluster.
instances: 3clusters
The number of rollout groups. Total servers equals `instances * clusters`, and clusters update one at a time.
clusters: 2init
Commands to run once on first initialization of a server, before any other run commands. Useful for one-time setup like seeding a database.
init:
- cp /setup/init.sh /usr/local/bin/init
- chmod +x /usr/local/bin/init
- /initlogs
An array of commands used to stream or collect logs from the service in the admin panel. Each entry is either a plain string or an object with a `cmd` key.
logs:
- journalctl -u myapp -f
- cmd: tail -f /var/log/myapp/error.logduplicate_service_name
Clone another service definition and override only the settings that differ for the new service.
duplicate_service_name: web_prodRuntime assets
How files, dependencies, and commands are modeled
Directory mappings
Map local files or directories onto the server filesystem. The files sync to the relay first, then out to the service servers.
dir_mappings:
- src: .
dst: /app
- src: ./secrets/prod.env
dst: /app/.env
ignore_file: .gitignore
use_gitignore: true
relay_ignore:
- node_modules
- .gitDependencies
Install packages with the underlying OS package manager or through TurboCI's cross-platform dependency helpers.
dependencies:
apt:
- rsync
- neofetch
turboci:
- docker
- bun
- nodeRun commands
Attach preflight, start, and postflight command groups to each service. TurboCI executes them in order during the rollout.
run:
preflight:
work_dir: /app
cmds:
- bun add -g pm2
- bun install
- bunx next build
start:
work_dir: /app
cmds:
- pm2 start "bunx next start"
postflight:
cmds:
- pm2 listHealth checks
Gate promotion on a passing command
TurboCI runs the health check up to five times with five-second delays. If the expected string never appears in the output, the rollout stops.
healthcheck:
cmd: curl http://localhost:3000/api/healthcheck
test: Server RunningThe cmd runs on the target server, and test must appear in the command output for the cluster to be promoted.
Load balancing
Attach a reverse proxy with target services and SSL
Use `type: load_balancer` to provision an NGINX reverse proxy and connect it to upstream services.
services:
web:
instances: 2
clusters: 2
load_balancer:
type: load_balancer
ssl:
email: admin@example.com
target_services:
- service_name: web
port: 3000
domains:
- example.com
- www.example.com
- service_name: web_dev
port: 3000
domains:
- dev.example.comDomains must already point at the balancer's public IP before running turboci up so Certbot can provision and renew the certificates.
Complete example
A production deployment with a load balancer and a cloud duplicate
- deployment_name: test
provider: hetzner
location: ash
description: Production deployment on Hetzner
services:
web:
instances: 2
clusters: 2
server_type: cpx21
dir_mappings:
- src: .
dst: /app
- src: ./secrets/prod.env
dst: /app/.env
dependencies:
apt:
- rsync
turboci:
- bun
- node
run:
preflight:
work_dir: /app
cmds:
- bun add -g pm2
- pm2 kill
- bun install
- bunx next build
start:
work_dir: /app
cmds:
- pm2 start "bunx next start"
postflight:
cmds:
- pm2 list
healthcheck:
cmd: curl http://localhost:3000/api/healthcheck
test: Server Running
logs:
- pm2 logs web
load_balancer:
type: load_balancer
target_services:
- service_name: web
port: 3000
- deployment_name: test_aws
provider: aws
location: us-east-1
duplicate_deployment_name: testTypeScript config
Write configuration in TypeScript instead of YAML
As an alternative to `config.yaml`, you can write `config.ts` for type safety, code reuse, and dynamic generation. Import the `TCIConfig` type from `@moduletrace/turboci`.
Array format
Simple deployment list
The simplest format — a plain array of deployment objects exported as the default export.
import type { TCIConfig } from "@moduletrace/turboci";
const config: TCIConfig = [
{
deployment_name: "my_app",
provider: "hetzner",
location: "ash",
services: {
web: {
instances: 2,
clusters: 2,
server_type: "cpx21",
dir_mappings: [{ src: ".", dst: "/app" }],
dependencies: { apt: ["rsync"], turboci: ["bun"] },
run: {
preflight: { work_dir: "/app", cmds: ["bun install", "bun run build"] },
start: { work_dir: "/app", cmds: ['pm2 start "bunx next start"'] },
postflight: { cmds: ["pm2 list"] },
},
healthcheck: {
cmd: "curl http://localhost:3000/api/healthcheck",
test: "Server Running",
},
},
},
},
];
export default config;Object format
With global environment variables
Use the object format to define global environment strings that apply across all deployments.
import type { TCIConfig } from "@moduletrace/turboci";
const config: TCIConfig = {
envs: ["NODE_ENV=production", "REGION=us-east"],
deployments: [
{
deployment_name: "my_app",
provider: "hetzner",
location: "ash",
services: {
web: {
instances: 2,
server_type: "cpx21",
dir_mappings: [{ src: ".", dst: "/app" }],
run: {
start: { work_dir: "/app", cmds: ['pm2 start "bun server.ts"'] },
},
},
},
},
],
};
export default config;Next step
Put the configuration behind the CLI
Once the deployment file is modeled, the CLI becomes the control surface for bootstrapping, pushing, targeting, and tearing it down.
Continue to CLI commands