AutomationFlowsDevOps › Automatic Workflow & Credentials Backup to Github with Change Detection

Automatic Workflow & Credentials Backup to Github with Change Detection

ByHamed Nickmehr @hamed-nickmehr on n8n.io

This n8n workflow template uses community nodes and is only compatible with the self-hosted version of n8n.

Cron / scheduled trigger★★★★☆ complexity21 nodesRead Write FileExecute CommandCryptoExecute Workflow TriggerGitHub
DevOps Trigger: Cron / scheduled Nodes: 21 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #4609 — 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 →

Download .json
{
  "nodes": [
    {
      "id": "6f0fcaed-fd41-4ac4-816d-41098539f42a",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1900,
        -180
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "1211ee7a-03d1-4a00-9759-bc0402d3686c",
      "name": "Get New Workflow Hash",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        -1020,
        -280
      ],
      "parameters": {
        "options": {},
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "U7Jh9njKLEjGLVIl",
          "cachedResultName": "n8n Backup Changes"
        },
        "workflowInputs": {
          "value": {
            "filePath": "={{ $('Set Workflow Path').item.json.filePath }}"
          },
          "schema": [
            {
              "id": "filePath",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "filePath",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "filePath"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "typeVersion": 1.2,
      "alwaysOutputData": false
    },
    {
      "id": "d655d400-d743-4dd8-8b05-12701c8c4f9d",
      "name": "Get Old Workflow Hash",
      "type": "n8n-nodes-base.executeWorkflow",
      "onError": "continueRegularOutput",
      "position": [
        -1460,
        -280
      ],
      "parameters": {
        "options": {},
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "U7Jh9njKLEjGLVIl",
          "cachedResultName": "n8n Backup Changes"
        },
        "workflowInputs": {
          "value": {
            "filePath": "={{ $('Set Workflow Path').item.json.filePath }}"
          },
          "schema": [
            {
              "id": "filePath",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "filePath",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "filePath"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "typeVersion": 1.2,
      "alwaysOutputData": true
    },
    {
      "id": "0d13634a-f74a-4194-8a54-9531205d0883",
      "name": "Read Workflow Data",
      "type": "n8n-nodes-base.readWriteFile",
      "position": [
        -580,
        -280
      ],
      "parameters": {
        "options": {},
        "fileSelector": "={{ $('Set Workflow Path').item.json.filePath }}"
      },
      "typeVersion": 1
    },
    {
      "id": "cfa7d2e0-e63d-4392-899d-13fd2b587a15",
      "name": "Set Workflow Path",
      "type": "n8n-nodes-base.set",
      "position": [
        -1680,
        -280
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "c60cce2a-609d-417e-a73c-9719a490cc85",
              "name": "filePath",
              "type": "string",
              "value": "/data/shared/WorkFlowBackup.json"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "5b5250ed-c3de-431f-8e4b-c8b6a6352393",
      "name": "Execute Workflow Backup",
      "type": "n8n-nodes-base.executeCommand",
      "position": [
        -1240,
        -280
      ],
      "parameters": {
        "command": "=n8n export:workflow --all --output={{ $('Set Workflow Path').item.json.filePath }}"
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "510d346d-2eec-4839-aa99-6d61cc00573a",
      "name": "Read File",
      "type": "n8n-nodes-base.readWriteFile",
      "position": [
        -1680,
        -540
      ],
      "parameters": {
        "options": {},
        "fileSelector": "={{ $json.filePath }}"
      },
      "typeVersion": 1
    },
    {
      "id": "9ce2b61a-d4cd-46f5-a20b-02cbb864c259",
      "name": "Extract Data",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -1460,
        -540
      ],
      "parameters": {
        "options": {},
        "operation": "text"
      },
      "typeVersion": 1
    },
    {
      "id": "381e022a-f265-4a07-9a49-27f401cc08d3",
      "name": "Hash Data",
      "type": "n8n-nodes-base.crypto",
      "position": [
        -1240,
        -540
      ],
      "parameters": {
        "type": "SHA256",
        "value": "={{$json.data}}",
        "dataPropertyName": "hash"
      },
      "typeVersion": 1
    },
    {
      "id": "73d5f6a5-a4ee-49f9-ba5f-2646887daf9b",
      "name": "Hash Maker",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        -1900,
        -540
      ],
      "parameters": {
        "workflowInputs": {
          "values": [
            {
              "name": "filePath"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "78bd1ed8-0c19-4106-ab84-1d25f0f4b806",
      "name": "Extract Workflow Data",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -360,
        -280
      ],
      "parameters": {
        "options": {},
        "operation": "text"
      },
      "typeVersion": 1
    },
    {
      "id": "740fd3e5-f356-436c-ad2b-86da10fb346d",
      "name": "GitHub Workflow Backup",
      "type": "n8n-nodes-base.github",
      "onError": "continueRegularOutput",
      "position": [
        -140,
        -280
      ],
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "list",
          "value": "nickmehr-hamed",
          "cachedResultUrl": "https://github.com/nickmehr-hamed",
          "cachedResultName": "nickmehr-hamed"
        },
        "filePath": "={{ \"backups/WorkFlow Backup \" + new Date($now).toISOString().replace('T', ' ').slice(0, 16) + \".json\" }}",
        "resource": "file",
        "repository": {
          "__rl": true,
          "mode": "url",
          "value": "https://github.com/nickmehr-hamed/n8n"
        },
        "fileContent": "={{ $json.data }}",
        "commitMessage": "={{ \"WorkFlow Backup \" + new Date($now).toISOString().replace('T', ' ').slice(0, 16) }}"
      },
      "credentials": {
        "githubApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "dc2e73a2-36d8-4d92-947f-b3d01fac934d",
      "name": "Get New Credential Hash",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        -1020,
        -80
      ],
      "parameters": {
        "options": {},
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "U7Jh9njKLEjGLVIl",
          "cachedResultName": "n8n Backup Changes"
        },
        "workflowInputs": {
          "value": {
            "filePath": "={{ $('Set Credential Path').item.json.filePath }}"
          },
          "schema": [
            {
              "id": "filePath",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "filePath",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "filePath"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "typeVersion": 1.2,
      "alwaysOutputData": false
    },
    {
      "id": "b5512300-5bb4-4781-9d5b-3b61a90d7220",
      "name": "Get Old Credential Hash",
      "type": "n8n-nodes-base.executeWorkflow",
      "onError": "continueRegularOutput",
      "position": [
        -1460,
        -80
      ],
      "parameters": {
        "options": {},
        "workflowId": {
          "__rl": true,
          "mode": "list",
          "value": "U7Jh9njKLEjGLVIl",
          "cachedResultName": "n8n Backup Changes"
        },
        "workflowInputs": {
          "value": {
            "filePath": "={{ $('Set Credential Path').item.json.filePath }}"
          },
          "schema": [
            {
              "id": "filePath",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "filePath",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "filePath"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "typeVersion": 1.2,
      "alwaysOutputData": true
    },
    {
      "id": "ef1807a5-8d7c-4d05-b819-a433d495ca36",
      "name": "Read Credential Data",
      "type": "n8n-nodes-base.readWriteFile",
      "position": [
        -580,
        -80
      ],
      "parameters": {
        "options": {},
        "fileSelector": "={{ $('Set Credential Path').item.json.filePath }}"
      },
      "typeVersion": 1
    },
    {
      "id": "ceaa31cb-bfff-43b6-9433-7d1e124d6d86",
      "name": "Set Credential Path",
      "type": "n8n-nodes-base.set",
      "position": [
        -1680,
        -80
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "c60cce2a-609d-417e-a73c-9719a490cc85",
              "name": "filePath",
              "type": "string",
              "value": "/data/shared/CredentialBackup.json"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "babf93ca-cd95-4a38-9ecc-c16ffbd48dc0",
      "name": "Execute Credential Backup",
      "type": "n8n-nodes-base.executeCommand",
      "position": [
        -1240,
        -80
      ],
      "parameters": {
        "command": "=n8n export:credentials --all --output={{ $('Set Credential Path').item.json.filePath }}"
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "d2c8c228-d276-44f7-831b-611d05610e8f",
      "name": "Extract Credential Data",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -360,
        -80
      ],
      "parameters": {
        "options": {},
        "operation": "text"
      },
      "typeVersion": 1
    },
    {
      "id": "1f94c09d-26aa-444b-b607-1366b7ffc4d0",
      "name": "GitHub Credential Backup",
      "type": "n8n-nodes-base.github",
      "onError": "continueRegularOutput",
      "position": [
        -140,
        -80
      ],
      "parameters": {
        "owner": {
          "__rl": true,
          "mode": "list",
          "value": "nickmehr-hamed",
          "cachedResultUrl": "https://github.com/nickmehr-hamed",
          "cachedResultName": "nickmehr-hamed"
        },
        "filePath": "={{ \"backups/ Credential Backup \" + new Date($now).toISOString().replace('T', ' ').slice(0, 16) + \".json\" }}",
        "resource": "file",
        "repository": {
          "__rl": true,
          "mode": "url",
          "value": "https://github.com/nickmehr-hamed/n8n"
        },
        "fileContent": "={{ $json.data }}",
        "commitMessage": "={{ \" Credential Backup \" + new Date($today).toISOString().replace('T', ' ').slice(0, 16) }}"
      },
      "credentials": {
        "githubApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "a1a606b2-a0d7-4d9c-98b1-4657b902fccd",
      "name": "If Workflow Updated",
      "type": "n8n-nodes-base.if",
      "position": [
        -800,
        -280
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "c028ce1d-3fe9-4dc9-a3e9-296460e12c83",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $('Get New Workflow Hash').item.json.hash }}",
              "rightValue": "={{ $('Get Old Workflow Hash').item.json.hash }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a6809c8d-ccd9-4acf-9854-b6a36e74c439",
      "name": "If Credential Updated",
      "type": "n8n-nodes-base.if",
      "position": [
        -800,
        -80
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "c028ce1d-3fe9-4dc9-a3e9-296460e12c83",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $('Get New Credential Hash').item.json.hash }}",
              "rightValue": "={{ $('Get Old Credential Hash').item.json.hash }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    }
  ],
  "connections": {
    "Hash Data": {
      "main": [
        []
      ]
    },
    "Read File": {
      "main": [
        [
          {
            "node": "Extract Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Hash Maker": {
      "main": [
        [
          {
            "node": "Read File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Data": {
      "main": [
        [
          {
            "node": "Hash Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Set Workflow Path",
            "type": "main",
            "index": 0
          },
          {
            "node": "Set Credential Path",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Workflow Path": {
      "main": [
        [
          {
            "node": "Get Old Workflow Hash",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Workflow Data": {
      "main": [
        [
          {
            "node": "Extract Workflow Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Workflow Updated": {
      "main": [
        [
          {
            "node": "Read Workflow Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Credential Path": {
      "main": [
        [
          {
            "node": "Get Old Credential Hash",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Credential Data": {
      "main": [
        [
          {
            "node": "Extract Credential Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Workflow Data": {
      "main": [
        [
          {
            "node": "GitHub Workflow Backup",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get New Workflow Hash": {
      "main": [
        [
          {
            "node": "If Workflow Updated",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Old Workflow Hash": {
      "main": [
        [
          {
            "node": "Execute Workflow Backup",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Credential Updated": {
      "main": [
        [
          {
            "node": "Read Credential Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Workflow Backup": {
      "main": [
        [
          {
            "node": "Get New Workflow Hash",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Credential Data": {
      "main": [
        [
          {
            "node": "GitHub Credential Backup",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get New Credential Hash": {
      "main": [
        [
          {
            "node": "If Credential Updated",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Old Credential Hash": {
      "main": [
        [
          {
            "node": "Execute Credential Backup",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Credential Backup": {
      "main": [
        [
          {
            "node": "Get New Credential Hash",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

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/4609/ — original creator credit. Request a take-down →

More DevOps workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

DevOps

Code Github. Uses manualTrigger, stickyNote, httpRequest, noOp. Event-driven trigger; 24 nodes.

HTTP Request, GitHub, Execute Command +1
DevOps

This n8n workflow template uses community nodes and is only compatible with the self-hosted version of n8n.

Execute Command, GitHub, Read Write File
DevOps

Code Github. Uses manualTrigger, stickyNote, n8n, httpRequest. Event-driven trigger; 25 nodes.

n8n, HTTP Request, GitHub +1
DevOps

Who is this for? This template is ideal for n8n administrators, automation engineers, and DevOps teams who want to maintain bidirectional synchronization between their n8n workflows and GitHub reposit

n8n, GitHub
DevOps

Display Project Data On A Smashing Dashboard. Uses httpRequest, github. Scheduled trigger; 24 nodes.

HTTP Request, GitHub