This project aims to provide a simple tool to monitor certificate validity. It is entirely built using GO.
Additionally, the app can be configured to run a job at a given schedule. The job will check the configured websites and send a message to a Webhook with a summary of the websites and their certificate validity.
Teams message:
Slack message:
Note: replace docker with podman if needed.
The easiest way to get started is to run the Docker image published to Docker Hub. Replace the SITE_1 parameter value with a website to monitor. To add other websites, just add parameters SITE_n where n is an integer.
docker run -it -p 8000:8000 \
--env ENV=DEV \
--env SITE_1=https://expired.badssl.com/ \
jlucaspains/sharp-cert-managergo install github.com/jlucaspains/sharp-cert-manager/cmd/sharp-cert-manager@latest
sharp-cert-manager check --url https://expired.badssl.com/- Go 1.24+
- Tailwindcss CLI
git clone https://github.com/jlucaspains/sharp-cert-manager.gitcd sharp-cert-manager
go mod downloadGenerate CSS using Tailwindcss CLI:
tailwindcss.exe -i ./frontend/styles.css -o ./public/styles.css --minifyCreate a dev .env file:
echo "ENV=local\nSITE_1=https://expired.badssl.com/" > .envgo run .\cmd\sharp-cert-manager\ check --url https://expired.badssl.com/Create an ACI resource via Azure CLI. The following parameters may be adjusted
--resource-group: resource group to be used--name: name of the ACI resource--dns-name-label: DNS to expose the ACI under--environment-variablesSITE_1..SITE_N: monitored websites.
az container create \
--resource-group rg-sharpcertmanager-001 \
--name aci-sharpcertmanager-001 \
--image jlucaspains/sharp-cert-manager \
--dns-name-label sharp-cert-manager \
--ports 8000 \
--environment-variables ENV=DEV SITE_1=https://expired.badssl.com/While more expensive, an ACA is a better option for production environments as it provides a more robust and scalable environment.
First, create an ACA environment using Azure CLI:
az containerapp env create \
--name ace-sharpcertmanager-001 \
--resource-group rg-experiments-soutchcentralus-001Now, create the actual ACA. The following parameters may be adjusted:
-g: resource group to be used-n: name of the app--env-varsSITE_1..SITE_N: monitored websites.
az containerapp create \
-n aca-sharpcertmanager-001 \
-g rg-experiments-soutchcentralus-001 \
--image jlucaspains/sharp-cert-manager \
--environment ace-sharpcertmanager-001 \
--ingress external --target-port 8000 \
--env-vars ENV=DEV SITE_1=https://expired.badssl.com/ \
--query properties.configuration.ingress.fqdnThe app can be configured to run a job at a given schedule. The job will check the configured websites and send a message to a Webhook with a summary of the websites and their certificate validity. Currently, Teams and Slack are supported.
Adjust the CHECK_CERT_JOB_SCHEDULE cron to run at the desired schedule.
The WEBHOOK_URL is the URL of the Teams/Slack Webhook to send the message to. Generate a webhook URL for Teams following this guide and for Slack following this guide.
docker run -it -p 8000:8000 `
--env ENV=DEV `
--env SITE_1=https://expired.badssl.com/ `
--env CHECK_CERT_JOB_SCHEDULE=* * * * * `
--env WEBHOOK_URL=ReplaceWithWebhookUrl `
--env WEBHOOK_TYPE=teams `
jlucaspains/sharp-cert-manager| Environment variable | Description | Default value |
|---|---|---|
| ENV | Environment name. Used to configure the app to run in different environments. | |
| SITE_1..SITE_N | Websites to monitor. | |
| AZUREKEYVAULT_1..AZUREKEYVAULT_N | Azure key vault certificates URLs to monitor. | |
| CHECK_CERT_JOB_SCHEDULE | Cron schedule to run the job that checks the certificates. | |
| WEBHOOK_URL | Webhook URL to send the message to. | |
| MESSAGE_URL | URL to be used message action | |
| MESSAGE_TITLE | Message title | Sharp Cert Manager Summary |
| MESSAGE_BODY | Message body body | The following certificates were checked on %s |
| WEB_HOST_PORT | Host and port the web server will listen on | :8000 |
| WEBHOOK_TYPE | Defines whether teams or slack webhooks are used | teams |
| TLS_CERT_FILE | Certificate used for TLS hosting | |
| TLS_CERT_KEY_FILE | Certificate key used for TLS hosting | |
| CERT_WARNING_VALIDITY_DAYS | Defines how many days from today a cert need to have to prevent a warning | 30 |
| CHECK_CERT_JOB_NOTIFICATION_LEVEL | Defines minimum notification level for jobs. Values are Info, Warning, or Error | Warning |
| HEADLESS | If set to "true", the web server does not start. |
This app is intended to run in private environments or at a minimum be behind a secure gateway with proper TLS and authentication to ensure it is not improperly used.
The app will allow unsecured requests to the configured websites. It will perform a get and discard any data returned. All information used is derived from the connection and certificate negotiated between the http client and the web server being monitored.
Below features are currentl being evaluated and/or built. If you have a suggestion, please create an issue.
- Display list of monitored certificates
- Display certificate details
- Monitor certificate in background
- Teams WebHook integration
- Slack WebHook integration
- Azure Key Vault integration
The HEADLESS environment variable is used to determine if the web server should start. If HEADLESS is set to "true", the web server does not start. This can be useful for running the job task only once and exiting with a success code.
To run the job task only once and exit with a success code, set HEADLESS to "true" and CHECK_CERT_JOB_SCHEDULE to an empty value.
Example: Running as a container app job using az cli
az containerapp job create `
--name sharp-cert-manager `
--resource-group <resource-group> `
--image jlucaspains/sharp-cert-manager `
--trigger-type "Schedule" `
--replica-timeout 1800 `
--cpu "0.25" --memory "0.5Gi" `
--cron-expression "0 8 * * 1" `
--replica-retry-limit 1 `
--parallelism 1 `
--replica-completion-count 1 `
--env-vars ENV=DEV `
SITE_1=https://blog.lpains.net/ `
CERT_WARNING_VALIDITY_DAYS=90 `
HEADLESS=true `
WEBHOOK_TYPE=teams `
WEBHOOK_URL=<webhook-url> `
MESSAGE_MENTIONS=<user@domain.com>
CHECK_CERT_JOB_NOTIFICATION_LEVEL=Info

