Configuration
Layouts, navigation, site variables, forms, auth, and plugins.
lazysite.conf
lazysite/lazysite.conf defines site-wide variables available in
layout.tt and all page bodies. It is a plain text file with one
key-value pair per line.
Minimal example
site_name: My Site
site_url: ${REQUEST_SCHEME}://${SERVER_NAME}
site_url uses Apache CGI environment variables set automatically on
every request. Do not hardcode the domain - the same lazysite.conf
works on staging and production.
Value types
# Literal string
site_name: My Site
# Environment variable (CGI - allowlisted vars only)
site_url: ${REQUEST_SCHEME}://${SERVER_NAME}
# Remote URL fetch (trimmed, cached with page TTL)
version: url:https://raw.githubusercontent.com/example/repo/main/VERSION
# Directory scan (array of page metadata)
blog_pages: scan:/blog/*.md sort=date desc
Recognised keys
site_name- Display name of the site.
site_url-
Full URL of the site. Typically
${REQUEST_SCHEME}://${SERVER_NAME}. layout-
Active layout. The processor resolves it to
lazysite/layouts/NAME/layout.tt. May also be a full remote URL. theme-
Active theme. Must declare the active layout in its
theme.json'slayouts[]. The processor resolves it tolazysite/layouts/LAYOUT/themes/THEME/theme.json. layouts_repo- GitHub OWNER/REPO source for the manager's release browser. Default unset hides the browser.
nav_file-
Navigation file path, docroot-relative. Default:
lazysite/nav.conf. search_default-
Site-wide default for the
search:front matter key.true(default) orfalse. manager-
enabledordisabled. Controls the built-in manager at/manager. manager_path-
URL path for the manager. Default:
/manager. manager_groups- Comma-separated groups. Only users in these groups can access the manager.
log_level-
ERROR,WARN,INFO(default), orDEBUG. log_format-
text(default) orjson. plugins- List of plugin script paths to pre-enable without using the manager UI.
auth_default-
Site-wide default for the
auth:front matter key.required,optional, ornone(default). auth_header_user,auth_header_name,auth_header_email,auth_header_groups-
Override HTTP header names when using an external auth proxy.
Defaults:
X-Remote-User,X-Remote-Name,X-Remote-Email,X-Remote-Groups. webdav_enabled-
trueorfalse(default). Master switch for the/davWebDAV publishing endpoint. While off,/davreturns 404. See WebDAV publishing. dav_allow_insecure-
trueorfalse(default). Permit WebDAV Basic auth without HTTPS (for a TLS-terminating proxy or trusted LAN). Loopback is always allowed; leave off otherwise.
All other keys become TT variables available in page content and the view template.
Example
site_name: My Site
site_url: ${REQUEST_SCHEME}://${SERVER_NAME}
theme: default
nav_file: lazysite/nav.conf
search_default: true
log_level: INFO
log_format: text
manager: enabled
manager_path: /manager
manager_groups: lazysite-admins
plugins:
- lazysite-auth.pl
- plugins/form-handler.pl
Allowlisted environment variables
Only these CGI variables may be used with ${VAR} syntax:
SERVER_NAME, REQUEST_SCHEME, SERVER_PORT, HTTPS, REDIRECT_URL,
DOCUMENT_ROOT, SERVER_ADMIN.
HTTP_HOST is intentionally excluded - it is request-supplied and
therefore untrusted. Use SERVER_NAME for host-based URL construction.
Navigation (nav.conf)
lazysite/nav.conf defines the site navigation. The processor reads
it into a nav TT variable available in every page.
Format
Navigation is YAML. Items may be links, group headings, or groups with nested children:
- label: Home
url: /
- label: About
url: /about
- label: Docs
children:
- label: Install
url: /docs/install
- label: Authoring
url: /docs/authoring
- label: Resources
children:
- label: GitHub
url: https://github.com/example
Rules:
- Items with a
urlrender as links - Items without
urlrender as non-clickable headings childrenprovides one level of nesting- One level of nesting is supported (parent with children)
Legacy pipe format
An older pipe-separated format is also accepted:
Home | /
About | /about
Docs | /docs/
Installation | /docs/install
nav TT variable structure
nav is an array of hashrefs. Each item has label, url, and
children keys. See Views for looping examples.
If nav.conf is missing, nav is an empty array and the template
renders without navigation.
Alternate nav file
Override the default path in lazysite.conf:
nav_file: lazysite/docs-nav.conf
The path is relative to the docroot.
Authentication
Authentication is configured through three mechanisms:
- User credentials in
lazysite/auth/users - Group memberships in
lazysite/auth/groups - Per-page
auth:andauth_groups:front matter keys - Site-wide
auth_default:andmanager_groups:inlazysite.conf
See Authentication for full details.
Forms
Forms are configured in three files under lazysite/forms/:
FORMNAME.conf- Per-form configuration. Lists dispatch targets by handler ID.
handlers.conf-
Named dispatch handlers. Each handler has an
id,type,name, and type-specific settings (e.g.pathfor file storage,to/fromfor SMTP). smtp.conf- SMTP connection settings shared by all SMTP-type handlers.
See Forms and Forms SMTP for full details.
Plugins
Plugins are CGI scripts and tools that register themselves with the
manager through a --describe JSON protocol. Enabled plugins appear in
the manager Plugins page.
Auto-discovery scans cgi-bin/ and tools/ for scripts supporting
--describe. Enable or disable from the manager Plugins page.
To pre-enable without the manager, list scripts in lazysite.conf:
plugins:
- lazysite-auth.pl
- plugins/form-handler.pl
- plugins/audit.pl
Logging
Log level and format are set in lazysite.conf:
log_level: INFO # ERROR, WARN, INFO, DEBUG
log_format: text # text or json
Both can be overridden at startup with environment variables:
LAZYSITE_LOG_LEVEL=DEBUG perl tools/lazysite-server.pl ...
LAZYSITE_LOG_FORMAT=json perl tools/lazysite-server.pl ...
Layouts and themes
Activate a layout and theme by name in lazysite.conf:
layout: default
theme: odcc
The processor resolves the layout to
lazysite/layouts/default/layout.tt and the theme to
lazysite/layouts/default/themes/odcc/theme.json. Theme assets
are web-served from /lazysite-assets/default/odcc/ (nested).
A theme must declare the active layout in its theme.json's
layouts[] array; mismatched themes render layout-only with a
warning.
See Layouts and themes for installation and authoring.
Page scan
The scan: prefix in lazysite.conf or tt_page_var scans a
directory and returns an array of page metadata as a TT variable.
blog_pages: scan:/blog/*.md
In a page body:
[% FOREACH post IN blog_pages %]
## [% post.title %]
[% post.subtitle %] - [% post.date %]
[% END %]
Pattern rules
- Pattern must start with
/(docroot-relative path) - Only
*.mdfiles are matched - One level of directory only - no recursive scanning
- Maximum 200 files per scan
- Each result is realpath-checked - rejected if outside docroot
Page object fields
Each item in the returned array has:
url- extensionless URI, e.g./blog/first-posttitle- from front mattertitle:subtitle- from front mattersubtitle:(may be empty)date- from front matterdate:, falls back to file mtimepath- absolute filesystem path (useful for debugging)
Sort order
Default sort is by filename. Use the sort= modifier to sort by field:
blog_pages: scan:/blog/*.md sort=date desc
news_pages: scan:/news/*.md sort=title asc
Sort fields: date, title, filename. Direction: asc or desc.
Default direction is asc.
For reverse-chronological blog posts, use sort=date desc. Date-prefix
filenames (2026-03-20-post-title.md) also sort chronologically by
filename without needing the sort modifier.
Per-page scan
Scan variables work in tt_page_var for page-scoped results:
tt_page_var:
section_pages: scan:/services/*.md sort=title asc
Config path override
The default lazysite.conf path can be overridden via a command-line
argument or environment variable. This is rarely needed - each site on
a server has its own docroot and therefore its own lazysite.conf
automatically. See
Config path override
for details.