This workflow corresponds to n8n.io template #3994 — we link there as the canonical source.
This workflow follows the Executecommand → Readwritefile recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "84883c25-ad4f-4b18-a227-609815a9024b",
"name": "Remove root node",
"type": "n8n-nodes-base.set",
"position": [
780,
-680
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "={{ $json.parsedData }}"
},
"typeVersion": 3.4
},
{
"id": "de5315d0-447e-4740-966a-f2fa711f54a4",
"name": "TAG? Auto deploy to dev",
"type": "n8n-nodes-base.if",
"position": [
1060,
-340
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "03241d00-9ec1-4215-8036-2d219a7874cb",
"operator": {
"type": "array",
"operation": "contains",
"rightType": "any"
},
"leftValue": "={{ $json.tags.map((obj) => obj.name) }}",
"rightValue": "Auto deploy to dev"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "82f0885b-ab23-4472-89d4-0a3c79ec3efb",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
1060,
-780
],
"parameters": {
"width": 520,
"height": 280,
"content": "## export\nadd the data in exports folder with readable names"
},
"typeVersion": 1
},
{
"id": "aa297fef-b961-435d-ba78-05cb73fd03f7",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-140,
-780
],
"parameters": {
"width": 380,
"height": 280,
"content": "## n8n export workflows\nadd the data in exports folder per workflow"
},
"typeVersion": 1
},
{
"id": "1c3188c5-9913-4c28-ae48-3cb79ae3dabd",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1300,
-460
],
"parameters": {
"width": 520,
"height": 280,
"content": "## export\nadd files to the import-dev folder if they should auto deploy to dev"
},
"typeVersion": 1
},
{
"id": "78a8be19-93cf-4a36-aaed-70ff29ae5e9e",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1300,
-140
],
"parameters": {
"width": 520,
"height": 280,
"content": "## export\nadd files to the import-dev folder if they should auto deploy to dev"
},
"typeVersion": 1
},
{
"id": "b7aa0923-340b-4be8-805a-f5f1dbe73af3",
"name": "TAG? Auto deploy to PROD",
"type": "n8n-nodes-base.if",
"position": [
1060,
-20
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "03241d00-9ec1-4215-8036-2d219a7874cb",
"operator": {
"type": "array",
"operation": "contains",
"rightType": "any"
},
"leftValue": "={{ $json.tags.map((obj) => obj.name) }}",
"rightValue": "Auto deploy to PROD"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "1f8086d4-c318-4eb4-b8ba-8e196bbd944d",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-360,
-1220
],
"parameters": {
"color": 5,
"width": 620,
"height": 420,
"content": "# Export workflows\n\n- All workflows will be stored, first with their ID as name.\n- These files will be processed and stored again with a readbable filename in the format **WorkflowName (ID).json**\n- If the files have a tag **'Auto deploy to dev'** or **'Auto deploy to PROD'** they will stored to these individual folders.\n\nOn commit a build pipeline will create a new image containing these workflow files and autodeploy this.\n\nOn startup:\n- Before we start n8n we will import the exported workflows using the n8n cli.\n- We start n8n and will wait till it is started.\n- Imported workflows will be disabled in n8n.\n- We manually start an AutoStarter workflow to start all workflows that have a specific **'AutoStarted'** tag."
},
"typeVersion": 1
},
{
"id": "e132b429-ce1e-4dea-bc0d-856e4a547203",
"name": "Start export workflows",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-300,
-680
],
"parameters": {},
"typeVersion": 1
},
{
"id": "d7f06044-52a4-4a1e-86ba-019b832bcbe8",
"name": "Create folders and run n8n cli",
"type": "n8n-nodes-base.executeCommand",
"position": [
-100,
-680
],
"parameters": {
"command": "mkdir export; \nmkdir export/n8n-workflows; \nmkdir export/named-workflows;\nrm -Rf export/n8n-workflows/*;\nrm -Rf export/named-workflows/*;\n\nmkdir import-dev/workflows;\n\nn8n export:workflow --all --output=export/n8n-workflows --pretty --separate"
},
"typeVersion": 1
},
{
"id": "41ffdc1d-59ce-411d-9542-1c5cdcc43e35",
"name": "load exported workflows",
"type": "n8n-nodes-base.readWriteFile",
"position": [
360,
-680
],
"parameters": {
"options": {},
"fileSelector": "export/n8n-workflows/*.*"
},
"typeVersion": 1
},
{
"id": "ff01046f-66f5-462f-af84-dc59d00b51d6",
"name": "parse workflow",
"type": "n8n-nodes-base.extractFromFile",
"position": [
580,
-680
],
"parameters": {
"options": {},
"operation": "fromJson",
"destinationKey": "parsedData"
},
"typeVersion": 1
},
{
"id": "920c1ea4-650a-4a37-a907-6e4d9c661b7e",
"name": "Create JSON file with readable name",
"type": "n8n-nodes-base.convertToFile",
"position": [
1100,
-680
],
"parameters": {
"mode": "each",
"options": {
"format": true,
"fileName": "=./export/named-workflows/{{ $json.name }} ({{ $json.id }}).json"
},
"operation": "toJson"
},
"typeVersion": 1.1
},
{
"id": "0ea7c70b-2cdb-4edb-84a1-54742c1e7c5b",
"name": "Store named workflow",
"type": "n8n-nodes-base.readWriteFile",
"position": [
1340,
-680
],
"parameters": {
"options": {},
"fileName": "={{ $binary.data.directory }}/{{ $binary.data.fileName }}",
"operation": "write"
},
"typeVersion": 1
},
{
"id": "3989b580-5525-4666-bc17-f40675bc56be",
"name": "Create JSON file with readable name (dev)",
"type": "n8n-nodes-base.convertToFile",
"position": [
1360,
-360
],
"parameters": {
"mode": "each",
"options": {
"format": true,
"fileName": "=./import-dev/workflows/{{ $json.name }} ({{ $json.id }}).json"
},
"operation": "toJson"
},
"typeVersion": 1.1
},
{
"id": "dcf2ea35-5214-4328-bced-ba3ee6d9f813",
"name": "Create JSON file with readable name (prod)",
"type": "n8n-nodes-base.convertToFile",
"position": [
1360,
-40
],
"parameters": {
"mode": "each",
"options": {
"format": true,
"fileName": "=./import-prod/workflows/{{ $json.name }} ({{ $json.id }}).json"
},
"operation": "toJson"
},
"typeVersion": 1.1
},
{
"id": "fa94f550-6367-4a8b-b55b-bcd217078985",
"name": "Store named workflow (dev)",
"type": "n8n-nodes-base.readWriteFile",
"position": [
1580,
-360
],
"parameters": {
"options": {},
"fileName": "={{ $binary.data.directory }}/{{ $binary.data.fileName }}",
"operation": "write"
},
"typeVersion": 1
},
{
"id": "72efde7d-8ac1-41e4-b823-621fd5effebf",
"name": "Store named workflow (prod)",
"type": "n8n-nodes-base.readWriteFile",
"position": [
1580,
-40
],
"parameters": {
"options": {},
"fileName": "={{ $binary.data.directory }}/{{ $binary.data.fileName }}",
"operation": "write"
},
"typeVersion": 1
},
{
"id": "1a5ad014-7fc7-41d5-b576-26e65bcf48a5",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-360,
-320
],
"parameters": {
"color": 4,
"width": 880,
"height": 460,
"content": "## Dockerfile\n```\nFROM docker.io/n8nio/n8n:stable\n \n# Some default n8n settings\nENV N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true\nENV N8N_RUNNERS_ENABLED=true\n \n# Add new entrypoint for auto importing credentials and workflows\nUSER root\nCOPY docker-files/importing-docker-entrypoint.sh /importing-docker-entrypoint.sh\nRUN chmod +x /importing-docker-entrypoint.sh\nUSER node\n \n# Optionally add extra packages\n# RUN apk add --update graphicsmagick tzdata\nCOPY package.json .\nRUN npm install\n \n# Copy only necessary source files\nCOPY import-dev ./import-dev\nCOPY import-prod ./import-prod\n \nENTRYPOINT [\"tini\" \"--\" \"/importing-docker-entrypoint.sh\"]\n```"
},
"typeVersion": 1
},
{
"id": "e14394da-d144-463e-af5f-fba4e6dffc20",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-360,
160
],
"parameters": {
"color": 4,
"width": 1400,
"height": 1000,
"content": "## docker-files/importing-docker-entrypoint.sh\n```\n#!/bin/sh\n \n# https://github.com/n8n-io/n8n/blob/master/docker/images/n8n\n \n# mount this file in /importing-docker-entrypoint.sh and override the command\n \nif [ -d /opt/custom-certificates ]; then\n echo \"Trusting custom certificates from /opt/custom-certificates.\"\n export NODE_OPTIONS=\"--use-openssl-ca $NODE_OPTIONS\"\n export SSL_CERT_DIR=/opt/custom-certificates\n c_rehash /opt/custom-certificates\nfi\n \necho \"Importing credentials and workflows...\"\necho \" these can be stored in /opt/import/credentials and /opt/import/workflows\"\nif [ -d /opt/import/credentials ]; then\n n8n import:credentials --input=/opt/import/credentials --separate\nfi\nif [ -d /opt/import/workflows ]; then\n n8n import:workflow --input=/opt/import/workflows --separate\nfi\n \necho \"Importing more credentials and workflows...\"\necho \" folder locations can be set using environment variables STARTUP_CREDENTIALS_LOAD_LOCATION and STARTUP_WORKFLOWS_LOAD_LOCATION\"\necho \" credentials: $STARTUP_CREDENTIALS_LOAD_LOCATION\"\necho \" workflows : $STARTUP_WORKFLOWS_LOAD_LOCATION\"\nif [ -n \"$STARTUP_CREDENTIALS_LOAD_LOCATION\" ] && [ -d \"$STARTUP_CREDENTIALS_LOAD_LOCATION\" ]; then\n n8n import:credentials --input=\"$STARTUP_CREDENTIALS_LOAD_LOCATION\" --separate\nfi\nif [ -n \"$STARTUP_WORKFLOWS_LOAD_LOCATION\" ] && [ -d \"$STARTUP_WORKFLOWS_LOAD_LOCATION\" ]; then\n n8n import:workflow --input=\"$STARTUP_WORKFLOWS_LOAD_LOCATION\" --separate\nfi\n \necho \"Auto executing workflow...\"\necho \" The id can be configured with STARTUP_WORKFLOW_ID\"\n# Check if STARTUP_WORKFLOW_ID is set and run the workflow after 30 seconds\nif [ -n \"$STARTUP_WORKFLOW_ID\" ]; then\n echo \"Will execute workflow with ID $STARTUP_WORKFLOW_ID after 10 and 60seconds\"\n (\n sleep 10\n echo \"Executing workflow with ID $STARTUP_WORKFLOW_ID\"\n n8n execute --id $STARTUP_WORKFLOW_ID\n sleep 50\n echo \"Executing workflow with ID $STARTUP_WORKFLOW_ID\"\n n8n execute --id $STARTUP_WORKFLOW_ID\n ) &\nfi\n \necho \"Starting n8n\"\nif [ \"$#\" -gt 0 ]; then\n # Got started with arguments\n exec n8n \"$@\"\nelse\n # Got started without arguments\n exec n8n\nfi\n```"
},
"typeVersion": 1
},
{
"id": "dcc9029e-8d83-4e26-a5c5-e55e53248af1",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-360,
-420
],
"parameters": {
"color": 4,
"width": 880,
"height": 80,
"content": "# Example files for us in a delivery pipeline"
},
"typeVersion": 1
}
],
"connections": {
"parse workflow": {
"main": [
[
{
"node": "Remove root node",
"type": "main",
"index": 0
}
]
]
},
"Remove root node": {
"main": [
[
{
"node": "Create JSON file with readable name",
"type": "main",
"index": 0
},
{
"node": "TAG? Auto deploy to dev",
"type": "main",
"index": 0
},
{
"node": "TAG? Auto deploy to PROD",
"type": "main",
"index": 0
}
]
]
},
"Start export workflows": {
"main": [
[
{
"node": "Create folders and run n8n cli",
"type": "main",
"index": 0
}
]
]
},
"TAG? Auto deploy to dev": {
"main": [
[
{
"node": "Create JSON file with readable name (dev)",
"type": "main",
"index": 0
}
]
]
},
"load exported workflows": {
"main": [
[
{
"node": "parse workflow",
"type": "main",
"index": 0
}
]
]
},
"TAG? Auto deploy to PROD": {
"main": [
[
{
"node": "Create JSON file with readable name (prod)",
"type": "main",
"index": 0
}
]
]
},
"Create folders and run n8n cli": {
"main": [
[
{
"node": "load exported workflows",
"type": "main",
"index": 0
}
]
]
},
"Create JSON file with readable name": {
"main": [
[
{
"node": "Store named workflow",
"type": "main",
"index": 0
}
]
]
},
"Create JSON file with readable name (dev)": {
"main": [
[
{
"node": "Store named workflow (dev)",
"type": "main",
"index": 0
}
]
]
},
"Create JSON file with readable name (prod)": {
"main": [
[
{
"node": "Store named workflow (prod)",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This n8n workflow template uses community nodes and is only compatible with the self-hosted version of n8n.
Source: https://n8n.io/workflows/3994/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Perfect for disaster recovery or migrating between environments, this workflow automatically identifies your most recent FTP backup and provides a manual restore capability that intelligently excludes
N8N Workflow. Uses localFileTrigger, executeCommand, readWriteFile. Event-driven trigger; 16 nodes.
🎯 Purpose: Generate audio files from text scripts stored in Google Drive.
Complete backup solution that saves both workflows and credentials to local/server disk with optional FTP upload for off-site redundancy.
Perfect for disaster recovery or migrating between environments, this workflow automatically identifies your most recent backup and provides a manual restore capability that intelligently excludes the