Skip to content

Admin Guide

Mikhail Deynekin edited this page Nov 13, 2026 · 1 revision

Admin guide

Everything below is in /admin.php. The panel is disabled entirely with ADMIN_ENABLED = false, and every action is rate limited (ADMIN_RATE_LIMIT, default 10 attempts per 15 minutes per IP).

First run

Until a password exists, only setup is offered. From localhost the new password alone is enough; remotely you also type the one-time code from storage/logs/setup.log (0600). Passwords must be at least 10 characters and are stored as ADMIN_PASSWORD_HASH. The plaintext ADMIN_PASSWORD key is cleared on the next request.

Files

  • Full tree of the content root with a filter box, sizes and timestamps.
  • New document / New folder — paths may include new folders, validated segment by segment.
  • New from template — five skeletons: blank, architecture decision (ADR), meeting notes, how-to guide, reference page. Give a title, get <dir>/<slug>.md with today's date filled in; an existing document of the same name is refused with 409, and the new file opens in the editor.
  • Upload .md — multi-file, drag & drop, target folder selectable. Admin uploads bypass the reader-side DISABLE_UPLOAD gate and are audited.
  • Upload image — png/jpg/gif/webp/avif, content-sniffed with getimagesize; SVG is refused by design; collisions get safe names.
  • Rename/move — validated targets, refuses overwrites.
  • Delete — soft: files move to storage/backups/trash/ and can be restored.

Editor

Split-pane live preview that runs the real rendering engine, so the preview cannot disagree with the published page. The toolbar inserts bold, italic, inline code, link, wikilink, bullet list, alert block and table at the cursor (Ctrl/⌘+B and +I are wired too). Saves carry a sha256 and a mismatch returns 409 instead of overwriting someone else's work. Word and reading-time counters, image upload at the cursor, and a deep link per document (?page=editor&file=…).

Revisions

Every save through the editor stores a revision (newest REVISIONS_MAX, default 20; identical content is deduplicated by sha256). A restore writes through the normal save path and first stores a (pre-restore) revision, so a restore is itself undoable. Disable with REVISIONS_ENABLED = false.

Backups and trash

  • backup.create snapshots the content root plus .md.ini, listed and downloadable in Backups & trash.
  • Restores need ALLOW_RESTORE = true and always write a …-pre-restore snapshot first.
  • Trash entries and backups can be deleted permanently — that one is irreversible.

Static export

export.static writes a self-contained HTML bundle to storage/exports/: one file per document plus all-documents.html, with a single embedded stylesheet and no JavaScript. The listing doubles as index.html only when no document owns that name.

Health and diagnostics

admin.php?action=health.run returns {ok, version, checks[]}: PHP version, extensions, storage writability, config sanity, manifest state and more. The panel shows the same list on Security & health. Also available: index stats and rebuild, link check (broken links, broken media, orphans), log tail, audit trail of settings and content changes.

Settings

The panel edits .md.ini through settings.set with validation — an unknown key or a bad type is reported per key instead of being written. settings.regenerate-key rotates API_KEY (the previous key stops working immediately).

Clone this wiki locally