Skip to content
Manifest schema

Manifest schema

Overview

Every Shrine manifest must begin with apiVersion: shrine/v1 and a kind field. Three kinds exist: Team (a namespace with quotas), Resource (a managed dependency with typed outputs), and Application (a deployable container with routing and dependency injection).

All manifests carry metadata.name (required on all kinds) and metadata.owner (required on Resource and Application; the owning Team name).

Validation is multi-error: all field errors are collected and reported together before any deployment begins.

Team

A Team defines a namespace with resource quotas. Register teams with shrine apply teams before deploying Applications or Resources that reference them.

apiVersion: shrine/v1
kind: Team
metadata:
  name: <string>         # required
spec:
  displayName: <string>  # required
  contact: <string>      # required — e.g. admin@example.com
  quotas:
    maxApps: <int>
    maxResources: <int>
    allowedResourceTypes:
      - <string>
  registryUser: <string>
FieldRequiredDefaultDescription
metadata.nameyesUnique identifier for the team. Used as the Docker network suffix.
spec.displayNameyesHuman-readable name shown in status output.
spec.contactyesContact address for the team (for documentation purposes).
spec.quotas.maxAppsno0 (unlimited)Maximum number of Application manifests the team may deploy.
spec.quotas.maxResourcesno0 (unlimited)Maximum number of Resource manifests the team may deploy.
spec.quotas.allowedResourceTypesnoanyRestricts which resource types (e.g. postgres) are permitted.
spec.registryUsernoDocker registry username associated with this team.

Resource

A Resource is a managed dependency container (Postgres, Redis, etc.) with named outputs that Applications consume via valueFrom.

apiVersion: shrine/v1
kind: Resource
metadata:
  name: <string>    # required
  owner: <string>   # required — team name
  access:
    - <team-name>   # teams allowed to consume outputs
spec:
  type: <string>    # required — e.g. postgres
  version: <string> # required — e.g. "16"
  port: <int>
  image: <string>
  outputs:
    - name: <string>
      value: <string>        # static value (mutually exclusive with generated/template)
      generated: <bool>      # generate a random secret at deploy time
      template: <string>     # Go text/template referencing other output names
  networking:
    exposeToPlatform: <bool>
  volumes:
    - name: <string>
      mountPath: <string>
  imagePullPolicy: <Always|IfNotPresent>
FieldRequiredDefaultDescription
metadata.nameyesUnique identifier within the owning team.
metadata.owneryesTeam that owns this resource.
metadata.access[]noAdditional teams that may reference this resource’s outputs.
spec.typeyesResource type string (e.g. postgres, redis).
spec.versionyesVersion tag passed to the resource image.
spec.portnoOverride the default port for this resource type.
spec.imagenoOverride the default image for this resource type.
spec.outputs[].nameyesOutput name. host and port are CLI built-ins filled automatically.
spec.outputs[].valueno*Static string value. Mutually exclusive with generated and template.
spec.outputs[].generatedno*Generate a random value at deploy time.
spec.outputs[].templateno*Go text/template expression referencing sibling output names, e.g. postgres://postgres:{{.password}}@{{.host}}:{{.port}}/app.
spec.outputs[].valueFromno*Fetch value from the active secrets vault at deploy time: vault:<project>/<environment>/<secret-name>. The project component may be the project’s display name, slug, or UUID (see Secrets vault guide). Mutually exclusive with value, generated, and template.
spec.networking.exposeToPlatformnofalseAttach the resource to the shared platform network so gateway plugins can reach it.
spec.volumes[].nameyes (per entry)Logical volume name; must be unique within the manifest.
spec.volumes[].mountPathyes (per entry)Absolute path inside the container.
spec.imagePullPolicynoAlways for :latest, IfNotPresent otherwiseDocker image pull policy.

* Each output (except the built-ins host and port) must set exactly one of value, generated, template, or valueFrom.

Application

An Application is a deployable container with routing, env injection, and dependency wiring.

apiVersion: shrine/v1
kind: Application
metadata:
  name: <string>   # required
  owner: <string>  # required — team name
spec:
  image: <string>  # required
  port: <int>      # required
  replicas: <int>
  routing:
    domain: <string>
    pathPrefix: <string>
    aliases:
      - host: <string>
        pathPrefix: <string>
        stripPrefix: <bool>
        tls: <bool>
  dependencies:
    - kind: Resource
      name: <string>
      owner: <string>
  env:
    - name: <string>
      value: <string>
      valueFrom: resource.<name>.<output>
      template: <string>
  networking:
    exposeToPlatform: <bool>
  volumes:
    - name: <string>
      mountPath: <string>
  imagePullPolicy: <Always|IfNotPresent>

Application top-level fields

FieldRequiredDefaultDescription
metadata.nameyesUnique identifier within the owning team. Used as the container name suffix.
metadata.owneryesTeam that owns this application.
spec.imageyesDocker image reference (e.g. nginx:alpine).
spec.portyesPort the container listens on.
spec.replicasno1Number of container instances to run.
spec.networking.exposeToPlatformnofalseAttach the container to the platform network and include it in Traefik routing generation.
spec.imagePullPolicynoAlways for :latest, IfNotPresent otherwiseDocker image pull policy.

spec.routing

FieldRequiredDefaultDescription
routing.domainnoPrimary hostname. Required when routing.aliases is set.
routing.pathPrefixnoURL path prefix for the primary-domain router.
routing.aliases[]noAdditional hostnames / path prefixes (see below). Requires routing.domain.

spec.routing.aliases[]

FieldRequiredDefaultDescription
hostyesHostname the alias router matches. Must be non-empty.
pathPrefixnoURL path prefix; router matches paths at or below it.
stripPrefixnotrue (when pathPrefix is set)Remove the prefix before forwarding. Set false for backends that own their basePath (e.g. Next.js). No-op when pathPrefix is absent.
tlsnofalseAttach this alias router to the websecure entrypoint and emit tls: {}. Only valid inside alias entries.

spec.env[]

Each env var must set exactly one of value, valueFrom, or template.

FieldDescription
nameEnvironment variable name passed to the container.
valueStatic string value.
valueFromReference to a Resource output (resource.<resource-name>.<output-name>) or a vault secret (vault:<project>/<environment>/<secret-name> — project may be a name, slug, or UUID; see the Secrets vault guide).
templateGo text/template expression; can reference other env vars or resource outputs by name.

Templating

Shrine resolves valueFrom references, vault-sourced values, and template expressions at deploy time using Go text/template. Vault secrets (any valueFrom field whose value starts with the vault: prefix) are fetched from the configured secrets plugin and treated as resolved string values before template expressions are evaluated. The dependency graph is topologically sorted (Kahn’s algorithm) so all three resolution mechanisms — valueFrom, vault fetch, and template — resolve in the correct order. Circular references are a validation error.

Examples

Team

apiVersion: shrine/v1
kind: Team
metadata:
  name: platform
spec:
  displayName: "Platform Team"
  contact: platform@example.com
  quotas:
    maxApps: 10
    maxResources: 5
    allowedResourceTypes:
      - postgres
      - redis

Resource

apiVersion: shrine/v1
kind: Resource
metadata:
  name: app-db
  owner: platform
spec:
  type: postgres
  version: "16"
  outputs:
    - name: host
    - name: port
      value: "5432"
    - name: password
      generated: true
    - name: url
      template: "postgres://postgres:{{.password}}@{{.host}}:{{.port}}/app"

Application

apiVersion: shrine/v1
kind: Application
metadata:
  name: api
  owner: platform
spec:
  image: my-api:1.2.3
  port: 8080
  routing:
    domain: api.home.lab
    aliases:
      - host: gateway.tailnet.ts.net
        pathPrefix: /api
        stripPrefix: true
  dependencies:
    - kind: Resource
      name: app-db
      owner: platform
  env:
    - name: DATABASE_URL
      valueFrom: resource.app-db.url
  networking:
    exposeToPlatform: true