(Image: Header Graphic)

Thursday, April 18, 2024

Doug's Domain

Doug Vetter, ATP/CFI

Like what you see?

Donations to dvatp.com are now processed via Stripe. Like this site? It's easier than ever to show your appreciation.

Installing October CMS on Debian with Postgres, Nginx and PHP5-FPM

(Image: October CMS Backend Desktop Screenshot)

Introduction

I recently had to deploy a new website. As a developer with Laravel experience I naturally gravitated toward the idea of building the app on top of Laravel. But the available timeframe precluded doing anything from scratch so I quickly ruled that out.

Since the site was to consist largely of static content I initially considered Jekyll but that proved too restrictive as I wanted the ability to evolve the site down the road into a fully dynamic, SQL-based backend to support user logins, comments, forums, file upload, etc. That got me thinking about a CMS on top of Laravel.

Surely, I assumed, there must exist a simple CMS app for Laravel that would allow me to remotely edit static content and generally make my life easier. Unfortunately I only found one such animal and by admission of its developer the software wasn't really ready for prime time.

So I continued to Google for "laravel" and "cms", which lead me to October CMS. A cursory overview including reading the forums and looking over the GitHub project issue list I didn't see any deal-killers, so I decided to try it out.

This document reflects my experience installing the application on my current go-to Linux distribution: Debian 8. And while I have many years of experience deploying apps on Apache, I've been deploying more systems recently on Nginx, so I decided to do that here too. I need to be up front, however, and say that my experience with October was not all positive. I recommend you read the Notes and Advisories section before you follow in my footsteps.

Install OS Packages

Install some packages:

# apt-get install nginx
# apt-get install php5-fpm
# apt-get install postgres-9.4
# apt-get install php5-pgsql

Note that the postgres-9.4 package will install both server and client.

Verify postgres and nginx are running before continuing.

 # ps -ef | grep postgres

and

# ps -ef | grep nginx

Nginx will have to be restarted later after it is configured but for now it's a good idea to sanity check the default configuration by browsing to the host and verifying the introductory page is shown.

Configure Postgres

Become the postgres user:

# su - postgres

Create a postgres database user called octo. I made the user a superuser but that's probably not strictly necessary or wise for production. The main benefit of that permission is the ability to create / delete databases. As October expects the database to be created up front (in other words, it doesn't do what some applications like Odoo do and ask you for the database name so it can login to the database server and create the database for you), omitting the -s is probably a good idea. Use your own judgment.

$ createuser -s octo

Still as the postgres user, call the psql application and select the template1 (default) database to assign a password to the octo user. Note that this should be something hard to guess and should include special characters, etc. Don't do something formulaic or stupid like "octo" or "admin":

$ psql template1
template1=# ALTER ROLE octo WITH PASSWORD 'octoxyzzycms1!';

Then create the database and assign ownership to it to the octo user we just created:

template1=# CREATE DATABASE octodb WITH OWNER octo;

These database commands should echo something back to the console like ALTER ROLE or CREATE DATABASE, respectively. If not, nothing has happened and you probably forgot to add the semicolon at the end of the command.

Verify the database just created is in fact present:

template1# \l

By the way, that command consists of a backslash and a lower case "L", which means "list databases". This should produce output similar to the following:

template1=# \l
List of databases
Name   | Owner | Encoding | Collate     | Ctype       | Access privileges
-------+-------+----------+-------------+-------------+------------------
octodb | octo  | UTF8     | en_US.UTF-8 | en_US.UTF-8 |

If you don't see the octodb database in that listing it's time to troubleshoot.

Configure Application Database Credentials

Change:

  /home/labsweb/october/config/database.php

to select pgsql as the default driver and change the appropriate parameters in the connections section, pgsql stanza:

  'pgsql' => [
  'driver' => 'pgsql',
  'host' => 'localhost',
  'port' => '5432',
  'database' => 'octodb',
  'username' => 'octo',
  'password' => 'octoxyzzycms1!',
  'charset' => 'utf8',
  'prefix' => '',
  'schema' => 'public',
  ],

Install October

Create a regular user to own the october CMS code. In this case I'm calling it "octoweb".

# adduser octoweb

Switch to that user via:

# su - octoweb

In the home directory of that user, e.g. /home/octoweb, call the following command to populate the project via composer. If composer is not installed, do that now. I typically put it in /usr/local/bin to separate it from packaged tools that are typically installed in /usr/bin.

Exit root if necessary, and then, as octoweb execute the following command while in the home directory:

  $ composer create-project october/october october dev-master

This download may also trigger github's throttling, in which case you will be prompted to enter your github credentials. Register for an account if needed.

Seeding the Database

To seed the database, in the top level of the source tree, as the code owner:

  $ php artisan october:up

This should output something similar to this:

Migrating application and plugins...
Migration table created successfully.

System

 - Migrated: 2013_10_01_000001_Db_Deferred_Bindings
 - Migrated: 2013_10_01_000002_Db_System_Files
 - Migrated: 2013_10_01_000003_Db_System_Plugin_Versions
 - Migrated: 2013_10_01_000004_Db_System_Plugin_History
 - Migrated: 2013_10_01_000005_Db_System_Settings
 - Migrated: 2013_10_01_000006_Db_System_Parameters
 - Migrated: 2013_10_01_000007_Db_System_Add_Disabled_Flag
 - Migrated: 2013_10_01_000008_Db_System_Mail_Templates
 - Migrated: 2013_10_01_000009_Db_System_Mail_Layouts
 - Migrated: 2014_10_01_000010_Db_Jobs
 - Migrated: 2014_10_01_000011_Db_System_Event_Logs
 - Migrated: 2014_10_01_000012_Db_System_Request_Logs
 - Migrated: 2014_10_01_000013_Db_System_Sessions
 - Migrated: 2015_10_01_000014_Db_System_Mail_Layout_Rename
 - Migrated: 2015_10_01_000015_Db_System_Add_Frozen_Flag
 - Migrated: 2015_10_01_000016_Db_Cache
 - Migrated: 2015_10_01_000017_Db_System_Revisions
 - Migrated: 2015_10_01_000018_Db_FailedJobs

Backend

 - Migrated: 2013_10_01_000001_Db_Backend_Users
 - Migrated: 2013_10_01_000002_Db_Backend_User_Groups
 - Migrated: 2013_10_01_000003_Db_Backend_Users_Groups
 - Migrated: 2013_10_01_000004_Db_Backend_User_Throttle
 - Migrated: 2014_01_04_000005_Db_Backend_User_Preferences
 - Migrated: 2014_10_01_000006_Db_Backend_Access_Log
 - Migrated: 2014_10_01_000007_Db_Backend_Add_Description_Field

Cms

 - Migrated: 2014_10_01_000001_Db_Cms_Theme_Data

Seeded System
Seeded Backend

Nginx Configuration

On Debian I placed my configuration file here:

/etc/nginx/sites-available/mysite-ssl

This file contains only a server stanza and is merely sourced by the main nginx configuration file located here:

/etc/nginx/nginx.conf

So unlike on an apache installation where you have to dink around with symlinks, this works out of the box, assuming of course you have configured everything correctly. The main nginx configuration file must be tweaked accordingly after learning about the various options. There is really no one size fits all here, though the default settings will work for a trial run and basic development.

I set the user in that file to octoweb.

As a result of that I had to change ownership of the fastcgi directory:

# chown -fR octoweb:octoweb /var/lib/nginx/fastcgi

If this step is not taken Nginx will report a 500 error and the error log will indicate something similar to the following:

  2015/11/12 18:04:44 [crit] 17266#0:
  *9 open() "/var/lib/nginx/fastcgi/4/00/0000000004" failed (13: Permission denied)
  while reading upstream,
  client: 1.2.3.4,
  server: www.mydomain.com,
  request: "GET /combine/4fde16f72d7215b8f3c08903634-1447349533 HTTP/1.1",
  upstream: "fastcgi://unix:/var/run/php5-fpm.sock:",
  host: "www.mydomain.com:444",
  referrer:"https://www.mydomain.com:444/"

Naturally, I also modified the "listen" directive to set the port on which the server would respond to requests. Initially this was set to a random value as my development host was living on a VPS accessible from the net. I eventually changed this to 443 to deploy using TLS / SSL.

PHP5-FPM Configuration

Nginx lacks a built-in PHP interpreter like Apache provides via mod-php. Therefore Nginx serves as little more than a proxy to a PHP interpreter sitting in the background waiting for some PHP code to process. On Debian that interpreter is provided by the PHP5-FPM package.

Like Nginx, PHP5-FPM by default runs as a non-privileged user and on Debian systems this is "www-data". This user is by default tweaked to disallow shell logins, and rightfully so. However, as I had code stored in the user's home directory and needed shell access to it I decided to run PHP5-FPM as the same user that owned the Nginx process: octoweb. This required modification of the PHP5-FPM configuration file:

/etc/php5/fpm/pool.d/www.conf

and changed the following parameters:

user = octoweb
group = octoweb

I then changed permissions of the special socket file so that requests by Nginx would not be refused.

# chown octoweb:octoweb /var/run/php5-fpm.sock

Using a Public Directory (Production Servers Only)

If you're coming to October with prior experience with Laravel it may throw you for a loop when you realize the October devs eliminated the public folder. People complained loudly enough and the October developers created an artisan command to mirror (symlink, really) the appropriate assets into a public folder that can then be referenced by the webserver.

To mirror assets whenever a change occurs the following command must be executed from the top of the source tree:

$ php artisan october:mirror public

That is perfectly acceptable for a production server where the updates occur relatively infrequently and deliberately as part of a formal process to update the system. It's a pain in the ass during development, however, so I'd generally recommend using a public directory on a production server only.

Security and Permissions with Split Users (Not Recommended)

For security reasons I initially attempted to provision my October installation like I do most web apps -- the code resided outside the Document Root and was owned by a different (non-privileged) user than the one that owns web server or php interpreter processes. This naturally created a permissions conflict.

It is normally possible to address these issues through a careful and deliberate tweaking of the permissions, creating a group to share assets, etc. Unfortunately in the case of October this created a permissions hell that I never quite felt comfortable deploying, so I didn't go in this direction. However, I present this work as a possible starting point for users that absolutely insist on this security architecture.

Permissions must be set correctly or a variety of problems can and will occur:

  1. If the october/storage/logs/system.log file isn't writeable by the web server process owner you'll get a blank page. The only clue to this error will exist in the nginx error log, which is typically /var/log/nginx/error.log.

  2. If october/storage/app/cache files and related directories aren't writeable the application will complain about it before it actually starts up or lets you login to the backend (URL: /backend). You'll probably get a stack trace in this case and you'll have to read the specifics of the trace to figure out what's wrong.

  3. If the themes and plugins directories aren't provisioned with write permissions, attempts to automatically download and install themes and plugins from the backend interface will fail with a coherent message provided in a warning dialog.

  4. If anything else is not set correctly you'll be able to login to the backend but the application will show a bunch of "System configuration tips" outlining each problem area. These are the easiest issues to identify because they're explained in English with the full path at issue, but they won't necessarily be easy to correct permanently.

  5. During multi-day running of the application, as cache files expire and new ones get created the application may fail with a stack trace complaining about an inability to write cache files to october/storage/framework/cache.

I addressed these problems by using a combination of commands designed to make it possible for the codebase to owned by one user and yet writeable in selected areas by another user. To apply these changes recursively and persistently I had to set the sticky bit on the group mask and set ACLs to ensure that the group mask was set correctly whenever new directories or files were created.

A quick note on ACL support in Linux:

ACL support must be enabled in the kernel configuration, be supported by the filesystem in use (like ext4) and enabled with the options used to mount the filesystem (see /etc/fstab). Provisioning the operating system to support ACLs is beyond the scope of this article but I will volunteer that you'll need the acl package (not installed by default on Debian 8) which provides the command line utilities necessary to create/modify/delete ACLs:

# apt-get install acl

I began by changing the owner and group to the owner of the code (octoweb) and the group to which the PHP interpreter belongs (www-data in the case of PHP5-FPM on Debian).

I then issued the following commands, substituting each of the following paths as required:

october/themes
october/storage
october/plugins
  1. The first command simply configures the owner and group:

    # chown -fR octoweb:www-data <dir>
  2. The following ACL statement changes the default group mask from 5 (r-x) to 7 (rwx) on all directories under that directory.

    # cd thedir && find . -type d -exec setfacl -d -m g::rwx {} \;
    

    where thedir is the directory to be changed.

  3. The sticky bit is then set on all directories. The effects of the sticky bit are normally recursive but they only apply to directories and files created after the top-level directory has been modified with the sticky bit. As the affected directories are populated already the commands find all subordinate directories and add the sticky bit to them as well...

    # cd /home/octoweb/october/thedir && find . -type d -exec chmod 2775 {} \;
    

While these changes were enough to make things work at least temporarily, hacking so many files and directories left me wondering about the security of the system. I did not have the time to verify the security of these changes so I ultimately took the easy way out, installed the application in the "recommended" way, i.e. in Document Root, and paid particular attention to the webserver configuration so as to ensure direct access to sensitive assets was not possible.

Logging Into Adminstrative Backend

Simply browse to:

http://www.mydomain.com/backend

or if using SSL running on the default port of 443:

https://www.mydomain.com/backend

This should present a login dialog. Use:

Username: admin
Password: admin

And then, assuming no configuration errors are present, the first priority should be to change the admin password to something less guessable.

Content may now be provisioned.

Theme Development Issues and Installing Gulp

Although beyond the scope of "installation" I figured I'd mention a few issues I encountered doing the very first thing a typical administrator / developer would do with a new October installation: create a custom theme for their website.

Given that October's theme structure was completely foreign to me I used the backend GUI to duplicate the demo theme, renamed it accordingly, activated it, and started modifying it beginning with the layout and markup first, followed by the CSS.

I ran into a snag after I realized that I'd come to rely on gulp and Elixir in Laravel to build my assets (js, css, etc.): Elixir doesn't exist in October, and Gulp/Grunt, etc. aren't configured or even mentioned in the documentation as alternatives.

If you have read some of the October documentation you might be asking why do I need gulp, etc. when October has a built-in compiler? Because the built-in compiler sucks. It only speaks less, only compiles the top level file "theme.less", does not appear to compile the files imported by that file if they're changed, and does not support any kind of minimization for production. But ya know, I don't want October to do any of this. I want the October devs to integrate existing tools like Elixir.

I found a couple forum posts in which people claimed they had integrated Elixir with October but they did not provide any details and I frankly didn't have the time required to blaze the trail here. So I did the next best thing: install and configure gulp manually. Fortunately I had done that before on the pre-Elixir Laravel 4 and for my purpose the required configuration was minimal.

First I grabbed npm. The version in the debian package repository is older than the version on the node site but I refused to launch the install.sh script as root and have it shove files into every orifice of my OS. So I installed the older version of NPM (globally) via apt-get:

# apt-get install npm

The only effects of using the older version will be incessant, verbose nagging from npm when you install other packages that npm itself is out of date. As an aside, I think npm's dependency chain output is too verbose for routine use -- all I want to see is "package: installed" or "package: install failed", but that's another story. Some developers like to see the world burn in a sea of needless complexity.

Then I installed gulp globally, which of course requires root permissions:

# npm install -g gulp

I then initialized the node environment from within the theme directory:

$ cd /home/octoweb/october/themes/mytheme
$ npm init

Then follow the prompts.

Note that the package.json file generated by this process will be created in the directory in which npm init is executed, so in this case that's the top-level theme directory. This is another thing you have to remember if you're coming from Laravel: in October everything is driven to be modular (plugins, themes, etc.) so node packages required for a particular plugin or theme must be installed only in the context of those components rather than in the top level of the source tree.

Since October's default themes use less I installed one additional gulp dependency, gulp-less:

$ npm install gulp gulp-less

These files will be installed in a new directory:

october/themes/mytheme/node_modules

Once those packages were installed I created a simple gulpfile.js:

  var gulp = require('gulp');
  var less = require('gulp-less');

  // Compile Less into CSS
  gulp.task('less', function() {
    gulp.src('assets/less/*.less')
       .pipe(less())
       .pipe(gulp.dest('assets/css'))
  });

  gulp.task('default', ['less']);

At this point compiling the less files into a css file (theme.css) is as easy as being in the top-level directory of the theme in question and typing gulp with no arguments at the command line.

Notes and Advisories

While this is not a review of October, I think it's important to point out a few things I learned during my initial installation and testing of the platform.

  1. This is October. Not Laravel.

    If you come to the platform expecting Laravel (and you would not be alone as the platform is advertised as being based on Laravel), you will be seriously disappointed. Most of my criticisms are, therefore, based on the expectation that a good portion, if not the entirety, of Laravel's capabilities and conventions would be respected by October. They are not.

    The October devs cherry picked the Laravel framework / core and discarded everything else. I don't really care for their justifications as to why they have done this. I will merely state the obvious -- this clearly isn't Laravel and I believe it is disingenuous of the October project to bill itself as a Laravel derivative. It's a completely different platform with its own design goals and ambitions. That's good for them but it sucks for Laravel devs coming to the platform expecting to leverage their knowledge of Laravel. Will Laravel knowledge help you to develop plugins in October? Sure. Eloquent is used, after all. But the similarities end there.

    To be fair, Taylor has made some annoying and controversial design decisions with Laravel over the years as well (particularly with Version 5 where I continue to bang my head on the wall wondering what he was thinking), but he's been justified in my opinion because he's blazed his own trail, and he didn't advertise Laravel as being based on Symfony despite using many of its components. So Symfony devs weren't tricked into thinking Laravel would in any way function like Symfony.

  2. The application is expected to live in Document Root. Yes, really.

    The application source tree must effectively live in Document Root, owned by the web server process and the web server configured to prohibit access to selected assets within the source tree, otherwise the permissions headaches border on the extreme.

    The addition of the artisan mirror command in response to the complaints of many is both half baked and a serious inconvenience during development. Every time a change is made to the static assets of a theme or plugin this command must be executed to make them available in the public directory. And that's in addition to calling gulp or whatever other asset processing that may be required. That will get tedious in development quickly.

    And if you're trying to use the split-user model to address security concerns good luck with that. The mirror command uses the permissions of the caller including the default umask, which are incorrect for a split user environment. More to the point, it does not do any of the ACL provisioning that is necessary to make it all work.

    What the hell is this, 1998? Excuse me a moment while I load another Plutonium pellet so I can activate the flux capacitor and get back to the future. No application should be designed to live in Document Root, no matter how convenient that is for developers or even if it is the only way to support "live" installations of content downloaded from the web -- something I consider a huge security risk in itself. I don't really give a shit about your platform and your quest to dumb-down the installation process to the point that administrators who lack the brains to do anything but enter a credit card number and click "install" can work with it. The security of my web server is paramount.

  3. The application does not make it easy to run the backend and front end on different ports.

    For security reasons I always run the backend of a CMS on a random port different from the front end. This is nothing more than security by obscurity, but in my experience it thwarts 99% of the script kiddies looking for common attack vectors like a url called "/backend". Plus it keeps the logs clean so I can see the real attacks.

    October should separate backend requests into a different entry point like backend.php. Then, in Nginx anyway, it's just a simple matter of provisioning two server stanzas -- one looking at port 80 or 443 for the front end and another looking at some random port for the backend, and writing a single location stanza within each server stanza to handle index.php and backend.php respectively.

    Being somewhat new to Nginx and very new to October it took a bit of trial and error to get my system functioning in this way despite the single entry point but I was able to make it work. Whether my solution is thoroughly secure is another issue entirely. Complexity in the server configuration breeds insecurity, particularly given that October expects to live in Document Root, so separating the frontend and backend entry points is the better design choice.

  4. No easy way to disable caching or remove the caching model.

    I find the inability to completely disable caching to be a serious problem, particularly during development. I do not want my static asset filenames changed during development (and sometimes even during production) because this needlessly complicates debugging.

    After two years of development and more than a few complaints from the community October still doesn't have a top-level switch to disable all caching -- or better yet a way to remove the caching model entirely -- and serve the assets as is. The best you're going to get is an artisan command (cache:clear) or if you want to be fancy, a plugin that installs a widget on the backend dashboard to show the current state of the cache and provide a means to clear it.

    Newsflash: caching is simply not required for all projects. I'm not deploying a "Facebook" or a "Reddit" on CDNs. In reality, few people ever do deploy applications like that and if they do, they sure as hell won't be using October.

  5. Twig instead of Blade.

    The October devs chose to replace Laravel's blade templating engine with Twig. I won't be drawn into a discussion of which is the better templating engine. I will, however, state the irrefutable -- they are different. Different means yet more time spent learning another system and its inevitable quirks. And yes, blade has them too, but as a Laravel developer I already know what they are.

    I don't know at this point whether it is realistic to expect the devs to make the templating engine pluggable, but I sincerely doubt that will ever be the case. My guess is they drew the line in the sand some time ago and Twig is here to stay.

  6. No out of the box Elixir / Gulp / Grunt support to manage assets.

    Had October been built as it should have been, which is to say an application sitting on top of the existing stock Laravel framework, we'd have Elixir support right now.

    I'll grant that October began development before Elixir was a twinkle in Taylor's eye, but the October devs apparently couldn't be bothered to provide a suitable alternative configuration for tools like gulp or grunt that have been around forever.

  7. No routes.php file and its powerful routing configuration engine.

    I'll grant that a single file would be difficult to edit on the fly when plugins are installed and removed. For that I give you the concept of a routes.d directory in which plugin developers could place the appropriate routing files, just like we do on Debian when different packages want to put stuff in various directories within /etc.

    So the answer was not "remove routes.php". It was "Add support for a routes.d directory to Laravel and send a pull request to Taylor" since I think that would be helpful in stock Laravel as well. What else can I say but "October ain't Laravel".

  8. The plugin concept is broken.

    Plugins seem like a good idea until you get into the nitty gritty of using them. Yes, they're easy to install and remove because the output of the plugin can be inserted into a given page template with a single twig variable but the problem is that basically precludes customization because from the end-user's perspective the entire thing is a black box.

    And while it's true that the system provides for overriding of "partials" the partials provided by the plugin cannot be viewed / edited / overridden from the backend. The current design is kind of like trying to use a C++ class without the accompanying Interface documentation or header file that tells you what functions are public, private, or virtual.

  9. The community isn't much of one.

    Many of the free plugins provided via the October CMS needed for basic functionality are buggy, and support is basically non-existent. After reporting a few bugs the only responses I received over several days were from those who maintained paid plugins. This doesn't exactly surprise me -- those who are paid are motivated to support their products -- but I've participated in countless open source ecosystems where there was great support and no money changed hands (Laravel is a good example).

    This tells me there isn't much of a traditional community behind October CMS...at least at the moment. The community presently consists mostly of a few "haves" and a whole hell of a lot of "have nots". Meaning, a bunch of users like me, fumbling their way around in the dark trying to learn how the system works, complaining when it doesn't, and a comparatively few developers who do understand the system and either can't be bothered to help others or are motivated to help others only after money has changed hands.

    This is not a healthy community or one I would feel comfortable joining if I lacked the development experience needed to fix things myself, but even doing that is difficult due to the plugin architecture. The message to new users? Get used to buying plugins or learning the internals of October CMS as required to build your own. Sadly, I think that's by design. October CMS has been built to sustain the App Store model of development and is open-source in name only.

  10. The plugin marketplace only accepts payments via PayPal.

    I tried three times to buy a plugin and it failed with some "temporary" error. I eventually worked around the problem by transferring funds via my paypal account rather than paying with my credit card.

    The time has come to move to a real payment processor like Stripe. Stripe integration is relatively simple for developers and a lot easier to use from the buyer's perspective. Win-Win. The problem is I doubt we'll ever see Stripe integration in the October marketplace because a good many of the developers may be outside of the areas covered by that service.

  11. Attaching an existing October CMS installation modifies the system without adminstrator consent.

    While the CMS backend integrates rather nicely with the marketplace in that it allows the download and installation of free plugins simply by knowing the namespace of the plugin (alxy.captcha, for example), buying a plugin requires that you login to the marketplace, create a project, and then use the generated ID to "bind" your October installation to the project by logging into your backend and plugging in the ID accordingly.

    The problem came when I decided to buy / install a plugin when I already had configured and tested my system with several free plugins installed. The second I bound the project, the backend phoned home and not only downloaded and installed the plugin I puchased but downloaded ALL of the plugins I had already installed and reinstalled them. Downloading everything again was unnecessary, but the real problem I have with this model is that had I made modifications to the plugins those would have been overwritten.

    And if you're knowledgeable in October internals and you're screaming at your monitor saying "well, what did you expect? You're modifying code that you don't own or maintain." Well, that's the problem. Once I put code on my system it is not something I want modified without my explicit permission. Plugins should be "lockable" so they are never upgraded even if the administrator clicks on the "upgrade all" button

    Business systems cannot be changed at the whim of a bunch of developers half way around the globe. Are they going to fix the ball of shit that results from a botched installation, a newer version of a plugin that removes an essential feature upon which the site or another plugin depended, or breaks something that previously worked because the developer didn't sufficiently test it?

    I sincerely doubt it.

    Oh, did I mention that the CMS core was also upgraded during this installation without my knowledge or authorization? Everything I'd based two weeks of testing on was ripped out from under me. Sure, it worked without issue but again, that's not the point. I got lucky. That's all.

  12. The October CMS plugin marketplace does not allow for demos.

    The great thing about open source code is that while it doesn't come with a warranty or guaranteed support, I don't pay anything and I have the source so I can fix it myself if I so desire.

    But the second money changes hands, as a buyer of software I expect a certain level of care. I don't care how good a developer thinks his product is. All software products for sale should be available for demonstration so the buyer can determine if the software is bug-free and otherwise meets their needs. As it stands right now, if you buy a plugin on the October marketplace and you realize it's broken or generally sucks, you're at the mercy of the developer responding to your request and refunding your money in a timely manner.

    For example, I paid for the Contact plugin ($5), installed and provisioned it, and then tried to access the page into which I had integrated the component. I expected the contact form to appear but instead got a stack trace. I then reported the issue, and waited for a response. To the developer's credit he responded in less than 30 minutes with a solution, but then I found two other issues to which he did not respond in a timely manner (read: days). In fact, I had to solve one of them myself, at which point I asked "what the hell am I paying this guy for?"

    It's not the $5. It's the principle. Had I been able to demo the software I would have discovered these errors, reported them, and kept my money until he demonstrated that the software was bug free. I'm a developer so I thoroughly appreciate the need to pay people for developing software but I only want to pay for software that works. If I'm going to be forced to fumble around in the dark I might as well write my own code.

    All plugins should be available for trial periods set by the developers (as some plugins might require longer demo periods to fully test), payments to the developers should be withheld for that period of time, and buyers should have the option to uninstall and obtain an immediate refund for any plugin that does not meet their needs. That way users get to see if the software works, and developers are not rewarded for their efforts until they provide software that works.

    All in all, the October CMS plugin system is a colossal failure and needs to be completely redesigned to meet the needs of the users.

  13. The use of ini files for configuration in some places, with yaml in others.

    I can understand not using json -- that's great for passing data structures but it's not really pleasant to edit manually. Yaml is a lot better for this purpose. ini? Sure, it works, but why two formats in the same system? I don't really care what format they use, but they should use only one format.

  14. HTML files require an .htm extension and are saved by the CMS in Windows format (CR/LF).

    Call me a Unix bigot, but my filesystem isn't limited to 3 character file extensions, and all of my html files have, since the dawn of the web, ended in .html. Hell, even Windows has supported four character file extensions since when...2000? That's 15 fucking years ago. I should be able to use .html on my system.

    The CMS editor also saves files in Windows format (CR/LF) rather than Unix (LF) as it should (at least on my Linux system). That's annoying. It should be configurable in the backend or better yet, set to an appropriate default during the installation process when the platform information is obtained.

  15. The maintenance mode doesn't work.

    The last bug I found testing just prior to deployment was that checking the maintenance mode checkbox and clicking the "Save" button does absolutely nothing.

    It's rare that I use maintenance mode on any CMS, but when I need it in a pinch to shut down a site, I need it. Since the devs can't be bothered to test anything as simple as this I guess I'll just do what we did in the old days and replace index.php with my own version that displays "System down for maintenance". After all, I use a CMS so I can do everything manually. *sigh*

Conclusion

October CMS is glossy, that's for sure. And like most glossy systems it makes a lot of promises. But under the hood I view it as a disaster.

It's been built from the ground up to support the App Store model and that benefits only the select few that care to learn the internals and then, I imagine, sell their apps to clients for which they have installed October. If you're just an average administrator looking for a CMS, there are far better open-source alternatives and I advise you investigate those instead.

Although I decided to go into production with October CMS I will not be using it for any other systems until I have proof that the community is more supportive and the application more mature. I'm not holding my breath.