Skip to main content
Server installations deploy server services to environments. Configure environment variables, resource limits, and service-specific settings for your web applications and APIs.
# yaml-language-server: $schema=https://api.ryvn.app/v1/schemas/resources.json
kind: ServiceInstallation
metadata:
  name: api-production
spec:
  service: api
  environment: production
  variableGroups:
    - name: shared-config
  env:
    - key: DATABASE_URL
      isSecret: true
    - key: LOG_LEVEL
      value: info
  config: |
    replicaCount: 3
    service:
      port: 8080
    resources:
      requests:
        cpu: 0.5
        memory: 512Mi

Properties

service

string — required Name of the server service to install.
service: api

environment

string — required Target environment for this installation.
environment: production

name

string — optional Custom name for this installation. If not specified, uses the service name.
name: api-instance

namespace

string — optional Kubernetes namespace to install into. If not provided, uses the environment’s default namespace.
namespace: apps

releaseChannel

string — optional Release channel to follow for this installation. If not specified, uses the environment’s channel. Mutually exclusive with branch.
releaseChannel: stable

branch

string — optional Branch to track for this installation. The service must have the branch listed in build.branches. When set, the installation deploys whatever was last built on that branch. Mutually exclusive with releaseChannel.
branch: staging

variableGroups

array — optional List of variable group references to link to this installation. Each entry references a variable group by name that must already exist in the target environment. Variable groups provide shared sets of environment variables across installations.
variableGroups:
  - name: shared-config
  - name: database-credentials

variableGroups[].name

string — required Name of the variable group in the target environment.
variableGroups:
  - name: shared-config

env

array — optional Environment variables for the server service. Each entry defines an individual variable using key, isSecret, and optionally value.
Use variableGroups to import shared sets of environment variables instead of defining them individually.
env:
  - key: DATABASE_URL
    isSecret: true
  - key: LOG_LEVEL
    value: info

env[].key

string — conditional (required when not using orgSecret) Environment variable name.
key: DATABASE_URL

env[].isSecret

boolean — conditional (optional when using key) Whether this environment variable is a secret. Defaults to false. If true, value must be set directly on the platform.
isSecret: true

env[].value

string — conditional (optional when using key) Environment variable value. Cannot be set if isSecret is true.
value: info

env[].orgSecret

string — conditional (required when not using key) Name of organization-level secret. All key-value pairs are loaded as environment variables. Cannot be used with key, isSecret, or value.
Prefer using variableGroups instead of orgSecret for sharing secrets across installations. Variable groups provide better visibility, versioning, and audit logging.
env:
  - orgSecret: database-credentials

env[].valueFromInput

object — conditional (optional when using key) Reference to a blueprint input for the value. Only valid when using key. If the referenced input has a condition that evaluates to false, this environment variable is automatically omitted.
env:
  - key: API_KEY
    isSecret: true
    valueFromInput:
      name: apiKey

env[].valueFromOutput

object — conditional (optional when using key) Reference to an output from a service installation or blueprint installation. Exactly one of serviceInstallation or blueprintInstallation must be specified.
Prefer valueFromOutput over template functions like {{ (serviceInstallation "...").outputs.x }} or {{ (blueprintInstallation "...").outputs.x }} in env var values. Template functions render outputs as plaintext, which means secrets end up in manifests and logs. valueFromOutput routes secret outputs through the secrets system so they are never exposed in plaintext.
Properties:
PropertyTypeDescription
serviceInstallationstringName of the service installation to get the output from.
blueprintInstallationstringName of the blueprint installation to get the output from.
namestring(required) Name of the output. Supports dot notation for nested values (e.g., bucket.name).
env:
  # Reference a service installation output
  - key: DATABASE_HOST
    valueFromOutput:
      serviceInstallation: postgres-rds
      name: endpoint

  # Reference a blueprint installation output
  - key: CACHE_HOST
    valueFromOutput:
      blueprintInstallation: cache-stack
      name: host

  # Secret output — routed through the secrets system automatically
  - key: DATABASE_URL
    isSecret: true
    valueFromOutput:
      blueprintInstallation: database-stack
      name: connection_string
To concatenate an output with other values, use valueFromOutput to set a base env var and reference it with $(VAR) syntax in a subsequent variable. The referenced variable must appear earlier in the list:
env:
  - key: DATABASE_HOST
    valueFromOutput:
      serviceInstallation: postgres-rds
      name: endpoint
  - key: DATABASE_URL
    value: "postgresql://$(DATABASE_HOST):5432/mydb"

autoscaling

object — optional Autoscaling configuration. Only supported for server installations. This setting lives at the top level of the installation spec, alongside config. Do not place autoscaling under config; config.autoscaling is rejected. When enabled, Ryvn controls replica scaling automatically. When autoscaling.enabled is true, configure at least one autoscaling trigger:
  • targetCPUUtilizationPercentage
  • targetMemoryUtilizationPercentage
  • One or more Temporal triggers in autoscaling.triggers
  • One or more RabbitMQ triggers in autoscaling.triggers
All trigger types can be used independently or combined in the same installation.
autoscaling:
  enabled: true
  minReplicas: 2
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80
  targetMemoryUtilizationPercentage: 85
  triggers:
    - temporal:
        connection: temporal-prod
        taskQueue: worker-queue
        targetQueueSize: 10
    - rabbitmq:
        queueName: tasks
        value: 5

autoscaling.enabled

boolean — required Whether autoscaling is enabled for this installation.
autoscaling:
  enabled: true

autoscaling.minReplicas

integer — required when enabled Minimum number of replicas. Set to 0 to allow scaling to zero when all triggers are idle.
autoscaling:
  minReplicas: 2

autoscaling.maxReplicas

integer — required when enabled Maximum number of replicas. Must be greater than or equal to minReplicas.
autoscaling:
  maxReplicas: 10

autoscaling.targetCPUUtilizationPercentage

integer — optional Target average CPU utilization percentage (1–100). Can be used on its own or combined with other triggers. When autoscaling is enabled, at least one trigger must be configured.
autoscaling:
  targetCPUUtilizationPercentage: 80

autoscaling.targetMemoryUtilizationPercentage

integer — optional Target average memory utilization percentage (1–100). Can be used on its own or combined with other triggers. When autoscaling is enabled, at least one trigger must be configured.
autoscaling:
  targetMemoryUtilizationPercentage: 80

autoscaling.triggers

array — optional List of autoscaling triggers. Each entry contains either a temporal or rabbitmq block. Triggers can be used on their own or alongside CPU and/or memory targets. You can combine multiple triggers of any type.
autoscaling:
  enabled: true
  minReplicas: 1
  maxReplicas: 20
  triggers:
    - temporal:
        connection: temporal-prod
        taskQueue: worker-queue
        targetQueueSize: 10
        activationTargetQueueSize: 0
        queueTypes: workflow
    - temporal:
        connection: temporal-prod
        taskQueue: priority-queue
        targetQueueSize: 5
        queueTypes: activity
    - rabbitmq:
        queueName: events
        value: 10
        mode: QueueLength

autoscaling.triggers[].temporal

object — required for each Temporal trigger entry Temporal queue-based autoscaling configuration for a single task queue.
autoscaling:
  triggers:
    - temporal:
        connection: temporal-prod
        taskQueue: worker-queue
        targetQueueSize: 10

autoscaling.triggers[].temporal.connection

string — required when using a Temporal trigger Name of the Temporal connection to use for this trigger.
autoscaling:
  triggers:
    - temporal:
        connection: temporal-prod

autoscaling.triggers[].temporal.endpoint

string — optional Optional Temporal Cloud endpoint override. Leave it unset to use the endpoint configured on the referenced Temporal connection.
autoscaling:
  triggers:
    - temporal:
        endpoint: myaccount.tmprl.cloud:7233

autoscaling.triggers[].temporal.namespace

string — optional Optional Temporal namespace override. Leave it unset to use the namespace configured on the referenced Temporal connection.
autoscaling:
  triggers:
    - temporal:
        namespace: production-workers

autoscaling.triggers[].temporal.taskQueue

string — required when using a Temporal trigger Temporal task queue to monitor.
autoscaling:
  triggers:
    - temporal:
        taskQueue: worker-queue

autoscaling.triggers[].temporal.targetQueueSize

integer — required when using a Temporal trigger Desired queue depth per replica before scaling out. Must be greater than 0.
autoscaling:
  triggers:
    - temporal:
        targetQueueSize: 10

autoscaling.triggers[].temporal.activationTargetQueueSize

integer — optional Queue depth required before activating the scaler. Must be 0 or greater.
autoscaling:
  triggers:
    - temporal:
        activationTargetQueueSize: 0

autoscaling.triggers[].temporal.queueTypes

string — optional Types of Temporal task queue to monitor. Supported values: workflow, activity, or workflow,activity. Defaults to the KEDA scaler default if not set.
autoscaling:
  triggers:
    - temporal:
        queueTypes: activity

autoscaling.triggers[].rabbitmq

object — required for each RabbitMQ trigger entry RabbitMQ queue-based autoscaling configuration. Scale based on queue length or message rate.
autoscaling:
  triggers:
    - rabbitmq:
        queueName: tasks
        value: 5

autoscaling.triggers[].rabbitmq.endpoint

string — optional RabbitMQ endpoint URL. For protocol: amqp (default), provide an AMQP(S) broker URL (e.g., amqps://host:5671). For protocol: http, provide an HTTP Management API URL (e.g., http://host:15672). Mutually exclusive with hostFromEnv. When set, usernameFromEnv and passwordFromEnv default to RABBITMQ_USERNAME and RABBITMQ_PASSWORD if not specified.
autoscaling:
  triggers:
    - rabbitmq:
        endpoint: amqps://rabbitmq.example.com:5671
        queueName: tasks
        value: 5

autoscaling.triggers[].rabbitmq.hostFromEnv

string — optional Name of the environment variable containing a fully-formed RabbitMQ connection URL. Mutually exclusive with endpoint. Defaults to RABBITMQ_HOST if neither endpoint nor hostFromEnv is specified.
autoscaling:
  triggers:
    - rabbitmq:
        hostFromEnv: RABBITMQ_URL
        queueName: tasks
        value: 5

autoscaling.triggers[].rabbitmq.queueName

string — required RabbitMQ queue to monitor for autoscaling.
autoscaling:
  triggers:
    - rabbitmq:
        queueName: tasks

autoscaling.triggers[].rabbitmq.value

integer — required Target value per replica. Interpretation depends on mode: queue length (default) or messages per second.
autoscaling:
  triggers:
    - rabbitmq:
        queueName: tasks
        value: 10

autoscaling.triggers[].rabbitmq.mode

string — optional Scaling mode: QueueLength (default) or MessageRate. MessageRate requires protocol: http.
autoscaling:
  triggers:
    - rabbitmq:
        queueName: tasks
        value: 100
        mode: MessageRate
        protocol: http

autoscaling.triggers[].rabbitmq.activationValue

integer — optional Value required before activating the scaler. Defaults to 0.
autoscaling:
  triggers:
    - rabbitmq:
        queueName: tasks
        value: 5
        activationValue: 1

autoscaling.triggers[].rabbitmq.protocol

string — optional Protocol for connecting to RabbitMQ: amqp (default) or http. Use http when you need MessageRate mode or when connecting via the RabbitMQ Management API.
autoscaling:
  triggers:
    - rabbitmq:
        queueName: tasks
        value: 5
        protocol: http

autoscaling.triggers[].rabbitmq.vhost

string — optional RabbitMQ virtual host. Defaults to /.
autoscaling:
  triggers:
    - rabbitmq:
        queueName: tasks
        value: 5
        vhost: /production

autoscaling.triggers[].rabbitmq.usernameFromEnv

string — optional Name of the environment variable containing the RabbitMQ username. Used when endpoint is set. Defaults to RABBITMQ_USERNAME.
autoscaling:
  triggers:
    - rabbitmq:
        endpoint: amqps://rabbitmq.example.com:5671
        queueName: tasks
        value: 5
        usernameFromEnv: RABBIT_USER

autoscaling.triggers[].rabbitmq.passwordFromEnv

string — optional Name of the environment variable containing the RabbitMQ password. Used when endpoint is set. Defaults to RABBITMQ_PASSWORD.
autoscaling:
  triggers:
    - rabbitmq:
        endpoint: amqps://rabbitmq.example.com:5671
        queueName: tasks
        value: 5
        passwordFromEnv: RABBIT_PASS

config

string or array — optional Service configuration. For servers, this is the Helm chart values.yaml content. Configure replicas, service type, ingress, resources, and more.
# As string
config: |
  replicaCount: 3
  service:
    type: LoadBalancer
    port: 80
  ingress:
    enabled: true
    className: external-nginx
    hosts:
      - host: api.example.com
        paths:
          - path: /
            pathType: Prefix
  resources:
    limits:
      cpu: 1000m
      memory: 1Gi
    requests:
      cpu: 500m
      memory: 512Mi

# As array with file path
config:
  - path: config/production.yaml

config.replicaCount

integer — optional Number of pod replicas. Defaults to 1. Use this only when autoscaling is disabled; when autoscaling is enabled, Ryvn removes replicaCount from the rendered chart values.
config: |
  replicaCount: 3

config.image

object — optional Container image configuration.
config: |
  image:
    repository: myapp
    pullPolicy: IfNotPresent
    tag: v1.0.0

config.imagePullSecrets

array — optional Secrets for pulling images from private registries. Ryvn-managed registries: Credentials are automatically distributed to all namespaces and added to the default service account. Reference them using the {{ .ryvn.registrySecrets }} template map.
# Custom registry managed by Ryvn
config: |
  imagePullSecrets:
    - name: {{ index .ryvn.registrySecrets "my-custom-registry" }}

config.serviceAccount

object — optional Service account configuration.
config: |
  serviceAccount:
    create: true
    automount: true
    annotations: {}
    name: ""

config.podAnnotations

object — optional Kubernetes annotations for pods.
config: |
  podAnnotations:
    prometheus.io/scrape: "true"

config.podLabels

object — optional Kubernetes labels for pods.
config: |
  podLabels:
    app: myapp
    tier: backend

config.podSecurityContext

object — optional Security context for the pod.
config: |
  podSecurityContext:
    fsGroup: 2000
    runAsNonRoot: true
    runAsUser: 1000

config.securityContext

object — optional Security context for the container.
config: |
  securityContext:
    capabilities:
      drop:
        - ALL
    readOnlyRootFilesystem: true
    runAsNonRoot: true
    runAsUser: 1000

config.service

object — optional Kubernetes service configuration.
config: |
  service:
    type: ClusterIP
    port: 80
    labels: {}
    annotations: {}

config.ingress

object — optional Ingress configuration for external access.
config: |
  ingress:
    enabled: true
    className: external-nginx
    annotations:
      cert-manager.io/cluster-issuer: external-issuer
    hosts:
      - host: api.example.com
        paths:
          - path: /
            pathType: ImplementationSpecific
    tls:
      - secretName: api-tls
        hosts:
          - api.example.com

config.ingress.enabled

boolean — optional Enable ingress for external access. Defaults to false.
config: |
  ingress:
    enabled: true

config.ingress.className

string — optional Ingress class name. Must be external-nginx or internal-nginx.
config: |
  ingress:
    className: external-nginx

config.ingress.annotations

object — optional Annotations for the ingress resource. The cert-manager.io/cluster-issuer must be internal-issuer or external-issuer.
config: |
  ingress:
    annotations:
      cert-manager.io/cluster-issuer: external-issuer
      nginx.ingress.kubernetes.io/rate-limit: "100"

config.ingress.hosts

array — optional List of host configurations for the ingress.
config: |
  ingress:
    hosts:
      - host: api.example.com
        paths:
          - path: /
            pathType: Prefix
      - host: api-staging.example.com
        paths:
          - path: /
            pathType: Prefix

config.ingress.hosts[].host

string — optional Hostname for this ingress rule.
config: |
  ingress:
    hosts:
      - host: api.example.com

config.ingress.hosts[].paths

array — optional Paths for this host.
config: |
  ingress:
    hosts:
      - host: api.example.com
        paths:
          - path: /
            pathType: Prefix
          - path: /api
            pathType: Exact

config.ingress.hosts[].paths[].path

string — required URL path for the ingress rule.
path: /api

config.ingress.hosts[].paths[].pathType

string — required Path type: Exact, Prefix, or ImplementationSpecific.
pathType: Prefix

config.ingress.tls

array — optional TLS configuration for the ingress.
config: |
  ingress:
    tls:
      - secretName: api-tls
        hosts:
          - api.example.com
          - api-staging.example.com

config.ingress.tls[].secretName

string — required Name of the Kubernetes secret containing the TLS certificate.
secretName: api-tls

config.ingress.tls[].hosts

array — required List of hosts covered by this TLS certificate.
hosts:
  - api.example.com
  - api-staging.example.com

config.env

array — optional Environment variables passed to the container (in addition to the installation-level env field).
config: |
  env:
    - name: DEBUG
      value: "true"

config.resources

object — optional Container resource requests and limits.
config: |
  resources:
    limits:
      cpu: 1000m
      memory: 1Gi
    requests:
      cpu: 500m
      memory: 512Mi

config.livenessEnabled

boolean — optional Enable liveness probe. Defaults to false.
config: |
  livenessEnabled: true

config.livenessProbe

object — optional Liveness probe configuration. Only used if livenessEnabled is true.
config: |
  livenessEnabled: true
  livenessProbe:
    httpGet:
      path: /healthz
      port: http
    initialDelaySeconds: 30
    periodSeconds: 10
    timeoutSeconds: 5
    successThreshold: 1
    failureThreshold: 3

config.livenessProbe.httpGet

object — optional HTTP GET probe configuration.
config: |
  livenessProbe:
    httpGet:
      path: /healthz
      port: http
      scheme: HTTP

config.readinessEnabled

boolean — optional Enable readiness probe. Defaults to false.
config: |
  readinessEnabled: true

config.readinessProbe

object — optional Readiness probe configuration. Only used if readinessEnabled is true.
config: |
  readinessEnabled: true
  readinessProbe:
    httpGet:
      path: /ready
      port: http
    initialDelaySeconds: 10
    periodSeconds: 5
    timeoutSeconds: 3
    successThreshold: 1
    failureThreshold: 3

config.readinessProbe.httpGet

object — optional HTTP GET probe configuration.
config: |
  readinessProbe:
    httpGet:
      path: /ready
      port: http
      scheme: HTTP

config.volumes

array — optional Additional volumes for the deployment.
config: |
  volumes:
    - name: config
      configMap:
        name: app-config

config.volumeMounts

array — optional Additional volume mounts for the container.
config: |
  volumeMounts:
    - name: config
      mountPath: /etc/config
      readOnly: true

config.nodeSelector

object — optional Node selector for pod scheduling.
config: |
  nodeSelector:
    disktype: ssd

config.tolerations

array — optional Tolerations for pod scheduling.
config: |
  tolerations:
    - key: node.kubernetes.io/not-ready
      operator: Exists
      effect: NoExecute

config.affinity

object — optional Affinity rules for pod scheduling.
config: |
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
              - key: app
                operator: In
                values:
                  - myapp
          topologyKey: kubernetes.io/hostname

config.command

array — optional Override container’s default entrypoint.
config: |
  command:
    - /bin/sh
    - -c

config.args

array — optional Arguments to container’s entrypoint.
config: |
  args:
    - --port=8080
    - --host=0.0.0.0

config.preDeploy

object — optional Pre-deploy job configuration. Runs before the main deployment via Helm hooks. Use this for database migrations, seeding, cache warming, or any initialization tasks. The pre-deploy job uses the same image, environment variables, volumes, and resources as the main deployment.
config: |
  preDeploy:
    enabled: true
    run: "./migrate.sh"

config.preDeploy.enabled

boolean — optional Enable the pre-deploy job. Defaults to false.
config: |
  preDeploy:
    enabled: true

config.preDeploy.run

string — optional Simple command to run. This is the recommended way to specify what the pre-deploy job should execute.
config: |
  preDeploy:
    enabled: true
    run: "./migrate.sh"
config: |
  preDeploy:
    enabled: true
    run: "npm run db:migrate"

config.preDeploy.command

array — optional Override the container entrypoint. Use this for advanced cases where run is not sufficient. Cannot be used together with run.
config: |
  preDeploy:
    enabled: true
    command:
      - /bin/sh
      - -c
    args:
      - "./migrate.sh && ./seed.sh"

config.preDeploy.args

array — optional Arguments to the container entrypoint. Used with command for advanced cases.
config: |
  preDeploy:
    enabled: true
    command:
      - python
    args:
      - manage.py
      - migrate

config.preDeploy.backoffLimit

integer — optional Number of retries before marking the job as failed. Defaults to 3.
config: |
  preDeploy:
    enabled: true
    run: "./migrate.sh"
    backoffLimit: 5

config.preDeploy.activeDeadlineSeconds

integer — optional Maximum time in seconds for the job to run before timing out. Defaults to 300 (5 minutes).
config: |
  preDeploy:
    enabled: true
    run: "./migrate.sh"
    activeDeadlineSeconds: 600

config.persistence

object — optional Persistent volume configuration.
config: |
  persistence:
    enabled: true
    existingClaim: ""
    storageClassName: standard
    size: 10Gi
    accessModes:
      - ReadWriteOnce
    annotations: {}

config.terminationGracePeriodSeconds

integer — optional Pod termination grace period in seconds. Defaults to 30.
config: |
  terminationGracePeriodSeconds: 60

Examples

With variable groups:
kind: ServiceInstallation
metadata:
  name: api-production
spec:
  service: api
  environment: production
  variableGroups:
    - name: prod-db-credentials
With multiple variable groups:
kind: ServiceInstallation
metadata:
  name: api-production
spec:
  service: api
  environment: production
  variableGroups:
    - name: database-credentials
    - name: api-keys
  env:
    - key: LOG_LEVEL
      value: info
With pre-deploy migrations:
kind: ServiceInstallation
metadata:
  name: api-production
spec:
  service: api
  environment: production
  env:
    - key: DATABASE_URL
      isSecret: true
  config: |
    replicaCount: 3
    preDeploy:
      enabled: true
      run: "./migrate.sh"