Skip to content
This repository was archived by the owner on Dec 30, 2025. It is now read-only.

Commit 53d7705

Browse files
committed
feat(ssl): add self-signed certificate generation as fallback
Introduce a new Makefile target and script command to generate self-signed certificates. This serves as a fallback when Let's Encrypt rate limits are reached, ensuring SSL support continuity. Update the README to document the new command and provide guidance on handling rate limits. Remove unnecessary volume mount in compose.yaml for UnrealIRCd TLS directory, as self-signed certificates are now managed internally. This change enhances the robustness of the SSL setup by providing an alternative when automated certificate issuance fails.
1 parent 68b4d0c commit 53d7705

File tree

4 files changed

+81
-14
lines changed

4 files changed

+81
-14
lines changed

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,12 +372,16 @@ help-ssl:
372372
@echo " ssl-setup - Setup certificates (only if none exist)"
373373
@echo " ssl-renew - Renew certificates (only if needed)"
374374
@echo " ssl-status - Check certificate status"
375+
@echo " ssl-self-signed - Generate self-signed certificate (fallback)"
375376
@echo ""
376377
@echo "Quick Start:"
377378
@echo " 1. Copy cloudflare-credentials.ini.template to cloudflare-credentials.ini"
378379
@echo " 2. Add your Cloudflare API token to cloudflare-credentials.ini"
379380
@echo " 3. make ssl-setup # Initial certificate setup (safe to run multiple times)"
380381
@echo " 4. make ssl-status # Check certificate status"
382+
@echo ""
383+
@echo "Fallback Options:"
384+
@echo " make ssl-self-signed # Generate self-signed cert if Let's Encrypt fails"
381385

382386
# Docker operations
383387
docker-build:
@@ -500,6 +504,10 @@ ssl-status: ## Check SSL certificate status
500504
@echo -e "$(PURPLE)=== SSL Certificate Status ===$(NC)"
501505
@./scripts/ssl-manager.sh status
502506

507+
ssl-self-signed: ## Generate self-signed certificate (fallback)
508+
@echo -e "$(PURPLE)=== Generating Self-Signed Certificate ===$(NC)"
509+
@./scripts/ssl-manager.sh self-signed
510+
503511
# ============================================================================
504512
# ENVIRONMENT SETUP
505513
# ============================================================================

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,13 @@ make ssl-renew
221221
# Setup certificates (only if none exist)
222222
make ssl-setup
223223

224+
# Generate self-signed certificate (fallback)
225+
make ssl-self-signed
226+
224227
# Direct script usage
225228
./scripts/ssl-manager.sh status
226229
./scripts/ssl-manager.sh renew
230+
./scripts/ssl-manager.sh self-signed
227231
```
228232

229233
### 🔧 **Available Commands**
@@ -232,8 +236,17 @@ make ssl-setup
232236
make ssl-setup # Setup certificates (only if none exist)
233237
make ssl-renew # Renew certificates (only if needed)
234238
make ssl-status # Check certificate status
239+
make ssl-self-signed # Generate self-signed certificate (fallback)
235240
```
236241

242+
### 🚨 **Rate Limit Handling**
243+
244+
If you hit Let's Encrypt rate limits, the system will automatically:
245+
-**Detect rate limit errors** during certificate issuance
246+
-**Generate self-signed certificates** as a fallback
247+
-**Provide clear guidance** on when to retry with Let's Encrypt
248+
-**Keep your IRC server running** with SSL support
249+
237250
### 📋 **Prerequisites**
238251

239252
1. **Cloudflare Account** with DNS hosting for your domain

compose.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,9 @@ services:
9494
- path: .env.local
9595
required: false
9696

97-
# Volume mounts - persist certificates and access UnrealIRCd TLS directory
97+
# Volume mounts - persist certificates and credentials
9898
volumes:
9999
- letsencrypt_data:/etc/letsencrypt
100-
- ./unrealircd/conf/tls:/etc/letsencrypt/unrealircd:rw
101100
- ./cloudflare-credentials.ini:/etc/letsencrypt/cloudflare-credentials.ini:ro
102101

103102
# Network access for DNS challenges

scripts/ssl-manager.sh

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ issue_certificates() {
7171
log_info "Issuing SSL certificates for $DOMAIN..."
7272

7373
# Run certbot container to issue certificates
74-
docker compose run --rm certbot certonly \
74+
if docker compose run --rm certbot certonly \
7575
--dns-cloudflare \
7676
--dns-cloudflare-credentials=/etc/letsencrypt/cloudflare-credentials.ini \
7777
--dns-cloudflare-propagation-seconds=60 \
@@ -81,12 +81,23 @@ issue_certificates() {
8181
--expand \
8282
--non-interactive \
8383
-d "$DOMAIN" \
84-
-d "*.$DOMAIN"
85-
86-
# Copy certificates to UnrealIRCd TLS directory
87-
copy_certificates
88-
89-
log_success "SSL certificates issued successfully!"
84+
-d "*.$DOMAIN" 2>&1 | tee /tmp/certbot_output.log; then
85+
86+
# Copy certificates to UnrealIRCd TLS directory
87+
copy_certificates
88+
log_success "SSL certificates issued successfully!"
89+
else
90+
# Check if we hit the rate limit
91+
if grep -q "too many certificates" /tmp/certbot_output.log; then
92+
log_warn "Let's Encrypt rate limit reached!"
93+
log_info "Automatically generating self-signed certificate as fallback..."
94+
generate_self_signed_certificate
95+
else
96+
log_error "Failed to issue SSL certificates"
97+
log_info "Check the error above and try again"
98+
return 1
99+
fi
100+
fi
90101
}
91102

92103
# Renew existing certificates
@@ -103,14 +114,44 @@ renew_certificates() {
103114
log_info "Renewing SSL certificates..."
104115

105116
# Run certbot container to renew certificates
106-
docker compose run --rm certbot renew \
117+
if docker compose run --rm certbot renew \
107118
--quiet \
108-
--no-random-sleep-on-renew
119+
--no-random-sleep-on-renew 2>&1 | tee /tmp/certbot_renew_output.log; then
120+
121+
# Copy renewed certificates
122+
copy_certificates
123+
log_success "SSL certificates renewed successfully!"
124+
else
125+
# Check if we hit the rate limit
126+
if grep -q "too many certificates" /tmp/certbot_renew_output.log; then
127+
log_warn "Let's Encrypt rate limit reached!"
128+
log_info "Current certificates will remain valid until they expire"
129+
log_info "Run 'make ssl-renew' after the rate limit resets to renew"
130+
else
131+
log_error "Failed to renew SSL certificates"
132+
log_info "Check the error above and try again"
133+
return 1
134+
fi
135+
fi
136+
}
137+
138+
# Generate self-signed certificate as fallback
139+
generate_self_signed_certificate() {
140+
log_info "Generating self-signed certificate for $DOMAIN..."
109141

110-
# Copy renewed certificates
111-
copy_certificates
142+
# Create TLS directory if it doesn't exist
143+
mkdir -p "$TLS_DIR"
112144

113-
log_success "SSL certificates renewed successfully!"
145+
# Generate self-signed certificate
146+
openssl req -x509 -newkey rsa:4096 -keyout "$TLS_DIR/server.key.pem" -out "$TLS_DIR/server.cert.pem" -days 365 -nodes -subj "/CN=$DOMAIN" 2>/dev/null
147+
148+
# Set proper permissions
149+
chmod 644 "$TLS_DIR/server.cert.pem"
150+
chmod 600 "$TLS_DIR/server.key.pem"
151+
152+
log_success "Self-signed certificate generated successfully!"
153+
log_warn "This is a self-signed certificate - browsers will show security warnings"
154+
log_info "Run 'make ssl-renew' after the Let's Encrypt rate limit resets to get a trusted certificate"
114155
}
115156

116157
# Copy certificates from certbot to UnrealIRCd TLS directory
@@ -213,11 +254,13 @@ show_usage() {
213254
echo " status - Check certificate status"
214255
echo " copy - Copy certificates to UnrealIRCd directory"
215256
echo " restart - Restart UnrealIRCd to load certificates"
257+
echo " self-signed - Generate self-signed certificate (fallback)"
216258
echo ""
217259
echo "Examples:"
218260
echo " $0 issue # Issue new certificates"
219261
echo " $0 renew # Renew existing certificates"
220262
echo " $0 status # Check certificate status"
263+
echo " $0 self-signed # Generate self-signed certificate"
221264
}
222265

223266
# Main function
@@ -244,6 +287,10 @@ main() {
244287
"restart")
245288
restart_unrealircd
246289
;;
290+
"self-signed")
291+
generate_self_signed_certificate
292+
restart_unrealircd
293+
;;
247294
"help"|"--help"|"-h")
248295
show_usage
249296
;;

0 commit comments

Comments
 (0)