Skip to main content

The one file, explained

This page is every knob pagifier.toml has. You'll never need most of them — templates handle the boring parts — but when you do, here they are.

Two kinds of file exist. The root file lists deployable projects (nothing is ever auto-discovered — if it's not on the list, it doesn't deploy); each project file completely defines one deployment.

TOML is the primary format (pagifier.toml); YAML (pagifier.yaml) is fully supported with identical keys — Pagifier detects the format from content. Get editor autocomplete with the published JSON Schema:

#:schema https://pagifier.company.com/v1/schema/pagifier.json
# yaml-language-server: $schema=https://pagifier.company.com/v1/schema/pagifier.json

Root file

pagifier.toml
version = 1

projects = [
"frontend/pagifier.toml",
"admin/pagifier.toml",
"api/pagifier.toml",
]

Project file

KeyRequiredNotes
versionyesMust be 1.
nameyesLowercase DNS label; becomes the workload name.
environmentyesdev qa uat staging prod preview. Selects the environment profile. preview apps are ephemeral: hostname auto-generated, garbage-collected after a TTL.
runtimeyes*static, node, python, or go. *May be supplied by the template.
templatenoPlatform template, optionally pinned: react-static@2.
hanotrue adds minimum replicas, anti-affinity, topology spread, a PodDisruptionBudget, and zero-downtime rollout.
portyes*Container port. Never guessed. *Node apps may use runtimeConfig.port instead.
autoRollbacknotrue reverts automatically when a rollout stalls. Usually set by environment profiles.
build.enablednofalse packages the uploaded artifact as-is.
build.workDir, build.commandswith buildCommands run verbatim in the toolchain image. Never inferred.
artifact.directorystaticDirectory shipped into the image — nothing else leaves the build. Optional for server runtimes (e.g. ship only a compiled Go binary).
server.typenonginx (the only static server); defaulted when omitted.
runtimeConfig.commandserver runtimesMandatory start command for node/python/go. package.json, requirements.txt, and go.mod are never read.
resourcesnocpu, memory (requests), cpuLimit, memoryLimit. Memory limit defaults to the request.
ingressnohost (required if enabled), path, className, tls (default on), annotations. mode: gateway renders a Gateway API HTTPRoute; the parent gateway: {name, namespace, sectionName} usually comes from the environment profile. Hosts are first-come-first-owned: the exact (host, path) pair belongs to the first application that deploys it — any other app (or tenant) gets a 409 naming the owner. Different paths on one host coexist, which is how several apps share www.abc.com (path-based ingress).
autoscalingnoenabled, minReplicas, maxReplicas, cpu, memory (target %). Declaring triggers (KEDA scalers) renders a ScaledObject instead of an HPA.
envnoPlain environment variables.
secretsnoprovider (kubernetes aws gcp azure vault external-secrets), keys mapping ENV_VAR → remote key, storeRef, refreshInterval. See the secrets guide.
secretFilesnoFile name → {source, mountPath}.
headers.corsnoenabled, allowOrigins, allowMethods, allowHeaders, maxAge.
headers.customnoExtra response headers.
authenticationnobasic (htpasswd secret, enforced in nginx); oidc / jwt / oauth2-proxy enforced at the ingress via platform middleware — projects cannot override those annotations.
compressionnogzip (default on), brotli.
security.profilenobasic recommended strict internal pci — expands to response headers from the platform library.
cache.static, cache.htmlnomaxAge in compact form: 365d, 12h, 5m, 30s.
routesnoPath-based proxying: {path, service, port, authentication}.
healthChecknopath plus probe timings.
deploynoDeployment strategy — see deployment strategies.
dnsnoTunes the external-dns record for the app's host: ttl (seconds) and target (e.g. a CDN distribution hostname). The record itself is created automatically from the rendered Ingress/HTTPRoute.
cdnnoFronts the app with the platform's CDN integration: cdn = "cloudfront" resolves cdn/cloudfront.yaml from the config bucket into edge annotations (platform-owned — they override project annotations). Requires ingress.

Shorthands

Common cases have compact spellings. They are pure syntax — each expands to the canonical object form before template merging, so a shorthand still deep-merges with whatever the templates set:

Shorthand (TOML)Expands to
ingress = "app.company.com"[ingress] with host
build = ["npm ci", "npm run build"][build] with enabled = true + commands
build = false[build] with enabled = false
artifact = "dist"[artifact] with directory
runtimeConfig = "node dist/main.js"[runtimeConfig] with command
security = "strict"[security] with profile
healthCheck = "/health"[healthCheck] with path
authentication = "basic"[authentication] enabled with type
compression = false[compression] with gzip = false
cache = {static = "365d", html = "5m"}per-rule maxAge tables
cdn = "cloudfront"[cdn] with provider
deploy = "canary"[deploy] with strategy
analysis = ["error-rate"]named gate references

The YAML spellings are the same shapes (ingress: app.company.com, build: [npm ci, npm run build], deploy: canary, …).

Merge order

platform defaults → runtime template → application template
→ environment profile → your pagifier.yaml

Your file always wins. Maps merge deep, lists replace whole, null deletes a key inherited from a template. Unknown keys are rejected — with a suggestion when it looks like a typo (unknown field "artefact" — did you mean "artifact"?).

To see exactly what the merge produced for a running release:

curl -H "Authorization: Bearer $TOKEN" \
https://pagifier.company.com/v1/applications/my-app/environments/prod/releases/RELEASE_ID/config

Validating with CUE

Prefer CUE over JSON Schema? The same contract is published as a CUE schema, with all shorthand forms expressed as disjunctions:

curl -sO https://pagifier.company.com/v1/schema/pagifier.cue

cue vet -d '#Project' pagifier.cue frontend/pagifier.yaml # project files
cue vet -d '#Root' pagifier.cue pagifier.yaml # root manifests

Both formats vet — cue vet reads the same files Pagifier does. It catches structural problems offline — unknown fields, enum violations, port ranges, non-ascending canary steps — before anything is uploaded. The server's POST /v1/validate remains the source of truth: it additionally resolves templates and enforces cross-field rules (for example, node requires a runtime command), so run both in CI: cue vet on every commit, /v1/validate on pull requests.

Things Pagifier will never do (pinky promise)

Detect your framework · snoop in package.json, requirements.txt, or go.mod · guess your port · guess your build commands · read a Dockerfile (you don't have one, that's the point) · deploy anything you didn't explicitly list.