Writing Criteria
Every guide in this repo is written to the same standard. If you're adding or editing a guide — human or AI — hold it to these.
- Plain words, real ideas. Simple language, never dumbed-down concepts. Explain jargon on first use; collect terms in the glossary.
- No hype. No marketing adjectives, no "revolutionary," no promises about what something will do for the reader.
- Honest about limits. Say what the thing can't do. State uncertainty instead of smoothing it over. Validation notes include what remains unverified.
- No invented numbers. Benchmarks, defaults, and specs are either measured or qualified with "depends on your setup." If it wasn't tested, say so.
- Checkable. Commands are meant to be run, with "Check:" blocks showing what success looks like. Sources are linked, not asserted.
- Respect the reader's setup. Call out Windows/Mac/Linux differences. Don't assume a GPU, a budget, or prior experience.
- Safety isn't skipped. Real risks get stated plainly, not buried.
- Scoped. Each guide says what it covers and points elsewhere for the rest. No guide pretends to be the whole subject.
- Structure over prose. Tables, before/after examples, symptom → fix. Scannable beats essay.
Verification notes for this guide
Built and verified 2026-10-22/23 against Nextcloud 35.0.2 (the project's current stable release on build day), PHP 8.3.6, and MariaDB 10.11.14.
Primary sources read, not remembered: the
release tarball itself from
download.nextcloud.com (SHA-256 matched the
published checksum, dfc7955e…f162d); the
installed code's own behaviour, including the
login controller's origin-check, which the lab
met the hard way before reading; and the
project's documentation for installation
routes, backup and restore, upgrades, and the
client apps.
The lab, and what happened to it: the
server was installed by hand (tarball, MariaDB,
occ maintenance:install, data folder outside
the web root) and served by PHP's built-in web
server on a loopback address, because the
sandbox has no Apache or nginx — a declared
deviation with two visible effects: addresses
keep index.php, and one pretty address
(/apps/files/) 404s because a real folder of
that name intercepts it (chapter 15). Midway
through the build the sandbox machine rebooted
and its system disk returned to the factory
image, destroying PHP, MariaDB, and the first
instance's database; the workspace disk — the
release, the fixtures, and the first data
folder, fossils intact — survived. The lab was
rebuilt and the entire proof suite was
re-run from scratch; every transcript below
and in nextcloud-lab/transcripts/ is from
that second, complete run.
Ran for real (transcripts in
nextcloud-lab/transcripts/):
- t00 — download checksum matched;
occ maintenance:installsucceeded; trusted domain set by occ;occ statusreports 35.0.2 installed,occ checkclean;status.phpagrees. - t01 — the real web login with curl: the
attempt without an Origin header bounced
to the login page and created no token;
with it, 303 → dashboard, the Files app
answered 200 carrying
data-user="ruth", and a session-token row appeared inoc_authtoken. - t02 — WebDAV end to end: two PUTs (201),
a PROPFIND listing, a GET back (200), and
the downloaded file's SHA-256 identical
to the fixture's (
15df1807…). - t03 —
occ user:add --password-from-envcreated the second user; his PROPFIND showed only the skeleton files; an OCS share POST returned status ok with the grant's anatomy (permissions 19); the shared file then appeared in his listing. - t04 — a public link (shareType=3) minted
via the same API; fetched with no
credentials: page 200, and the
/downloadfetch byte-identical (SHA-25668a590c5…) to the original. - t05 — CalDAV with no extra app: calendars listed (personal, contact_birthdays, inbox, outbox, trashbin); an .ics event PUT returned 201 and a GET returned it with summary and start intact.
- t06 — versions and trash: the file's
oc:fileidfetched, an overwrite (204), the versions door listing two stored versions and the version file found on disk underfiles_versions/; a DELETE (204, then 404) and the file — with its old version — found infiles_trashbin/. Also established by asking: there is noocc versions:listin this release. - t07 —
occ integrity:check-coreexit 0; background mode set to cron and onecron.phppass completed (exit 0);occ setupchecksoutput reviewed (mostly passes; honest warnings about the maintenance window, a pending mimetype migration, and a data-directory check the toy web server can't satisfy); a realmysqldumptaken (901,186 bytes, 138 CREATE TABLEs) and opened — both fixture filenames present.
Documented only, and labelled as such in
the chapters: the Docker All-in-One and
compose routes and the snap (no container
runtime exists in the sandbox;
examples/docker-compose.yml follows the
project's own examples); Apache/nginx
serving and pretty URLs; the desktop and
mobile sync clients (the WebDAV door they
use is the one t02 proves; no client was run);
Talk; the integrated office suites
(Collabora/ONLYOFFICE); CardDAV writes (the
dav machinery and door are t05's; no contact
was written); external storage mounts;
Redis/APCu scaling; password- and
upload-only public links (the plain link is
t04's); federation; backup restoration
(chapter 11 teaches the documented procedure;
the two-halves distinction itself was
demonstrated by the lab's own reboot, the
hard way); the upgrade sequence.
Fixtures: the admin (Ruth Calloway, ruth@example.com), the second user (Theo Marchetti, theo@example.com), the recipe and book-club files, and the calendar event are invented and were generated on the build machine. Passwords and the share token are redacted in every transcript.