Hi @Jon ! Thanks for the help I now have a functional backup workflow, and while it is still not perfect ( I had to add jq to the docker image ) but it works as expected, and now I can put my mind at rest that it’s there it’s running, and can worry about making it perfect a bit later, sharing the whole workflow for further reference, feel free to make upgrade suggestions, copy re-use publish whatever.
{
"meta": {
"instanceId": "my_instanceid"
},
"nodes": [
{
"parameters": {
"mode": "jsonToBinary",
"options": {
"useRawData": true
}
},
"id": "myid"
"name": "Move Binary Data",
"type": "n8n-nodes-base.moveBinaryData",
"typeVersion": 1,
"position": [
2340,
580
]
},
{
"parameters": {
"fileName": "=code/{{ $('Generate git friendly filenames').item.json.filename }}",
"options": {
"append": false
}
},
"id": "myid"
"name": "Write Binary File",
"type": "n8n-nodes-base.writeBinaryFile",
"typeVersion": 1,
"position": [
2540,
580
]
},
{
"parameters": {
"authentication": "gitPassword",
"operation": "clone",
"repositoryPath": "={{ $('Set variables').item.json.codefolder }}",
"sourceRepository": "={{ $('Set variables').item.json.repourl }}"
},
"id": "myid"
"name": "Clone the repo",
"type": "n8n-nodes-base.git",
"typeVersion": 1,
"position": [
1500,
420
],
"alwaysOutputData": true,
"credentials": {
"gitPassword": {
"id": "myid"
"name": "Git account"
}
},
"continueOnFail": true
},
{
"parameters": {
"operation": "add",
"repositoryPath": "={{ $('Set variables').item.json.codefolder }}",
"pathsToAdd": "={{ $('Generate git friendly filenames').item.json.filename }}"
},
"id": "myid"
"name": "Add them to git",
"type": "n8n-nodes-base.git",
"typeVersion": 1,
"position": [
2960,
580
]
},
{
"parameters": {
"filters": {}
},
"id": "myid"
"name": "List n8n workflows",
"type": "n8n-nodes-base.n8n",
"typeVersion": 1,
"position": [
1940,
580
],
"credentials": {
"n8nApi": {
"id": "myid"
"name": "n8n itself"
}
}
},
{
"parameters": {
"operation": "pull",
"repositoryPath": "code"
},
"id": "myid"
"name": "Pull the repo",
"type": "n8n-nodes-base.git",
"typeVersion": 1,
"position": [
1740,
580
]
},
{
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.error }}",
"value2": "Error: Cannot use simple-git on a directory that does not exist"
}
]
}
},
"id": "myid"
"name": "Is repo already exist",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
740,
440
]
},
{
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.remote }}",
"value2": "={{ $('Set variables').item.json.repourl }}"
}
]
}
},
"id": "myid"
"name": "Is this the right repo",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
1140,
600
]
},
{
"parameters": {
"command": "=rm -rf {{ $('Set variables').item.json.codefolder }}"
},
"id": "myid"
"name": "Delete current repo",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
1360,
680
]
},
{
"parameters": {
"language": "python",
"pythonCode": "return [{\"remote\": \"https://\" + str(_input.first().json[\"remote.origin.url\"].split(\"@\")[1])}]"
},
"id": "myid"
"name": "construct repo url",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
960,
600
],
"alwaysOutputData": true,
"continueOnFail": true
},
{
"parameters": {
"values": {
"string": [
{
"name": "codefolder",
"value": "code"
},
{
"name": "repourl",
"value": "https://git.domain.tld/myusername/n8n_flows"
},
{
"name": "git_email",
"value": "[email protected]"
},
{
"name": "git_username",
"value": "n8n-bot"
}
]
},
"options": {}
},
"id": "myid"
"name": "Set variables",
"type": "n8n-nodes-base.set",
"typeVersion": 2,
"position": [
360,
440
]
},
{
"parameters": {
"language": "python",
"pythonCode": "list = _input.all()\nreturn_data = []\nfor item in list:\n data = item.json\n filename = data[\"name\"].lower().replace(\" \",\"_\") + \".json\"\n data[\"filename\"] = filename\n return_data.append(data)\nreturn return_data"
},
"id": "myid"
"name": "Generate git friendly filenames",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2140,
580
]
},
{
"parameters": {
"operation": "listConfig",
"repositoryPath": "={{ $json.codefolder }}"
},
"id": "myid"
"name": "Check repo config",
"type": "n8n-nodes-base.git",
"typeVersion": 1,
"position": [
560,
440
],
"alwaysOutputData": true,
"continueOnFail": true
},
{
"parameters": {
"operation": "commit",
"repositoryPath": "={{ $('Set variables').item.json.codefolder }}",
"message": "=Automated workflow backup from N8N",
"options": {}
},
"id": "myid"
"name": "Commit",
"type": "n8n-nodes-base.git",
"typeVersion": 1,
"position": [
3560,
580
]
},
{
"parameters": {
"operation": "addConfig",
"repositoryPath": "={{ $('Set variables').item.json.codefolder }}",
"key": "user.email",
"value": "={{ $('Set variables').item.json.git_email }}",
"options": {
"mode": "set"
}
},
"id": "myid"
"name": "User e-mail",
"type": "n8n-nodes-base.git",
"typeVersion": 1,
"position": [
3160,
580
],
"alwaysOutputData": true
},
{
"parameters": {
"operation": "addConfig",
"repositoryPath": "={{ $('Set variables').item.json.codefolder }}",
"key": "=user.name",
"value": "={{ $('Set variables').item.json.git_username }}",
"options": {}
},
"id": "myid"
"name": "Git username",
"type": "n8n-nodes-base.git",
"typeVersion": 1,
"position": [
3360,
580
]
},
{
"parameters": {
"authentication": "gitPassword",
"operation": "push",
"repositoryPath": "={{ $('Set variables').item.json.codefolder }}",
"options": {}
},
"id": "myid"
"name": "Push to remote",
"type": "n8n-nodes-base.git",
"typeVersion": 1,
"position": [
3760,
580
],
"credentials": {
"gitPassword": {
"id": "myid"
"name": "Git account"
}
}
},
{
"parameters": {
"executeOnce": false,
"command": "=jq . {{ $json.fileName }} > {{ $json.fileName }}.tmp\nmv {{ $json.fileName }}.tmp {{ $json.fileName }}"
},
"id": "myid"
"name": "Convert JSON files into git friendly format",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
2740,
580
]
},
{
"parameters": {
"rule": {
"interval": [
{}
]
}
},
"id": "myid"
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
160,
440
]
}
],
"connections": {
"Move Binary Data": {
"main": [
[
{
"node": "Write Binary File",
"type": "main",
"index": 0
}
]
]
},
"Write Binary File": {
"main": [
[
{
"node": "Convert JSON files into git friendly format",
"type": "main",
"index": 0
}
]
]
},
"Clone the repo": {
"main": [
[
{
"node": "Pull the repo",
"type": "main",
"index": 0
}
]
]
},
"Add them to git": {
"main": [
[
{
"node": "User e-mail",
"type": "main",
"index": 0
}
]
]
},
"List n8n workflows": {
"main": [
[
{
"node": "Generate git friendly filenames",
"type": "main",
"index": 0
}
]
]
},
"Pull the repo": {
"main": [
[
{
"node": "List n8n workflows",
"type": "main",
"index": 0
}
]
]
},
"Is repo already exist": {
"main": [
[
{
"node": "Clone the repo",
"type": "main",
"index": 0
}
],
[
{
"node": "construct repo url",
"type": "main",
"index": 0
}
]
]
},
"Is this the right repo": {
"main": [
[
{
"node": "Pull the repo",
"type": "main",
"index": 0
}
],
[
{
"node": "Delete current repo",
"type": "main",
"index": 0
}
]
]
},
"Delete current repo": {
"main": [
[
{
"node": "Clone the repo",
"type": "main",
"index": 0
}
]
]
},
"construct repo url": {
"main": [
[
{
"node": "Is this the right repo",
"type": "main",
"index": 0
}
]
]
},
"Set variables": {
"main": [
[
{
"node": "Check repo config",
"type": "main",
"index": 0
}
]
]
},
"Generate git friendly filenames": {
"main": [
[
{
"node": "Move Binary Data",
"type": "main",
"index": 0
}
]
]
},
"Check repo config": {
"main": [
[
{
"node": "Is repo already exist",
"type": "main",
"index": 0
}
]
]
},
"Commit": {
"main": [
[
{
"node": "Push to remote",
"type": "main",
"index": 0
}
]
]
},
"User e-mail": {
"main": [
[
{
"node": "Git username",
"type": "main",
"index": 0
}
]
]
},
"Git username": {
"main": [
[
{
"node": "Commit",
"type": "main",
"index": 0
}
]
]
},
"Convert JSON files into git friendly format": {
"main": [
[
{
"node": "Add them to git",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Set variables",
"type": "main",
"index": 0
}
]
]
}
}
}