Skip to content

Infraspec Reference

Complete field reference for infraspec.yaml.

Top-Level Fields

FieldTypeRequiredDescription
namestringyesApp identifier (used as Nomad job ID, Consul service prefix)
deployboolnoSet false to disable deploys for this app
repoRepoSpecnoGit repository configuration
buildBuildSpecnoDocker build configuration
processesmap[string]ProcessyesNamed process definitions
servicesstring[]noLegacy service list (v1 compat)
secretsstring[]noExpected secret key names
migrationsstringnoPath to migrations directory (relative to repo root)
envmap[string]stringnoStatic environment variables
infrastructureInfrastructurenoBacking service declarations
endpointsEndpoint[]noExternal URL mappings
volumesVolumeSpec[]noHost volume mounts
snapshotsSnapshotPolicynoSnapshot retention defaults
deployPolicyDeployPolicynoDeploy safety policy such as auto-rollback

Process

Each key in the processes map is the process name. The process type is inferred from which fields are set.

FieldTypeDefaultDescription
portintListen port (makes this a service process)
commandstringOverride the Docker CMD
schedulestringCron expression (makes this a periodic batch job)
functionFunctionSpecFunction configuration (makes this a batch job)
healthHealthSpecHTTP health check (only for processes with a port)
metricsMetricsSpecPrometheus scrape endpoint for this process
scalingScalingInstance count and autoscaling
drainDrainGraceful shutdown configuration
resourcesResourcescpu: 100, memory: 128CPU (MHz) and memory (MB) limits
tuningTuningPolicyAdvisory resource tuning policy and signal declarations
canaryCanaryConfigCanary allocation count and evaluation window

Health

FieldTypeDefaultDescription
pathstringHTTP health check path (e.g. /health)
intervalstring10sCheck interval (Go duration)
timeoutstring5sCheck timeout (Go duration)

MetricsSpec

FieldTypeDefaultDescription
enabledboolfalseRegister this process as a Prometheus scrape target
pathstring/metricsMetrics path
portintprocess portInternal metrics port when separate from the main process port

Scaling

FieldTypeDefaultDescription
minint1Minimum instance count
maxintMaximum instance count (for autoscaling)
per_regionintInstances per region
autoAutoScaleAutoscaling configuration

AutoScale

FieldTypeDescription
metricstringScaling metric: cpu, memory, kafka_lag, custom
targetintTarget value for the metric
topicstringKafka topic (required when metric is kafka_lag)

Drain

FieldTypeDefaultDescription
signalstringSIGTERMSignal sent to the process on shutdown
timeoutstringTime to wait after signal before force-killing

Resources

FieldTypeDefaultDescription
cpuint100CPU allocation in MHz
memoryint128Memory allocation in MB

TuningPolicy

tuning declares how Norn should interpret resource signals for a process. The first implementation is advisory: norn tune and /api/tuning/recommendations report current signals and recommended resources or scaling changes, but they do not mutate Nomad jobs.

yaml
processes:
  web:
    resources:
      cpu: 25
      memory: 256
    tuning:
      mode: advisory
      cooldown: 6h
      profiles:
        quiet:
          cpu: 25
          memory: 256
          scale: 1
        normal:
          cpu: 50
          memory: 512
          scale: 1
      limits:
        min:
          cpu: 25
          memory: 128
          scale: 1
        max:
          cpu: 500
          memory: 2048
          scale: 3
      signals:
        - name: live-rss
          source: nomad
          metric: memory_rss
          aggregate: current
        - name: memory-p95
          source: prometheus
          metric: container_memory_working_set_bytes
          window: 24h
          aggregate: p95
FieldTypeDefaultDescription
modestringadvisoryadvisory reports recommendations; auto is reserved for future guarded application
cooldowndurationMinimum interval between automated changes when auto mode is implemented
profilesmap[string]TuningProfileNamed target CPU, memory, and scale profiles such as quiet or busy
limitsTuningLimitsMinimum and maximum recommendation bounds
signalsTuningSignal[]built-in Nomad live signalsSignal declarations used to explain recommendations

TuningProfile

FieldTypeDescription
cpuintCPU allocation in MHz
memoryintMemory allocation in MB
scaleintDesired instance count

TuningLimits

FieldTypeDescription
minTuningProfileLower bound for recommended CPU, memory, and scale
maxTuningProfileUpper bound for recommended CPU, memory, and scale

TuningSignal

FieldTypeDescription
namestringHuman-readable signal name
sourcestringnomad, prometheus, or app
metricstringSignal metric, such as memory_rss, memory_max, or cpu_percent
windowdurationLookback window for historical sources
aggregatestringAggregation such as current, max, or p95

CanaryConfig

FieldTypeDefaultDescription
countintNumber of canary allocations to start before full promotion
evaluateAfterstringDuration to wait before evaluating canary health, such as 2m

When a process declares canary settings, Norn submits the Nomad deployment with canary allocations, waits through the normal health gate, then evaluates allocation health after evaluateAfter. Operators can inspect and promote with norn canary <app> and norn promote <app>.

FunctionSpec

FieldTypeDefaultDescription
timeoutstringMaximum execution time (Go duration)
memoryintMemory override in MB (takes precedence over resources.memory)

Repo

FieldTypeDefaultDescription
urlstringGit clone URL
branchstringmainDefault branch
autoDeployboolfalseAuto-deploy on webhook push
repoWebstringWeb URL for the repo (used in UI links)

Build

FieldTypeDefaultDescription
dockerfilestringDockerfilePath to Dockerfile
teststringTest command (runs before deploy, fails pipeline on error)

Infrastructure

FieldTypeDescription
postgres.databasestringDatabase name for snapshots, migrations, and DATABASE_URL
redis.namespacestringRedis key namespace
kafka.topicsstring[]Kafka topics to declare
nats.streamsstring[]NATS JetStream stream names
objectStorage.providerstringS3-compatible provider hint; defaults to garage
objectStorage.bucketsObjectStorageBucket[]Buckets to provision and expose to the app

ObjectStorageBucket

FieldTypeDefaultDescription
namestringDNS-compatible bucket name
accessstringreadWritereadOnly, readWrite, or owner
publicboolfalseReserved for future public exposure policy
prefixstringOptional object key prefix exposed as S3_PREFIX...
envstringderived from bucket nameEnv alias for S3_BUCKET_<ENV>

Endpoints

FieldTypeDescription
urlstringExternal hostname (maps to cloudflared ingress rule)
regionstringOptional region hint

Volumes

FieldTypeDefaultDescription
namestringNomad host volume name
mountstringMount path inside the container
readOnlyboolfalseMount as read-only

SnapshotPolicy

FieldTypeDefaultDescription
keepint3Newest local snapshots to keep when retention runs without --keep
preRestoreboolfalseCreate a safety snapshot before restore when the API or CLI does not override the restore request
retentionEnabledboolfalseReserved flag for scheduled retention automation
exportBucketstringS3-compatible bucket for norn snapshots export/remote/import

DeployPolicy

FieldTypeDefaultDescription
autoRollbackbooltrueQueue rollback to the last successful deployment when the deploy health gate fails

Because autoRollback defaults to enabled, omit deployPolicy for normal apps. Set autoRollback: false when a failed health gate should stop for manual operator review.

Defaults Summary

SettingDefault Value
resources.cpu100 MHz
resources.memory128 MB
health.interval10s
health.timeout5s
scaling.min1
repo.branchmain
snapshots.keep3
deployPolicy.autoRollbacktrue

Full Example

A real-world infraspec for an app with a web process, background worker, cron job, and database:

yaml
name: signal-sideband

repo:
  url: git@github.com:antiartificial/signal-sideband.git
  branch: master
  autoDeploy: true
  repoWeb: https://github.com/antiartificial/signal-sideband

build:
  dockerfile: Dockerfile
  test: go test ./...

processes:
  web:
    port: 8080
    command: ./signal-sideband
    health:
      path: /health
    metrics:
      enabled: true
      path: /metrics
    scaling:
      min: 1
    resources:
      cpu: 200
      memory: 256
    canary:
      count: 1
      evaluateAfter: 2m
  poller:
    command: ./signal-sideband --mode=poller
    resources:
      cpu: 100
      memory: 128
  digest:
    schedule: "0 8 * * *"
    command: ./signal-sideband --mode=digest

secrets:
  - DATABASE_URL
  - OPENAI_API_KEY
  - FILTER_GROUP_ID

migrations: ./migrations

env:
  LOG_LEVEL: info
  TZ: America/New_York

infrastructure:
  postgres:
    database: signal_sideband
  objectStorage:
    provider: garage
    buckets:
      - name: signal-sideband-attachments
        access: readWrite
        env: ATTACHMENTS

snapshots:
  keep: 5
  exportBucket: signal-sideband-snapshots

deployPolicy:
  autoRollback: true

endpoints:
  - url: signal.example.com

volumes:
  - name: signal-data
    mount: /var/lib/signal-cli