DEV Community

Cover image for Setting up OctoberCMS on Heroku
Saifur Rahman Mohsin
Saifur Rahman Mohsin

Posted on • Updated on

Setting up OctoberCMS on Heroku

OctoberCMS is one of the cleanest CMF (content management frameworks) based on Laravel that can be used to build web apps very rapidly. It's a developer-centric CMF as opposed to CMS system such as Joomla, Wordpress, etc. which are user-centric and are pretty much just over-glorified blogging platforms. And the main difference is that as a developer, you can use the CMF to build a system tailored to your client's needs i.e. you create a CMS for them to use, which may consist of CRMs, or other kinds of admin panels, settings pages, user hierarchies, etc. In this post, I will show how one can install OctoberCMS into Heroku with ease (will highlight the main changes only).

  1. Start by creating the application on Heroku and setup Heroku CLI as usual.

  2. Since OctoberCMS handles requests a bit differently, you'd be required to specify a custom nginx server configuration in the Procfile. Here's the Procfile I use:

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

    And the contents of nginx_app.conf is:

     location / {
         rewrite ^/.*$ /index.php last;
     }
    
     location ~ ^/index.php {
         try_files @heroku-fcgi @heroku-fcgi;
         # ensure that /index.php isn't accessible directly, but only through a rewrite
         internal;
     }
    
     location ^~ /.well-known/ {
         rewrite ^/.*$ /index.php last;
     }
    
     # Whitelist
     ## Let October handle if static file not exists
     location ~ ^/favicon\.ico { try_files $uri /index.php; }
     location ~ ^/sitemap\.xml { try_files $uri /index.php; }
     location ~ ^/robots\.txt { try_files $uri /index.php; }
     location ~ ^/humans\.txt { try_files $uri /index.php; }
    
     ## Let nginx return 404 if static file not exists
     location ~ ^/storage/app/uploads/public { try_files $uri 404; }
     location ~ ^/storage/app/media { try_files $uri 404; }
     location ~ ^/storage/app/resized { try_files $uri 404; }
     location ~ ^/storage/temp/public { try_files $uri 404; }
    
     location ~ ^/modules/.*/assets { try_files $uri 404; }
     location ~ ^/modules/.*/resources { try_files $uri 404; }
     location ~ ^/modules/.*/behaviors/.*/assets { try_files $uri 404; }
     location ~ ^/modules/.*/behaviors/.*/resources { try_files $uri 404; }
     location ~ ^/modules/.*/widgets/.*/assets { try_files $uri 404; }
     location ~ ^/modules/.*/widgets/.*/resources { try_files $uri 404; }
     location ~ ^/modules/.*/formwidgets/.*/assets { try_files $uri 404; }
     location ~ ^/modules/.*/formwidgets/.*/resources { try_files $uri 404; }
     location ~ ^/modules/.*/reportwidgets/.*/assets { try_files $uri 404; }
     location ~ ^/modules/.*/reportwidgets/.*/resources { try_files $uri 404; }
    
     location ~ ^/plugins/.*/.*/assets { try_files $uri 404; }
     location ~ ^/plugins/.*/.*/resources { try_files $uri 404; }
     location ~ ^/plugins/.*/.*/behaviors/.*/assets { try_files $uri 404; }
     location ~ ^/plugins/.*/.*/behaviors/.*/resources { try_files $uri 404; }
     location ~ ^/plugins/.*/.*/reportwidgets/.*/assets { try_files $uri 404; }
     location ~ ^/plugins/.*/.*/reportwidgets/.*/resources { try_files $uri 404; }
     location ~ ^/plugins/.*/.*/formwidgets/.*/assets { try_files $uri 404; }
     location ~ ^/plugins/.*/.*/formwidgets/.*/resources { try_files $uri 404; }
     location ~ ^/plugins/.*/.*/widgets/.*/assets { try_files $uri 404; }
     location ~ ^/plugins/.*/.*/widgets/.*/resources { try_files $uri 404; }
    
     location ~ ^/themes/.*/assets { try_files $uri 404; }
     location ~ ^/themes/.*/resources { try_files $uri 404; }
    

    Which was taken from the docs but modified for Heroku.

    There is an additional block:

     location ^~ /.well-known/ {
         rewrite ^/.*$ /index.php last;
     }
    

    Which can be removed unless you are running a paid plan which allows installing SSL certificates on Heroku (I will write how you can do this below).

  3. Another major difference is that you HAVE to checkin the composer.lock file. And for plugins that have their own composer.json, you may need to fetch the vendor directory and fetch those in as well as the Heroku build process doesn't seem to respect the composer-merge-plugin i.e. pulling plugin dependencies as well.

  4. And lastly, the database configuration needs to use Heroku's environment variables. I run

     php artisan october:env
    

    This creates the .env file. The good thing here is that Heroku itself creates some environment variables when you add the database as:

     heroku addons:create heroku-postgresql:hobby-dev
    

    So you don't need to do anything extra and when you commit the code, it will automatically configure itself to use the database. However, it will still throw and error initially because the database migrations wouldn't have run. To overcome this run:

     heroku run bash
     php artisan october:up
    

    This will run the command and also throw out the password for the admin user. Copy and store this since you will need this to login from the backend. Now visit the URL to open the web app.

  5. Heroku's Trust Proxy issue
    When you load the web app, you will notice that the CSS and other images are not being loaded. This is because Heroku passes the requests through a buncha reverse proxies which allow it to load balance as mentioned here. Installing this plugin will sort that out by installing a Middleware that trusts Heroku's proxies and you don't need to do any additional steps. Alternatively, you can find the plugin from your backend by searching for Mohsin.Heroku. Deploy the code and the website will work fine. Walla, that's pretty much it. Enjoy!

GitHub logo mohsin / Heroku-Plugin

Heroku plugin for OctoberCMS

Heroku Plugin

Introduction

This plugin has 2 features:

  1. A middleware class to allow OctoberCMS apps to run thro' the reverse proxy which Heroku uses.
  2. Helper to validate SSL certificates during the setup process.

Tutorial

You can find usage steps described here.




Bonus Content

Domain Setup
If you have a custom domain that you would like to set up then you can do that using PointDNS (a free addon). First enable it by running:

heroku addons:create pointdns:developer
Enter fullscreen mode Exit fullscreen mode

Now you need to configure your domain's nameserver to point to this PointDNS service. Simply run:

heroku addons:open pointdns
Enter fullscreen mode Exit fullscreen mode

And then add the domain. First head to the Heroku apps settings page and add the domain. It will return the nameserver on creation. Copy this and then click the Resources tab and open PointDNS. Click the nameserver tab and paste the nameserver into your domain host's nameserver record.

Next, use the copied DNS and add it as an Alias record. If you lost it from the clipboard, you can always run this command to get a list of domains along with the DNS name they should be pointing to (assuming you've added the custom domain in the Heroku app's Settings page):

heroku domains
Enter fullscreen mode Exit fullscreen mode

So you fill this info inside the records of your domain at PointDNS. Filling the Alias record here will make your domain work directly i.e. as yourwebsite.com rather than keeping the DNS provider somewhere else since you will be unable to set the A record to Heroku since it doesn't give a dedicated IP to point to.

SSL certificate
If you are on a paid Heroku plan and would like to add SSL certificates to your website manually rather than using their Automated Certificate Management for some reason, then the Heroku plugin has additional provisions for enabling this. First install the plugin and deploy it to Heroku. Now visit the plugin's settings page and you will reach this:
Heroku Settings Page

You need to add the challenge keys here which can be generated using certbot tool. First ensure it's installed by using:

brew install certbot
Enter fullscreen mode Exit fullscreen mode

Then manually fetch the certificate:

sudo certbot certonly --manual
Enter fullscreen mode Exit fullscreen mode

It will ask for the domain names and you can add www.yourwebsite.com and yourwebsite.com

Now it will throw out a URL and a challenge key for each domain. Copy the slug part of the URL and paste it in the challenge slug field and the challenge key in the key field. Do this for each domain and save the settings. Now go back to command line and hit enter which will validate the keys. And that's it, you have the certificates installed. You can upload them using:

heroku plugins:install heroku-certs
heroku certs:add /etc/letsencrypt/live/yourwebsite.com/fullchain.pem /etc/letsencrypt/live/yourwebsite.com/privkey.pem
Enter fullscreen mode Exit fullscreen mode

And if you are on a paid plan, it should work fine.

Discussion (0)