AutomationFlowsWeb Scraping › Backup n8n Credentials to GitHub

Backup n8n Credentials to GitHub

Original n8n title: Backup Credentials to Github

Backup Credentials to GitHub. Uses httpRequest, github, executeCommand, executeWorkflowTrigger. Event-driven trigger; 25 nodes.

Event trigger★★★★☆ complexity25 nodesHTTP RequestGitHubExecute CommandExecute Workflow Trigger
Web Scraping Trigger: Event Nodes: 25 Complexity: ★★★★☆ Added:

This workflow follows the Executecommand → HTTP Request 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
{
  "active": false,
  "activeVersion": null,
  "activeVersionId": null,
  "connections": {
    "Get File": {
      "main": [
        [
          {
            "node": "Merge Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "File is new": {
      "main": [
        [
          {
            "node": "Create new file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Items": {
      "main": [
        [
          {
            "node": "isDiffOrNew",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "isDiffOrNew": {
      "main": [
        [
          {
            "node": "Check Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Status": {
      "main": [
        [
          {
            "node": "Same file - Do nothing",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "File is different",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "File is new",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get file data": {
      "main": [
        [
          {
            "node": "If file too large",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create new file": {
      "main": [
        [
          {
            "node": "Return",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Command": {
      "main": [
        [
          {
            "node": "JSON formatting",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "JSON formatting": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Execute Workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Workflow": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Execute Command",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "File is different": {
      "main": [
        [
          {
            "node": "Edit existing file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If file too large": {
      "main": [
        [
          {
            "node": "Get File",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Merge Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit existing file": {
      "main": [
        [
          {
            "node": "Return",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On clicking 'execute'": {
      "main": [
        [
          {
            "node": "Execute Command",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Same file - Do nothing": {
      "main": [
        [
          {
            "node": "Return",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Workflow Trigger": {
      "main": [
        [
          {
            "node": "Globals",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge Items",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Globals": {
      "main": [
        [
          {
            "node": "Get file data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "createdAt": "2025-11-17T19:36:33.702Z",
  "id": "FvFAM9NXC9ne5rfT",
  "isArchived": false,
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Backup Credentials to GitHub",
  "nodes": [
    {
      "parameters": {},
      "id": "7c541978-5fc7-4ff4-beb4-e11b91aba483",
      "name": "On clicking 'execute'",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        208,
        176
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "content": "## Subworkflow",
        "height": 750.8363163824032,
        "width": 2086.845881354743,
        "color": 6
      },
      "id": "ffa21b1b-f42c-47c2-bfb4-aaa6b7442897",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -240,
        544
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "8d513345-6484-431f-afb7-7cf045c90f4f",
              "name": "Done",
              "type": "boolean",
              "value": true
            }
          ]
        },
        "options": {}
      },
      "id": "19ea86e8-4fc8-4b3f-83b7-d09658a3f191",
      "name": "Return",
      "type": "n8n-nodes-base.set",
      "position": [
        1648,
        752
      ],
      "typeVersion": 3.3
    },
    {
      "parameters": {
        "url": "={{ $json.download_url }}",
        "options": {}
      },
      "id": "ecd6ef14-9a5f-45b6-9c80-c1ad48991b68",
      "name": "Get File",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        752,
        624
      ],
      "typeVersion": 4.2
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "45ce825e-9fa6-430c-8931-9aaf22c42585",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json.content }}",
              "rightValue": ""
            },
            {
              "id": "9619a55f-7fb1-4f24-b1a7-7aeb82365806",
              "operator": {
                "type": "string",
                "operation": "notExists",
                "singleValue": true
              },
              "leftValue": "={{ $json.error }}",
              "rightValue": ""
            }
          ]
        },
        "options": {}
      },
      "id": "21edd171-72d4-43ea-921c-a16ba605cd99",
      "name": "If file too large",
      "type": "n8n-nodes-base.if",
      "position": [
        544,
        656
      ],
      "typeVersion": 2
    },
    {
      "parameters": {},
      "id": "7d439910-f23b-4875-a39d-ac4b3f7d87cc",
      "name": "Merge Items",
      "type": "n8n-nodes-base.merge",
      "position": [
        544,
        912
      ],
      "typeVersion": 2
    },
    {
      "parameters": {
        "jsCode": "const orderJsonKeys = (jsonObj) => {\n  const ordered = {};\n  Object.keys(jsonObj).sort().forEach(key => {\n    ordered[key] = jsonObj[key];\n  });\n  return ordered;\n}\n\n// Check if file returned with content\nif (Object.keys($input.all()[0].json).includes(\"content\")) {\n  // Decode base64 content and parse JSON\n  const origWorkflow = JSON.parse(Buffer.from($input.all()[0].json.content, 'base64').toString());\n  const n8nWorkflow = $input.all()[1].json;\n  \n  // Order JSON objects\n  const orderedOriginal = orderJsonKeys(origWorkflow);\n  const orderedActual = orderJsonKeys(n8nWorkflow);\n\n  // Determine difference\n  if (JSON.stringify(orderedOriginal) === JSON.stringify(orderedActual)) {\n    $input.all()[0].json.github_status = \"same\";\n  } else {\n    $input.all()[0].json.github_status = \"different\";\n    $input.all()[0].json.n8n_data_stringy = JSON.stringify(orderedActual, null, 2);\n  }\n  $input.all()[0].json.content_decoded = orderedOriginal;\n// No file returned / new workflow\n} else if (Object.keys($input.all()[0].json).includes(\"data\")) {\n  const origWorkflow = JSON.parse($input.all()[0].json.data);\n  const n8nWorkflow = $input.all()[1].json;\n  \n  // Order JSON objects\n  const orderedOriginal = orderJsonKeys(origWorkflow);\n  const orderedActual = orderJsonKeys(n8nWorkflow);\n\n  // Determine difference\n  if (JSON.stringify(orderedOriginal) === JSON.stringify(orderedActual)) {\n    $input.all()[0].json.github_status = \"same\";\n  } else {\n    $input.all()[0].json.github_status = \"different\";\n    $input.all()[0].json.n8n_data_stringy = JSON.stringify(orderedActual, null, 2);\n  }\n  $input.all()[0].json.content_decoded = orderedOriginal;\n\n} else {\n  // Order JSON object\n  const n8nWorkflow = $input.all()[1].json;\n  const orderedActual = orderJsonKeys(n8nWorkflow);\n  \n  // Proper formatting\n  $input.all()[0].json.github_status = \"new\";\n  $input.all()[0].json.n8n_data_stringy = JSON.stringify(orderedActual, null, 2);\n}\n\n// Return items\nreturn $input.all();"
      },
      "id": "2041e6a5-78d4-4a30-acb7-76b11f439ec0",
      "name": "isDiffOrNew",
      "type": "n8n-nodes-base.code",
      "position": [
        752,
        912
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "dataType": "string",
        "value1": "={{$json.github_status}}",
        "rules": {
          "rules": [
            {
              "value2": "same"
            },
            {
              "value2": "different",
              "output": 1
            },
            {
              "value2": "new",
              "output": 2
            }
          ]
        }
      },
      "id": "c279514f-0d18-4a65-b2e2-f4149db3a82f",
      "name": "Check Status",
      "type": "n8n-nodes-base.switch",
      "position": [
        960,
        912
      ],
      "typeVersion": 1
    },
    {
      "parameters": {},
      "id": "dff3dad6-2901-4c01-993f-be438aa96d3c",
      "name": "Same file - Do nothing",
      "type": "n8n-nodes-base.noOp",
      "position": [
        1184,
        752
      ],
      "typeVersion": 1
    },
    {
      "parameters": {},
      "id": "fd5ef674-9979-4cd6-9cf6-8e92022963c0",
      "name": "File is different",
      "type": "n8n-nodes-base.noOp",
      "position": [
        1184,
        912
      ],
      "typeVersion": 1
    },
    {
      "parameters": {},
      "id": "746395e7-bcf9-45b6-aea7-fc437f93bda4",
      "name": "File is new",
      "type": "n8n-nodes-base.noOp",
      "position": [
        1184,
        1072
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "resource": "file",
        "owner": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Globals').item.json.repo.owner }}"
        },
        "repository": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Globals').item.json.repo.name }}"
        },
        "filePath": "={{ $('Globals').item.json.repo.path }}{{$('Execute Workflow Trigger').first().json.id}}.json",
        "fileContent": "={{$('isDiffOrNew').item.json[\"n8n_data_stringy\"]}}",
        "commitMessage": "={{$('Execute Workflow Trigger').first().json.name}} ({{$json.github_status}})"
      },
      "id": "a4db66c0-30b2-4870-a27b-e2fe26b2af2d",
      "name": "Create new file",
      "type": "n8n-nodes-base.github",
      "position": [
        1408,
        1072
      ],
      "typeVersion": 1,
      "credentials": {
        "githubApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "resource": "file",
        "operation": "edit",
        "owner": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Globals').item.json.repo.owner }}"
        },
        "repository": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Globals').item.json.repo.name }}"
        },
        "filePath": "={{ $('Globals').item.json.repo.path }}{{$('Execute Workflow Trigger').first().json.id}}.json",
        "fileContent": "={{$('isDiffOrNew').item.json[\"n8n_data_stringy\"]}}",
        "commitMessage": "={{$('Execute Workflow Trigger').first().json.name}} ({{$json.github_status}})"
      },
      "id": "2d3186aa-df51-492d-8916-665976573be4",
      "name": "Edit existing file",
      "type": "n8n-nodes-base.github",
      "position": [
        1408,
        896
      ],
      "typeVersion": 1,
      "credentials": {
        "githubApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "options": {}
      },
      "id": "1e8bdd89-0e55-4b98-80b4-2029a07b3916",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        800,
        272
      ],
      "typeVersion": 3
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 2
            }
          ]
        }
      },
      "id": "02d5a51b-9d69-40a3-8a0d-1cde47cb7880",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        208,
        368
      ],
      "typeVersion": 1.2
    },
    {
      "parameters": {
        "content": "## Backup to GitHub \nThis workflow will backup all instance credentials to GitHub.\n\nThe files are saved `ID.json` for the filename.\n\n### Setup\nOpen `Globals` node and update the values below \ud83d\udc47\n\n- **repo.owner:** your Github username\n- **repo.name:** the name of your repository\n- **repo.path:** the folder to use within the repository. If it doesn't exist it will be created.\n\n\nIf your username was `john-doe` and your repository was called `n8n-backups` and you wanted the credentials to go into a `credentials` folder you would set:\n\n- repo.owner - john-doe\n- repo.name - n8n-backups\n- repo.path - credentials/\n\n\nThe workflow calls itself using a subworkflow, to help reduce memory usage.",
        "height": 596.4810912485963,
        "width": 365.19481715599653,
        "color": 4
      },
      "id": "0c8b41fa-fa6e-4cc8-aa31-6b4d6d1a6a67",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -240,
        -96
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "content": "## Main workflow loop",
        "height": 434.88564057365943,
        "width": 1028.7522287279464,
        "color": 7
      },
      "id": "f1ebd9b8-dac2-4d30-90cf-061e86aa39cf",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        96
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "resource": "file",
        "operation": "get",
        "owner": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $json.repo.owner }}"
        },
        "repository": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $json.repo.name }}"
        },
        "filePath": "={{ $json.repo.path }}{{ $('Execute Workflow Trigger').item.json.id }}.json",
        "asBinaryProperty": false,
        "additionalParameters": {}
      },
      "id": "b239be87-761c-4d5b-93c5-9e6937c4f14f",
      "name": "Get file data",
      "type": "n8n-nodes-base.github",
      "position": [
        352,
        656
      ],
      "typeVersion": 1,
      "alwaysOutputData": true,
      "credentials": {
        "githubApi": {
          "name": "<your credential>"
        }
      },
      "continueOnFail": true
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "6cf546c5-5737-4dbd-851b-17d68e0a3780",
              "name": "repo.owner",
              "type": "string",
              "value": "LePeanutButter"
            },
            {
              "id": "452efa28-2dc6-4ea3-a7a2-c35d100d0382",
              "name": "repo.name",
              "type": "string",
              "value": "n8n-workflows-aquasense"
            },
            {
              "id": "81c4dc54-86bf-4432-a23f-22c7ea831e74",
              "name": "repo.path",
              "type": "string",
              "value": "credentials/"
            }
          ]
        },
        "options": {}
      },
      "id": "a76322d5-77fc-4d43-b54a-cec12c83c3b4",
      "name": "Globals",
      "type": "n8n-nodes-base.set",
      "position": [
        144,
        816
      ],
      "typeVersion": 3.4
    },
    {
      "parameters": {
        "command": "npx n8n export:credentials --all"
      },
      "id": "4f20b8c8-0115-4650-8538-b5d789bc8df1",
      "name": "Execute Command",
      "type": "n8n-nodes-base.executeCommand",
      "position": [
        432,
        272
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "jsCode": "// Function to beautify JSON\nfunction beautifyJson(jsonString) {\n  try {\n    // Parse the JSON string\n    const jsonObject = JSON.parse(jsonString);\n\n    // Format the JSON with indentation\n    return jsonObject; // Return the parsed object directly\n  } catch (error) {\n    // Return the error message if JSON is invalid\n    return `Invalid JSON: ${error.message}`;\n  }\n}\n\n// Retrieve the JSON object from the input data\nconst input = $input.all()[0].json;\n\n// Extract the JSON string from the stdout field\nconst jsonString = input.stdout.match(/\\[{.*}\\]/s);\n\n// Check if a valid JSON string is found\nif (!jsonString) {\n  return {\n    json: {\n      error: \"No valid JSON string found in stdout.\"\n    }\n  };\n}\n\n// Beautify the JSON\nconst beautifiedJson = beautifyJson(jsonString[0]);\n\n// Output the beautified JSON, ensuring each entry is in an object with a 'json' key\nconst output = beautifiedJson.map(entry => ({ json: entry }));\n\n// Return the output\nreturn output;\n"
      },
      "id": "ce76465f-0738-4773-880e-80f880d3dba6",
      "name": "JSON formatting",
      "type": "n8n-nodes-base.code",
      "position": [
        608,
        272
      ],
      "typeVersion": 2
    },
    {
      "parameters": {
        "content": "## Edit this node \ud83d\udc47",
        "height": 80,
        "width": 150,
        "color": 4
      },
      "id": "a56698d4-29b9-4e87-a780-dc8e1e4a3043",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        112,
        704
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "workflowId": "={{ $workflow.id }}",
        "mode": "each",
        "options": {}
      },
      "id": "dafb3884-1f29-4db3-a7ba-764f17fc6666",
      "name": "Execute Workflow",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        1024,
        288
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "inputSource": "passthrough"
      },
      "id": "da4d1247-5637-43f5-b367-56bd5e2ca4fe",
      "name": "Execute Workflow Trigger",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        -128,
        928
      ],
      "typeVersion": 1.1
    },
    {
      "parameters": {
        "content": "### \ud83d\udca1 **Want to learn advanced n8n skills and earn money building workflows?**\n\u200e \u200e \u200e \u200e \u200e \u200e \u200e \u200eCheck out [Scrapes Academy](https://www.skool.com/scrapes/about?ref=21f10ad99f4d46ba9b8aaea8c9f58c34)",
        "width": 640,
        "color": 4
      },
      "id": "d949f682-3b19-4401-81b9-30a74aa1cfec",
      "name": "Sticky Note16",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160,
        -96
      ],
      "typeVersion": 1
    }
  ],
  "settings": {
    "executionOrder": "v1"
  },
  "shared": [
    {
      "updatedAt": "2025-11-17T19:36:33.708Z",
      "createdAt": "2025-11-17T19:36:33.708Z",
      "role": "workflow:owner",
      "workflowId": "FvFAM9NXC9ne5rfT",
      "projectId": "xno20arzPonor2IK"
    }
  ],
  "staticData": null,
  "tags": [
    {
      "updatedAt": "2025-12-06T23:03:02.485Z",
      "createdAt": "2025-12-06T23:03:02.485Z",
      "id": "XhlHyiNabErISAFU",
      "name": "GitHub"
    }
  ],
  "triggerCount": 0,
  "updatedAt": "2025-12-06T23:03:23.000Z",
  "versionId": "3f8352d1-cd6f-4c2c-b03e-25ca4e5a67e9"
}

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

Backup Credentials to GitHub. Uses httpRequest, github, executeCommand, executeWorkflowTrigger. Event-driven trigger; 25 nodes.

Source: https://github.com/LePeanutButter/n8n-workflows-aquasense/blob/main/workflows/FvFAM9NXC9ne5rfT.json — original creator credit. Request a take-down →

More Web Scraping workflows → · Browse all categories →

Related workflows

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

Web Scraping

Based on Jonathan's work. Check out his templates.

HTTP Request, GitHub, Execute Command +1
Web Scraping

Remixed Backup your workflows to GitHub from Solomon's work. Check out his templates.

HTTP Request, GitHub, Execute Workflow Trigger +1
Web Scraping

Remixed Backup your workflows to GitHub from Solomon's work. Check out his templates.

Execute Workflow Trigger, HTTP Request, GitHub
Web Scraping

Create, iterate, and share! Transform a single image through multiple scenes while maintaining consistency.

HTTP Request, Execute Workflow Trigger, GitHub +1
Web Scraping

Based on Jonathan & Solomon work.

n8n, HTTP Request, GitHub +1