How to deploy Craft CMS with Postgres on Heroku
Published: 2019-10-01 22:17:16

---
title: How to deploy Craft CMS with Postgres on Heroku
published: true
description: This is a step-by-step tutorial on how to get Craft CMS with a Postgres database running locally and how to get it deployed on Heroku. tags: webdev, html, postgres, tutorial
series: Deploying a new CMS at Coda
cover_image: https://cl.ly/d6a3889a1b8e/igor-miske-JVSgcV8_vb4-unsplash.jpg
---
## Moving your company blog from Medium to a subfolder
Why did I start looking into a CMS in the first place? If you are in the SEO space, chances are you've explored this issue before. There are countless [articles](https://medium.com/@pineappleaday/blog-as-domain-vs-subdirectory-which-is-better-for-seo-8582973a68c4) on the implications of having your company's blog on Medium versus a subfolder or subdomain under your main domain. Coda's [blog](https://www.blog.coda.io) is on Medium and our subdomain `blog.coda.io` points to it. This project started as a way for me to experiment with new CMSs to move Coda's blog to a new CMS and ultimately to a subfolder under Coda's main domain. 

## Other use cases for a CMS
As my team and I thought about which CMS to use, we started thinking about other requirements for the CMS. Can the CMS be used for other parts of our website? How secure is it? How does it handle image compression? Long story short, we are still experimenting and exploring different CMSs but I wanted to document my explorations with [Craft](https://craftcms.com). Heard about it from some Slack community and just started poking around and came across various [videos](https://www.youtube.com/user/mijingollc), [Stack Exchange](https://craftcms.stackexchange.com/) community, and even a [podcast](https://devmode.fm/) hosted by @gaijinity (among others). So far, so good. Lot of places I can seek help if I'm stuck. 

##Deploying on Heroku was not as easy as I thought
Speaking of places to get help, the first thing I did was try to find a good tutorial on how to deploy Craft to Heroku. I wouldn't be writing this tutorial had I found one that worked exactly as I needed it to :). The first guide that got me 75% of the way there was [this one](https://torbensko.com/posts/2019/creating-a-site-using-craftcms-heroku-and-cloudcannon/) from Torben Sko. In that guide, he or she goes into some of the Postgres stuff I'm not super familiar with. Some other resources about Craft in general:

1. **[Setting up a new Craft 3 project](https://nystudio107.com/blog/setting-up-a-craft-cms-3-project)** - Probably best overall tutorial (not about Heroku) for setting up Craft by @gaijinity  
2. **[Craft 3 Starter kit](https://github.com/edenspiekermann/craft3-heroku-starterkit)** by [Moritz Guth](https://github.com/mguth) provides a good alternative method for deploying to Heroku (using the app.json file).
3. **[Chris Hallahan](https://chrishallahan.com/blog/using-craft-cms-to-build-modern-website)** - Good guide on customizing Craft
4. **[OneSignal](https://onesignal.com/blog/craft-cms/)** - Another guide on overall benefits of Craft (see their [blog](https://onesignal.com/blog/) as an example of a blog built on Craft)
5. **[Craft Docker base](https://hub.docker.com/r/wyveo/craftcms-docker/)** - Exploring deploying on Docker next
6. **[Matt Grayisok](https://mattgrayisok.com/developing-with-craft-cms-3-in-docker)** - Another tutorial for Craft and Docker

Ok so now onto the steps that I've gathered from the above resources and just playing around with stuff. If something doesn't work or is incorrect, let me know in the comments.

## Step 1: Create a project directory and run the Craft installtion
This is for Craft 3. All instructions are on the [Craft website](https://docs.craftcms.com/v3/installation.html). Create a directory in terminal, go into that directory, and run `composer create-project craftcms/craft .` (make sure you have [Composer](https://getcomposer.org/) installed). You'll get a screen that looks like this if done correctly:
![](https://cl.ly/f2db46f0ecd7/Image%202019-09-30%20at%209.18.52%20PM.png)

## Step 2: Setup Postgres locally
A few commands here:

1. `brew install postgres` to install Postgres
2. `brew services start postgresql` to start Postgres
3. Create a super user by following the prompts after you run `createuser --interactive --pwprompt`
4. Create a database with `createdb -O [USERNAME] -Eutf8 [DATABASE]`. Replace [USERNAME] with what you created in the last step. Replace [DATABASE] with whatever you want to call your database.

## Step 3: Run Craft setup
This is simply running `craft setup` from your project directory. There was some reason to enter a tilda in front of the setup command but can't remember what it was, so for me it looked like this: `~/coda/craft-test/craft setup`. 

## Step 4: Settings asked during the setup phase 
You'll get asked a series of prompts during the setup phase. Most of the settings you can just hit ENTER for the default but there are a few to be aware of:

1. When asked for database driver, enter `pgsql`
2. Server name should be the default `localhost`
3. Port should be 5432
4. Enter the Postgres username, password, and database name from step 2 when prompted

Hit "yes" when prompted to install Craft and you'll be asked to create a Craft username and password as well for the Craft admin interface.

## Step 5: Editing the db.php file
This is code taken from [Torben Sko](https://torbensko.com/posts/2019/creating-a-site-using-craftcms-heroku-and-cloudcannon/), so just replace whatever is in your /config/db.php file with the following code:

```php
preg_match('|postgres://([a-z0-9]*):([a-z0-9]*)@([^:]*):([0-9]*)/(.*)|i', getenv('DATABASE_URL'), $matches);

$user = $matches[1];
$password = $matches[2];
$server = $matches[3];
$port = $matches[4];
$database = $matches[5];

return [
  'driver' => "pgsql",
  'server' => $server,
  'user' => $user,
  'password' => $password,
  'database' => $database,
  'schema' => getenv('DB_SCHEMA'),
  'tablePrefix' => getenv('DB_TABLE_PREFIX'),
  'port' => $port
];
``` 
This code takes the `DATABASE_URL` environment variable from your Heroku setup (which is one long URL) and parses it for the properties that Craft needs in order to make a connection with your Postgres database. More on this later.

## Step 6: Editing your local `.env` file
In order for Craft to run *locally*, you need to add the following code to your local `.env` file (which should not be committed to git):

`DATABASE_URL="postgres://[POSTGRES USERNAME]:@localhost:5432/[POSTGRES DB NAME]"`

Replace [POSTGRES USERNAME] and [POSTGRES DATABASE] with your Postgres setup from step 2. The `.env` file in your local project directory has a few variables that may be important for your Heroku setup.

## Step 7: Create a Heroku app
I'll assume you have the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli) so run `heroku create` to create a Heroku app and provision the [Postgres Heroku add-on](https://elements.heroku.com/addons/heroku-postgresql) under "Resources":

![](https://cl.ly/bbc5b0a0661f/Image%202019-09-30%20at%2010.58.20%20PM.png)

## Step 8: Edit the Config Vars in Heroku
This is one of those "gotchas" that I didn't really find in any tutorial. Under "Settings", you'll see a "Reveal Config Vars" button and this is where you'll define environment variables in Heroku (similar to the variables in your local `.env` file). 

![](https://cl.ly/557e7a6f93c4/Image%202019-09-30%20at%2010.59.55%20PM.png)

In the Config vars, you'll already see an entry for the `DATABASE_URL` from when you provisioned the Postgres db in step 7. However, you'll need to add a few variables from our *local* .env file to the *Heroku* config vars:

1. `ENVIRONMENT` should be "dev" (you will most likely change this when your website is ready for production)
2. `SECURITY_KEY` is the random string of characters in the `SECURITY_KEY` variable in your .env file
3. `DB_SCHEMA` should be "public"

## Step 9: Push your local Postgres db to Heroku
Also from the Torben Sko article, you should run the following:

1. `heroku pg:reset DATABASE_URL --app [HEROKU APP NAME]` to reset the Postgres db on Heroku (should be empty anyway)
2. `heroku pg:push [LOCAL POSTGRES DB NAME] DATABASE_URL --app [HEROKU APP NAME]` to push your local Postgres db to the Heroku

## Step 9: Create a Procfile
This is something needed for Heroku, so you just create a file at your root directory called `Procfile` with no extension and add the following line to this file:

```
web: vendor/bin/heroku-php-apache2 web
```

In other tutorials, I've seen an alternative nginx server you can add to the `Procfile`:

```
web: vendor/bin/heroku-php-nginx -C nginx_app.conf web
```

Up to you on which one to use. The latter one requires you to add another file to your root folder (`nginx_app.conf`).

## Step 10: Add the PHP ImageMagick extension to Composer
If you don't have this extension in your `composer.json` file, you'll get this error when trying to navigate to the admin page:

![](https://cl.ly/d2df9f44b405/Image%202019-10-01%20at%205.29.48%20PM.png)

Add `"ext-imagick": "*",` under the require section in your `composer.json` file like this:

![](https://cl.ly/99c0a9569d65/Image%202019-10-01%20at%205.32.10%20PM.png)

At first, you may run into an error when running `composer update` as stated [here](https://github.com/Homebrew/homebrew-core/issues/26408). I can't find the resources to solve this issue right now, but it basically involved removing a symlink to the `imagick.so` package in your /usr/local/Cellar directory and then installing the `imagick` package again with [`pecl`](https://pecl.php.net). 

Then run `composer update` in terminal. This will update your `composer.lock` file as well. It's really important to `git add` and `commit` changes at this point so that your `composer.lock` file is up to date with `composer.json`.

## Step 11: Run Craft locally with Valet
Instead of setting up MAMP or LAMP, this solution for running websites locally from [Ryan Irelan](https://www.youtube.com/watch?v=eZVIDQjp8ro) is such an easier way to go. Having futzed around before with `.htaccess` files and various permissions, [Laravel Valet](https://laravel.com/docs/5.8/valet) is by far the *easiest* solution I've used so far for getting a website up and running locally. You just run `valet link` while in your project directory and then `valet secure` to add SSL to your local website. You'll then have internal links like these below you can use to run Craft (or any project) locally:

![](https://cl.ly/707bfe796325/Image%202019-10-01%20at%205.41.54%20PM.png)

## Step 12: Finishing up
Commit all your changes and push to Heroku. If everything was setup correctly, you'll see your local `.dev` page on your Heroku remote!

![](https://thepracticaldev.s3.amazonaws.com/i/pninb5in0ypralwnkj3k.gif)

Here's my public repo in case you're interested in seeing my setup:

{% github albertc44/coda-blog %}