Deploy Shopware With GitHub Actions

This guide takes you from having no deployment pipeline to a fully automated GitOps workflow for your Shopware store on JetRails AutoPilot. Using Deployer PHP and GitHub Actions, we will set up a pipeline where pushing to your master branch automatically builds and deploys your Shopware store to production. This guide assumes you have a Shopware deployment on JetRails AutoPilot and a GitHub repository containing your Shopware project.

Dedicated GitHub Action Runner

GitHub's hosted runners use a large and frequently changing pool of IP addresses, making it impractical to whitelist them all. The recommended approach is to use a self-hosted runner whose outbound IP address you control. If you are using the JetRails AutoPilot K3s template, you can set up a self-hosted runner using Actions Runner Controller (ARC) by following the Self-Hosted GitHub Action Runners guide.

The rest of this guide assumes you have a self-hosted runner named autopilot-github-runner ready to accept workflow jobs.

Install AutoPilot Recipe

In your Shopware project's repository, install the jetrails/deployer-autopilot deployer recipe using Composer.

composer require jetrails/deployer-autopilot

This will update your composer.json and composer.lock files. You should commit these changes to your Github repository.

Create SSH Key Pair

Generate a dedicated SSH key pair for the deployment pipeline. This key will be used in your Github Action's workflow to connect to your Shopware deployment on AutoPilot:

ssh-keygen -t ed25519 -f ./deploy_key -N "" -C "github-actions-deploy"

This creates 2 files in the current directory. The public key is deploy_key.pub and the private key is deploy_key.

Whitelist & Authorize Connection

We will have to whitelist the outbound IP address of your self-hosted runner as well as authorize the SSH key (that we just made) on your Shopware deployment.

First start by going to the Overview tab of your K3s deployment in AutoPilot. There you will find the Outbound IP address of your self-hosted runner in the Network card.

Outbound IP Address of Self-Hosted Runner
Outbound IP Address of Self-Hosted Runner

Take note of this IP address and head to the Security tab in your Shopware deployment in AutoPilot. Once there, you can whitelist the outbound IP address of your self-hosted runner and whitelist the SSH port for that IP address. While you are there, also whitelist the SSH key using the contents of the deploy_key.pub file.

Authorize SSH Connection
Authorize SSH Connection

Setup Github Repository Secrets

Next, create the following Repository secrets in your Github repository under Settings > Secrets and variables > Actions:

Name Description
SSH_USER The cluster user of your Shopware deployment on AutoPilot
SSH_HOST The elastic IP address of your Shopware deployment on AutoPilot
SSH_PRIVATE_KEY The private SSH key that we generated (deploy_key)

Additionally, we will set credentials to setup a database connection since the default Shopware recipe requires it. You can find these values in the Database card on the Overview tab of your Shopware deployment in the AutoPilot dashboard.

Name Description
DB_USER The database user for your Shopware deployment on AutoPilot
DB_PASS The database password for your Shopware deployment on AutoPilot
DB_NAME The database name for your Shopware deployment on AutoPilot
Github Repository Secrets
Github Repository Secrets

Customize Deployer File

You can find an example deploy.php file here. Put this file in the root of your repository and customize it to fit your Shopware deployment.

Out of the box, you should only need to change the primary_domain to match your store's domain. The cluster_user and elastic_ip values are read from environment variables that our workflow will pass to Deployer:

set("primary_domain", "example.com");
set("cluster_user", getenv("SSH_USER"));
set("elastic_ip", getenv("SSH_HOST"));

Once you have customized the deploy.php file, you can commit it to your repository.

Create Github Actions Workflow

Create a file at this path relative to your repository: .github/workflows/deploy.yml. Put the following contents in this file:

name: Deploy

on:
  push:
    branches:
      - master

jobs:
  deploy:
    runs-on: autopilot-github-runner
    steps:
      - uses: actions/checkout@v6

      - uses: jetrails/github-actions/ssh-tunnel@v1
        with:
          ssh-user: ${{ secrets.SSH_USER }}
          ssh-host: ${{ secrets.SSH_HOST }}
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
          source-port: "3306"
          target-port: "3306"
          target-host: database.internal

      - uses: shivammathur/setup-php@v2
        with:
          php-version: '8.4'
          tools: composer

      - uses: actions/setup-node@v6
        with:
          node-version: '22'

      - name: install-system-dependencies
        run: sudo apt-get update && sudo apt-get install -y rsync

      - name: install-php-dependencies
        run: composer install --no-interaction --prefer-dist --no-dev

      - uses: deployphp/action@v1
        env:
          SSH_USER: ${{ secrets.SSH_USER }}
          SSH_HOST: ${{ secrets.SSH_HOST }}
          DATABASE_URL: mysql://${{ secrets.DB_USER }}:${{ secrets.DB_PASS }}@127.0.0.1/${{ secrets.DB_NAME }}
        with:
          dep: deploy
          private-key: ${{ secrets.SSH_PRIVATE_KEY }}

Here is a breakdown of what each step does:

  • Clones your repository onto the runner
  • Opens an SSH tunnel to your database, making it accessible at 127.0.0.1:3306 for theme compilation
  • Installs PHP and Composer (customize php-version to match your deployment)
  • Installs Node.js (customize node-version to match your deployment)
  • Installs rsync, which Deployer uses to upload files to the server (default code update strategy)
  • Installs production PHP dependencies via Composer
  • Runs Deployer using the official deployphp/action with a DATABASE_URL pointing to the tunneled connection

Once you commit this file and push to the master branch, the workflow will run automatically.

Verify Workflow Run

Once the workflow runs, you can monitor its progress under the Actions tab in your GitHub repository. Click into the run to see the details of each step. A successful run will show all steps completed with a checkmark.

Successful Workflow Run
Successful Workflow Run

Possible Optimizations

If you want your workflow runs to execute faster, consider creating a custom runner image that already has PHP, Node.js, Composer, and rsync pre-installed. This way, you can skip the setup steps and go straight to installing dependencies and deploying.