SSL Certificate Renewal Prompt
Context
Use this prompt when renewing or setting up SSL certificates for Pacing Agency services. Most of our services use:
- Cloudflare proxy - Automatic SSL (most client sites)
- Let's Encrypt - Free automated certificates (self-hosted services)
- Manual certificates - Rare, for special requirements
This prompt focuses on Let's Encrypt certificates for self-hosted services on Hetzner servers.
This prompt will help you:
- Set up or renew Let's Encrypt certificates
- Configure automatic renewal
- Verify SSL is working correctly
- Troubleshoot certificate issues
Prerequisites
- Server access - SSH access to Hetzner server
- Domain configured - DNS pointing to server (A record)
- Port 80/443 open - Firewall allows HTTP/HTTPS
- Certbot installed - Let's Encrypt client tool
- Web server running - Nginx, Caddy, or similar
See Hetzner Tool Documentation for server details and Cloudflare Documentation for DNS.
Prompt Template
I need to set up or renew an SSL certificate for a self-hosted service on Pacing Agency infrastructure:
**Domain Information:**
- Domain/subdomain: [DOMAIN]
- Server: [SERVER_NAME] (from Hetzner documentation)
- Server IP: [SERVER_IP]
- Web server: [WEB_SERVER] (Nginx/Caddy/Apache)
**Current Status:**
- Certificate status: [STATUS] (None/Expired/Expiring soon/Valid)
- Days until expiry: [DAYS] (if applicable)
- Certificate issuer: [ISSUER] (Let's Encrypt/Other)
**Service Configuration:**
- Service type: [SERVICE_TYPE] (n8n/TwentyCRM/Notifuse/Remark42)
- Service port: [PORT]
- Reverse proxy: [PROXY_SETUP] (Yes/No)
**Requirements:**
- Certificate type: Let's Encrypt (automatic)
- Renewal method: [RENEWAL_METHOD] (Certbot standalone/Webroot/Nginx plugin)
- Automatic renewal: Yes (via cron)
- Email for expiry notices: [EMAIL]
Please provide:
1. **Certificate setup/renewal commands**:
- Certbot installation (if needed)
- Certificate request command
- Verification steps
2. **Web server configuration**:
- Nginx/Caddy SSL configuration
- Certificate paths
- SSL best practices
- HTTPS redirect setup
3. **Automatic renewal setup**:
- Cron job configuration
- Renewal test command
- Failure notification
4. **Verification checklist**:
- SSL certificate validation
- Browser test
- SSL Labs test
- Expiry monitoring
5. **Troubleshooting guide**:
- Common certificate issues
- Renewal failures
- Port conflicts
- DNS issues
6. **Documentation template** for adding to service tool doc
Include:
- Commands with explanations
- Error handling
- Security best practices
- Testing procedures
Format with clear sections and code blocks.
Variables to Customize
| Variable | Description | Example |
|---|---|---|
[DOMAIN] | Full domain or subdomain | "n8n.pacing.agency", "crm.pacing.agency" |
[SERVER_NAME] | Hetzner server name | "n8n2", "twenty-crm-prod-2" |
[SERVER_IP] | Public IP address | "91.98.150.95", "49.13.82.194" |
[WEB_SERVER] | Web server software | Nginx, Caddy, Apache |
[STATUS] | Current certificate status | "None", "Expired", "Expiring in 7 days", "Valid" |
[DAYS] | Days until expiry | "7", "30", "90" |
[ISSUER] | Certificate authority | "Let's Encrypt", "Cloudflare" |
[SERVICE_TYPE] | Type of service | "n8n", "TwentyCRM", "Notifuse" |
[PORT] | Service port | "5678" (n8n), "3000" (TwentyCRM) |
[PROXY_SETUP] | Reverse proxy status | "Yes (Nginx)", "No (direct)" |
[RENEWAL_METHOD] | How to renew certificate | "Standalone", "Webroot", "Nginx plugin" |
[EMAIL] | Admin email for notices | "tech@pacing.agency" |
Certificate Renewal Methods
Standalone - Certbot runs its own web server
- Use when: No web server running, or can stop server briefly
- Pros: Simple, no web server config needed
- Cons: Requires stopping web server during renewal
Webroot - Certbot uses existing web server
- Use when: Web server running, can't stop for renewal
- Pros: No downtime, works with any web server
- Cons: Requires web server configuration
Nginx Plugin - Certbot directly configures Nginx
- Use when: Using Nginx as reverse proxy
- Pros: Automatic Nginx configuration
- Cons: Nginx-specific, requires plugin
Expected Output
The AI should provide:
1. Certbot Installation (if needed)
# Install Certbot on Ubuntu 24.04
apt update
apt install certbot
# If using Nginx plugin
apt install python3-certbot-nginx
# Verify installation
certbot --version
2. Certificate Request (New Certificate)
# Method 1: Standalone (requires stopping web server)
systemctl stop nginx
certbot certonly --standalone \
-d n8n.pacing.agency \
--email tech@pacing.agency \
--agree-tos \
--no-eff-email
systemctl start nginx
# Method 2: Webroot (no downtime)
certbot certonly --webroot \
-w /var/www/html \
-d n8n.pacing.agency \
--email tech@pacing.agency \
--agree-tos \
--no-eff-email
# Method 3: Nginx plugin (automatic configuration)
certbot --nginx \
-d n8n.pacing.agency \
--email tech@pacing.agency \
--agree-tos \
--no-eff-email
3. Certificate Renewal (Existing Certificate)
# Test renewal (dry run)
certbot renew --dry-run
# Perform actual renewal
certbot renew
# Renew specific certificate
certbot renew --cert-name n8n.pacing.agency
# Renew with Nginx reload
certbot renew --deploy-hook "systemctl reload nginx"
4. Nginx SSL Configuration
# /etc/nginx/sites-available/n8n.conf
server {
listen 80;
listen [::]:80;
server_name n8n.pacing.agency;
# ACME challenge for Let's Encrypt
location /.well-known/acme-challenge/ {
root /var/www/html;
}
# Redirect everything else to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name n8n.pacing.agency;
# SSL Certificate paths
ssl_certificate /etc/letsencrypt/live/n8n.pacing.agency/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/n8n.pacing.agency/privkey.pem;
# SSL Configuration (Mozilla Modern)
ssl_protocols TLSv1.3 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/n8n.pacing.agency/chain.pem;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Proxy to service
location / {
proxy_pass http://localhost:5678;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
5. Automatic Renewal Setup
# Certbot creates automatic renewal via systemd timer
# Check renewal timer status
systemctl list-timers | grep certbot
# Or via cron (if using cron instead of systemd)
# Add to crontab
crontab -e
# Add this line (runs twice daily at 3:15 AM and PM)
15 3,15 * * * certbot renew --quiet --deploy-hook "systemctl reload nginx"
# Test automatic renewal
certbot renew --dry-run
6. Verification Commands
# Check certificate details
certbot certificates
# Check expiry date
openssl x509 -in /etc/letsencrypt/live/n8n.pacing.agency/fullchain.pem -noout -dates
# Test SSL configuration
openssl s_client -connect n8n.pacing.agency:443 -servername n8n.pacing.agency
# Check SSL Labs score (from browser)
# https://www.ssllabs.com/ssltest/analyze.html?d=n8n.pacing.agency
7. Monitoring Script
#!/bin/bash
# check-ssl-expiry.sh - Check SSL certificate expiry
DOMAIN="n8n.pacing.agency"
DAYS_WARNING=30
# Get expiry date
EXPIRY=$(echo | openssl s_client -servername $DOMAIN -connect $DOMAIN:443 2>/dev/null | openssl x509 -noout -dates | grep notAfter | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))
echo "Certificate expires: $EXPIRY"
echo "Days remaining: $DAYS_LEFT"
if [ $DAYS_LEFT -lt $DAYS_WARNING ]; then
echo "⚠️ Certificate expiring soon!"
# Send alert (Slack, email, etc.)
else
echo "✅ Certificate is valid"
fi
Follow-up Actions
After setting up or renewing certificate:
1. Document in Service Tool Doc
Add SSL configuration to service documentation:
## SSL Certificate
**Domain**: [DOMAIN]
**Issuer**: Let's Encrypt
**Certificate path**: `/etc/letsencrypt/live/[DOMAIN]/`
**Automatic renewal**: Enabled (twice daily via systemd timer)
**Expiry monitoring**: `certbot certificates`
**Last renewed**: [DATE]
**Expires**: [DATE]
2. Verify HTTPS is Working
Test from multiple locations:
# Test from server
curl -I https://[DOMAIN]
# Test from external location
curl -I https://[DOMAIN] --resolve [DOMAIN]:443:[SERVER_IP]
# Check in browser (should show lock icon)
3. Test SSL Labs Score
Check SSL configuration quality:
- Go to https://www.ssllabs.com/ssltest/
- Enter your domain
- Aim for A+ grade
4. Set Up Monitoring
Configure expiry monitoring:
- Add to monitoring dashboard
- Set alert for <30 days remaining
- Verify automatic renewal emails work
5. Test Automatic Renewal
Ensure renewal will work:
# Dry run test (doesn't actually renew)
certbot renew --dry-run
# Should see "Congratulations, all simulated renewals succeeded"
Related Documentation
- Cloudflare Tool Documentation - DNS configuration
- Hetzner Tool Documentation - Server details
- n8n Documentation - n8n SSL setup
- Architecture - Infrastructure overview
Success Criteria
Before considering SSL setup complete, verify:
✅ Certificate is issued and valid
✅ HTTPS is working in browser
✅ HTTP redirects to HTTPS
✅ Certificate paths are correct in web server config
✅ SSL Labs score is A or A+
✅ Automatic renewal is configured
✅ Renewal test (dry run) passes
✅ Monitoring is set up
✅ Documentation is updated
✅ No SSL warnings in browser
Common Issues
Issue: Certificate request fails (DNS validation)
Symptoms: "DNS problem: NXDOMAIN looking up A for [DOMAIN]"
Solutions:
- Verify DNS is configured correctly:
dig [DOMAIN]
# Should show A record pointing to server IP - Wait for DNS propagation (5-10 minutes)
- Test from Cloudflare DNS:
dig @1.1.1.1 [DOMAIN] - Ensure DNS record is not orange-clouded if using Cloudflare
- Try again after waiting
Issue: Port 80 already in use
Symptoms: "Problem binding to port 80: Could not bind to IPv4 or IPv6"
Solutions:
- Check what's using port 80:
lsof -i :80
netstat -tlnp | grep :80 - If Nginx is running, use webroot method instead:
certbot certonly --webroot -w /var/www/html -d [DOMAIN] - Or temporarily stop web server:
systemctl stop nginx
certbot certonly --standalone -d [DOMAIN]
systemctl start nginx
Issue: Certificate not trusted in browser
Symptoms: Browser shows "Not Secure" or certificate warning
Solutions:
- Check certificate chain:
certbot certificates
# Should show "Certificate Path: /etc/letsencrypt/live/[DOMAIN]/fullchain.pem" - Ensure using
fullchain.pemnotcert.pem:ssl_certificate /etc/letsencrypt/live/[DOMAIN]/fullchain.pem; - Reload web server:
systemctl reload nginx - Clear browser cache and test in incognito
Issue: Automatic renewal failing
Symptoms: Renewal emails saying renewal failed
Solutions:
- Test renewal manually:
certbot renew --dry-run - Check logs:
journalctl -u certbot.timer
cat /var/log/letsencrypt/letsencrypt.log - Common causes:
- Port 80 blocked by firewall
- Web server configuration changed
- DNS changed
- Rate limiting (5 renewals per week max)
- Fix issue and test again
Issue: Renewal succeeds but site still shows old certificate
Symptoms: Certificate renewed but browser shows old expiry date
Solutions:
- Reload web server:
systemctl reload nginx
systemctl status nginx - Check web server is using correct certificate path:
nginx -t
grep ssl_certificate /etc/nginx/sites-enabled/* - Restart web server if reload doesn't work:
systemctl restart nginx - Add deploy hook to automatic renewal:
certbot renew --deploy-hook "systemctl reload nginx"
Cost Considerations
Let's Encrypt Certificates
Cost: £0 (completely free) Rate limits:
- 50 certificates per domain per week
- 5 renewals per certificate per week
- 300 new orders per account per 3 hours
Best for:
- Self-hosted services
- Internal tools
- Development environments
Cloudflare Universal SSL
Cost: £0 (included with free plan) Features:
- Automatic issuance
- Automatic renewal
- Covers root and www by default
Best for:
- Client websites
- Public-facing sites
- Sites behind Cloudflare proxy
Custom SSL Certificates
Cost: £50-500/year (varies by provider) Use cases:
- Extended validation (EV) certificates
- Wildcard certificates (also available free via Let's Encrypt)
- Special compliance requirements
Rarely needed for Pacing Agency infrastructure.
Examples
Example 1: n8n Service
# Initial setup
certbot certonly --standalone \
-d n8n.pacing.agency \
--email tech@pacing.agency \
--agree-tos
# Nginx configuration
ssl_certificate /etc/letsencrypt/live/n8n.pacing.agency/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/n8n.pacing.agency/privkey.pem;
# Automatic renewal
certbot renew --deploy-hook "systemctl reload nginx"
Result: HTTPS enabled, A+ SSL Labs score, automatic renewal
Example 2: TwentyCRM
# Using Nginx plugin
certbot --nginx \
-d crm.pacing.agency \
--email tech@pacing.agency \
--agree-tos
# Automatic configuration by Certbot
# Verify with: nginx -t
Result: Nginx auto-configured, HTTPS working, automatic renewal enabled
Example 3: Multiple Subdomains
# Request certificate for multiple domains
certbot certonly --standalone \
-d app.pacing.agency \
-d api.pacing.agency \
--email tech@pacing.agency \
--agree-tos
# Or separate certificates (recommended)
certbot certonly --standalone -d app.pacing.agency
certbot certonly --standalone -d api.pacing.agency
Result: Separate certificates for each subdomain, easier management
Last updated: 2026-01-07
Tested on: Ubuntu 24.04 LTS with Certbot 2.x
Estimated time: 10 minutes (setup + verification)