---
title: Preparing Your Project Repository | Shopware Community Hub
description: >-
  Prepare a Shopware project for Native PaaS by treating Git and Composer as the
  source of truth, adding shopware/paas-meta , handling Composer auth securely,…
canonical_url: 'https://hub.shopware.com/learn/unit/preparing-your-project-repository'
---

# Preparing Your Project Repository

<LearningObjectives>

- Explain why Native PaaS builds must be reproducible from Git and Composer.
- Prepare a Shopware repository and identify the artifacts required for reproducible builds.
- Provide secure access to private dependencies using Vault-backed Composer authentication.
- Design file handling for object storage instead of local disk.

</LearningObjectives>

# Preparing Your Project Repository

Before you think about configuration or deployment, your repository has to match how Native PaaS actually builds applications.

This matters because the platform rebuilds your project from Git and Composer. If something is missing there, the next build will not reliably reproduce it.

In this learning unit, you prepare that baseline. You look at why Composer and Git are the source of truth, how `shopware/paas-meta` fits into the project, how private package access is handled securely, and why durable files must go to object storage instead of local disk.

## Why Git and Composer Are the Source of Truth

Native PaaS runs your application on more than one container instance. That means the code installed on those instances must be predictable and consistent.

The build pipeline resolves **what to install** from Git, Composer, and the lockfiles that describe the exact dependency state:

```mermaid
flowchart LR
  subgraph repo["Your repository"]
    C[composer.json / composer.lock / symfony.lock]
    P[custom/plugins and config]
  end
  subgraph platform["Native PaaS"]
    B[Build: Composer, vendor, assets]
    D[Deploy: same code on all instances]
  end
  repo --> B --> D
```

This is the core mental model for the rest of the learning unit: Every instance that serves traffic must run the same application code and dependency set.

### Why Extensions Must Be Added Through Composer

Installing an extension only through the Shopware administration UI is not a good primary workflow on Native PaaS. In a highly available setup, multiple instances can serve traffic at the same time, and they all need the same extension code.

Use `composer require`, update the relevant lockfiles, and merge that change to your main or deploy branch as the canonical workflow. That way the build can install the same dependency set for every instance.

Runtime extension management is **disabled by default** in the Shopware administration on Native PaaS. If you need **in-app Extension Store** purchases, add the store integration through Composer as well, for example with `composer require shopware/swag-extension-store`, and follow the current product documentation.

The important rule stays the same: Server-relevant extensions must be part of the Composer-driven build, not a one-off runtime change on one instance.

## Start With `shopware/production` and Add `shopware/paas-meta`

The [shopware/production](https://github.com/shopware/template) template is Shopware's official Composer-based starting point for a new Shopware project. You can think of it as the standard project template and repository baseline for a production-ready Shopware application.

Once that project exists locally, you prepare it for Native PaaS with `shopware/paas-meta`. This package connects the project to the Native PaaS expectations used in your enablement flow.

The usual workflow is simple:

1. Choose the parent directory where you want the project to live.
2. Create a new Shopware project from `shopware/production`.
3. Move into the new project root, and then require `shopware/paas-meta`.

```bash
cd /path/to/your/projects
composer create-project shopware/production my-shop-project
cd my-shop-project
composer require shopware/paas-meta
```

If your project also needs other first-party Native PaaS integration packages, add them in the same Composer-driven workflow.

If you are starting from an existing Shopware project instead of a fresh template, the idea is the same: move into the project root first and then add `shopware/paas-meta` there.

Once the project is set up, these are the key files and folders you should check in your repository:

- `composer.json`: Defines which dependencies the project requires.
- `composer.lock`: Records the exact resolved versions used for reproducible builds. In practice, `composer install` uses this file to install the locked versions.
- `symfony.lock`: Records Symfony Flex recipes and package integration state that can affect the generated project structure.
- `custom/plugins`: Regular plugin location, especially for plugins installed or managed through the Shopware administration. Do not treat manually copied plugin code here as the primary source of truth on Native PaaS.
- `custom/static-plugins`: Recommended location for project-specific static plugins that are typically committed with the project. The Shopware Administration does not detect them automatically; require them via Composer using the package name from the plugin's `composer.json`.
- `application.yaml` and other Shopware configuration files that affect build and runtime. You will work through those files in detail in the next course.

During the build, Composer uses those files to create the installed `/vendor` directory. That installed vendor code is what the running application actually uses, so the lockfiles and the resulting `/vendor` content must match across all instances that serve traffic.

## Access Private Composer Packages via Vault

Many real projects do not install packages from one source only. Agencies often use a mix of Shopware packages, private VCS repositories, and artifact endpoints.

If your project uses private packages, the build on Native PaaS also needs access to them. Without that access, Composer would fail during the build even if the project works on your local machine.

Native PaaS handles this through Vault-managed Composer authentication. Common examples are:

- `shopware_packages_token` (buildenv) — Shopware packages; this is normally created automatically when the organization is created in SBP.
- `composer_auth` (buildenv) — Composer HTTP basic or token auth for private feeds

Configure additional Composer credentials in Vault; never commit raw tokens to Git.

This keeps sensitive credentials out of Git while still making them available during the build. In other words, Native PaaS gives the build the access it needs without forcing you to store secrets in Git.

## Design for Object Storage, Not Local Disk

On Native PaaS, you should not treat the container filesystem as permanent storage. Files written there can disappear on rebuild or redeploy.

For durable files such as media and uploads, Native PaaS provides object storage. Each application receives dedicated S3 buckets, and some shared buckets may exist at organization level for shared assets. More on that comes in the operations course.

This matters especially for plugins. If a plugin hard-codes paths such as `/var/www/html/public/media` or assumes a local NFS mount, persistent file handling will simply not work as expected on Native PaaS. Use Shopware’s filesystem abstraction with object storage instead.

<Callout title="Debugging Tip" type="info">

If a plugin writes where the OS user lacks permission, logs and Grafana often show permission denied or read-only filesystem symptoms—fix by storage adapter configuration or plugin change, not by chmod on the container.

</Callout>

**Rule of thumb:** Design media, uploads, and plugin file handling for object storage from the start.

## Use Ephemeral Applications for Short-Lived Checks

Once the repository is prepared, one useful first use case is a short-lived environment for quick validation. That is where ephemeral applications fit.

Sometimes you want to test a feature branch, run a QA check, or reproduce a production issue without touching your long-lived staging setup. Ephemeral applications are made for this kind of temporary validation. They give you a separate environment for a short period of time and are cleaned up automatically by the platform.

Do not treat an ephemeral application like a small staging environment that will reliably still be available the next day. The cleanup is automatic, and the actual available time depends on when the cleanup runs. If an ephemeral application is created shortly before the next cleanup, it may only be available for a few hours.

Use ephemeral applications for quick checks during an active development or review session. For longer QA phases, customer handovers, or reviews across multiple time zones, use a more stable environment instead.

This is only a first orientation. You will work with application creation and deployment flow in more detail in the following units.

## Check Your Understanding

Use these questions to verify the two core rules from this unit: Native PaaS needs the same code and dependency state across all running instances, and durable files belong in object storage, not on local disk.

<ArticleMultipleQuestionnaire>
  <ArticleQuestionnaire>
    <ArticleQuestionnaireQuestion>A merchant has migrated from self-hosted Shopware to Native PaaS. They used to install plugins through the Shopware administration, but on Native PaaS the extension install controls are not available. They ask how to add the `SwagPaymentPayPal` plugin. What is the correct guidance?</ArticleQuestionnaireQuestion>
    <ArticleQuestionnaireAnswer>Open a shell on a running pod with `sw-paas exec`, run `composer require swag/paypal`, and restart the application</ArticleQuestionnaireAnswer>
    <ArticleQuestionnaireAnswer correct>Add `swag/paypal` to the project's `composer.json` in the connected Git repository, commit the change, and trigger a new deploy</ArticleQuestionnaireAnswer>
    <ArticleQuestionnaireAnswer>Ask Shopware to enable plugin installation in the administration for that organization, then install it from the UI</ArticleQuestionnaireAnswer>
  </ArticleQuestionnaire>
  <ArticleQuestionnaire>
    <ArticleQuestionnaireQuestion>A custom plugin uploads signed PDF contracts to customer accounts. On the old self-hosted setup it wrote them to `public/files/contracts/`. On Native PaaS, some downloads return 404 on the same day, and after an overnight deploy all contracts are gone. What is the fix?</ArticleQuestionnaireQuestion>
    <ArticleQuestionnaireAnswer>Configure a persistent volume mount for `public/files/contracts/` in `application.yaml` so the directory survives pod restarts and rebuilds</ArticleQuestionnaireAnswer>
    <ArticleQuestionnaireAnswer correct>Refactor the plugin to write through Shopware's filesystem abstraction, which is backed by object storage on Native PaaS</ArticleQuestionnaireAnswer>
    <ArticleQuestionnaireAnswer>Move the files to `/tmp/contracts/` and add a cron job that copies them into the public directory whenever a pod starts</ArticleQuestionnaireAnswer>
  </ArticleQuestionnaire>
</ArticleMultipleQuestionnaire>

## Summary

In this learning unit, you learned:

- Why Git, Composer, and lockfiles define the dependency state that all running instances should share.
- How to start from `shopware/production`, add `shopware/paas-meta`, and identify the key repository parts the platform depends on.
- How Vault-based Composer authentication gives the build secure access to private packages without putting secrets into Git.
- Why media and uploads must be designed for object storage instead of local disk.
- When ephemeral applications are useful as a first short-lived validation step after the repository is prepared.

With this foundation, you can prepare a repository that leads to a predictable build and a consistent application state across the instances that serve traffic.
