Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
252 changes: 252 additions & 0 deletions site/src/content/docs/best-practices/package-values.mdx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Across this PR we reference zarf package inspect, zarf dev inspect and using the values schema however none of these features are merged into Zarf as of yet. IMO we should wait until a feature is merged before documenting it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that this is addressed now

Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
---
title: Package Values
sidebar:
order: 10
---

This guide provides best practices for using [Package Values](/ref/package-values/) in your Zarf packages.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's briefly touched on in the ref document - but If I think of the ref document as the "how" and best practices as the "why" - I wonder if a good addition here could be the mention of why the use of granular sourcePath/targetPath. Security considerations and treating it as an allow list as well as traceability when we think about potential collisions with on-deployment values files and the future of imports.


:::caution

Package Values is currently an **alpha feature** and requires the `--features="values=true"` flag when creating, deploying, inspecting, or removing packages.

:::

## Organize Values Logically

Group related values together using nested structures. This makes your values files easier to understand and maintain:

```yaml
# values.yaml
app:
name: "my-app"
environment: "production"
replicas: 3

database:
host: "db.example.com"
port: 5432
name: "appdb"

monitoring:
enabled: true
retention: "30d"
```

## Use Meaningful Defaults

Provide sensible defaults in your package values files that work out-of-the-box:

```yaml
app:
replicas: 3 # Default for production
logLevel: "info"
resources:
limits:
cpu: "1000m"
memory: "512Mi"

# Optional settings with safe defaults
features:
experimental: false
debug: false
```

## Separate Environment-Specific Values

Use multiple values files for different environments:

```yaml
# values.yaml (base configuration)
app:
name: "my-app"
replicas: 1

# values-production.yaml (production overrides)
app:
replicas: 3
logLevel: "warn"

# values-development.yaml (development overrides)
app:
replicas: 1
logLevel: "debug"
features:
debug: true
```

Deploy with environment-specific values:

```bash
# Production deployment
zarf package deploy my-package.tar.zst \
--features="values=true" \
-f values-production.yaml

# Development deployment
zarf package deploy my-package.tar.zst \
--features="values=true" \
-f values-development.yaml
```

## Use Schema Validation

Define a JSON schema to validate values and catch errors early:

```json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"app": {
"type": "object",
"properties": {
"replicas": {
"type": "integer",
"minimum": 1,
"maximum": 10,
"description": "Number of application replicas"
},
"environment": {
"type": "string",
"enum": ["development", "staging", "production"],
"description": "Deployment environment"
},
"logLevel": {
"type": "string",
"enum": ["debug", "info", "warn", "error"],
"default": "info"
}
},
"required": ["replicas", "environment"]
}
},
"required": ["app"]
}
```

Reference the schema in your package:

```yaml
# zarf.yaml
values:
files:
- values.yaml
schema: values-schema.json
```

## Leverage Templating Functions

Use [functions](/ref/templating/#template-functions) for dynamic configuration:

```yaml
# In manifests with template: true
metadata:
name: {{ .Values.app.name | kebabcase }}
labels:
app: {{ .Values.app.name | kebabcase }}
environment: {{ .Values.app.environment | upper }}
version: {{ .Values.app.version | quote }}

spec:
# Use defaults for optional values
replicas: {{ .Values.app.replicas | default 1 }}

# Conditional configuration:
{{- if .Values.monitoring.enabled }}
annotations:
prometheus.io/scrape: "true"
{{- end }}
```

:::note
Conditionals are powerful but can quickly become confusing. If you find yourself needing complex conditionals, see if
you can instead express the problem with data.
:::

See the [Templating Reference](/ref/templating/) for complete function documentation.

## Do Not Commit Sensitive Values in Package

Values are the best way to pass secrets into your Zarf package, but those secrets should not be baked into the values files a package is created with:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

++


```yaml
# values.yaml
# DO NOT DO THIS
database:
password: "super-secret-password"
apiKey: "sk-1234567890"
```

```yaml
# zarf.yaml
values:
files:
- values.yaml
```

Instead, pass secret values to Zarf on deploy or remove with `-f` or by declaring the files in `.zarf-config.yaml`

```bash
zarf package deploy \
--features="values=true" \
-f production.yaml
```

or

```yaml
# ~/.zarf-config.yaml
package:
deploy:
values:
- production.yaml
```

Or set the values directly with `--set-values`,
```bash
zarf package deploy \
--features="values=true" \
--set-values=".database.password=$(DB_PASSWORD)"
--set-values=".database.apiKey=$(DB_API_KEY)"
```

Secrets can also be set dynamically by using `actions` and `setValues`:

```yaml
components:
- name: dynamic-secrets
actions:
onDeploy:
before:
- cmd: kubectl get secret db-creds -o jsonpath='{.data.password}' | base64 -d
setValues:
- name: database.password
```

## Test Your Values

Use `zarf dev inspect manifests` to preview templated resources without deploying:

```bash
# Test with default values
zarf dev inspect manifests --features="values=true"

# Test with custom values
zarf dev inspect manifests \
--features="values=true" \
-f custom-values.yaml \
--set-values="app.replicas=5"
```

This helps you:
- Verify templates render correctly
- Catch syntax errors before deployment
- Test different value combinations
- Review the final Kubernetes manifests

## Related Documentation

- [Package Values Reference](/ref/package-values/) - Complete Package Values documentation
- [Templating Reference](/ref/templating/) - Template syntax and functions
- [values-templating Example](https://github.com/defenseunicorns/zarf/tree/main/examples/values-templating) - Working examples
Loading
Loading