---
title: Configuration and Secrets Management | Shopware Community Hub
description: >-
  Learn how application.yaml, BUILD and RUN scopes, and Vault work together so
  that configuration lives in the right place and sensitive values stay out of
  Git.
canonical_url: 'https://hub.shopware.com/learn/unit/configuration-and-secrets-management'
---

# Configuration and Secrets Management

<LearningObjectives>

- Explain the role of `application.yaml`, Vault, and `.env` in Native PaaS configuration.
- Decide whether a value belongs to `BUILD`, `RUN`, `env`, `buildenv`, or `ssh` based on when it is needed.
- Use Vault to create, inspect, and manage secrets without exposing sensitive values in Git.
- Distinguish human-created from system-managed Vault entries and handle them safely.

</LearningObjectives>

# Configuration and Secrets Management

Before you create applications and deploy them, you need a clear rule for where configuration should live.

In this learning unit, you use `application.yaml` as the place for application configuration in Git, and Vault as the place for secrets that must stay out of Git. This helps you avoid one of the most common mix-ups on Native PaaS: putting sensitive values into the file, or putting build-only values into runtime by mistake.

## What Goes in `application.yaml`, Vault, and `.env`

This mental model guides the rest of the learning unit.

Use the three layers like this:

| Location           | Use it for                                      | Typical examples                                                              |
|--------------------|-------------------------------------------------|-------------------------------------------------------------------------------|
| `application.yaml` | Intentional application configuration in Git    | non-secret environment variables, enabled services, resource-related settings |
| Vault              | Sensitive values that must not be committed     | API keys, passwords, Composer auth, license material                          |
| `.env`             | Local defaults outside platform-managed secrets | non-sensitive defaults for local development                                  |

That boundary already answers an important question: `application.yaml` tells the platform **how the application should be configured**, while Vault provides the **sensitive values** that should not live in the repository.

Treat the official [Application YAML](https://developer.shopware.com/docs/products/paas/shopware/fundamentals/application-yaml.html) reference as authoritative for exact keys and additional examples.

## Configure `environment_variables` in `application.yaml`

The part of `application.yaml` that most often affects builds and deployments is `app.environment_variables`.

The file lives at the root of your project repository: `[shop_root]/application.yaml`.

This matters because it is **not** one of the YAML files inside the Shopware `config/` directory. `application.yaml` belongs to the Native PaaS application setup at repository level.

A minimal excerpt looks like this:

```yaml
app:
  php:
    version: "8.3"
  # … other application settings …
  environment_variables:
    - name: MY_BUILDTIME_VARIABLE
      value: bar
      scope: BUILD
    - name: MY_RUNTIME_VARIABLE
      value: foo
      scope: RUN
services:
  mysql:
    version: "8.0"
  opensearch:
    enabled: false
```

After changing `application.yaml`, commit, push, and apply the update with `sw-paas application update` (or your team's build-then-deploy flow).

The most important decision in this block is the `scope`. It tells Native PaaS **when** a variable should be available:

| Scope  | Meaning                                                                            |
|--------|------------------------------------------------------------------------------------|
| BUILD  | Available during image build and dependency install (Composer, asset build steps). |
| RUN    | Injected into the running Shopware PHP processes (runtime).                        |

The practical question behind the table is simple: Does the value only matter while the image is being built, or does Shopware still need it after startup?

![Diagram: BUILD scope covers image build and Composer; RUN scope covers live PHP processes; Vault maps to buildenv vs env as in the unit table](./assets/images/buildVsRunScopes.jpg)

If you keep that distinction clear, you avoid a lot of deployment confusion early. `BUILD` supports the creation of the application image. `RUN` stays relevant after the application is already running.

### Environment Variable Precedence

The same variable name can appear in more than one place. When that happens, **higher-priority sources win** (verify exact behavior in [Environment variables](https://developer.shopware.com/docs/products/paas/shopware/fundamentals/environment-variables.html)):

| Priority  | Source                                               | Typical use                                   |
|-----------|------------------------------------------------------|-----------------------------------------------|
| Highest   | **Vault** secrets (`env` / `buildenv`)               | Passwords, API tokens, `COMPOSER_AUTH`        |
| Middle    | **`application.yaml`** (`app.environment_variables`) | Non-secret defaults and per-environment flags |
| Lowest    | **`.env`** in the repository                         | Safe defaults only—never production secrets   |

This leads to a practical rule for real projects:

- Use `.env` for local and non-sensitive defaults.
- Use `application.yaml` for intentional configuration in Git.
- Use Vault for anything confidential.

That way, useful defaults stay visible in the repository, while sensitive values are injected only where they are actually needed.

This also marks an important boundary: `.env` can provide safe defaults from the repository, but it is not the platform-managed place for confidential or per-environment secrets.

<Callout title="Secrets Stay Out of Git" type="warning">

Never paste database passwords, API keys, or Composer tokens into committed YAML. Put them in Vault with the right scope (`env` vs `buildenv`) instead.

</Callout>

## Vault CLI Essentials

Vault is the Native PaaS secret store. You use it for sensitive information that must stay out of Git, for example API keys, passwords, Composer credentials, license-related values, and SSH keys.

That makes its role easier to place:

- `application.yaml` defines configuration in the repository.
- Vault stores the confidential values that should not live in the repository.

You access Vault through the `sw-paas` CLI as part of the Native PaaS platform workflow. In day-to-day work, you mainly use Vault for three tasks:

- Create a new secret.
- Inspect existing secrets.
- Update or remove secrets that your team created.

You already saw `ssh` secrets in the first course when Git access was set up. Here, the important extension is that Vault also stores other sensitive values, for example credentials for the Shopware administration, Grafana, NATS, or OpenSearch.

This is one of the practical strengths of Vault: it gives you one central place for credentials and other secrets that belong to connected systems. Instead of scattering sensitive values across files, local notes, or ad-hoc handovers, you manage them where the Native PaaS platform expects them.

If you only need browser access, use helpers such as `sw-paas open admin` or `sw-paas open grafana` instead of retrieving credentials manually.

### Commands

These are the commands you will use most often:

| Command | What it does |
|---------|---------------|
| `sw-paas vault create` | Creates a new secret entry. |
| `sw-paas vault list` | Shows which entries exist. |
| `sw-paas vault get --secret-id SECRET-ID` | Reads the current value of one secret. |
| `sw-paas vault edit` | Changes an existing secret. |
| `sw-paas vault delete --secret-id SECRET-ID` | Removes a secret. |

With these commands, you can handle the most common Vault tasks without leaving the Native PaaS workflow.

## Choose the Right Secret Type

The next question is what kind of secret you are creating.

The type determines **when** the secret is available. This matters because the same value can be correct in one phase of the workflow and wrong in another.

| Type | When it is available | Typical use |
|------|----------------------|-------------|
| `env` | Runtime | API keys, license material, runtime credentials |
| `buildenv` | Image build | `COMPOSER_AUTH`, `SHOPWARE_PACKAGES_TOKEN`, private Composer feeds |
| `ssh` | Build (Git clone) | Deploy keys for private repositories |

That gives you a simple rule.

1. Use `env` when Shopware needs the value while the application is already running. Typical examples are API keys, license-related values, or other runtime credentials.
2. Use `buildenv` when the value is only needed while the application image is being created. This is the usual place for Composer authentication and other build-time access.
3. Use `ssh` when the build needs secure repository access, for example through deploy keys during Git clone.

Choosing the right type early helps you avoid secrets that appear in the wrong phase of the workflow.

## Choose the Right Secret Scope

The secret type answers **when** a value is available. The secret scope answers **where** the value should apply.

This distinction is important because Vault secrets are reusable across applications. That is useful for shared build credentials, but risky for secrets that belong to only one environment or application.

For example, a shared Composer token may be safe to reuse during builds across several applications. A production payment API key, however, should not accidentally be available to staging, QA, or ephemeral applications. If the wrong application can read the wrong secret, the technical setup may still work, but the environment boundary is broken.

Before creating a secret, ask two questions:

1. **When is this value needed?**  
   Use `env` for runtime values, `buildenv` for build-time values, and `ssh` for repository access during the build.
2. **Where should this value be available?**  
   Reuse broadly only when the value is intentionally shared. Scope sensitive or environment-specific values as narrowly as your setup allows.

Use the current `sw-paas vault create --help` output and the [Vault documentation](https://developer.shopware.com/docs/products/paas/shopware/guides/secrets-vault-guide.html) for the exact flags and supported scope options.

### Human-Created vs. System-Managed Entries

Not every secret in Vault was created by your team. With the following command, you can get a list that shows system-managed entries, for example for storefront proxy, Grafana, or NATS:

```bash
sw-paas vault list
```

By running this command, you may see identifiers such as `STOREFRONT_CREDENTIALS`, `GRAFANA_CREDENTIALS`, `NATS_USER_CREDENTIALS`, and `STOREFRONT_PROXY_KEY`. Because Vault stores secrets for different platform services connected to Native PaaS, these identifiers can appear in different formats, for example uppercase names, underscores, or other naming patterns. The important point is not the exact format, but that Vault contains platform-managed entries in addition to the secrets your team creates.

Treat those platform-managed entries as **do not edit** and **do not delete** unless Shopware support explicitly tells you to do so. Removing them can break the application or the observability stack.

<Callout title="Vault Has No Version History" type="warning">

Vault has **no version history**. Before editing a value, back it up first with `sw-paas vault get`.

</Callout>

<Callout title="Vault Housekeeping" type="info">

Review **human-created** secrets from time to time. Remove duplicates, fix naming mistakes, and delete entries that are no longer used. Rotate credentials on a schedule that matches your security policy, for example quarterly, and capture the current value with `sw-paas vault get` before you edit it. Never include system-managed secrets in that cleanup.

</Callout>

## Common Secret Keys From Enablement

Some secret keys appear in enablement materials often enough that it helps to recognize the pattern behind them early.

The important lesson is not only the exact name, but **when** the value is needed:

| Key                       | Scope      | Role                                                   |
|---------------------------|------------|--------------------------------------------------------|
| `SHOPWARE_PACKAGES_TOKEN` | `buildenv` | Installs Shopware packages from packages.shopware.com. |
| `COMPOSER_AUTH`           | `buildenv` | Provides Composer authentication for private feeds.    |

This pattern reinforces the earlier rule:

- **Build-related** keys such as `SHOPWARE_PACKAGES_TOKEN` and `COMPOSER_AUTH` belong in `buildenv`.
- **Runtime secrets** such as API tokens, payment credentials, or integration credentials belong in Vault as type `env`.

Do not confuse Vault type `env` with the `.env` file. Use `.env` for local and non-sensitive defaults, use `application.yaml` with `scope: RUN` for non-secret runtime configuration, and use Vault type `env` for runtime secrets.

This makes the pattern easier to apply when you later read or create secrets in a real project.

## Helpful CLI shortcuts

Besides direct Vault commands, the CLI also gives you shortcuts for common destinations.

These helpers are useful when you want to open a tool directly instead of looking up credentials first:

- `sw-paas open admin`: Opens the Shopware administration page of your shop with credentials resolved via Vault.
- `sw-paas open grafana`: Opens Grafana for the selected application.

That saves time in day-to-day work and keeps Vault focused on what it is best at: Storing and resolving secrets in the background.

## Check your understanding

Use these questions to check the two core rules from this learning unit: When a value belongs to `RUN` instead of `BUILD` and when a secret belongs in Vault instead of Git.

<ArticleMultipleQuestionnaire>
  <ArticleQuestionnaire>
    <ArticleQuestionnaireQuestion>Your team adds `MAILJET_API_KEY`, used by a Symfony Mailer transport that sends order confirmation emails at checkout. Which scope should the variable have?</ArticleQuestionnaireQuestion>
    <ArticleQuestionnaireAnswer>`BUILD`, because Symfony's container is compiled and cache-warmed during the build</ArticleQuestionnaireAnswer>
    <ArticleQuestionnaireAnswer correct>`RUN`, because the running PHP processes need the value when they dispatch emails</ArticleQuestionnaireAnswer>
    <ArticleQuestionnaireAnswer>Both `BUILD` and `RUN`, so the value is available in every phase</ArticleQuestionnaireAnswer>
  </ArticleQuestionnaire>
  <ArticleQuestionnaire>
    <ArticleQuestionnaireQuestion>Your application needs `ERP_API_TOKEN` for a runtime integration, `COMPOSER_AUTH` during the build for a private plugin, and `STRIPE_SECRET_KEY` at checkout. Which placement is correct?</ArticleQuestionnaireQuestion>
    <ArticleQuestionnaireAnswer>All three as Vault secrets with type `env`, because all three values are sensitive</ArticleQuestionnaireAnswer>
    <ArticleQuestionnaireAnswer correct>`ERP_API_TOKEN` and `STRIPE_SECRET_KEY` as Vault secrets with type `env`; `COMPOSER_AUTH` as a Vault secret with type `buildenv`</ArticleQuestionnaireAnswer>
    <ArticleQuestionnaireAnswer>`ERP_API_TOKEN` and `STRIPE_SECRET_KEY` as Vault secrets with type `env`; `COMPOSER_AUTH` in `application.yaml` with `scope: BUILD`</ArticleQuestionnaireAnswer>
  </ArticleQuestionnaire>
</ArticleMultipleQuestionnaire>

## Summary

In this learning unit, you learned:

- Where `application.yaml` belongs and how it differs from Vault and `.env`.
- How `BUILD` and `RUN` scopes affect when configuration is available.
- What Vault is, how it fits into Native PaaS, and how to work with it safely.
- How to recognize common secret patterns and assign them to the right scope.

With this understanding, you can prepare Native PaaS configuration more clearly, keep sensitive values out of Git, and move into the next deployment steps with a stronger mental model.
