Digital Ocean has been my personal choice of hosting since late 2015. Myself and the company I previously worked for deployed dozens of applications without any notable downtime or problems. Their documentation and community portals are extremely valuable and their companion services like Spaces are also excellent.

Craft has been my choice of CMS for about the same period of time, over which period I have had many configurations of deployment ranging from everything on a single LAMP server through to my current setup consisting of two Droplets and a Spaces instance, which we'll take a look at in this post.

Two Droplets

Each of the droplets has a single responsibility. The first droplet is a Docker deployment used to run a Postgres image. Private networking should be enabled so that the Droplet running your application is able to communicate with it. This is extremely trivial to set up - all that needs to be done is:

  1. SSH into the Droplet.
  2. Create a docker-compose.yml.
  3. Run docker-compose up -d.
  4. Whatever firewall/security considerations you want to make (e.g. IP restricting access to the Droplet).

Your database is running and accessible. The docker-compose file I use isn't indifferent from the one that the official Docker Hub page for Postgres suggests:

version: '3.1'

    image: postgres:10.4-alpine
    restart: always
      POSTGRES_USER: xxx
      POSTGRES_DB: xxx
      - ./data:/var/lib/postgresql/data
      - 5432:5432

The second Droplet is responsible for running the application. Lately I've been using NGINX and php-fpm but I have used Apache many times in the past without any problems. The main gotcha is to make sure your PHP installation includes all the necessary dependencies to connect with Postgres. Also be sure to create the Droplet in the same region as your first Droplet running Postgres (else internal networking won't be possible and you certainly do not want to connect using the public IP of the Postgres Droplet).

For application deployments I am still using a bare Git repository which I simply git push to. An appropriate post-receive hook is setup based on the specific requirements of the application, which takes care of composer dependency installations, SASS compilation, etc. This for me is the most streamlined way to iterate on something quickly during development and continues to be reliable into production.


Digital Ocean Spaces is a typical object storage service with some Digital Ocean flavour. This comes into play to alleviate some huge pain-points when working with any content-management platform: managing assets between deployments, moving the project around with all of its assets (which can become quite large), space and bandwidth restrictions and so on. Keeping the files completely separate from the project also makes room for the ability to easily load-balance your application or run it in a cluster.

Craft CMS

In the case of a Craft application which supports asset volumes via Leagues' Flysystem - we can use the Digital Ocean Spaces Volume to manage assets from the Craft control panel.

This stack has worked really well for me in my recent projects and is something I will probably stick to for at least my next few projects until I have more experience with deploying my applications as Docker images (at which point it will be trivial to move to a Kubernetes cluster because of its total separation from both the database and persistent file storage).