Files
Sankofa/docs/proxmox/acme-setup.md
defiQUG 33d50fb91e
Some checks failed
API CI / API Lint (push) Successful in 47s
API CI / API Type Check (push) Failing after 47s
API CI / API Test (push) Successful in 1m0s
API CI / API Build (push) Failing after 50s
API CI / Build Docker Image (push) Has been skipped
Build Crossplane Provider / build (push) Failing after 5m51s
CD Pipeline / Deploy to Staging (push) Failing after 29s
CI Pipeline / Lint and Type Check (push) Failing after 36s
CI Pipeline / Build (push) Has been skipped
CI Pipeline / Test Backend (push) Failing after 1m33s
CI Pipeline / Test Frontend (push) Failing after 30s
CI Pipeline / Security Scan (push) Failing after 1m16s
Crossplane Provider CI / Go Test (push) Failing after 3m23s
Crossplane Provider CI / Go Lint (push) Failing after 7m27s
Crossplane Provider CI / Go Build (push) Failing after 3m27s
Deploy to Staging / Deploy to Staging (push) Failing after 30s
Portal CI / Portal Lint (push) Failing after 21s
Portal CI / Portal Type Check (push) Failing after 21s
Portal CI / Portal Test (push) Failing after 21s
Portal CI / Portal Build (push) Failing after 22s
Test Suite / frontend-tests (push) Failing after 30s
Test Suite / api-tests (push) Failing after 49s
Test Suite / blockchain-tests (push) Failing after 30s
Type Check / type-check (map[directory:. name:root]) (push) Failing after 23s
Type Check / type-check (map[directory:api name:api]) (push) Failing after 21s
Type Check / type-check (map[directory:portal name:portal]) (push) Failing after 19s
Validate Configuration Files / validate (push) Failing after 1m52s
CD Pipeline / Deploy to Production (push) Has been skipped
chore: consolidate local WIP (repo cleanup 20260707)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 09:41:34 -07:00

662 lines
18 KiB
Markdown

# Proxmox ACME Certificate Setup with Cloudflare DNS-01
## Overview
This guide provides step-by-step instructions for configuring Let's Encrypt certificates on Proxmox nodes using Cloudflare DNS-01 validation. This setup enables automatic certificate issuance and renewal without exposing Proxmox to the internet.
## Prerequisites
### Domain Requirements
- Domain must be managed by Cloudflare DNS
- Domain must be active in Cloudflare account
- DNS records for Proxmox nodes must exist (or will be created automatically)
**Current Setup:**
- **Domain**: `sankofa.nexus`
- **Proxmox Nodes**:
- `ml110-01.sankofa.nexus` (192.168.11.10) - Admin functions
- `r630-01.sankofa.nexus` (192.168.11.11) - VMs and heavy lifting
### Proxmox Requirements
- Proxmox VE 6.0+ (ACME plugin included)
- Administrative access to Proxmox web UI
- Network connectivity from Proxmox to Cloudflare API (outbound HTTPS)
### Cloudflare Requirements
- Cloudflare account with DNS management access
- Ability to create API tokens
## Step 1: Create Cloudflare API Token
### Purpose
The API token allows Proxmox ACME plugin to create and delete DNS TXT records for domain validation.
### Instructions
1. **Log in to Cloudflare Dashboard**
- Go to [https://dash.cloudflare.com](https://dash.cloudflare.com)
- Select your account
2. **Navigate to API Tokens**
- Click your profile icon (top right)
- Select **"My Profile"**
- Click **"API Tokens"** in the left sidebar
- Click **"Create Token"**
3. **Configure Token Permissions**
**Option A: Use Template (Recommended)**
- Scroll to **"Edit zone DNS"** template
- Click **"Use template"**
- Continue to Zone Resources
**Option B: Custom Token**
- Click **"Create Custom Token"**
- **Token Name**: `proxmox-acme-dns01` (or descriptive name)
- **Permissions**:
- Resource: `Zone`
- Permission: `DNS`
- Permission Level: `Edit`
- Click **"Continue to summary"**
4. **Configure Zone Resources**
- **Include**: Select **"Specific zone"**
- **Zone**: Select `sankofa.nexus`
- **DNS**: `Edit` (should be pre-selected)
- Review permissions summary
5. **Create Token**
- Click **"Continue to summary"**
- Review configuration
- Click **"Create Token"**
- **CRITICAL**: Copy the token immediately (shown only once)
- Store securely (password manager recommended)
### Security Best Practices
- **Scope**: Token scoped to `sankofa.nexus` zone only (not "All zones")
- **Permissions**: DNS Edit only (minimal required permissions)
- **Naming**: Use descriptive token name for easy identification
- **Rotation**: Rotate token periodically (recommended: every 90 days)
- **Storage**: Never commit token to version control
- **Access**: Limit who has access to the token
### Token Format
The token will look like:
```
abcdef1234567890abcdef1234567890abcdef12
```
## Step 2: Configure ACME Account in Proxmox
### On ml110-01 (Admin Node)
1. **Access Proxmox Web UI**
- Navigate to `https://ml110-01.sankofa.nexus:8006`
- Log in with administrative credentials
2. **Navigate to ACME Accounts**
- Click **"Datacenter"** in the left sidebar
- Expand **"ACME"** section
- Click **"Accounts"**
3. **Add ACME Account**
- Click **"Add"** button
- **Directory**: Select **"Let's Encrypt"** (production)
- **Email**: Enter your administrative email address
- Used for certificate expiration notifications
- Example: `admin@sankofa.nexus`
- **Name**: `letsencrypt-prod`
- Click **"Register"**
4. **Verify Account Creation**
- Account should appear in the list
- Status should show as active/registered
## Step 3: Configure Cloudflare DNS Plugin
1. **Navigate to ACME DNS Plugins**
- In **"Datacenter"** → **"ACME"** section
- Click **"DNS Plugin"**
2. **Add DNS Plugin**
- Click **"Add"** button
- **ID**: `cloudflare-dns` (or descriptive identifier)
- **Plugin**: Select **"cloudflare"** from dropdown
- **API Token**: Paste the Cloudflare API token from Step 1
- **Domain**: `sankofa.nexus`
- Click **"Create"**
3. **Verify Plugin Configuration**
- Plugin should appear in the list
- Status should be valid
### Troubleshooting Plugin Configuration
**Error: "Invalid API token"**
- Verify token was copied correctly (no extra spaces)
- Ensure token has DNS Edit permissions for `sankofa.nexus` zone
- Check token hasn't been deleted or rotated in Cloudflare
**Error: "Zone not found"**
- Verify domain spelling matches exactly
- Ensure domain is in your Cloudflare account
- Check you have DNS management access to the zone
## Step 4: Order Certificates
### Wildcard Certificate (Recommended)
1. **Navigate to ACME Certificates**
- In **"Datacenter"** → **"ACME"** section
- Click **"Certificates"**
2. **Order Wildcard Certificate**
- Click **"Order Certificate"**
- **ACME Account**: Select `letsencrypt-prod`
- **DNS Plugin**: Select `cloudflare-dns`
- **Domain**: `*.sankofa.nexus`
- **Name**: `wildcard-sankofa-nexus` (optional, for identification)
- Click **"Order"**
3. **Monitor Certificate Order**
- Certificate status will show as "Ordering..."
- Proxmox will automatically:
- Create DNS TXT record via Cloudflare API
- Wait for DNS propagation
- Validate domain ownership
- Download certificate
- Process typically takes 1-2 minutes
4. **Verify Certificate**
- Status should change to "Valid" or "Active"
- Certificate should show expiration date (~90 days from now)
- Click certificate to view details (SANs, issuer, etc.)
### Single-Host Certificates (Optional)
While the wildcard certificate covers all subdomains, you may want specific certificates for clarity or compliance.
#### Certificate for ml110-01
1. **Order Certificate**
- Click **"Order Certificate"**
- **ACME Account**: `letsencrypt-prod`
- **DNS Plugin**: `cloudflare-dns`
- **Domain**: `ml110-01.sankofa.nexus`
- **Name**: `ml110-01-sankofa-nexus`
- Click **"Order"**
2. **Wait for Validation**
- Same process as wildcard certificate
- Status should become "Valid"
#### Certificate for r630-01
1. **Order Certificate**
- Click **"Order Certificate"**
- **ACME Account**: `letsencrypt-prod`
- **DNS Plugin**: `cloudflare-dns`
- **Domain**: `r630-01.sankofa.nexus`
- **Name**: `r630-01-sankofa-nexus`
- Click **"Order"**
2. **Wait for Validation**
- Status should become "Valid"
## Step 5: Apply Certificates to Nodes
### Apply Wildcard Certificate to All Nodes
1. **Navigate to Certificates**
- Click **"Datacenter"** in left sidebar
- Click **"Certificates"** (not under ACME section)
2. **Select Certificate**
- Find `wildcard-sankofa-nexus` in the list
- Click on the certificate name
3. **Edit Certificate Assignment**
- Click **"Edit"** button
- Check boxes for both nodes:
- `ml110-01` (Admin node)
- `r630-01` (VM node)
- Click **"OK"**
4. **Verify Application**
- Certificate should show as assigned to both nodes
- Nodes will automatically use the certificate for HTTPS
### Apply Single-Host Certificates (if created)
Single-host certificates are automatically used by the matching node when present.
To verify:
- Check certificate details show correct hostname
- Certificate should automatically appear on the matching node
## Step 6: Verify Certificate Installation
### Method 1: Proxmox Web UI
1. **Check Certificate Status**
- **Datacenter** → **Certificates**
- Verify certificates show as "Valid"
- Check expiration dates (should be ~90 days)
2. **Test HTTPS Connection**
- Access Proxmox web UI via HTTPS
- Browser should show valid certificate (green lock icon)
- Certificate should show as issued by "Let's Encrypt"
- Click lock icon to view certificate details
### Method 2: Command Line (from Proxmox node)
```bash
# Check certificate on ml110-01
openssl s_client -connect ml110-01.sankofa.nexus:8006 -servername ml110-01.sankofa.nexus < /dev/null 2>/dev/null | openssl x509 -noout -dates -subject -issuer
# Check certificate on r630-01
openssl s_client -connect r630-01.sankofa.nexus:8006 -servername r630-01.sankofa.nexus < /dev/null 2>/dev/null | openssl x509 -noout -dates -subject -issuer
```
Expected output:
- **Issuer**: Should show "Let's Encrypt"
- **Subject**: Should include node hostname
- **Valid From/To**: Should show current date and ~90 days future
### Method 3: Using Verification Script
Run the provided verification script:
```bash
./scripts/verify-proxmox-certs.sh
```
This script will:
- Check certificate validity on both nodes
- Verify expiration dates
- Test SSL connections
- Report certificate status
## Step 7: Update Cloudflare Tunnel Configurations
After certificates are installed, update tunnel configurations to remove `skipVerify: true`.
### Files to Update
- `cloudflare/tunnel-configs/proxmox-site-1.yaml` (ml110-01)
- `cloudflare/tunnel-configs/proxmox-site-2.yaml` (r630-01)
- `cloudflare/tunnel-configs/proxmox-site-3.yaml` (if applicable)
### Changes Required
**Before:**
```yaml
originRequest:
tls:
skipVerify: true
```
**After:**
```yaml
originRequest:
tls:
skipVerify: false
```
Or simply remove the `tls` section entirely (defaults to `skipVerify: false`).
### Apply Changes
1. Update configuration files
2. Copy updated configs to Proxmox nodes
3. Restart cloudflared tunnel service:
```bash
systemctl restart cloudflared-tunnel
```
4. Verify tunnel connectivity:
```bash
systemctl status cloudflared-tunnel
```
## Auto-Renewal
### How It Works
Proxmox ACME plugin automatically renews certificates before expiration:
- Renewal typically occurs 30 days before expiration
- Process is automatic (no manual intervention)
- Renewal uses same DNS-01 validation process
- No downtime required
### Verification
1. **Check Auto-Renewal Status**
- **Datacenter** → **ACME** → **Certificates**
- Certificates should show auto-renewal enabled
- Check renewal date (should be ~30 days before expiration)
2. **Monitor Renewal**
- Proxmox logs renewal attempts
- Check logs if renewal fails:
```bash
journalctl -u pvedaemon -f | grep -i acme
```
3. **Email Notifications**
- Let's Encrypt sends expiration warnings to account email
- Proxmox may also send notifications on renewal failure
## Troubleshooting
### Certificate Order Fails
**Symptom**: Certificate status shows "Failed" or "Error"
**Possible Causes**:
1. **Invalid API Token**
- Verify token in DNS Plugin configuration
- Test token in Cloudflare API directly
- Create new token if necessary
2. **DNS Propagation Delay**
- Wait 5-10 minutes and retry
- Check DNS TXT records manually:
```bash
dig _acme-challenge.sankofa.nexus TXT
```
3. **Rate Limiting**
- Let's Encrypt has rate limits (50 certs/week/domain)
- Wait and retry later
- Use staging environment for testing
4. **Network Connectivity**
- Verify Proxmox can reach Cloudflare API (outbound HTTPS)
- Check firewall rules
- Test connectivity:
```bash
curl -I https://api.cloudflare.com
```
**Solution**: Check Proxmox logs:
```bash
journalctl -u pvedaemon | grep -i acme | tail -50
```
### Certificate Not Applied to Node
**Symptom**: Node still uses self-signed certificate
**Possible Causes**:
1. Certificate not assigned to node
2. Node needs restart (rare)
3. Certificate format issue
**Solution**:
1. Check certificate assignment in **Datacenter** → **Certificates**
2. Verify certificate is valid and not expired
3. Restart pveproxy service if needed:
```bash
systemctl restart pveproxy
```
### DNS TXT Records Not Created
**Symptom**: Certificate validation fails, TXT records missing
**Possible Causes**:
1. API token lacks permissions
2. Token expired or deleted
3. Cloudflare API error
**Solution**:
1. Verify API token in DNS Plugin configuration
2. Test token manually:
```bash
curl -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
-H "Authorization: Bearer YOUR_TOKEN"
```
3. Check Cloudflare API status page
### Auto-Renewal Fails
**Symptom**: Certificate expires, not renewed automatically
**Possible Causes**:
1. API token expired or rotated
2. Network connectivity issues
3. Let's Encrypt rate limiting
4. DNS plugin configuration changed
**Solution**:
1. Check renewal logs:
```bash
journalctl -u pvedaemon | grep -i "acme\|renewal" | tail -100
```
2. Verify API token is still valid
3. Manually trigger renewal:
- Go to **Datacenter** → **ACME** → **Certificates**
- Select certificate
- Click **"Renew"** (if available)
### Certificate Shows as Invalid in Browser
**Symptom**: Browser shows certificate error despite valid certificate
**Possible Causes**:
1. Browser cache issue
2. Certificate chain incomplete
3. Wrong certificate applied
**Solution**:
1. Clear browser cache and cookies
2. Try incognito/private browsing mode
3. Verify certificate via command line (see Step 6)
4. Check certificate chain is complete
## Certificate Management
### View Certificate Details
**In Proxmox Web UI**:
- **Datacenter** → **Certificates**
- Click certificate name to view details:
- Subject Alternative Names (SANs)
- Issuer
- Valid from/to dates
- Serial number
- Public key fingerprint
**Via Command Line**:
```bash
# View certificate file
cat /etc/pve/nodes/ml110-01/pveproxy-ssl.pem
# Parse certificate details
openssl x509 -in /etc/pve/nodes/ml110-01/pveproxy-ssl.pem -text -noout
```
### Revoke Certificate
If a certificate is compromised or no longer needed:
1. **Via Proxmox Web UI**:
- **Datacenter** → **ACME** → **Certificates**
- Select certificate
- Click **"Revoke"**
- Confirm revocation
2. **Note**: Revoked certificates cannot be reused
- Order new certificate if needed
- Let's Encrypt tracks revoked certificates
### Delete Certificate
To remove a certificate from Proxmox:
1. **Remove from Nodes**:
- **Datacenter** → **Certificates**
- Select certificate
- Click **"Edit"**
- Uncheck all nodes
- Click **"OK"**
2. **Delete Certificate**:
- **Datacenter** → **ACME** → **Certificates**
- Select certificate
- Click **"Delete"**
- Confirm deletion
## Token Rotation
### When to Rotate
- Every 90 days (recommended)
- After security incident
- If token is compromised
- As part of security policy
### Rotation Procedure
1. **Create New Token**
- Follow Step 1 to create new Cloudflare API token
- Use same permissions and zone scope
2. **Update DNS Plugin**
- **Datacenter** → **ACME** → **DNS Plugin**
- Select `cloudflare-dns` plugin
- Click **"Edit"**
- Replace **API Token** with new token
- Click **"OK"**
3. **Verify Certificates Still Work**
- Check certificate status
- Test HTTPS connections
- Monitor for 24-48 hours
4. **Revoke Old Token**
- Go to Cloudflare Dashboard
- **My Profile** → **API Tokens**
- Find old token
- Click **"Revoke"**
- Confirm revocation
### Testing New Token
Before rotating, test new token works:
```bash
# Test token can read DNS records
curl -X GET "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \
-H "Authorization: Bearer NEW_TOKEN" \
-H "Content-Type: application/json"
# Test token can create DNS records (careful!)
# This creates a test record - delete it after testing
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/dns_records" \
-H "Authorization: Bearer NEW_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"TXT","name":"_acme-test.sankofa.nexus","content":"test","ttl":120}'
```
## Security Considerations
### API Token Security
- **Never commit tokens to version control**
- **Store tokens in password manager**
- **Use separate tokens for different purposes**
- **Rotate tokens regularly**
- **Monitor token usage in Cloudflare**
### Certificate Security
- **Let's Encrypt certificates are public** (anyone can view them)
- **Private keys are stored securely on Proxmox**
- **Automatic renewal prevents expiration**
- **Monitor certificate expiration dates**
### Network Security
- **Proxmox nodes should be behind firewall**
- **Only allow necessary outbound connections**
- **Monitor Cloudflare API access**
- **Use VPN or private network when possible**
### Access Control
- **Limit who can modify ACME configuration**
- **Audit certificate changes**
- **Review certificate assignments regularly**
- **Monitor for unauthorized certificate issuance**
## Compliance
### Certificate Requirements
- **Valid certificates required for compliance (SOC 2, ISO 27001)**
- **Automatic renewal ensures continuous validity**
- **Certificate audit trail in Proxmox logs**
- **Let's Encrypt certificates meet industry standards**
### Monitoring and Auditing
- **Log all certificate operations**
- **Monitor certificate expiration**
- **Audit API token usage**
- **Review certificate assignments quarterly**
## Related Documentation
- [TLS Configuration Guide](./TLS_CONFIGURATION.md) - General TLS/SSL configuration
- [DNS Configuration](./DNS_CONFIGURATION.md) - DNS setup for Proxmox
- [Cloudflare Domain Setup](./CLOUDFLARE_DOMAIN_SETUP.md) - Cloudflare integration
- [Cloudflare Tunnel Configs](../cloudflare/tunnel-configs/) - Tunnel configuration files
## Verification Checklist
After completing setup, verify:
- [ ] Cloudflare API token created and stored securely
- [ ] ACME account registered in Proxmox
- [ ] Cloudflare DNS plugin configured
- [ ] Wildcard certificate ordered and valid
- [ ] Single-host certificates ordered (if applicable)
- [ ] Certificates applied to both nodes
- [ ] HTTPS connections show valid certificates
- [ ] Auto-renewal configured and verified
- [ ] Tunnel configurations updated (skipVerify removed)
- [ ] Verification script passes
- [ ] Email notifications configured
## Support
### Proxmox Resources
- [Proxmox ACME Documentation](https://pve.proxmox.com/pve-docs/chapter-pve-certificate-management.html)
- [Proxmox Forum](https://forum.proxmox.com/)
### Let's Encrypt Resources
- [Let's Encrypt Documentation](https://letsencrypt.org/docs/)
- [Let's Encrypt Community](https://community.letsencrypt.org/)
### Cloudflare Resources
- [Cloudflare API Documentation](https://developers.cloudflare.com/api/)
- [Cloudflare DNS API](https://developers.cloudflare.com/api/operations/dns-records-for-a-zone-list-dns-records)
## Last Updated
- **Date**: 2024-12-19
- **Status**: Complete
- **Next Review**: 2025-03-19