Documentation
OpenBSD Interactive Installer
Fresh OpenBSD VPS installation flow, account setup, DNS, TLS, firewall, packages, and validation.
OPENBSD_INSTALL.mdUse this path for a fresh OpenBSD VPS.
perl install/openbsd-install.pl --dry-run --domain desertarchive.kldhosting.com
doas perl install/openbsd-install.pl
Run the dry-run first. It performs read-only preflight checks and prints the system changes without writing files, loading pf, restarting services, creating users, installing packages, or issuing TLS.
The real installer is intentionally interactive. It starts by asking for the OpenBSD server-admin username and password, creates or updates that account, adds it to wheel and desertcms-admins, and writes a managed doas.conf block so that account can fully manage the backend through doas.
It then walks through:
- Site domain and site name.
- Optional first-party Shop module served at
/shop. - SSH port and CIDR allowed through
pf. - Required packages:
p5-DBI,p5-DBD-SQLite,libvips, andp5-HTTP-Daemon. - Local asset audit with
tools/check-local-assets.pl. _desertcmsservice user and OpenBSD filesystem layout.- Copying the CMS to
/usr/local/www/desertcms. /etc/desertcms.conf.pf,httpd,acme-client, anddesertcms_slowcgi.- DNS instructions and verification for the configured domain.
- TLS issuance through
acme-client. - Temporary CMS admin creation.
The generated HTTPS httpd server block sets connection max request body 67108864 so the admin can upload full-resolution photo originals up to 64 MB. OpenBSD httpd defaults to 1 MB, which is too small for photographic JPEG uploads.
The Shop module uses the main /etc/desertcms.conf, database, media library, and Stripe settings. It is served from the main site at /shop; no separate shop subdomain is required.
For OpenBSD 7.4 systems whose default /etc/installurl no longer has package files, the installer probes fallback package paths and can select a release-specific PKG_PATH, such as https://ftp.eu.openbsd.org/pub/OpenBSD/7.4/packages/amd64/. You can override that with --package-repo.
Useful dry-run example for the DreamHost-managed subdomain:
perl install/openbsd-install.pl --dry-run --domain desertarchive.kldhosting.com --server-admin siteadmin --ssh-allow 203.0.113.10/32
When deploying through an existing OpenBSD shell account, keep that account's password unchanged and only add the required groups/doas access:
doas perl install/openbsd-install.pl --domain desertarchive.kldhosting.com --server-admin kld997 --keep-server-admin-password --ssh-allow 208.76.93.70/32 --no-www
Server Admin Vs CMS Admin
The first account the installer asks for is an OpenBSD shell account. It is for server operations, not the CMS login.
The installer creates a separate temporary CMS admin named setup-admin with a generated password. On the first CMS login, the admin UI immediately requires a permanent CMS username and password before the dashboard, editor, settings, media, or backups can be used.
The CMS is intentionally single-admin. If the temporary password is lost, or if production access needs to be handed off again, rotate the only active CMS admin:
doas su -m _desertcms -c 'env DESERTCMS_CONFIG=/etc/desertcms.conf perl /usr/local/www/desertcms/bin/desertcms-maint.pl reset-admin setup-admin'
That command disables any other active admin, revokes existing sessions, prints a new temporary password, and forces the next login through the account setup screen.
DreamHost DNS
kldhosting.com uses DreamHost nameservers. In the DreamHost DNS panel for kldhosting.com, create records pointing the subdomain at the OpenBSD VPS:
A desertarchive 206.125.172.18
AAAA desertarchive <server IPv6> # optional, when available and wanted
Do not create www.desertarchive.kldhosting.com unless you specifically want that extra hostname. The installer defaults to no www alias for subdomains, and prints the detected egress IPv4/IPv6 plus current DNS lookup results before trying TLS.
For the production rights shop, enable Settings > Modules > Shop and configure Stripe to post webhooks to https://<domain>/shop/stripe/webhook.
Files Installed
/usr/local/www/desertcms/ root-owned application code
/etc/desertcms.conf root:_desertcms 0640 app config
/etc/rc.d/desertcms_slowcgi rc.d service for admin CGI
/etc/httpd.conf generated httpd config
/etc/acme-client.conf generated ACME config
/etc/pf.conf generated host firewall
/etc/doas.conf managed desertcms-admins doas block
/var/desertcms/ _desertcms-owned data
/var/desertcms/originals/ private photo originals
/var/desertcms/backups/ compressed backups
/var/desertcms/themes/ editable theme copy
/var/www/htdocs/desert-archive/ generated public webroot
/var/www/acme/ ACME HTTP challenge root
/var/www/run/desertcms.sock slowcgi socket visible inside httpd chroot
Photo originals remain under /var/desertcms/originals and are not served by httpd. Public pages reference generated downscaled JPEG derivatives under /var/www/htdocs/desert-archive/assets/media/.
Existing /etc/httpd.conf, /etc/acme-client.conf, /etc/pf.conf, /etc/doas.conf, /etc/desertcms.conf, and /etc/rc.d/desertcms_slowcgi files are backed up with a timestamp before replacement or managed-block rewrite.
Local Assets
The CMS does not depend on CDN-hosted admin assets. Editing icons and social icons are local inline SVG. The public theme uses local CSS and system fonts.
Run the audit manually with:
perl tools/check-local-assets.pl
It fails if runtime admin/theme files contain remote script, stylesheet, image, font import, CSS URL, or common CDN references.
Recovery Notes
If ACME fails during install, wait for DNS propagation and rerun:
doas acme-client -v example.com
doas httpd -n
doas rcctl restart httpd
If the firewall config needs review:
doas pfctl -nf /etc/pf.conf
doas pfctl -sr
Production Validation
After the installer finishes on the OpenBSD server, run:
doas perl /usr/local/www/desertcms/tools/openbsd-validate.pl --domain example.com
The validation script is read-only. It checks the OpenBSD release, required packages and Perl modules, doas, pf, httpd, service status, ports, filesystem ownership, database tables, local asset boundary, public CSS publishing, DNS results, and TLS files.
Contributor site worker
Contributor invites and site actions are queued by the admin CGI and applied by a root-owned OpenBSD worker. Install the worker into root's crontab after deployment:
doas perl /usr/local/www/desertcms/tools/openbsd-apply-site-queue.pl --install-cron
The worker runs once per minute, takes /var/run/desertcms-site-queue.lock, processes queued create/enable/disable/destroy actions, rewrites /etc/acme-client.conf and /etc/httpd.conf, issues ACME certificates, rebuilds the target site, and restarts httpd only after httpd -n passes. Existing /etc/httpd.conf and /etc/acme-client.conf files are timestamp-backed up before replacement.
For automatic invite-created subdomains, configure wildcard DNS such as *.desertarchives.com to point at the server. Without wildcard DNS, create A/AAAA records for each contributor subdomain before the queue worker can issue TLS.
Postmark invites use the Admin Settings > Contributors fields. Set Send email to a verified Postmark sender address for the domain, and set Postmark server token to the server token from Postmark.
Admin password resets are available in two places:
- A logged-in admin can update the admin username, account email, and password from Admin Settings > Admin Account.
- The login screen has a forgot-password link. It sends a one-time reset link to the admin email stored for that site.
When a contributor accepts an invite, the queue worker provisions the subdomain site, attaches the contributor email to that site's admin account, and sends a one-time password setup link through Postmark. The setup link lets the contributor choose their admin username and password.
For the specific OpenBSD 7.4 validation pass, any release other than 7.4 is reported as a warning so the deployment transcript is explicit.