Actualización automatizada basada en Docker de n8n con aprobación por correo y SSH
Este es unDevOpsflujo de automatización del dominio deautomatización que contiene 27 nodos.Utiliza principalmente nodos como If, Set, Ssh, EmailSend, HttpRequest. Automatización de actualizaciones de n8n basado en Docker con aprobación por correo y SSH
- •Pueden requerirse credenciales de autenticación para la API de destino
Nodos utilizados (27)
Categoría
{
"meta": {
"instanceId": "0cf1013c00750bfab7ca7f6a76bf0e8c2407d7a4a9a4e66c4888ec456837f043",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "6486fadd-3584-4544-9a02-57ede53e836b",
"name": "Nota adhesiva 1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3456,
-448
],
"parameters": {
"color": 4,
"width": 280,
"height": 288,
"content": "## 🚀 WORKFLOW START\n\n**Triggers:**\n- Manual execution (test runs)\n- Automated every 3 days at 4 PM UTC\n\nThis workflow checks for n8n updates and sends an approval email, to automatically update the n8n instance."
},
"typeVersion": 1
},
{
"id": "683461fc-856d-41e8-9d49-9b725fa3a2fa",
"name": "Activador programado",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-3120,
-368
],
"parameters": {
"rule": {
"interval": [
{
"daysInterval": 3,
"triggerAtHour": 16
}
]
}
},
"typeVersion": 1.2
},
{
"id": "ab507d4a-1a4c-49de-9b32-07f60969b0e7",
"name": "Si no hay cambios",
"type": "n8n-nodes-base.if",
"position": [
-2000,
-368
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "47b24202-69ea-481a-8848-67de206ea3c0",
"operator": {
"type": "boolean",
"operation": "false",
"singleValue": true
},
"leftValue": "={{ $json.update_available }}",
"rightValue": "=Download complete"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "bcdcdc19-e21c-48fb-80bb-014144c6fa6a",
"name": "Verificar existencia del script de actualización",
"type": "n8n-nodes-base.ssh",
"position": [
-1328,
-384
],
"parameters": {
"cwd": "/root",
"command": "=sh -c \"if [ -f update_docker.sh ]; then echo true; else echo false; fi\""
},
"credentials": {
"sshPassword": {
"id": "09btBw3BAMtH8hXO",
"name": "SSH Password account"
}
},
"typeVersion": 1
},
{
"id": "a9cbbad8-5f2f-411f-bc4a-62230e93c0e2",
"name": "Si el archivo existe",
"type": "n8n-nodes-base.if",
"position": [
-1104,
-384
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "1cf2c480-a309-46bc-a0c4-c2cf9827822d",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.stdout }}",
"rightValue": "true"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "ba972070-a78a-4982-975f-7219f26571e3",
"name": "Crear script de actualización",
"type": "n8n-nodes-base.ssh",
"position": [
-880,
-304
],
"parameters": {
"cwd": "/root",
"command": "=sh -c \"printf '%s\\n' 'sleep 30s' 'cd /opt/n8n-docker-caddy' 'docker compose pull' 'docker compose down' 'docker compose up -d' > update_docker.sh; chmod +x update_docker.sh\""
},
"credentials": {
"sshPassword": {
"id": "09btBw3BAMtH8hXO",
"name": "SSH Password account"
}
},
"typeVersion": 1
},
{
"id": "12f9fcab-8bcb-4bea-8e66-69f5227fb7bf",
"name": "Si está aprobado",
"type": "n8n-nodes-base.if",
"position": [
-1552,
-272
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "32c6b0f0-0747-47de-90e4-56ded46d3d34",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.data.approved }}",
"rightValue": "true"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "f3a6c807-0f12-45b6-bed7-ce4cbda4e42b",
"name": "Sin actualizaciones",
"type": "n8n-nodes-base.noOp",
"position": [
-1776,
-464
],
"parameters": {},
"typeVersion": 1
},
{
"id": "3a90a6d9-b1b1-4f9b-8194-676dccbdb5a5",
"name": "No hacer nada",
"type": "n8n-nodes-base.noOp",
"position": [
-1328,
-160
],
"parameters": {},
"typeVersion": 1
},
{
"id": "c1dbc70c-db44-4f5c-9854-64d34d9f114f",
"name": "Solicitar aprobación para actualizar",
"type": "n8n-nodes-base.emailSend",
"position": [
-1776,
-272
],
"webhookId": "c1c2c77a-a3c1-4c4d-83e9-229dfc3b0903",
"parameters": {
"message": "=<h2>🔔 n8n Update Available</h2>\n\n<p>A new version of n8n is available on Docker Hub!</p>\n\n<table style=\"border-collapse: collapse; width: 100%; margin: 20px 0;\">\n <tr style=\"background-color: #f8f9fa;\">\n <td style=\"padding: 12px; border: 1px solid #dee2e6; font-weight: bold;\">Current Version:</td>\n <td style=\"padding: 12px; border: 1px solid #dee2e6;\">{{ $json.current_version }}</td>\n </tr>\n <tr>\n <td style=\"padding: 12px; border: 1px solid #dee2e6; font-weight: bold;\">New Version Available:</td>\n <td style=\"padding: 12px; border: 1px solid #dee2e6; color: #28a745; font-weight: bold;\">Latest from Docker Hub</td>\n </tr>\n <tr style=\"background-color: #f8f9fa;\">\n <td style=\"padding: 12px; border: 1px solid #dee2e6; font-weight: bold;\">Local Digest:</td>\n <td style=\"padding: 12px; border: 1px solid #dee2e6; font-family: monospace; font-size: 11px;\">{{ $json.local_digest }}</td>\n </tr>\n <tr>\n <td style=\"padding: 12px; border: 1px solid #dee2e6; font-weight: bold;\">Remote Digest:</td>\n <td style=\"padding: 12px; border: 1px solid #dee2e6; font-family: monospace; font-size: 11px;\">{{ $json.remote_digest }}</td>\n </tr>\n</table>\n\n<h3>📋 What happens if you approve?</h3>\n<ol>\n <li>Pull the new n8n Docker image from Docker Hub</li>\n <li>Restart the n8n container with the new version</li>\n</ol>\n\n<h3>🔧 Manual Update Option</h3>\n<p>If you prefer to update manually later, run these commands on your server:</p>\n<pre style=\"background-color: #f8f8f8; padding: 10px; border-radius: 4px; border: 1px solid #ddd;\">\ncd /opt/n8n-docker-caddy\ndocker compose pull\ndocker compose down\ndocker compose up -d\n</pre>\n\n<p><strong>Do you want to proceed with the automatic update?</strong></p>",
"options": {
"limitWaitTime": {
"values": {
"resumeAmount": 3
}
},
"appendAttribution": false
},
"subject": "Approval Required for Updating n8n!",
"toEmail": "youremail@yourdomain.com",
"fromEmail": "info@yourdomain.com",
"operation": "sendAndWait",
"approvalOptions": {
"values": {
"approvalType": "double"
}
}
},
"credentials": {
"smtp": {
"id": "7qY1U0ZUdM7HKciv",
"name": "SMTP account"
}
},
"typeVersion": 2.1
},
{
"id": "0829b238-0c14-4be8-bbf1-edaa63016b51",
"name": "Nota adhesiva - Actualización automática",
"type": "n8n-nodes-base.stickyNote",
"position": [
-992,
-112
],
"parameters": {
"color": 6,
"width": 320,
"height": 432,
"content": "## 🔧 AUTOMATED UPDATE PROCESS\n\n**Three-step update execution:**\n\n1. **Check Script**: Verify if update script exists\n2. **Create Script** (if needed): Generate update script with:\n - 30-second delay\n - Navigate to docker directory\n - Execute update commands\n3. **Execute**: Run script in background via `nohup`\n\n**The 60-second delay ensures this workflow completes before container restarts!**"
},
"typeVersion": 1
},
{
"id": "c68450b6-ff97-4be4-932f-42dbabdab811",
"name": "Nota adhesiva - Lógica del script",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1392,
-672
],
"parameters": {
"color": 7,
"width": 280,
"height": 248,
"content": "## 🎯 SCRIPT LOGIC\n\n**Optimizes script creation:**\n\n- If script exists → Use it directly\n- If script missing → Create new one\n\nPrevents unnecessary file operations and ensures idempotency."
},
"typeVersion": 1
},
{
"id": "277ab82a-701a-4edc-8def-1dab9165ebe2",
"name": "Nota adhesiva - Ejecución final",
"type": "n8n-nodes-base.stickyNote",
"position": [
-976,
-752
],
"parameters": {
"color": 3,
"width": 320,
"height": 328,
"content": "## 🚀 FINAL EXECUTION\n\n**Runs in background:**\n\nExecutes `update_docker.sh` with:\n- `nohup`: Runs independently of this session\n- `> update.log`: Logs output for debugging\n- `2>&1`: Captures both stdout and stderr\n- `&`: Background execution\n\n**Workflow completes immediately, update happens 30 seconds later!**"
},
"typeVersion": 1
},
{
"id": "5a44fe76-5ca3-4477-9f5d-486c8abec4ab",
"name": "Ejecutar script de actualización",
"type": "n8n-nodes-base.ssh",
"position": [
-656,
-400
],
"parameters": {
"cwd": "/root",
"command": "=sh -c \"exec >/root/update.log 2>&1; nohup /root/update_docker.sh &\""
},
"credentials": {
"sshPassword": {
"id": "09btBw3BAMtH8hXO",
"name": "SSH Password account"
}
},
"typeVersion": 1
},
{
"id": "9a65a79e-eb2e-4ad2-8920-fe6a4a8053c6",
"name": "Nota adhesiva",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3536,
-928
],
"parameters": {
"color": 5,
"width": 3104,
"height": 1520,
"content": "# n8n-Self-Updater"
},
"typeVersion": 1
},
{
"id": "9b195a5d-3057-4690-9a7f-63947349df7b",
"name": "Obtener digest de imagen local",
"type": "n8n-nodes-base.ssh",
"position": [
-2672,
-368
],
"parameters": {
"cwd": "/root",
"command": "sh -c \"docker inspect n8n-docker-caddy-n8n-1 --format='{{index .Image}}' | xargs docker inspect --format='{{index .RepoDigests 0}}'\""
},
"credentials": {
"sshPassword": {
"id": "09btBw3BAMtH8hXO",
"name": "SSH Password account"
}
},
"typeVersion": 1
},
{
"id": "9f46efa6-bfa4-43cc-bc8b-50f4789bfc3f",
"name": "Obtener digest de imagen remota",
"type": "n8n-nodes-base.httpRequest",
"position": [
-2448,
-368
],
"parameters": {
"url": "https://hub.docker.com/v2/repositories/n8nio/n8n/tags/latest",
"options": {}
},
"typeVersion": 4.2
},
{
"id": "b06e54b7-3760-46b6-b35b-95f74ea19ada",
"name": "Nota adhesiva 9",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2224,
-672
],
"parameters": {
"width": 320,
"height": 264,
"content": "## 🔀 UPDATE CHECK\n\n**Checks if update exists:**\n\nCompares local vs remote digest:\n- If digests match → No update (top path)\n- If digests differ → Update available (bottom path)\n\n**Prevents unnecessary email notifications!**"
},
"typeVersion": 1
},
{
"id": "ef630305-91e7-4d78-9a8d-a2729063ddb0",
"name": "Preparar datos de actualización",
"type": "n8n-nodes-base.set",
"position": [
-2224,
-368
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "832662b6-8fe8-4849-870b-71d32bf88a46",
"name": "current_version",
"type": "string",
"value": "={{ $('Get Current n8n Version').first().json.stdout }}"
},
{
"id": "local-digest-assign",
"name": "local_digest",
"type": "string",
"value": "={{ $('Get Local Image Digest').first().json.stdout.split('@')[1] }}"
},
{
"id": "remote-digest-assign",
"name": "remote_digest",
"type": "string",
"value": "={{ $('Get Remote Image Digest').first().json.digest }}"
},
{
"id": "new-version-assign",
"name": "update_available",
"type": "boolean",
"value": "={{ $('Get Local Image Digest').first().json.stdout.split('@')[1] !== $('Get Remote Image Digest').first().json.digest }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "71409d64-8391-4f08-8359-223728303c20",
"name": "Nota adhesiva",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1840,
-736
],
"parameters": {
"color": 4,
"width": 320,
"height": 224,
"content": "## ⛔ NO UPDATES FOUND\n\nWorkflow ends when:\n- Local and remote digests match\n- Already running latest version\n\n**No unnecessary emails!**\n\nWorkflow completes silently."
},
"typeVersion": 1
},
{
"id": "1c01f1f9-5c06-41fd-a130-44c43f9a5c11",
"name": "Nota adhesiva 2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2864,
-656
],
"parameters": {
"color": 5,
"width": 280,
"height": 248,
"content": "## 🔍 GET CURRENT INFO\n\nRetrieves:\n1. Current n8n version\n2. Local image digest (RepoDigest)\n\nThis tells us what we're currently running."
},
"typeVersion": 1
},
{
"id": "09ef5f83-d20d-489f-9199-aa1ce267427b",
"name": "Nota adhesiva 4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2528,
-144
],
"parameters": {
"color": 6,
"width": 280,
"height": 236,
"content": "## 🔎 CHECK REMOTE DIGEST\n\nQueries Docker Hub registry to get:\n- Remote image digest for :latest tag\n- WITHOUT pulling the image!\n\nUses Docker Registry HTTP API v2."
},
"typeVersion": 1
},
{
"id": "0aaada39-31ce-49b8-8526-b22264de5092",
"name": "Obtener versión actual de n8n",
"type": "n8n-nodes-base.ssh",
"position": [
-2896,
-368
],
"parameters": {
"cwd": "/root",
"command": "=sh -c \"docker exec n8n-docker-caddy-n8n-1 n8n --version\""
},
"credentials": {
"sshPassword": {
"id": "09btBw3BAMtH8hXO",
"name": "SSH Password account"
}
},
"typeVersion": 1
},
{
"id": "9982be9b-af55-4364-a29a-d70dca2af86e",
"name": "Nota adhesiva 5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1888,
-64
],
"parameters": {
"color": 3,
"width": 320,
"height": 232,
"content": "## 📧 APPROVAL REQUEST\n\nSends email with:\n- Current version\n- Digest comparison\n- **Approve/Disapprove buttons**\n\nn8n stays exactly as-is until you click APPROVE!"
},
"typeVersion": 1
},
{
"id": "4cf50320-6d4a-4af1-ac91-941f8f2c7851",
"name": "Nota adhesiva - Rechazado1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1408,
0
],
"parameters": {
"color": 4,
"width": 280,
"height": 248,
"content": "## 🛑 UPDATE DECLINED\n\nWorkflow ends when:\n- User clicks **Decline**\n- Update will wait for next check or manual execution\n\n**Manual option always available!**"
},
"typeVersion": 1
},
{
"id": "69673ede-0abc-43ec-86ea-5ae72a6289d2",
"name": "Nota adhesiva 6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-4080,
-160
],
"parameters": {
"color": 2,
"width": 496,
"height": 408,
"content": "## 📊 WORKFLOW SUMMARY\n\n**Flow:**\n1. Get current version + local digest\n2. Get remote digest from Docker Hub\n3. Compare digests\n4. If different → Request approval with version info\n5. If approved → Pull and restart\n6. If same → Silent skip\n\n**Benefits:**\n- Bandwidth efficient\n- Clear version comparison\n- Manual approval control\n- No spam when no updates"
},
"typeVersion": 1
},
{
"id": "b1613e0c-a14f-4903-96c3-dedd46423a25",
"name": "Configurar requisitos",
"type": "n8n-nodes-base.stickyNote",
"position": [
-4080,
-928
],
"parameters": {
"width": 500,
"height": 704,
"content": "## 🧩 SETUP REQUIREMENTS\n\n**1️⃣ SSH Credentials**\n- Go to *Credentials → New → SSH Password*\n- Enter:\n - Host: your VPS IP (e.g., 165.22.xx.xx)\n - Port: 22\n - Username: root / ubuntu\n - Password or Private Key\n\n\n**2️⃣ SMTP Credentials (Email)**\n- Go to *Credentials → New → SMTP*\n- Fill in:\n - Host: smtp.yourprovider.com\n - Port: 465 (SSL) / 587 (TLS)\n - User: your email\n - Password: email password or app password\n\n\n**3️⃣ Docker Server Setup**\n- Ensure Docker + docker-compose are installed\n- n8n is deployed via docker-compose (e.g., /opt/n8n-docker-caddy)\n\n\n**4️⃣ Workflow Setup**\n- Import the JSON workflow\n- Edit Email Node → update `fromEmail` & `toEmail`\n- Connect correct SSH + SMTP credentials\n- Enable Schedule Trigger (optional)\n\n✅ Once complete, test manually before activating auto checks."
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"12f9fcab-8bcb-4bea-8e66-69f5227fb7bf": {
"main": [
[
{
"node": "bcdcdc19-e21c-48fb-80bb-014144c6fa6a",
"type": "main",
"index": 0
}
],
[
{
"node": "3a90a6d9-b1b1-4f9b-8194-676dccbdb5a5",
"type": "main",
"index": 0
}
]
]
},
"ab507d4a-1a4c-49de-9b32-07f60969b0e7": {
"main": [
[
{
"node": "f3a6c807-0f12-45b6-bed7-ce4cbda4e42b",
"type": "main",
"index": 0
}
],
[
{
"node": "c1dbc70c-db44-4f5c-9854-64d34d9f114f",
"type": "main",
"index": 0
}
]
]
},
"a9cbbad8-5f2f-411f-bc4a-62230e93c0e2": {
"main": [
[
{
"node": "5a44fe76-5ca3-4477-9f5d-486c8abec4ab",
"type": "main",
"index": 0
}
],
[
{
"node": "ba972070-a78a-4982-975f-7219f26571e3",
"type": "main",
"index": 0
}
]
]
},
"683461fc-856d-41e8-9d49-9b725fa3a2fa": {
"main": [
[
{
"node": "0aaada39-31ce-49b8-8526-b22264de5092",
"type": "main",
"index": 0
}
]
]
},
"ef630305-91e7-4d78-9a8d-a2729063ddb0": {
"main": [
[
{
"node": "ab507d4a-1a4c-49de-9b32-07f60969b0e7",
"type": "main",
"index": 0
}
]
]
},
"ba972070-a78a-4982-975f-7219f26571e3": {
"main": [
[
{
"node": "5a44fe76-5ca3-4477-9f5d-486c8abec4ab",
"type": "main",
"index": 0
}
]
]
},
"9b195a5d-3057-4690-9a7f-63947349df7b": {
"main": [
[
{
"node": "9f46efa6-bfa4-43cc-bc8b-50f4789bfc3f",
"type": "main",
"index": 0
}
]
]
},
"0aaada39-31ce-49b8-8526-b22264de5092": {
"main": [
[
{
"node": "9b195a5d-3057-4690-9a7f-63947349df7b",
"type": "main",
"index": 0
}
]
]
},
"9f46efa6-bfa4-43cc-bc8b-50f4789bfc3f": {
"main": [
[
{
"node": "ef630305-91e7-4d78-9a8d-a2729063ddb0",
"type": "main",
"index": 0
}
]
]
},
"c1dbc70c-db44-4f5c-9854-64d34d9f114f": {
"main": [
[
{
"node": "12f9fcab-8bcb-4bea-8e66-69f5227fb7bf",
"type": "main",
"index": 0
}
]
]
},
"bcdcdc19-e21c-48fb-80bb-014144c6fa6a": {
"main": [
[
{
"node": "a9cbbad8-5f2f-411f-bc4a-62230e93c0e2",
"type": "main",
"index": 0
}
]
]
}
}
}¿Cómo usar este flujo de trabajo?
Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.
¿En qué escenarios es adecuado este flujo de trabajo?
Avanzado - DevOps
¿Es de pago?
Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.
Flujos de trabajo relacionados recomendados
Muhammad Anas Farooq
@anasn-farooqCompartir este flujo de trabajo