npx CLI tool to create a full backup of a Storyblok space and restore single resources from it.
npm install storyblok-backup

A npx CLI tool to create a full backup of a space of the Storyblok CMS.
A restore tool to restore (create or update) resources is also included.
The backup script will fetch the following resources of a Storyblok space using the Management API and archive them in a zip file:
- Stories
- Collaborators
- Components
- Component groups
- Assets (optionally incl. original files)
- Asset folders
- Internal Tags
- Datasources (incl. entries)
- Space
- Space Roles
- Tasks
- Activities
- Presets
- Field types
- Webhooks
- Workflows
- Workflow stages
- Workflow stage changes
- Releases
- Pipeline Branches
- Access Tokens
The restore script is able to individually restore the resources from the backup files (via update or create) with the following exceptions:
- Assets: Only updating asset-resource-data is supported. Creating assets and updating asset-files is not supported.
- Field types: Currently not supported
- Workflow stage changes: No update possible.
- Access Tokens: Creating access tokens from backup makes no sense, since it will result in a new token-string.
- Installation
- Usage
- Backup
- Backup options
- Minimal backup example
- Maximal backup example
- Continuous backup integration examples
- Example for a GitHub workflow for a complete backup as an artifact
- Example for a GitHub workflow for an incremental git-commit-based backup
- Restore
- Restore options
- Minimal restore example
- Maximal restore example
``shell
Usage
$3
Call
npx storyblok-backup with the following options:#### Backup options
`text
--token (required) Personal OAuth access token created
in the account settings of a Stoyblok user.
(NOT the Access Token of a Space!)
Alternatively, you can set the STORYBLOK_OAUTH_TOKEN environment variable.
--space (required) ID of the space to backup
Alternatively, you can set the STORYBLOK_SPACE_ID environment variable.
--region Region of the space. Possible values are:
- 'eu' (default): EU
- 'us': US
- 'ap': Australia
- 'ca': Canada
- 'cn': China
Alternatively, you can set the STORYBLOK_REGION environment variable.
--types Comma separated list of resource-types to backup (default=all).
Possible values are:
- 'stories'
- 'collaborators'
- 'components'
- 'component-groups'
- 'assets'
- 'asset-folders'
- 'internal-tags'
- 'datasources'
- 'space'
- 'space-roles'
- 'tasks'
- 'activities'
- 'presets'
- 'field-types'
- 'webhooks'
- 'workflow-stages'
- 'workflow-stage-changes'
- 'workflows'
- 'releases'
- 'pipeline-branches'
- 'access-tokens'
--omit-types Comma separated list of resource-types to omit.
--with-asset-files Downloads all files (assets) of the space (default=false).
--output-dir Directory to write the backup to (default=./.output)
(ATTENTION: Will fail if the directory already exists!)
--force Force deletion and recreation of existing output directory.
--create-zip Create a zip file of the backup (default=false).
--zip-prefix Prefix for the zip file. (default='backup').
(The suffix will automatically be the current date.)
--verbose Will show detailed output for every file written.
--help Show this help
`OAuth token, space-id and region can be set via environment variables. You can also use a
.env file in your project root for this (see .env.example).#### Minimal backup example
`shell
npx storyblok-backup --token 1234567890abcdef --space 12345
`This will create the folder
./.output/backup and fetch all resources sorted into folders.#### Maximal backup example
`shell
npx storyblok-backup \
--token 1234567890abcdef \
--space 12345 \
--region ap \
--types "stories,components" \
--with-asset-files \
--output-dir ./my-dir \
--force \
--create-zip \
--zip-prefix daily \
--verbose
`This will create the folder
./my-dir/backup, fetch all resources (incl. the original file assets) sorted into folders, zip them to ./my-dir/daily-Y-m-d-H-i-s.zip, and log every written file to console.#### Continuous backup integration examples
You can use this script to create periodic backups of Storyblok spaces using GitHub Actions and artifacts, or commit each content change to a git repository usint Storyblok's webhooks.
##### Example for a GitHub workflow for a complete backup as an artifact
Here would be an example for a weekly backup, that removes the artifacts/backups from previous runs and uploads a new one:
`yaml
name: Weekly Storyblok Backupon:
schedule:
- cron: '0 0 0'
jobs:
backup:
runs-on: ubuntu-latest
permissions:
actions: write
steps:
- name: Perform Backup
env:
STORYBLOK_OAUTH_TOKEN: ${{ secrets.STORYBLOK_OAUTH_TOKEN }}
STORYBLOK_SPACE_ID: ${{ secrets.STORYBLOK_SPACE_ID }}
run: npx storyblok-backup
- name: Delete Old Artifacts
uses: actions/github-script@v6
id: artifact
with:
script: |
const res = await github.rest.actions.listArtifactsForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
})
res.data.artifacts
.filter(({ name }) => name === 'weekly-backup')
.forEach(({ id }) => {
github.rest.actions.deleteArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: id,
})
})
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: weekly-backup
path: .output
include-hidden-files: true
if-no-files-found: error
`Make sure, to set the secrets
STORYBLOK_OAUTH_TOKEN and STORYBLOK_SPACE_ID in your repository settings.Note that artifact manipulation requires the
actions: write permission for the workflow. The workflow above has this permission set already.If you create multiple workflows for daily, weekly and monthly backups, by changing the cron-schedule and the two occurrences of the artifact name
weekly-backup, you will always have exactly one daily, weekly and monthly backup.Also keep in mind, that there is a limit on artifact storage and runner minutes (see GitHub docs).
##### Example for a GitHub workflow for an incremental git-commit-based backup
The following workflow should run via webhook on every relevant change (e.g.publish) in Storyblok. It creates a new current backup (excl. asset files) and commits them to the current repository in the
backup folder. This enables an incremental git-commit-based backup of all Storyblok-content.`yaml
name: Incremental Repository Backupon:
repository_dispatch:
types:
- webhook
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
backup:
runs-on: ubuntu-24.04
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: 'main'
- name: Perform backup
env:
STORYBLOK_OAUTH_TOKEN: ${{ secrets.STORYBLOK_OAUTH_TOKEN }}
STORYBLOK_SPACE_ID: ${{ secrets.STORYBLOK_SPACE_ID }}
run: npx storyblok-backup
- name: Copy files into repository
run: |
rm -rf backup
cp -r .output/backup .
rm -rf .output
- name: Perform commit
run: |
git config --global user.name 'Your User'
git config --global user.email 'email@example.com'
git add backup
git diff --staged --quiet || git commit -m "content: update
date +'%Y-%m-%d %H:%M:%S'"
git push
`Make sure, to set the secrets
STORYBLOK_OAUTH_TOKEN and STORYBLOK_SPACE_ID in your repository settings.Note that actions performing commits require the
contents: write permission for the workflow. The workflow above has this permission set already.A webhook to the URL
https://api.github.com/repos/{owner}/{repo}/dispatches must be setup and triggered by every relevant content change in Storyblok. Since Storyblok's webhooks do not support authentication headers - which are required by GitHub - you can use Pipedream (or a similar service) as an intermediate webhook.$3
Make sure to install the package first (see Installation).
Call
npx storyblok-restore with the following options:#### Restore options
`text
--token (required) Personal OAuth access token created
in the account settings of a Stoyblok user.
(NOT the Access Token of a Space!)
Alternatively, you can set the STORYBLOK_OAUTH_TOKEN environment variable.
--space (required) ID of the space to backup
Alternatively, you can set the STORYBLOK_SPACE_ID environment variable.
--region Region of the space. Possible values are:
- 'eu' (default): EU
- 'us': US
- 'ap': Australia
- 'ca': Canada
- 'cn': China
Alternatively, you can set the STORYBLOK_REGION environment variable.
--type (required) Type of resource to restore. Possible values are:
- 'story'
- 'collaborator'
- 'component'
- 'component-group'
- 'asset'
- 'asset-folder'
- 'internal-tag'
- 'datasource'
- 'datasource-entries'
- 'space'
- 'space-role'
- 'task'
- 'preset'
- 'webhook'
- 'workflow'
- 'workflow-stage'
- 'release'
- 'pipeline-branch'
- 'access-token'
--file (required) File of resource to restore.
--publish Perform a publish after restore of a story (default=false).
--create Create a new resource instead of updating (default=false).
Not supported for assets.
--propagate Propagate new story UUID to referencing stories (default=false).
Usable with create and stories. A create results in a new ID and UUID.
This option will update all stories referencing the old
UUID (as stated in the backup-json) with the new one.
--id (required if type=datasource-entries and create is set)
ID of datasource the entries belong to.
--verbose Will show detailed result of the restore process.
--help Show this help
`#### Minimal restore example
`shell
npx storyblok-restore --token 1234567890abcdef --space 12345 --type story --file ./.output/backup/123456789.json
`This will restore the story from the stated file by updating it.
#### Maximal restore example
`shell
npx storyblok-restore \
--token 1234567890abcdef \
--space 12345 \
--region ap \
--type story \
--file ./.output/backup/123456789.json \
--publish \
--create \
--propagate \
--verbose
``This will restore the story by creating a new story, immediately publish it, and log the API result to console.
This package is open-sourced software licensed under the MIT license.