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.
environment
string — required
Target environment for this installation.
name
string — optional
Custom name for this installation. If not specified, uses the service name.
namespace
string — optional
Kubernetes namespace to install into. If not provided, uses the environment’s
default namespace.
releaseChannel
string — optional
Release channel to follow for this installation. If not specified, uses the
environment’s channel. Mutually exclusive with branch.
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.
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.
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.
env[].value
string — conditional (optional when using key)
Environment variable value. Cannot be set if isSecret is true.
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
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:
| Property | Type | Description |
|---|
serviceInstallation | string | Name of the service installation to get the output from. |
blueprintInstallation | string | Name of the blueprint installation to get the output from. |
name | string | (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.
config.ingress.hosts[].paths[].pathType
string — required
Path type: Exact, Prefix, or ImplementationSpecific.
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.
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"