8
n8n 한국어amn8n.com

이메일 승인 및 SSH를 사용한 Docker 기반 n8n 업데이트 자동화

고급

이것은DevOps분야의자동화 워크플로우로, 27개의 노드를 포함합니다.주로 If, Set, Ssh, EmailSend, HttpRequest 등의 노드를 사용하며. 이메일 승인 및 SSH를 사용한 Docker 기반 n8n 업데이트 자동화

사전 요구사항
  • 대상 API의 인증 정보가 필요할 수 있음

카테고리

워크플로우 미리보기
노드 연결 관계를 시각적으로 표시하며, 확대/축소 및 이동을 지원합니다
워크플로우 내보내기
다음 JSON 구성을 복사하여 n8n에 가져오면 이 워크플로우를 사용할 수 있습니다
{
  "meta": {
    "instanceId": "0cf1013c00750bfab7ca7f6a76bf0e8c2407d7a4a9a4e66c4888ec456837f043",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "6486fadd-3584-4544-9a02-57ede53e836b",
      "name": "메모 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": "일정 트리거",
      "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": "If No Changes",
      "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": "Check Existence of Update Script",
      "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": "If File Exists",
      "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": "Create Update Script",
      "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": "If Approved",
      "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": "No Updates",
      "type": "n8n-nodes-base.noOp",
      "position": [
        -1776,
        -464
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "3a90a6d9-b1b1-4f9b-8194-676dccbdb5a5",
      "name": "Do Nothing",
      "type": "n8n-nodes-base.noOp",
      "position": [
        -1328,
        -160
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "c1dbc70c-db44-4f5c-9854-64d34d9f114f",
      "name": "Ask For Approval to Update",
      "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": "메모 - Auto Update",
      "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": "메모 - Script Logic",
      "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": "메모 - Final Execution",
      "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": "Execute Update Script",
      "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": "메모",
      "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": "Get Local Image Digest",
      "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": "Get Remote Image Digest",
      "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": "메모 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": "Prepare Update Data",
      "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": "메모",
      "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": "메모 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": "메모 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": "Get Current n8n Version",
      "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": "메모 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": "메모 - Declined1",
      "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": "메모 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": "설정up Requirements",
      "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
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "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
          }
        ]
      ]
    }
  }
}
자주 묻는 질문

이 워크플로우를 어떻게 사용하나요?

위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.

이 워크플로우는 어떤 시나리오에 적합한가요?

고급 - 데브옵스

유료인가요?

이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.

워크플로우 정보
난이도
고급
노드 수27
카테고리1
노드 유형8
난이도 설명

고급 사용자를 위한 16+개 노드의 복잡한 워크플로우

외부 링크
n8n.io에서 보기

이 워크플로우 공유

카테고리

카테고리: 34