Skip to content

Deploy spec reference

The deploy spec is the declarative description of a workload cornus runs. It is the YAML (or JSON) document you pass to cornus deploy -f. It is applied imperatively: one spec goes in, and the selected deploy backend converges actual state to it (creating or recreating the workload).

A Compose file or devcontainer is translated into this same spec internally, so every field here is also reachable through cornus compose. The six backends — dockerhost (default), podman, containerd, bare, incus, and kubernetes — sit behind one interface and honor the same spec, but not every field maps onto every backend. Where the source records a per-backend behavior, it is called out in the field's description. The incus backend maps the narrowest subset (no client-local mounts, healthchecks, user networks, or command-only overrides; workingDir and user map only in their absolute and numeric forms); it warns for every field it cannot map rather than dropping one silently, and deploy backends lists the gaps in one place.

The canonical source of truth is pkg/.cornus/v1/deploy.go.

Example

A reasonably complete spec, showing the common fields plus a few nested blocks:

yaml
name: web
image: localhost:5000/web@sha256:1c2d...   # digest-pinned is ideal
replicas: 2
restart: unless-stopped

command: ["--port", "8080"]                 # args to the image ENTRYPOINT
env:
  LOG_LEVEL: info
  DATABASE_URL: postgres://db:5432/app

ports:
  - host: 8080
    container: 80
  - host: 127.0.0.1:5432                     # see hostIP below
    hostIP: 127.0.0.1
    container: 5432

mounts:
  - source: /srv/data
    target: /data
    readOnly: true

volumes:
  - name: web_cache                          # named => shared/persistent
    target: /var/cache
    size: 2Gi

networks:
  - name: myproj_frontend
    aliases: [web, frontend]

resources:
  cpuLimit: 0.5                              # half a core
  memoryLimit: 268435456                     # 256 MiB, in bytes
  reservedMemory: 134217728                  # 128 MiB floor

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost/healthz"]
  interval: 30s
  timeout: 5s
  retries: 3

labels:
  app.kubernetes.io/part-of: myproj

Top-level fields (DeploySpec)

FieldTypeRequiredDefaultDescription
namestringyesUniquely identifies the deployment; managed resources are labeled with it for idempotent apply/delete.
imagestringyesImage reference to run, ideally digest-pinned.
command[]stringnoimage CMDOverrides the image's default command (Docker CMD): the arguments to the image ENTRYPOINT, which stays in effect. On kubernetes it is carried in the container's Args so the image entrypoint is preserved. On incus, a command set without entrypoint cannot be mapped and is warned about — set entrypoint too.
entrypoint[]stringnoimage ENTRYPOINTOverrides the image entrypoint (Docker ENTRYPOINT / Kubernetes container command). When set, command supplies its arguments; empty keeps the image default. On incus it becomes the instance's oci.entrypoint, which replaces the image argv as a whole.
envmap[string]stringnoEnvironment variables, applied as KEY=VALUE from the map.
ports[]PortMappingnoMaps host ports to container ports.
mounts[]MountnoBind host paths into the container.
volumes[]VolumeSpecnoManaged (non-bind) volumes the backend provisions storage for.
networks[]NetworkAttachmentnoUser-defined networks this workload joins (Compose networks:). Empty means default connectivity only.
proxyProxySpecnoRequests a userspace enforcing egress proxy. kubernetes only (dockerhost gets isolation from libnetwork and ignores it).
dnsDNSSpecnoRequests a per-pod caretaker DNS resolver. kubernetes only.
hubHubSpecnoJoins the workload to the server's workload-to-workload overlay. kubernetes only. See the workload hub.
dockerDockerSpecnoExposes a Docker Engine API endpoint to the workload. kubernetes only. Requires CORNUS_CLIENT_TOKEN_SECRET on the server.
credentialsCredentialSpecnoBrokers short-lived client-minted credentials into the workload. Realized on kubernetes only; every host backend currently rejects them. Compose services set it with x-cornus-credentials:. See Credentials.
restartstringnounless-stoppedRestart policy: no, always, on-failure, or unless-stopped.
restartMaxAttemptsintno0 (backend default, unlimited)Caps restart attempts for an on-failure policy. dockerhost only (kubernetes and containerd cannot bound the count and ignore it).
replicasintnobackend defaultDesired number of instances. Honored by every backend; on host backends published host ports go to replica 0 only.
privilegedboolnofalseRuns with full privileges (Docker --privileged / Kubernetes securityContext.privileged). Opt-in; see Security and authentication for the default-deny posture.
healthcheckHealthchecknoContainer health probe.
resourcesResourcesnoCPU/memory limits and reservations.
updateConfigUpdateConfignoRolling-update strategy. kubernetes only (host backends recreate a single instance and ignore it).
userstringnoimage defaultUser (and optional group) the process runs as: uid, uid:gid, user, or user:group. kubernetes maps a numeric uid[:gid] only and cannot express a username; incus has the same limit (oci.uid/oci.gid) and refuses uid:groupname whole rather than dropping the group.
workingDirstringnoimage defaultContainer working directory (compose working_dir). On incus it maps only when absolute (oci.cwd); a relative path is warned about.
hostnamestringnobackend defaultContainer hostname (compose hostname).
labelsmap[string]stringnoUser metadata. On kubernetes they become pod-template annotations (not labels); cornus's own management labels always win on a key clash.
originOriginnoWorkload lineage: the project it belongs to and the client host / user / directory / git repo it was spawned from. The CLI populates it automatically; the server stamps the authenticated subject. Reported back on status/list.
stopSignalstringnoimage defaultSignal used to stop the main process, e.g. SIGTERM. dockerhost only; kubernetes and containerd ignore it.
stopGracePeriodstringnobackend defaultHow long to wait after the stop signal before killing, as a Go duration (10s, 1m30s). containerd ignores it.
initbool (nullable)nobackend defaulttrue requests / false declines a PID-1 init reaping zombies (compose init). dockerhost only; kubernetes and containerd ignore it.
ttyboolnofalseAllocates a pseudo-TTY (compose tty).
stdinOpenboolnofalseKeeps the container's stdin open (compose stdin_open). containerd ignores it.
readOnlyboolnofalseMounts the root filesystem read-only (compose read_only).
capAdd[]stringnoAdd Linux capabilities (compose cap_add).
capDrop[]stringnoDrop Linux capabilities (compose cap_drop).
securityOpt[]stringnoSecurity options (compose security_opt). dockerhost passes them verbatim; kubernetes/containerd map only the well-known ones (no-new-privileges, label=) and warn on seccomp=/apparmor=.
groupAdd[]stringnoSupplementary groups (compose group_add). kubernetes/containerd accept numeric GIDs only and skip names with a warning.
sysctlsmap[string]stringnoNamespaced kernel parameters (compose sysctls).
extraHosts[]stringnoCustom /etc/hosts entries as host:ip (compose extra_hosts). containerd ignores it.
dnsServers[]stringnoCustom nameservers (compose dns). Distinct from the dns caretaker field. containerd ignores it.
dnsSearch[]stringnoCustom DNS search domains (compose dns_search). containerd ignores it.
dnsOptions[]stringnoCustom resolver options (compose dns_opt), each name or name:value. containerd ignores it.
ulimits[]UlimitnoPer-resource rlimits (compose ulimits). kubernetes ignores it.
tmpfs[]stringnotmpfs mounts, each a container path with optional :-separated options (e.g. /run:size=64m).
devices[]stringnoHost device mappings (compose devices), each host:container[:perms] (perms defaults to rwm). kubernetes ignores it.
shmSizeint64no0 (backend default)Size of /dev/shm in bytes (compose shm_size).
pidModestringnobackend defaultPID namespace mode (compose pid), e.g. host. kubernetes/containerd map only host.
ipcModestringnobackend defaultIPC namespace mode (compose ipc), e.g. host. kubernetes/containerd map only host.
egressEgressSpecnoRoutes outbound traffic through a client-side vantage point. See Egress.
ingressIngressSpecnoDeclares HTTP(S) host/path routing for a published workload port. Kubernetes creates a native Ingress; on host backends the cornus server realizes the same routes. See Ingress.
knativeKnativeSpecnoDeploys the workload as a Knative Serving Service (serverless, autoscaling, scale-to-zero). Realized only on a kubernetes backend whose cluster serves serving.knative.dev; elsewhere it is warned about and ignored (the workload runs as an ordinary container). Usually populated by the serving.knative.dev/v1 descriptor loader — see cornus deploy.
agentForwardboolnofalseWires a caretaker AgentRelayRole for this deployment so cornus exec --forward-agent / cornus compose exec --forward-agent can relay a local ssh-agent into an exec session. kubernetes only, opt-in per deployment (dockerhost/containerdhost gate this instead on the backend-wide CORNUS_DOCKER_REMOTE / CORNUS_CONTAINERD_REMOTE, which already runs a per-instance companion for every deployment). Compose services set it with x-cornus-agent-forward: true.
telemetryTelemetrySpecnoRuns an embedded OpenTelemetry Collector in the caretaker and auto-wires the workload's OTEL_* env to it. Exports to endpoint, or to cornus's own store when none is set. All backends. Compose: x-cornus-telemetry: (service or project level); CLI: --telemetry-*. See Observability.

TIP

restart maps from Compose's deploy.restart_policy.condition (noneno, on-failureon-failure, anyalways), which is authoritative over the service-level restart: when the planner writes the spec.

Nested types

Origin

The workload's lineage (origin) — where the deployment came from. The CLI fills every field but subject from the client environment (cornus deploy records the working directory; cornus compose records the project name and the Compose file's directory); the server overwrites subject with the authenticated request identity and discards any client-supplied value, so claimed origin and verified identity stay separate. All fields are best-effort. It is persisted per backend as cornus.origin.* container labels (dockerhost / containerd), record fields (bare), or object annotations (kubernetes), and reported back on cornus deploy / status / list.

FieldTypeRequiredDefaultDescription
projectstringnoOwning project — the Compose project name, or cornus deploy --project.
hoststringnoClient machine hostname the deploy was spawned from (client-attested).
userstringnoClient OS user that spawned the deploy (client-attested).
directorystringnoAbsolute client-side directory the deploy was launched from (client-attested).
gitGitOriginnoGit provenance of directory, when it is a repository.
subjectstringnoServer-stamped authenticated identity (JWT subject). Any value sent by the client is ignored; empty when auth is disabled.

GitOrigin

Git provenance of the origin directory (origin.git), client-attested and best-effort.

FieldTypeRequiredDefaultDescription
remotestringnoThe origin remote URL.
branchstringnoChecked-out branch (empty on a detached HEAD).
commitstringnoFull HEAD commit SHA.
dirtyboolnofalseThe working tree had uncommitted changes at deploy time.

PortMapping

Maps a host port to a container port (ports[]).

FieldTypeRequiredDefaultDescription
hostintyesHost port to publish.
containerintyesContainer port to reach.
protocolstringnotcptcp or udp.
hostIPstringno0.0.0.0 (all interfaces)Restricts the host-side publish to a specific interface (compose 127.0.0.1:8080:80). Honored by the host backends; kubernetes Services have no equivalent.

Mount

Binds a host source into the container (mounts[]). Distinct from a managed volumes entry.

FieldTypeRequiredDefaultDescription
sourcestringyesHost path to bind.
targetstringyesContainer path to mount it at.
readOnlyboolnofalseMount read-only.
selinuxstringnoSELinux relabel (compose :z/:Z): z shares the content among containers, Z makes it private. Applied by dockerhost; containerd/kubernetes do not relabel.
immutableboolnofalseClient-local, read-only mount whose contents remain unchanged for the deployment lifetime. Enables the server per-file cache. Ignored for server-host mounts.
asyncCacheboolnofalseClient-local writable mount using the cache-coherent block protocol. Requires one replica and cannot combine with readOnly or immutable. Ignored for server-host mounts.
noCreateHostPathboolnofalseRefuse to auto-create a missing caller-local bind source. The default creates it as an empty directory, matching Compose bind.create_host_path: true; Compose bind.create_host_path: false sets this field. Ignored for server-host mounts.

VolumeSpec

A managed (non-bind) volume mounted into the container (volumes[]). On kubernetes it becomes a dynamically-provisioned PersistentVolumeClaim; on dockerhost a Docker anonymous/named volume. On first start the volume is seeded with whatever the image ships at target (Docker volume semantics); subsequent starts preserve writes.

The name field selects the two Compose volume flavours:

  • Anonymous (name empty): storage is private to this deployment and ephemeral — reaped when the deployment is deleted (like docker rm -v).
  • Named (name set): a shared, project-scoped store whose lifecycle is independent of any one deployment; it survives cornus delete of any single deployment that uses it. Supply the already project-scoped logical name (e.g. myproj_cache).
FieldTypeRequiredDefaultDescription
namestringnoanonymousSet => shared/persistent named volume; empty => anonymous.
targetstringyesContainer mount path.
sizestringno1GiRequested size, e.g. 1Gi.
storageClassstringnocluster default classKubernetes StorageClass for the PVC.
readOnlyboolnofalseMount read-only.
driverstringnoDocker default (local)Volume plugin for a named volume (compose driver). dockerhost only; kubernetes/containerd ignore it.
driverOptsmap[string]stringnoOpaque driver options (compose driver_opts). dockerhost only.
labelsmap[string]stringnoUser metadata on a named volume. dockerhost sets them; kubernetes copies them onto the PVC (management labels win); containerd ignores them.

NetworkAttachment

One membership of a workload in a user-defined network (networks[]), modelled on Docker/Compose user-network semantics: a member is reachable by its service name (and any aliases) from other members of the same network, and — where the fabric supports it — isolated from networks it does not join.

driver selects how the kubernetes backend realises the network; empty takes the backend default (CORNUS_K8S_NET_DRIVER, itself defaulting to services). Recognised kubernetes drivers: services (DNS only, any cluster), bridge/ipvlan/macvlan (Multus CNI), cilium. The dockerhost backend passes driver straight through to Docker's own network drivers.

FieldTypeRequiredDefaultDescription
namestringyesProject-scoped network resource name (e.g. myproj_frontend).
driverstringnoservices (kubernetes) / Docker bridgeRealisation driver (see above).
driverOptsmap[string]stringnoOpaque per-network knobs forwarded to the driver (compose driver_opts).
aliases[]stringnoExtra DNS names for this member on the network.
defaultboolnofalseDetached-primary mode on kubernetes: replaces the pod's primary interface (Multus default-network). At most one attachment may set it. dockerhost ignores it.
ipstringnoPins the member's IPv4 address on this network, in CIDR form (e.g. 10.222.14.7/24). Honored on Multus-realised kubernetes networks only. dockerhost ignores it (libnetwork addresses and resolves members natively, and the CIDR form is not a valid Docker endpoint address); containerd and bare warn and ignore it — their bridge CNI uses host-local IPAM with no reservation, so the instance takes the next free address in the auto-allocated range.
subnetstringnoNetwork IPAM subnet (compose ipam.config[0].subnet). dockerhost and the Multus netdriver use it; containerd ignores it.
gatewaystringnoNetwork IPAM gateway. dockerhost only.
ipRangestringnoNetwork IPAM IP range. dockerhost only.
internalboolnofalseRestricts the network to intra-network traffic with no external egress (compose internal). dockerhost only.
attachableboolnofalseAllows standalone containers to join a swarm-scoped network (compose attachable). dockerhost only.
enableIPv6boolnofalseTurns on IPv6 addressing (compose enable_ipv6). dockerhost only.
labelsmap[string]stringnoUser metadata on the network. dockerhost only (management labels win).
ipv6stringnoPins this member's per-network IPv6 address (compose ipv6_address). dockerhost only.
macstringnoPins this member's MAC address (compose mac_address). dockerhost only.
priorityintno0Orders network attachment (compose priority): highest-priority network is joined first and its gateway becomes the default route. dockerhost only.

ProxySpec

Configures the userspace egress proxy for a workload (proxy). kubernetes only. allow is the set of peer service names the workload may reach (services sharing a proxy network).

FieldTypeRequiredDefaultDescription
modestringnoenforcingenforcing (all outbound TCP redirected to an nftables sidecar that permits only destinations resolving to an allow peer — real L4 isolation) or cooperative (soft isolation: each allow peer's DNS name points at a loopback address the sidecar forwards; bypassed by dialing a raw pod IP).
allow[]stringnoPeer service names the workload may reach.
portsmap[string][]intnoCooperative mode: per allow peer, the container ports to proxy.
listenPortintnobackend defaultPort the sidecar listens on for redirected traffic.

DNSSpec

Configures the per-pod caretaker DNS resolver (dns). kubernetes only. records maps a peer service name to the IPv4 address the pod should resolve it to (typically the peer's user-network / Multus-secondary address). Everything not in records is forwarded to the cluster DNS.

FieldTypeRequiredDefaultDescription
recordsmap[string]stringnoPeer service name → IPv4 address to resolve it to.
requireUserNetboolnofalseMarks records that point at Multus secondary addresses. When the cluster cannot realise the Multus fabric, the backend skips the DNS caretaker entirely and resolution degrades to the cluster DNS.

DockerSpec

Configures the caretaker's Docker Engine API endpoint (docker). kubernetes only. The caretaker binds a Docker-API proxy on a pod-loopback endpoint and injects DOCKER_HOST so stock docker / docker compose drive the same cornus server that manages the pod's own stack. Requires a client-scoped token Secret on the server (CORNUS_CLIENT_TOKEN_SECRET).

FieldTypeRequiredDefaultDescription
transportstringnotcptcp (binds 127.0.0.1:port), unix (binds a socket at socketPath), or both (DOCKER_HOST then points at the TCP endpoint).
portintno2375Loopback TCP port for the tcp / both transports.
socketPathstringno/cornus/docker/docker.sockUnix socket path for the unix / both transports (on a shared emptyDir).
envVarstringnoDOCKER_HOSTEnvironment variable used to advertise the endpoint to the app container.

TelemetrySpec

Runs an embedded OpenTelemetry Collector in the caretaker (compose x-cornus-telemetry:, service or project level; CLI --telemetry-*). The app sends OTLP to a pod-loopback receiver and the Collector exports it to endpoint — or, when none is given, to cornus's own built-in observability store; the backend injects the workload's OTEL_* env automatically. All backends. See Observability. Requires the collector-enabled image (-tags otelcol, set in the released image).

FieldTypeRequiredDefaultDescription
enabledboolnofalseTurns telemetry on. A non-empty endpoint implies it; a bare x-cornus-telemetry: {} is enough to enable it.
endpointstringnothe server's own storeThe OTLP backend to export to (host:port for grpc, URL for http/protobuf). Leave it empty to export to cornus's built-in observability store, which the server fills in at deploy time. A deploy path with no store to default to (a local cornus deploy, or a server started without --obs) rejects an empty endpoint with a message naming both remedies.
protocolstringnogrpcExporter protocol: grpc or http/protobuf (also selects the receiver port advertised to the app: 4317 vs 4318).
headersmap[string]stringnoStatic export headers (e.g. an auth token). On kubernetes projected via a Deployment-owned Secret + secretKeyRef, so no value appears in the pod spec.
insecureboolnofalseDisable transport security to the backend (plaintext / no cert verification).
signals[]stringnoallRestrict pipelines to traces, metrics, and/or logs.
serviceNamestringnodeployment nameOverride OTEL_SERVICE_NAME injected into the app (a user-set env wins).
resourceAttributesmap[string]stringnoExtra OTEL_RESOURCE_ATTRIBUTES merged with cornus-derived defaults (a user-set env wins).
grpcPort / httpPortintno4317 / 4318OTLP receiver loopback ports inside the pod.
debugboolnofalseAlso log collected telemetry to the collector stdout (troubleshooting).
viaMuxboolnoon when cornus is the destinationCarry the exports over a caretaker connection to the cornus server instead of dialing it from the workload's network. Defaults ON whenever the endpoint resolves to this server, on every backend that runs a telemetry caretaker; set false to force the direct dial. With an explicit third-party endpoint it stays off (there is no connection to ride). Requires CORNUS_ADVERTISE_URL. Compose: via_mux. See Observability.

HubSpec

Requests workload-to-workload overlay membership (hub). kubernetes only. See the workload hub.

FieldTypeRequiredDefaultDescription
identitystringnodeployment namePolicy identity.
export[]HubExportnoServices this workload hosts on the overlay.
import[]HubImportnoServices this workload reaches through the overlay.
importDynamicHubImportDynamicnoOpts the workload into dynamic import discovery.

HubExport / HubImport / HubImportDynamic

HubExport — one service this workload hosts on the overlay:

FieldTypeRequiredDefaultDescription
namestringyesService name on the overlay.
portintyesPort the service listens on.
deliverboolnofalseRequests ingress delivery (the hub relays to this pod, which dials port on localhost) so the service need not be reachable from the hub.
protocolstringnotcptcp or udp.

HubImport — one service this workload reaches through the overlay:

FieldTypeRequiredDefaultDescription
namestringyesService name to reach.
ports[]intyesPorts to bind a loopback listener for.
protocolstringnotcptcp or udp.

HubImportDynamic — subscribes to hub catalog pushes and binds a loopback listener at the synthetic IP of every cataloged service (excluding this workload's own exports and static imports), adding/closing listeners as services appear and vanish. No DNS records are wired (names are unknown at deploy time):

FieldTypeRequiredDefaultDescription
ports[]intyesShared port set bound per discovered service.
protocolstringnotcptcp or udp.

CredentialSpec

Brokers client-sourced credentials into a workload (credentials). The secret value is minted on the client (never carried in this spec) and delivered through the cornus server and the caretaker sidecar. Realized on kubernetes over a session the client holds for the workload's lifetime. cornus deploy --detach and every host backend (dockerhost, containerd, bare, and incus) reject it. Compose services set it with x-cornus-credentials: (service or project level), where cornus compose up -d is supported too — the project's background agent holds the session. See Credentials.

FieldTypeRequiredDefaultDescription
sources[]CredentialSourcenoEach entry is one credential the container can retrieve on demand.

CredentialSource

FieldTypeRequiredDefaultDescription
namestringyesLogical credential name. Doubles as the capability key and default file basename / endpoint path segment.
backendstringyesClient-side backend that mints the credential (e.g. aws-sts, github-cli, static, exec). Runs on the caller's machine with the caller's own cloud/API credentials.
configmap[string]stringnoNon-secret backend configuration (e.g. role_arn, duration, region). Must never hold the secret itself.
ttlstringnobackend defaultClient-side cache/refresh hint, a Go duration string.
deliveries[]CredentialDeliverynoHow the container consumes the credential. Empty is valid (fetchable but not surfaced).

CredentialDelivery

One provider-agnostic way to surface a credential to the container.

FieldTypeRequiredDefaultDescription
kindstringnoendpointendpoint (an HTTP metadata server / auth-injecting proxy), file (materialize to a path in a shared volume), or env (inject into the app container's environment).
providerstringnogenericendpoint kind. generic serves the cornus-native JSON contract (GET /credentials/<name>); aws-imds and future adapters render the same credential in a cloud SDK's expected shape; the auth-injecting proxies (anthropic-proxy, openai-proxy, github-proxy) hold the credential themselves and add it to the workload's API calls.
wellKnownboolnofalseendpoint kind. Binds the provider's canonical link-local address (e.g. AWS 169.254.169.254, IMDSv2) inside the pod netns. Needs NET_ADMIN; when false the endpoint binds loopback and is advertised via an injected env var (for aws-imds, AWS_CONTAINER_CREDENTIALS_FULL_URI — the ECS container-credentials endpoint).
upstreamstringnoprovider defaultendpoint kind, auth-proxy providers. Overrides the vendor API the proxy forwards to (e.g. an Anthropic-/OpenAI-compatible gateway, or a GitHub Enterprise Server REST base such as https://ghe.corp/api/v3). Non-secret.
pathstringnofile kind. Container path to materialize the credential to.
formatstringnojsonfile kind. json (the neutral {values,expiration} object), env (KEY=VALUE lines), raw (a single value), or aws-credentials (an ini profile).
envVarstringnoenv kind. App-container environment variable to set. Fetched once at deploy time into a Kubernetes Secret (secretKeyRef) — static, no runtime refresh, lives in etcd. Prefer proxy/file delivery for short-lived credentials.
valueKeystringnovalue then tokenenv kind. Which credential values key supplies the env value.

Healthcheck

A container health probe (healthcheck), modelled on Docker's healthcheck. On dockerhost it becomes the Docker container healthcheck; on kubernetes an exec liveness (and readiness) probe. test uses Docker's CMD form: first element is CMD (exec the rest), CMD-SHELL (run the single string via the shell), or NONE (disable any inherited healthcheck).

FieldTypeRequiredDefaultDescription
test[]stringnoProbe command in Docker CMD form (see above).
intervalstringnobackend defaultProbe interval, a Go duration string (30s).
timeoutstringnobackend defaultPer-probe timeout, a Go duration string.
startPeriodstringnobackend defaultGrace period before failures count, a Go duration string.
startIntervalstringnobackend defaultProbe interval during the start period (compose start_interval).
retriesintnobackend defaultConsecutive failures before unhealthy.

containerd

The containerd backend ignores healthchecks (with a warning).

Resources

Caps a workload's compute (the *Limit fields) and/or reserves a guaranteed floor (the reserved* fields, from compose deploy.resources.reservations). A zero field means "unset on that axis".

FieldTypeRequiredDefaultDescription
cpuLimitfloat64no0 (unset)Fractional core count (e.g. 0.5 = half a core). Docker NanoCpus; kubernetes CPU quantity in millicores.
memoryLimitint64no0 (unset)Byte count. Docker Memory; kubernetes memory quantity.
reservedCpufloat64no0 (unset)Reservation floor. kubernetes resources.requests.cpu; no-op on dockerhost (Docker has no CPU reservation); containerd ignores it.
reservedMemoryint64no0 (unset)Reservation floor. kubernetes resources.requests.memory; dockerhost MemoryReservation; containerd ignores it.

UpdateConfig

The rolling-update strategy (updateConfig, from compose deploy.update_config). Only kubernetes maps it, onto the Deployment strategy.rollingUpdate. The other compose knobs (delay, monitor, max_failure_ratio) are swarm concepts a Deployment cannot express and are dropped at translate time.

FieldTypeRequiredDefaultDescription
parallelismintno0 (backend default of 1)How many instances to update at once. Sizes maxUnavailable (stop-first) or maxSurge (start-first).
orderstringnostop-firststop-first (take an old instance down before bringing a new one up) or start-first (surge a new instance up before removing the old).

Ulimit

One process resource limit (ulimits[], compose ulimits). Compose's shorthand (a bare integer) sets soft == hard. dockerhost HostConfig.Ulimits; containerd OCI Process.Rlimits; kubernetes ignores it.

FieldTypeRequiredDefaultDescription
namestringyesBare limit name (nofile, nproc).
softint64noSoft bound.
hardint64noHard bound.

EgressSpec

Routes a workload's outbound traffic through a client-side vantage point (egress) — for air-gapped clusters or VPN/corporate-proxy/SASE networks where the sanctioned egress path lives on the caller's side. See Egress.

Routing is per destination: each flow is sent to one of four routes — client (relay to the client-side network), gateway (relay to a durable egress-gateway node, for --detach), cluster (egress directly, no relay), or deny (drop). default applies to unmatched destinations and defaults to cluster, so enabling egress never silently diverts in-cluster traffic — you opt destinations out to the client/gateway.

FieldTypeRequiredDefaultDescription
modestringnoenvenv (propagate HTTP_PROXY/HTTPS_PROXY/NO_PROXY/ALL_PROXY into the container — every backend, no relay), proxy (caretaker runs an HTTP CONNECT + SOCKS5 forward proxy relayed back through the server), or transparent (all outbound TCP is captured by an nftables redirect and relayed). The relay modes run in a Kubernetes sidecar or a host-backend companion caretaker; incus does not yet support them.
gatewaystringnoReserved; must be empty today. The gateway route currently egresses through the cornus server itself; a non-empty value is rejected by validation.
proxiesmap[string]stringnoclient-resolvedMode env: explicit proxy variables to inject. Empty asks the client to resolve its own OS proxy configuration at deploy time.
rules[]EgressRulenoDeclarative routing policy: an ordered list, first-match-wins, falling back to default. Superseded by script.
scriptstringnoOptional PAC-style JavaScript (FindProxyForURL) that decides the route per destination. When set it supersedes rules: DIRECTcluster, PROXY client/PROXY gateway→relay routes, DENY→drop, no match→default.
defaultstringnoclusterRoute for destinations no rule/script matches: cluster, client, gateway, or deny.
listenPortintnobackend defaultCaretaker proxy's listen port (modes proxy and transparent).

Modes proxy and transparent tunnel traffic back through the client and therefore require a live deploy-attach session (they cannot be used with a stateless --detach deploy); env does not.

EgressRule

Maps a destination to a route (egress.rules[]).

FieldTypeRequiredDefaultDescription
patternstringyesMatches the destination host (glob, e.g. *.internal), a CIDR (e.g. 10.0.0.0/8), and/or an explicit port (e.g. api.example.com:443, 10.0.0.0/8:5432). An empty host or port part matches any.
routestringyesOne of client, gateway, cluster, or deny.

IngressSpec

Declares public HTTP(S) host/path routing for a published workload port (ingress). On Kubernetes, cornus creates a native Ingress fronting the workload's ClusterIP Service. On dockerhost, containerd, bare, and incus, the cornus server realizes the same routing declaration itself. The spec must publish at least one port. See Ingress.

FieldTypeRequiredDefaultDescription
enabledboolnofalseTurns ingress on. A non-empty hosts (or the Compose host:) implies enabled; a bare x-cornus-ingress: {} enables it with every field defaulted.
hosts[]stringnoderivedExternal hostnames; each becomes its own Ingress rule sharing one TLS entry. @ maps to the apex (the base domain itself, no <name>. prefix). Empty derives a single <subdomain>.<domain> host; neither a host nor a base domain is rejected.
domainstringnoCORNUS_INGRESS_DOMAINClient override of the base domain used to auto-derive the host when hosts is empty. A server may enforce that resolved hosts stay within its domain (CORNUS_INGRESS_ENFORCE_DOMAIN).
subdomainstringnodeployment nameLabel(s) prefixed to the base domain when auto-deriving (<subdomain>.<domain>). The Compose translator sets <service>.<project>. Sanitized to DNS-1123.
pathstringno/HTTP path prefix to route.
pathTypestringnoPrefixKubernetes path match type: Prefix, Exact, or ImplementationSpecific.
portintnofirst publishedContainer port the ingress routes to. Non-zero must match one of the spec's published ports.
classNamestringnoCORNUS_INGRESS_CLASS, then cluster defaultIngressClassName for the Ingress.
annotationsmap[string]stringnoMerged verbatim onto the Ingress object, for controller-specific knobs.
tlsIngressTLSnoWhen set, requests HTTPS for the host(s); omit for plain HTTP.
tunnelIngressTunnelOptnoAsks the client to publish this ingress through a public tunnel after a successful foreground remote deploy.

IngressTLS

Configures HTTPS for the ingress host(s) (ingress.tls).

FieldTypeRequiredDefaultDescription
secretNamestringno<name>-tlsExisting TLS secret to serve. The default is provisioned by cert-manager when clusterIssuer (or the server default) is set.
clusterIssuerstringnoCORNUS_INGRESS_TLS_ISSUERSets the cert-manager.io/cluster-issuer annotation so cert-manager provisions the certificate.

IngressTunnelOpt

Declares that the client should publish this deployment's ingress through the server's configured tunnel provider after a successful foreground cornus deploy --server. The server does not act on this block during apply: tunnel credentials remain client-side and are sent separately to the authenticated ingress-tunnel endpoint. Consequently, this automatic tunnel is not started by --detach or a local deploy, and it lasts only for the foreground deploy session.

The client reads the credential file and default ingress host mode from the selected connection profile's tunnel block. If no credential file is configured, it falls back to NGROK_AUTHTOKEN; a server-side provider credential may also make a client credential unnecessary. A failure to publish the optional tunnel is reported but does not turn an otherwise successful deployment into a failed one.

FieldTypeRequiredDefaultDescription
enabledboolnofalsePublish the ingress after deployment.
hostModestringnoprofile default, then autoHost-header behavior: auto, passthrough, alias, or rewrite.
hoststringnoauto-selectedDeclared ingress hostname to front when the deployment has more than one.

KnativeSpec

Deploys the workload as a Knative Serving Service (knative). Realized only on a kubernetes backend whose cluster serves serving.knative.dev — the backend then emits a serving.knative.dev/v1 Service instead of a Deployment plus Service, so Knative owns autoscaling, scale-to-zero, and the Route. On a plain cluster or the dockerhost / containerd / bare backends it is warned about and ignored. Most often set by the Knative descriptor loader when you cornus deploy -f service.yaml; see cornus deploy.

FieldTypeRequiredDefaultDescription
enabledboolnofalseMarks the workload as a Knative Service. A bare {} enables it with every field defaulted.
minScaleintno0Autoscaling floor (autoscaling.knative.dev/minScale). 0 permits scale-to-zero.
maxScaleintno0Autoscaling ceiling (autoscaling.knative.dev/maxScale). 0 means unlimited.
targetintnoAutoscaling target per replica (autoscaling.knative.dev/target): concurrent requests, or requests-per-second for the rps metric.
concurrencyintno0Hard limit on simultaneous requests per replica (revision containerConcurrency). 0 means unlimited.
classstringnocluster defaultAutoscaler class: kpa (Knative Pod Autoscaler) or hpa.
metricstringnoconcurrencyScaling metric: concurrency, rps, or cpu (cpu requires class: hpa).
timeoutSecondsintno300Maximum duration of a single request (revision timeoutSeconds).
portintnofirst publishedThe single container port Knative routes to. Non-zero must match one of the published ports.
annotationsmap[string]stringnoMerged onto the revision template for autoscaling knobs beyond the fields above (the fields win on a collision).

See also

Released under the Apache-2.0 License.