Set up uptime and certificate expiry checks
A website can fail quietly. A certificate expires, an app crashes, or the server stops answering, and nobody notices until a visitor complains. This guide shows you how to check your site with a small script, and how to watch the certificate expiry date so renewals never surprise you.
Before you begin
- A VPS running Ubuntu 24.04 LTS with a website served over HTTPS. This guide uses example.com as a placeholder.
- SSH access as a user with sudo rights, such as alex.
- curl and openssl. Both come preinstalled on a standard Ubuntu image.
Step 1: Check the site by hand
Before you automate anything, learn what a healthy response looks like. curl requests the address, -I asks for headers only, and -s hides the progress meter. The first line should show status 200, which means "OK".
curl -sI https://example.com/
HTTP/2 200
server: nginx
content-type: text/html
...
Step 2: Check the certificate expiry date by hand
This command connects to port 443, which is where HTTPS lives, and prints the certificate. The x509 step extracts the expiry date, shown as notAfter. The echo at the start closes the connection cleanly, and 2>/dev/null hides connection noise we do not need.
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -enddate
notAfter=Jan 20 12:00:00 2027 GMT
Step 3: Write a check script
Open a new file in nano. The script checks two things: whether the site returns HTTP 200 within 10 seconds, and whether the certificate has at least 14 days left. The first line, #!/bin/bash, tells Linux which program should run the file.
sudo nano /usr/local/bin/check-site.sh
Paste this content, then save with Ctrl+O, Enter, and exit with Ctrl+X:
#!/bin/bash
# Usage: check-site.sh example.com
DOMAIN="${1:?Usage: check-site.sh your-domain}"
# 1. Does the site answer with HTTP 200 within 10 seconds?
CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "https://${DOMAIN}/")
if [ "$CODE" != "200" ]; then
echo "WARNING: https://${DOMAIN}/ returned HTTP ${CODE}"
exit 1
fi
# 2. How many days until the certificate expires?
END=$(echo | openssl s_client -servername "$DOMAIN" -connect "${DOMAIN}:443" 2>/dev/null \
| openssl x509 -noout -enddate | cut -d= -f2)
DAYS=$(( ( $(date -d "$END" +%s) - $(date +%s) ) / 86400 ))
if [ "$DAYS" -lt 14 ]; then
echo "WARNING: certificate for ${DOMAIN} expires in ${DAYS} days"
exit 1
fi
echo "OK: ${DOMAIN} returned 200 and the certificate has ${DAYS} days left"
Make the script executable so you can run it directly:
sudo chmod +x /usr/local/bin/check-site.sh
Step 4: Run it once
Run the script with your domain as the argument. A successful run prints an OK line and exits with code 0. A failure prints a WARNING and exits with code 1, which is how automation tools tell "fine" from "needs attention".
/usr/local/bin/check-site.sh example.com
echo $?
OK: example.com returned 200 and the certificate has 81 days left
0
Step 5: Run the check every 10 minutes with a systemd timer
A systemd timer runs a service on a schedule and keeps its output in the system journal, so you can read the history later. First create the service that runs the script:
sudo nano /etc/systemd/system/site-check.service
[Unit]
Description=Check example.com uptime and certificate expiry
[Service]
Type=oneshot
ExecStart=/usr/local/bin/check-site.sh example.com
Next create the timer that starts the service:
sudo nano /etc/systemd/system/site-check.timer
[Unit]
Description=Run the site check every 10 minutes
[Timer]
OnBootSec=2min
OnUnitActiveSec=10min
[Install]
WantedBy=timers.target
Reload systemd so it notices the new files, then enable and start the timer. The --now flag starts it immediately as well as at every boot.
sudo systemctl daemon-reload
sudo systemctl enable --now site-check.timer
systemctl list-timers site-check.timer
To read the results later, ask the journal for the service's recent messages:
journalctl -u site-check.service -n 5
Oct 31 12:20:01 vps check-site.sh[1834]: OK: example.com returned 200 and the certificate has 81 days left
Troubleshooting
- The script prints
HTTP 000. curl could not connect at all. Check that the domain points at your server, that the firewall allows ports 80 and 443, and that your web server is running. - The script says
openssl: command not found. Install it withsudo apt update && sudo apt install -y openssl. - The days count is wrong or the message mentions an invalid date. The site is probably not serving a certificate on port 443. Run the step 2 command by hand to see the raw error.
- The timer never runs. Run
systemctl status site-check.timer. If it says the unit was not found, you skippeddaemon-reload.
Next steps
Once your checks run reliably, add an outside monitor so you hear about outages even when the whole server is down. Then read the troubleshooting guide for a site that is down, so you know which command to run first when an alert arrives.
Something not working? Chat or email our support team and we will help you get unstuck.
Contact support