{"_id":"@alphanull/directus-extension-backup","_rev":"5-d5a0b34daf21d932c19fb68a5614efce","name":"@alphanull/directus-extension-backup","dist-tags":{"latest":"0.10.2"},"versions":{"0.9.0":{"name":"@alphanull/directus-extension-backup","version":"0.9.0","keywords":["directus-extension","directus","docker","backup","restore"],"author":{"name":"Frank Kudermann","email":"kudermann@alphanull.de"},"license":"AGPL-3.0-only","_id":"@alphanull/directus-extension-backup@0.9.0","maintainers":[{"name":"alphanull","email":"kudermann@alphanull.de"}],"homepage":"https://github.com/alphanull/directus-backup","bugs":{"url":"https://github.com/alphanull/directus-backup/issues"},"dist":{"shasum":"d6a4b20b27888b41a87341549b08dcca614959e5","tarball":"https://registry.npmjs.org/@alphanull/directus-extension-backup/-/directus-extension-backup-0.9.0.tgz","fileCount":5,"integrity":"sha512-J6VGLy6FnqQIPhRV9DIIH7zvDPVXbxR7l9TU7qDeUM9soSZjzFTaEmXgCyTZz7t8d6LEnbb6C5vCvkRJ1FbSwA==","signatures":[{"sig":"MEUCIQD6E+sLrQBsa+F/am368Va7Cr3ztsx+/mVrUY+3YClnkQIgK5RXnDLaC/yH1nDmLJl9CeglikkUzbuoCOvbVm8BdzQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":191970},"icon":"backup","type":"module","engines":{"node":">=18"},"gitHead":"39d14bbc6b0998e8fd5b71619bcea0bfc723f171","scripts":{"dev":"directus-extension build -w --no-minify","test":"vitest run","build":"directus-extension build --no-minify","prebuild":"npm run typecheck","typecheck":"tsc --noEmit -p tsconfig.test.json","test:watch":"vitest","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"alphanull","email":"kudermann@alphanull.de"},"repository":{"url":"git+https://github.com/alphanull/directus-backup.git","type":"git","directory":"packages/extension"},"_npmVersion":"10.9.8","description":"Backup & restore UI for Directus — admin module + API proxy to the backup sidecar","directories":{},"_nodeVersion":"22.22.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.5.35","vitest":"^4.1.8","vue-i18n":"^11.4.5","typescript":"^6.0.3","@vitest/coverage-v8":"^4.1.8","@directus/extensions-sdk":"^17.1.4"},"directus:extension":{"host":"^11.0.0","path":{"api":"dist/api.js","app":"dist/app.js"},"type":"bundle","entries":[{"name":"backup-module","type":"module","source":"src/module/index.ts"},{"name":"backup-api","type":"endpoint","source":"src/api/index.ts"}]},"_npmOperationalInternal":{"tmp":"tmp/directus-extension-backup_0.9.0_1780757154819_0.6669921899121138","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package is no longer maintained. See https://github.com/alphanull/directus-backup for archived source."},"0.10.0":{"name":"@alphanull/directus-extension-backup","version":"0.10.0","keywords":["directus-extension","directus","backup","restore"],"author":{"name":"Frank Kudermann","email":"kudermann@alphanull.de"},"license":"AGPL-3.0-only","_id":"@alphanull/directus-extension-backup@0.10.0","maintainers":[{"name":"alphanull","email":"kudermann@alphanull.de"}],"homepage":"https://github.com/alphanull/directus-backup","bugs":{"url":"https://github.com/alphanull/directus-backup/issues"},"dist":{"shasum":"2df86fd12d15d7b5bbcea0da3e82f2361a03774d","tarball":"https://registry.npmjs.org/@alphanull/directus-extension-backup/-/directus-extension-backup-0.10.0.tgz","fileCount":21,"integrity":"sha512-PmEd4XBavzHPVGeDcg/OgRb1uaKgLqFVH3T24WOgOxTUcyKsenosgXD8lc92xD43IGOflA84ksnyclfbRtP0AQ==","signatures":[{"sig":"MEUCIQDFKfqijgXjt1GstfPr6TVMASViO5T5FmzKGh1IW/+/2gIgc8f4BsOJBTYozLBvAV7vcouwUKTlI3w4Qop9vBlOcDs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@alphanull%2fdirectus-extension-backup@0.10.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":484954},"icon":"backup","type":"module","engines":{"node":">=18"},"gitHead":"31a2f6f0f4112696767eec2c5081a45770c97d4c","scripts":{"dev":"directus-extension build -w --no-minify","lint":"eslint . && stylelint \"**/*.{css,scss,vue}\" --ignore-path .gitignore","test":"vitest run && npm run test:adapters && npm run test:runner","build":"directus-extension build --no-minify","prebuild":"npm run typecheck","typecheck":"tsc --noEmit -p tsconfig.test.json","test:watch":"vitest","test:runner":"sh test/runner/restore-result.test.sh && sh test/runner/path-decoupling.test.sh && sh test/runner/recover-flag-env.test.sh && sh test/runner/restore-timeout.test.sh","test:adapters":"sh test/adapters/postgres-restore.test.sh","test:coverage":"vitest run --coverage","test:integration":"bash test/integration/run.sh"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:605b1a48-f3b8-4876-9527-f9fa612023ea"}},"repository":{"url":"git+https://github.com/alphanull/directus-backup.git","type":"git"},"_npmVersion":"11.17.0","description":"Self-contained backup & restore for Directus — admin module + API, no sidecar, no Docker socket","directories":{},"_nodeVersion":"22.22.3","dependencies":{"node-cron":"^4.2.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.5.35","eslint":"^10.4.1","vitest":"^4.1.8","globals":"^17.6.0","vue-i18n":"^11.4.5","stylelint":"^17.12.0","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^25.9.2","postcss-html":"^1.8.1","stylelint-scss":"^7.2.0","stylelint-order":"^8.1.1","eslint-plugin-vue":"^10.9.2","typescript-eslint":"^8.60.1","vue-eslint-parser":"^10.4.1","@vitest/coverage-v8":"^4.1.8","eslint-plugin-jsdoc":"^63.0.2","@directus/extensions-sdk":"^17.1.4","@stylistic/eslint-plugin":"^5.10.0","@stylistic/stylelint-plugin":"^5.2.0"},"directus:extension":{"host":"^11.0.0","path":{"api":"dist/api.js","app":"dist/app.js"},"type":"bundle","entries":[{"name":"backup-module","type":"module","source":"src/module/index.ts"},{"name":"backup-api","type":"endpoint","source":"src/api/index.ts"}]},"_npmOperationalInternal":{"tmp":"tmp/directus-extension-backup_0.10.0_1781281374012_0.4865630596339454","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package is no longer maintained. See https://github.com/alphanull/directus-backup for archived source."},"0.10.1":{"name":"@alphanull/directus-extension-backup","version":"0.10.1","keywords":["directus-extension","directus","backup","restore"],"author":{"name":"Frank Kudermann","email":"kudermann@alphanull.de"},"license":"AGPL-3.0-only","_id":"@alphanull/directus-extension-backup@0.10.1","maintainers":[{"name":"alphanull","email":"kudermann@alphanull.de"}],"homepage":"https://github.com/alphanull/directus-backup","bugs":{"url":"https://github.com/alphanull/directus-backup/issues"},"dist":{"shasum":"91b992cb6db4691d4298cbda1c6544cc7dd24ce3","tarball":"https://registry.npmjs.org/@alphanull/directus-extension-backup/-/directus-extension-backup-0.10.1.tgz","fileCount":21,"integrity":"sha512-ozhPSURNr+QEnWUgYeSKjRAZ1q/Toa6+phNiAKX8If2y2559LwZR4FhGKmlFuP/vcmIubQMqzHoVY57e6sQFwQ==","signatures":[{"sig":"MEUCIF5QlqQBBRJ8qZiPinvIrRTETKGeCFf3Ba2T/gWw6ZsLAiEA1TZPsfxeLasdvW1/ENW++o5UDwVDB1Eq0OSTnlTnFcM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@alphanull%2fdirectus-extension-backup@0.10.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":484955},"icon":"backup","type":"module","engines":{"node":">=18"},"gitHead":"7bf9ee816ca639eb2dd6ac5a4f98a66743fcc051","scripts":{"dev":"directus-extension build -w --no-minify","lint":"eslint . && stylelint \"**/*.{css,scss,vue}\" --ignore-path .gitignore","test":"vitest run && npm run test:adapters && npm run test:runner","build":"directus-extension build --no-minify","prebuild":"npm run typecheck","typecheck":"tsc --noEmit -p tsconfig.test.json","test:watch":"vitest","test:runner":"sh test/runner/restore-result.test.sh && sh test/runner/path-decoupling.test.sh && sh test/runner/recover-flag-env.test.sh && sh test/runner/restore-timeout.test.sh","test:adapters":"sh test/adapters/postgres-restore.test.sh","test:coverage":"vitest run --coverage","test:integration":"bash test/integration/run.sh"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:605b1a48-f3b8-4876-9527-f9fa612023ea"}},"repository":{"url":"git+https://github.com/alphanull/directus-backup.git","type":"git"},"_npmVersion":"11.17.0","description":"Self-contained backup & restore for Directus — admin module + API, no sidecar, no Docker socket","directories":{},"_nodeVersion":"22.22.3","dependencies":{"node-cron":"^4.2.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.5.35","eslint":"^10.4.1","vitest":"^4.1.8","globals":"^17.6.0","vue-i18n":"^11.4.5","stylelint":"^17.12.0","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^25.9.2","postcss-html":"^1.8.1","stylelint-scss":"^7.2.0","stylelint-order":"^8.1.1","eslint-plugin-vue":"^10.9.2","typescript-eslint":"^8.60.1","vue-eslint-parser":"^10.4.1","@vitest/coverage-v8":"^4.1.8","eslint-plugin-jsdoc":"^63.0.2","@directus/extensions-sdk":"^17.1.4","@stylistic/eslint-plugin":"^5.10.0","@stylistic/stylelint-plugin":"^5.2.0"},"directus:extension":{"host":"^11.0.0","path":{"api":"dist/api.js","app":"dist/app.js"},"type":"bundle","entries":[{"name":"backup-module","type":"module","source":"src/module/index.ts"},{"name":"backup-api","type":"endpoint","source":"src/api/index.ts"}]},"_npmOperationalInternal":{"tmp":"tmp/directus-extension-backup_0.10.1_1781295747686_0.24935254671352003","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package is no longer maintained. See https://github.com/alphanull/directus-backup for archived source."},"0.10.2":{"name":"@alphanull/directus-extension-backup","version":"0.10.2","keywords":["directus-extension","directus","backup","restore"],"author":{"name":"Frank Kudermann","email":"kudermann@alphanull.de"},"license":"AGPL-3.0-only","_id":"@alphanull/directus-extension-backup@0.10.2","maintainers":[{"name":"alphanull","email":"kudermann@alphanull.de"}],"homepage":"https://github.com/alphanull/directus-backup","bugs":{"url":"https://github.com/alphanull/directus-backup/issues"},"dist":{"shasum":"a736681b356064d2623dff752bda80032ec62721","tarball":"https://registry.npmjs.org/@alphanull/directus-extension-backup/-/directus-extension-backup-0.10.2.tgz","fileCount":21,"integrity":"sha512-S8rSOwdCDnqhTuMYxmS6+GEJ077ce+JvihFYt8JiB+rp2bjUxIBub11JSMWGKZqPFb/5S3kYoBzh3ieOjtSRQQ==","signatures":[{"sig":"MEQCIDesYIhHtPcDPC336fK2IqVU1gqH4kdkVUvYUYuNqf5XAiBou/gKELjQ7fc+GMdx/+9dK1iJsDfpavpckyzt3RzbZw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@alphanull%2fdirectus-extension-backup@0.10.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":485386},"icon":"backup","type":"module","engines":{"node":">=18"},"gitHead":"688e34e91a8ef19a0200d623244e500f3134a4fc","scripts":{"dev":"directus-extension build -w --no-minify","lint":"eslint . && stylelint \"**/*.{css,scss,vue}\" --ignore-path .gitignore","test":"vitest run && npm run test:adapters && npm run test:runner","build":"directus-extension build --no-minify","prebuild":"npm run typecheck","typecheck":"tsc --noEmit -p tsconfig.test.json","test:watch":"vitest","test:runner":"sh test/runner/restore-result.test.sh && sh test/runner/path-decoupling.test.sh && sh test/runner/recover-flag-env.test.sh && sh test/runner/restore-timeout.test.sh","test:adapters":"sh test/adapters/postgres-restore.test.sh","test:coverage":"vitest run --coverage","test:integration":"bash test/integration/run.sh"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:605b1a48-f3b8-4876-9527-f9fa612023ea"}},"repository":{"url":"git+https://github.com/alphanull/directus-backup.git","type":"git"},"_npmVersion":"11.17.0","description":"Self-contained backup & restore for Directus — admin module + API, no sidecar, no Docker socket","directories":{},"_nodeVersion":"22.22.3","dependencies":{"node-cron":"^4.2.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.5.35","eslint":"^10.4.1","vitest":"^4.1.8","globals":"^17.6.0","vue-i18n":"^11.4.5","stylelint":"^17.12.0","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^25.9.2","postcss-html":"^1.8.1","stylelint-scss":"^7.2.0","stylelint-order":"^8.1.1","eslint-plugin-vue":"^10.9.2","typescript-eslint":"^8.60.1","vue-eslint-parser":"^10.4.1","@vitest/coverage-v8":"^4.1.8","eslint-plugin-jsdoc":"^63.0.2","@directus/extensions-sdk":"^17.1.4","@stylistic/eslint-plugin":"^5.10.0","@stylistic/stylelint-plugin":"^5.2.0"},"directus:extension":{"host":"^11.0.0","path":{"api":"dist/api.js","app":"dist/app.js"},"type":"bundle","entries":[{"name":"backup-module","type":"module","source":"src/module/index.ts"},{"name":"backup-api","type":"endpoint","source":"src/api/index.ts"}]},"_npmOperationalInternal":{"tmp":"tmp/directus-extension-backup_0.10.2_1781951392924_0.1685790014704045","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package is no longer maintained. See https://github.com/alphanull/directus-backup for archived source."}},"time":{"created":"2026-06-06T14:45:54.662Z","modified":"2026-06-20T10:31:08.498Z","0.9.0":"2026-06-06T14:45:54.965Z","0.10.0":"2026-06-12T16:22:54.194Z","0.10.1":"2026-06-12T20:22:27.894Z","0.10.2":"2026-06-20T10:29:53.077Z"},"bugs":{"url":"https://github.com/alphanull/directus-backup/issues"},"author":{"name":"Frank Kudermann","email":"kudermann@alphanull.de"},"license":"AGPL-3.0-only","homepage":"https://github.com/alphanull/directus-backup","keywords":["directus-extension","directus","backup","restore"],"repository":{"url":"git+https://github.com/alphanull/directus-backup.git","type":"git"},"description":"Self-contained backup & restore for Directus — admin module + API, no sidecar, no Docker socket","maintainers":[{"name":"alphanull","email":"kudermann@alphanull.de"}],"readme":"# Directus Backup\n\n> ‼️ **DISCONTINUED** — This project has been discontinued and is no longer actively maintained. As I have decided to move away from Directus for future projects, no further development, feature requests, bug fixes, or compatibility updates are planned. The repository will remain available readonly for reference and for existing users, at least for some time. Feel free to clone it, fork it, or build upon it.\n\nFull backup and restore system for Directus. Create, schedule, download, upload, and restore backups through a UI module in Directus Studio — running **entirely inside Directus**, with no sidecar container and no Docker socket access.\n\n## Features\n\n- **No sidecar, no Docker socket** — installs as a single Directus extension; restore is driven by a container restart instead of a privileged Docker connection\n- **Complete Directus backups** — database, uploads, and extensions in a single archive\n- **Full & partial restore** — restore the entire system or individual collections directly from the UI\n- **Selective scope** — choose which components to include, exclude specific collections\n- **Scheduled backups** — configurable intervals (hourly to weekly) with automatic retention\n- **Import & Export backups** — download and upload backups (must be enabled manually)\n- **Localized UI** — full-featured backup module built into Directus Studio, currently available in English and German\n- **Integrity verification** — SHA-256 checksums + row-count comparison on every restore\n- **Crash-safe restore** — multi-stage validation before the destructive step; the restore runs on a clean container boot while the database is idle\n- **Disaster recovery** — the host CLI (`scripts/recover.sh`) can arm a restore without Directus Studio, even when Directus will not boot (e.g. a corrupt or destroyed database)\n- **Storage management** — quota limits, free-space checks, automatic rotation\n- **PostgreSQL support** — PostgreSQL is the supported database adapter in this release; the runner keeps an internal adapter boundary for future engines\n- **Activity logs** — keep track of all operations\n- **Admin notifications** — in-app alerts on scheduled backup failures\n\n## Screenshot\n\n![Backup list with status, size, and activity log](https://raw.githubusercontent.com/alphanull/directus-backup/main/docs/images/screenshot.jpg)\n\n## How It Works\n\nThe extension runs **inside the Directus container** as a bundle of two parts: a Vue **UI module** and an **API endpoint** mounted at `/backup-api/`. There is no separate service and no Docker socket.\n\n- **Backups** run as a child process (`backup.sh`) spawned by the endpoint. Because the heavy work happens in its own process, Directus itself stays responsive. The backup process shares the container's CPU/RAM limits with Directus — size them accordingly.\n- **Restores** cannot run while Directus holds open database connections, so the destructive work is moved out of the running process entirely:\n  1. The endpoint **validates** the backup while Directus is still up (status, checksums, `pg_restore --list`, DB reachability) — before the point of no return.\n  2. It writes a restore **flag** to the backup volume and sends `SIGTERM` to PID 1.\n  3. The container's `restart: unless-stopped` policy **restarts** the container. A small entrypoint stub runs the restore on the clean boot — while the database has zero application connections — *before* Directus starts.\n  4. On the next boot the endpoint **reconciles** the manifest from the restore result and releases the locks.\n\nThis restart-based mechanism is why the deployment needs a custom entrypoint and a restart policy (see [Quick Start](#quick-start)).\n\n## Before You Start\n\n> ‼️ **WARNING - Beta Software** — This project is not under active development anymore and has not been tested across all possible configurations and environments. It is **not recommended** to run this directly in a production environment without prior testing in a staging setup. Feedback, bug reports, and contributions are very welcome and greatly appreciated.\n\n> ‼️ **IMPORTANT** - The API endpoint uses **direct database access** for authorization and **spawns a child process** for backups, so it is **not sandboxed**. A Marketplace install therefore requires `MARKETPLACE_TRUST=all` on self-hosted instances; Directus Cloud does not allow this and is not supported. `BACKUP_IMPORT_ENABLED` and `BACKUP_EXPORT_ENABLED` have security implications and are disabled by default for a reason — see [Security](https://github.com/alphanull/directus-backup/blob/main/docs/security.md).\n\n> ⚠️ **Upgrading from an earlier version?** The architecture has changed fundamentally — the separate backup **sidecar container** is gone and everything now runs **inside the Directus container**. The npm package and Marketplace entry are unchanged, but the deployment is not: a custom image, a restart policy, and a backup volume are now required. If you are coming from the sidecar-based release, read the [Migration Guide](https://github.com/alphanull/directus-backup/blob/main/docs/migration.md) **before upgrading**.\n\n## Quick Start\n\nUnlike the sidecar deployment, everything runs in the Directus container. Setup is: update the Directus service in Compose, add the Dockerfile it builds from, install the extension.\n\n### 1. Configure the Directus service\n\nOpen the `docker-compose.yml` (or `compose.yaml`) that starts Directus and find your existing `directus:` service. Replace the stock `image: directus/directus:...` line with `build: .`, then add the **restart policy** (required — it is what brings the container back after a restore) and mount a **backup volume**.\n\n`build: .` means Compose will build a `Dockerfile` from the same folder as your Compose file. You will add that `Dockerfile` in step 2; do not start the stack until both steps are done. The extension reuses Directus's own database and cache settings, so no extra DB credentials are needed.\n\n```yaml\ndirectus:\n  build: .                 # builds the Dockerfile from step 2\n  restart: unless-stopped  # REQUIRED — the restore restarts the container\n  volumes:\n    - ./uploads:/directus/uploads\n    - ./extensions:/directus/extensions\n    - backups:/directus/backups   # backup storage (BACKUP_DIR)\n  environment:\n    # Reused by the extension — typically already present on your Directus service:\n    DB_CLIENT: pg\n    DB_HOST: database\n    DB_DATABASE: ${DB_DATABASE}\n    DB_USER: ${DB_USER}\n    DB_PASSWORD: ${DB_PASSWORD}\n    # Optional — enable upload/download of backup archives (off by default):\n    BACKUP_IMPORT_ENABLED: \"true\"\n    BACKUP_EXPORT_ENABLED: \"true\"\n\nvolumes:\n  backups:\n```\n\n> ⚠️ **NOTE** The `backups:` named volume shown above does not require a host directory. If you use a bind mount instead (for example `./backups:/directus/backups`), the host directory must be writable by uid 1000.\n\n> ⚠️ **NOTE** Backups run inside the Directus container and share its CPU/RAM limits. If your `directus:` service has explicit CPU or memory limits in Compose, remember that backups share those limits. In this case, as a practical starting point, give the Directus service about **one additional CPU** if backups run during normal traffic. If scheduled for quiet hours, less may be enough. Run one representative backup in staging and adjust CPU/RAM or the schedule if Directus latency becomes noticeable.\n\n### 2. Add the Dockerfile\n\nThe stock Directus image has no Dockerfile and does not ship `pg_dump`/`pg_restore`, and the restore must run on a clean boot **before** Directus starts (see [Architecture](https://github.com/alphanull/directus-backup/blob/main/docs/architecture.md#restore-data-flow)). Therefore, first check whether there is already a `Dockerfile` next to the Compose file from step 1.\n\n- **No existing Dockerfile:** copy `[examples/Dockerfile](https://github.com/alphanull/directus-backup/blob/main/examples/Dockerfile)` into that folder. If your Compose file used a different Directus image tag, update the `FROM directus/directus:...` line to the same Directus version.\n- **Existing Dockerfile:** do not replace it blindly. Merge the required parts instead: install the PostgreSQL client as `root`, add the restore entrypoint logic before Directus starts, create `/directus/backups` with `node` ownership, and preserve any existing `ENTRYPOINT`/`CMD` behavior. See the detailed [Installation guide](https://github.com/alphanull/directus-backup/blob/main/docs/installation.md#step-2--add-the-dockerfile).\n\n### 3. Install the extension\n\n- **Marketplace:** in **Settings → Marketplace**, search for `backup` (or `@alphanull/directus-extension-backup`) and install. Requires `MARKETPLACE_TRUST=all` (see [Before You Start](#before-you-start)).\n- **Manual:** copy the package contents — the `dist/` directory, `scripts/`, and `package.json` — into your Directus extensions folder as `extensions/directus-extension-backup/`. The `scripts/` directory (which contains `backup.sh`, `restore.sh`, `recover.sh`, and the adapters) must be included; the entrypoint from step 2 looks it up there.\n\n### 4. Build and start\n\n```sh\ndocker compose up -d --build\n```\n\n### 5. Enable the module\n\nIn Directus Studio, go to **Settings → Modules**, enable **Backup**, and save. The Backup module then appears for admin users and users with the **Backup Access** policy.\n\n## Disaster Recovery\n\nRestores can be triggered without the Directus Studio UI — and even when Directus will not boot at all (e.g. a corrupt or destroyed database) — with the `scripts/recover.sh` host CLI. It writes the restore flag into the backup volume via a throwaway helper container and restarts the Directus container; `scripts/restore.sh` then runs on the next boot before Directus starts.\n\n```sh\n# Interactive picker — lists available backups:\nCONTAINER=<your-directus-container> ./scripts/recover.sh\n\n# Or restore a specific backup directly:\nCONTAINER=<your-directus-container> ./scripts/recover.sh 2026-02-20__14-30-00__manual\n```\n\nSee [Security](https://github.com/alphanull/directus-backup/blob/main/docs/security.md#disaster-recovery-cli) for the security implications.\n\n## Access control\n\nAdmin users always have access. Non-admins are granted access via a Directus **access policy** named exactly `Backup Access`. The extension does **not** create this policy — create it manually and assign it to roles and/or users. The policy needs no permissions of its own; the endpoint only checks that it is *assigned*.\n\n## Documentation\n\nThe full documentation set lives in the [main repository](https://github.com/alphanull/directus-backup):\n\n- [Installation](https://github.com/alphanull/directus-backup/blob/main/docs/installation.md) — custom image, entrypoint, restart policy, backup volume, enabling the module\n- [Configuration](https://github.com/alphanull/directus-backup/blob/main/docs/configuration.md) — schedule, retention, quota, scope\n- [Architecture](https://github.com/alphanull/directus-backup/blob/main/docs/architecture.md) — API, data flow, restore lifecycle, locking model, manifest schema\n- [Security](https://github.com/alphanull/directus-backup/blob/main/docs/security.md) — trust model, authentication, import/export risks\n- [Development](https://github.com/alphanull/directus-backup/blob/main/docs/development.md) — building, testing, publishing\n- [DB Adapter](https://github.com/alphanull/directus-backup/blob/main/docs/db-adapters.md) — PostgreSQL support and the internal adapter boundary\n- [Migration](https://github.com/alphanull/directus-backup/blob/main/docs/migration.md) — upgrading from the sidecar-based release\n\n## License\n\nCopyright (c) 2026 Frank Kudermann / alphanull\n\nLicensed under the GNU Affero General Public License v3.0 only (AGPL-3.0-only).\nSee the [LICENSE](https://github.com/alphanull/directus-backup/blob/main/LICENSE) file for details.\n\nCommercial licensing is available for use cases not covered by the AGPL\n(e.g. integration into a closed-source product or a hosted/managed service).\nContact: [kudermann@alphanull.de](mailto:kudermann@alphanull.de).\n","readmeFilename":"README.md"}