Monitoreo automatizado de tiempo de actividad del sitio web, alertas por correo electrónico y actualización de la página de estado de GitHub
Este es unDevOpsflujo de automatización del dominio deautomatización que contiene 19 nodos.Utiliza principalmente nodos como If, Code, Gmail, Github, Switch. Monitoreo automatizado del tiempo de actividad del sitio web, alertas por correo y actualizaciones de la página de estado de GitHub
- •Cuenta de Google y credenciales de API de Gmail
- •Personal Access Token de GitHub
- •Pueden requerirse credenciales de autenticación para la API de destino
Nodos utilizados (19)
Categoría
{
"id": "PAjyHjl5YdaEp6Y2",
"meta": {
"instanceId": "cb69a80257e9c986533bb4191c0c85ea4947fbef18ed5faeb970927362aeebdc",
"templateCredsSetupCompleted": true
},
"name": "Automated Website Uptime Monitor with Email Alerts & GitHub Status Page Update",
"tags": [],
"nodes": [
{
"id": "24b40a8b-20b2-4ead-87a4-0be04641323a",
"name": "Disparador programado",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-3568,
-80
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 2
}
]
}
},
"typeVersion": 1.2
},
{
"id": "09c86eff-846d-43d1-a93f-f398f2223d67",
"name": "Solicitud HTTP",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
-3360,
-80
],
"parameters": {
"url": "https://app.yourdomain.com/health",
"options": {
"response": {
"response": {
"fullResponse": true
}
}
}
},
"typeVersion": 4.2,
"alwaysOutputData": false
},
{
"id": "7c7791f1-9174-4a60-b6bd-80f32d220952",
"name": "Nota adhesiva",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3808,
-480
],
"parameters": {
"color": 7,
"width": 400,
"height": 368,
"content": "> **About 📝**\n- Runs automatically every **2 minutes**.\n- Acts as the \"heartbeat\" of the workflow.\n- You can change the interval to any value (e.g., seconds, minutes, hours, days).\n- Useful when you want continuous monitoring without manual input.\nThe workflow checks your website every **2 minutes** (interval configurable). \n- If the website is **down (503, bad response, or error)** → it sends an email alert and updates the GitHub-hosted status page to show **Down**. \n- If the website is **up (200)** → it updates the GitHub-hosted status page to show **Up**. \n- The email notification includes an **HTML-formatted alert page**. \n- You can use GitHub Pages to **host the status page** publicly. \n"
},
"typeVersion": 1
},
{
"id": "99b08165-3c6c-4505-94e9-a23d7bdf606f",
"name": "Nota adhesiva1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3344,
160
],
"parameters": {
"color": 7,
"width": 320,
"height": 272,
"content": "> **HTML Request & Switch 📝**\n- Pings the target website (ex:(`https://app.yourdomain.com/health`).\n- Returns the **status code** and full response.\n- If website responds with **200**, site is considered **Up**.\n- If request fails (e.g., 503, ERR_BAD_RESPONSE), it will be treated as **Down**.\n- Always outputs data (even on error), ensuring the workflow doesn’t break.\n"
},
"typeVersion": 1
},
{
"id": "aad36f3c-6f6a-4c2a-9d9a-db60a08b54a7",
"name": "Nota adhesiva4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3312,
-224
],
"parameters": {
"width": 294,
"height": 80,
"content": "Here, upload your Website URL. EX: (`https://app.yourdomain.cc/health`)"
},
"typeVersion": 1
},
{
"id": "b4d88251-7516-4f8d-998b-86aa4e62f201",
"name": "Nota adhesiva2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2720,
-656
],
"parameters": {
"color": 7,
"width": 288,
"height": 256,
"content": "> **Email 📝**\n- Sends an **email alert** if the site is down.\n- Recipient: `example@gmail.com` (replace with your email/team DL).\n- Subject: \"Server Down\".\n- Message: Pre-styled HTML alert page with error details.\n- Can be customized for different recipients or notification styles.\n \n\n \n"
},
"typeVersion": 1
},
{
"id": "3c09250f-9f90-48fd-8a95-0c3d28ac3c90",
"name": "Nota adhesiva5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2608,
-368
],
"parameters": {
"width": 214,
"height": 80,
"content": "Upload with your Email ID.\nEX:\nexamaple@gmail.com"
},
"typeVersion": 1
},
{
"id": "741d5e5b-88f1-4acb-8ed8-0527f3c9448f",
"name": "Nota adhesiva6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2160,
192
],
"parameters": {
"color": 7,
"width": 560,
"height": 192,
"content": "> **Extract from File(Github)📝**\n\n-Extract the file from the Github Repository if the status is same (Extracted Status = Github Status) then make no changes/ no commit into Github.\n-If both are no same then commit the status in the Github."
},
"typeVersion": 1
},
{
"id": "348d04d6-1b88-4cb6-80f2-93a136850a81",
"name": "Nota adhesiva7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2464,
-144
],
"parameters": {
"height": 80,
"content": "-Upload your GitHub Repository owner URL.\n-Upload your Repository Name.\n"
},
"typeVersion": 1
},
{
"id": "83ddb904-7e94-4d2d-8cbe-a02e832435a1",
"name": "Nota adhesiva8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2800,
224
],
"parameters": {
"color": 7,
"width": 384,
"height": 368,
"content": "> **Template HTML Code & GitHub 📝**\n- Dynamically creates the **status page HTML (index.html) from the existing template**.\n- Two modes:\n - **Up** → Green status page with \"Server Up\".\n - **Down** → Red status page with error details (status code + error message).\n- You can fully customize the HTML & CSS here for branding.\n - Commits the newly generated `index.html` file to your GitHub repo.\n- Path: `index.html` in repository (default branch).\n- Commit message is configurable (default: \"test\").\n- If GitHub Pages is enabled, this file becomes the **live status page**."
},
"typeVersion": 1
},
{
"id": "d4f178ad-6597-4944-aa80-7335f26be23d",
"name": "Update Index.html file",
"type": "n8n-nodes-base.github",
"position": [
-1504,
-16
],
"webhookId": "efc7d4f3-037b-4ade-aab0-e9ec870bd39d",
"parameters": {
"owner": {
"__rl": true,
"mode": "url",
"value": "https://github.com/<OWNER_NAME>"
},
"filePath": "index.html",
"resource": "file",
"operation": "edit",
"binaryData": true,
"repository": {
"__rl": true,
"mode": "name",
"value": "status"
},
"commitMessage": "test"
},
"typeVersion": 1.1
},
{
"id": "7d86a237-36e6-4ce8-95cf-19ab8a58581d",
"name": "Send a notification mail",
"type": "n8n-nodes-base.gmail",
"position": [
-2832,
-384
],
"webhookId": "50a40372-a118-4922-9abe-ab5c3065b284",
"parameters": {
"sendTo": "example@gmail.com",
"message": "=\n <!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Status Page</title>\n <style>\n body {\n font-family: Arial, sans-serif;\n background: #f9fafb;\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100vh;\n margin: 0;\n }\n\n .status-container {\n text-align: center;\n padding: 2rem 3rem;\n }\n\n .status {\n font-size: 2rem;\n font-weight: bold;\n margin: 1rem 0;\n }\n\n .up {\n color: #fff;\n background-color: #16a34a; /* green */\n }\n\n .down {\n color: #fff;\n background-color: #dc2626; /* red */\n }\n\n .label {\n font-size: 1rem;\n color: #fff;\n text-transform: uppercase;\n letter-spacing: 2px;\n }\n </style>\n</head>\n<body class=\"down\">\n <div class=\"status-container down\">\n <div class=\"label\">Server Status</div>\n <div class=\"status down\">Down</div>\n <div class=\"down\">503</div>\n <div class=\"down\">ERR_BAD_RESPONSE</div>\n </div>\n</body>\n</html>\n\t",
"options": {},
"subject": "Server Down"
},
"typeVersion": 2.1
},
{
"id": "ba9b1eb6-6fcd-4ca8-b308-2b0daad7c299",
"name": "Switch - status code",
"type": "n8n-nodes-base.switch",
"position": [
-3152,
-80
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "503",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "1f49118f-0394-43bb-aaa0-2a850da82ac7",
"operator": {
"type": "number",
"operation": "equals"
},
"leftValue": "={{ $json.error.status }}",
"rightValue": 503
}
]
},
"renameOutput": true
},
{
"outputKey": "200",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "55486cce-71e5-4c93-a518-09c108a2f307",
"operator": {
"type": "number",
"operation": "equals"
},
"leftValue": "={{ $json.statusCode }}",
"rightValue": 200
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "ec136a3f-e79d-4480-8c19-893184458928",
"name": "Extract from File - Generated HTML",
"type": "n8n-nodes-base.extractFromFile",
"position": [
-2528,
-16
],
"parameters": {
"options": {},
"operation": "text"
},
"typeVersion": 1
},
{
"id": "3e4c16f9-25f7-4944-958a-3f5c2a8651b9",
"name": "Template HTML Código",
"type": "n8n-nodes-base.code",
"position": [
-2720,
-16
],
"parameters": {
"jsCode": "// n8n Code node (JavaScript)\n\nconst items = [];\n if ($input.first().json.statusCode){\n const htmlContent = `\n <!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Status Page</title>\n <style>\n body {\n font-family: Arial, sans-serif;\n background: #f9fafb;\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100vh;\n margin: 0;\n }\n\n .status-container {\n text-align: center;\n padding: 2rem 3rem;\n }\n\n .status {\n font-size: 2rem;\n font-weight: bold;\n margin: 1rem 0;\n }\n\n .up {\n color: #fff;\n background-color: #16a34a; /* green */\n }\n\n .down {\n color: #fff;\n background-color: #dc2626; /* red */\n }\n\n .label {\n font-size: 1rem;\n color: #fff;\n text-transform: uppercase;\n letter-spacing: 2px;\n }\n </style>\n</head>\n<body class=\"up\">\n <div class=\"status-container up\">\n <div class=\"label\">Server Status</div>\n <div class=\"status\">Up</div>\n <!-- If server is down, replace above with -->\n <!-- <div class=\"status down\">Down</div> -->\n </div>\n</body>\n</html>\n\t`;\n\n\t// Convert HTML string to Base64\n\tconst base64Data = Buffer.from(htmlContent, 'utf-8').toString('base64');\n\n\t// Push result in binary format\n\titems.push({\n\t\tbinary: {\n\t\t\tdata: {\n\t\t\t\tfileName: 'index.html',\n\t\t\t\tmimeType: 'text/html',\n\t\t\t\tdata: base64Data,\n\t\t\t}\n\t\t}\n\t});\n\nreturn items;\n }\nelse if ($input.first().json.error.status) {\n const htmlContent = `\n <!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Status Page</title>\n <style>\n body {\n font-family: Arial, sans-serif;\n background: #f9fafb;\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100vh;\n margin: 0;\n }\n\n .status-container {\n text-align: center;\n padding: 2rem 3rem;\n }\n\n .status {\n font-size: 2rem;\n font-weight: bold;\n margin: 1rem 0;\n }\n\n .up {\n color: #fff;\n background-color: #16a34a; /* green */\n }\n\n .down {\n color: #fff;\n background-color: #dc2626; /* red */\n }\n\n .label {\n font-size: 1rem;\n color: #fff;\n text-transform: uppercase;\n letter-spacing: 2px;\n }\n </style>\n</head>\n<body class=\"down\">\n <div class=\"status-container down\">\n <div class=\"label\">Server Status</div>\n <div class=\"status down\">Down</div>\n <div class=\"down\">${$input.first().json.error.status}</div>\n <div class=\"down\">${$input.first().json.error.code}</div>\n </div>\n</body>\n</html>\n\t`;\n\n\t// Convert HTML string to Base64\n\tconst base64Data = Buffer.from(htmlContent, 'utf-8').toString('base64');\n\n\t// Push result in binary format\n\titems.push({\n\t\tbinary: {\n\t\t\tdata: {\n\t\t\t\tfileName: 'index.html',\n\t\t\t\tmimeType: 'text/html',\n\t\t\t\tdata: base64Data,\n\t\t\t}\n\t\t}\n\t});\n\nreturn items;\n}\n\t"
},
"typeVersion": 2
},
{
"id": "4423f742-0144-4ffb-b28b-a6d108e3b5ca",
"name": "Get existing index.html file",
"type": "n8n-nodes-base.github",
"position": [
-2160,
-16
],
"webhookId": "8c6e35c4-1460-4620-a736-732f472881bd",
"parameters": {
"owner": {
"__rl": true,
"mode": "url",
"value": "https://github.com/<OWNER_NAME>"
},
"filePath": "index.html",
"resource": "file",
"operation": "get",
"repository": {
"__rl": true,
"mode": "name",
"value": "status"
},
"binaryPropertyName": "github_data",
"additionalParameters": {}
},
"typeVersion": 1.1
},
{
"id": "d9c2a2ee-5698-4a60-8ab9-1ff133d71505",
"name": "Extract from existing File (github)",
"type": "n8n-nodes-base.extractFromFile",
"position": [
-1968,
-16
],
"parameters": {
"options": {},
"operation": "text",
"destinationKey": "github_data",
"binaryPropertyName": "github_data"
},
"typeVersion": 1
},
{
"id": "e310e8e7-ad13-4f9e-a4b6-12f45d33a62a",
"name": "If - Compare existing HTML file with generated HTML",
"type": "n8n-nodes-base.if",
"position": [
-1776,
-16
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "ffd5eaf3-0a36-43ac-8529-03b71cf9f1c6",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.github_data }}",
"rightValue": "={{ $('Extract from File - Generated HTML').item.json.data }}"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "0deafbe1-d715-45b0-9fe4-ea910a6d8f83",
"name": "Nota adhesiva3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-4880,
-496
],
"parameters": {
"width": 976,
"height": 2416,
"content": "# 🖥️ Automated Website Uptime Monitor with Email Alerts & GitHub Status Page Update \n\nThis n8n workflow continuously monitors your website’s availability, sends **email alerts** when the server goes down, and automatically updates a **status page (index.html)** in your GitHub repository to reflect the live status. \n\n---\n\n## 📌 Good to Know \n- The workflow checks your website every **2 minutes** (interval configurable). \n- If the website is **down (503, bad response, or error)** → it sends an email alert and updates the GitHub-hosted status page to show **Down**. \n- If the website is **up (200)** → it updates the GitHub-hosted status page to show **Up**. \n- The email notification includes an **HTML-formatted alert page**. \n- You can use GitHub Pages to **host the status page** publicly.\n\n### ℹ️ What is GitHub Pages? \n- GitHub Pages is a free hosting service provided by GitHub that lets you publish **static websites (HTML, CSS, JS)** directly from a GitHub repository. \n- You can use it to make your `index.html` status page publicly accessible with a URL like: \n\n\n### ⚡ How to Set Up GitHub Pages for Your Status Page \n1. Create a **new repository** on GitHub (recommended name: `status`). \n2. Add a blank `index.html` file (n8n workflow will later update this file). \n3. Go to your repository → **Settings** → **Pages**. \n4. Under **Source**, select the branch (`main` or `master`) and folder (`/root`). \n5. Save changes. \n6. Your status page will now be live at: `https://<USERNAME>.github.io/status`\n\n\n## ✅ Prerequisites \n- An **n8n instance** (self-hosted or cloud). \n- A **GitHub account & repository** (to host the status page). \n- A **Gmail account** (or any email service supported by n8n – example uses Gmail). \n- Access to the target **website URL** you want to monitor. \n\n---\n\n## ⚙️ How it Works \n1. **Schedule Trigger** → Runs every 2 minutes. \n2. **HTTP Request** → Pings your website URL. \n3. **Switch Node** → Evaluates the response status (200 OK vs error/503). \n4. **Code Node** → Generates a dynamic **HTML status page** (Up/Down).\n5. **GitHub Repo & File** → Github Repo Name Should be `https://github.com/<OWNER_NAME>/status` (recommended) & Must have(required) a blank file named as `index.html` before triggering this flow.\n5. **GitHub Node** → Updates/commits the `index.html` file in your repository. \n6. **Gmail Node** → Sends an email alert if the site is down. \n\n---\n\n## 🚀 How to Use \n1. Import the workflow JSON into your **n8n instance**. \n2. Configure credentials for: \n - **GitHub** (Personal Access Token with repo permissions). \n - **Gmail** (or your preferred email service). \n3. Replace the following: \n - `https://app.yourdomain.com/health` → with your own website URL. \n - `example@gmail.com` → with your email address (or distribution list). \n - GitHub repo details → with your repository where `index.html` will live. \n4. Deploy the workflow. \n5. (Optional) Enable **GitHub Pages** on your repo to serve `index.html` as a live status page. \n\n---\n\n## 🛠 Requirements \n- n8n v1.0+ \n- GitHub personal access token \n- Gmail API credentials (or SMTP/email service of your choice) \n\n---\n\n## 🎨 Customising this Workflow \n- **Interval** → Change schedule from 2 minutes to any desired frequency. \n- **Email Content** → Modify HTML alert template in the Gmail node. \n- **Status Page Styling** → Edit the HTML/CSS in the Code node to match your branding. \n- **Error Handling** → Extend Switch node for other status codes (e.g., 404, 500). \n- **Multiple Websites** → Duplicate HTTP Request + Switch nodes for multiple URLs. \n\n---\n\n## 👤 Who Can Use It? \n- **DevOps & SRE Engineers** → For automated uptime monitoring. \n- **Freelancers/Developers** → To monitor client websites. \n- **Startups & SMEs** → For a free, lightweight status page without paid tools. \n- **Educators/Students** → As a hands-on learning project with n8n. \n\n---\n\n## 🌟 Key Features \n- 🔄 Automated uptime checks (configurable interval). \n- 📧 Email notifications on downtime. \n- 📝 Dynamic HTML status page generation. \n- 🌍 GitHub Pages integration for public visibility. \n- ⚡ Lightweight & cost-effective (no paid monitoring tool needed). \n\n---\n\n## 🔗 Tools Integration \n- **n8n** – Orchestration & automation. \n- **GitHub** – Version control + hosting of status page. \n- **Gmail** – Email notifications. \n- **HTTP Request** – Website availability check. \n\n---\n\n## 📈 Example Use Cases \n- Personal website monitoring with public status page. \n- Monitoring SaaS apps & notifying support teams. \n- Internal company services uptime dashboard. \n "
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "052ffe26-4ea6-4e74-91db-0076dc880da6",
"connections": {
"HTTP Request": {
"main": [
[
{
"node": "ba9b1eb6-6fcd-4ca8-b308-2b0daad7c299",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"Template HTML Code": {
"main": [
[
{
"node": "ec136a3f-e79d-4480-8c19-893184458928",
"type": "main",
"index": 0
}
]
]
},
"ba9b1eb6-6fcd-4ca8-b308-2b0daad7c299": {
"main": [
[
{
"node": "Template HTML Code",
"type": "main",
"index": 0
},
{
"node": "7d86a237-36e6-4ce8-95cf-19ab8a58581d",
"type": "main",
"index": 0
}
],
[
{
"node": "Template HTML Code",
"type": "main",
"index": 0
}
]
]
},
"4423f742-0144-4ffb-b28b-a6d108e3b5ca": {
"main": [
[
{
"node": "d9c2a2ee-5698-4a60-8ab9-1ff133d71505",
"type": "main",
"index": 0
}
]
]
},
"ec136a3f-e79d-4480-8c19-893184458928": {
"main": [
[
{
"node": "4423f742-0144-4ffb-b28b-a6d108e3b5ca",
"type": "main",
"index": 0
}
]
]
},
"d9c2a2ee-5698-4a60-8ab9-1ff133d71505": {
"main": [
[
{
"node": "e310e8e7-ad13-4f9e-a4b6-12f45d33a62a",
"type": "main",
"index": 0
}
]
]
},
"e310e8e7-ad13-4f9e-a4b6-12f45d33a62a": {
"main": [
[
{
"node": "d4f178ad-6597-4944-aa80-7335f26be23d",
"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
Linearloop Team
@linearloop-n8nCompartir este flujo de trabajo