Improve maintenance and performance of your CMS

Situation

I am using PicoCMS1.

It's not installed through the global package management: all its files, content & executables (except PHP itself) are located under a single directory.

This is not ideal, but common practice; and it has the advantage that it makes maintenance easier.

This article will deal with two topics:

  1. keep two versions of your CMS, one to make edits in, and one to serve
  2. move the served version to a ramdisk2 to speed up performance

This article does not deal with setting up the server that serves the CMS' content.

Staging and production

Two versions of the same CMS installation.

The latter ("Production" from now on) is the final form that is served to the public.

The former ("Staging" from now on) is for making edits, creating content, deploying updates etc. I am also serving Staging, but on a different port and with authentication. This helps me to see what the final product will look like before commiting it.

I have a bash script that copies Staging to Production-new, then changes a few settings (like enabling caching) and removes a whole slew of files and directories that are not required for serving (and might even pose a security risk). The script is highly specialised, but here's a sanitized version. It's missing quality control, dependency checks etc., so please do not use as it is.

bash
#!/bin/bash basedir="/var/www" # the following directories are relative to $basedir: dst=production src=staging ramdisk="/dev/shm/cms" cd "$basedir" cp -a "$src" "${dst}-new" ## Entering the new Production: cd "${dst}-new" ## Finding and deleting files in ${dst}-new that should not be in production... ## Note: I am not using Apache, so I have no use for .htaccess files list=( '*\.template' '\.htaccess' '\.gitignore' README.md 'LICENSE*' 'composer\.????' 'README*' 'CHANGELOG*' 'CONTRIBUTING*' '*\.xcf' '*\.twig\.example' ) for i in "${list[@]}"; do echo "Finding and deleting all occurences of $i" find -name "$i" -delete done ## Finding and removing .git directories... find -type d -name '\.git' | while read dir; do echo "Removing directory $dir" rm -rf "$dir" done ## PicoCMS specific: ## Enabling twig cache. sed -i "s|^\(\s\+\)cache:.*|\1cache: /dev/shm/cache|" config/config.yml ## Finding and minifying all CSS... find -type f -iname '*.css' -exec minify {} -o {} \; -printf '%P | ' ## Changing directory back to $basedir cd "$basedir" ## Ready to commit (also clears cache) - only if all of the above worked OK! ## Removing ${dst}-old... rm -rf "${dst}"-old ## PicoCMS specific: ## Removing old cache - this is not necessary if you only changed some content sudo rm -rf /dev/shm/cache ## COMMIT! ## Moving ${dst} to ${dst}-old... mv "${dst}" "${dst}"-old ## Moving ${dst}-new to ${dst}... mv "${dst}"-new "${dst}"

So, the script

  • copies the staging directory to production-new
  • removes all sorts of stuff from production-new, minifies CSS files, enables twig caching
  • only after these changes went through without a hitch, it completely removes production-old
  • renames the current production to production-old, then immediately renames production-new to production

The last step happens very fast, it's practically impossible that a client will visit during the renaming. Nginx (my server software) does not check the contents of production and doesn't need to be restarted either.

But even if something should go wrong, we are always keeping the last known version to work in production-old.

Move everything to ramdisk

I use Archlinux and Debian, and they both maintain a ramdisk2 under /dev/shm. That's where we want to move our content to, and serve it from. You will have to change the document root in your server software configuration accordingly.

Then, the

## Copying ${dst} to ${ramdisk}...
sudo -u www-data mkdir -p "$ramdisk"
sudo -u www-data cp -dR "${dst}" "${ramdisk}"

  1. It's a wonderfully small and lightweight flat-file CMS, but it has a few caveats: like all flat-file CMS, it has to deal with the underlying file system and plain text files, instead of using a database (and one of the main purposes of databases is to speed things up). Also every time PicoCMS loads a page, it has to access all pages. 

  2. Here's a wikipedia article explaining what that is, but on Linux tmpfs would be a more correct term. Also try grep tmpfs /etc/mtab to see what you have.