{
  "name": "Uptime and SSL expiry check (Agent Routines)",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "*/15 * * * *"
            }
          ]
        }
      },
      "id": "3d30d8bb-a6d9-59bd-92f2-3cc659bde35f",
      "name": "Every 15 minutes",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "return ['https://example.com','https://example.org'].map(url => ({ json: { url } })); // <EDIT YOUR URLS>"
      },
      "id": "f3750667-5605-5a23-a12c-c2de03dc0272",
      "name": "URL list",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        490,
        300
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "={{ $json.url }}",
        "options": {
          "response": {
            "response": {
              "fullResponse": true,
              "neverError": true
            }
          },
          "timeout": 10000
        }
      },
      "id": "91498fa8-6b8a-5c4e-a547-21c4e64b07af",
      "name": "Check URL",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        730,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "const out=[];for (const [i,it] of $input.all().entries()){const url=$('URL list').all()[i].json.url;const s=it.json.statusCode;if(s!==200) out.push({json:{url,status:s}});}\nreturn out;"
      },
      "id": "01e3b04d-e501-5336-bc39-bb13d155cb3e",
      "name": "Flag failures",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        970,
        300
      ]
    },
    {
      "parameters": {
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "name",
          "value": "#alerts"
        },
        "text": "=DOWN: {{ $json.url }} returned {{ $json.status }} at {{ $now.toISO() }}",
        "otherOptions": {}
      },
      "id": "875fff77-9669-55b0-a9bd-b3591980f0c6",
      "name": "Downtime alert",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [
        1210,
        300
      ],
      "credentials": {
        "slackApi": {
          "id": "REPLACE_ME",
          "name": "Slack account"
        }
      }
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 9 * * *"
            }
          ]
        }
      },
      "id": "6802cd0e-c7bd-54bb-a297-cdb3b9ae87b0",
      "name": "Daily SSL check",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        250,
        460
      ]
    },
    {
      "parameters": {
        "jsCode": "const tls=require('tls');const hosts=['example.com']; // <EDIT YOUR DOMAINS>\nconst check=h=>new Promise(r=>{const s=tls.connect(443,h,{servername:h},()=>{const c=s.getPeerCertificate();s.end();r({host:h,days:Math.round((new Date(c.valid_to)-Date.now())/864e5)})});s.on('error',e=>r({host:h,days:-1,error:e.message}))});\nconst res=await Promise.all(hosts.map(check));return res.filter(x=>x.days<14).map(json=>({json}));"
      },
      "id": "c019e6d1-ff25-5554-9241-222ad3a0e4d1",
      "name": "Certificate expiry",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        490,
        620
      ]
    },
    {
      "parameters": {
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "name",
          "value": "#alerts"
        },
        "text": "=SSL for {{ $json.host }} expires in {{ $json.days }} days",
        "otherOptions": {}
      },
      "id": "d00109d3-ccb7-5c94-8f7c-a6b0e3c2ff81",
      "name": "SSL alert",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [
        730,
        620
      ],
      "credentials": {
        "slackApi": {
          "id": "REPLACE_ME",
          "name": "Slack account"
        }
      }
    }
  ],
  "connections": {
    "Every 15 minutes": {
      "main": [
        [
          {
            "node": "URL list",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "URL list": {
      "main": [
        [
          {
            "node": "Check URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check URL": {
      "main": [
        [
          {
            "node": "Flag failures",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Flag failures": {
      "main": [
        [
          {
            "node": "Downtime alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily SSL check": {
      "main": [
        [
          {
            "node": "Certificate expiry",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Certificate expiry": {
      "main": [
        [
          {
            "node": "SSL alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "meta": {
    "templateCredsSetupCompleted": false,
    "source": "https://agentroutines.si/r/uptime-and-ssl-expiry-check/"
  },
  "tags": []
}