Documentation
Technical Architecture
The DesertCMS engine, runtime model, static-first renderer, SQLite storage, contributor product mode, capability policy, modules, media pipeline, and OpenBSD boundaries.
TECHNICAL_ARCHITECTURE.mdDesertCMS 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:
| Surface | Runtime |
|---|---|
| Public site | Generated static files under public_root, served directly by OpenBSD httpd. |
| Admin app | Perl CGI entrypoint behind slowcgi, used for editing, settings, uploads, billing, operations, and rebuilds. |
| Background operations | Root-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_namesite_urldata_dirdb_pathpublic_rootoriginals_dirbackup_dirtheme_diradmin_asset_dirmax_request_body_bytesimage_public_max_widthimage_public_qualityimage_toolanalytics_enabledcontributor_site_idcontributor_domainmaster_config_pathstandalone_master_configsmodule_*_enableddocs_source_dircommerce_modelstripe_*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_contentupload_mediadownload_media_sourcespublish_media_resourcesbulk_manage_mediacustomize_themeenable_allowed_modulesmanage_billingview_usagemanage_provider_settingsrun_operationsrun_upgradesmanage_governancereview_federated_contentmanage_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:
keylabeldescriptionpublic_pathsettings_pathsetting_keydefault_plan_enabledavailableenabledlocked_by_planrequires_upgrademanaged_by_master
Current module keys are:
mapshopgallery- legacy storage key for the Showcase featureformscontributor_requestsdocsresource_publishing
Forms
DesertCMS::Forms backs the dynamic /forms/ CGI route and the admin Forms inbox.
Supported public submission types are:
contactquoteapplicationintakersvp
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_pathblank 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_derivativepublic_resource_downloadprivate_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.