NewHalo Edge 3 is here: HTTP/3 everywhere and 42 edge locations.Learn more
Docs / Backups and monitoring

Set up uptime and certificate expiry checks

Backups and monitoring6 min readUbuntu 24.04 LTS

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
Tip: A check that runs on the server cannot report that the server itself is offline. For that, use an outside monitor. LightServe Beacon uptime monitoring checks your site from outside your VPS, so it still works when the machine is unreachable.

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 with sudo 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 skipped daemon-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