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 →
{
"name": "Marcel - Sauvegarde Automatique",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 2 * * *"
}
]
}
},
"id": "f8b8c8e0-6234-4567-8901-000000000001",
"name": "Sauvegarde Quotidienne",
"type": "n8n-nodes-base.cron",
"typeVersion": 1,
"position": [
240,
300
]
},
{
"parameters": {
"jsCode": "// G\u00e9n\u00e9rer le nom de fichier de sauvegarde\nconst now = new Date();\nconst dateStr = now.toISOString().split('T')[0];\nconst timeStr = now.toTimeString().split(' ')[0].replace(/:/g, '-');\n\nconst backupName = `marcel_backup_${dateStr}_${timeStr}`;\nconst sqlFile = `/backups/${backupName}.sql`;\nconst archiveFile = `/backups/${backupName}.tar.gz`;\n\nreturn {\n backup_name: backupName,\n sql_file: sqlFile,\n archive_file: archiveFile,\n date: dateStr,\n time: timeStr\n};"
},
"id": "f8b8c8e0-6234-4567-8901-000000000002",
"name": "Pr\u00e9parer Sauvegarde",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
460,
300
]
},
{
"parameters": {
"command": "pg_dump -h postgres -U marcel_user -d marcel_n8n > {{ $json.sql_file }}",
"options": {}
},
"id": "f8b8c8e0-6234-4567-8901-000000000003",
"name": "Dump Base Donn\u00e9es",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
680,
300
]
},
{
"parameters": {
"command": "tar -czf {{ $json.archive_file }} -C /home/node/.n8n . && tar -czf {{ $json.archive_file.replace('.tar.gz', '_db.tar.gz') }} {{ $json.sql_file }}",
"options": {}
},
"id": "f8b8c8e0-6234-4567-8901-000000000004",
"name": "Cr\u00e9er Archive",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
900,
300
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "condition1",
"leftValue": "={{ $vars.BACKUP_S3_BUCKET }}",
"rightValue": "",
"operator": {
"type": "string",
"operation": "isNotEmpty"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "f8b8c8e0-6234-4567-8901-000000000005",
"name": "Backup S3 Configur\u00e9 ?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1120,
200
]
},
{
"parameters": {
"bucket": "={{ $vars.BACKUP_S3_BUCKET }}",
"fileKey": "marcel/{{ $('Pr\u00e9parer Sauvegarde').first().json.backup_name }}.tar.gz",
"binaryData": true,
"additionalFields": {
"storageClass": "STANDARD_IA"
}
},
"id": "f8b8c8e0-6234-4567-8901-000000000006",
"name": "Upload S3",
"type": "n8n-nodes-base.awsS3",
"typeVersion": 1,
"position": [
1340,
120
],
"credentials": {
"aws": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "insert",
"table": "logs_systeme",
"columns": "niveau, module, message, details",
"additionalFields": {
"niveau": "info",
"module": "backup",
"message": "Sauvegarde automatique effectu\u00e9e avec succ\u00e8s",
"details": "{{ JSON.stringify({backup_name: $('Pr\u00e9parer Sauvegarde').first().json.backup_name, s3_upload: $('Backup S3 Configur\u00e9 ?').first().json ? 'success' : 'skipped'}) }}"
}
},
"id": "f8b8c8e0-6234-4567-8901-000000000007",
"name": "Log Sauvegarde",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.4,
"position": [
1120,
400
],
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"operation": "insert",
"table": "notifications",
"columns": "type_notification, titre, message, priorite, canaux",
"additionalFields": {
"type_notification": "systeme",
"titre": "\u2705 Sauvegarde Marcel termin\u00e9e",
"message": "\ud83d\udcbe **Sauvegarde automatique r\u00e9ussie**\\n\\n\ud83d\udcc1 Fichier: {{ $('Pr\u00e9parer Sauvegarde').first().json.backup_name }}\\n\ud83d\udcc5 Date: {{ new Date().toLocaleString('fr-FR') }}\\n{{ $('Backup S3 Configur\u00e9 ?').first().json ? '\u2601\ufe0f Upload\u00e9 sur S3' : '\ud83d\udcbd Sauvegarde locale uniquement' }}\\n\\n\ud83d\udd12 Vos donn\u00e9es Marcel sont s\u00e9curis\u00e9es !",
"priorite": "faible",
"canaux": [
"telegram"
]
}
},
"id": "f8b8c8e0-6234-4567-8901-000000000008",
"name": "Notification Succ\u00e8s",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.4,
"position": [
1340,
400
],
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 4 * * 0"
}
]
}
},
"id": "f8b8c8e0-6234-4567-8901-000000000009",
"name": "Nettoyage Sauvegardes",
"type": "n8n-nodes-base.cron",
"typeVersion": 1,
"position": [
240,
600
]
},
{
"parameters": {
"command": "find /backups -name 'marcel_backup_*.tar.gz' -mtime +30 -delete && find /backups -name 'marcel_backup_*.sql' -mtime +7 -delete",
"options": {}
},
"id": "f8b8c8e0-6234-4567-8901-000000000010",
"name": "Supprimer Anciennes",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
460,
600
]
},
{
"parameters": {
"operation": "insert",
"table": "logs_systeme",
"columns": "niveau, module, message, details",
"additionalFields": {
"niveau": "info",
"module": "backup",
"message": "Nettoyage des anciennes sauvegardes effectu\u00e9",
"details": "{{ JSON.stringify({action: 'cleanup', retention_days: 30}) }}"
}
},
"id": "f8b8c8e0-6234-4567-8901-000000000011",
"name": "Log Nettoyage",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.4,
"position": [
680,
600
],
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"httpMethod": "POST",
"path": "backup/restore",
"options": {}
},
"id": "f8b8c8e0-6234-4567-8901-000000000012",
"name": "Webhook Restauration",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
240,
800
]
},
{
"parameters": {
"jsCode": "// Valider la demande de restauration\nconst body = $json.body;\n\nif (!body.backup_name) {\n return {\n error: 'Nom de sauvegarde requis',\n status: 400\n };\n}\n\n// V\u00e9rifier que le fichier existe\nconst fs = require('fs');\nconst backupFile = `/backups/${body.backup_name}.sql`;\n\nif (!fs.existsSync(backupFile)) {\n return {\n error: 'Fichier de sauvegarde non trouv\u00e9',\n status: 404,\n backup_name: body.backup_name\n };\n}\n\nreturn {\n backup_name: body.backup_name,\n backup_file: backupFile,\n status: 200,\n confirmed: body.confirm === true\n};"
},
"id": "f8b8c8e0-6234-4567-8901-000000000013",
"name": "Valider Restauration",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
460,
800
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "condition1",
"leftValue": "={{ $json.status }}",
"rightValue": 200,
"operator": {
"type": "number",
"operation": "equals"
}
},
{
"id": "condition2",
"leftValue": "={{ $json.confirmed }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "f8b8c8e0-6234-4567-8901-000000000014",
"name": "Restauration Confirm\u00e9e ?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
680,
700
]
},
{
"parameters": {
"command": "psql -h postgres -U marcel_user -d marcel_n8n < {{ $json.backup_file }}",
"options": {}
},
"id": "f8b8c8e0-6234-4567-8901-000000000015",
"name": "Restaurer Base",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
900,
620
]
},
{
"parameters": {
"operation": "insert",
"table": "logs_systeme",
"columns": "niveau, module, message, details",
"additionalFields": {
"niveau": "warning",
"module": "backup",
"message": "Restauration de sauvegarde effectu\u00e9e",
"details": "{{ JSON.stringify({backup_name: $('Valider Restauration').first().json.backup_name, restored_at: new Date().toISOString()}) }}"
}
},
"id": "f8b8c8e0-6234-4567-8901-000000000016",
"name": "Log Restauration",
"type": "n8n-nodes-base.postgres",
"typeVersion": 2.4,
"position": [
1120,
620
],
"credentials": {
"postgres": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"respondWith": "json",
"responseBody": "{\n \"success\": {{ $json.status === 200 && $json.confirmed ? 'true' : 'false' }},\n \"message\": \"{{ $json.error || 'Restauration effectu\u00e9e avec succ\u00e8s' }}\",\n \"backup_name\": \"{{ $json.backup_name }}\"\n}",
"options": {}
},
"id": "f8b8c8e0-6234-4567-8901-000000000017",
"name": "R\u00e9ponse Restauration",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
680,
900
]
}
],
"connections": {
"Sauvegarde Quotidienne": {
"main": [
[
{
"node": "Pr\u00e9parer Sauvegarde",
"type": "main",
"index": 0
}
]
]
},
"Pr\u00e9parer Sauvegarde": {
"main": [
[
{
"node": "Dump Base Donn\u00e9es",
"type": "main",
"index": 0
}
]
]
},
"Dump Base Donn\u00e9es": {
"main": [
[
{
"node": "Cr\u00e9er Archive",
"type": "main",
"index": 0
}
]
]
},
"Cr\u00e9er Archive": {
"main": [
[
{
"node": "Backup S3 Configur\u00e9 ?",
"type": "main",
"index": 0
},
{
"node": "Log Sauvegarde",
"type": "main",
"index": 0
}
]
]
},
"Backup S3 Configur\u00e9 ?": {
"main": [
[
{
"node": "Upload S3",
"type": "main",
"index": 0
}
]
]
},
"Log Sauvegarde": {
"main": [
[
{
"node": "Notification Succ\u00e8s",
"type": "main",
"index": 0
}
]
]
},
"Nettoyage Sauvegardes": {
"main": [
[
{
"node": "Supprimer Anciennes",
"type": "main",
"index": 0
}
]
]
},
"Supprimer Anciennes": {
"main": [
[
{
"node": "Log Nettoyage",
"type": "main",
"index": 0
}
]
]
},
"Webhook Restauration": {
"main": [
[
{
"node": "Valider Restauration",
"type": "main",
"index": 0
}
]
]
},
"Valider Restauration": {
"main": [
[
{
"node": "Restauration Confirm\u00e9e ?",
"type": "main",
"index": 0
},
{
"node": "R\u00e9ponse Restauration",
"type": "main",
"index": 0
}
]
]
},
"Restauration Confirm\u00e9e ?": {
"main": [
[
{
"node": "Restaurer Base",
"type": "main",
"index": 0
}
]
]
},
"Restaurer Base": {
"main": [
[
{
"node": "Log Restauration",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {
"executionOrder": "v1"
},
"versionId": "1",
"meta": {
"templateCredsSetupCompleted": true
},
"id": "marcel-backup",
"tags": [
{
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z",
"id": "marcel-system",
"name": "Marcel Syst\u00e8me"
}
]
}
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.
awspostgres
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
How this works
This workflow ensures your PostgreSQL database is automatically backed up daily, safeguarding critical data against loss and enabling quick recovery if needed, which is essential for businesses relying on reliable data storage. It suits database administrators or small teams managing web applications, automating the tedious process of manual backups to save time and reduce errors. The key step involves executing a command-line dump of the database, compressing it into an archive, and securely uploading it to AWS S3 for long-term storage, with success logged and notifications sent via PostgreSQL.
Use this workflow for routine daily backups of production databases where data integrity is paramount, such as e-commerce or content management systems. Avoid it for very large datasets exceeding S3's practical limits or when real-time replication tools like PostgreSQL's built-in streaming are more appropriate. Common variations include adjusting the cron schedule for weekly runs or adding email notifications instead of database logs for non-technical users.
About this workflow
Marcel - Sauvegarde Automatique. Uses executeCommand, awsS3, postgres. Scheduled trigger; 17 nodes.
Source: https://github.com/EpicSanDev/MARCEL/blob/83184adb16a52a1b39a4a118ab7e10aa6e236200/workflows/06-backup.json — 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.
Automated Knowledge Management Backup & Recovery. Uses executeCommand, postgres, httpRequest, googleDrive. Scheduled trigger; 30 nodes.
Project Genji - Complete Data Pipeline. Uses schedule, executeCommand, postgres. Scheduled trigger; 4 nodes.
Disparador 1.8. Uses itemLists, postgres, emailSend, httpRequest. Scheduled trigger; 85 nodes.
공유회_알림톡_크론. Uses postgres, httpRequest, n8n-nodes-solapi. Scheduled trigger; 39 nodes.
QuepasaAutomatic. Uses postgres, postgresTrigger, httpRequest. Scheduled trigger; 39 nodes.