Setting up a Cloud Server with ddev

During the development phase of a project, we usually provide a wildcard server as a demo for our clients. No one wants to struggle with hosting setup at this point, on the other hand, a „realistic“ server setup (e.g. with RabbitMQ and ElasticSearch) is desired.

Few people are aware that ddev, a popular open source tool for launching local web development environments in minutes, can also be used for hosting on a cloud server. Setting up ddev for Shopware 6 local development in less than 5 minutes is explained here.

Read along to understand the benefits of using ddev for your demo servers, and how little it takes to set it up.

Why use ddev for a Demo Server?

Setting up (and hardening) a cloud server for Shopware 6 can be a hassle. It’s the LAMP stack, getting all the PHP settings right, setting up the vhosts, setting up the database – and you still do not have components like Redis or RabbitMQ. If you go for a cost-effective hosting, you will end up fighting the hosted servers limitations. I use ddev now since a while for my local development, and wondered whether I could use it for my demo servers as well. And yes, I can. At ddev, they call it „casual hosting“. So these are the seven major benefits I’d put on my list:

  1. The server requirements are minimal – just Linux with Docker and ddev, and a firewall. No web server, no database, not even PHP or nodejs required to install – its al integrated in ddev.

  2. ddev comes with LetsEncrypt integrated, so you will not even have to worry about SSL certificates.

  3. Excellent performance, easily matching a native installation of all components. This is because the way the components are implemented in ddev is highly optimized for performance.

  4. Installing extras like shopware-cli, RabbitMQ, ElasticSearch or redis on the server is, more or less, just activating a ddev add-on. All of this very well documented. No specific system know-how required.

  5. You may even install multiple demo sites with individual URLs on the same server, without any further configuration. No need to setup additional vhosts or similar.

  6. The effective server configuration is entirely within your ddev configuration – which means you can keep it in and track it within your project repository. No need for maintaining server specific files/settings off-repo on the server.

  7. Very simple deployment.

Step 1: Get a Cloud Server

Head over to Hetzner or DigitalOcean for a value-for-money cloud server.

In any case, what you need is a simple cloud server, based on an Ubuntu 22.04 LTS image (though any other Linux will do as well).

For safety reasons, prepare your server by creating a non-root sudo user like described here: https://www.digitalocean.com/community/tutorials/how-to-create-a-new-sudo-enabled-user-on-ubuntu-18-04-quickstart

For your convenience, you might want to allow password less sudo mode for this user – https://phpraxis.wordpress.com/2016/09/27/enable-sudo-without-password-in-ubuntudebian/

Harden your SSH access to the server as suggested here: https://www.digitalocean.com/community/tutorials/how-to-harden-openssh-on-ubuntu-18-04. You should at least disable root login and password authentication.

I recommend to use UFW as a firewall (in addition or as an alternative your cloud provider’s firewall), you may want to initialize it with

sudo ufw limit ssh
sudo ufw allow http
sudo ufw allow https
sudo ufw enable

Install Docker: https://docs.docker.com/engine/install/ubuntu/ – I recommend the install using the apt-repository, as it is much easier to keep your installation up-to-date later.

Don’t forget to follow the post-install instructions: https://docs.docker.com/engine/install/linux-postinstall/

Now install ddev following the instructions on https://ddev.readthedocs.io/en/latest/users/install/ddev-installation/#__tabbed_1_2

Eventually, point your wildcard or demo URL to the server’s IP4 address.

The following instructions assume that you are logged into your cloud server with the non-root-user credentials.

Step 2: Basic ddev Setup

Initalize ddev’s global config settings to use hardened containers and LetsEncrypt certificates (see https://ddev.readthedocs.io/en/latest/users/topics/hosting/ for more details). Just run the following command:dev config global \

 --router-bind-all-interfaces \
 --omit-containers=ddev-ssh-agent \
 --use-hardened-images \
 --router=nginx-proxy \
 --use-letsencrypt \
 --letsencrypt-email=you@example.com

This command initializes ddev’s global config file.

-router-bind-all-interfaces just applies the relevant ports to your servers public network interfaces. This is why using a firewall (and allow just ports 22, 80 and 443 for inbound traffic) is essential.

You won’t need and shouldn’t have the ddev-ssh-agent on a cloud server, so it’s omitted.

--use-hardened-images essentially switches to web container images without the sudo command, and discards the mailpit service in the web container.

--router=nginx-proxy switches the router to nginx from ddev’s default Traefik, which does, without further configuration, not support LetsEncrypt.

Finally, replace the LetsEncrypt email address with your address (this is used for renewal and other notifications by LetsEncrypt).

Step 3: Setup ddev for Your Demo Site

Create a project folder somewhere within your home folder, say

mkdir ~/<my-project> && cd ~/<my-project>

Create a new folder .ddev and within this folder a file config.yaml:

# <my-project>/.ddev./config.yaml
name: <my-project>
type: shopware6
docroot: shopware/public
php_version: "8.2"
webserver_type: apache-fpm
xdebug_enabled: false
additional_hostnames: [ ]
additional_fqdns: [ ]
project_tld: <your-wildcard-domain>
database:
    type: mysql
    version: "8.0"
working_dir:
    web: /var/www/html/shopware
use_dns_when_possible: true
composer_version: "2"
disable_settings_management: true

Replace <your-wildcard-domain> with the name of your wildcard domain, if you have one registered with Shopware. The demo server’s full URL in our example will be <my-project>.<your-wildcard-domain>.

You should now be able to run ddev start to bring up your ddev containers.

Note, should you want to run multiple Shopware instances on the same server using individual URLs, you can just repeat this step for all instances.

From here, you can either install Shopware with Symfony Flex, like described in the less-than-5-minutes installation guide. Or, if you have a local installation with ddev already, you may want to follow the deployment instructions below.

Step 4: Deployment

Note that repository based deployments will only transfer your source code to the demo server, the database needs to be initialized manually. If you have a local installation, create a database copy with ddev export-db and import it on the server side with ddev import-db. You will need to change the sales channel domains to your demo server URL using the Admin UI later.

I assume that, in your repository, you have mirrored your local project’s structure, i.e.

<my-project>
├── .ddev
├── .gitignore
└── shopware
    ├── auth.json    
    ├── bin    
    ├── composer.json    
    ├── composer.lock    
    ├── config    
    ├── custom    
    ├── .env    
    ├── files    
    ├── .gitignore    
    ├── .htaccess    
    ├── install.lock    
    ├── public    
    ├── README.md    
    ├── symfony.lock    
    ├── var    
    └── vendor

Deployment is basically two handful of steps:

  1. On the runner

    • composer install -d shopware

    • shopware/bin/ci bundle:dump

    • shopware/bin/ci feature:dump

    • shopware/bin/build-js.sh

    • rsync your project sources from the repository to the destination at ~/<my-project>/shopware

    • optionally, also rsync your .ddev sources to the server

  2. On the server side, run

    • ddev restart (a safe means to reset all php caches, mandatory if you update your .ddev settings)

    • ddev exec bin/console theme:compile

    • ddev exec bin/console assets:install

    • ddev exec bin/console cache:clear

In addition to the .env file auto-generated by composer create-project, you will need a .env.local file similar to this one:

# <my-project>/shopware/.env.local
APP_ENV=prod
APP_DEBUG=0
APP_URL=${DDEV_PRIMARY_URL}
DATABASE_URL=mysql://db:db@db:3306/db
MAILER_DSN=null://null

Note that the MAILER_DSN setting reflects the fact that, because you are using the hardened ddev images, mailpit is not active on your demo server. You may want to use a tool like mailtrap.io instead.

Step 5: Automatic Start of ddev Containers

To automatically start your ddev containers at system startup, add and enable a systemd service.

sudo nano /etc/systemd/system/ddev.service
# /etc/systemd/system/ddev.service
[Unit]
Description=DDEV sites
After=network.target
Requires=docker.service
PartOf=docker.service

[Service]
User=<non-root-user>
WorkingDirectory=~
Type=oneshot
ExecStart=/usr/bin/ddev start --all
RemainAfterExit=true
ExecStop=/usr/bin/ddev poweroff 

[Install]
WantedBy=multi-user.target

Replace <non-root-user> with your username. Save the file and run the following commands to activate and enable the service at system boot. The next time you (re-)start your server, this service will start all ddev containers.

sudo systemctl start ddev.service
sudo systemctl enable ddev.service

What’s next?

Watch out for more to come:

  • Add extra components like RabbitMQ, Redis and ElasticSearch

Last updated