1*8d8c8007Stracker-user# Site Backup plugin for DokuWiki 2*8d8c8007Stracker-user 3*8d8c8007Stracker-userAn admin plugin for [DokuWiki](https://www.dokuwiki.org/) that builds a `tar.gz` of selected wiki content and code, streams it to your browser, and deletes it from the server. Nothing persists on disk after the download finishes. 4*8d8c8007Stracker-user 5*8d8c8007Stracker-userBuilt for and tested against DokuWiki `2025-05-14b "Librarian"`. 6*8d8c8007Stracker-user 7*8d8c8007Stracker-user## Why another backup plugin? 8*8d8c8007Stracker-user 9*8d8c8007Stracker-userDokuWiki has the well-known [`backup`](https://www.dokuwiki.org/plugin:backup) plugin by Terence J. Grant, which solves the same problem. This plugin exists because: 10*8d8c8007Stracker-user 11*8d8c8007Stracker-user- **The archive is never left on the server.** The `backup` plugin writes the tar to `data/media/wiki/backup/` and relies on the admin correctly configuring an ACL on that namespace; the plugin page warns that "It is important to secure the backup namespace by ACLs otherwise your backup files can be downloaded by anyone". Site Backup instead writes to `data/tmp/` (which DokuWiki already protects with a deny-all `.htaccess`), with a random filename, and `unlink()`s the file as soon as the download completes (or the connection is aborted, or PHP crashes). 12*8d8c8007Stracker-user- **The upstream `backup` plugin's author [retired](https://www.freelists.org/post/dokuwiki/Fwd-Retiring-my-DW-plugins) and archived the repo in 2020.** It still works via DokuWiki's legacy class alias, but it's no longer maintained. 13*8d8c8007Stracker-user- **Single file.** Roughly 400 lines of one well-commented `admin.php`. No external assets, no language files for ten locales, no preference store. Easy to audit before installing on a wiki you share with other admins. 14*8d8c8007Stracker-user 15*8d8c8007Stracker-userIf you don't share the "ephemeral archive" requirement and you prefer something with a longer track record, the upstream `backup` plugin is a perfectly reasonable choice. 16*8d8c8007Stracker-user 17*8d8c8007Stracker-user## What it backs up 18*8d8c8007Stracker-user 19*8d8c8007Stracker-userEach option is an independent checkbox. The first three columns are usually all you want; the rest are situational. 20*8d8c8007Stracker-user 21*8d8c8007Stracker-user| Option | Path inside archive | Notes | 22*8d8c8007Stracker-user| --- | --- | --- | 23*8d8c8007Stracker-user| Pages | `data/pages/` | Current wiki text. | 24*8d8c8007Stracker-user| Media | `data/media/` | Uploaded files. | 25*8d8c8007Stracker-user| Page metadata | `data/meta/` | Last-edit, subscriptions, changelogs. | 26*8d8c8007Stracker-user| Media metadata | `data/media_meta/` | | 27*8d8c8007Stracker-user| Page revisions | `data/attic/` | Old versions of pages. Can be large. | 28*8d8c8007Stracker-user| Media revisions | `data/media_attic/` | | 29*8d8c8007Stracker-user| Search index | `data/index/` | Rebuildable; off by default. | 30*8d8c8007Stracker-user| Configuration | `conf/` | Includes secrets — see below. `*.dist`, `*.example`, `*.bak` are filtered. | 31*8d8c8007Stracker-user| Plugins source | `lib/plugins/` | Useful for capturing local modifications. | 32*8d8c8007Stracker-user| Templates source | `lib/tpl/` | | 33*8d8c8007Stracker-user 34*8d8c8007Stracker-userAlways excluded: `data/cache/`, `data/tmp/`, `data/locks/`, `data/log/`, `_dummy` placeholders, `.DS_Store`, `Thumbs.db`, and `.git` / `.svn` / `.hg` directories anywhere. 35*8d8c8007Stracker-user 36*8d8c8007Stracker-userTo restore from an archive, follow the standard DokuWiki procedure: install a fresh DokuWiki of the same version, then untar your backup over the install root, overwriting existing files. You should be able to log in immediately with your previous credentials. 37*8d8c8007Stracker-user 38*8d8c8007Stracker-user## Security model 39*8d8c8007Stracker-user 40*8d8c8007Stracker-user- **Admin-only.** DokuWiki's `AdminPlugin` framework enforces `auth_isadmin()` before `handle()` or `html()` is invoked, because the plugin declares `forAdminOnly()`. A second explicit check in the streaming method catches any framework bypass. 41*8d8c8007Stracker-user- **CSRF-protected.** Every action submission is validated with DokuWiki's `checkSecurityToken()`. 42*8d8c8007Stracker-user- **POST-only downloads.** The Download button submits as POST; GET / HEAD / pre-fetch requests are rejected. A stray link or curious co-admin pasting a URL cannot trigger a backup. 43*8d8c8007Stracker-user- **Random filename.** Temp archives are named `sitebackup_tmp_<16 hex chars>.tar.gz` — 64 bits of CSPRNG entropy. 44*8d8c8007Stracker-user- **Locked-down storage.** The archive is written to `$conf['tmpdir']` (default `data/tmp/`), which DokuWiki protects with a deny-all `.htaccess`. The file is `chmod 0600` immediately after creation, with a `umask(0077)` set during writes. 45*8d8c8007Stracker-user- **Auto-deleted.** The temp file is removed both at the end of the stream and via a `register_shutdown_function` callback, so it disappears even on connection abort or fatal PHP error. 46*8d8c8007Stracker-user- **Stale sweep.** Every page load deletes any leftover `sitebackup_tmp_*` files older than 1 hour, in case a previous run died before reaching its shutdown handler. 47*8d8c8007Stracker-user 48*8d8c8007Stracker-user**The archive itself is sensitive.** If you include `conf/`, it may contain password hashes (`conf/users.auth.php`), ACL rules, and any credentials stored in `conf/local.php` (DB connection strings, SMTP passwords, API keys). Treat the downloaded file the same way you would treat your wiki's credentials and delete it from your local machine when you're done. 49*8d8c8007Stracker-user 50*8d8c8007Stracker-user## Install 51*8d8c8007Stracker-user 52*8d8c8007Stracker-userIn your wiki: 53*8d8c8007Stracker-user 54*8d8c8007Stracker-user1. **Admin → Extension Manager → Manual Install** 55*8d8c8007Stracker-user2. Upload `sitebackup.zip`, click **Install** 56*8d8c8007Stracker-user3. Refresh the Admin page; a **Site Backup** entry appears in the Additional Plugins section 57*8d8c8007Stracker-user 58*8d8c8007Stracker-userOr extract the zip into `lib/plugins/sitebackup/` directly if you have file access. 59*8d8c8007Stracker-user 60*8d8c8007Stracker-user## Use 61*8d8c8007Stracker-user 62*8d8c8007Stracker-user1. Open **Site Backup** from the Admin menu. 63*8d8c8007Stracker-user2. Tick the components you want. 64*8d8c8007Stracker-user3. Click **Preview** to see the file list and total size per section. 65*8d8c8007Stracker-user4. Click **Download tar.gz** to receive the archive in your browser. The download filename is `<hostname>-backup-<timestamp>.tar.gz`; the same directory structure appears as a single top-level directory inside the archive. 66*8d8c8007Stracker-user 67*8d8c8007Stracker-userFor very large wikis where the request might time out, run two passes — for example, one without `attic`/`media_attic`, then a second pass with only those checked. 68*8d8c8007Stracker-user 69*8d8c8007Stracker-user## Uninstall 70*8d8c8007Stracker-user 71*8d8c8007Stracker-userSame path: **Admin → Extension Manager**, find **Site Backup** under Installed Extensions, click **Uninstall**. 72*8d8c8007Stracker-user 73*8d8c8007Stracker-user## Compatibility 74*8d8c8007Stracker-user 75*8d8c8007Stracker-userTested on DokuWiki `2025-05-14b "Librarian"`. Should work on Greebo / Hogfather / Igor / Jack Jackrum / Kaos as well — the only DokuWiki APIs used are `AdminPlugin`, `dokuwiki\Form\Form`, `auth_isadmin()`, `checkSecurityToken()`, `msg()`, and the bundled `splitbrain\PHPArchive\Tar`, all of which have been stable. No external dependencies; uses only what ships with DokuWiki. 76*8d8c8007Stracker-user 77*8d8c8007Stracker-userPHP 7.4 or newer (uses array destructuring in `foreach` and `??`). 78*8d8c8007Stracker-user 79*8d8c8007Stracker-user## License 80*8d8c8007Stracker-user 81*8d8c8007Stracker-userGPL-2.0-or-later, matching DokuWiki itself. 82