Documentation

Technical Architecture

The DesertCMS engine, runtime model, static-first renderer, SQLite storage, contributor product mode, capability policy, modules, media pipeline, and OpenBSD boundaries.

Source: TECHNICAL_ARCHITECTURE.md

DesertCMS is a Perl CGI, SQLite, static-first CMS designed for OpenBSD 7.4 with httpd, slowcgi, pf, acme-client, and local filesystem operations.

Runtime Model

The public site and admin app are different surfaces:

SurfaceRuntime
Public siteGenerated static files under public_root, served directly by OpenBSD httpd.
Admin appPerl CGI entrypoint behind slowcgi, used for editing, settings, uploads, billing, operations, and rebuilds.
Background operationsRoot-owned OpenBSD worker scripts for provisioning, upgrades, operations, and package-backed tasks.

The admin app writes structured state to SQLite and generates public artifacts during publish or rebuild.

Main Paths

Default production paths are:

/usr/local/www/desertcms/          application code
/etc/desertcms.conf                main instance config
/var/desertcms/desertcms.sqlite    SQLite database
/var/desertcms/originals/          private source assets
/var/desertcms/backups/            backup archives
/var/desertcms/themes/             editable theme state
/var/desertcms/upgrades/           staged upgrade archives
/var/www/htdocs/desertcms-site/    generated public site
/var/www/run/desertcms.sock        slowcgi socket

Contributor sites use separate config and data roots. A contributor instance is detected when contributor_site_id or contributor_domain is set.

Configuration

DesertCMS::Config loads key-value config from DESERTCMS_CONFIG or /etc/desertcms.conf.

Important settings include:

  • site_name
  • site_url
  • data_dir
  • db_path
  • public_root
  • originals_dir
  • backup_dir
  • theme_dir
  • admin_asset_dir
  • max_request_body_bytes
  • image_public_max_width
  • image_public_quality
  • image_tool
  • analytics_enabled
  • contributor_site_id
  • contributor_domain
  • master_config_path
  • standalone_master_configs
  • module_*_enabled
  • docs_source_dir
  • commerce_model
  • stripe_*
  • postmark_*
  • google_*
  • indexnow_*
  • operations_*
  • upgrade_*
  • font_package_repo

Database

The SQLite schema stores:

  • Admin users and sessions.
  • Content items and revisions.
  • Media assets, preview jobs, and resource metadata.
  • Shop catalog and order records.
  • Settings.
  • Analytics.
  • Backups and operations.
  • Contributor blueprints, service plans, sites, invites, and requests.
  • Federated review records.
  • Provider delivery logs.

Schema changes are applied by DesertCMS::DB->migrate.

Static Renderer

DesertCMS::Renderer writes public artifacts.

It generates:

  • Pages.
  • Posts.
  • Indexes.
  • Module pages.
  • Sitemap.
  • Robots.
  • Redirect files.
  • Public theme CSS.
  • Public media manifests.
  • Documentation pages when the Docs module is enabled.

Generated module pages yield to published content if a page explicitly claims the same URL. This lets site owners replace a module landing page with curated content where appropriate.

Admin App

DesertCMS::App handles the server-rendered admin and public CGI routes.

It owns:

  • Authentication.
  • CSRF checks.
  • Admin shell.
  • Contributor product mode shell.
  • Editor screens.
  • Media screens.
  • Site settings.
  • Feature catalog.
  • Billing screens.
  • Account and help screens.
  • Master control and operations.
  • Contributor review and lifecycle surfaces.

Capability Policy

DesertCMS::CapabilityPolicy centralizes role permissions and route access.

Capabilities include:

  • edit_content
  • upload_media
  • download_media_sources
  • publish_media_resources
  • bulk_manage_media
  • customize_theme
  • enable_allowed_modules
  • manage_billing
  • view_usage
  • manage_provider_settings
  • run_operations
  • run_upgrades
  • manage_governance
  • review_federated_content
  • manage_contributor_lifecycle

Master roles and contributor roles map through the same policy. Contributor product mode blocks master-managed routes before capability checks allow route access.

Contributor Product Mode

Contributor product mode changes both product shape and security posture.

It affects:

  • Admin shell.
  • Navigation.
  • Route policy.
  • Terminology.
  • Dashboard.
  • Billing and usage surfaces.
  • Plan-gated feature catalog.
  • Provider inheritance.

The contributor owner role should be understood as site manager, not system owner.

Modules

DesertCMS::Modules defines first-party modules and plan-gated feature state.

Each module exposes:

  • key
  • label
  • description
  • public_path
  • settings_path
  • setting_key
  • default_plan_enabled
  • available
  • enabled
  • locked_by_plan
  • requires_upgrade
  • managed_by_master

Current module keys are:

  • map
  • shop
  • gallery - legacy storage key for the Showcase feature
  • forms
  • contributor_requests
  • docs
  • resource_publishing

Forms

DesertCMS::Forms backs the dynamic /forms/ CGI route and the admin Forms inbox.

Supported public submission types are:

  • contact
  • quote
  • application
  • intake
  • rsvp

Each submission stores structured fields in form_submissions, including contact details, request dates, guest count, budget, message text, attachment metadata, and Postmark notification state.

Form uploads are private. Files are written below data_dir/form-submissions/<id>/ with 0600 permissions, and the public site only receives metadata. Admin downloads are served through authenticated /admin/settings/modules/forms/submissions/<id>/uploads/<index> routes.

Postmark notifications use forms_notification_email when configured, otherwise the contributor request recipient can act as a fallback. Notification status is recorded on the submission row, and delivery attempts also flow through the shared email delivery log.

Media Pipeline

DesertCMS::Media implements the private source asset pipeline.

Image uploads:

  • Store the original under originals_dir.
  • Generate a public optimized derivative.
  • Generate responsive sizes.
  • Store dimensions and derivative metadata.

Non-image uploads:

  • Store the source under originals_dir.
  • Keep public_path blank until explicitly published.
  • Extract safe preview metadata when possible.
  • Queue private preview jobs for supported PDF and video assets.
  • Publish Resource Downloads only through the resource publishing workflow.

The public policy is one of:

  • optimized_public_derivative
  • public_resource_download
  • private_source_only

Provider Inheritance

Contributor sites inherit platform services unless a plan explicitly allows override.

Inherited services include:

  • Postmark delivery.
  • Stripe service billing.
  • Search indexing defaults.
  • Operations.
  • Backups.
  • Upgrades.

Paid plan options can allow custom Postmark senders, Stripe Connect payout setup, and indexing overrides.

Security Boundaries

Important boundaries include:

  • Private source files are outside the public webroot.
  • Public artifacts are generated, not served from private data roots.
  • Contributor sites have separate config, database, public root, and data paths.
  • Contributor route access is capability-driven.
  • Master-managed operations stay out of SubCMS.
  • Upgrade archives are staged and applied by a root worker.
  • OpenBSD httpd, slowcgi, pf, and filesystem ownership form the deployment boundary.