Content

Introduction

cms.sh is a minimalistic web content management system with command line administration interface. This document talks about what cms.sh is, the problem being solved by cms.sh and describes how to use it without going into implementation details.

Objective

Nowadays there are lots of various content management systems available, but I decided to write another one which would satisfy my specific requirements:

  1. Convenience for usage from command line. This allows the user to manipulate data in a usual environment and use web interface only for viewing content.
  2. Clarity of internal workings. For this goal, cms.sh does not use a DBMS, all the content is stored in plain files. So it's very easy to correlate input and output of the system.
  3. Compliance for adding new features and modifying the existing functional.

Architecture

cms.sh consists of two major parts: content presentation system and content manipulation system. The presentation system is based on HTML/CSS as in any other web CMS, but content manipulation is performed via UNIX-style command-line interface.

cms.sh is built as an application framework, and has a pluggable architecture to aid in the extensibility of the existing functional. Each pluggable module implements a particular operation mode. The mode defines types of objects which may be published (details below), provides managers for the objects and composes general view elements (like menu, for example). Developers can create custom modes that match their own requirements. Currently the following modes are available:

  • Document mode deals with ordinary documents and categories of documents.
  • Gallery mode allows user to preview an album with image thumbnails or view a particular image.
  • Video shows videos via HTML5.
  • Storage mode is used for managing ordinary files published on the server.

The list of enabled modes is controlled by the ENABLED_MODES parameter. By default all the modes are enabled.

Publications

From the user's point of view, publication is a unit of data, which can be displayed and/or managed. Generally there are two types of publications: an ordinary publication (for example, an image) and a publication collection (for example, an album). Collections may contain another publications. On the file system layer a publication is represented by one or few file(s) and/or directory(ies).

Every publication has a name - a string of characters. The allowed characters are: alphabet (a-z), digits (0-9), space (), underscore (\_), dash (-), dot (.), colon (:), comma (,), parentheses (()) and apostrophe ('). Publication name is strongly associated with names of the corresponding files/directories forming the publication. Some publication types may have extra restrictions on names due to mode-specific peculiarities.

Every publication is identified by an address - URI, which is unique in the context of the mode. The address spaces of different modes are independent. URI consists of the current publication name and all the parent names up to the root (/), for example:

/collection/sub_collection/ordinary_publication

Presentation

Presentation layer is based on HTML4 and CSS2 (and HTML5 video if the video mode is enabled). Since web interface is not used for content management, cms.sh uses neither HTML forms, nor JavaScript.

In order to get view of a publication, user has to make a request to the corresponding URL address, which generally looks like this:

http://domain.name/urlkey/URI

Where domain.name is a host domain name, urlkey is a mode-specific prefix (mentioned in the mode descriptions below), URI is a publication identifier.

Besides mode-specific URL keys, there are two common prefixes: DIR_MEDIA and URLKEY_DOWNLOAD. The first one tells that the requested object is a file and should be returned to the user as is. The second one tells that the user agent should display a save dialog rather than displaying the raw content.

For example, the following URL-address corresponds to the image Birches from the album Nature:

http://vminko.org/gallery/Nature/Birches

Regardless of the type of publication, the view always contains the following components:

  • Header, which consists of a menu, a path to the publication being viewed and a date of the publication. Menu consists of a constant set of elements provided by the modes. Each mode can provide several elements.
  • Main content, which is generated by the publication being viewed.
  • Footer, which contains copyright and licensing information.

Presentation of the publications themselves is mentioned in the description of corresponding modes.

Administration

Content manipulation is entirely performed via the cms.sh script. The script is just an intermediary, which sends accepted parameters to the server, where the user's request is actually processed by a corresponding mode.

Generally the command looks like this:

cms.sh cmd [source1 [source2 ...]] [destination]

cmd is a string, which consists of an operation abbreviation and a publication type. There are five types of operation: ls, mk, rn, mv and rm. Publication type is designated by one letter (see the mode descriptions for details).

ls shows listing of a publication collection. Accepts exactly one argument: URI of the publication collection to list.

For example, the following command lists the blog category:

cms.sh lsc /blog/

If an item in the listing is ended by /, that means that the item is a publication collection and can also be listed.

mk creates new publications. The number and meaning of the arguments is highly dependent on type of the publication. In general, source is a basis for new objects. It maybe just a name or a path to local files. destination is URI of a publication collection in which the new publication will be stored.

For example, the following command adds one document with an icon to the category blog; the document will be accessible by domain.name/blog/new_article:

cms.sh mkd new_article.mkd icon.jpg /blog

rn renames publications. Accepts exactly two arguments: URI and a new name.

For example, the following command renames one document:

cms.sh rnd /blog/new_article renamed_article

mv moves publications. Accepts two or more arguments: URI(s) of the publication(s) to be moved and URI of the publication collection in which the publications will be placed.

For example, the following command moves a document from blog to the root category:

cms.sh mvd /blog/renamed_article /

rm removes publications. Accepts one or more arguments: path(s) to the publication(s).

The following command removes one document:

cms.sh rmd /renamed_article

All URI arguments allow wildcard characters (like*, ?, [ and ]).

For example, the following command removes all images from the album Temp:

cms.sh rmi '/Temp/*'

In order to avoid collisions, cms.sh forbids to create multiple publications having the same URI (for example, an ordinary publication and a publication collection) despite of the fact that the file system layer may allow to create them.

The administration operations are not allowed for root publication collections. There collections are supposed to be created once during the system configuration and not modified later.

Administration distinctivenesses of publications are mentioned in the description of respective modes.

Document mode

Publication types

This mode provides two types of publications: documents and categories (abbreviations d and c respectively).

On the file system layer Document consists of a MultiMarkdown file and (optionally) an icon. The default extension allowed for MultiMarkdown files is mkd (controlled by EXT_DOC), for icons - jpg (which is common for all images and is controlled by EXT_IMG).

Category is a collection of documents. On file system layer it consists of a directory for MultiMarkdown files, a directory for icons and a description file in the MultiMarkdown format, where metadata is mandatory, but the main part is optional. A category name is identical to the names of corresponding directories.

There are few restrictions on publication names:

  1. It's recommended not to create root publications, whose names are equal to URL keys of the other modes (URLKEY_GALLERY, URLKEY_VIDEO, DIR_STORAGE, DIR_MEDIA, URLKEY_DOWNLOAD).
  2. A Document/Category name can not consist only from numbers in order to avoid conflicts with page numbers.
  3. A Document/Category name can not contain '.' in order to avoid conflicts with CSS files.

Presentation

This mode has en empty URL key (urlkey) and all publications are addressed directly from the domain name.

A document presentation consists of a full path and date in the header, its content in the main part and a link for the source mkd file in the footer.

A category presentation consists of a full path in the header, a description and a list of previews of nested publications. If there is no preview of a nested publication (see the metadata key Summary below), then the category displays full document (or full description in case of a nested category). If a document has an icon, it will be displayed next to the title.

The root category has few distinctivenesses:

  • It's described by a special file called main.mkd by default (the name is controlled by ROOT_DESC_NAME).
  • Categories nested into the root category are displayed in the menu.

By default the number of previews displayed in a category is limited to 5 (the value is controlled by PREVIEWS_PER_PAGE). If the number of nested objects exceeds this value, then the category will be displayed page by page and there will be a paginator above the footer.

Metadata

The following metadata is supported:

Key Value
Title Title of the document.
It's displayed in page titles, in parent category listings and in headers (in case of a document).
Mandatory for both documents and categories.
Summary Summary of the document in plain text. May contain line breaks.
Copyright Copyright information. May contain line breaks.
Date Date of the last change in the document.
Any format recognised by str2time is allowed.
Mandatory for documents.
Web URL link to this document.
Sort by Determines sort order of documents in the category.
The only supported value is Date (sort by date in descending order).
The default order is lexicographic.
Priority A number, which controls position of the category in the menu.
The higher the value is, the closer to the left the category is displayed. Optional.
Name Name of the category, which will be displayed in the header.

Administration

mkc creates new categories. Accepts exactly two arguments: local path to the description file and URI of the destination category.

For example, the following command creates a new category blog, which will be accessible by domain.name/blog:

cms.sh mkc docs/blog.mkd /

mkd adds new documents to categories. Accepts two or three arguments: local path to the MultiMarkdown file, local path to the icon (optional) and URI of the destination category.

For example, the following command adds one document with an icon into the category blog. The document will be accessible by domain.name/blog/new_article:

cms.sh cpd new_article.mkd icon.jpg /blog

All the other administration operations conform to the common description.

Parameters

Here are the configuration parameters of this mode:

Name Description / Default value
DIR_DOC Name of the directory containing text files.
text
DIR_ICON Name of the directory containing document icons.
Has to start with '.'.
.icons
EXT_DOC Filename extension for allowed text files.
mkd
ROOT_DESC_NAME Basename of the root category description file.
main
PREVIEWS_PER_PAGE How many previews to display on one page at most.
5
DATE_TMPL Date format, identical to the strftime format.
%e %b %Y

Gallery mode

Publication types

This mode provides two types of publications: images and albums (abbreviations i and a respectively).

On the file system layer Image consists of an original image file and two system files (a thumbnail and a preview). Basename of the original file is identical to the publication name. The default extension allowed for images is jpg (controlled by EXT_IMG).

Album is a collection of images. On the file system layer it consists of a directory for original files and two system directories (for thumbnails and for previews). An album name is identical to the names of corresponding directories.

The only restriction on the publication names is that they can't start with '.' in order to avoid conflicts with system directories (DIR_THUMB, DIR_PREVIEW, etc).

Presentation

URL key of this mode is controlled by URLKEY_GALLERY. The default value is gallery.

An image presentation consists of a full path in the header, and a preview image with a link to the original image in the main part. Size of the preview image is controlled by PREVIEW_WIDTH и PREVIEW_HEIGHT (the default size is 1027 by 768 pixels). If the current album contains other images, then there will be navigation arrows to go to the next/preview images.

An album presentation consists of a full path in the header, a list of nested albums and a set of thumbnails of nested images with captions. Size of the thumbnails is controlled by THUMB_SIZE (the default value is 240 pixels). The nested publications are sorted in lexicographic order.

In the menu the gallery mode is displayed as a link (named Gallery by default) with zero priority (name and priority are controlled by TITLE_GALLERY and INMENU_PRIORITY respectively).

Administration

mka creates new albums. Accepts exactly two arguments: name of the new album and URI of the destination album.

Fox example, the following command creates a new album in the root album. The new album will be accessible by domain.name/gallery/NewAlbum:

cms.sh mka NewAlbum /

mki adds new images to albums. Accepts two or more arguments: one or few image files and URI of the destination album.

For example, the following command adds one image Image into the album NewAlbum. The new image will be accessible by domain.name/gallery/NewAlbum/Image:

cms.sh mki Image.jpg /NewAlbum

All the other administration operations conform to the common description.

Parameters

Here are the configuration parameters of this mode:

Name Description / Default value
DIR_THUMB Name of the directory containing thumbnails.
Has to start with '.'.
.thumbnails
DIR_PREVIEW Name of the directory containing previews.
Has to start with '.'.
.preview
URLKEY_GALLERY URI prefix of this mode.
gallery
TITLE_GALLERY A string, which will be displayed in the menu and page titles.
Gallery
PREVIEW_WIDTH The maximum width of image previews in pixels.
1024
PREVIEW_HEIGHT The maximum height of image previews in pixels.
768
THUMB_SIZE The maximum dimension (width or height) of image thumbnails in pixels.
240
INMENU_PRIORITY A number, which controls position of the gallery link in the menu.
0

Video mode

Publication types

This mode provides for users only ordinary publications called 'video' (abbreviation v). All videos are stored in the common collection called 'videoteque', which can't be manipulated as any other root collection. However, it can be listed using the lsV command.

On the file system layer Video consists of one Theora/Vorbis file. The default extension allowed for video is ogv (controlled byEXT_VIDEO). Basename of the ogv file is identical to the publication name.

Presentation

URL key of this mode is controlled by URLKEY_VIDEO. The default value is video.

A video presentation consists of a name in the header, and an HTML5-player with a link to the video file in the main part.

Administration

mkv adds new video files. Accepts one or more arguments: one or few local paths to video files. Destination argument is not used since all video publications are stored in the common collection.

For example, the following command adds one video Demo to the server. The new video will be accessible by domain.name/video/Demo:

cms.sh mkv Demo.ogv

The mv operation is not available for video publications, because there is only one collection to hold them.

All the other administration operations conform to the common description.

How to convert videos to Theora/Vorbis

ffmpeg2theora is the most popular converter and is recommended at the Theora project page. It is a cross-platform command-line tool. In most cases you will only need a simple command indicating the name of the file to convert:

ffmpeg2theora input_file.avi

Parameters

Here are the configuration parameters of this mode:

Name Description / Default value
DIR_VIDEO Name of the directory containing video files.
video
URLKEY_VIDEO URI prefix of this mode.
video
EXT_VIDEO Filename extension for allowed video files.
ogv

Storage mode

Publication types

This mode provides two types of publications: files and directories (abbreviations f and D respectively), which are fully equivalent to the same terms of file systems. The mode does not perform file type validation, any file extension is allowed.

Presentation

URL key of this mode is controlled by DIR_STORAGE. The default value is storage.

Publications of this mode don't have a presentation. The mode deals with files which are not used for rendering the content, but which are referenced by it.

Administration

mkD creates new directories. Accepts exactly two arguments: name of the new directory and URI of the destination directory.

For example, the following command creates a new directory in the root directory. The new directory will be accessible by domain.name/storage/temp:

cms.sh mkD temp /

mkf adds new files to directories. Accepts two or more arguments: one or few files and URI of the destination directory.

For example, the following command adds one file sample.txt into to directory temp. The new file will be accessible by domain.name/storage/temp/sample.txt:

cms.sh cpf sample.txt /temp

All the other administration operations conform to the common description.

Parameters

Here are the configuration parameters of this mode:

Name Description / Default value
DIR_STORAGE Name of the root directory.
It's identical to the URI prefix of this mode.
storage

Installation and configuration

Requirements

The server part of cms.sh is written in Perl. The only tested and proven for compatibility version is Perl-5.8.8. Besides the perl interpreter and core modules, cms.sh requires the following modules: Template, Text::MultiMarkdown, GD, URI::Escape. All of them are available on CPAN.

As any other web CMS, cms.sh requires a web server. There are no stringent restrictions on it, but Apache-2.2 is the recommended one since it's the only tested and proven for compatibility server (see Apache server configuration for details).

The administration system is built using SSH. Therefore, the server part requires an SSH server and the client part requires an SSH client. The only tested and proven for compatibility implementation is OpenSSH-5.2.

The client part of cms.sh is written in Shell. Therefore, besides an ssh-client, the client part requires a shell interpreter. The only tested and proven for compatibility version is Bash-4.0.

Unpacking

First of all, you need to extract the src directory from the tarball (see Download) into some directory, which will be the root of cms.sh (ROOT_WWW):

tar xvf cms.sh-$VERSION.tar.bz2 -C /var/www --strip=1

Next you need to set proper owner and group for all data files and directories:

chown user:group -R /var/www/htdocs

where user and group are the name and the group of the administrator (see USER in Client side configuration).

The /var/www/bin/cms.sh needs to be placed on the client machine into some directory included in $PATH (for example, /usr/local/bin).

In order to make the configuration steps clear, below is described the src directory content:

cgi-bin/                  | CGI scripts
htdocs/                   | 
    media/                | Content of the web pages
        images/           | Images
            .preview/     | Preview images
            .thumbnails/  | Image thumbnails
            .icons/       | Icons for documents
        video/            | Video files
    text/             | Text files
    storage/              | Files referenced by the content
lib/                      | Perl modules used by the scripts
tmpl/                     | Templates
bin/                      | Administration scripts

Server side configuration

The server side is configured via the Config modules. All the configuration parameters are defined in variables named Settings. Common settings used by the presentation/administration scripts are defined in CMSsh::Config. Settings specific to some mode are defined in its Config module.

Below are listed the common configuration parameters. Parameters specific to some mode are described in the section dedicated to this mode.

Name Description / Default value
ROOT_WWW Path to the cms.sh root directory.
/var/www
ROOT_TMP Path to the directory containing temporary files.
Used when adding new content to the server.
/tmp.
DIR_HTDOCS Web server's document root.
htdocs
DIR_TMPL Name of the directory containing templates.
tmpl
DIR_MEDIA Name of the directory containing content of the web pages.
media
DIR_IMG Name of the directory containing images.
images
OWNER_NAME Full name of the owner.
Owner Name
OWNER_EMAIL E-mail address of the owner.
user.name@email.domain
COPYRIGHT_YEARS Copyright years.
2011
LICENSE Licensing information.
May contain HTML tags.
GNU Free Documentation License 1.3
URLKEY_DOWNLOAD URI prefix indicating that the resource is to be downloaded rather than viewed.
download
EXT_IMG The filename extension for allowed images.
jpg
IMG_QUALITY Quality of resized images (a number between 0 and 100).
100
ENABLED_MODES The list of enabled modes.
['Doc', 'Gallery', 'Video', 'Storage']

Root publication collections

The tarball extraction automatically emerges the following root publications:

  • htdocs/media/text, htdocs/media/text/main.mkd and htdocs/media/images/.icons form the root category.
  • htdocs/media/images, /htdocs/media/images/.preview htdocs/media/images/.thumbnails form the root album.
  • htdocs/media/video forms the videoteque.
  • htdocs/storage forms the root directory of the storage.

If you modify the associated parameters (for example, DIR_MEDIA or ROOT_DESC_NAME), you need also to manually rename dependent directories/files.

By default the root category description (main.mkd) is the only file, which needs to be edited.

Apache server configuration

cms.sh requires few particular parameters of the http server to be set. Here is an example of the cms.sh-specific parameters of the Apache server:

1   DocumentRoot "/var/www/htdocs"
2   <Directory "/var/www/www/htdocs">
3       Options Indexes
4       AllowOverride None
5       Order allow,deny
6       Allow from all
7   </Directory>
8 
9   ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
10  <Directory "/var/www/www/cgi-bin">
11      AllowOverride None
12      Options ExecCGI
13      Order allow,deny
14      Allow from all
15  </Directory>
16
17  RewriteEngine On
18  RewriteRule  ^/video/(.*)$\
19      /var/www/www/cgi-bin/video.pl?path=$1\
20      [T=application/x-httpd-cgi,L]
21  RewriteRule  ^/gallery(?:/(.*))?$\
22      /var/www/www/cgi-bin/gallery.pl?path=$1\
23      [T=application/x-httpd-cgi,L]
24  RewriteRule  ^/(\d+)$\
25      /var/www/www/cgi-bin/doc.pl?pgnum=$1\
26      [T=application/x-httpd-cgi,L]
27  RewriteRule  ^/(?!media|storage)([^\.]*)/(\d+)$\
28      /var/www/www/cgi-bin/doc.pl?path=$1&pgnum=$2\
29      [T=application/x-httpd-cgi,L]
30  RewriteRule  ^/(?!media|storage)([^\.]*)$\
31      /var/www/www/cgi-bin/doc.pl?path=$1\
32      [T=application/x-httpd-cgi,L]
33  RewriteRule  ^/download/(.+)$ /$1 [L,E=force_download:1]
34  Header set Content-Disposition "attachment" env=force_download

Notes:

  • /var/www is the value of ROOT_WWW.
  • htdocs is the value of DIR_HTDOCS.
  • video at line 18 is the value of URLKEY_VIDEO.
  • gallery at line 21 is the value of URLKEY_GALLERY.
  • media and storage an lines 27 and 30 are the values of DIR_MEDIA and DIR_STORAGE respectively.
  • download at line 33 is the value of URLKEY_DOWNLOAD.
  • lines 18-20 are necessary only if the video mode is enabled.
  • lines 21-23 are necessary only if the gallery mode is enabled.
  • lines 24-32 are necessary only if the document mode is enabled.

Here is a comprehensive manual for the Apache 2.2.

Client side configuration

The client side is configured via the configuration file located at /etc/cmssh.conf or ~/.cmsshrc. The tarball contains an example of this config (src/etc/cmssh.conf). Here is the description of parameters used in this file:

Name Description / Default value
SERVER Domain name of the sever.
domain.name
PORT Port of the SSH server.
22
USER Administrator name.
This user performs all the administration operations.
user
SERVER_ADMIN Path to the administration script on the server.
/var/www/bin/admin-serv.pl

SSH login without password

Since cms.sh uses SSH to transfer parameters of administration operations, by default the SSH server asks for password each time user runs the command. If you find this inconvenient, you may want to authenticate via public/private key pair instead of by password.

Use ssh-keygen on the client system to generate public and private keys:

ssh-keygen -t rsa

Append the public key (id_rsa.pub) to the server's ~/.ssh/authorized_keys:

cat ~/.ssh/id_rsa.pub | ssh $USER@$SERVER 'cat >> ~/.ssh/authorized_keys'

Besides that, PubkeyAuthentication needs to be enabled in the sshd config.

From now on you can log into the server without password.

Bash completion

Management of publications may be much easier with bash completion turned on. In order to enable it, you need to place the contrib/bash-completion file somewhere on your client (for example, to ~/.cmssh/) and make bash read it during initialization by adding the following line to your ~/.bashrc:

source ~/.cmssh/bash-completion

After that you can use <Tab> to autocomplete commands, file names and URIs.

Download

The latest released version is available here: cmssh-0.2.tar.bz2.

To fetch the latest source code from the git repository, run the following command:

git clone git://vminko.org/cms.sh

cms.sh is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3.

ToDo

Below is a list of features which I consider useful, but I can't promise that any of them will ever be implemented.

  • Operations for updating existing publications.
  • RSS support. You may want to use F5er as a temporary solution.
  • An utility for checking integrity of the data.

Alternatives

I don't know any.

History

27 Dec 2013 - Version 0.2
Implemented bash completion for cms.sh.
Implemented listing of publication collections (ls<t> commands).
Performed significant refactoring of the administration part in order to make it easier to read and support.
Added auto tests for the administration part of the system.
Minor improvements in the presentation system (bug fixes mostly).

20 Mar 2011 - Version 0.1
Initial public release.