Surveillance automatisée du temps de fonctionnement du site avec alertes par e-mail et mise à jour de la page de statut GitHub
Ceci est unDevOpsworkflow d'automatisation du domainecontenant 19 nœuds.Utilise principalement des nœuds comme If, Code, Gmail, Github, Switch. Surveillance automatisée du temps de fonctionnement des sites web, alertes par e-mail et mise à jour des pages de statuts GitHub
- •Compte Google et informations d'identification Gmail API
- •Personal Access Token GitHub
- •Peut nécessiter les informations d'identification d'authentification de l'API cible
Nœuds utilisés (19)
Catégorie
{
"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": "Déclencheur Planifié",
"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": "HTTP Request",
"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": "Note Adhésive",
"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": "Note Adhésive1",
"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": "Note Adhésive4",
"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": "Note Adhésive2",
"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": "Note Adhésive5",
"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": "Note Adhésive6",
"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": "Note Adhésive7",
"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": "Note Adhésive8",
"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": "Mettre à jour le fichier Index.html",
"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": "Envoyer un email de notification",
"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 - code de statut",
"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": "Extraire du Fichier - HTML Généré",
"type": "n8n-nodes-base.extractFromFile",
"position": [
-2528,
-16
],
"parameters": {
"options": {},
"operation": "text"
},
"typeVersion": 1
},
{
"id": "3e4c16f9-25f7-4944-958a-3f5c2a8651b9",
"name": "Modèle de Code HTML",
"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": "Obtenir le fichier index.html existant",
"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": "Extraire du Fichier existant (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 - Comparer le fichier HTML existant avec le HTML généré",
"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": "Note Adhésive3",
"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": {
"09c86eff-846d-43d1-a93f-f398f2223d67": {
"main": [
[
{
"node": "ba9b1eb6-6fcd-4ca8-b308-2b0daad7c299",
"type": "main",
"index": 0
}
]
]
},
"24b40a8b-20b2-4ead-87a4-0be04641323a": {
"main": [
[
{
"node": "09c86eff-846d-43d1-a93f-f398f2223d67",
"type": "main",
"index": 0
}
]
]
},
"3e4c16f9-25f7-4944-958a-3f5c2a8651b9": {
"main": [
[
{
"node": "ec136a3f-e79d-4480-8c19-893184458928",
"type": "main",
"index": 0
}
]
]
},
"ba9b1eb6-6fcd-4ca8-b308-2b0daad7c299": {
"main": [
[
{
"node": "3e4c16f9-25f7-4944-958a-3f5c2a8651b9",
"type": "main",
"index": 0
},
{
"node": "7d86a237-36e6-4ce8-95cf-19ab8a58581d",
"type": "main",
"index": 0
}
],
[
{
"node": "3e4c16f9-25f7-4944-958a-3f5c2a8651b9",
"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
}
]
]
}
}
}Comment utiliser ce workflow ?
Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.
Dans quelles scénarios ce workflow est-il adapté ?
Avancé - DevOps
Est-ce payant ?
Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.
Workflows recommandés
Linearloop Team
@linearloop-n8nPartager ce workflow