Hex.pm Certificate expired Jul. 31 2025

I hope somebody is aware of it.

1 Like

I’m following this for updates so I don’t have to just keep refreshing :slight_smile:

1 Like

Wait, is someone manually updating hex.pm’s letsencrypt certificate based off of the email reminders that recently stopped? I was doing this with a client and they emailed me today about this very issue because I kept telling myself every three months “Oh right, I gotta set up a cron for this, ugh… I’ll do it this afternoon…” :sweat_smile:

1 Like

Thanks, did not know this was already a known issue. 4 hours already…

thats Claude telling me it’s quite possible to have those certificates renewed like 30 days before they expire… that way there is plenty of time to intervene manually in case of some automated renewal issues.

I’ve been on the other side of having those kinds of things ruining my day, so please don’t take this as an smart-ass reply. We are all human after all.

# Let's Encrypt Certificate Early Renewal Guide

## Overview

Yes, you can absolutely renew a Let's Encrypt certificate well before it expires! This is not only possible but considered best practice for maintaining secure SSL/TLS certificates.

## Key Facts

- Let's Encrypt certificates are valid for **90 days**
- **Recommended renewal time**: 30 days or less remaining
- Early renewal provides a safety buffer in case of renewal issues
- Automatic renewal systems typically trigger at the 30-day mark

## Manual Renewal Commands

### Force Immediate Renewal
```bash
certbot renew --force-renewal

Check Certificate Status

certbot certificates

Test Renewal Process (Dry Run)

certbot renew --dry-run

Automatic Renewal Setup

Cron Job Example

Most systems benefit from automated renewal checks. Here’s a typical cron entry that runs twice daily:

# Add to crontab (crontab -e)
0 12 * * * /usr/bin/certbot renew --quiet

Systemd Timer

Many modern Linux distributions use systemd timers instead of cron:

# Check if certbot timer is active
systemctl status certbot.timer

# Enable automatic renewal
systemctl enable certbot.timer
systemctl start certbot.timer

Best Practices

  1. Set up automatic renewal - Don’t rely on manual renewals
  2. Monitor renewal logs - Check that automatic renewals are working
  3. Use dry-run testing - Verify your renewal process works before you need it
  4. Renew at 30 days remaining - This is the sweet spot for timing
  5. Have monitoring in place - Get alerts if renewals fail

Alternative ACME Clients

If you’re not using Certbot, other popular ACME clients also support early renewal:

  • acme.sh - Lightweight shell script alternative
  • Traefik - Reverse proxy with built-in ACME support
  • Caddy - Web server with automatic HTTPS
  • cert-manager - Kubernetes certificate management

Rate Limits

Let’s Encrypt has rate limits, but they’re generous for normal use:

  • 50 certificates per registered domain per week
  • 5 duplicate certificates per week (same set of hostnames)

The --force-renewal flag will create a duplicate certificate, so use it sparingly.

Troubleshooting

If renewal fails, common issues include:

  • Webserver configuration blocking the challenge
  • Firewall blocking port 80 or 443
  • DNS changes affecting domain validation
  • File permissions on certificate directories

Always test with --dry-run first to catch issues without hitting rate limits.

1 Like

That was the sentiment of my comment. I know I can set up a cron, I know when it can be done (without asking AI), but I just didn’t… partially because in a weird way I enjoy doing it manually (I only have one freelance client as I work work a full time job, if I had more I would have nipped this in the bud long ago). So I was delighting at the idea that maybe (and it probably isn’t even the case) that an owner of hex is doing the same :slight_smile:

3 Likes

It’s working now!
Thanks Elixir team!

1 Like

Enjoying the manual renewal… Heh… That’s one special joy, for sure. ))))

It’s all about that shh’ing into prod—what is life without it…? :sweat_smile: :upside_down_face:

I… guess… Keeps one sharp :slight_smile:

Hey, you’re the one who said we’re all human… there is a huge amount of irrationality that comes with that, even among the most rational of us :slight_smile:


Also, I’m still not getting access to hex.pm here (I’m in Canada).

1 Like

True… I could access hex docs (which was also not working before), so I prematurely assumed the issue was resolved. I guess the hex docs have different certificates than hex.pm… So, hex.pm still on-going.

It’s also affecting commands like

$ mix hex.info image

yep, it’s a pain. I’ll go to sleep now (EU timezone), hopefully this will be resolved soon. And yes, the EU-located Elixir team members will be up in the morning and this should take couple hours to be fix then. My guess is in the next 3-6 hours.

Good night!

1 Like

Sometimes scripts fail too - on most of the servers I manage we use HAProxy so whenever letsencrypt renews a cert it has to be copied over to HAProxy and then restart it, on occasion this has failed, and of course it doesn’t get run again as letsencrypt thinks you have a valid cert as it only checks its own files.

A cool Elixir app/script idea if anyone wants it: make a program that checks your favourite sites every day and then get it to alert you if the cert will expire in less than a week - if you get any alerts you can let the administrator know! :icon_biggrin:

1 Like

Still not working here, and the issue is still open :thinking:

You inspired me to cobble something together (it’s in Bash, sorry).

It’s a script that checks the certificate expiration date for a bunch of domains, then uses notify-send to send a notification for each domain that has a certificate that expires in 3 days or less. Then I made it run in a cronjob once per hour.

/home/user/scripts/network/cert-checker.sh

#!/bin/bash

# List of domains to check
DOMAINS="elixirforum.com erlangforums.com hex.pm hexdocs.pm"

# # Log file (optional, for debugging)
# LOG_FILE="/tmp/cert_check.log"

for domain in $DOMAINS; do
  exp_date=$(echo | openssl s_client -connect $domain:443 -servername $domain 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
  
  # Check if we got a valid date
  if [ -n "$exp_date" ]; then
    exp_time=$(date -d "$exp_date" +%s) && 
    current_time=$(date +%s) && 
    diff_seconds=$((exp_time - current_time)) && 
    diff_days=$((diff_seconds / 86400)) && 
    diff_hours=$(((diff_seconds % 86400) / 3600)) && 
    if [ $diff_days -le 3 ] && [ $diff_days -ge 0 ]; then 
      notify-send "Certificate Alert" "$domain expires in $diff_days days and $diff_hours hours"
      # # Optional: log to file
      # echo "$(date): $domain expires in $diff_days days and $diff_hours hours" >> $LOG_FILE
    fi
  fi
done

Make it executable with chmod +x /path/to/script, then add it to a cronjob to check the certs once per hour:

0 * * * * DISPLAY=:0 /home/user/scripts/network/cert-checker.sh

Seems to be working so far.

I put this together with a lot of help from the new Qwen3-Coder model.

4 Likes

That’s what I get for recommending temporary measures like disabling strict HTTPS – 3x “:-1:t2:” reactions in the GitHub issue. But hey, at least I got 8x “:heart:” as well.

Our rolling production deployment failed and that’s how I got aware of it. We’re still keeping an eye and it’s still not fixed.

1 Like

Hey everyone, certs have been renewed.

11 Likes

Can confirm, thanks.