Backups and maintenance
A backup is a recoverable copy of your knowledge and the files needed to use it. Page history can help undo a content edit; it does not replace a server backup.
Start with a new v0.1.2 installation using the installation guide. This page covers backing up the knowledge you create afterward, practicing restoration, and maintaining that installation. Before moving to a later software release, read the update instructions for that release.
What to keep together
| Installation | Data and configuration to preserve |
|---|---|
| Local default | All of ~/.dtxwiki, including the database, uploads, Library files, and session secret |
| systemd default | /var/lib/dtxwiki and /etc/dtxwiki; keep the wheel for the running version too |
| Docker default | The mounted /var/lib/dtxwiki data volume and your Compose configuration/.env |
| Internal CA | Caddy’s pki data or Docker caddy_data volume, so clients keep trusting the same certificate authority |
Custom paths take precedence over these defaults. Backups contain private pages, credentials, and signing keys; restrict their permissions and store a second copy outside the server.
Make a local backup
Stop dtxWiki (Ctrl+C) and any separately running worker before copying. With the default local path:
BACKUP_DIR="$HOME/dtxwiki-backups/$(date -u +%Y%m%dT%H%M%SZ)"
umask 077
mkdir -p "$BACKUP_DIR"
cp -a "$HOME/.dtxwiki" "$BACKUP_DIR/data"
Keep the backup outside ~/.dtxwiki so it is not copied into itself. Preserve any -wal/-shm files present. Record dtxwiki --version and the installed wheel or package version alongside the backup.
After the copy succeeds, restart the app with dtxwiki in one terminal and the worker with dtxwiki-worker run in a second terminal. For an npm installation, use the launcher and matching uvx/pipx worker commands from installation. Use the same account, installed package, and data/database settings as before the backup for both processes. Starting the app does not start the worker; imports and other queued background jobs need the worker to resume.
Make a systemd backup
Schedule a brief outage so no one writes during the backup. The SQLite command requires the sqlite3 utility on the server.
BACKUP_STAMP="$(date -u +%Y%m%dT%H%M%SZ)"
BACKUP_DIR="/var/backups/dtxwiki/$BACKUP_STAMP"
if sudo install -d -o dtxwiki -g dtxwiki -m 0700 "$BACKUP_DIR" &&
sudo systemctl stop dtxwiki-worker dtxwiki &&
sudo -u dtxwiki sqlite3 /var/lib/dtxwiki/dtxwiki.sqlite \
".backup '$BACKUP_DIR/dtxwiki.sqlite'" &&
sudo install -d -o root -g root -m 0700 "$BACKUP_DIR/data" &&
sudo cp -a /var/lib/dtxwiki/. "$BACKUP_DIR/data/" &&
sudo cp -a /etc/dtxwiki "$BACKUP_DIR/etc-dtxwiki" &&
sudo chown -R root:root "$BACKUP_DIR" &&
sudo chmod -R go-rwx "$BACKUP_DIR" &&
sudo sha256sum "$BACKUP_DIR/dtxwiki.sqlite"; then
sudo systemctl start dtxwiki dtxwiki-worker
else
printf '%s\n' 'Backup incomplete. Inspect the error before restarting or upgrading.'
fi
If a backup step fails, resolve it before upgrading. For internal TLS, also preserve /var/lib/caddy/.local/share/caddy/pki when that is the Caddy CA path. The top-level dtxwiki.sqlite created with .backup is the database to restore; the copy under data/ is included to preserve the complete original directory.
Make a Docker backup
Run from the infra/prod directory you used for installation. The archive contains secrets; the private directory and archive permissions matter.
BACKUP_DIR="$HOME/dtxwiki-backups"
if docker compose stop app worker &&
APP_CONTAINER="$(docker compose ps --all --quiet app)" &&
test -n "$APP_CONTAINER" &&
(umask 077 && mkdir -p "$BACKUP_DIR") &&
docker run --rm --volumes-from "$APP_CONTAINER" \
-v "$BACKUP_DIR:/backup" alpine \
sh -c 'umask 077; tar czf "/backup/dtxwiki-$(date -u +%Y%m%dT%H%M%SZ).tgz" -C /var/lib/dtxwiki .'; then
docker compose start app worker
else
printf '%s\n' 'Backup incomplete. Inspect the error before restarting or upgrading.'
fi
Keep a protected copy of .env and the Compose configuration too. With internal TLS, archive the Caddy volume containing its CA. Do not use down -v, remove the data volume, or prune volumes. Keep the Compose project name and database/data paths unchanged during updates.
Check database state before maintenance
For an active systemd deployment, collect a read-only revision inventory before stopping services:
sudo dtxwiki db revision-inventory --configured prod
This collects evidence; it is not approval to migrate. The supported revision chain is bd62193d5cf6 → efcbcf724889, with efcbcf724889 as the current head. A recognized revision must also have consistency=consistent. The maintenance command still performs its own preflight check.
This inventory command currently requires SQLite WAL sidecars (-wal/-shm). A cleanly stopped, checkpointed database may produce sqlite_wal_sidecars_required; that result alone does not prove corruption. Keep the evidence from the running deployment and use the supported preflight for the final decision.
If a database check refuses to continue, preserve the database and backup and follow Troubleshooting. Do not use a blind revision stamp or delete the database to bypass the check. If the database records 0001_initial_release or 0002_epic1, follow the explicit, schema-checked conversion below.
Convert existing revision identifiers
This is an administrator task only when reusing a database with 0001_initial_release or 0002_epic1 recorded in it. A new installation does not need it. The supported mappings are:
| Existing identifier | Supported identifier |
|---|---|
0001_initial_release | bd62193d5cf6 |
0002_epic1 | efcbcf724889 |
Stop the server and worker, verify a recoverable backup, and install the v0.1.2 code without starting the app. Load the configuration of the actual database you intend to use. The conversion checks the schema and changes only its revision record; it does not replay table or data migrations. Unsupported schemas are refused. App startup does not perform this conversion automatically.
For a local Python-package installation, reinstall the pinned package with your original tool, then preview:
# pipx
pipx install --force --python python3.12 'dtxwiki==0.1.2'
# Or uv: uv tool install --force --python python3.12 'dtxwiki==0.1.2'
dtxwiki db rename-revisions
For npm, the matching launcher can run the preview without starting the server:
npx @dtxsuite/dtxwiki@0.1.2 db rename-revisions
Check the actual database configuration and the reported mapping before applying it:
# Local Python-package installation
dtxwiki db rename-revisions --apply
# npm installation
npx @dtxsuite/dtxwiki@0.1.2 db rename-revisions --apply
Only after a successful conversion, start the app and its matching worker using installation. If a command refuses the database, leave the writers stopped and keep the original backup.
systemd
Use the v0.1.2 wheel from deployment. With services stopped, install that wheel, then preview through the wrapper that loads /etc/dtxwiki/dtxwiki.env:
chmod 0644 /tmp/dtxwiki-0.1.2-py3-none-any.whl
sudo systemctl stop dtxwiki-worker dtxwiki &&
sudo -u dtxwiki /opt/dtxwiki/.venv/bin/pip install --upgrade --force-reinstall \
/tmp/dtxwiki-0.1.2-py3-none-any.whl &&
sudo dtxwiki db rename-revisions
After checking the preview and backup:
sudo dtxwiki db rename-revisions --apply &&
sudo dtxwiki bootstrap &&
sudo systemctl start dtxwiki dtxwiki-worker &&
curl -fsS https://wiki.example.com/health/ready
The ordinary package-index update command does not perform this identifier conversion for you.
Docker
Keep the existing checkout location, Compose project name, environment, and data volume. Stop app and worker and complete the backup first. Select tag v0.1.2 in that checkout, then run from its infra/prod directory:
docker compose build &&
docker compose run --rm --no-deps app dtxwiki db rename-revisions
--no-deps prevents the init service from trying to migrate the database before its identifiers have been converted. The app service retains the configured database and SKIP_BOOTSTRAP=1 environment. After checking the preview:
docker compose run --rm --no-deps app dtxwiki db rename-revisions --apply &&
docker compose run --rm --no-deps app dtxwiki bootstrap &&
docker compose up -d
Check docker compose ps, /health/ready, sign-in, and a content read. Never remove the data volume to resolve a revision error.
Maintain or reinstall v0.1.2
The examples below reinstall the documented version when repairing an installation. They are separate from first-time setup. For a later release, use that release's instructions and matching package or source tag.
Local package
After backing up and stopping the local application and worker, reinstall v0.1.2 with the tool you used originally:
pipx install --force --python python3.12 'dtxwiki==0.1.2'
For a source-built package, use the exact wheel from installation and your package tool’s local-wheel install/reinstall procedure. Specify the version explicitly rather than using pipx upgrade dtxwiki, which selects the latest available package.
If you originally used uv, use uv tool install --force --python python3.12 'dtxwiki==0.1.2'. For npm, the launcher version chooses the Python application version: after stopping both writers and backing up, use npx @dtxsuite/dtxwiki@0.1.2, or reinstall a global launcher with npm install --global @dtxsuite/dtxwiki@0.1.2. In an npm installation, dtxwiki update and dtxwiki rollback print npm instructions and do not change the application. Use the separate matching worker commands from installation.
systemd: a verified local wheel
Use the wheel made by the deployment procedure. Preserve the previous wheel and complete the backup first:
chmod 0644 /tmp/dtxwiki-0.1.2-py3-none-any.whl
if sudo systemctl stop dtxwiki-worker dtxwiki &&
sudo -u dtxwiki /opt/dtxwiki/.venv/bin/pip install --upgrade --force-reinstall \
/tmp/dtxwiki-0.1.2-py3-none-any.whl &&
sudo dtxwiki bootstrap; then
sudo systemctl start dtxwiki dtxwiki-worker &&
curl -fsS https://wiki.example.com/health/ready
else
printf '%s\n' 'Update failed. Keep services stopped; inspect the error and restore if needed.'
fi
If bootstrap fails, leave the services stopped until you have resolved the problem or restored the backup.
For a later package-index update, consult that release's guide and the systemd wrapper's sudo dtxwiki update --help. The update command handles backup, package installation, migration, restart, and readiness checks. A failure prints recovery instructions; it does not automatically roll back. Migration-stage failure can leave services stopped to avoid serving a partial database.
Docker: rebuild from a pinned version
After a backup, use the installation checkout to select tag v0.1.2 with git checkout --detach v0.1.2 and rebuild that version. From infra/prod, run docker compose build then docker compose up -d. The init service prepares the database. Check docker compose ps and /health/ready before reopening access.
Practice restoration
Restore to a separate machine first using the same app version, data, uploads, configuration, and keys. Check /health/ready, sign-in, a published Context page, and its images or attachments. Keep an isolated restore from sending real recovery mail or accepting real client traffic.
For systemd package-index updates, sudo dtxwiki rollback --list shows managed backups and sudo dtxwiki rollback --to-backup /var/lib/dtxwiki/backups/EXACT_BACKUP_ID restores a chosen backup. It needs the previous wheel to remain available in the package index. Manually supplied wheels require preserving and reinstalling the matching previous wheel plus the data/configuration backup set. Restore code and database together.
See Troubleshooting for migration_preflight_refused and runtime-lock errors.
Version evidence: backup and upgrade runbook, blocked-database behavior, version-specific pipx install command, schema-checked revision conversion.