- Knowledge
- technology
- OOP
- Tips
- Programming
- Tips
- Tutorial
- SEO
- Ranking
- Knowledge
- Special Day
- Seo
- Bug
- Data science
- Seo
- artificial intelligence
- Machine Learning
- Robotics
- happyNewYear2021
- newYearEve
- 2021
- Automation
- Smart Home
- Career
- Best Practices
- Git
- Logging
- Web Fundamentals
- DNS
- HTTPS
- Performance
- AI Tools
- ChatGPT
- Claude
- Gemini
- Laravel
- Eloquent
- MySQL
- HTTPS
- TLS
- Web Security
- Certificates
- Developer Life
- Debugging
- Docker
- DevOps
- Transactions
- Queues
- LLMs
- AI
- AI Coding
- Developer Tools
- React Native
- Expo
- Kate PMS
- Mobile Apps
- Laravel
- Authentication
- Sanctum
- Cookies
- API Design
- Payments
- Idempotency
- DeepSeek
- Open Source AI
- LLMs
- AI News
- Git
- Version Control
- AI Coding
- Prompting
- PHP
- Checklist
- MCP
- AI Agents
- OpenAI
- Architecture
- Microservices
- Modular Monolith
- Estimation
- Developer Life
- Project Planning
- Humour
- OAuth
- OpenID Connect
- Authentication
- Embeddings
- Vector Search
- RAG
- pgvector
- OpenAI
- GPT-4.1
- Codex CLI
- Events
- Testing
- Clean Code
- Maintainability
- Code Review
- Webhooks
- API
- Security
- Claude Code
- Workflow
- AI
- LLM
- Prompt Injection
- Mobile
- React
- Networking
- TCP
- UDP
- HTTP/3
- CLAUDE.md
- AWS
- Cloud Security
- Backups
- PHPUnit
- Software Engineering
- Leadership
- Communication
- RAG
- Embeddings
- AI Engineering
- IT Infrastructure
- Networking
- Access Control
- CI/CD
- GitHub Actions
- Gemini CLI
- Claude Code
- JavaScript
- Async/Await
- Node.js
- Promises
- Security
- Cryptography
- Passwords
- MySQL
- Database
- Vibe Coding
- Software Quality
- DNS
- Code Reading
- Onboarding
- Productivity
- Background Jobs
- Developer Humour
- Estimates
- Dev Life
- JWT
- o3-mini
- DeepSeek R1
- Rate Limiting
- Kate PMS
- E-Signing
- Audit Trail
- REST
- GraphQL
- API Design
- Laravel 12
- Upgrade Guide
- Open Source
- Self-Hosting
- Task Scheduling
- Cron
- Secrets
- CORS
- PHP
- PHP-FPM
- OPcache
- GitHub Copilot
- Software Architecture
- Engineering
- TypeScript
- JavaScript
- Type Safety
- AI Security
- React Native
- Product Design
- AI Agents
- Kiro
- Queues
- Redis
- RabbitMQ
- AWS SQS
- Nginx
- Apache
- GPT-5
- gpt-oss
- Clean Code
- Architecture
- Naming
- Documentation
- Career
- ADR
- Teamwork
- Supply Chain
- Kate HRM
- HR Software
- Permissions
- System Design
- Pagination
- SSH
- Linux
- Big O
- Databases
- Laravel Boost
- MCP
- Developer Skills
- Validation
- Databases
- Indexes
- Code Quality
- Deployment
- Developer Humour
- Feature Flags
- Code Review
- Pull Requests
- Docker
- Cursor
- Authorization
- RBAC
- Gemini
- Long Context
- PHP 8.4
- Caching
- Dependency Injection
- Web Performance
- Browser
- CSS
- Database
- Migrations
- ChatGPT
- AI for Developers
- Monitoring
- On-Call
- REST
- Backend
- SQL
- NoSQL
- Database Design
- Coding Agents
- Claude 4
- API Resources
- REST API
- Load Balancing
- Scaling
- AWS
- AI Tools
- Claude
- Sora 2
- CTE
- 2FA
- TOTP
- Programming Languages
- Prompts
- Developer Workflow
- API Gateway
- APIs
- Passport
- API Auth
- Learning
- Burnout
- Developer Growth
- Web Development
- SEO
- Kate Mall
- ChatGPT Atlas
- Agent Skills
- Middleware
- Laravel 12
- Collections
- Context Window
- Monitoring
- Commit Messages
- Self Review
- Growth
- Regex
- Programming Basics
- Text Processing
- Database Design
- Normalization
- Linux
- Server Security
- Linux Foundation
- Open Standards
- Legacy Code
- Documentation
- AI Workflow
- File Uploads
- Test Data
- Hashing
- Performance
- Caching
- Enums
- Scope Creep
- Estimation
- Codex
- Gemini CLI
- Timezones
- Carbon
- Bugs
- PHP 8.5
- Gemini 3
- GPT-5.1
- Data Integrity
- Event Loop
- Async
- Opus 4.5
- AI Models
- React
- Forms
- Frontend
- Backups
- AI Images
- DALL-E
- Midjourney
- Race Conditions
- Concurrency
- Legacy Code
- Refactoring
- Senior Engineer
- Scope
- LLM
- CDN
- Web
- Sub-Agents
- Soft Deletes
- Audit Log
- Concurrency
- AI Learning
- NestJS
- AI Evals
- Policies
- SPF DKIM DMARC
- Unicode
- UTF-8
- Knowledge Graph
- Value Objects
- Technical Debt
- Feature Flags
- Laravel Pennant
- Deployment
- Copilot
- Composer
- Dependencies
- Artisan
- Automation
- AWS S3
- Object Storage
- Cloud
- Small Language Models
- Ollama
- Production
- Sessions
- HTTP
- Mentoring
- SQL
- Virtual Machines
- Web Development
- HTTP/2
- QUIC
- Web Performance
- AI Integration
- LLM API
- SOLID
- OOP
- Hosting
- Serverless
- Merge Conflicts
- Temperature
- AI Development
- Reverse Proxy
- Nginx
- Infrastructure
- Verification
- Passkeys
- WebAuthn
- Teams
- Communication
- Stakeholders
- Monorepo
- CI/CD
- Versioning
- JSON Schema
- Livewire
- Inertia
- Meetings
- Distributed Systems
- Privacy
- Full-Stack
- T-Shaped Skills
- Money
- Notifications
- Web Security
- HTTP Headers
- CSP
- Function Calling
- Load Testing
- k6
- Data Extraction
- Debugging
- WebSockets
- SSE
- Real-Time
- Laravel Reverb
- Infrastructure as Code
- Terraform
- Side Projects
- Laravel Pint
- OpenAPI
- Swagger
- UX
- Multimodal
- Jest
- Pair Programming
- APIs
- Rate Limiting
- Resilience
- Dev Humour
- Design Tokens
- JWT
- API Keys
- Sessions
- PHPStan
- Rector
- Incidents
- Reporting
- Dashboards
- Zero Trust
- IAM
- Search
- Laravel Scout
- Junior Developers
- Mentoring
- Images
- WebP
- AVIF
- Bug Reports
- Let's Encrypt
- Design Docs
- Software Design
- Observers
- Replication
- Accountability
- Data Structures
- Reliability
- LLM Memory
- Error Handling
- Payments
- Payment Gateway
- Webhooks
- PCI DSS
- Observability
- OpenTelemetry
- Personal Brand
- Writing
- Conventions
- Dates
- Scheduling
- Disaster Recovery
- Compression
- Brotli
- Deadlines
- Developer Habits
- State Machines
- Tech Roles
- UUID
- ULID
- Horizon
- Planning
- Engineering Culture
- Ownership
- Soft Skills
- Socialite
- Cost Control
- Collations
- Unicode
- Octane
- PostgreSQL
How HTTPS Certificates Renew Themselves: Let's Encrypt and ACME Explained
About Post
Somewhere on your server, a small program wakes up twice a day, checks a date, and almost always goes back to sleep. You've probably never looked at it. You set it up once, years ago maybe, by copying a command from a tutorial.
When it works, nobody thinks about it. When it quietly stops working, you find out weeks later, when every visitor to your site gets a full-page browser warning and your phone starts ringing.
Let's open the box: how a free certificate gets issued and renewed without a human, what can break, and the one check you should add today.
Why the certificates are so short-lived
A Let's Encrypt certificate is valid for 90 days. Traditional certificates used to last a year or more, so 90 days can feel like a hassle. It's deliberate.
- Less damage from a leaked key. If a private key is stolen, a short-lived certificate stops being useful much sooner.
- It forces automation. Nobody renews something by hand four times a year for long. Short lifetimes make the automated path the only sensible one, and automated renewal is far more reliable than a calendar reminder.
The whole industry is moving in this direction: the CA/Browser Forum, which sets the rules for publicly trusted certificates, has voted to shrink the maximum certificate lifetime in stages over the next few years. Manual renewal is on its way out everywhere, not just with Let's Encrypt.
ACME: the conversation behind the certificate
The automation runs on a protocol called ACME (Automatic Certificate Management Environment), standardised as RFC 8555. A client on your server, most often certbot, talks to the certificate authority. Simplified, the conversation goes like this:
- "Hi, I'm account X." The client has an account key pair, created the first time you ran it. Every request is signed with it.
- "I'd like a certificate for example.com." The client places an order.
- "Prove you control example.com." The CA hands back one or more challenges.
- "Done, go check." The client completes a challenge and the CA verifies it from the outside.
- "Here's my CSR." The client generates a key for the certificate and sends a certificate signing request.
- "Here's your certificate." The client downloads it, along with the intermediate chain.
Notice what's missing: no human, no email, no payment, no document. Control of the domain is the only thing being proven, and it's proven fresh each time.
The challenges: how you prove you own the domain
| Challenge | How you prove control | Good for | Watch out for |
|---|---|---|---|
| HTTP-01 | Serve a token at http://your-domain/.well-known/acme-challenge/<token> | A normal web server with port 80 open | No wildcards; port 80 must be reachable |
| DNS-01 | Create a TXT record at _acme-challenge.your-domain | Wildcard certificates, servers not reachable from the internet | Needs API access to your DNS provider, and a token to protect |
| TLS-ALPN-01 | Answer a special TLS handshake on port 443 | Setups where only 443 is open | Less common; fewer clients and servers support it |
Most Laravel apps on a VPS use HTTP-01 through the web server plugin, which is why "certbot --nginx" feels like magic: it temporarily answers the challenge for you and then edits your server config to use the new certificate.
What renewal actually does
When you install certbot from a package or snap, it also installs a scheduled task: a systemd timer or a cron entry that runs certbot renew about twice a day. Most runs do nothing. A certificate is only renewed when it's getting close to expiry; the usual guidance is to renew with about a third of the lifetime left, so around 30 days for a 90-day certificate.
That gives you a generous buffer. If a renewal fails, the next run tries again, and there are weeks of retries before anything visible breaks. Which is precisely why failures go unnoticed.
Three commands worth knowing:
# Is the timer actually there and scheduled?
systemctl list-timers | grep certbot
# What do I have, and when does it expire?
sudo certbot certificates
# Rehearse a renewal against the staging server, without issuing anything
sudo certbot renew --dry-run
Why renewals fail
The first issuance worked, so why would a renewal fail months later? Because something around it changed:
- Port 80 got closed. Someone tightened the firewall or security group to "HTTPS only". HTTP-01 needs port 80 reachable, even if it only redirects to HTTPS.
- A rule blocks the challenge path. A new redirect, a maintenance mode page, basic auth on the whole site, or a framework route that swallows
/.well-known/. - DNS moved. The domain now points at a CDN or a new load balancer, so the challenge request never reaches the server running certbot.
- The DNS API token expired for DNS-01 setups, or was rotated without updating the config.
- The certificate renewed, but nobody reloaded the web server. The new file is on disk; Nginx is still serving the old one from memory. This is the sneakiest one.
For that last one, use a deploy hook, which only runs after a successful renewal:
sudo certbot renew --deploy-hook "systemctl reload nginx"
Or drop an executable script in /etc/letsencrypt/renewal-hooks/deploy/, so every future renewal picks it up automatically.
Monitor from the outside
Here's the uncomfortable part. Let's Encrypt used to send expiry reminder emails, and many people relied on them as a safety net. They stopped sending those in 2025. If your renewal breaks today, nobody is going to warn you unless you've set something up.
The check should look at what visitors actually see, not at files on disk, because "renewed but not reloaded" passes every on-server check:
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -enddate
# notAfter=...
Better still, let your uptime monitoring do it. Most uptime services can alert when a certificate is within a set number of days of expiry. Set the alert well inside the renewal window, so it only fires when automation has genuinely failed, and you have weeks to fix it calmly.
The rule: automation removes the work, not the responsibility. Automate the renewal, then monitor the expiry date from outside your server. One without the other is a time bomb with a long fuse.
A five-minute checklist
- Confirm the renewal timer or cron job exists on every server that has certificates.
- Run
certbot renew --dry-runafter any firewall, DNS or web server change. - Add a deploy hook that reloads your web server.
- Add an external certificate expiry check with an alert.
- Write down which method each domain uses (HTTP-01 or DNS-01) and where any DNS API token lives.
The Let's Encrypt challenge types page is a good, short read if you want the official details.
Have you ever been caught by an expired certificate? I'm curious which cause got you: the firewall, the DNS move, or the missing reload.

Be first to comment it...