# SSL Certificates with Let's Encrypt and DuckDNS

Your homelab uses **Let's Encrypt** to automatically provide free SSL certificates for all your services. This ensures secure HTTPS connections without manual certificate management.

## How SSL Certificates Work in Your Homelab

### The Certificate Flow

1. **Domain Registration**: DuckDNS provides your dynamic domain (e.g., `yourname.duckdns.org`)
2. **Certificate Request**: Traefik requests a wildcard certificate (`*.yourname.duckdns.org`)
3. **Domain Validation**: Let's Encrypt validates you own the domain via DNS challenge
4. **Certificate Issuance**: Free SSL certificate is issued and stored
5. **Automatic Renewal**: Certificates renew automatically before expiration

### DuckDNS + Let's Encrypt Integration

**DuckDNS** handles dynamic DNS updates, while **Let's Encrypt** provides certificates:

- **DuckDNS**: Updates your public IP → domain mapping every 5 minutes
- **Let's Encrypt**: Issues trusted SSL certificates via ACME protocol
- **DNS Challenge**: Proves domain ownership by setting TXT records

### Wildcard Certificates Explained

Your setup uses a **wildcard certificate** (`*.yourdomain.duckdns.org`) that covers:
- `dockge.yourdomain.duckdns.org`
- `plex.yourdomain.duckdns.org`
- `jellyfin.yourdomain.duckdns.org`
- Any other subdomain automatically

**Why wildcard?** One certificate covers all services - no need for individual certificates per service.

### Certificate Storage & Management

- **Location**: `/opt/stacks/core/traefik/acme.json`
- **Permissions**: Must be `600` (read/write for owner only)
- **Backup**: Always backup this file - contains your certificates
- **Renewal**: Automatic, 30 days before expiration

## Testing vs Production Certificates

### Staging Server (For Testing)
```yaml
# In traefik.yml, add this line for testing:
caServer: https://acme-staging-v02.api.letsencrypt.org/directory
```

**Staging Benefits:**
- Unlimited certificates (no rate limits)
- Fast issuance for testing
- **Not trusted by browsers** (shows "Not Secure")

**When to use staging:**
- Setting up new environments
- Testing configurations
- Learning/development

### Production Server (For Live Use)
```yaml
# Remove or comment out caServer line for production
# certificatesResolvers:
#   letsencrypt:
#     acme:
#       # No caServer = production
```

**Production Limits:**

>This is why you want to use staging certificates for testing purposes!!!
>Always use staging certificates if you are running the setup & deploy scripts repeatedly

- **50 certificates per domain per week**
- **5 duplicate certificates per week**
- **Trusted by all browsers**

## Certificate Troubleshooting

### Check Certificate Status
```bash
# Count certificates in storage
python3 -c "import json; d=json.load(open('/opt/stacks/core/traefik/acme.json')); print(f'Certificates: {len(d[\"letsencrypt\"][\"Certificates\"])}')}"
```

### Common Issues & Solutions

**"Certificate not trusted" or "Not Secure" warnings:**
- **Staging certificates**: Expected - use production for live sites
- **DNS propagation**: Wait 5-10 minutes after setup
- **Browser cache**: Clear browser cache and try incognito mode

**Certificate request fails:**
- Check Traefik logs: `docker logs traefik | grep -i certificate`
- Verify DuckDNS token is correct in `.env`
- Ensure ports 80/443 are open and forwarded
- Wait 1+ hours between certificate requests

**Rate limit exceeded:**
- Switch to staging server for testing
- Wait 1 week for production limits to reset
- Check status at: https://letsencrypt.org/docs/rate-limits/

### DNS Challenge Process

When requesting certificates, Traefik:
1. Asks DuckDNS to set TXT record: `_acme-challenge.yourdomain.duckdns.org`
2. Let's Encrypt checks the TXT record to verify ownership
3. If valid, certificate is issued
4. TXT record is cleaned up automatically

**Note:** DuckDNS allows only ONE TXT record at a time. Multiple Traefik instances will conflict.

### Certificate Validation Commands

```bash
# Test certificate validity
echo | openssl s_client -connect yourdomain.duckdns.org:443 -servername dockge.yourdomain.duckdns.org 2>/dev/null | openssl x509 -noout -subject -issuer -dates

# Check if certificate covers wildcards
echo | openssl s_client -connect yourdomain.duckdns.org:443 -servername any-subdomain.yourdomain.duckdns.org 2>/dev/null | openssl x509 -noout -text | grep "Subject Alternative Name"
```

## Best Practices

### For Production
- Use production Let's Encrypt server
- Backup `acme.json` regularly
- Monitor certificate expiration (Traefik dashboard)
- Keep DuckDNS token secure

### For Development/Testing
- Use staging server to avoid rate limits
- Test with different subdomains
- Reset environments safely (preserve `acme.json` if possible)

### Security Notes
- Certificates are stored encrypted in `acme.json`
- Private keys never leave your server
- HTTPS provides encryption in transit
- Consider additional security headers in Traefik

## Port Forwarding Requirements

**Critical**: SSL certificates require ports 80 and 443 to be forwarded from your router to your homelab server.

### Router Configuration
1. Log into your router's admin interface (usually 192.168.1.1)
2. Find the "Port Forwarding" or "NAT" section
3. Create forwarding rules:
   - **External Port**: 80 → **Internal IP**: your-server-ip **Internal Port**: 80
   - **External Port**: 443 → **Internal IP**: your-server-ip **Internal Port**: 443
4. Protocol: TCP for both
5. Save changes

### Why This Is Required
- **Port 80**: Used by Let's Encrypt for domain ownership verification (HTTP-01 challenge)
- **Port 443**: Used for all HTTPS traffic to your services
- **Wildcard Certificates**: Enables automatic SSL for all `*.yourdomain.duckdns.org` subdomains

### Testing Port Forwarding
```bash
# Test from external network (not your local network)
curl -I http://yourdomain.duckdns.org
# Should return HTTP 200 or redirect to HTTPS
```