{"id":40885729,"url":"https://github.com/pavelkim/check_certificates","last_synced_at":"2026-01-22T01:37:01.049Z","repository":{"id":44039036,"uuid":"280696870","full_name":"pavelkim/check_certificates","owner":"pavelkim","description":"Monitor your HTTPS SSL Certificate's expiration.","archived":false,"fork":false,"pushed_at":"2024-08-25T02:15:12.000Z","size":100,"stargazers_count":5,"open_issues_count":6,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-08-25T18:10:01.979Z","etag":null,"topics":["bash","certificate","expiration","https","monitoring","ssl"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pavelkim.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-18T16:38:08.000Z","updated_at":"2024-08-25T02:14:15.000Z","dependencies_parsed_at":"2023-01-22T04:01:51.402Z","dependency_job_id":null,"html_url":"https://github.com/pavelkim/check_certificates","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/pavelkim/check_certificates","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavelkim%2Fcheck_certificates","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavelkim%2Fcheck_certificates/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavelkim%2Fcheck_certificates/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavelkim%2Fcheck_certificates/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pavelkim","download_url":"https://codeload.github.com/pavelkim/check_certificates/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pavelkim%2Fcheck_certificates/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28649546,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"ssl_error","status_checked_at":"2026-01-22T01:17:35.564Z","response_time":86,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bash","certificate","expiration","https","monitoring","ssl"],"created_at":"2026-01-22T01:37:00.925Z","updated_at":"2026-01-22T01:37:01.024Z","avatar_url":"https://github.com/pavelkim.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# check_certificates\n\nUse this script to automate HTTPS SSL Certificate monitoring. It curl's remote server on 443 port and then checks remote SSL Certificate expiration date. You can use it with Zabbix, Nagios/Icinga or other.\n\n# Releases\n\nLatest release: [Download](https://github.com/pavelkim/check_certificates/releases/latest/download/check_certificates.sh)\n\nDocker Hub: [Visit](https://hub.docker.com/repository/docker/pavelkim/check_certificates/general)\n\nGitHub Registry: [Visit](https://github.com/pavelkim/check_certificates/pkgs/container/check_certificates%2Fcheck_certificates)\n\n# Usage\n\nThe script takes on input a file with a list of hostnames:\n```bash\nUsage: check_certificates.sh [-h] [-v] [-s] [-l] [-n] [-A n] [-G] -i input_filename -d domain_name -b backend_name\n\n   -b, --backend-name       Domain list backend name (pastebin, gcs, etc.)\n   -i, --input-filename     Path to the list of domains to check\n   -d, --domain             Domain name to check\n   -s, --sensor-mode        Exit with non-zero if there was something to print out\n   -l, --only-alerting      Show only alerting domains (expiring soon and erroneous)\n   -n, --only-names         Show only domain names instead of the full table\n   -A, --alert-limit        Set threshold of upcoming expiration alert to n days\n   -G, --generate-metrics   Generates a Prometheus metrics file to be served by nginx\n   -v, --verbose            Enable debug output\n   -h, --help               Show help\n```\n\n# Docker container\n\nYou can run a container either in daemon mode, or single start.\n\nAn example environment is provided under the `./docker/` directory. Take a look into `docker-compose.yml`. Manual setup is easy too, though.\n\n## Create directories\n\n```bash\nmkdir -pv \"/opt/check_certificates/etc/check_certificates\"\nmkdir -pv \"/opt/check_certificates/htdocs\"\n```\n\n## Create configuration files\n\n```bash\ncat \u003c\u003c EOF \u003e /opt/check_certificates/etc/check_certificates/.config\nPROMETHEUS_EXPORT_FILENAME=\"/htdocs/metrics\"\n\nEOF\n```\n\n```bash\ncat \u003c\u003c EOF \u003e /opt/check_certificates/etc/check_certificates/domains.txt\nexample.com\nexample.org\ngoogle.com\n\nEOF\n```\n\n## Start a docker container\n\n```bash\ndocker run \\\n  --name check_certificates-daemon \\\n  --detach \\\n  --rm \\\n  -ti \\\n  -v \"/opt/check_certificates/etc/check_certificates:/etc/check_certificates\" \\\n  -v \"${PWD}/docker/usr/share/nginx/htdocs:/htdocs\" \\\n  -e CHECK_INTERVAL=$(( 60 * 60 * 2 )) \\\n  ghcr.io/pavelkim/check_certificates/check_certificates:1.9.1 \\\n  -i /etc/check_certificates/domains.txt \\\n  -G\n```\n\nEnvironment variable `CHECK_INTERVAL` sets the sleep interval between the checks. Currently it doesn't work like a schedule (like cron would). It just waits for N seconds between checks. So, if each your check takes ~7min, the \"schedule\" will shift for that time.\n\nThis will result with a recurrent checks every `$(( 60 * 60 * 2 ))` seconds (2 hours).\n\nPrometheus metrics will appear in a static file: `/opt/check_certificates/htdocs/metrics`. If you want them to be served by nginx or something like that, just make sure `metrics` file is reachable by nginx container.\n\n# Supported domain list backends\n\nDomain list backends allow you to manage configuration in a centralised manner.\n\n## PasteBin source\n\nYou can use a PasteBin paste as a source of domain names to be checked. We encorage you to register on PasteBin and create all your pastes related to `check_certificates` as Private or at least as Unlisted.\n\n1. Create a paste with a valid structure ([example](https://pastebin.com/FJFvdiPg))\n1. Obtain devkey and userkey ([documentation](https://pastebin.com/doc_api#7))\n1. Fill out variables in `.config` file\n\n### Paste structure\n\n```json\n{ \n  \"check_ssl\": [ \n    \"example.com\",\n    \"google.com\",\n    \"mail.com\",\n    \"imaginary-domain-9000.com\"\n  ]\n}\n```\n\n### .config file variables\n\n```bash\nPASTEBIN_USERKEY=youruserkey\nPASTEBIN_DEVKEY=yourdevkey\nPASTEBIN_PASTEID=pasteid\n```\n\n# Input file format\n\nExample of an input file contents:\n```\nexample.com\ngoogle.com\nmail.com\nimaginary-domain-9000.com\n```\n\n# Output data format\n\nOutput fields: \n```\nHostname    Valid Not Before    Valid Not After    Expires in N Days    Outcome\n```\n\nFull output (default) example:\n```\nimaginary-domain-9000.com  error      error     error      error     error  error\ngoogle.com                 2020-06-30 20:43:12  2020-09-22 20:43:12  66     ok\nexample.com                2018-11-28 00:00:00  2020-12-02 12:00:00  136    ok\nmail.com                   2018-01-15 00:00:00  2021-01-14 12:00:00  179    ok\n```\n\nDomain names only output (with parameters `-n -l -A 90`) example:\n```\nimaginary-domain-9000.com\ngoogle.com\n```\n\n# Prometheus metrics\n\nThe script can generate a static file with Prometheus metrics that is to be served by an external web server (eg. nginx or httpd).\n\nUse `-G` or `--generate-metrics` parameters to enable this feature.\n\n## .config file variables\n\n```bash\nPROMETHEUS_EXPORT_FILENAME=\"/path/to/htdocs/metrics\"\n```\n\n## Metrics example\n\n```prometheus\n# HELP check_certificates_expiration Days until HTTPs SSL certificate expires\n# TYPE check_certificates_expiration gauge\ncheck_certificates_expiration{domain=\"example.com\",outcome=\"ok\"} 20\ncheck_certificates_expiration{domain=\"example.de\",outcome=\"ok\"} 193\ncheck_certificates_expiration{domain=\"imaginary-domain-9000.com\",outcome=\"error\"} 0\n```\n\n## nginx configuration example\n\nNote: if you're running your nginx in a container, make sure your metrics file is accessable for nginx within the container (use volumes or something).\n\n```nginx\nserver {\n\n    listen 127.0.0.1:80;\n    listen [::1]:80;\n\n    listen 127.0.0.1:443 ssl;\n    listen [::1]:443 ssl;\n\n    ssl_certificate /etc/pki/tls/certs/localhost.crt;\n    ssl_certificate_key /etc/pki/tls/private/localhost.key;\n\n    server_name localhost;\n\n    access_log  /var/log/nginx/localhost-access.log  main;\n    error_log  /var/log/nginx/localhost-error.log;\n\n    location /check_certificates/metrics {\n        alias /opt/check_certificates/metrics;\n        allow 127.0.0.1/32;\n        deny  all;\n    }\n\n}\n```\n\n## prometheus.yml example\n\n\n```yaml\nglobal:\n  scrape_interval:     30s\n\nscrape_configs:\n\n  - job_name: 'check_certificates'\n    scrape_interval: 1h\n    scheme: https\n    metrics_path: \"check_certificates/metrics\"\n    params:\n      format: ['prometheus']\n    static_configs:\n      - targets: ['localhost']\n\n```\n\n## Grafana dashboard\n\nDashboard can be imported by id `15298`.\n\nMore informatin: https://grafana.com/grafana/dashboards/15298\n\n![Grafana dashboard screenshot](https://grafana.com/api/dashboards/15298/images/11337/image)\n\n# Application examples\n\n## Monitoring in Cron\n\n_NOTE_: Take a look into the Docker application examples with recurrent checks support built-in.\n\nThe following example of a crontab will provide you with email notfications in 14 days prior to SSL certificate expiration (or in case of other errors). Before that you'll receive no emails. Keep in mind that you'll need to have your Cron and MTA configured properly.\n\n/etc/cron.d/check_certificates:\n```java\nHOME=/opt/check_certificates\nMAILTO=\"john.doe@example.com\"\n\n30 11 * * * nobody bash ./check_certificates.sh -l -A 14 -i corp_domains.txt\n35 11 * * * nobody bash ./check_certificates.sh -l -A 14 -d \"example.com\"\n```\n\n## Sensor script for Zabbix/Nagios/Icinga etc.\n\nYou could use `--sensor-mode` along with other parameters to make the script exit with non-zero code if your remote host has an expiring certificate. \n\nFor Zabbix you can create a simple check to monitor your remote SSL certificate. For Nagios/Icinga you can configure a separate service check.\n\n```bash\n./check_certificates.sh \\\n  --sensor-mode \\\n  --only-names \\\n  --only-alerting \\\n  --alert-limit 14 \\\n  --domain example.com\n```\n\nThe script executed as displayed above will return 0 in case if `example.com` has SSL certificate valid for 15 or more days. In case of error (DNS, firewall, etc.) or if certificate will expire in less then 14 days, the script will return 1.\n\n# Supported platforms\n\nCurrently tested on the following platforms:\n1. CentOS 7, bash 4.2.46, openssl 1.0.2k\n2. CentOS 8, bash 4.4.19, openssl 1.1.1c\n3. Mac OS 10.13.6, bash 3.2.57, openssl 1.1.1d\n4. Mac OS 12.5, bash 5.1.16, OpenSSL 3.0.7\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpavelkim%2Fcheck_certificates","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpavelkim%2Fcheck_certificates","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpavelkim%2Fcheck_certificates/lists"}